rails4 Edge Rails: PATCH is the new primary HTTP method for updates
2014-07-16 19:43
513 查看
What is PATCH?
The HTTP method PUT means resource creation or replacement at some given URL.Think files, for example. If you upload a file to S3 at some URL, you want either to create the file at that URL or replace an existing file if there's one. That is PUT.
Now let's say a web application has an
Invoicemodel with a
paidflag
that indicates whether the invoice has been paid. How do you set that flag in a RESTful way? Submitting
paid=1via PUT to
/invoices/:iddoes
not conform to HTTP semantics, because such request would not be sending a complete representation of the invoice for replacement.
With the constraints of the methods GET, POST, PUT, DELETE, the traditional answer is to define the paid flag of a given invoice to be a resource by itself. So, you define a route to be able to PUT
paid=1to
/invoices/:id/paid.
You have to do that because PUT does not allow partial updates to a resource.
Now let's think about ordinary edit forms in typical Ruby on Rails applications. How many times are we sending a complete representation for replacement? Not always, perhaps we could say that it is even rare in practice that you do so. For example, the conventional
created_atand
updated_attimestamps
normally can't be set by end-users, though they are often considered to belong to the representation of resources that map to records.
PUT in addition is an idempotent method. You should be able to replay a request as many times as you want and get the same resource, something that sometimes is violated by conventional idioms for creating children resources using nested attributes
while updating a parent resource.
There's nothing theoretical preventing PUT from doing partial updates, but when HTTP was being standarized the replacement semantics were already deployed.
Because of that, the PATCH method was defined in 1995 and standarized later. PATCH is a method that is not safe, nor idempotent, and allows full and partial
updates and side-effects on other resources.
In practice, as you see, PATCH suits everyday web programming way better than PUT for updating resources. In Ruby on Rails it corresponds naturally to the way we use
update_attributesfor
updating records.
Thus, PATCH is going to be the primary method for updates in Rails 4.0.
Routing
This is an important change, but we plan to do it in a way that is backwards compatible.When a resource is declared in config/routes.rb, for example,
resources :users
the action in
UsersControllerto update a user is still
updatein
Rails 4.0.
PUT requests to
/users/:idin Rails 4.0 get routed to
updateas
they are today. So, if you have an API that gets real PUT requests it is going to work.
In Rails 4.0, though, the router also routes PATCH requests to
/users/:idto the
updateaction.
So, in Rails 4.0 both PUT and PATCH are routed to
update.
Forms
Forms of persisted resources:form_for @user
get "patch" in the hidden field "_method". The RFC is deliberately vague about the way to represent changes in a PATCH request. Submitting a form is perfectly valid, client and server must simply agree on the accepted ways to update a resource.
Let me emphasize that the "_method" hack is a workaround for the limitations in web browsers. As you probably know Rails routes real HTTP methods. That is, actual PUT, DELETE, and now, PATCH requests are routed to their respective actions.
General availability
PATCH requests are available in all places where the rest of the methods are available today. There is a patchmacro for the routes DSL,
:viaunderstands
the symbol
:patch. Tests can issue PATCH requests, request objects respond to
patch?,
etc. Please see theoriginal commit for details (with an important followup here).
Will my web server understand PATCH?
Yes, it should. I have personally tried Apache, nginx, Phusion Passenger, Unicorn, Thin, and WEBrick. They all understood PATCH requests out of the box.Also, HTTP clients should be in general able to issue PATCH requests. For example in curl(1) you'd execute:
curl -d'user[name]=wadus' -X PATCH http://localhost:3000/users/1[/code]
转自:http://weblog.rubyonrails.org/2012/2/25/edge-rails-patch-is-the-new-primary-http-method-for-updates/
相关文章推荐
- The method getDispatcherType() is undefined for the type HttpServletRequest的解决方法
- jsp The method getDispatcherType() is undefined for the type HttpServletRequest
- The method getDispatcherType() is undefined for the type HttpServletRequest
- 升级到tomcat8遇到The method getDispatcherType() is undefined for the type HttpServletRequest
- 问题“The method getDispatcherType() is undefined for the type HttpServletRequest”
- The method getDispatcherType() is undefined for the type HttpServletRequest
- The method getServletContext() is undefined for the type HttpServletRequest
- Java 被访问时报 the method getDispatcherType() is undefined for the type HttpServletRequest
- The method makeText(Context, int, int) in the type Toast is not applicable for the arguments (new Vi
- android The method execute(Void[]) is ambiguous for the type new AsyncTask<Void,Void,Void>(){} (转)
- The method setCharacterEncoding(String) is undefined for the type HttpServletResponse
- 日常问题记录--访问JSP文件时The method getDispatcherType() is undefined for the type HttpServletRequest
- The method DataOutputStream(OutputStream) is undefined for the type new Runnable(){}
- The method execute(Void[]) is ambiguous for the type new AsyncTask<Void,Void,Void>(){}
- Web crash:The method getDispatcherType() is undefined for the type HttpServletRequest
- 升级到tomcat8遇到The method getDispatcherType() is undefined for the type HttpServletRequest
- The method getDispatcherType() is undefined for the type HttpServletRequest 升级到tomcat8
- The method setCharacterEncoding(String) is undefined for the type HttpServletResponse
- The method execute(Void[]) is ambiguous for the type new AsyncTask<Void,Void,Void>(){}
- The method getDispatcherType() is undefined for the type HttpServletRequest