2013-06-17 1 views
1

У меня есть то, что становится сложной моделью, и я пытаюсь высушить ее. В случае моих опций has_many, вместо того, чтобы повторять их, я хотел бы просто загрузить их из метода в классе.Загрузка has_many options hash методом

class ExampleClass < ActiveRecord::Base 
    has_many :related_things, get_association_hash(arg1) 
    has_many :other_things, get_association_hash(arg2) 

    def get_association_hash(arg) 
    { :class_name => 'SomeClass', :conditions => ['table.column = ?', arg] } 
    end 
end 

К сожалению, это приводит к undefined method ‘get_association_hash’ for #<Class:0x007f9ae9efe6c0> при загрузке класса.

(В качестве проверки на здравомыслие этот метод является прекрасным, если я просто позвоню ему, не включив его в has_many. Кроме того, фактический класс значительно больше, и поэтому DRY более полезен, чем в этом небольшом примере.)

Я отмечаю, что в сообщении об ошибке упоминается Class, а не мой производный ExampleClass, так что, возможно, это связано с тем, как has_many загружен и где я определяю свой метод?

ответ

1

has_many это просто метод класса, так это:

has_many :related_things, get_association_hash(arg1) 

это просто вызов метода, как и любой другой, и приемник в этом контексте является ваш ExampleClass. Это означает, что get_association_hash должен быть методом класса. Кроме того, вы должны определить его перед ваших has_many звонков или вы не сможете назвать его там, где вы хотите:

class ExampleClass < ActiveRecord::Base 
    def self.get_association_hash(arg) 
    { :class_name => 'SomeClass', :conditions => ['table.column = ?', arg] } 
    end 
    has_many :related_things, get_association_hash(arg1) 
    has_many :other_things, get_association_hash(arg2) 
end 

Это может быть немного некрасиво и напутать обычное определение заказ. Если это так, то вы можете нажать ваш метод get_association_hash в модуль, а затем включить этот модуль в верхней части вашего класса:

module Pancakes 
    def self.included(base) 
    # There are various different ways to do this, use whichever one you like best 
    base.class_exec do 
     def self.get_association_hash(arg) 
     # ... 
     end 
    end 
    end 
end 

class ExampleClass < ActiveRecord::Base 
    include Pancakes 
    has_many :related_things, get_association_hash(arg1) 
    has_many :other_things, get_association_hash(arg2) 
end 

Вы бы, вероятно, назвать свой модуль что-то более осмысленное, чем Pancakes, это только мой имя по умолчанию для вещей (потому что foo получает скучно через некоторое время, и я предпочитаю Fargo по традиции).

+0

Выглядит хорошо, я спрятал модуль в/lib. –

Смежные вопросы