如果Input
模型has_many :translations
,哪个翻译行已排序?
Input.includes(:translations).order("translations.value DESC")
模型
class Input < ActiveRecord::Base
has_many :translations, dependent: :destroy
end
class Translation < ActiveRecord::Base
belongs_to :input
belongs_to :language
end
# translations table schema:
# id :integer
# value :string
# input_id :integer
# language_id :integer
我需要列出所有输入,其中8列(对于与翻译相关的8种语言)按第一种语言的翻译值(任意设置)排序。
答案 0 :(得分:2)
value
表的translations
列。它将生成一个如下所示的SQL:
SELECT "inputs"."id" AS t0_r0, "inputs"."name" AS t0_r1, ...,
"translations"."id" AS t1_r0, "translations"."value" AS t1_r1, ...
FROM "inputs"
LEFT OUTER JOIN "translations"
ON "translations"."input_id" = "inputs"."id"
ORDER BY translations.value DESC // <== YOUR `.order()` method
如您所见,订购是在DB中完成的,而不是Rails。因此,订购将是您的数据库订购。
答案 1 :(得分:1)
要回答第一个问题,Input表的所有行都用于加入Translations表,因此所有连接的行将按翻译表中的value
进行排序。
由于您没有在输入表的查询中提供任何where
条件,因此使用输入表中的所有行,这听起来像是您的意图。
您在查询中使用includes
时几乎肯定是joins
。虽然在许多情况下它们在语法上是可互换的,但它们在语义上用于不同的目的。
includes
专门用于促进eager loading,而joins
定义为支持joining tables。经验法则是,如果要在查询中使用联接表中的任何列,请使用joins
,否则,您可以使用includes
来急切加载关联。
您只是想要获得的结果很难用SQL实现。但是,您可以轻松获取Input行和关联,并使用简单的Ruby集合转换来获得所需的结果,包括Translations中缺少值的占位符。
试试这个:
languages = Language.all.order("name")
inputs = Input.includes(:translations).order("id")
translations = inputs.map do |input|
{
input.id => languages.map do |language|
item = input.translations.find_index {|i| i.language_id == language.id }
item ? nil : input.translations[item]
end
}
end
这将返回一个哈希数组,input.id
作为键,并为每个提供8列的翻译表。 nil
用作输入不存在的翻译占位符,因此您可以将其用作视图中的指示,以插入&#34;翻译...&#34;选项。这是如何使用的:
<table>
<% inputs.each do |input| %>
<tr>
<% translation = translations[input.id] %>
<% translation.each do |item| %>
<% item %>
<td class="translation-available"><%= item.value %></td>
<% else %>
<td><%= link_to "Translate...", translate_input_path(input) %></td>
<% end %>
</tr>
<% end %>
显然,我嘲笑了一些结构和设计元素,以向您展示如何处理inputs
数组;您可以根据需要调整它以适应您的视图结构。