diff --git a/actionpack/lib/action_controller/assertions/routing_assertions.rb b/actionpack/lib/action_controller/assertions/routing_assertions.rb index 491b72d586..312b4e228b 100644 --- a/actionpack/lib/action_controller/assertions/routing_assertions.rb +++ b/actionpack/lib/action_controller/assertions/routing_assertions.rb @@ -2,7 +2,7 @@ module ActionController module Assertions # Suite of assertions to test routes generated by Rails and the handling of requests made to them. module RoutingAssertions - # Asserts that the routing of the given +path+ was handled correctly and that the parsed options (given in the +expected_options+ hash) + # Asserts that the routing of the given +path+ was handled correctly and that the parsed options (given in the +expected_options+ hash) # match +path+. Basically, it asserts that Rails recognizes the route given by +expected_options+. # # Pass a hash in the second argument (+path+) to specify the request method. This is useful for routes @@ -14,16 +14,16 @@ module ActionController # # You can also pass in +extras+ with a hash containing URL parameters that would normally be in the query string. This can be used # to assert that values in the query string string will end up in the params hash correctly. To test query strings you must use the - # extras argument, appending the query string on the path directly will not work. For example: + # extras argument, appending the query string on the path directly will not work. For example: # # # assert that a path of '/items/list/1?view=print' returns the correct options - # assert_recognizes({:controller => 'items', :action => 'list', :id => '1', :view => 'print'}, 'items/list/1', { :view => "print" }) + # assert_recognizes({:controller => 'items', :action => 'list', :id => '1', :view => 'print'}, 'items/list/1', { :view => "print" }) # - # The +message+ parameter allows you to pass in an error message that is displayed upon failure. + # The +message+ parameter allows you to pass in an error message that is displayed upon failure. # # ==== Examples # # Check the default route (i.e., the index action) - # assert_recognizes({:controller => 'items', :action => 'index'}, 'items') + # assert_recognizes({:controller => 'items', :action => 'index'}, 'items') # # # Test a specific action # assert_recognizes({:controller => 'items', :action => 'list'}, 'items/list') @@ -44,16 +44,16 @@ module ActionController request_method = nil end - clean_backtrace do - ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty? + clean_backtrace do + ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty? request = recognized_request_for(path, request_method) - + expected_options = expected_options.clone extras.each_key { |key| expected_options.delete key } unless extras.nil? - + expected_options.stringify_keys! routing_diff = expected_options.diff(request.path_parameters) - msg = build_message(message, "The recognized options did not match , difference: ", + msg = build_message(message, "The recognized options did not match , difference: ", request.path_parameters, expected_options, expected_options.diff(request.path_parameters)) assert_block(msg) { request.path_parameters == expected_options } end @@ -64,7 +64,7 @@ module ActionController # a query string. The +message+ parameter allows you to specify a custom error message for assertion failures. # # The +defaults+ parameter is unused. - # + # # ==== Examples # # Asserts that the default action is generated for a route with no action # assert_generates("/items", :controller => "items", :action => "index") @@ -73,34 +73,34 @@ module ActionController # assert_generates("/items/list", :controller => "items", :action => "list") # # # Tests the generation of a route with a parameter - # assert_generates("/items/list/1", { :controller => "items", :action => "list", :id => "1" }) + # assert_generates("/items/list/1", { :controller => "items", :action => "list", :id => "1" }) # # # Asserts that the generated route gives us our custom route # assert_generates "changesets/12", { :controller => 'scm', :action => 'show_diff', :revision => "12" } def assert_generates(expected_path, options, defaults={}, extras = {}, message=nil) - clean_backtrace do + clean_backtrace do expected_path = "/#{expected_path}" unless expected_path[0] == ?/ # Load routes.rb if it hasn't been loaded. - ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty? - + ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty? + generated_path, extra_keys = ActionController::Routing::Routes.generate_extras(options, defaults) found_extras = options.reject {|k, v| ! extra_keys.include? k} msg = build_message(message, "found extras , not ", found_extras, extras) assert_block(msg) { found_extras == extras } - - msg = build_message(message, "The generated path did not match ", generated_path, + + msg = build_message(message, "The generated path did not match ", generated_path, expected_path) assert_block(msg) { expected_path == generated_path } end end - # Asserts that path and options match both ways; in other words, it verifies that path generates + # Asserts that path and options match both ways; in other words, it verifies that path generates # options and then that options generates path. This essentially combines +assert_recognizes+ # and +assert_generates+ into one step. # # The +extras+ hash allows you to specify options that would normally be provided as a query string to the action. The - # +message+ parameter allows you to specify a custom error message to display upon failure. + # +message+ parameter allows you to specify a custom error message to display upon failure. # # ==== Examples # # Assert a basic route: a controller with the default action (index) @@ -119,12 +119,12 @@ module ActionController # assert_routing({ :method => 'put', :path => '/product/321' }, { :controller => "product", :action => "update", :id => "321" }) def assert_routing(path, options, defaults={}, extras={}, message=nil) assert_recognizes(options, path, extras, message) - - controller, default_controller = options[:controller], defaults[:controller] + + controller, default_controller = options[:controller], defaults[:controller] if controller && controller.include?(?/) && default_controller && default_controller.include?(?/) options[:controller] = "/#{controller}" end - + assert_generates(path.is_a?(Hash) ? path[:path] : path, options, defaults, extras, message) end diff --git a/actionpack/lib/action_controller/routing.rb b/actionpack/lib/action_controller/routing.rb index dfbaa53b7c..8d51e823a6 100644 --- a/actionpack/lib/action_controller/routing.rb +++ b/actionpack/lib/action_controller/routing.rb @@ -201,7 +201,7 @@ module ActionController # With conditions you can define restrictions on routes. Currently the only valid condition is :method. # # * :method - Allows you to specify which method can access the route. Possible values are :post, - # :get, :put, :delete and :any. The default value is :any, + # :get, :put, :delete and :any. The default value is :any, # :any means that any method can access the route. # # Example: @@ -213,7 +213,7 @@ module ActionController # # Now, if you POST to /posts/:id, it will route to the create_comment action. A GET on the same # URL will route to the show action. - # + # # == Reloading routes # # You can reload routes if you feel you must: @@ -281,9 +281,9 @@ module ActionController end class << self - # Expects an array of controller names as the first argument. - # Executes the passed block with only the named controllers named available. - # This method is used in internal Rails testing. + # Expects an array of controller names as the first argument. + # Executes the passed block with only the named controllers named available. + # This method is used in internal Rails testing. def with_controllers(names) prior_controllers = @possible_controllers use_controllers! names @@ -292,10 +292,10 @@ module ActionController use_controllers! prior_controllers end - # Returns an array of paths, cleaned of double-slashes and relative path references. - # * "\\\" and "//" become "\\" or "/". - # * "/foo/bar/../config" becomes "/foo/config". - # The returned array is sorted by length, descending. + # Returns an array of paths, cleaned of double-slashes and relative path references. + # * "\\\" and "//" become "\\" or "/". + # * "/foo/bar/../config" becomes "/foo/config". + # The returned array is sorted by length, descending. def normalize_paths(paths) # do the hokey-pokey of path normalization... paths = paths.collect do |path| @@ -314,7 +314,7 @@ module ActionController paths = paths.uniq.sort_by { |path| - path.length } end - # Returns the array of controller names currently available to ActionController::Routing. + # Returns the array of controller names currently available to ActionController::Routing. def possible_controllers unless @possible_controllers @possible_controllers = [] @@ -339,28 +339,27 @@ module ActionController @possible_controllers end - # Replaces the internal list of controllers available to ActionController::Routing with the passed argument. - # ActionController::Routing.use_controllers!([ "posts", "comments", "admin/comments" ]) + # Replaces the internal list of controllers available to ActionController::Routing with the passed argument. + # ActionController::Routing.use_controllers!([ "posts", "comments", "admin/comments" ]) def use_controllers!(controller_names) @possible_controllers = controller_names end - # Returns a controller path for a new +controller+ based on a +previous+ controller path. - # Handles 4 scenarios: - # - # * stay in the previous controller: - # controller_relative_to( nil, "groups/discussion" ) # => "groups/discussion" - # - # * stay in the previous namespace: - # controller_relative_to( "posts", "groups/discussion" ) # => "groups/posts" - # - # * forced move to the root namespace: - # controller_relative_to( "/posts", "groups/discussion" ) # => "posts" - # - # * previous namespace is root: - # controller_relative_to( "posts", "anything_with_no_slashes" ) # =>"posts" - # - + # Returns a controller path for a new +controller+ based on a +previous+ controller path. + # Handles 4 scenarios: + # + # * stay in the previous controller: + # controller_relative_to( nil, "groups/discussion" ) # => "groups/discussion" + # + # * stay in the previous namespace: + # controller_relative_to( "posts", "groups/discussion" ) # => "groups/posts" + # + # * forced move to the root namespace: + # controller_relative_to( "/posts", "groups/discussion" ) # => "posts" + # + # * previous namespace is root: + # controller_relative_to( "posts", "anything_with_no_slashes" ) # =>"posts" + # def controller_relative_to(controller, previous) if controller.nil? then previous elsif controller[0] == ?/ then controller[1..-1] @@ -369,12 +368,11 @@ module ActionController end end end - Routes = RouteSet.new ActiveSupport::Inflector.module_eval do - # Ensures that routes are reloaded when Rails inflections are updated. + # Ensures that routes are reloaded when Rails inflections are updated. def inflections_with_route_reloading(&block) returning(inflections_without_route_reloading(&block)) { ActionController::Routing::Routes.reload! if block_given? diff --git a/actionpack/lib/action_controller/routing/optimisations.rb b/actionpack/lib/action_controller/routing/optimisations.rb index 4b70ea13f2..b44ebd5ca2 100644 --- a/actionpack/lib/action_controller/routing/optimisations.rb +++ b/actionpack/lib/action_controller/routing/optimisations.rb @@ -1,14 +1,14 @@ module ActionController module Routing - # Much of the slow performance from routes comes from the + # Much of the slow performance from routes comes from the # complexity of expiry, :requirements matching, defaults providing - # and figuring out which url pattern to use. With named routes - # we can avoid the expense of finding the right route. So if + # and figuring out which url pattern to use. With named routes + # we can avoid the expense of finding the right route. So if # they've provided the right number of arguments, and have no # :requirements, we can just build up a string and return it. - # - # To support building optimisations for other common cases, the - # generation code is separated into several classes + # + # To support building optimisations for other common cases, the + # generation code is separated into several classes module Optimisation def generate_optimisation_block(route, kind) return "" unless route.optimise? @@ -53,12 +53,12 @@ module ActionController # map.person '/people/:id' # # If the user calls person_url(@person), we can simply - # return a string like "/people/#{@person.to_param}" + # return a string like "/people/#{@person.to_param}" # rather than triggering the expensive logic in +url_for+. class PositionalArguments < Optimiser def guard_condition number_of_arguments = route.segment_keys.size - # if they're using foo_url(:id=>2) it's one + # if they're using foo_url(:id=>2) it's one # argument, but we don't want to generate /foos/id2 if number_of_arguments == 1 "(!defined?(default_url_options) || default_url_options.blank?) && defined?(request) && request && args.size == 1 && !args.first.is_a?(Hash)" @@ -94,14 +94,14 @@ module ActionController end # This case is mostly the same as the positional arguments case - # above, but it supports additional query parameters as the last + # above, but it supports additional query parameters as the last # argument class PositionalArgumentsWithAdditionalParams < PositionalArguments def guard_condition "(!defined?(default_url_options) || default_url_options.blank?) && defined?(request) && request && args.size == #{route.segment_keys.size + 1} && !args.last.has_key?(:anchor) && !args.last.has_key?(:port) && !args.last.has_key?(:host)" end - # This case uses almost the same code as positional arguments, + # This case uses almost the same code as positional arguments, # but add an args.last.to_query on the end def generation_code super.insert(-2, '?#{args.last.to_query}') @@ -110,7 +110,7 @@ module ActionController # To avoid generating "http://localhost/?host=foo.example.com" we # can't use this optimisation on routes without any segments def applicable? - super && route.segment_keys.size > 0 + super && route.segment_keys.size > 0 end end diff --git a/actionpack/lib/action_controller/routing/recognition_optimisation.rb b/actionpack/lib/action_controller/routing/recognition_optimisation.rb index cf8f5232c1..67d354a943 100644 --- a/actionpack/lib/action_controller/routing/recognition_optimisation.rb +++ b/actionpack/lib/action_controller/routing/recognition_optimisation.rb @@ -51,7 +51,6 @@ module ActionController # 3) segm test for /users/:id # (jump to list index = 5) # 4) full test for /users/:id => here we are! - class RouteSet def recognize_path(path, environment={}) result = recognize_optimized(path, environment) and return result @@ -152,7 +151,6 @@ module ActionController segments << nil segments end - end end end diff --git a/actionpack/lib/action_controller/routing/route.rb b/actionpack/lib/action_controller/routing/route.rb index a0d108ba03..a05c8c10ac 100644 --- a/actionpack/lib/action_controller/routing/route.rb +++ b/actionpack/lib/action_controller/routing/route.rb @@ -226,15 +226,14 @@ module ActionController end end - protected - def requirement_for(key) - return requirements[key] if requirements.key? key - segments.each do |segment| - return segment.regexp if segment.respond_to?(:key) && segment.key == key + protected + def requirement_for(key) + return requirements[key] if requirements.key? key + segments.each do |segment| + return segment.regexp if segment.respond_to?(:key) && segment.key == key + end + nil end - nil - end - end end end diff --git a/actionpack/lib/action_controller/routing/route_set.rb b/actionpack/lib/action_controller/routing/route_set.rb index 5bc13cf268..4a9bc259f3 100644 --- a/actionpack/lib/action_controller/routing/route_set.rb +++ b/actionpack/lib/action_controller/routing/route_set.rb @@ -1,6 +1,6 @@ module ActionController module Routing - class RouteSet #:nodoc: + class RouteSet #:nodoc: # Mapper instances are used to build routes. The object passed to the draw # block in config/routes.rb is a Mapper instance. # @@ -432,4 +432,4 @@ module ActionController end end end -end \ No newline at end of file +end diff --git a/actionpack/lib/action_controller/routing/routing_ext.rb b/actionpack/lib/action_controller/routing/routing_ext.rb index 2ad20ee699..5f4ba90d0c 100644 --- a/actionpack/lib/action_controller/routing/routing_ext.rb +++ b/actionpack/lib/action_controller/routing/routing_ext.rb @@ -1,4 +1,3 @@ - class Object def to_param to_s diff --git a/actionpack/lib/action_controller/routing/segments.rb b/actionpack/lib/action_controller/routing/segments.rb index f0ad066bad..18e76b6b82 100644 --- a/actionpack/lib/action_controller/routing/segments.rb +++ b/actionpack/lib/action_controller/routing/segments.rb @@ -130,6 +130,7 @@ module ActionController def extract_value "#{local_name} = hash[:#{key}] && hash[:#{key}].to_param #{"|| #{default.inspect}" if default}" end + def value_check if default # Then we know it won't be nil "#{value_regexp.inspect} =~ #{local_name}" if regexp @@ -141,6 +142,7 @@ module ActionController "#{local_name} #{"&& #{value_regexp.inspect} =~ #{local_name}" if regexp}" end end + def expiry_statement "expired, hash = true, options if !expired && expire_on[:#{key}]" end @@ -175,7 +177,7 @@ module ActionController end def regexp_chunk - if regexp + if regexp if regexp_has_modifiers? "(#{regexp.to_s})" else @@ -214,7 +216,6 @@ module ActionController def regexp_has_modifiers? regexp.options & (Regexp::IGNORECASE | Regexp::EXTENDED) != 0 end - end class ControllerSegment < DynamicSegment #:nodoc: diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index 84996fd6b1..22e394dc95 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -834,6 +834,7 @@ uses_mocha 'LegacyRouteSet, Route, RouteSet and RouteLoading' do puts "#{1 / per_url} url/s\n\n" end end + def test_time_generation n = 5000 if RunTimeTests diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb index b624005a57..61b8c83ee0 100644 --- a/actionpack/test/controller/test_test.rb +++ b/actionpack/test/controller/test_test.rb @@ -64,7 +64,7 @@ class TestTest < Test::Unit::TestCase HTML end - + def test_xml_output response.content_type = "application/xml" render :text => < { :count => 1, :only => { :tag => "img" } } } } end - + def test_should_not_impose_childless_html_tags_in_xml process :test_xml_output @@ -486,7 +486,7 @@ XML assert_nil @request.env['HTTP_X_REQUESTED_WITH'] end - def test_header_properly_reset_after_get_request + def test_header_properly_reset_after_get_request get :test_params @request.recycle! assert_nil @request.instance_variable_get("@request_method") @@ -532,15 +532,15 @@ XML assert_equal file.path, file.local_path assert_equal expected, file.read end - + def test_test_uploaded_file_with_binary filename = 'mona_lisa.jpg' path = "#{FILES_DIR}/#{filename}" content_type = 'image/png' - + binary_uploaded_file = ActionController::TestUploadedFile.new(path, content_type, :binary) assert_equal File.open(path, READ_BINARY).read, binary_uploaded_file.read - + plain_uploaded_file = ActionController::TestUploadedFile.new(path, content_type) assert_equal File.open(path, READ_PLAIN).read, plain_uploaded_file.read end @@ -549,10 +549,10 @@ XML filename = 'mona_lisa.jpg' path = "#{FILES_DIR}/#{filename}" content_type = 'image/jpg' - + binary_file_upload = fixture_file_upload(path, content_type, :binary) assert_equal File.open(path, READ_BINARY).read, binary_file_upload.read - + plain_file_upload = fixture_file_upload(path, content_type) assert_equal File.open(path, READ_PLAIN).read, plain_file_upload.read end @@ -584,7 +584,7 @@ XML get :test_send_file assert_nothing_raised(NoMethodError) { @response.binary_content } end - + protected def with_foo_routing with_routing do |set| @@ -597,7 +597,6 @@ XML end end - class CleanBacktraceTest < Test::Unit::TestCase def test_should_reraise_the_same_object exception = Test::Unit::AssertionFailedError.new('message') @@ -658,7 +657,7 @@ end class NamedRoutesControllerTest < ActionController::TestCase tests ContentController - + def test_should_be_able_to_use_named_routes_before_a_request_is_done with_routing do |set| set.draw { |map| map.resources :contents }