How to prevent rails from changing paths when an editing action is displayed from an update action

As far as I know, this is a standard rail template for editing and updating a resource.

I have a GET route for the edit action on /users/:id/edit and both PUT and PATCH routes for the update action on /users/:id .

Here are my actions with the controller:

 def edit @user = User.find params[:id] end def update @user = User.find params[:id] if @user.update_attributes(user_params) redirect_to @user, success: "Changes saved" else flash.now.alert = "Unable to change account details" render :edit end end 

And I use the default form form_for in my part:

 <%= form_for @user do |f| %> 

which creates the following form in html:

 <form accept-charset="UTF-8" action="/users/1" id="edit_user_1" method="post"> ... <input name="_method" type="hidden" value="patch"> 

When the update_attributes call succeeds, the user is redirected correctly, however, when the call fails (due to ActiveRecord checking), the visualization action displays the edit view correctly, but the path in the user browser changes from /users/1/edit to /users/1 .

From what I read, this seems to be the expected behavior of the rails, but it seems incomprehensible to me, since I thought the main idea of ​​REST is that the URL refers to the canonical representation of the resource?

If I redirect_to for the edit action instead of render , then the url will be what it should be, however I am losing error messages in the form.

Is there a smarter way to save URLs and error messages than dumping errors into a session before using redirect_to? I would like to avoid this if I can.

Update:

Why do I want the url to persist (as well as errors) because I use current_page? to set active states in navigation. Therefore, the β€œChange” action in the menu loses it, indicating whether the form is submitted with errors.

+7
ruby-on-rails
source share
2 answers

The reason you were in /users/1 is because the view displayed by #update rather than #edit .

By default, the resource path to #update same as #show , with a different GET and PUT request method. Thus, when #update displays an HTML response, it is similar to #show .

I think the result will be acceptable, no matter which path you expect as a result. As you have already found, when using redirect , the @user instance will be changed to a new branch, while losing errors and previous populations.

There is a workaround along the way, for example, using a session to pass an instance variable, but I don't think it is worth the effort. The current result is good enough.

Add

Managing active states is easy. I don't like current_page? that needs too much code. Use controller_path and action_name .

  if controller_path == 'users' && (action_name == 'edit' || 'update') # add active class end 
+1
source share

You should be able to redirect the edit URL and not lose the error message by replacing

 flash.now.alert = "Unable to change account details" 

from

 flash.alert = "Unable to change account details" 
0
source share

All Articles