My app has Photos that belong to Users.
In a photo#show view I\'d like to show \"More from this user\", and show a next and previous photo from that user. I would be
Modify your app/models/application_record.rb to the following code:
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
def next
self.class.where("id > ?", id).order("id ASC").first || self.class.first
end
def previous
self.class.where("id < ?", id).order("id DESC").first || self.class.last
end
end
Then you can use next() and previous() in all your models.
You might want to check Nexter. It works on any dynamically created scope instead of relying on one hardcoded in your model.
This should work, and I think it's more efficient than the other solutions in that it doesn't retrieve every record above or below the current one just to get to the next or previous one:
def next
# remember default order is ascending, so I left it out here
Photo.offset(self.id).limit(1).first
end
def prev
# I set limit to 2 because if you specify descending order with an
# offset/limit query, the result includes the offset record as the first
Photo.offset(self.id).limit(2).order(id: :desc).last
end
This is my first answer ever posted on StackOverflow, and this question is pretty old...I hope somebody sees it :)
class Photo < ActiveRecord::Base
belongs_to :user
default_scope { order('published_at DESC, id DESC') }
def next
current = nil
user.photos.where('published_at >= ?', published_at).each do |p|
if p.id == id then break else current = p end
end
return current
end
def previous
current = nil
user.photos.where('published_at <= ?', published_at).reverse.each do |p|
if p.id == id then break else current = p end
end
return current
end
end
I found that the answers already here did not serve my case. Imagine that you want a previous or next based on the date published, but some photos are published on the same date. This version will loop through the photos in the order they are rendered on the page, and take the ones before and after the current one in the collection.
Try this:
class User
has_many :photos
end
class Photo
belongs_to :user
def next
user.photos.where("id > ?", id).first
end
def prev
user.photos.where("id < ?", id).last
end
end
Now you can:
photo.next
photo.prev
You can pass some options into the where method:
For the next photo:
Photo.where(:user_id => current_user.id, :created_at > current_photo.created_at).order("created_at").first
Previous photo
Photo.where(:user_id => current_user.id, :created_at < current_photo.created_at).order("created_at").last
I may have the first/last mixed up.