pro*_*fan 2 activerecord ruby-on-rails
问题:
如何告诉 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
Run Code Online (Sandbox Code Playgroud)
总结一下:
TypeAPage
是通过数据库表中的STI实现的pages
。TypeAPage
PageTemplateA
通过多态关联关联(pages.pageable_type
当PageTemplateA
与 关联时PageTemplateA
)我想做的改变:
我想将上述所有模型移到一个新的命名空间中,例如 ,PagesEngine
所以我的定义PageTemplateA
如下:
module PagesEngine
class PageTemplateA < ActiveRecord::Base
has_many :type_a_pages, :as => :pageable, :class_name => 'TypeAPage', :inverse_of => :pageable
end
end
Run Code Online (Sandbox Code Playgroud)
这工作得很好,除了ActiveRecord 推断pageable_type
forTypeAPage
是PagesEngine::PageTemplateA
。
我如何告诉 ActiveRecord 不包含名称空间,并解析pageable_type
为PageTemplateA
而不是PagesEngine::PageTemplateA
?
对于保存多态关系的模型,您可以设置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
Run Code Online (Sandbox Code Playgroud)
使用与关联模型 (PagesEngine::PageTemplateA) 匹配但没有命名空间的类型列 (pageable_type) 显式确定关系 (type_as_pages) 的范围。
module PagesEngine
class PageTemplateA < Base
has_many :type_a_pages,
-> { where(pageable_type: 'PageTemplateA') },
foreign_key: :pageable_id,
inverse_of: :pageable
end
end
Run Code Online (Sandbox Code Playgroud)
最后重写belongs_to方法并自定义Active Record属于多态关联。
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
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1803 次 |
最近记录: |