我遇到了一些与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?
非常感谢任何帮助。
答案 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">]>