2011-07-27 122 views
2

我正尝试创建一个包含与Mongoid的多态关系的模块。简单的例子:ActiveSupport中的Mongoid关系::关注模块

module Scalable 
    extend ActiveSupport::Concern 

    included do 
    references_many :scales, :as => :scalable 

    before_save :add_scale 
    end 

    module InstanceMethods 
    def add_scale 
     self.scales.create 
    end 
    end 
end 

class Scale 
    include Mongoid::Document 

    referenced_in :scalable, :index => true 
end 

class ScalableModel 
    include Mongoid::Document 
    include Scalable 
end 

然而,当我试图像ScalableModel.create运行的东西,我得到以下错误:

NoMethodError Exception: undefined method `relations' for Scalable:Module 

这是不可能的,还是我做错了什么?

回答

2

我认为模块(从ScalableScale)在协会是好的,但相反的一半ScaleScalable是一个问题。这是因为目标班级是根据将Mongoid引导至Scalable模块的关联名称派生出来的,当您真的需要它参考ScalableModel类时。然后提出错误,因为Mongoid将模块视为模型类。

起初我以为你必须在可扩展的包含块中定义关联的两侧,但事实证明,你可以通过标记为多态来修复关联的缩放侧。

还有另外一个问题,self.scale.create引发异常,因为直到保存父对象后才能创建新的子对象。为了解决这个问题,我只使用了after_save。这是我想出来的:

module Scalable 
    extend ActiveSupport::Concern 

    included do 
    references_many :scales, :as => :scalable 
    after_save :add_scale      # changed from before_save 
    end 

    module InstanceMethods 
    def add_scale 
     self.scales.create 
    end 
    end 
end 

class Scale 
    include Mongoid::Document 
    referenced_in :scalable_model, :index => true, :polymorphic => true 
end 

class ScalableModel1 
    include Mongoid::Document 
    include Scalable 
end 

class ScalableModel2 
    include Mongoid::Document 
    include Scalable 
end 

s1 = ScalableModel1.create 
s2 = ScalableModel2.create 
+0

非常感谢Steve,这很好地工作。通过添加':autosave => true'并将'self.scales.create'更改为'self.scales.build'在回调中,我实际上能够保留回调。 – geetarista