diff options
author | Xavier Noria <fxn@hashref.com> | 2012-02-22 09:00:53 -0800 |
---|---|---|
committer | Xavier Noria <fxn@hashref.com> | 2012-02-22 09:00:53 -0800 |
commit | 7f2548e34d79c47ca138ca0378f4a06390c407f1 (patch) | |
tree | 4807b806fe8f3cfe30314fc522599b776e4a6d36 /actionpack/lib/action_dispatch | |
parent | f28d9f15482addeb95ab05545b7a8467a4e0182d (diff) | |
parent | 002713c64568114f3754799acc0723ea0d442f7a (diff) | |
download | rails-7f2548e34d79c47ca138ca0378f4a06390c407f1.tar.gz rails-7f2548e34d79c47ca138ca0378f4a06390c407f1.tar.bz2 rails-7f2548e34d79c47ca138ca0378f4a06390c407f1.zip |
Merge pull request #5130 from dlee/revised_patch_verb
Add config.default_method_for_update to support PATCH
Diffstat (limited to 'actionpack/lib/action_dispatch')
-rw-r--r-- | actionpack/lib/action_dispatch/http/request.rb | 6 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/railtie.rb | 1 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/routing.rb | 15 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/routing/mapper.rb | 125 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/testing/integration.rb | 26 |
5 files changed, 106 insertions, 67 deletions
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 0a0ebe7fad..de014a9c00 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -97,6 +97,12 @@ module ActionDispatch HTTP_METHOD_LOOKUP[request_method] == :post end + # Is this a PATCH request? + # Equivalent to <tt>request.request_method == :patch</tt>. + def patch? + HTTP_METHOD_LOOKUP[request_method] == :patch + end + # Is this a PUT request? # Equivalent to <tt>request.request_method_symbol == :put</tt>. def put? diff --git a/actionpack/lib/action_dispatch/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb index 35f901c575..4135f3c142 100644 --- a/actionpack/lib/action_dispatch/railtie.rb +++ b/actionpack/lib/action_dispatch/railtie.rb @@ -23,6 +23,7 @@ module ActionDispatch ActionDispatch::Http::URL.tld_length = app.config.action_dispatch.tld_length ActionDispatch::Request.ignore_accept_header = app.config.action_dispatch.ignore_accept_header ActionDispatch::Response.default_charset = app.config.action_dispatch.default_charset || app.config.encoding + ActionDispatch::Routing::Mapper.default_method_for_update = app.config.default_method_for_update ActionDispatch::ExceptionWrapper.rescue_responses.merge!(config.action_dispatch.rescue_responses) ActionDispatch::ExceptionWrapper.rescue_templates.merge!(config.action_dispatch.rescue_templates) diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index 107fe80d1f..38a0270151 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -182,10 +182,13 @@ module ActionDispatch # # == HTTP Methods # - # Using the <tt>:via</tt> option when specifying a route allows you to restrict it to a specific HTTP method. - # Possible values are <tt>:post</tt>, <tt>:get</tt>, <tt>:put</tt>, <tt>:delete</tt> and <tt>:any</tt>. - # If your route needs to respond to more than one method you can use an array, e.g. <tt>[ :get, :post ]</tt>. - # The default value is <tt>:any</tt> which means that the route will respond to any of the HTTP methods. + # Using the <tt>:via</tt> option when specifying a route allows you to + # restrict it to a specific HTTP method. Possible values are <tt>:post</tt>, + # <tt>:get</tt>, <tt>:patch</tt>, <tt>:put</tt>, <tt>:delete</tt> and + # <tt>:any</tt>. If your route needs to respond to more than one method you + # can use an array, e.g. <tt>[ :get, :post ]</tt>. The default value is + # <tt>:any</tt> which means that the route will respond to any of the HTTP + # methods. # # Examples: # @@ -198,7 +201,7 @@ module ActionDispatch # === HTTP helper methods # # An alternative method of specifying which HTTP method a route should respond to is to use the helper - # methods <tt>get</tt>, <tt>post</tt>, <tt>put</tt> and <tt>delete</tt>. + # methods <tt>get</tt>, <tt>post</tt>, <tt>patch</tt>, <tt>put</tt> and <tt>delete</tt>. # # Examples: # @@ -283,6 +286,6 @@ module ActionDispatch autoload :PolymorphicRoutes, 'action_dispatch/routing/polymorphic_routes' SEPARATORS = %w( / . ? ) #:nodoc: - HTTP_METHODS = [:get, :head, :post, :put, :delete, :options] #:nodoc: + HTTP_METHODS = [:get, :head, :post, :patch, :put, :delete, :options] #:nodoc: end end diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index cf9c0d7b6a..bb0441c100 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -7,6 +7,8 @@ require 'action_dispatch/routing/redirection' module ActionDispatch module Routing class Mapper + cattr_accessor(:default_method_for_update) {:put} + class Constraints #:nodoc: def self.new(app, constraints, request = Rack::Request) if constraints.any? @@ -465,7 +467,7 @@ module ActionDispatch # # Example: # - # get 'bacon', :to => 'food#bacon' + # get 'bacon', :to => 'food#bacon' def get(*args, &block) map_method(:get, args, &block) end @@ -475,17 +477,27 @@ module ActionDispatch # # Example: # - # post 'bacon', :to => 'food#bacon' + # post 'bacon', :to => 'food#bacon' def post(*args, &block) map_method(:post, args, &block) end + # Define a route that only recognizes HTTP PATCH. + # For supported arguments, see <tt>Base#match</tt>. + # + # Example: + # + # patch 'bacon', :to => 'food#bacon' + def patch(*args, &block) + map_method(:patch, args, &block) + end + # Define a route that only recognizes HTTP PUT. # For supported arguments, see <tt>Base#match</tt>. # # Example: # - # put 'bacon', :to => 'food#bacon' + # put 'bacon', :to => 'food#bacon' def put(*args, &block) map_method(:put, args, &block) end @@ -495,7 +507,7 @@ module ActionDispatch # # Example: # - # delete 'broccoli', :to => 'food#broccoli' + # delete 'broccoli', :to => 'food#broccoli' def delete(*args, &block) map_method(:delete, args, &block) end @@ -522,13 +534,13 @@ module ActionDispatch # This will create a number of routes for each of the posts and comments # controller. For <tt>Admin::PostsController</tt>, Rails will create: # - # GET /admin/posts - # GET /admin/posts/new - # POST /admin/posts - # GET /admin/posts/1 - # GET /admin/posts/1/edit - # PUT /admin/posts/1 - # DELETE /admin/posts/1 + # GET /admin/posts + # GET /admin/posts/new + # POST /admin/posts + # GET /admin/posts/1 + # GET /admin/posts/1/edit + # PUT/PATCH /admin/posts/1 + # DELETE /admin/posts/1 # # If you want to route /posts (without the prefix /admin) to # <tt>Admin::PostsController</tt>, you could use @@ -556,13 +568,13 @@ module ActionDispatch # not use scope. In the last case, the following paths map to # +PostsController+: # - # GET /admin/posts - # GET /admin/posts/new - # POST /admin/posts - # GET /admin/posts/1 - # GET /admin/posts/1/edit - # PUT /admin/posts/1 - # DELETE /admin/posts/1 + # GET /admin/posts + # GET /admin/posts/new + # POST /admin/posts + # GET /admin/posts/1 + # GET /admin/posts/1/edit + # PUT/PATCH /admin/posts/1 + # DELETE /admin/posts/1 module Scoping # Scopes a set of routes to the given default options. # @@ -651,13 +663,13 @@ module ActionDispatch # # This generates the following routes: # - # admin_posts GET /admin/posts(.:format) admin/posts#index - # admin_posts POST /admin/posts(.:format) admin/posts#create - # new_admin_post GET /admin/posts/new(.:format) admin/posts#new - # edit_admin_post GET /admin/posts/:id/edit(.:format) admin/posts#edit - # admin_post GET /admin/posts/:id(.:format) admin/posts#show - # admin_post PUT /admin/posts/:id(.:format) admin/posts#update - # admin_post DELETE /admin/posts/:id(.:format) admin/posts#destroy + # admin_posts GET /admin/posts(.:format) admin/posts#index + # admin_posts POST /admin/posts(.:format) admin/posts#create + # new_admin_post GET /admin/posts/new(.:format) admin/posts#new + # edit_admin_post GET /admin/posts/:id/edit(.:format) admin/posts#edit + # admin_post GET /admin/posts/:id(.:format) admin/posts#show + # admin_post PUT/PATCH /admin/posts/:id(.:format) admin/posts#update + # admin_post DELETE /admin/posts/:id(.:format) admin/posts#destroy # # === Options # @@ -972,12 +984,12 @@ module ActionDispatch # the +GeoCoders+ controller (note that the controller is named after # the plural): # - # GET /geocoder/new - # POST /geocoder - # GET /geocoder - # GET /geocoder/edit - # PUT /geocoder - # DELETE /geocoder + # GET /geocoder/new + # POST /geocoder + # GET /geocoder + # GET /geocoder/edit + # PUT/PATCH /geocoder + # DELETE /geocoder # # === Options # Takes same options as +resources+. @@ -1002,8 +1014,10 @@ module ActionDispatch member do get :edit if parent_resource.actions.include?(:edit) get :show if parent_resource.actions.include?(:show) - put :update if parent_resource.actions.include?(:update) delete :destroy if parent_resource.actions.include?(:destroy) + if parent_resource.actions.include?(:update) + send default_method_for_update, :update + end end end @@ -1020,13 +1034,13 @@ module ActionDispatch # creates seven different routes in your application, all mapping to # the +Photos+ controller: # - # GET /photos - # GET /photos/new - # POST /photos - # GET /photos/:id - # GET /photos/:id/edit - # PUT /photos/:id - # DELETE /photos/:id + # GET /photos + # GET /photos/new + # POST /photos + # GET /photos/:id + # GET /photos/:id/edit + # PUT/PATCH /photos/:id + # DELETE /photos/:id # # Resources can also be nested infinitely by using this block syntax: # @@ -1036,13 +1050,13 @@ module ActionDispatch # # This generates the following comments routes: # - # GET /photos/:photo_id/comments - # GET /photos/:photo_id/comments/new - # POST /photos/:photo_id/comments - # GET /photos/:photo_id/comments/:id - # GET /photos/:photo_id/comments/:id/edit - # PUT /photos/:photo_id/comments/:id - # DELETE /photos/:photo_id/comments/:id + # GET /photos/:photo_id/comments + # GET /photos/:photo_id/comments/new + # POST /photos/:photo_id/comments + # GET /photos/:photo_id/comments/:id + # GET /photos/:photo_id/comments/:id/edit + # PUT/PATCH /photos/:photo_id/comments/:id + # DELETE /photos/:photo_id/comments/:id # # === Options # Takes same options as <tt>Base#match</tt> as well as: @@ -1104,13 +1118,13 @@ module ActionDispatch # # The +comments+ resource here will have the following routes generated for it: # - # post_comments GET /posts/:post_id/comments(.:format) - # post_comments POST /posts/:post_id/comments(.:format) - # new_post_comment GET /posts/:post_id/comments/new(.:format) - # edit_comment GET /sekret/comments/:id/edit(.:format) - # comment GET /sekret/comments/:id(.:format) - # comment PUT /sekret/comments/:id(.:format) - # comment DELETE /sekret/comments/:id(.:format) + # post_comments GET /posts/:post_id/comments(.:format) + # post_comments POST /posts/:post_id/comments(.:format) + # new_post_comment GET /posts/:post_id/comments/new(.:format) + # edit_comment GET /sekret/comments/:id/edit(.:format) + # comment GET /sekret/comments/:id(.:format) + # comment PUT/PATCH /sekret/comments/:id(.:format) + # comment DELETE /sekret/comments/:id(.:format) # # === Examples # @@ -1138,11 +1152,14 @@ module ActionDispatch get :new end if parent_resource.actions.include?(:new) + # TODO: Only accept patch or put depending on config member do get :edit if parent_resource.actions.include?(:edit) get :show if parent_resource.actions.include?(:show) - put :update if parent_resource.actions.include?(:update) delete :destroy if parent_resource.actions.include?(:destroy) + if parent_resource.actions.include?(:update) + send default_method_for_update, :update + end end end diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb index 0287e7728b..62b3a344f8 100644 --- a/actionpack/lib/action_dispatch/testing/integration.rb +++ b/actionpack/lib/action_dispatch/testing/integration.rb @@ -26,8 +26,8 @@ module ActionDispatch # object's <tt>@response</tt> instance variable will point to the same # response object. # - # You can also perform POST, PUT, DELETE, and HEAD requests with +#post+, - # +#put+, +#delete+, and +#head+. + # You can also perform POST, PATCH, PUT, DELETE, and HEAD requests with + # +#post+, +#patch+, +#put+, +#delete+, and +#head+. def get(path, parameters = nil, headers = nil) process :get, path, parameters, headers end @@ -38,6 +38,12 @@ module ActionDispatch process :post, path, parameters, headers end + # Performs a PATCH request with the given parameters. See +#get+ for more + # details. + def patch(path, parameters = nil, headers = nil) + process :patch, path, parameters, headers + end + # Performs a PUT request with the given parameters. See +#get+ for more # details. def put(path, parameters = nil, headers = nil) @@ -65,10 +71,10 @@ module ActionDispatch # Performs an XMLHttpRequest request with the given parameters, mirroring # a request from the Prototype library. # - # The request_method is +:get+, +:post+, +:put+, +:delete+ or +:head+; the - # parameters are +nil+, a hash, or a url-encoded or multipart string; - # the headers are a hash. Keys are automatically upcased and prefixed - # with 'HTTP_' if not already. + # The request_method is +:get+, +:post+, +:patch+, +:put+, +:delete+ or + # +:head+; the parameters are +nil+, a hash, or a url-encoded or multipart + # string; the headers are a hash. Keys are automatically upcased and + # prefixed with 'HTTP_' if not already. def xml_http_request(request_method, path, parameters = nil, headers = nil) headers ||= {} headers['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' @@ -108,6 +114,12 @@ module ActionDispatch request_via_redirect(:post, path, parameters, headers) end + # Performs a PATCH request, following any subsequent redirect. + # See +request_via_redirect+ for more information. + def patch_via_redirect(path, parameters = nil, headers = nil) + request_via_redirect(:patch, path, parameters, headers) + end + # Performs a PUT request, following any subsequent redirect. # See +request_via_redirect+ for more information. def put_via_redirect(path, parameters = nil, headers = nil) @@ -318,7 +330,7 @@ module ActionDispatch @integration_session = Integration::Session.new(app) end - %w(get post put head delete options cookies assigns + %w(get post put patch head delete options cookies assigns xml_http_request xhr get_via_redirect post_via_redirect).each do |method| define_method(method) do |*args| reset! unless integration_session |