ruby on rails how to get latest records from has many relationship
Asked Answered
M

4

6

I am new to Ruby on Rails. I have a problem- how to get only latest records from has many relationship in model. My code is like this:

class User < ActiveRecord::Base 
  has_many :books
end

class Book < ActiveRecord::Base
  belongs_to :user

  scope :rating, -> { where(rating: 5) }
end

What I would like to achieve is: I'd like to get all latest (last) book for each user and than filter this books using scope rating. I can do this using for each loop (Looping through User.books and get book.last)- but this is very inefficient because I have a lot of data. Do you have any ideas how I can do this? maybe some kind of scope chaining with each other?

Malicious answered 28/3, 2015 at 19:57 Comment(3)
Could you explain this more? so we get all users, then get the last book per each user? then what does the rating have to do with it ?Juncture
my goal is to first: find last book for each user and get for example an array of this data, eg. when I have 10 users and each user have 2 books-> so I'd like to choose only one (last) book from each user (so in the end have an array of 10 books) and after it filter this array of latest books using scope rating.Malicious
yea i got that part, I've added an answer, check if it works with youJuncture
O
4

You can do this if you want to avoid writing SQL:

class Book < ActiveRecord::Base
  scope :latest, -> do
    book_ids_hash = Book.group(:user_id).maximum(:id)
    book_ids = book_ids_hash.values
    where(id: book_ids)
  end
end

Then all you have to do is:

Book.rating.latest
Omeara answered 28/3, 2015 at 20:26 Comment(0)
P
0

Try this:

User.find_each do |user|
  puts 'User top 10 books:'

  user.books.rating.order('id DESC').limit(10).each do |book|
    puts book.title 
  end
end

I'd like to get all latest (last) book for each user

In the example above, note the .order('id DESC').limit(10). This will sort books by ID in descending order.

Pyxie answered 28/3, 2015 at 20:2 Comment(1)
ok, but my goal is to first: find last book for each user and get for example an array of this data, eg. when I have 10 users and each user have 2 books-> so I'd like to choose only one (last) book from each user (so in the end have an array of 10 books) and after it filter this array of books using scope. I tried to do this in loop- so looping thruogh each user and get last book and push this book to an array- but this was very inefficient- my site was loading a minute or more so Iam lookinf for another solution. thanks anyway!Malicious
J
0

One book for each user, then limit the result to only those who have rating 5, one query no loops or any thing.

Book.order(created_at: :desc).group(:user_id).rating
Juncture answered 28/3, 2015 at 20:40 Comment(0)
C
-1

Just use last method and pass the number of records you want to the parameter :

user.books.last(5).rating

this will give you the 5 last books and apply the rating to it.

see http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-last

Cormac answered 28/3, 2015 at 20:11 Comment(1)
I will try this, thanks, can I do it also in that way: User.all.books.last(1).rating ?Malicious

© 2022 - 2024 — McMap. All rights reserved.