在Rails中,我可以通过委托方法订购查询吗?

我很难通过委托方法订购查询。 我的任务是帮助将一个相当大的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 ,所以我认为我的控制器不需要知道它被委派给哪里。

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

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

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

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

说明

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

此行直接映射到SQL查询。

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

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