2016-05-15 165 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