如何在ActiveRecord中动态设置belongs_to关联?

时间:2013-10-08 20:36:41

标签: ruby-on-rails ruby activerecord

我试图创建一个mixin,它允许ActiveRecord模型充当另一个模型的委托。所以,这是典型的方式:

class Apple < ActiveRecord::Base
   def foo_species
      "Red delicious"
   end    
end


class AppleWrapper < ActiveRecord::Base
   belongs_to :apple
   # some meta delegation code here so that AppleWrapper 
   # has all the same interface as Apple
end


a = Apple.create
w = AppleWrapper.create
w.apple = a 
w.foo_species
# => 'Red delicious'

我想要的是将这种行为抽象为一个Mixin,所以给定一堆数据模型,我可以创建&#34; Wrapper&#34;也是ActiveRecords的类,但每个包装器对应一个特定的类。为什么?每个数据模型都有计算,与其他模型的聚合,我想要&#34; Wrapper&#34;包含与这些计算相对应的字段(在模式中)的类......所以实际上。 Wrapper充当原始数据模型的缓存版本,具有相同的界面。

我必须写出每个Wrapper ...所以对于Apple,Orange,Pear,每个都有一个不同的Wrapper模型。但是,我只想抽象出包装器的行为...这样就有了一个类级别的方法来设置Wrapper指向的内容,la:

module WrapperMixin
    extend ActiveSupport::Concern
    module ClassMethods
       def set_wrapped_class(klass)
        # this sets the relation to another data model and does the meta delegation
        end
    end
end


class AppleWrapper < ActiveRecord::Base
    include WrapperMixin
    set_wrapped_class Apple
end

class OrangeWrapper < ActiveRecord::Base
    include WrapperMixin
    set_wrapped_class Orange
end

我该如何设置?这是否必须是STI类型的关系?也就是说,Wrapper类必须有一个wrapped_record_id和一个wrapped_record_type吗?

1 个答案:

答案 0 :(得分:2)

您可以在belongs_to方法中使用set_wrapped_class

def set_wrapped_class(klass)
  belongs_to klass.to_s.downcase.to_sym
end