哪个关联在该代码行中排序?

时间:2016-05-18 18:36:44

标签: ruby-on-rails ruby postgresql sorting associations

如果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种语言)按第一种语言的翻译值(任意设置)排序。

enter image description here

2 个答案:

答案 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数组;您可以根据需要调整它以适应您的视图结构。