如何使用has_many:通过关联为所有者和成员建模?

时间:2013-05-19 05:51:34

标签: ruby-on-rails ruby associations has-many-through

在我的rails应用程序中,我有事件和用户模型。业务规则规定事件有一个所有者和许多成员,并且所有者必须是成员。相反的是用户有许多“拥有的事件”和“事件”(事件他/她是所有者的成员但不是所有者)。我本来打算像这样建模这个协会:

class Event < ActiveRecord::Base
  has_many :event_members, dependent: :destroy

  has_one :owner, through: :event_members, source: :user, conditions: { owner: true }
  has_many :members, through: :event_members, source: :user
end

class EventMember < ActiveRecord::Base
  belongs_to :event
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :owned_events, through: :event_members, conditions: { owner: true }
  has_many :events, through: :event_members
end

我认为这样可以确保一位所有者和所有者免费加入成员协会。但是,这不起作用,因为我无法通过集合指定has_one - :event_members关联。

有更好的方法对此进行建模吗?我可以在通过所有者标志查询EventMember的事件上添加一个瞬态“所有者”attr - 但这是否可以用于设置所有者(即我可以获取创建的EventMember记录并确保设置所有者标志)?

1 个答案:

答案 0 :(得分:4)

如何在连接模型owner上添加EventMember属性(在event_members表中也是类型为boolean的字段,默认值为false)。使用每个相应模型上的方法访问ownerowned_events

class Event < ActiveRecord::Base             
  has_many :event_members
  has_many :members, :through => :event_members, :source => :user

  def owner                                  
    event_members.ownerships.map(&:user).first                                                              
  end                                        
end                                          

class EventMember < ActiveRecord::Base       
  belongs_to :event                          
  belogns_to :user

  scope :ownerships, -> { where(:owner => true) }                          
end                                          

class User < ActiveRecord::Base              
  has_many :event_members                    
  has_many :events, :through => :event_members

  def owned_events                           
    event_members.ownerships.map(&:event)      
  end                                        
end

Event对象可能有责任使用户成为其所有者。

class Event
  def make_owner!(user)
    membership = event_members.where(:user_id = user).first
    membership.owner = true
    membership.save
  end
end

也许在那里放置逻辑来强制只有一个所有者和make_owner!EventMember的抽象部分,具体取决于它在您的应用程序中的混乱程度。