Activerecord 活动记录,多态性与STI有许多联系

Activerecord 活动记录,多态性与STI有许多联系,activerecord,has-many-through,polymorphic-associations,single-table-inheritance,sti,Activerecord,Has Many Through,Polymorphic Associations,Single Table Inheritance,Sti,我有一些问题与多态性有很多通过与性传播感染。让我解释一下我想做什么: 假设我有一份合同。一份合同可以有多家公司作为协议的当事方,即一份合同可以有多个许可方作为合同中授予权利的一方,多个被许可方作为合同下接受权利的一方。许可方和被许可方都是可以成为多个合同当事人的公司 到目前为止,我有以下代码: #contract.rb class Contract < ApplicationRecord has_many :relationships, dependent: :destroy ha

我有一些问题与多态性有很多通过与性传播感染。让我解释一下我想做什么:

假设我有一份合同。一份合同可以有多家公司作为协议的当事方,即一份合同可以有多个许可方作为合同中授予权利的一方,多个被许可方作为合同下接受权利的一方。许可方和被许可方都是可以成为多个合同当事人的公司

到目前为止,我有以下代码:

#contract.rb
class Contract < ApplicationRecord
  has_many :relationships, dependent: :destroy
  has_many :companies, through: :relationships
  has_many :licensors, through: :relationships, source: :party, source_type: "Licensor"
  has_many :licensees, through: :relationships, source: :party, source_type: "Licensee"
end

#relationship.rb
class Relationship < ApplicationRecord
  belongs_to :contract
  belongs_to :party, polymorphic: true
end

#company.rb
class Company < ApplicationRecord
  has_many :relationships, as: :party, dependent: :destroy
  has_many :contracts, through: :relationships
end

#licensor.rb
class Licensor < Company
end

#licensee.rb
class Licensee < Company
end
然后,以下步骤将起作用:

c.licensors # results in...
Licensor Load (1.1ms)  SELECT  "companies".* FROM "companies" INNER JOIN "relationships" ON "companies"."id" = "relationships"."party_id" WHERE "relationships"."contract_id" = $1 AND "relationships"."party_type" = $2 LIMIT $3  [["contract_id", 1], ["party_type", "Licensor"], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Licensor id: 1, name: "The Licensor Company", created_at: "2018-02-14 19:46:19", updated_at: "2018-02-14 19:46:19">]>

c.licensees # results in...
Licensee Load (1.3ms)  SELECT  "companies".* FROM "companies" INNER JOIN "relationships" ON "companies"."id" = "relationships"."party_id" WHERE "relationships"."contract_id" = $1 AND "relationships"."party_type" = $2 LIMIT $3  [["contract_id", 1], ["party_type", "Licensee"], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Licensee id: 2, name: "Some Licensee Company", created_at: "2018-02-14 19:46:19", updated_at: "2018-02-14 19:46:19">]>
因此,许可方和被许可方被正确创建,并且他们的party_类型被正确设置

不幸的是,以下情况不起作用:

lor = Licensor.first
lor.contracts # which results in...
Contract Load (0.9ms)  SELECT  "contracts".* FROM "contracts" INNER JOIN "relationships" ON "contracts"."id" = "relationships"."contract_id" WHERE "relationships"."party_id" = $1 AND "relationships"."party_type" = $2 LIMIT $3  [["party_id", 1], ["party_type", "Company"], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy []>
如您所见,我无法查询特定许可方或被许可方的合同列表。这似乎是因为我当前的设置导致查询的公司类型为party_。我认为这是因为许可方和被许可方都是从公司继承的

在许可方或被许可方的模型中,是否有办法通过关联来设置Has Many中的party_类型

任何帮助都将不胜感激。

您可以在此处使用REW。在公司中,定义与以下关联范围的关系:

has_many :relationships, ->(x) { rewhere(party_type: x.class.name) }, as: :party, dependent: :destroy
您可以在连接中看到正在查询的许可方类型:

>> l = Licensor.first
  Licensor Load (1.4ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."type" IN ('Licensor') ORDER BY "companies"."id" ASC LIMIT $1  [["LIMIT", 1]]
=> #<Licensor id: 1, name: "The Licensor Company", type: "Licensor", created_at: "2018-02-23 00:38:13", updated_at: "2018-02-23 00:38:13">
>> l.contracts
  Contract Load (1.9ms)  SELECT  "contracts".* FROM "contracts" INNER JOIN "relationships" ON "contracts"."id" = "relationships"."contract_id" WHERE "relationships"."party_id" = $1 AND "relationships"."party_type" = $2 LIMIT $3  [["party_id", 1], ["party_type", "Licensor"], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Contract id: 1, name: "Test Contract", created_at: "2018-02-23 00:38:13", updated_at: "2018-02-23 00:38:13">]>

没有专家,但也许在“属于”一侧设置“反向”可以有所帮助?反向关联的自动猜测使用基于类名称的启发式方法,因此它可能不适用于所有关联,尤其是具有非标准名称的关联-
>> l = Licensor.first
  Licensor Load (1.4ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."type" IN ('Licensor') ORDER BY "companies"."id" ASC LIMIT $1  [["LIMIT", 1]]
=> #<Licensor id: 1, name: "The Licensor Company", type: "Licensor", created_at: "2018-02-23 00:38:13", updated_at: "2018-02-23 00:38:13">
>> l.contracts
  Contract Load (1.9ms)  SELECT  "contracts".* FROM "contracts" INNER JOIN "relationships" ON "contracts"."id" = "relationships"."contract_id" WHERE "relationships"."party_id" = $1 AND "relationships"."party_type" = $2 LIMIT $3  [["party_id", 1], ["party_type", "Licensor"], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Contract id: 1, name: "Test Contract", created_at: "2018-02-23 00:38:13", updated_at: "2018-02-23 00:38:13">]>