【问题标题】:ActiveRecord associations with two different modelsActiveRecord 与两个不同模型的关联
【发布时间】:2019-01-21 15:31:56
【问题描述】:

我很难思考应该如何配置我的表 + 关联。

我有一个Lawsuit 模型。诉讼has_many各方(被告、原告、律师等)。反过来,聚会可以是PersonCompany。最终,我希望能够得到:

  • 一个人的诉讼(@person.lawsuits);
  • 公司诉讼(@company.lawsuits);和
  • 诉讼当事人 (@lawsuit.parties),可以是 peoplecompanies

这就是我目前设置表格和模型的方式:

| id | fname  | lname | date_of_birth |
| -- | ------ | ----- | ------------- |
|  1 | John   | Smith |    1974-02-04 |
|  2 | George | Glass |    1963-07-29 |

公司

| id | name      | duns      | ticker | address      |
| -- | --------- | --------- | ------ | ------------ |
|  1 | Acme Inc. | 239423243 | ACME   | 123 Main St. |

诉讼

| id | jurisdiction | court | case_no    | title                       |
| -- | ------------ | ----- | ---------- | --------------------------- |
|  1 |      federal | SDNY  | 18-CV-1234 | Smith v. Glass, Acme, et al |

诉讼当事人

| id | lawsuit_id | person_id | company_id | role      |
| -- | ---------- | --------- | ---------- | --------- |
|  1 |          1 |         1 |            | plaintiff |
|  2 |          1 |         2 |            | defendant |
|  3 |          1 |           |          1 | defendant |
# models/lawsuit.rb:
class Lawsuit < ApplicationRecord
    has_many :lawsuit_parties

    def parties
        self.lawsuit_parties
    end

    def defendants
        self.parties(where(lawsuit_parties: {role: 'defendant'})
    end

    def plaintiffs
        self.parties(where(lawsuit_parties: {role: 'plaintiff'})
    end

    def attorneys
        self.parties(where(lawsuit_parties: {role: 'attorney'})
    end
end
# models/lawsuit_party.rb
class LawsuitParty < ApplicationRecord
    belongs_to :person
    belongs_to :company
end
# models/person.rb
class Person < ApplicationRecord
    has_many :lawsuit_parties
    has_many :lawsuits, through: :lawsuit_parties
end
# models/company.rb
class Company < ApplicationRecord
    has_many :lawsuit_parties
    has_many :lawsuits, through: :lawsuit_parties
end

任何帮助将不胜感激......

【问题讨论】:

    标签: ruby-on-rails ruby activerecord ruby-on-rails-5 polymorphic-associations


    【解决方案1】:

    您在正确的轨道上,但您需要在您的加入模型中引入polymorphic relationship 才能使这种类型的建模工作。 An Enum can handle differentiating between Defendants and Plaintiffs,并免费提供您要求的几种范围/方法。

    class LawsuitParty < ApplicationRecord
        belongs_to :lawsuit
        belongs_to :partiable, polymorphic: true
    
        enum role: [:defendant, :plaintiff]
    end
    

    您需要编写迁移以将 lawsuit_parties 表更改为以下列(所有 Rails 约定名称):

    partiable_id   = Integer
    partiable_type = String
    role           = String
    
    lawsuit_parties
    
    | id | lawsuit_id | partiable_id | partiable_type | role      | 
    | -- | ---------- | ------------ | -------------- | ----------|
    |  1 |          1 |            1 | Person         | defendant |
    |  2 |          1 |            2 | Company        | plaintiff |
    |  3 |          1 |            1 | Company        | defendant |
    

    接下来,使用has_many:as 选项告诉Rails PersonCompany 记录与许多Lawsuit 相关联。

    class Person < ApplicationRecord
        has_many :lawsuit_parties, as: :partiable
        has_many :lawsuits, through: :lawsuit_parties
    end
    

    将相同的has_many :lawsuit_parties, as: :partiable 添加到公司,或以后可能出现的任何其他模型(即JudgeJuryMember)。

    一旦您设置了这样的诉讼派对,您就应该准备就绪。

    【讨论】:

    • 我想这让我明白了,谢谢!要创建关联,@lawsuit.lawsuit_parties &lt;&lt; Person.first 得到以下错误:ActiveRecord::AssociationTypeMismatch (LawsuitParty(#70357266387440) expected, got #&lt;Person id: 1, fname: "John", lname: "Doe", created_at: "2019-01-21 04:07:20", updated_at: "2019-01-21 04:07:20"&gt; which is an instance of Person(#70357238653680)) 我是否需要手动创建 LawsuitParty 记录(`@lawsuit.lawsuit_parties.create(paritable_type: "Person", role "plaintiff"),或者有这方面的捷径吗?
    • 很高兴为您提供帮助。您定义了 parties 以映射到某处的 LawsuitParty 记录。该错误告诉您您正在尝试将错误类型的记录铲到该关联上。我不完全了解你的 DSL,但也许你的意思是 @lawsuit.people &lt;&lt; Person.first ??
    • 啊,我错了。我在返回self.lawsuit_parties 的诉讼模型中添加了parties 方法。所以我的问题是,一旦建立了关系和表格,将个人、公司等添加到诉讼方的标准方法是什么。例如,@lawsuit.lawsuit_parties &lt;&lt; Person.first(但这就是返回上述错误的原因)。
    • def各方; self.lawsuit_party;结束 - 是问题所在。简单的做法是在诉讼中定义一个“add_party_as(partiable:, role:)”方法,这样您就不必过多地摆弄 Rails。定义如何在那里添加派对。类似于self.lawsuit_parties.create(args)
    猜你喜欢
    • 2015-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多