Skip to content

Instantly share code, notes, and snippets.

@pawel2105
Last active August 29, 2015 13:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pawel2105/8780769 to your computer and use it in GitHub Desktop.
Save pawel2105/8780769 to your computer and use it in GitHub Desktop.
Given the following domain and scenario:
Topic has_many votes
A rails noob that has a massive dataset but little understanding into ActiveRecord query methods
and little SQL knowledge.
Using elegant and idiomatic Ruby, what is a good solution for returning all topics sorted by the
number of votes they have. Because of the SQL knowledge gap, you should avoid having to use SQL directly.
@BenJanecke
Copy link

Rails
Topic.find(:all, joins: :vote, order: 'votes.count')
Ruby
Topic.find(:all, joins: :vote).sort{ | previous, current | previous.votes.count <=> current.votes.count }

@pixeltrix
Copy link

Depends on whether you cache the association count:

# with counter_cache: true
Topic.all.sort_by{ |topic| topic.votes_count }

# with counter_cache: false
Topic.all.sort_by{ |topic| topic.votes.count }

This will return the lowest number of votes first - use reverse to get the highest first. Obviously this may not be the most performant depending on the number of topics.

@pawel2105
Copy link
Author

My approach:

Class Vote < ActiveRecord::Base
  belongs_to :topic, dependent: destroy, counter_cache: true
end

Then use:

@topics = Topic.all.sort_by(&:votes_count)

This to me is better than using:

@sorted_topics = Topic.include(:votes).sort do |a,b| 
  a.votes.size <=> b.votes.size
end

The problem is that doing either of these will return an array instead of an ActiveRecord relation.

@pawel2105
Copy link
Author

Pixeltrix

One issue I still have with this is that it's using the block to do the sorting. If you have 5 million topics and hundreds of votes each, surely you'd want the ordering to be done in the DB? I know then most people would say then you should optimize your query to use raw SQL but I feel that there is something missing that abstracts that and should belong in ActiveRecord::QueryMethods or somewhere.

@pixeltrix
Copy link

If you have 5 million topics and hundreds of votes each, surely you'd want the ordering to be done in the DB?

But if you do have 5 million rows any kind of SQL ordering sucks as well. In those circumstances I'd probably look at using a full-blown search engine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment