[英]Double polymorphic association
In my rails app I have two models: Person
and Company
. 在我的rails应用程序中,我有两个模型: Person
和Company
。 I need to specify many-to-many relationship between any pairs of this objects. 我需要指定此对象的任何对之间的多对多关系。 So I should be able do like this: 所以我应该可以这样:
@connections = @person.connections
where @connections
is an array of Person
and Company
objects. 其中@connections
是一个Person
和Company
对象的数组。
Right now I've created ConnectionBinding
model for this and it does not work as wanted: 现在,我为此创建了ConnectionBinding
模型,它无法按需工作:
class ConnectionBinding < ActiveRecord::Base
belongs_to :connect_from, polymorphic: true
belongs_to :connect_to, polymorphic: true
end
It thougths ActiveRecord::HasManyThroughAssociationPolymorphicSourceError
exception 它认为ActiveRecord::HasManyThroughAssociationPolymorphicSourceError
异常
Does anybody already solve this problem? 有人已经解决了这个问题吗? Any suggestions appreciated. 任何建议表示赞赏。
You need to tell ActiveRecord the associated column that it is looking for. 您需要告诉ActiveRecord它正在寻找的关联列。 I'm guessing you want to have the following: 我想您要具备以下条件:
class Person < ActiveRecord::Base
has_many :connection_bindings
has_many :companies, :through => :connection_bindings
has_many :people, :through => :connection_bindings
end
class company < ActiveRecord::Base
has_many :connection_bindings
has_many :companies, :through => :connection_bindings
has_many :people, :through => :connection_bindings
end
The problem there is that you have two tables putting there id in one column and Rails doesn't know which table to look up. 问题在于您有两个表,其中的id放在一列中,Rails不知道要查找哪个表。
For example, on any given connection_binding row in the database, the connect_from can be either a company_id or a person_id and the same is true of connect_to. 例如,在数据库中任何给定的connection_binding行上,connect_from可以是company_id或person_id,connect_to也是如此。 So you say: 'Hey Rails, load up my associated ConnectionBindings' and it gets a row where the connect_from is 11 and the connect_to is 12. But does it do Person.find(12) or Company.find(12)? 因此,您说:“嘿,Rails,加载我关联的ConnectionBindings”,它会得到一行,其中connect_from为11,connect_to为12。但这是Person.find(12)还是Company.find(12)吗? There is no way to tell! 没有办法告诉!
Instead, you'll have to give Rails some more information: 相反,您必须为Rails提供更多信息:
class Person < ActiveRecord::Base
has_many :connection_bindings
has_many :person_connections, :through => :connection_bindings, :source => :to_connect, :source_type => 'Person'
has_many :company_connections, :through => :connection_bindings, :source => :to_connect, :source_type => 'Company
def connections
person_connections + company_connections
end
end
You'll need to build that on the other side (as well as the associated :from_connect's) but it depends on how you're using these connections. 您需要在另一侧(以及相关的:from_connect)上进行构建,但这取决于您如何使用这些连接。 Should be enough to get you started. 应该足以让您入门。
It is a lot more typing than you're used to in the magical world of Ruby and Rails, but it is a very complex data pattern that you're trying to construct. 它比Ruby和Rails的神奇世界中的类型输入要多得多,但是它是您要构造的非常复杂的数据模式。 That doesn't mean it is impossible – Rails, as a good framework, won't stop you from doing anything you really want to – but it is uncommon enough to require some explicitness on your end. 这并不意味着不可能-作为一个好的框架,Rails不会阻止您执行您真正想做的任何事情-但这并不常见,需要在端头进行明确说明。
Thanx Chris for showing the idea. 感谢克里斯(Chris)的想法。 But I need to do some changes to make this work. 但是我需要进行一些更改才能使此工作生效。 The problem of Chris example is that if I call person_connections
method it will generate wrong query. 克里斯示例的问题是,如果我调用person_connections
方法,它将生成错误的查询。
Person.find(720).person_connections
generates this SQL 生成此SQL
SELECT "people".* FROM "people"
INNER JOIN "connection_bindings"
ON "people"."id" = "connection_bindings"."connect_to_id"
WHERE "connection_bindings"."person_id" = 720
AND "connection_bindings"."connect_to_type" = 'Person'
That person_id
column should be connect_from_id
. 该person_id
列应为connect_from_id
。 So I need to add :as => :connect_from
option to has_many :connection_bindings
to show ActiveRecord that its a polymorphic association. 因此,我需要在has_many :connection_bindings
添加:as => :connect_from
选项,以向ActiveRecord显示其多态关联。
has_many :connection_bindings, :as => :connect_from
has_many :person_connections, :through => :connection_bindings,
:source => :connect_to, source_type: 'Person'
has_many :company_connections, :through => :connection_bindings,
:source => :connect_to, source_type: 'Company'
But it is still not enough. 但这还不够。 I need to be able to get reverse connections. 我需要能够获得反向连接。 So if Person @a
adds connection to Person @b
? 因此,如果Person @a
将连接添加到Person @b
? method connections should show that connection in both directions @a.connections
and @b.connections
. 方法连接应该在两个方向上显示该连接@a.connections
和@b.connections
。
And now I think I can do this by adding couple of additional associations and aggregation methods. 现在,我想可以通过添加几个附加的关联和聚合方法来做到这一点。
A Concern: 关心:
module Linkable
extend ActiveSupport::Concern
included do
has_many :links_to, as: :linkable_to, class_name: 'Link' # [this]->[other object]
has_many :links_from, as: :linkable_from, class_name: 'Link' # [other object]->[this]
end
end
Links Table: 链接表:
class Link < ActiveRecord::Base
#The idea for this class is to by a double polymorphic table, linking an object to another object
belongs_to :linkable_from, :polymorphic => true
belongs_to :linkable_to, :polymorphic => true
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.