Rails 3:在模块中使用'before_create'(对于ActiveRecord模型)

Jen*_*ens 2 ruby activerecord module ruby-on-rails-3

我正在编写一个应用程序,其中许多(但不是全部)ActiveRecord模型都有一hash列.这是使用随机MD5哈希创建时填充的,用于引用单个对象而不是其ID.为实现这一目标,我在相应的型号中包含了以下模块,并find_by_id_or_hash!()在所有控制器中使用而不是find:

module IdOrHashFindable

  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods

    before_create :create_hash             ## <-- THIS FAILS

    # legacy. in use only until find by ID is phased out altogether
    def find_by_id_or_hash!(id_or_hash)
      id_or_hash.to_s.size >= 32 ? find_by_hash!(id_or_hash) : find(id_or_hash)
    end
  end

  def to_param; self.hash end
  def create_hash; self.hash = Support.create_hash  end

end
Run Code Online (Sandbox Code Playgroud)

为了保持干燥,我想before_create在模块内部进行调用.但是,我一直在努力

undefined method `before_create' for IdOrHashFindable:Module
Run Code Online (Sandbox Code Playgroud)

要么

undefined method `before_create' for IdOrHashFindable::ClassMethods:Module
Run Code Online (Sandbox Code Playgroud)

取决于我把它放在哪里.这是有道理的(毕竟,我正在调用一个函数,而不是定义它),但我仍然想知道如何做到这一点.(before_create因为还有其他before_create调用,我无法覆盖).

此外,对于包含此模块的所有型号,都应用非常类似的测试.我如何持续测试此功能?我是否将自定义describe ... endrequire写入每个model_spec.rb适用的位置?如何在不诉诸全局变量的情况下传递正确的模型?

任何想法,将不胜感激!

Shi*_*Ray 6

您必须将类方法调用放入class_eval或直接调用它,如:

module IdOrHashFindable

  def self.included(base)
    base.extend(ClassMethods)
    base.before_create :create_hash
    # or
    base.class_eval do
      before_create :create_hash
    end
  end

end
Run Code Online (Sandbox Code Playgroud)

因为当你将方法放在模块中时,它会直接调用它作为模块的方法

  • 我建议使用[ActiveSupport关注](http://opensoul.org/blog/archives/2011/02/07/concerning-activesupportconcern/) (3认同)