如何将给定模型的所有记录的所有相关数据融合在一起?
我有以下型号:
User --N:1--> Reservation <--1:N-- Concert
所以伪代码:
Reservation belongs_to User
Reservation belongs_to Concert
User has_many Reservations
User has_many Concerts through Reservations
Concert has_many Reservations
Concert has_many Users through Reservations
我如何制作一个单一的大数组?
- 我可以通过
Reservation.all
获得所有预订 - 我可以通过
Reservation.find(25).user
获取特定预订的用户 - 我可以通过
Reservation.find(25).concert
获得特定预订的音乐会
但是我如何为他们所有人获得它?如果我做
Reservation.all.each do |res|
res.user.name+","+res.concert.name+","+res.concert.date # etc.
end
然后,当它循环通过时,它将为每个预订执行两个新的数据库查询。对于10张唱片来说,这可能无关紧要,但对于成千上万的唱片来说,它可能非常痛苦。添加其他关联(例如音乐会归属地、用户有一封电子邮件等)…
有没有办法说"获取所有预订和以下附加信息",这样它就可以加载到一个SQL查询中?
您试图完成的任务称为热切加载,可以在ActiveRecord
中使用includes
来完成。见下文:
N+1查询问题
"活动记录"允许您提前指定要加载的所有关联。这可以通过指定Model.find调用的includes方法来实现。使用includes,Active Record可确保使用尽可能少的查询数量加载所有指定的关联。
http://guides.rubyonrails.org/active_record_querying.html#eager-加载关联
在您的示例中,您可以使用以下内容:
Reservation.all.includes(:user, :concert)
为:belongs_to
关系指定:inverse_of
选项也是一个好主意。这优化了对象加载,并确保交叉引用模型将指向内存中的同一对象,即:
@user == @user.reservations.first.user # true
此处提供更多信息:
如果您在联接模型上使用belongs_to,最好在belong_to上设置:inverse_of选项。。。
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
在您的示例中:
# app/models/reservation.rb
belongs_to :user, :inverse_of => :reservations
belongs_to :concert, :inverse_of => :reservations