伙计们,我们正在构建一种地址簿,我们有用户、联系人和一个名为 UserEntity 的父表。我们希望通过一个名为关系的表将它们以多对多关联的方式关联起来,这种关系必须在 UserEntity 表中的自相关中。
一位用户有很多联系人,一位联系人有很多用户。
稍后我们需要将新模型与用户相关联,因此关系模型必须是多态的。我们已经构建了这个:
class UserEntity < ActiveRecord::Base
self.table_name = "users"
end
class User < UserEntity
has_many :relationships, as: :relatable
has_many :contacts, through: :relationships, source: :relatable, source_type "Contact"
end
class Contact < UserEntity
has_many :relationships, as: :relatable
has_many :users, through: :relationships, source: :relatable, source_type "User"
end
class Relationship < ActiveRecord::Base
belongs_to :user
belongs_to :relatable, polymorphic: true
end
但是当我们尝试保存关联时
user.contacts << contact
relatable_type
字段保存“UserEntity”值而不是“Contact”或“User”值。我们已经尝试过这样做,但没有任何有利的结果http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Polymorphic+Associations我们怎样才能做到
relatable_type
value 保存模型名称(“Contact”||“User”)而不是 STI 父模型名称(“UserEntity”)?
最佳答案
这就是所谓的 STI
base class
,Rails 将保存 Parent
类,即使你调用了 subclass
.我们有这方面的经验:
上面应该有Node
如Company
...
去年我花了一些时间研究这个;有一个gem
调用 store_sti_base_class
:
Notice that
addressable_type
column isPerson
even though the actual class isVendor
.Normally, this isn't a problem, however it can have negative performance characteristic in certain circumstances. The most obvious one is that a join with persons or an extra query is required to find out the actual type of addressable.
绕过它 - 至少从
gem
的角度来看- 是扩展ActiveRecord
这样它将保存模型的实际类,而不是其父类。我拥有的唯一代码 - 已过时 - 如下:
#config/initializers/sti_base.rb
ActiveRecord::Base.store_base_sti_class = false
#lib/extensions/sti_base_class.rb
module Extensions
module STIBaseClass #-> http://stackoverflow.com/questions/2328984/rails-extending-activerecordbase
extend ActiveSupport::Concern
included do
class_attribute :store_base_sti_class
self.store_base_sti_class = true
end
end
# include the extension
ActiveRecord::Base.send(:include, STIBaseClass)
####
module AddPolymorphic
extend ActiveSupport::Concern
included do #-> http://stackoverflow.com/questions/28214874/overriding-methods-in-an-activesupportconcern-module-which-are-defined-by-a-cl
define_method :replace_keys do |record=nil|
super(record)
owner[reflection.foreign_type] = ActiveRecord::Base.store_base_sti_class ? record.class.base_class.name : record.class.name
Rails.logger.info record.class.base_class.name
end
end
end
ActiveRecord::Associations::BelongsToPolymorphicAssociation.send(:include, AddPolymorphic)
end
由于我需要让这项工作正常进行,因此可能值得开玩笑。
关于ruby-on-rails - 为 STI 模型保存 STI 父类名称而不是 STI 子类名称具有许多直通、自相关和多态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35329578/