我正在努力寻找为团队/成员/人定义模型的最佳方式,其中一个人可以是许多团队的成员,团队可以拥有许多成员。与“成员”关系一起是该人填补团队的位置。一支球队也应该只有一名主教练和一名助理教练。一个人可以成为多个团队的主管/助理教练。
以下是我目前的(徒劳)尝试:
class Team < ActiveRecord::Base
has_many :members
has_many :people, :through => :members
belongs_to :head_coach :class => 'Person'
belongs_to :assistant_coach :class => 'Person'
end
class Person < ActiveRecord::Base
has_many :teams
has_many :teams, :through => :members
end
class Member < ActiveRecord::Base
belongs_to :team
belongs_to :person
# has a "position" which is a string
end
这种方法给我带来两个问题:
团队的belongs_to:head_coach和:assistant_coach不起作用。也许它应该是一个has_one,但是我不确定将belongs_to置于Person中是否有意义(我想在Team to Person中使用FK)。下面的示例显示我如何设置它与ActiveRecord不一致:
irb(main):006:0> t = Team.find(1)
=> #<Team id: 1, name: "Champs", created_at: "2011-07-18 01:50:56", updated_at: "2011-07-19 01:47:26", head_coach: nil>
irb(main):007:0> t.head_coach
=> nil
irb(main):008:0> t.head_coach = Person.find(1)
=> #<Person id: 1, name: "Chris", created_at: "2011-07-18 01:52:34", updated_at: "2011-07-18 01:52:34">
irb(main):009:0> t.save
=> true
irb(main):010:0> t.head_coach
=> #<Person id: 1, name: "Chris", created_at: "2011-07-18 01:52:34", updated_at: "2011-07-18 01:52:34">
irb(main):011:0> Team.find(1).head_coach
=> nil
has_many:through似乎有效,但我没有找到一个很好的方法来列出团队中每个人的位置。这是我目前在视图中的尝试:
<% @team.people.each do |person| %>
<%= person.name +" "+ @team.members.find_by_person_id(person).position %>
是否有更好的方法来表示这些关系?
感谢您的帮助!
-Chris
答案 0 :(得分:0)
你的成员表中是否有head_coach和assistant_coach的布尔字段,并使用带范围的验证唯一规则。
EG 添加到成员表
is_head_coach:boolean
is_assistant_coach:boolean
现在你的会员模型中有
validates_uniqueness_of :is_head_coach, :scope => [:team_id, :person_id]
validates_uniqueness_of :is_assistant_coach, :scope => [:team_id, :person_id]
然后,您可以在个人模型或团队模型中使用一些命名范围来查找head_coach。
至于列出所有职位,你不能使用:
@team.members.each do |member|
"#{member.person.name} #{member.position}"
如果你想以特定的方式对它们进行排序,你可以在member表中添加一个名为sort_order:integer的字段并按其排序。
更新
我认为上述解决方案不具备可扩展性。如果您在成员模型中使用位置字段并为其创建一个名为“命名范围”的范围,如下所示:
scope :head_coach, lambda { where('position = 'head coach') }
然后你可以使用类似的东西:
team.members.head_coach
你可以进一步了解这个范围
scope :get_position, lambda{|pos| where('position = ?', pos)}
并使用
team.members.get_position('head_coach')
您可以编写一个自定义验证方法来检查您是否最终在每个团队的head_coach上等等。
答案 1 :(得分:0)
我最终使用显式的foreign_key进行以下方法,该方法正常工作。
class Team < ActiveRecord::Base
has_many :members
has_many :people, :through => :members
belongs_to :head_coach, :class => 'Person', :foreign_key head_coach_id
belongs_to :assistant_coach, :class => 'Person', :foreign_key assistant_coach_id
end
class Person < ActiveRecord::Base
has_many :teams, :through => :members
end
class Member < ActiveRecord::Base
belongs_to :team
belongs_to :person
# has a "position" which is a string
end
迄今为止唯一的缺点是我无法在控制器中自动加载外键。我需要添加以下代码以保存关联:
# POST /teams
def create
@team = Team.new
@team.head_coach = Person.find(params[:head_coach])
@team.assistant_coach = Person.find(params[:assistant_coach])
....