默认情况下如何转换ActiveRecord :: Relation

时间:2015-02-12 21:48:04

标签: ruby activerecord

我正在开发一个项目,需要在ActiveRecord::Relation对象上调用非常具体的方法。这些方法无法扩展ActiveRecord::Relation,因为Class拥有自己的initialize方法来确定是否应该收集对象。我已经尝试了十几种方法来处理这个问题,但由于AR中的方法链接,我无法完成此任务。目前我使用一种方法修改了ActiveRecord::Relation,并将其转换为:

module ActiveRecord
  class Relation
    def to_claim_set
      exec_queries unless loaded?
      ClaimSet.new(@records)
    end
  end
end

首先,我确信这是处理它的一种不正确的方法。其次,这导致我必须在整个应用程序中不断调用#to_claim_set

我希望有人可以在所有方法链接完成后协助将此作为默认返回。

我希望的是

Claim.policy_number('913006')
#=> ClaimSetObjectHere

但是我需要它支持像AR这样的链接,以便像

这样的东西
Claim.policy_number('913006').by_program('Base')
#=> ClaimSetObjectHere

我还尝试在#where内修补Claim方法,除非我使用scope或I链式方法,否则它会起作用ClaimSet定义default_scoped?

非常感谢任何见解。至于"为什么你要这样做" 就像我说我在整个应用程序中不断调用这个方法而我需要在ClaimSet中定义的方法功能正常。

注意:这是在rails

之外使用的

1 个答案:

答案 0 :(得分:0)

好的,我最终做的是为ActiveRecord::Relation强加一个包装器,如下所示:(为简洁起见,删除了特定的业务逻辑)

class ClaimSet
   def initialize(object)
     process_target(object)
    # ...
   end
  # ...
   def respond_to_missing?(method_name,include_private=false)
     @target.respond_to?(method_name)
   end
   def method_missing(method_name, *args, &block)
     if @target.respond_to?(method_name)
       ClaimSet.new(@target.send(method_name,*args,&block))
     else
       super
     end
   end
   private
     def process_target(object)
       @target = object if object.is_a?(ActiveRecord::Relation)
       @target = object.target if object.is_a?(ClaimSet)
     end
 end

然后在Claim班。

 class Claim < ActiveRecord::Base
    class << self
      def where(*args)
        ClaimSet.new(super(*args))
      end
      def localized_scope(name,proc)
        scope_proc = lambda do |*args|
          ClaimSet.new(proc.call(*args))
        end
        singleton_class.send(:define_method,name,scope_proc)
      end
   end
 end 

然后我将所有范围定义为localized_scope,例如

localized_scope :policy_number, ->(policy_number){where(policy_number: policy_number)}

现在它总是返回ClaimSet代替ActiveRecord::Relation#where的{​​{1}},并支持通过#localized_scope进行方法链接。它还删除了#method_missing上的猴子补丁。

如果您有任何其他建议,请告诉我,因为我很乐意接受其他想法,但这暂时适用。