70

in my rails app I'm creating an array like so:

@messages.each do |message|

  @list << {
    :id => message.id,
    :title => message.title,
    :time_ago => message.replies.first.created_at
  }
end

After making this array I would like to then sort it by time_ago ASC order, is that possible?

6 Answers 6

155
 @list.sort_by{|e| e[:time_ago]}

it defaults to ASC, however if you wanted DESC you can do:

 @list.sort_by{|e| -e[:time_ago]}

Also it seems like you are trying to build the list from @messages. You can simply do:

@list = @messages.map{|m| 
  {:id => m.id, :title => m.title, :time_ago => m.replies.first.created_at }
}
Sign up to request clarification or add additional context in comments.

10 Comments

So I do this before I build @list ? or? I'm tried it after and it errors with: NoMethodError (undefined method `time_ago' for #<Hash:0x10e8ac1e0>):
You do this after you build @list. So @messages.each do |message| @list << { :id => message.id, :title => message.title, :time_ago => message.replies.first.created_at } end @list.sort_by...
For DESC, tried that got, undefined method `-@' for Wed Apr 20 20:40:35 UTC 2011:Time
@list = @list.sort_by { |e| -e[:time_ago] }
In the absolute worst case that you still wanted to do this programmatically (as in not via SQL), you can do @list.sort_by{|e| e[:time_ago]}.reverse but that really weird that it doesn't work for you.
|
16

In rails 4+

@list.sort_by(&:time_ago)

Comments

12

You could do:

@list.sort {|a, b| a[:time_ago] <=> b[:time_ago]}

1 Comment

Better yet, @list.sort_by { |m| m[:time_ago] }.
6

You can also do @list.sort_by { |message| message.time_ago }

2 Comments

Thanks but how do you define the sorting order?
You define the sorting order with the { |message| message.time_ago } part. It's called sort_by because it sorts by the criteria in the block. Here, we're saying to sort by the .time_ago member of the elements. It always sorts ascending. To sort descending, we can sort ascending by the negative of that value, as described in Mike Lewis' answer. :) If it doesn't work, it's because whatever type time_ago has doesn't define negation. :/
4

Just FYI, I don't see the point in moving the messages into a new list and then sorting them. As long as it is ActiveRecord it should be done directly when querying the database in my opinion.

It looks like you should be able to do it like this:

@messages = Message.includes(:replies).order("replies.created_at ASC")

That should be enough unless I have misunderstood the purpose.

Comments

0

Yes, you can use group_by :

http://api.rubyonrails.org/classes/Enumerable.html#method-i-group_by

2 Comments

Rails 4 breaks this link. The old documentation can be found here: api.rubyonrails.org/v3.2.19/classes/…
it's about sorting not grouping

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.