ruby-on-rails - 为什么 ActiveRecord::Base 上的猴子修补方法会重新定义 Model.count 上不相关的方法

标签 ruby-on-rails activerecord monkeypatching

当我使用类方法猴子修补 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/

相关文章:

ruby-on-rails - has_and_belongs_to_many 按 id 精确匹配

ruby-on-rails - 来自 ActiveRecord 关联的查询结果的自定义排序

ruby-on-rails - 禁用 ActiveRecord 中的事务

mysql - Rails,将列添加到选择语句

mysql - Yii2 通过联结表进行急切负载聚合

ruby - 扩展 uniq 方法

java - 在 Cucumber Rails 应用程序中安装 Java 应用程序

ruby-on-rails - Rails打印出很多不必要的东西

Python 猴子补丁最佳实践

ruby-on-rails - [] Ruby 字符串的方法