Tyler Crosse
Tyler Crosse

Reputation: 43

Next element in array of active record objects

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

Answers (3)

charlysisto
charlysisto

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

Dmitry Sokurenko
Dmitry Sokurenko

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

MrYoshiji
MrYoshiji

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

Related Questions