当我使用类方法猴子修补 ActiveRecord::Base 时,这些方法由不同模型 ActiveRecord_Relation 类(如 User::ActiveRecord_Relation)继承,并且可以在特定事件记录关系的实例上调用。但是,在对原始模型进行事件记录调用时,这会导致一些意外行为。
这是一个简单的例子:
User.count
=> 3544
users = User.where("created_at > ?", 1.month.ago)
users.count
=> 174
class ActiveRecord::Base
def self.monkey_foo(options = {}, &block)
User.count
end
end
User.monkey_foo
=> 3544
Book.monkey_foo # Another model
=> 3544
users.monkey_foo
=> 173 # This is the count of the users relation, not the User model
Book.where("created_at > 1.year.ago").monkey_foo
=> 3544 # Issue only affects User model relations
是什么导致了这种行为?
我知道像这样的猴子修补对于任何严肃的事情来说都是一个非常糟糕的主意。我无意中发现了这种行为,我很好奇为什么会发生这种情况。
最佳答案
这个问题的关键在delegation.rb
基本上,这有以下方法缺少 Relation 的实现(为了简洁而稍微简化)
def method_missing(method,*args,&block)
scoping { @klass.public_send(method, *args, &block) }
end
(@klass 是关系所属的事件记录类)
作用域方法在 block 的持续时间内设置类的current_scope
。它包含诸如 where 子句、排序等内容。这允许您在关系上调用类方法,并使这些类方法在关系定义的范围内进行操作。
在图书案例中,这种情况仍然发生,但是范围界定发生在图书上,但查询是针对用户的,因此范围界定不会改变结果。
关于ruby-on-rails - 为什么 ActiveRecord::Base 上的猴子修补方法会重新定义 Model.count 上不相关的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39456947/