Rails has_many:通过连接模型中的额外属性查找

Ruby和Rails都是新手,但现在我已经受过教育(这显然意味着什么,哈哈)。

我有两个模型,事件和用户通过表EventUserjoin

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 

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

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

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

之后,您应该能够通过调用以下方式获取用户的活动事件:

 User.first.active_events 

米兰Novota有一个很好的解决scheme – 但是:conditions现在不推荐使用,而且:conditions => ['event_users.active = ?',true]位似乎不是很好的select。 我更喜欢这样的事情:

 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 

即使你的u.events没有显式地调用user_events表,但由于必要的连接,该表仍然隐含在SQL中。 所以,你仍然可以在你的查找条件中使用该表:

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

当然,如果你打算做这个查询很多,那么可以肯定的是,按照米兰诺瓦塔(Milan Novota)的build议,给它一个单独的关联,但是没有必要这样做

那么,在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 ,作为活动事件或不活动事件的function属于EventUser模型,如果将来需要修改function,则只能在一个位置进行修改: EventUser模型,其更改将为反映在所有其他模式。

Interesting Posts