在 Rails 中,我可以通过委托方法订购查询吗?
In Rails, can I order a query by a delegate method?
我很难通过委托方法对查询进行排序。我的任务是帮助将一个相当大的 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')
因为我知道 InfoItem
将 name
方法委托给 InfoItemIdentifiers
,我认为我的控制器不需要知道它被委托到哪里。
有没有办法保留现有代码并仍然通过委托方法排序?
是的,但它需要先实例化所有记录(这会降低性能)。
@measurements = Measurement.joins(:identifier).sort_by &:name
此代码加载所有测量并实例化它们,然后通过 Ruby 方法对它们进行排序 .name
说明
delegate
只影响 ActiveRecord 模型的实例。它不会影响您的 SQL 查询。
此行直接映射到 SQL 查询。
Measurement.includes(:identifier).order(:name)
如您所见,它在测量值 table 上查找 name
列,但没有找到任何内容。您的 ActiveRecord 模型实例知道 name
仅存在于 identifier
,但您的 SQL 数据库不知道,因此您必须明确告诉它要查找的 table专栏。
我很难通过委托方法对查询进行排序。我的任务是帮助将一个相当大的 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')
因为我知道 InfoItem
将 name
方法委托给 InfoItemIdentifiers
,我认为我的控制器不需要知道它被委托到哪里。
有没有办法保留现有代码并仍然通过委托方法排序?
是的,但它需要先实例化所有记录(这会降低性能)。
@measurements = Measurement.joins(:identifier).sort_by &:name
此代码加载所有测量并实例化它们,然后通过 Ruby 方法对它们进行排序 .name
说明
delegate
只影响 ActiveRecord 模型的实例。它不会影响您的 SQL 查询。
此行直接映射到 SQL 查询。
Measurement.includes(:identifier).order(:name)
如您所见,它在测量值 table 上查找 name
列,但没有找到任何内容。您的 ActiveRecord 模型实例知道 name
仅存在于 identifier
,但您的 SQL 数据库不知道,因此您必须明确告诉它要查找的 table专栏。