我基本上没有使用 Rails 的经验,我正在尝试帮助一个正在学习如何编程的朋友,但是我在 SQL 方面有很多经验,我正在努力让 Rails 为一个简单的事情做正确的事情使用连接查询。
我有两张桌子,drawings
和drawing_types
。 drawings
有一个指向 的外键drawing_types
,它有一type_description
列。这显然是你能想象到的最简单的关系。在 SQL 中,我会这样做以获取所有正确的图纸type_descriptions
:
SELECT d.*, dt.type_description FROM drawings as d
INNER JOIN drawing_types as dt ON dt.id = d.drawing_type_id;
这是一个高效的 SQL 查询,它返回的正是我想要的:一个包含文本类型描述的图纸列表。
在我的一生中,我无法让 Rails 生成和使用这样的单个查询。我能做的最好的就是让它做两个查询,这清楚地表明它在代码中做“加入”,而不是让数据库去做。有时它喜欢做 N+1 个查询!?!
这是模型的代码:
class Drawing < ActiveRecord::Base
attr_accessible :image, :drawing_type_id
belongs_to :drawing_type
end
class DrawingType < ActiveRecord::Base
attr_accessible :type_description
has_many :drawings
end
这是相关的控制器代码:
@drawings = Drawing.includes(:drawing_type)
这是视图:
<% @drawings.each do |drawing| %>
<tr>
<td><b><%= drawing.drawing_type.type_description %></b></td>
这会生成两个 SQL 查询,一个 on drawings.*
,另一个用于获取所有描述,然后在代码中清楚地查找这些描述。如果我将其更改includes
为 ajoins
它会执行 1+M+N 个 SQL 查询(M = 绘图类型数,N = 绘图数)!?!?!?!
我可以通过使用它(从这里)向日志发出正确的 SQL 连接:
@drawings = Drawing.select("drawings.*, drawing_types.type_description").
joins("INNER JOIN drawing_types ON drawing_types.id = drawings.drawing_type_id")
但是,rails 似乎只将结果用作绘图数组,而忽略了type_description
结果中的列,因此它执行了额外的 M+N 个查询!
所有这些变体都“起作用”,因为页面为所有这些变体都正确呈现,但相对于应该执行的单个正确 SQL 连接,它们都是做这个简单事情的错误方式。
只需要一种简单的方法来正确地做到这一点,因为它是您可能在一个完全无聊的网站架构中找到的最基本的关系,但我已经搜索了高低,包括在这里阅读很多答案和所有文档,并且有无法弄清楚如何做到这一点。
谢谢,克里斯