如何使用新方法扩展 ActiveRecord 关系?

kim*_*rey 5 activerecord ruby-on-rails

假设我有这样的简单 ActiveRecord 模型:

class Post < ActiveRecord::Base
  belongs_to :category
end

class Category < ActiveRecord::Base
  has_many :posts
  has_many :published_posts, -> { where(:published => true) }
end
Run Code Online (Sandbox Code Playgroud)

我想创建一个模块Reindexable,它将添加一个调用reindex到基类中的方法。我希望能够通过以下 3 种方式调用此方法:

Place.reindex
Place.reindex(Place.where(:published => true))
Place.where(:published => true).reindex
Category.first.places.reindex
Run Code Online (Sandbox Code Playgroud)

在这个方法里面,我应该能够做这样的事情:

Reindexer.new(relation).reindex # how can I get relation here?
Run Code Online (Sandbox Code Playgroud)

在 Ruby-on-Rails 中执行此操作的正确方法是什么?在所有这种情况下,我如何访问当前关系?

小智 0

我尝试将代码包含到 ActiveRecord_Relation 类中,该类会动态添加到任何 AR 类中。

如果您需要将 .to_csv 添加到所有调用(例如 MyModel.all.to_csv):

模型:

class MyModel < ActiveRecord::Base
  include ToCsv
end
Run Code Online (Sandbox Code Playgroud)

您想要包含的模块

module ToCsv
  extend ActiveSupport::Concern

  #  Dynamically including our Relation and extending current class
  #
  def self.included(child_class)
    child_class.const_get('ActiveRecord_Relation').include(RelationMethods)
    child_class.extend(ExtendMethods)
  end

  #  Instance Method
  #
  def to_csv(opts = {})
  end

  #  Module containing methods to be extended into the target
  #
  module ExtendMethods

    #  Allowing all child classes to extend ActiveRecord_Relation
    #
    def inherited(child_class)
      super + (child_class.const_get('ActiveRecord_Relation').include(RelationMethods) ? 1 : 0 )
    end
  end

  #  Holds methods to be added to relation class
  #
  module RelationMethods
    extend ActiveSupport::Concern

    #  Relation Method
    #
    def to_csv(opts = {})
    end
  end
end
Run Code Online (Sandbox Code Playgroud)