2012-05-15 4 views
1

Допустим, у меня есть этот модуль:полиморфизм на моделях и модули

module Template 

def self.included(base) 

    base.class_eval do 
     before_validation(:on => :create) { sanitize_text! } 
    end 

    base.extend(ClassMethods) 
end 

module ClassMethods 

    def sanitize_text! 
    # some stuff 
    end 

end 

end 

И тогда я модель определяется следующим образом:

class Invitation < ActiveRecord::Base 
    include Template 
end 

Обратите внимание, что я не переопределить метод sanitize_text! но когда я пройду через этот Rails, я получу ошибку:

undefined method `sanitize_text! ' для #

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

ответ

2

До того, как_добавление вызывает блок как экземпляр, поэтому нет sanitize_text! потому что sanitize_text! является методом класса.

Определить sanitize_text! в модуле, а не как метод класса.

module Template 
    ... 
    def sanitize_text! 
    # some stuff 
    end 
end 
0

Вы включили его в качестве метода класса, а не в качестве способа по любому конкретному экземпляру этой модели.

Чтобы использовать это, вам нужно вызвать его как:

Invitation.sanitize_text! 

Для вызова на примере приглашения, сделать эти изменения:

module Template 

def self.included(base) 

    base.class_eval do 
     before_validation(:on => :create) { sanitize_text! } 
    end 

    base.extend(ClassMethods) 
end 

def sanitize_text! 
    # some stuff 
end 

module ClassMethods 
end 

end 

Тогда вы будете в состоянии назвать его на конкретном методе:

@invitation.sanitize_text! 
0

, как вы делаете это вы расширяете Invitation класс с встретил hod sanitize_text!, а не экземпляры Invitation.

Если вы хотите, например, чтобы иметь sanitize_text!, вы должны лучше переименовать ClassMethods в InstanceMethods и изменить self.included, чтобы иметь эту линию:

base.send :include, InstanceMethods 

Таким образом, весь код будет выглядеть следующим образом:

module Template 
    def self.included(base) 
    base.class_eval do 
     before_validation(:on => :create) { sanitize_text! } 
    end 

    base.send :include, InstanceMethods 
    end 

    module InstanceMethods 
    def sanitize_text! 
     # method body 
    end 
    end 
end 
Смежные вопросы