Reputation: 386
I am sorting an Array in Rails 4 using sort_by:
sort_column = 'experience_in_months'
@[email protected]_by(&:"#{sort_column}")
This throws an error
An ArgumentError occurred in SNIP:
comparison of Fixnum with nil failed
This is a strange problem because I remember reading about this earlier. It was supposed to put the nil values first or last based on the database used. I am using PostGreSQL.
I remember this working quite flawlessly a few days ago - it just put nil values at the top in my table.
It isn't a difficult problem to solve - I can take out the nil values, sort the rest and then add back the nil enteries. But I would like to be clear if this is a random behaviour or if it is as expected.
Upvotes: 0
Views: 1010
Reputation: 9485
Once the data is out of the database, Ruby has full control and ruling over ordering rules. Databases' rules no longer apply because arrays are used everywhere and no gems expect them to be broken in this way.
Taking advantage of the fact that nil.to_i
is 0
, you can use the following:
attribute_proc = sort_column.to_sym.to_proc
@userstoshow = @userstoshow.sort_by { |x| attribute_proc.call(x).to_i }
...and you're replacing the value in-place, so you can use sort_by!
, not sort_by
:
attribute_proc = sort_column.to_sym.to_proc
@userstoshow.sort_by! { |x| attribute_proc.call(x).to_i }
Looks kinda intimidating. That's because you're not using a fixed attribute name. Otherwise, it'd be:
@userstoshow.sort_by! { |x| x.experience_in_months.to_i }
Upvotes: 1
Reputation: 5479
@arunt, I am guessing that you have in @userstoshow
objects of type User
or something as such.
Now when you use Ruby's sort_by
it enumerates over the collection and tries to a <=> b
, here is an equivalent code snippet.
@userstoshow = @userstoshow.sort_by do |a, b|
a.experience_in_months <=> b.experience_in_months
end
Now Ruby doesn't know how to compare a Fixnum to a NilClass, here is a similar case
[1, 2, 3, nil].sort => ArgumentError: comparison of Fixnum with nil failed
So the problem is that your User
object is returning nil
for some of it's object rather than a Fixnum value.
So you can either change your sort_by
to include a code block or fix your User object to return a default value which is not nil.
Upvotes: 2