【问题标题】:Active Record, Polymorphic Has Many Through with STIActive Record、多态性与 STI 有很多不同之处
【发布时间】:2018-02-14 19:59:38
【问题描述】:

我在与 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 为“公司”。我认为这是因为许可方和被许可方都从公司继承。

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

任何帮助将不胜感激。

【问题讨论】:

  • 不是专家,但也许在belongs_to 一侧设置逆可以在这里提供帮助? “反向关联的自动猜测使用基于类名的启发式算法,因此它可能不适用于所有关联,尤其是那些具有非标准名称的关联。” - api.rubyonrails.org/classes/ActiveRecord/Associations/…

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


【解决方案1】:

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

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

可以看到Licensorparty_type在join中被查询:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多