From 5892827e87e6cfd09470cb8b2d270ce1a652c7d8 Mon Sep 17 00:00:00 2001 From: Brennan Dunn Date: Thu, 28 Aug 2008 07:35:00 -0400 Subject: [PATCH] Accept an array of method symbols for collection/member actions of resources --- actionpack/lib/action_controller/resources.rb | 21 +++++++++++++-------- actionpack/test/controller/resources_test.rb | 13 +++++++++++++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/actionpack/lib/action_controller/resources.rb b/actionpack/lib/action_controller/resources.rb index 5f579cd..d5e86b8 100644 --- a/actionpack/lib/action_controller/resources.rb +++ b/actionpack/lib/action_controller/resources.rb @@ -238,8 +238,9 @@ module ActionController # # The +resources+ method accepts the following options to customize the resulting routes: # * :collection - Add named routes for other actions that operate on the collection. - # Takes a hash of #{action} => #{method}, where method is :get/:post/:put/:delete - # or :any if the method does not matter. These routes map to a URL like /messages/rss, with a route of +rss_messages_url+. + # Takes a hash of #{action} => #{method}, where method is :get/:post/:put/:delete, + # an array of any of the previous, or :any if the method does not matter. + # These routes map to a URL like /messages/rss, with a route of +rss_messages_url+. # * :member - Same as :collection, but for actions that operate on a specific member. # * :new - Same as :collection, but for actions that operate on the new resource action. # * :controller - Specify the controller name for the routes. @@ -480,8 +481,10 @@ module ActionController def map_collection_actions(map, resource) resource.collection_methods.each do |method, actions| actions.each do |action| - action_options = action_options_for(action, resource, method) - map_named_routes(map, "#{action}_#{resource.name_prefix}#{resource.plural}", "#{resource.path}#{resource.action_separator}#{action}", action_options) + [method].flatten.each do |m| + action_options = action_options_for(action, resource, m) + map_named_routes(map, "#{action}_#{resource.name_prefix}#{resource.plural}", "#{resource.path}#{resource.action_separator}#{action}", action_options) + end end end end @@ -521,12 +524,14 @@ module ActionController def map_member_actions(map, resource) resource.member_methods.each do |method, actions| actions.each do |action| - action_options = action_options_for(action, resource, method) + [method].flatten.each do |m| + action_options = action_options_for(action, resource, m) - action_path = resource.options[:path_names][action] if resource.options[:path_names].is_a?(Hash) - action_path ||= Base.resources_path_names[action] || action + action_path = resource.options[:path_names][action] if resource.options[:path_names].is_a?(Hash) + action_path ||= Base.resources_path_names[action] || action - map_named_routes(map, "#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}#{resource.action_separator}#{action_path}", action_options) + map_named_routes(map, "#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}#{resource.action_separator}#{action_path}", action_options) + end end end diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index e153b0c..e8eb3ad 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -263,6 +263,19 @@ class ResourcesTest < Test::Unit::TestCase end end end + + def test_array_as_collection_or_member_method_value + with_restful_routing :messages, :collection => { :search => [:get, :post] }, :member => { :toggle => [:get, :post] } do + assert_restful_routes_for :messages do |options| + [:get, :post].each do |method| + assert_recognizes(options.merge(:action => 'search'), :path => "/messages/search", :method => method) + end + [:get, :post].each do |method| + assert_recognizes(options.merge(:action => 'toggle', :id => '1'), :path => '/messages/1/toggle', :method => method) + end + end + end + end def test_with_new_action with_restful_routing :messages, :new => { :preview => :post } do -- 1.5.6.4 From 5546e7e21c5c91a51302080df7c7d01d60a852bc Mon Sep 17 00:00:00 2001 From: Brennan Dunn Date: Thu, 28 Aug 2008 07:53:29 -0400 Subject: [PATCH] Allow for an array of request methods in routing conditions. --- .../lib/action_controller/routing/builder.rb | 12 +++++---- actionpack/lib/action_controller/routing/route.rb | 2 +- actionpack/test/controller/routing_test.rb | 25 ++++++++++++++++++++ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/actionpack/lib/action_controller/routing/builder.rb b/actionpack/lib/action_controller/routing/builder.rb index 03427e4..5704d9d 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 2106ac0..3b2cb28 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 6cf134c..7f0c47b 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)) -- 1.5.6.4