Why is post request favoured over delete in rails?
I have seen this in a lot of code written using Ruby-on-Rails.
It seems that post requests are often preferred over delete ones
def destroy
relation = IssueRelation.find(params[:id])
if request.post? && @issue.relations.include?(rel开发者_StackOverflow社区ation)
relation.destroy
@issue.reload
end
end
I find this a bit strange, because it does not seem to follow the REST convention used so much in Rails.
Does this have to do with security, or is it present for compatibility with some old browsers that don't support the delete request?
You basically answered your own question, browsers aren't exactly great at supporting all HTTP verbs. There's a nice site where you can test what your current browser supports, have a look at what things fail, I'm sure you'll notice some with regarding delete
, for example when redirects are involved:
http://www.mnot.net/javascript/xmlhttprequest/
The Delete request isn't a full on true delete request. It's actually faked, much like the put request is when you use the form_for on a saved object. As far as I know, there's no reason why not use the REST convention provided.
On another note, is that your own code in the snippet, or an example? Kind of curious why you would check to see if the record you are deleting is associated to parent. I guess there's always the possibility that in between the time you clicked on the delete, and it got to the request, that someone changed its parent somewhere else.
Edit, here's the header information when i click on the delete link in a rails 3 scaffold app:
Request URL:http://phone_qa.dev/sites/2
Request Method:POST
Status Code:302 Moved Temporarily
Request Headersview source
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:86
Content-Type:application/x-www-form-urlencoded
Cookie: _phone_qa_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFRkkiJTg4Y2Q4ZTgyOGYwM2IyMWI1N2Y4MjYyMTcwMzJiMzMwBjsAVEkiEF9jc3JmX3Rva2VuBjsARkkiMVY0QkFIOXdzRFZXZi9yYnlkODJCUEdLTisvT2V6dVpkVDYyckkyR3JQSzg9BjsARg%3D%3D--e8244fd59e5fc34b37a93c2e768ace7a3bfffe44
Host:phone_qa.dev
Origin:http://phone_qa.dev
Referer:http://phone_qa.dev/sites
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.107 Safari/535.1
Form Dataview URL encoded
_method:delete
authenticity_token:V4BAH9wsDVWf/rbyd82BPGKN /OezuZdT62rI2GrPK8=
You can see how it's actually a post request, but under the form data, there's a variable called _method with the value delete.
That code snippet is from Redmine and was committed in May 2007: https://github.com/edavis10/redmine/blob/92b02014d21f0e60230fc7a5c3c5ad71dac6e472/app/controllers/issue_relations_controller.rb
That's a long time ago, and if my memory doesn't escape me, REST wasn't all that well known nor all that well implemented in Rails back then. The above pattern was a sensible way to do things back then.
For comparison, the same action looks like this in Redmine now:
verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed }
def destroy
raise Unauthorized unless @relation.deletable?
@relation.destroy
respond_to do |format|
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
format.js { render(:update) {|page| page.remove "relation-#{@relation.id}"} }
format.api { head :ok }
end
rescue ActiveRecord::RecordNotFound
render_404
end
Not only does it verify that the HTTP verb is DELETE (albeit faked due to browsers lacking support), but it also has the ability to respond to requests for different MIME types - much more RESTful now.
精彩评论