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

问题描述 投票:0回答:1

我在通过委托方法排序查询时遇到困难。我的任务是帮助将一个相当大的 Rails 3 应用程序升级到 Rails 4。我在索引操作中遇到了这个查询。

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

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

ERROR: column items.name does not exist LINE 1: ...D (item_names.name LIKE '%') ORDER BY "item...

所以我看了一下模型,发现:

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

# item.rb
belongs_to :item, class_name: 'ItemName'
delegate :name, :name=, to: :item

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

如果我在终端中并且有一个

Measurement
的实例,我可以轻松调用
.name
方法并且效果很好。但当涉及到
.order(:name)
时,由于该列不存在,因此不起作用。

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

@measurements = Measurement.includes(:item).order('item_names.name')

因为我知道

Item
name
方法委托给
ItemNames
,所以我认为我的控制器不需要知道它被委托到哪里。

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

ruby-on-rails ruby ruby-on-rails-4 delegates rails-activerecord
1个回答
3
投票

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

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

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

.name

解释

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

此行直接映射到 SQL 查询。

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

正如您所注意到的,它会在测量表上查找

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

© www.soinside.com 2019 - 2024. All rights reserved.