我有一个Person类,我想代表贡献者,如委员会的主席和副主席(以及后来的其他事情)。所以在我的委员会课程中,我想使用Person类来提供一个主席和许多副主席:
Chairs和ViceChairs都是人。
我期待说
class Committee < ActiveRecord::Base
has_many :vice_chairs, class_name: 'People'
has_one :chair, class_name: 'People'
end
class Person < ActiveRecord::Base
belongs_to :group, foreign_key: 'vice_chair_id'
belongs_to :group, foreign_key: 'chair_id'
end
这是正确的方法吗?
更新:我被建议使用Single Table Inheritance来解决此问题。我改变了我的代码:
class Person < ActiveRecord::Base
end
class Chair < Person
end
class ViceChair < Person
end
class CreatePeople < ActiveRecord::Migration
def change
create_table :people do |t|
t.string :type
t.string :first_name
t.string :last_name
t.string :email
t.string :affiliation
t.timestamps null: false
end
end
end
这会有用吗?如何编写迁移以支持此操作?
答案 0 :(得分:2)
根据模型类型要求略有不同的行为但属性相同的用例,最好使用单表继承[1]。
所以我建议如下:
<强>型号:强>
class Group < ApplicationRecord
has_many :vice_chairs
has_one :chair
end
class Person < ApplicationRecord
belongs_to :group
end
class ViceChair < Person
belongs_to :group
end
class Chair < Person
belongs_to :group
end
<强>迁移强>
class CreateGroups < ActiveRecord::Migration[5.0]
def change
create_table :groups do |t|
t.string :name
t.timestamps
end
end
end
class CreatePeople < ActiveRecord::Migration[5.0]
def change
create_table :people do |t|
t.string :type
t.string :full_name
t.integer :age
t.references :group, foreign_key: true
t.timestamps
end
end
end
使用示例:
# create some test data
grp = Group.create!(name: "superheros")
vc = ViceChair.create!(full_name: "Superman Sam")
c = Chair.create!(full_name: "Batman Bob")
p = Person.create!(full_name: "Regular John Doe")
# add to group's ViceChairs
grp.vice_chairs << vc
# add Chair to group
grp.chair = c
grp.save!
# Convert person to vice chair
p.type = "ViceChair"
p.save!
new_vc = ViceChair.where(full_name: p.full_name).first
grp.vice_chairs << new_vc
grp.vice_chairs.count
# => 2
rails CLI命令:
rails generate model Group name
rails generate model Person type full_name age:integer group:references:index
rails generate model ViceChair group:references --parent=Person
rails generate model Chair group:references --parent=Person
处理管理主席变更的业务逻辑:
您需要添加一些自定义逻辑来管理主席关联,而无需创建悬空椅。我建议将一个实例方法添加到Group类中add_chair
和remove_chair
,然后您需要决定将Person从主席位置移除时会发生什么。他们可能成为一个普通人。在这种情况下,您可以将类型设置为nil
。
享受!
[1]有关STI http://guides.rubyonrails.org/association_basics.html#single-table-inheritance
的更多信息答案 1 :(得分:0)
如果您的公共字段具有不同的型号名称,那么只需在表格中添加类型字段即可使用Single Table Inheritance
。该字段包含型号名称。
您可以参考以下链接获取单表继承https://github.com/maxime1992/angular-ngrx-starter