Rails ActiveRecord is continuously being improved. The latest improvement is the “in_order_of” method. This method is used to order records in the order of the given values (of a particular column). This query previously only used to allow symbolic column names, it now handles string values also.
Before
Let’s create a Rocket model which has id and name attributes. Now, when trying to order the records in the order of the given values, we can use the “in_order_of” method as shown below.
irb(main):012:0> Rocket.in_order_of(:id, [1,2,3]).count
Rocket Count (1.1ms) SELECT COUNT(*) FROM "rockets" WHERE "rockets"."id" IN (1, 2, 3)
=> 3
However if we try to use the “in_order_of” method with string values, it throws an error.
irb(main):001:0> Rocket.in_order_of('id', [1,2,3]).count
/Users/swaathi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4/lib/active_record/relation/query_methods.rb:459:in `in_order_of': undefined method `in' for "id":String (NoMethodError)
.where!(arel_column.in(values))
^^^
Did you mean? in?
As you can see, the error is thrown because the “in_order_of” method is trying to call the “in” method on the string value “id”.
After
Thanks to this PR the ActiveRecord queries no longer check if a given column is symbol and then perform a query, but instead check for Arel types. This allows for greater flexibility.
What used to be,
activerecord/lib/active_record/relation/query_methods.rb
...
arel_column = column.is_a?(Symbol) ? order_column(column.to_s) : column
...
is now,
...
arel_column = column.is_a?(Arel::Nodes::SqlLiteral) ? column : order_column(column.to_s)
...
Now when we try to use the “in_order_of” method with string values, it works as expected.
irb(main):001:0> Rocket.in_order_of('id', [1,2,3]).count
(0.2ms) SELECT COUNT(*) FROM "rockets" WHERE "rockets"."id" IN (1, 2, 3)
=> 3