我有3个模特
User.left_outer_joins(:debits, :credits).where("users.id = ?", @user.id)
正如预期的那样,用户返回所有字段的次数与信用和借记中的记录一样多。
User.includes(:credits, :debits).order(created_at: :asc).where("users.id = ?", @user.id)
它运行了3个查询,我认为应该在一个查询中完成。
这个问题的第二部分是。我怎样才能将记录类型添加到查询中?
在信用记录中会有一个额外的字段来显示信用额度和相同的借方
我已经研究过ActiveRecordUnion gem,但我没看到它会如何解决这个问题
答案 0 :(得分:3)
parcel
无法在一个查询中神奇地检索您想要的所有内容;它将为每个需要命中的模型(通常)运行一个查询。相反,它消除了未来不必要的查询。请看以下示例:
(def data
[{:start "a" :end "c" :delivery true}
{:start "d" :end "f" :delivery false}
{:start "x" :end "y" :delivery true}])
(defn process-parcels
[[{:keys [start end delivery] :as parcel} & parcels]]
(if parcel
(do
(if delivery
(println "Parcel Delivered")
(println "Parcel Collected"))
(process-parcels parcels))
(println "Deliveries Completed")))
(process-parcels data)
Parcel Delivered
Parcel Collected
Parcel Delivered
Deliveries Completed
=> nil
这里总共有6个查询,一个用户检索所有用户,然后一个用于循环中的每个includes
调用。
users = User.first(5)
users.each do |user|
p user.debits.first
end
您只会在此处发出两个查询:一个用于用户,另一个用于相关的借记。这就是.debits
加速您的应用程序的方式,通过热切地加载您知道自己需要的东西。
至于你的评论,是的,将它们组合成一个表似乎是有意义的。根据您的具体情况,我建议您查看单表继承(STI)。如果你没有采用这条路线,请小心添加名为users = User.includes(:debits).first(5)
users.each do |user|
p user.debits.first
end
的列,Rails不会那样!
答案 1 :(得分:2)
首先,在第一个查询中,通过调用User类上的查询,您要求输入User类型的记录,如果您不想要用户对象,则执行额外的连接可能会很昂贵。 (可能不会)
如果您想要信用卡和借记卡记录,只需在信用卡和借记卡模型上调用查询。如果您在此之前的某处加载用户对象,请使用includes
preload
eager_load
一次性加载关联的信用和借记记录。
在rails中有两种预加载记录的方法。在第一个中,rails对每种类型的记录执行单个查询,第二个rails仅执行一个查询,并使用返回的数据加载不同类型的对象。
includes
是一个智能的预加载器,可以执行其中一种方式,具体取决于它认为哪种方式更快。</ p>
如果你想强迫rails使用一个查询,无论如何,eager_load
就是你要找的。 p>
请在文章here中阅读有关includes
,eager_load
和preload
的所有内容