我很难通过委托方法订购查询。我的任务是帮助将相当大的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
,我不认为我的控制器需要知道它被委派的位置。
有没有办法保留现有代码并仍按委托方法排序?
答案 0 :(得分:3)
是的,但它需要首先实例化所有记录(这会降低性能)。
@measurements = Measurement.joins(:identifier).sort_by &:name
此代码加载所有测量并实例化它们,然后通过Ruby方法.name
<强>解释强>
delegate
仅影响ActiveRecord模型的实例。它不会影响您的SQL查询。
此行直接映射到SQL查询。
Measurement.includes(:identifier).order(:name)
正如您所注意到的,它会在测量表上查找name
列并且找不到任何内容。您的ActiveRecord模型实例知道name
仅存在于identifier
,但您的SQL数据库并不知道,因此您必须明确告知它在哪个表中找到该列。