Reputation: 1591
I have a user
model, a movie
model and this association in user.rb (I use has_many :through because there are other associations between these two models):
has_many :has_seens
has_many :movies_seen, :through => :has_seens, :source => :movie
I'm trying to get an array of the ten most recent has_seens
associations created.
For now, the only solution I found is to crawl through all the users, creating an array with every user.has_seens found, then sort the array by has_seen.created_at and only keep the last 10 items… Seems like a heavy operation.
Is there a better way?
Kevin
Upvotes: 2
Views: 551
Reputation: 115292
You should be able to accomplish this by adding an :order
clause to the has_many :has_seens
association to order them by the creation date. Then use an association extension to define a method on the association itself:
class User < ActiveRecord::Base
has_many :has_seens, :order => 'created_at DESC' do
def recent(count=10)
all(:limit => count)
end
end
end
Now you can use user.has_seens.recent
to get the most recent ten movies seen. Optionally, pass in a different count e.g. user.has_seens.recent(25)
.
Incidentally, I think that viewings
is a less awkward association name than has_seens
!
Edit: Personally, I would arrange things with a Viewing
join model, like this:
class User < ActiveRecord::Base
has_many :viewings
has_many :movies, :through => :viewings
end
class Viewing < ActiveRecord::Base
belongs_to :user
belongs_to :movie
default_scope :order => 'created_at DESC'
# Recent n viewings for any user
named_scope :recent, lambda { |count| { :limit => count }}
end
class Movie < ActiveRecord::Base
has_many :viewings
has_many :users, :through => :viewings
end
I've used a default scope on the Viewing
model, but you could specify the ordering on the associations if viewings should be ordered by some other attribute other than creation date by default.
Now you can do:
# 10 most recent viewings for everyone
recent = Viewing.recent(10)
Upvotes: 1
Reputation: 9138
You can do that using find:
HasSeen.find(:order => 'created_at DESC', :limit => 10)
You can use a named_scope (inside HasSeen model) like this:
named_scope :recent, :order => 'created_at DESC', :limit => 10
and call HasSeen.recent
.
If you are looking for the users, an easy (but not most efficient, I just don't know exactly how to do the join) way to do it is recent_users = HasSeen.recent.map { |h| h.user }
If the latter is what you are looking for, post a comment and I'll clean it up into a named_scope for the users model.
Upvotes: 0