Search code examples
ruby-on-railsruby-on-rails-3url-routingnested-resources

Rails Nested Singular Resource Routing


I have a simple User model with a singular nested Profile resource so in my routes.rb I have:

resources :users do
  resource :profile, :only => [:edit, :update, :show]
end

This generates the expected routes:

edit_user_profile GET    /users/:user_id/profile/edit(.:format)  {:action=>"edit", :controller=>"profiles"}
     user_profile GET    /users/:user_id/profile(.:format)       {:action=>"show", :controller=>"profiles"}
     user_profile PUT    /users/:user_id/profile(.:format)       {:action=>"update", :controller=>"profiles"}

I've created a simple controller update method that updates the model and then redirects upon successful update:

def update
  @profile = Profile.find_by_user_id(params[:user_id])
  @user = User.find_by_id(params[:user_id])

  respond_to do |format|
    if @profile.update_attributes(params[:profile])
      format.html { redirect_to( user_profile_path(@user, @profile), :notice => 'Profile was successfully updated.') }
    else
      # ...
    end
  end
end

The problem is that once the form is submitted, the form redirects to mydomain.com/users/4/profile.22 where 22 happens to be the id of the profile. Clearly this confuses the controllers since the routing interprets the '22' as the format.

My question is, how do I get this to redirect to mydomain.com/users/4/profile instead? I've tried the following variations on the redirect_to statement to no effect, they all result in the same incorrect url:

redirect_to( user_profile_path(@user), ... )
redirect_to( user_profile_path(@user, @profile), ... )
redirect_to([@user, @profile], ... )
redirect_to( @profile, ... )

What's more, using 'user_profile_path(@user)' elsewhere produces the correct url.

Any ideas? Oh, and I'm using Rails 3.0.0 and Ruby 1.9.2 if that helps.


Solution

  • After looking around, it appears that the form generating the update had an incorrect url. If anyone is seeing this issue, it's because I had my form set up as:

    form_for [@user, @profile] do |f| ...
    

    This caused the form action to have the incorrect url (of the offending form above). Instead, I used

    form_for @profile, :url => user_profile_path(@user) do |f| ...
    

    and everything seemed to work.