【问题标题】:In Rails, can I order a query by a delegate method?在 Rails 中,我可以通过委托方法订购查询吗?
【发布时间】:2015-01-28 21:23:52
【问题描述】:

我很难通过委托方法对查询进行排序。我的任务是帮助将一个相当大的 Rails 3 应用程序升级到 Rails 4。我在索引操作中遇到了这个查询。 我知道这些对象的命名是可怕和混乱的。

# measurements_controller.rb
def index
  @measurements = Measurement.includes(:identifier).order(:name)
end

在 Rails 4 中,我收到此错误:

ERROR: column info_items.name does not exist LINE 1: ...D (info_item_identifiers.name LIKE '%') ORDER BY "info_item...

于是我看了一下模型,发现:

# measurement.rb
class Measurement < InfoItem
  ...
end

# info_item.rb
belongs_to :identifier, class_name: 'InfoItemIdentifier'
delegate :name, :name=, to: :identifier

# info_item_identifier.rb
# This object has a name column in the database

如果我在终端中并且我有一个Measurement 的实例,我可以轻松地调用.name 方法并且效果很好。但是当涉及到.order(:name) 时,由于该列不存在,这不起作用。

我找到了一种解决方案,但它似乎违背了委托方法的目的。在控制器中,我可以将其更改为:

@measurements = Measurement.includes(:identifier).order('info_item_identifiers.name')

由于我知道InfoItemname 方法委托给InfoItemIdentifiers,我认为我的控制器不需要知道它被委托给了哪里。

有没有办法保留现有代码并仍然通过委托方法排序?

【问题讨论】:

  • 是否将包含更改为 eager_load 帮助(或添加 .references(:identifier) )
  • 好提示,我确实阅读了 Rails 4 和 .references。唉,我尝试了你的两个建议都没有运气。明天早上我回到工作岗位时,我会尝试任何其他建议。谢谢!

标签: ruby-on-rails ruby ruby-on-rails-4 delegates rails-activerecord


【解决方案1】:

是的,但它需要先实例化所有记录(这会降低性能)。

@measurements = Measurement.joins(:identifier).sort_by &:name

此代码加载所有测量值并实例化它们,然后通过 Ruby 方法 .name 对它们进行排序

说明

delegate 仅影响 ActiveRecord 模型的实例。它不会影响您的 SQL 查询。

此行直接映射到 SQL 查询。

Measurement.includes(:identifier).order(:name)

正如您所注意到的,它在测量表中查找 name 列,但没有找到任何内容。您的 ActiveRecord 模型实例知道 name 仅存在于 identifier 上,但您的 SQL 数据库不知道这一点,因此您必须明确告诉它在哪个表上找到该列。

【讨论】:

  • 感谢您的出色解释。我知道在 Rails 4 中对includes 进行了一些更改。你知道这是否对此产生了影响吗?我没有在这个项目的 Rails 3 版本上工作,但是那个代码在那里(.order(:name))并且他们声称我们所有的测试都通过了(包括正确访问那个实例变量)。
  • 这里有一个选项。当您使用带有符号的.order(如:name)时,Rails 将尝试为您添加表名(ORDER BY info_items.name)。但是,使用字符串,它会将该字符串直接添加到您的查询中。在这种特定情况下,您可以使用joins(:identifier).order('name'),其结果为ORDER BY name。由于name 列在info_items 上不存在,但在info_item_identifiers 上存在,因此它将正常工作。您确实需要使用连接而不是包含。请注意,如果您使用 name 列连接(或包含)任何其他表,您将收到一个不明确的列 SQL 错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多