Rails 3 ORDER BY FIELD and last

青春壹個敷衍的年華 提交于 2019-12-12 12:25:54

问题


Hello I have an issue with Rails 3.2 and ordering.

When wanting to order a collection by a field, when calling .last ActiveRecord behaves weirdly...

   >> User.order("FIELD(id, '1')")
   User Load (0.4ms)  SELECT `users`.* FROM `users` ORDER BY FIELD(id, '1')
   => []
   >> User.order("FIELD(id, '1')").first
   User Load (0.4ms)  SELECT `users`.* FROM `users` ORDER BY FIELD(id, '1') LIMIT 1
   => nil
   >> User.order("FIELD(id, '1')").last
   User Load (0.3ms)  SELECT `users`.* FROM `users` ORDER BY FIELD(id DESC, '1') DESC LIMIT 1
   Mysql2::Error: You have an error in your SQL syntax;

As you can see calling last on the relation add DESC twice, but it should have only put it after the whole ORDER BY FIELD, and not inside the parenthesis..

Do anyone has an idea how to do it?

Thanks!


回答1:


This is because the FIELD function is not supported by the ActiveRecord order method. Using the order method will parse out commas as field separators and append DESC to each segment when you invoke last.

As an alternative you can either avoid using FIELD(), or avoid using last and just provide forward and reverse scopes

scope :forward_order, order("FIELD(id, '1') ASC")
scope :reverse_order, order("FIELD(id, '1') DESC")

Then you can use User.reverse_order.first in place of User.order(...).last




回答2:


This is old but I run into this problem today and found a workaround that doesn't require the use of extra scopes.

Create a SQL function to wrap the call to FIELD, this way there will be no comma in the invocation to order. This is PostgreSQL but the translation is straightforward:

CREATE FUNCTION field1(value text) RETURNS text AS $$
BEGIN
  RETURN FIELD(value, 1);
END;
$$ LANGUAGE plpgsql IMMUTABLE

Calling last in ActiveRecord now works:

User.order('field1(id)').last


来源:https://stackoverflow.com/questions/12096948/rails-3-order-by-field-and-last

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