2016-05-15 137 views
2

问题的命名空间:ActiveRecord的模型“型”态关联的列包含关联的模型

我怎么能告诉ActiveRecord的不包括关联类的命名空间,而存储/查询关联类型列?

当前的事物状态:

考虑下面的类定义:

class PageTemplateA < ActiveRecord::Base 
    has_many :type_a_pages, :as => :pageable, :class_name => 'TypeAPage', :inverse_of => :pageable 
end 

##### The following class is implemented through STI. 
class TypeAPage < Page 
    belongs_to :pageable, :class_name => 'PageTemplateA', :inverse_of => :type_a_page 
end 

class Page < ActiveRecord::Base 
    belongs_to :pageable, :polymorphic => true 
end 

总结:

  • TypeAPage通过STI数据库中的表来实现,pages
  • TypeAPagePageTemplateA通过多态关联相关(pages.pageable_typePageTemplateAPageTemplateA相关)

我想说明的变化:

我想移动所有上述型号为新名称空间,比如说PagesEngine,所以我对PageTemplateA的定义如下所示:

module PagesEngine 
    class PageTemplateA < ActiveRecord::Base 
    has_many :type_a_pages, :as => :pageable, :class_name => 'TypeAPage', :inverse_of => :pageable 
    end 
end 

这工作正常,除了,ActiveRecord推断pageable_typeTypeAPagePagesEngine::PageTemplateA

如何告诉ActiveRecord不包含名称空间,并将pageable_type改为PageTemplateA而不是PagesEngine::PageTemplateA

回答

0

使用self.sti_name覆盖型列名的各等级:

module PagesEngine 
    class PageTemplateA < ActiveRecord::Base 
    def self.sti_name 
     "PageTemplateA" 
    end 
    end 
end 

您可能会发现下面的博客文章有用:https://lorefnon.me/2014/07/27/optimizing-sti-columns.html

+0

感谢您的回应,安东尼。 但是,在这种情况下,'PageTemplateA'上没有执行STI。它实际上是在'TypeAPage'上。 – progfan

2

对于持有多形关系模型,你可以设置self.store_full_sti_class = false或从将store_full_sti_class设置为false的抽象模型继承。

module PagesEngine 
    class Page < Base 
    # self.store_full_sti_class = false 
    belongs_to :pageable, polymorphic: true 
    end 

    class TypeAPage < Page 
    belongs_to :pageable, 
       class_name: 'PageTemplateA', 
       inverse_of: :type_a_pages 
    end 
end 

明确范围的关系(type_as_pages)与型柱(pageable_type)匹配关联的模型(PagesEngine :: PageTemplateA),但没有的命名空间。

module PagesEngine 
    class PageTemplateA < Base 
    has_many :type_a_pages, 
      -> { where(pageable_type: 'PageTemplateA') }, 
      foreign_key: :pageable_id, 
      inverse_of: :pageable 
    end 
end 

最后覆盖belongs_to方法并自定义活动记录属于多态关联。

module PagesEngine 
    class Base < ActiveRecord::Base 
    self.abstract_class = true 
    self.store_full_sti_class = false 

    def self.belongs_to(name, scope = nil, options = {}) 
     super(name, scope, options).tap do |hash| 
     reflection = hash[name.to_s] 
     def reflection.association_class 
      if polymorphic? 
      BelongsToPolymorphicAssociation 
      else 
      super 
      end 
     end unless store_full_sti_class 
     end 
    end 
    end 

    class BelongsToPolymorphicAssociation < ActiveRecord::Associations::BelongsToPolymorphicAssociation 
    def klass 
     type = owner[reflection.foreign_type] 
     type.presence && PagesEngine.const_get(type) 
    end 
    end 
end