In Rails, can I order a query by a delegate method?

梦想的初衷 提交于 2019-12-10 21:26:45

问题


I'm having difficulty ordering a query by a delegate method. I've been tasked with helping upgrade a fairly large Rails 3 application to Rails 4. I've come across this query in an index action. I am aware the naming of these objects is horrible and confusing.

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

In Rails 4, I'm getting this error:

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

So I took a look at the models and found:

# 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

If I'm in the terminal and I have an instance of a Measurement, I can easily call the .name method and it works great. But when it comes to .order(:name), that does not work due to the column not existing.

I have found one solution, but it seems to defeat the purpose of the delegate method. In the controller, I can change it to:

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

Since I know that InfoItem delegates the name method to InfoItemIdentifiers, I don't think my controller needs to know where it's delegated to.

Is there a way to keep the existing code and still order by the delegate method?


回答1:


Yes, but it requires instantiating all your records first (which will decrease performance).

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

This code loads all Measurements and instantiates them and then sorts them by the Ruby method .name

Explanation

delegate only affects instances of your ActiveRecord model. It does not affect your SQL queries.

This line maps directly to a SQL query.

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

As you have noticed, it looks for a name column on the measurements table and doesn't find anything. Your ActiveRecord model instances know that name only exists on identifier, but your SQL database doesn't know that, so you have to tell it explicitly on which table to find the column.



来源:https://stackoverflow.com/questions/28202660/in-rails-can-i-order-a-query-by-a-delegate-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!