Rails Nested Singular Resource Routing

2019-04-04 00:35发布

问题:

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.

回答1:

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.



回答2:

You should redirect to user_profile_path(@user) since as your routes says it is:

/users/:user_id/profile(.:format)

If you look at it closely, then you will see, that there is only :user_id parameter needed, thou it is only @user in a path.

/users/:user_id/profile/:id(.:format)

It would be correct if you had resource*s* :profiles in your routes.rb, then as well you could use your path as in your example.



回答3:

user_profile_path(@user) should be correct. You're sure that one is returning mydomain.com/users/4/profile.22?