Rails:来自模块的回调

时间:2011-03-06 10:52:41

标签: ruby-on-rails module mixins

我尝试这样做:

应用程序/模型/ 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

我该如何纠正呢。

我也是红宝石的新手。这些“属性”是什么类型:before_destroy,validates,has_many? 它们是变量或方法还是什么? 感谢

3 个答案:

答案 0 :(得分:14)

before_destroyvalidates等不是属性或类似的东西。这些是方法调用。

在ruby中,类的主体都是可执行代码,这意味着类主体的每一行都由interpeter执行,就像方法体一样。

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

答案 1 :(得分:0)

在lib / my_module.rb中,执行以下操作:

  class MyInheritedClass <  ActiveRecord::Base
    before_destroy :my_func
    def my_func
       ...
    end
  end

在app / models / my_model.rb中,执行以下操作:

class MyModel < MyInheritedClass
  ...
end

您尝试在上面创建的模块中没有before_destroy过滤器。我的代码所做的是创建一个将继承自ActiveRecord :: Base的类,这将是您的所有其他类可以继承的模板类。模板类还包含ActiveRecord :: Base的所有属性。

答案 2 :(得分:0)

你可以通过从MyModule中删除before_destroy并将其放在MyModel中来解决这个问题

before_destroy和其他回调仅适用于扩展ActiveRecord :: Base的类,更多信息here

希望这有助于=)