简体   繁体   English

双重多态关联

[英]Double polymorphic association

In my rails app I have two models: Person and Company . 在我的rails应用程序中,我有两个模型: PersonCompany 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是一个PersonCompany对象的数组。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM