ruby-on-rails - ActiveRecord 模型 'type' 多态关联列包括关联模型的命名空间

标签 ruby-on-rails 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_type 关联时 PageTemplateAPageTemplateA )

我想要做出的改变:

我想将上述所有模型移至新的命名空间中,例如 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_type对于 TypeAPage成为PagesEngine::PageTemplateA .

如何告诉 ActiveRecord 不包含命名空间,并解析 pageable_typePageTemplateA而不是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

使用与关联模型 (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

最后重写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

关于ruby-on-rails - ActiveRecord 模型 'type' 多态关联列包括关联模型的命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37243116/

相关文章:

ruby-on-rails - 一个凌乱的 View 层,我应该离开 MVC 吗?

ruby-on-rails - 如何在 Capybara finder 中使用正则表达式?

ruby-on-rails-3 - 如何选择博客模型中的最后一个和倒数第二个条目?

mysql - 恢复迁移时 ActiveRecord::IrreversibleMigration 异常

ruby-on-rails - 在表单嵌套模型中销毁记录而不是更新

ruby-on-rails - ActiveRecord::Relation 上下文中的独立 ActiveRecord 查询

ruby-on-rails - 如何在compoundjs Controller 中从json检索数据

ruby-on-rails - ActiveRecord (Rails) 中的层父类(super class)型

ruby-on-rails - 让 rails-api 和 strong_parameters 一起工作

mysql - 在没有 Arel 的情况下如何在 Rails 中编写此查询