Reputation: 43
Ruby on Rails Next/Previous Post
I have an index page - posts#index which has links to the show pages of each post. Each post references a particular topic and may have been created at different times, so the id's of the posts aren't necessarily sequential for all the posts in that topic. I want to be able to go to the next & previous posts for a particular topic.
In my PostsController I've got instance variables for all the posts for a topic and the particular topic being shown
def index
@topic = Topic.find(params[:topic_id])
@posts = @topic.posts.all
end
def show
@topic = Topic.find(params[:topic_id])
@posts = @topic.posts.all
@post = @topic.posts.find(params[:id])
end
@posts is an array of active record objects
@posts => #<ActiveRecord::AssociationRelation [
#<Post id: 73, topic_id: 3>,
#<Post id: 74, topic_id: 3>,
#<Post id: 76, topic_id: 3>,
#<Post id: 77, topic_id: 3>,
#<Post id: 91, topic_id: 3>]
If this was an array of ruby objects I could use @posts.index(@post)
to find the id of a particular element of the array and then do either index + 1
or index - 1
to traverse the array of posts, but .index
is a different method in active record. If I'm on the show page for any given post in a particular topic, Post id: 76
for example, how can I go to link_to Post id: 74
(next) and link_to Post id: 77
(previous) in a way that work for any post in a particular topic?
Upvotes: 3
Views: 1019
Reputation: 3700
There are a few gems to help. I have created one which is quit flexible because it works dynamically with any collection and its order (which is not the case when it's hardcoded like : Book.where("id > ?", 74).order(:id)
)
The gem is called nexter and it's basic usage is like this :
@books = Book.includes(:author).bestsellers.
order("genre", "authors.name", "published_at desc")
nexter = Nexter.wrap( @books, @books.find(params[:id]) )
nexter.previous
nexter.next
See the README for more info.
Upvotes: 0
Reputation: 6132
Try something like this:
Post.where("id > ?", 74).order(:id).first
Or, if you have some topics (not sure about your model), but it will look similar to this:
some_topic.posts.where("id > ?", 74).order(:id).first
Here the 74
is an ID of the current post.
Upvotes: 0
Reputation: 54882
You can simply do the following:
def show
@topic = Topic.find(params[:topic_id])
posts = @topic.posts.order('posts.id ASC')
@post = posts.find(params[:id])
@previous_post = posts.where('posts.id < ?', @post.id).first
@next_post = posts.where('posts.id > ?', @post.id).first
end
Upvotes: 1