使用ActiveRecord:特定类的关系,而不是ActiveRecord之间的所有关系

时间:2014-02-18 22:40:11

标签: ruby-on-rails ruby activerecord ruby-on-rails-4 gem

我正在构建一个gem,其目的之一是扩展目标类的关联。虽然我可以通过使用类似的东西轻松扩展所有关联:

 ActiveRecord::Relation.send(:include, MyGem::ActiveRecord::RelationMethods)

这太宽泛了,对于可能使用这个Gem的Rails应用程序,我不想扩展所有类的关联。

为了更好的粒度,我想提供相应的:

 class User < ActiveRecord::Base

    has_many :messages, :extend => MyGem::ActiveRecord::RelationMethods
    has_many :comments, :extend => MyGem::ActiveRecord::RelationMethods

 end

使用

class User < ActiveRecord::Base

    acts_as_my_fancy_gem

    has_many :messages
    has_many :comments

 end

当我将acts_as_my_fancy_gem添加到类中时,我遇到的问题是尝试在Gem中有条件地扩展关联。这是它的基础。

module MyGem

   extend ActiveSupport::Concern

   def self.included(base)
     base.extend ClassMethods
   end  

  module ClassMethods

    def acts_as_my_fancy_gem
      include MyGem::InstanceMethods
    end

  end

  module InstanceMethods

   ...

  end
 end

我已经研究过反射,但此时可以找到一条清晰的路径,并且只是在黑暗中进行实验。

更新:

目前,我可以通过提供像

这样的类方法来实现每个关联
class User < ActiveRecord::Base

    has_many :messages
    has_many :comments

    fancy_extend :messages

 end

module MyGem

   extend ActiveSupport::Concern

   def self.included(base)
     base.extend ClassMethods
   end  

  module ClassMethods

    def acts_as_my_fancy_gem
      include MyGem::InstanceMethods
    end

    def fancy_extend *associations
       class_eval do
            associations.each do |association|
                reflections[association].options[:extend] = MyGem::ActiveRecord::RelationMethods
            end 
       end
    end


  end

  module InstanceMethods

   ...

  end
 end

将这种方法添加到act_as_my_fancy方法(我想要它的地方)中,这给了我:

 # NoMethodError: undefined method `options' for nil:NilClass

1 个答案:

答案 0 :(得分:1)

这是轨道4吗?我没有找到记录的:extend选项。看起来rails 4现在使用块来做到这一点。

可能就是这么简单:

module Fancy
  def has_many(name, scope = nil, options = {})
    super(name, scope, options) do
      def doit
        "i did"
      end
    end
  end
end

# in your model
extend Fancy

YourModel.your_relation.doit # => 'i did'