So I have a bunch of users, who all have user.dj_name attributes. It's a validated necessity on the model, but I'm still being cautious here because I'm running into problems.
I want to get a bunch of users, then order them by their dj_name. Something like this:
@djs = Event.all.map { |e| e.program.user }.sort_by {|x,y| x.dj_name <=> y.dj_name }
where it's pulling all DJs who have Events (shows). It fails with "NoMethodError: undefined method `dj_name' for nil:NilClass"
So I tried:
@djs = Event.all.map { |e| e.program.user }
@djs.compact.sort_by! {|x,y| x.dj_name <=> y.dj_name rescue nil}
And it doesn't sort. Without the "rescue nil" clause, I get the same error.
And if I do a reject! if the object is nil I get nothing.
> @djs.reject! {|d| d.nil? }
=> nil
It seems like none of the objects in the array are nil, the sorting mechanism is giving me errors, and rescuing it just stops the sorting process and returns an unchanged array.
halp?
Use the database sort for this kind of task. You can resume your queries by using:
Event.all(:include => {:program => :user}, :order => 'users.dj_name')
Decoupling this query would result in the include
method making the join associations on your models and the order
creating an ORDER BY
on your query.
Use sort!
, not sort_by!
.
sort_by!
passes a single argument into its block. So, when you call .sort_by! {|x,y| ... }
, y
is always nil
.
The purpose of sort_by!
is to sort by keys instead of elements. The block gets a single element and must return the element's key to use for sorting.
In this code:
@djs.compact.sort_by! {|x,y| x.dj_name <=> y.dj_name rescue nil}
the block returns nil
as a key for every element. As result, no sorting happens.
BTW, I agree with @MurifoX that in this particular case you should you database-provided sorting.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With