aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/CHANGELOG4
-rw-r--r--actionpack/lib/action_controller/routing/builder.rb12
-rw-r--r--actionpack/lib/action_controller/routing/route.rb2
-rw-r--r--actionpack/test/controller/routing_test.rb25
4 files changed, 37 insertions, 6 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index 6717162d1e..7fdff1c8e0 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,9 @@
*Edge*
+* Routes may be restricted to lists of HTTP methods instead of a single method or :any. #407 [Brennan Dunn, Gaius Centus Novus]
+ map.resource :posts, :collection => { :search => [:get, :post] }
+ map.session 'session', :requirements => { :method => [:get, :post, :delete] }
+
* Deprecated implicit local assignments when rendering partials [Josh Peek]
* Introduce current_cycle helper method to return the current value without bumping the cycle. #417 [Ken Collins]
diff --git a/actionpack/lib/action_controller/routing/builder.rb b/actionpack/lib/action_controller/routing/builder.rb
index 03427e41de..5704d9d01a 100644
--- a/actionpack/lib/action_controller/routing/builder.rb
+++ b/actionpack/lib/action_controller/routing/builder.rb
@@ -187,12 +187,14 @@ module ActionController
private
def validate_route_conditions(conditions)
if method = conditions[:method]
- if method == :head
- raise ArgumentError, "HTTP method HEAD is invalid in route conditions. Rails processes HEAD requests the same as GETs, returning just the response headers"
- end
+ [method].flatten.each do |m|
+ if m == :head
+ raise ArgumentError, "HTTP method HEAD is invalid in route conditions. Rails processes HEAD requests the same as GETs, returning just the response headers"
+ end
- unless HTTP_METHODS.include?(method.to_sym)
- raise ArgumentError, "Invalid HTTP method specified in route conditions: #{conditions.inspect}"
+ unless HTTP_METHODS.include?(m.to_sym)
+ raise ArgumentError, "Invalid HTTP method specified in route conditions: #{conditions.inspect}"
+ end
end
end
end
diff --git a/actionpack/lib/action_controller/routing/route.rb b/actionpack/lib/action_controller/routing/route.rb
index 2106ac09e0..3b2cb28545 100644
--- a/actionpack/lib/action_controller/routing/route.rb
+++ b/actionpack/lib/action_controller/routing/route.rb
@@ -201,7 +201,7 @@ module ActionController
# recognition, not generation.
def recognition_conditions
result = ["(match = #{Regexp.new(recognition_pattern).inspect}.match(path))"]
- result << "conditions[:method] === env[:method]" if conditions[:method]
+ result << "[conditions[:method]].flatten.include?(env[:method])" if conditions[:method]
result
end
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index 6cf134c26f..1a802c464f 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -1297,6 +1297,31 @@ uses_mocha 'LegacyRouteSet, Route, RouteSet and RouteLoading' do
end
end
+ def test_recognize_array_of_methods
+ begin
+ Object.const_set(:BooksController, Class.new(ActionController::Base))
+ rs.draw do |r|
+ r.connect '/match', :controller => 'books', :action => 'get_or_post', :conditions => { :method => [:get, :post] }
+ r.connect '/match', :controller => 'books', :action => 'not_get_or_post'
+ end
+
+ @request = ActionController::TestRequest.new
+ @request.env["REQUEST_METHOD"] = 'POST'
+ @request.request_uri = "/match"
+ assert_nothing_raised { rs.recognize(@request) }
+ assert_equal 'get_or_post', @request.path_parameters[:action]
+
+ # have to recreate or else the RouteSet uses a cached version:
+ @request = ActionController::TestRequest.new
+ @request.env["REQUEST_METHOD"] = 'PUT'
+ @request.request_uri = "/match"
+ assert_nothing_raised { rs.recognize(@request) }
+ assert_equal 'not_get_or_post', @request.path_parameters[:action]
+ ensure
+ Object.send(:remove_const, :BooksController) rescue nil
+ end
+ end
+
def test_subpath_recognized
Object.const_set(:SubpathBooksController, Class.new(ActionController::Base))