重写CollectionProxy查找方法

时间:2018-11-02 16:28:18

标签: ruby-on-rails ruby activerecord

重写ActiveRecord的find的正确方法是什么,以使其在模型类(如Comment.find(1))和集合(如post.comments.find(1))上使用时具有相同的行为?

让我们以这两个简单的模型为例:

class Post < ApplicationRecord
  has_many :comments
end

class Comment < ApplicationRecord
  belongs_to :post

  def self.find(*args)
    puts 'Overridden find called!'
    super
  end
end

对于这样的类,Comment.find(1)正确使用了重写方法,但是post.comments.find(1)仍使用find的原始版本。 我知道我可以在#find中覆盖ActiveRecord::Associations::CollectionProxy,但是我不喜欢这种解决方案,因为它会影响应用程序中的每个模型。您能提出正确的解决方案吗?

编辑: 我想要实现的是:

Comment.find(1) # prints 'Overridden find called'
some_post.comments.find(1) # prints 'Overridden find called'
Post.find(1) # does NOT print 'Overridden find called', calls regular find

1 个答案:

答案 0 :(得分:3)

由于CollectionProxyfind上调用了CollectionAssociation,随后又调用了scope.find,因此您不需要做任何花哨的操作来覆盖:

module CustomFinder
  def find
    puts "I'm noisy!"
    super
  end
end

class Post < ApplicationRecord
  extend CustomFinder
  has_many :comments
end

class Comment < ApplicationRecord
  extend CustomFinder
  belongs_to :post
end

或者,如果您要做在每个模型上都想要这样做:

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
  extend CustomFinder
end

将来,您可以使用foo.method(:find).source_location,然后在Github上查看相关代码,以更好地了解幕后情况,而不会浪费很多时间在黑暗中摸索。

有关如何执行此操作的另一个示例,check out the way Friendly ID handles it