我正在编写一个应用程序,其中许多(但不是全部)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
为了让事情变得干燥,我想在模块内部进行before_create
调用。但是,我一直得到
undefined method `before_create' for IdOrHashFindable:Module
或
undefined method `before_create' for IdOrHashFindable::ClassMethods:Module
取决于我把它放在哪里。这是有道理的(毕竟,我正在调用一个函数,而不是定义它),但我仍然想知道如何做到这一点。 (我无法覆盖before_create
,因为还有其他before_create
次调用。
此外,对于包含此模块的所有型号,都应用非常相似的测试。我如何持续测试此功能?我是否将自定义describe ... end
块及require
写入适用的每个model_spec.rb
?如何在不诉诸全局变量的情况下传递正确的模型?
任何想法都将不胜感激!
答案 0 :(得分: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
因为当你将方法放在模块中时,它会直接调用它作为模块的方法