Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I link to next or previous record belonging to an object in Rails 3?

So I have have an image(tattoo) sharing site with 3 different ways of indexing images. The main page that just shows Image.all, member's images which shows @member.images.all, and member's album images. That is to say, the a Member has many images (and albums), and an Album has many images.

Now when you click on an image, regardless of where it was (index, member's profile, or member's album) you get to the show page. Im thinking I probably need a previous and next link to show the next image but I need to be able to restrict the images to their parent container.

So if Im looking at an image within an album, I would need the next and previous links to only link to images in that album. If Im looking at a member's images NOT in an album it the links would point to images the member owns, not in an album.

And if the image was in the front page, then the links would just point to ALL images.

like image 592
rugbert Avatar asked Feb 21 '23 21:02

rugbert


2 Answers

If you don't want pagination, then you'd have to do additional queries to ensure the links to the next/previous records are accurate. Example shown below...

In your image model:

class Image < ActiveRecord::Base
  belongs_to :album

  def previous
    Image.where("album_id = ? AND id < ?", self.album.id, self.id).first
  end
  def next
    Image.where("album_id = ? AND id > ?", self.album.id, self.id).first
  end
end

Then in your controller:

def show
  @current_image = Image.find(params[:id])
  @prev = @current_image.previous
  @next = @current_image.next

  respond_to do |format|
    format.html
  end
end

And finally in your view (this is HAML code):

= link_to_unless(@prev.blank?, 'Prev', image_path(@prev))
= link_to_unless(@next.blank?, 'Next', image_path(@next))

Just keep in mind that previous and next could return nil if no previous or next image is found so you should not show the prev / next links in that scenario.


If you end up using the will_paginate or Kaminari gem (highly recommended), you can generate "pretty" routes by just adding a matched route to your routes.rb file:

match '/albums/:id/page/:page' => "albums#show"

# put the matched route above the regular :albums resource
# so it matches that route first if it's given a page
resources :albums

The reason that works is because both pagination gems use Rails url_for method to generate the previous/next links and therefore Rails will match that route and generate something like http://rtattoos.com/albums/2/page/26 instead of http://rtattoos.com/albums/2?page=26

like image 178
iwasrobbed Avatar answered Feb 24 '23 09:02

iwasrobbed


This is a typical pagination type problem. Each display of records always comes with some kind of conditions (even if it is find(:all)). Take a look at will_paginate for easy creation of the view and collection objects. The only additional work is always providing the conditions back on a page change to reissue model request with the next set.

like image 32
Nick Avatar answered Feb 24 '23 10:02

Nick