为了回答您的第一个问题,您的 Input 表的所有行都用于连接 Translations 表,因此所有连接的行都将按 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 用作输入不存在的翻译的占位符,因此您可以将其用作视图中的指示以插入“翻译...”选项。可以这样使用:
<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 数组;您可以根据需要对其进行调整以适应您的视图结构。