积极记录,多态与STI有很多共同点

时间:2018-02-14 19:59:39

标签: activerecord has-many-through polymorphic-associations single-table-inheritance sti

我遇到了一些与STI相关的多态性问题。让我解释一下我要做的事情:

假设我有合同。合同可以有许多公司作为协议的当事方,即合同可以有多个许可方(授予合同权利的一方)和一个以上的被许可方(根据合同获得权利的一方)。许可人和被许可人都是可以成为多个合同的当事人的公司。

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

#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 = Contract.new(nickname:"Test Contract")
lor = c.licensors.new(name:"The Licensor Company")
lee = c.licensees.new(name:"Some Licensee Company")
c.save

然后以下内容将起作用:

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_type。

不幸的是,不起作用的是:

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_type为“Company”。我认为这是因为许可方和被许可方均继承公司。

有没有办法在许可方或被许可方模型中的Has Many Through关联中设置party_type?

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

您可以使用rewhere。在Company中定义relationships,其关联范围如下:

has_many :relationships, ->(x) { rewhere(party_type: x.class.name) }, as: :party, dependent: :destroy

您可以在加入中看到party_type Licensor被查询:

>> 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">]>