如何在 Rails 中使用单个表继承对人员和公司进行建模?



在我的发票应用程序中,invoices可以发送到companyperson。据我了解,这是Rails的单表继承(STI(的一个很好的用例。由于这两种类型共享许多属性和函数,我认为超类Recipient可能是一个不错的方法:

class Recipient < ActiveRecord::Base 
end
class Company < Recipient
has_many :people
end
class Person < Recipient
belongs_to :company
end

我也明白我需要在Recipient模型中type属性。

唯一困扰我的是person可能(也可能不属于(company的事实。如何在 Rails 中对此进行建模?通常,我只需将另一个数据库字段company_id添加到people表中。但是这里只有一个表(recipients(。那么如何做到这一点呢?

感谢您的任何帮助。

结构可能如下所示:

class Recipient < ActiveRecord::Base 
has_many :invoices
end
class Company < Recipient
has_many :people
end
class Person < Recipient
belongs_to :company
end
class Invoice < ActiveRecord::Base
belongs_to :recipients
end
# Schema
create_table "invoices", force: :cascade do |t|
t.integer "recipient_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["recipient_id"], name: "index_invoices_on_recipient_id"
end
create_table "recipients", force: :cascade do |t|
t.integer "company_id"
t.string "type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

我刚刚在控制台中尝试过:

> Recipient.all
=> [#<Company:0x007fd55d797220
id: 1,
company_id: nil,
type: "Company",
created_at: Fri, 04 Aug 2017 10:57:41 UTC +00:00,
updated_at: Fri, 04 Aug 2017 10:57:41 UTC +00:00>,
#<Person:0x007fd55d796730
id: 2,
company_id: 1,
type: "Person",
created_at: Fri, 04 Aug 2017 10:57:41 UTC +00:00,
updated_at: Fri, 04 Aug 2017 10:57:41 UTC +00:00>,
#<Person:0x007fd55d796208
id: 3,
company_id: nil,
type: "Person",
created_at: Fri, 04 Aug 2017 10:57:41 UTC +00:00,
updated_at: Fri, 04 Aug 2017 10:57:41 UTC +00:00>]
> Person.last.company
Person Load (0.2ms)  SELECT  "recipients".* FROM "recipients" WHERE "recipients"."type" IN ('Person') ORDER BY "recipients"."id" DESC LIMIT ?  [["LIMIT", 1]]
=> nil
> Person.first.company
Person Load (0.2ms)  SELECT  "recipients".* FROM "recipients" WHERE "recipients"."type" IN ('Person') ORDER BY "recipients"."id" ASC LIMIT ?  [["LIMIT", 1]]
Company Load (0.2ms)  SELECT  "recipients".* FROM "recipients" WHERE "recipients"."type" IN ('Company') AND "recipients"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<Company id: 1, company_id: nil, type: "Company", created_at: "2017-08-04 10:57:41", updated_at: "2017-08-04 10:57:41">
class Recipient < ActiveRecord::Base 
end
class Company < Recipient
has_many :people, class_name: "Recipient", foreign_key: 'parent_id' 
end
class Person < Recipient
belongs_to :company, class_name: "Recipient", foreign_key: 'parent_id'
end

只需向收件人迁移添加parent_id即可。 这就是它简单快捷,您可以获得您想要的模型两个 STI 和has_many并在companyperson之间belongs_to

最新更新