Rails Best Practices for RESTful controller CREATE and UPDATE methods
OK, I am trying to understand the best practices for the CREATE and UPDATE methods for both HTML and XML formats. The default code for a controller that the rails generator generates is a little unclear to me.
For the CREATE method, given a good save, the generator says to "redirect_to(@whatever)" for HTML 开发者_运维技巧and "render :xml => @whatever, :status => :created, :location => @whatever" for XML.
Given a bad save, the generator says to "render :action => 'new'" for HTML and "render :xml => @whatever.errors, :status => :unprocessable_entity" for XML.
However, for the UPDATE method, given a good update, the generator says to "redirect_to(@whatever)" for HTML and "head :ok" for XML.
And, given a bad update, the generator says to "render :action => 'edit'" for HTML and "render :xml => @whatever.errors, :status => :unprocessable_entity" for XML.
I understand this, and it makes sense to me, and works just fine - BUT, I have two questions:
First, for a successful CREATE and UPDATE, HTML format, why "redirect_to(@whatever)" instead of "render :action => 'show'"? I understand the differences between redirect and render, just more curious about which way you guys tend to do it and why. It seems the redirect would be an unnecessary extra trip for the browser to make.
Second, why "head :ok" upon successful UPDATE via XML, but "render :xml => @whatever, :status => :created, :location => @whatever" upon successful CREATE via XML? This seems inconsistent to me. Seems like a successful UPDATE via XML should be the same as a successful CREATE via XML. Seems like you would need the new/updated object returned so you could test it. How do you guys do it and why?
I'd already written this out when Sam C replied, but here it is anyway :-)
For the first part - why redirect instead of render? Two reasons I can think of:
1) It's consistent. If you rendered the show action and the user uses the back button later on return to that page, the user will see unexpected behaviour. Some versions of IE will give you some kind of session timeout error IIRC, other browsers may handle it a bit more gracefully.
Same goes for if the user bookmarked that page and returns to it at a later date using a GET request - they won't see the show action. Your app may throw an error or may render the index action because the user is requesting a URL like http://my.app.com/users, which would map to the index action when using a GET request.
2) if you render the show action without redirecting to a GET request and the user hits refresh, your browser will re-submit the POST request with all the same data, potentially creating duplicate instances of whatever it is you were creating. The browser will warn the user about this so they can abort, but it's potentially confusing and an unnecessary inconvenience.
As for the second part of your question, not too sure to be honest. My guess is that since you are already updating the object in question, you already have a copy of it so do not need another instance of it returned. Having said that, updating an object could trigger various callbacks which modify other attributes of the object, so returning that updated object with those modifications could make sense.
On create or update, redirect_to(@whatever)
to clear the post, so that the user doesn't resubmit by refreshing. It also shows the correct url in the address bar for the create case, which posts to the collection path (/whatevers).
head :ok
makes a minimal response on update, when usually you would already have the object in the dom. If you are updating the page after an update, the standard method is to use rjs views to update dom elements and render partials.
精彩评论