rugbert
rugbert

Reputation: 12653

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.

Upvotes: 4

Views: 1973

Answers (3)

iwasrobbed
iwasrobbed

Reputation: 46703

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

Upvotes: 5

Vasseurth
Vasseurth

Reputation: 6486

If in the show page you have @photo = Photo.find(params[:id]) You could try passing the id of the current photo to either a nextPhoto or a previousPhoto method. The nextPhoto method would then have @photo = Photo.find(id + 1) and previousPhoto have @photo = Photo.find(id -1). I'm not sure if this syntax works but something along these lines seems to be what you are looking for.

Upvotes: 0

Nick
Nick

Reputation: 2413

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.

Upvotes: 3

Related Questions