Rails: обратные вызовы из модуля - PullRequest
5 голосов
/ 06 марта 2011

Я пытаюсь сделать это:

app / models / my_model.rb:

class MyModel <  ActiveRecord::Base
  include MyModule
  ...
end

lib / my_module.rb:

module MyModule
  before_destroy :my_func    #!

  def my_func
    ...
  end
end

но я получаюошибка:

undefined method `before_destroy' for MyModule:Module

Как я могу это исправить.

Также я новичок в ruby.Какой тип имеет эти "атрибуты": before_destroy, validates, has_many?Это переменные или методы или что?Спасибо

Ответы [ 3 ]

14 голосов
/ 06 марта 2011

before_destroy, validates и т. Д. Не являются атрибутами или чем-то подобным.Это вызовы методов.

В ruby ​​все тело класса представляет собой исполняемый код, то есть каждая строка тела класса выполняется интерпретатором так же, как и тело метода.before_destroy :my_func - это обычный вызов метода ruby.Вызываемый метод - before_destroy, и он получает символ :my_func в качестве аргумента.Этот метод ищется в классе (или модуле), в области его вызова

module MyModule
  before_destroy :my_func    #!

  def my_func
    ...
  end
end

он начинает выполнение своего тела и ищет метод before_destroy в этом модуле и не может найти его.То, что вы хотите сделать, это вызвать этот метод не в модуле, а в классе, в который включен модуль.Для этого у нас есть общая идиома, использующая метод Module#included:

module MyModule
  module InstanceMethods
    def my_func
      ...
    end
  end

  def self.included(base)
    base.send :include, InstanceMethods
    base.before_destroy :my_func
  end
end
0 голосов
/ 06 марта 2011

Вы можете исправить это, удалив before_destroy из MyModule и поместить вместо него в MyModel

before_destroy и другие обратные вызовы доступны только для классов, расширяющих ActiveRecord :: Base, больше информации здесь

надеюсь, это поможет =)

0 голосов
/ 06 марта 2011

В lib / my_module.rb сделайте это:

  class MyInheritedClass &#60;  ActiveRecord::Base
    before_destroy :my_func
    def my_func
       ...
    end
  end

В app / models / my_model.rb сделайте это:

class MyModel &#60; MyInheritedClass
  ...
end

В полеМодуль, который вы пытаетесь создать выше.Мой код создает класс, который будет наследоваться от ActiveRecord :: Base, и это будет ваш шаблонный класс, от которого могут наследовать все остальные ваши классы.Шаблонный класс также содержит все свойства ActiveRecord :: Base.

...