Rails has_many:通过Join模型中的Extra Attributes查找

时间:2009-01-03 10:39:47

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

Ruby和Rails都是新手,但我现在已经接受过教育了(显然没什么意义,哈哈)。

我有两个模型,Event和User通过表EventUser加入

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

class EventUser < ActiveRecord::Base
  belongs_to :event
  belongs_to :user

  #For clarity's sake, EventUser also has a boolean column "active", among others
end

class Event < ActiveRecord::Base
  has_many :event_users
  has_many :users, :through => :event_users
end

这个项目是一个日历,我必须跟踪人们注册并为特定事件划掉他们的名字。我认为多对多是一种很好的方法,但我做不到这样的事情:

u = User.find :first
active_events = u.events.find_by_active(true)

因为事件实际上没有那些额外的数据,所以EventUser模型可以。虽然我能做到:

u = User.find :first
active_events = []
u.event_users.find_by_active(true).do |eu|
  active_events << eu.event
end

这似乎与“轨道方式”相反。任何人都可以启发我,今晚(今天上午)这已经困扰了我很长时间?

4 个答案:

答案 0 :(得分:123)

如何将这样的内容添加到用户模型中?

has_many  :active_events, :through => :event_users, 
          :class_name => "Event", 
          :source => :event, 
          :conditions => ['event_users.active = ?',true]

之后,您应该只需致电:

即可为用户获取活动事件
User.first.active_events

答案 1 :(得分:22)

Milan Novota有一个很好的解决方案 - 但:conditions现已被弃用,而:conditions => ['event_users.active = ?',true]位似乎并不是很好。我更喜欢这样的东西:

has_many :event_users
has_many :active_event_users, -> { where active: true }, class_name: 'EventUser'
has_many :active_events, :through => :active_event_users, class_name: 'Event', :source => :event

之后,您仍然可以通过调用以下方式为用户获取活动事件:

User.first.active_events

答案 2 :(得分:12)

即使您的u.events不是显式调用user_events表,由于必要的连接,该表仍然包含在SQL 隐式中。因此,您仍然可以在查找条件中使用该表:

u.events.find(:all, :conditions => ["user_events.active = ?", true])

当然,如果你计划进行大量的查询,那么肯定会给它一个单独的关联,正如Milan Novota建议的那样,但是没有要求让你这样做

答案 3 :(得分:7)

嗯,User模型中的责任比实际需要的更多,并没有充分的理由这样做。

我们可以先在EventUser模型中定义范围,因为它实际上属于它,例如:

class EventUser < ActiveRecord::Base
  belongs_to :event
  belongs_to :user

  scope :active,   -> { where(active: true)  }
  scope :inactive, -> { where(active: false) } 
end

现在,用户可以同时拥有两种事件:活动事件和非活动事件,因此我们可以在User模型中定义关系,如下所示:

class User < ActiveRecord::Base
  has_many :active_event_users,   -> { active },   class_name: "EventUser"
  has_many :inactive_event_users, -> { inactive }, class_name: "EventUser"

  has_many :inactive_events, through: :inactive_event_user,
                             class_name: "Event",
                             source: :event
  has_many :active_events,   through: :active_event_users,
                             class_name: "Event",
                             source: :event
end

这种技术的优点在于,作为活动或非活动事件的功能属于EventUser模型,如果将来需要修改功能,则只能在一个地方修改它:{ {1}}模型,更改将反映在所有其他模型中。