问题
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