views:

58

answers:

3

How can I design my view such that it "remembers" its route? So that "Back" on /team/1/members/1 links to /team/1/members and /members/1 links back to /members?

I have models of team and member. Teams have many members.

My routes allow me to view all member or members on a team.

  resources :teams do
    resources :members
  end
  resources :members do
    resources :member_parts
  end

I've currently tried to keep the route consistent. But doing so I seem to have to repeat myself a lot and add many bits of logic to the view. (this just seems wrong)

excerpt from app/views/members/show.html.erb

<%= link_to 'Edit', params[:team_id].nil? ? edit_member_path(@member) : edit_team_member_path(@member.team,@member) %> |
<%= link_to 'Back', params[:team_id].nil? ? members_path : team_members_path(@member.team) %>
+2  A: 

A quick hack, not tested in Rails3, you may have to adapt it:

In application_controller.rb

before_filter :store_location

def store_location
  session[:return_to] = request.fullpath
end

def redirect_back_or_default(default=root_path, flash=nil)
  session[:return_to] ||= default
  redirect_to(session[:return_to], flash)
  session[:return_to] = nil
end

In your routes

match '/back' => 'application#redirect_back_or_default'

In your views

<%= link_to 'Back', '/back' %>

You can also use this redirect_back_or_default method in your actions…

Yannis
This is interesting, but isn't quite the same thing. I should clarify the question a bit. My concern isn't so much with "back" or the history, as it is knowing whether or not the view is being rendered nested or directly.
hometoast
It only works for one level "deep" back
klew
+2  A: 

Updated Updated the code, the problem was that, the method couldn't recognized the path because I provided only an id instead of a class.

Use polymorphic paths.

The edit link:

Generate your path array

paths = []
paths << @member.team if params[:team_id]
paths << @member
polymorphic_path(paths,:action=>:edit)

paths2 = []
paths2 << @member.team if params[:team_id]
paths2 << :members
polymorphic_path(paths2)

For more information please see the Rails api

Hope this will be a good start point.

dombesz
I can't get this to work -- I'm guessing I'm doing it wrong.
hometoast
What is the error?
dombesz
for /teams/7/members/66 I get "undefined method `edit_7_member_path'"
hometoast
updated the post, it was an error
dombesz
thanks. I see. This isn't much different than me toggling between edit_member_path and edit_team_member_path based on the existence of :team_id. I think if I could get the plugin to work in Rails 3 the resource controller would do it. Right now I'm going to redsign the views that "back" will be replaced with "all members", and "all team members". This way there's no ambiguity to the link to begin with.
hometoast
+1  A: 

You can take a look on urligecne in resource_controller plugin and on it's url helpers. It allows you to use object_path or collection_path and it returns path according to present url, so it just do what you want.

You can also add this dirty and ugly solution:

# application helper
def collection_path
  request.request_uri.gsub(/\/[\d]+[\/]*$/, "")
end

It should remove strings like "/2/" or "/14" or "/" from the end of your url. However I feel very week when it comes to use regexp, so be careful with this.

You can use this helper in view:

<%= link_to "Back", collection_path %>

Also to generate edit path, you can just add "edit" string at the end of current url. You can create edit_object_path helper for this:

def edit_object_path
  request.request_uri.chop('/') + "/edit"
end 

But again it is quite dirty solution and you should be careful.

EDIT: As I look at @dombesz answer, it probably is what you are looking for!

klew
This seems to be EXACTLY what I need. But I (or someone) needs to update it to fit Rails 3.
hometoast