Rails has_many :通过连接模型中的额外属性查找
Posted
技术标签:
【中文标题】Rails has_many :通过连接模型中的额外属性查找【英文标题】:Rails has_many :through Find by Extra Attributes in Join Model 【发布时间】:2010-09-29 08:40:55 【问题描述】: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
这似乎与“铁轨方式”相反。谁能启发我,今晚(今天早上)这一直困扰着我很长时间?
【问题讨论】:
您也可以使用 Gareth 的建议创建一个命名范围。 【参考方案1】:嗯,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
模型,如果将来需要修改功能,只需在一个地方修改:EventUser
模型,并且更改将反映在所有其他模型中。
【讨论】:
你的解决方案让我很开心 :)【参考方案2】: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
【讨论】:
如果您还没有使用 Rails 4,您仍然可以遵循这个出色的示例,但您可能需要使用已弃用的:conditions => active: true
。为我工作,谢谢!【参考方案3】:
在你的用户模型中添加这样的东西怎么样?
has_many :active_events, :through => :event_users,
:class_name => "Event",
:source => :event,
:conditions => ['event_users.active = ?',true]
之后,您应该能够通过调用来获取用户的活动事件:
User.first.active_events
【讨论】:
我已经标记了你,但如果我早上没有得到更好的答案,那就是你的了。 查看下面我的答案以获取更新的方法 谢谢,Rails 4 方式是:-> where event_users: active: true
但是条件不可能由event_users
范围定义?喜欢scope :active, where(:active => true)
? (使用 Rails 3.2)
@IvanBlack 你能解释一下has_many through:
的位置吗?你能包括整个 Rails 4 特定的等价物吗?【参考方案4】:
即使您的 u.events 没有显式调用 user_events 表,由于必要的连接,该表仍然隐式包含在 SQL 中。因此,您仍然可以在查找条件中使用该表:
u.events.find(:all, :conditions => ["user_events.active = ?", true])
当然,如果您打算经常进行此查找,那么可以确定,按照 Milan Novota 的建议给它一个单独的关联,但您没有要求这样做
【讨论】:
我喜欢在一个地方定义所有范围 - 在模型中,即使我只使用它们一次。它使我的控制器保持纤薄,整体设计更加一致。以上是关于Rails has_many :通过连接模型中的额外属性查找的主要内容,如果未能解决你的问题,请参考以下文章
如何在has_many中获取模型的属性:通过Rails 5中的关联
Rails has_many 通过表单在连接模型中带有复选框和额外字段
使用带有 Rails 的改革 gem,我如何填充 has_many :通过嵌套模型
通过Rails中的关联使用has_many创建新模型时出现不允许的参数错误