Andrew
Andrew

Reputation: 43123

Rails: sessions + views dependent on referrer?

I have an app with Photos. Users can view photos directly from a link or a bookmark etc, or they can search for photos, or they can browse through folders of photos.

No matter how they find a photo, they're landing on the photos#show view. However, they can get to that view from photos#search or from folders#show.

I've been working on creating a "next/previous" photo function. Here's what I've got so far...

In any controller action that shows an index of the photos, there is the following line:

session[:query] = @photos.map(&:id)

This generates an array of the ids for the photos that are going to be shown to the user in that view.

Here's the Photo model:

# NEXT / PREVIOUS FUNCTIONALITY
def previous(query)
  unless query.nil?
    index = query.find_index(self.id)
    prev_id = query[index-1] unless index.zero?
    self.class.find_by_id(prev_id)
  end
end

def next(query)
  unless query.nil?
    index = query.find_index(self.id)
    next_id = query[index+1] unless index == query.size
    self.class.find_by_id(next_id)
  end
end

The above methods accept the array of ids, find the current photos place in that array, and then find the ids coming before and after it.

So, then in the photos#show controller I have:

...
if session[:query]
  @next_photo = @photo.next(session[:query])
  @prev_photo = @photo.previous(session[:query])
end
...

So, this actually works pretty well, but with one big "gotcha":

If the user gets to a photo view by browsing through the site everything is fine, but if they user gets to a photo via a bookmark, a link, or by skipping back through their history, then the SESSION still is holding onto the old query, but the user is now looking at a photo that may or may not have been part of that query, and the "next" and "previous" photos that are shown are now part of an old query.

This is a bit confusing, so just imagine the following (simplest case):


A user browses through a folder of images, and finds photos with ids: 1, 2, 3, 4, 5

The user browses through this a bit, and thinks photo 4 is neat. While looking at photo 4, photos 3 and 5 are shown as "previous" and "next". The user bookmarks this page.

The user then goes and conducts a search, which returns photos: 1, 4, 7, 9, 12

The user clicks on photo 1, looks at the picture, then leaves the site for a moment to go to wikipedia or something. Wanting to go back to the site the user clicks the bookmark for Photo 4.

Now the user sees photo 4, but because the last query in session was for a search, the user sees photos 1 and 7 as previous/next, whereas the last time the user visited this page he saw photos 3 and 5.


In other words, once a query has been loaded into session it stays around, which is usually good, except when the user jumps directly around photos using bookmarks or history etc. In that case, it would be better if the session was just cleared, so no "next / previous" photos would show (because the user didn't browse to this page from an index).

So, all that setup for these questions:

  1. Is there a way to clear the session[:query] param based on the referrer? IE something like, if the user didn't get here from folders#show or photos#search or another photo included in the original query, then forget the old query.

  2. Is there a way to have the view respond to the previous referrer as well? Something like, if the user got there from folders#show then say "Other photos from this folder", but if the user got there from photos#search then say "next search result / previous search result"

I'm pretty stumped on this one, and I'd greatly appreciate any suggestions.

Thanks!!

Upvotes: 0

Views: 350

Answers (1)

Mike Lewis
Mike Lewis

Reputation: 64147

You could do something like:

session[:query] = nil if /photos\/search|folders\/show/.match(request.env["HTTP_REFERER"]) || photo_included_in_query

Where you would implement the photo_included_in_query method.

For the view, you could factor this logic out into a helper, such as:

def request_from_folder?
  /folders\/show/.match(request.env["HTTP_REFERER"]) 
end

And in your view:

<% if request_from_folder? %>
  Other photos from this folder
<% else %>
   Next/Previous
<% end %>

Upvotes: 2

Related Questions