From 4f2a04cc085b9117e8af8079a95a063f671d7a3d Mon Sep 17 00:00:00 2001 From: Jeremy Kemper <jeremy@bitsweat.net> Date: Sat, 28 Nov 2009 12:49:07 -0800 Subject: Notifications: extract central Notifier, cordon off the internal Fanout implementation, and segregate instrumentation concerns --- actionpack/test/controller/caching_test.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index 3ce90b6ccf..54de920740 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -632,13 +632,15 @@ class FragmentCachingTest < ActionController::TestCase def test_fragment_for_logging fragment_computed = false - ActiveSupport::Notifications.queue.expects(:publish).times(2) + events = [] + ActiveSupport::Notifications.subscribe { |*args| events << args } buffer = 'generated till now -> ' @controller.fragment_for(buffer, 'expensive') { fragment_computed = true } assert fragment_computed assert_equal 'generated till now -> ', buffer + assert_equal [:fragment_exist?, :write_fragment], events.map(&:first) end end -- cgit v1.2.3 From 45d8ff08a449d694f33e42ec2f97515d790e3cf7 Mon Sep 17 00:00:00 2001 From: Yehuda Katz <wycats@Yehuda-Katz.local> Date: Sat, 28 Nov 2009 21:36:58 -0800 Subject: Remove reference to class that doesn't exist (ht: brynary) --- actionpack/lib/action_view.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index e95e84aeb5..f6f7ec0c8c 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -25,7 +25,7 @@ require File.join(File.dirname(__FILE__), "action_pack") module ActionView def self.load_all! - [Context, Base, InlineTemplate, TemplateError] + [Context, Base, TemplateError] end autoload :Base, 'action_view/base' -- cgit v1.2.3 From bb84cab2fceb470cd1e7fa1ceeb5e7c4c764f5de Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp <bryan@brynary.com> Date: Sun, 29 Nov 2009 01:37:50 -0500 Subject: Update reference to deprecated constant to avoid warnings --- actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb index f8f6b424ca..07b4919934 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb @@ -7,7 +7,7 @@ names = traces.collect {|name, trace| name} %> -<p><code>RAILS_ROOT: <%= defined?(RAILS_ROOT) ? RAILS_ROOT : "unset" %></code></p> +<p><code>Rails.root: <%= defined?(Rails) && Rails.respond_to?(:root) ? Rails.root : "unset" %></code></p> <div id="traces"> <% names.each do |name| %> -- cgit v1.2.3 From 3f025e64083c4a0cde4841254a88ef54780824f9 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Sun, 29 Nov 2009 15:23:27 -0600 Subject: Resource collection should be defined before member routes --- actionpack/lib/action_dispatch/routing/mapper.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index cfe7425a61..087d4ab478 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -75,18 +75,18 @@ module ActionDispatch with_scope_level(:resources, :name => singular) do yield if block_given? + collection do + get "", :to => :index, :as => plural + post "", :to => :create + get "new", :to => :new, :as => "new_#{singular}" + end + member do get "", :to => :show, :as => singular put "", :to => :update delete "", :to => :destroy get "edit", :to => :edit, :as => "edit_#{singular}" end - - collection do - get "", :to => :index, :as => plural - post "", :to => :create - get "new", :to => :new, :as => "new_#{singular}" - end end end end -- cgit v1.2.3 From 8815fefd162bbb8f7c0214d48e9f4f2ee47823a4 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Sun, 29 Nov 2009 15:34:46 -0600 Subject: Bump required rack-mount version to 0.2.3 --- actionpack/actionpack.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index ccf6bf1e83..936279ad12 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |s| s.add_dependency('activemodel', '= 3.0.pre') s.add_dependency('rack', '~> 1.0.1') s.add_dependency('rack-test', '~> 0.5.0') - s.add_dependency('rack-mount', '~> 0.2.2') + s.add_dependency('rack-mount', '~> 0.2.3') s.add_dependency('erubis', '~> 2.6.5') s.require_path = 'lib' -- cgit v1.2.3 From 40ae2070d57867bac1c9e7f77c25ac7ac7b5a647 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Sun, 29 Nov 2009 16:59:44 -0600 Subject: Extract Resource and SingletonResource helper objects --- actionpack/lib/action_dispatch/routing/mapper.rb | 112 +++++++++++++++++------ 1 file changed, 84 insertions(+), 28 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 087d4ab478..9b00bd3dc0 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -2,6 +2,71 @@ module ActionDispatch module Routing class Mapper module Resources + class Resource #:nodoc: + attr_reader :plural, :singular + attr_reader :path_prefix, :name_prefix + + def initialize(entities, options = {}) + entities = entities.to_s + + @plural = entities.pluralize + @singular = entities.singularize + + @path_prefix = options[:path_prefix] + @name_prefix = options[:name_prefix] + end + + def name + plural + end + + def controller + plural + end + + def member_name + if name_prefix + "#{name_prefix}_#{singular}" + else + singular + end + end + + def collection_name + if name_prefix + "#{name_prefix}_#{plural}" + else + plural + end + end + + def new_name + if name_prefix + "new_#{name_prefix}_#{singular}" + else + "new_#{singular}" + end + end + + def edit_name + if name_prefix + "edit_#{name_prefix}_#{singular}" + else + "edit_#{singular}" + end + end + end + + class SingletonResource < Resource #:nodoc: + def initialize(entity, options = {}) + super(entity) + end + + def name + singular + end + end + def resource(*resources, &block) options = resources.last.is_a?(Hash) ? resources.pop : {} @@ -11,29 +76,27 @@ module ActionDispatch return self end - resource = resources.pop + name_prefix = @scope[:options][:name_prefix] if @scope[:options] + resource = SingletonResource.new(resources.pop, :name_prefix => name_prefix) if @scope[:scope_level] == :resources member do - resource(resource, options, &block) + resource(resource.name, options, &block) end return self end - singular = resource.to_s - plural = singular.pluralize - - controller(plural) do - namespace(resource) do - with_scope_level(:resource) do + controller(resource.controller) do + namespace(resource.name) do + with_scope_level(:resource, :name => resource.singular) do yield if block_given? - get "", :to => :show, :as => "#{singular}" + get "", :to => :show, :as => resource.member_name post "", :to => :create put "", :to => :update delete "", :to => :destroy - get "new", :to => :new, :as => "new_#{singular}" - get "edit", :to => :edit, :as => "edit_#{singular}" + get "new", :to => :new, :as => resource.new_name + get "edit", :to => :edit, :as => resource.edit_name end end end @@ -50,42 +113,35 @@ module ActionDispatch return self end - resource = resources.pop - - plural = resource.to_s - singular = plural.singularize + name_prefix = @scope[:options][:name_prefix] if @scope[:options] + resource = Resource.new(resources.pop, :name_prefix => name_prefix) if @scope[:scope_level] == :resources parent_resource = @scope[:scope_level_options][:name] with_scope_level(:member) do scope(":#{parent_resource}_id", :name_prefix => parent_resource) do - resources(resource, options, &block) + resources(resource.name, options, &block) end end return self end - if @scope[:options] && (prefix = @scope[:options][:name_prefix]) - plural = "#{prefix}_#{plural}" - singular = "#{prefix}_#{singular}" - end - - controller(resource) do - namespace(resource) do - with_scope_level(:resources, :name => singular) do + controller(resource.controller) do + namespace(resource.name) do + with_scope_level(:resources, :name => resource.singular) do yield if block_given? collection do - get "", :to => :index, :as => plural + get "", :to => :index, :as => resource.collection_name post "", :to => :create - get "new", :to => :new, :as => "new_#{singular}" + get "new", :to => :new, :as => resource.new_name end member do - get "", :to => :show, :as => singular + get "", :to => :show, :as => resource.member_name put "", :to => :update delete "", :to => :destroy - get "edit", :to => :edit, :as => "edit_#{singular}" + get "edit", :to => :edit, :as => resource.edit_name end end end -- cgit v1.2.3 From 5da01a92c741b3a9a020a4dec9ddf120c0484e20 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Sun, 29 Nov 2009 17:01:14 -0600 Subject: Make use of extract_options! --- actionpack/lib/action_dispatch/routing/mapper.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 9b00bd3dc0..9ec85daba8 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -68,7 +68,7 @@ module ActionDispatch end def resource(*resources, &block) - options = resources.last.is_a?(Hash) ? resources.pop : {} + options = resources.extract_options! if resources.length > 1 raise ArgumentError if block_given? @@ -105,7 +105,7 @@ module ActionDispatch end def resources(*resources, &block) - options = resources.last.is_a?(Hash) ? resources.pop : {} + options = resources.extract_options! if resources.length > 1 raise ArgumentError if block_given? @@ -173,7 +173,7 @@ module ActionDispatch end def match(*args) - options = args.last.is_a?(Hash) ? args.pop : {} + options = args.extract_options! args.push(options) case options.delete(:on) @@ -203,7 +203,7 @@ module ActionDispatch module Scoping def scope(*args) - options = args.last.is_a?(Hash) ? args.pop : {} + options = args.extract_options! constraints = options.delete(:constraints) || {} unless constraints.is_a?(Hash) @@ -300,7 +300,7 @@ module ActionDispatch end def match(*args) - options = args.last.is_a?(Hash) ? args.pop : {} + options = args.extract_options! if args.length > 1 args.each { |path| match(path, options) } @@ -384,7 +384,7 @@ module ActionDispatch private def map_method(method, *args, &block) - options = args.last.is_a?(Hash) ? args.pop : {} + options = args.extract_options! options[:via] = method args.push(options) match(*args, &block) -- cgit v1.2.3 From 312c3bfa247249a1562eb9d04c335f4d38a18b28 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Sun, 29 Nov 2009 17:39:37 -0600 Subject: Break down long match routing method --- actionpack/lib/action_dispatch/routing/mapper.rb | 76 +++++++++++++++++------- 1 file changed, 53 insertions(+), 23 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 9ec85daba8..57bbb55c1c 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -202,6 +202,12 @@ module ActionDispatch end module Scoping + def self.extended(object) + object.instance_eval do + @scope = {} + end + end + def scope(*args) options = args.extract_options! @@ -249,9 +255,24 @@ module ActionDispatch def constraints(constraints = {}) scope(:constraints => constraints) { yield } end + + def match(*args) + options = args.extract_options! + options = (@scope[:options] || {}).merge(options) + args.push(options) + super(*args) + end end class Constraints + def new(app, constraints = []) + if constraints.any? + super(app, constraints) + else + app + end + end + def initialize(app, constraints = []) @app, @constraints = app, constraints end @@ -273,7 +294,6 @@ module ActionDispatch def initialize(set) @set = set - @scope = {} extend Scoping extend Resources @@ -313,7 +333,6 @@ module ActionDispatch path = args.first - options = (@scope[:options] || {}).merge(options) conditions, defaults = {}, {} path = nil if path == "" @@ -345,29 +364,12 @@ module ActionDispatch conditions[:request_method] = Regexp.union(*via) end - defaults[:controller] = @scope[:controller].to_s if @scope[:controller] - - if options[:to].respond_to?(:call) - app = options[:to] - defaults.delete(:controller) - defaults.delete(:action) - elsif options[:to].is_a?(String) - defaults[:controller], defaults[:action] = options[:to].split('#') - elsif options[:to].is_a?(Symbol) - defaults[:action] = options[:to].to_s - end - app ||= Routing::RouteSet::Dispatcher.new(:defaults => defaults) + defaults[:controller] ||= @scope[:controller].to_s if @scope[:controller] - if app.is_a?(Routing::RouteSet::Dispatcher) - unless defaults.include?(:controller) || segment_keys.include?("controller") - raise ArgumentError, "missing :controller" - end - unless defaults.include?(:action) || segment_keys.include?("action") - raise ArgumentError, "missing :action" - end - end + app = initialize_app_endpoint(options, defaults) + validate_defaults!(app, defaults, segment_keys) + app = Constraints.new(app, blocks) - app = Constraints.new(app, blocks) if blocks.any? @set.add_route(app, conditions, requirements, defaults, options[:as]) self @@ -383,6 +385,34 @@ module ActionDispatch end private + def initialize_app_endpoint(options, defaults) + app = nil + + if options[:to].respond_to?(:call) + app = options[:to] + defaults.delete(:controller) + defaults.delete(:action) + elsif options[:to].is_a?(String) + defaults[:controller], defaults[:action] = options[:to].split('#') + elsif options[:to].is_a?(Symbol) + defaults[:action] = options[:to].to_s + end + + app || Routing::RouteSet::Dispatcher.new(:defaults => defaults) + end + + def validate_defaults!(app, defaults, segment_keys) + return unless app.is_a?(Routing::RouteSet::Dispatcher) + + unless defaults.include?(:controller) || segment_keys.include?("controller") + raise ArgumentError, "missing :controller" + end + + unless defaults.include?(:action) || segment_keys.include?("action") + raise ArgumentError, "missing :action" + end + end + def map_method(method, *args, &block) options = args.extract_options! options[:via] = method -- cgit v1.2.3 From f69f9820ee84f32bb53d001efd6ebc79517fb0e1 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Sun, 29 Nov 2009 17:45:12 -0600 Subject: Wrap up http related routing helpers --- actionpack/lib/action_dispatch/routing/mapper.rb | 70 +++++++++++++----------- 1 file changed, 37 insertions(+), 33 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 57bbb55c1c..8dfac30ac0 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -264,6 +264,42 @@ module ActionDispatch end end + module HttpHelpers + def get(*args, &block) + map_method(:get, *args, &block) + end + + def post(*args, &block) + map_method(:post, *args, &block) + end + + def put(*args, &block) + map_method(:put, *args, &block) + end + + def delete(*args, &block) + map_method(:delete, *args, &block) + end + + def redirect(path, options = {}) + status = options[:status] || 301 + lambda { |env| + req = Rack::Request.new(env) + url = req.scheme + '://' + req.host + path + [status, {'Location' => url, 'Content-Type' => 'text/html'}, ['Moved Permanently']] + } + end + + private + def map_method(method, *args, &block) + options = args.extract_options! + options[:via] = method + args.push(options) + match(*args, &block) + self + end + end + class Constraints def new(app, constraints = []) if constraints.any? @@ -295,26 +331,11 @@ module ActionDispatch def initialize(set) @set = set + extend HttpHelpers extend Scoping extend Resources end - def get(*args, &block) - map_method(:get, *args, &block) - end - - def post(*args, &block) - map_method(:post, *args, &block) - end - - def put(*args, &block) - map_method(:put, *args, &block) - end - - def delete(*args, &block) - map_method(:delete, *args, &block) - end - def root(options = {}) match '/', options.merge(:as => :root) end @@ -375,15 +396,6 @@ module ActionDispatch self end - def redirect(path, options = {}) - status = options[:status] || 301 - lambda { |env| - req = Rack::Request.new(env) - url = req.scheme + '://' + req.host + path - [status, {'Location' => url, 'Content-Type' => 'text/html'}, ['Moved Permanently']] - } - end - private def initialize_app_endpoint(options, defaults) app = nil @@ -412,14 +424,6 @@ module ActionDispatch raise ArgumentError, "missing :action" end end - - def map_method(method, *args, &block) - options = args.extract_options! - options[:via] = method - args.push(options) - match(*args, &block) - self - end end end end -- cgit v1.2.3 From 075f50d62cd02c2cc14b145cdb34bc9ee85cc83c Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Sun, 29 Nov 2009 18:17:14 -0600 Subject: Fix some nested resource generation tests --- actionpack/lib/action_dispatch/routing/mapper.rb | 15 ++++++++++----- actionpack/test/dispatch/routing_test.rb | 8 ++------ 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 8dfac30ac0..34d75e55b6 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -80,15 +80,19 @@ module ActionDispatch resource = SingletonResource.new(resources.pop, :name_prefix => name_prefix) if @scope[:scope_level] == :resources - member do - resource(resource.name, options, &block) + parent_resource = @scope[:scope_level_options][:name] + parent_named_prefix = @scope[:scope_level_options][:name_prefix] + with_scope_level(:member) do + scope(":#{parent_resource}_id", :name_prefix => parent_named_prefix) do + resource(resource.name, options, &block) + end end return self end controller(resource.controller) do namespace(resource.name) do - with_scope_level(:resource, :name => resource.singular) do + with_scope_level(:resource, :name => resource.singular, :name_prefix => resource.member_name) do yield if block_given? get "", :to => :show, :as => resource.member_name @@ -118,8 +122,9 @@ module ActionDispatch if @scope[:scope_level] == :resources parent_resource = @scope[:scope_level_options][:name] + parent_named_prefix = @scope[:scope_level_options][:name_prefix] with_scope_level(:member) do - scope(":#{parent_resource}_id", :name_prefix => parent_resource) do + scope(":#{parent_resource}_id", :name_prefix => parent_named_prefix) do resources(resource.name, options, &block) end end @@ -128,7 +133,7 @@ module ActionDispatch controller(resource.controller) do namespace(resource.name) do - with_scope_level(:resources, :name => resource.singular) do + with_scope_level(:resources, :name => resource.singular, :name_prefix => resource.member_name) do yield if block_given? collection do diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 496445fc34..b8bcdc2808 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -251,9 +251,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get '/projects/1/companies/1/people' assert_equal 'people#index', @response.body - pending do - assert_equal '/projects/1/companies/1/people', project_company_people_path(:project_id => '1', :company_id => '1') - end + assert_equal '/projects/1/companies/1/people', project_company_people_path(:project_id => '1', :company_id => '1') get '/projects/1/companies/1/avatar' assert_equal 'avatars#show', @response.body @@ -345,9 +343,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get '/projects/1/posts/1/comments' assert_equal 'comments#index', @response.body - pending do - assert_equal '/projects/1/posts/1/comments', project_post_comments_path(:project_id => '1', :post_id => '1') - end + assert_equal '/projects/1/posts/1/comments', project_post_comments_path(:project_id => '1', :post_id => '1') post '/projects/1/posts/1/comments/preview' assert_equal 'comments#preview', @response.body -- cgit v1.2.3 From 6e30361260205cb7029fbc78b4a98b66a884ce45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= <jose.valim@gmail.com> Date: Tue, 1 Dec 2009 13:11:24 -0200 Subject: Allow ActionController::Responder to have a common entry point for all formats. Signed-off-by: Yehuda Katz <wycats@Yehuda-Katz.local> --- actionpack/lib/action_controller/metal/responder.rb | 11 ++++++++--- actionpack/test/controller/mime_responds_test.rb | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/responder.rb b/actionpack/lib/action_controller/metal/responder.rb index e8e88e7479..6c76c57839 100644 --- a/actionpack/lib/action_controller/metal/responder.rb +++ b/actionpack/lib/action_controller/metal/responder.rb @@ -102,9 +102,14 @@ module ActionController #:nodoc: # not defined, call to_format. # def self.call(*args) - responder = new(*args) - method = :"to_#{responder.format}" - responder.respond_to?(method) ? responder.send(method) : responder.to_format + new(*args).respond + end + + # Main entry point for responder responsible to dispatch to the proper format. + # + def respond + method = :"to_#{format}" + respond_to?(method) ? send(method) : to_format end # HTML format does not render the resource, it always attempt to render a diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index fee9cf46f9..c1fa74b8c8 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -507,6 +507,13 @@ class RespondWithController < ActionController::Base end end + def using_responder_with_respond + responder = Class.new(ActionController::Responder) do + def respond; @controller.render :text => "respond #{format}"; end + end + respond_with(Customer.new("david", 13), :responder => responder) + end + protected def _render_js(js, options) @@ -735,6 +742,16 @@ class RespondWithControllerTest < ActionController::TestCase assert_equal "foo - #{[:html].to_s}", @controller.response_body end + def test_respond_as_responder_entry_point + @request.accept = "text/html" + get :using_responder_with_respond + assert_equal "respond html", @response.body + + @request.accept = "application/xml" + get :using_responder_with_respond + assert_equal "respond xml", @response.body + end + def test_clear_respond_to @controller = InheritedRespondWithController.new @request.accept = "text/html" -- cgit v1.2.3 From 0c4990b5f4b8c99ea656170eff9bb9c3490de642 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper <jeremy@bitsweat.net> Date: Tue, 1 Dec 2009 12:19:42 -0800 Subject: Fix caching test to ensure notifications are all delivered --- actionpack/test/controller/caching_test.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'actionpack') diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index 54de920740..682a8f3995 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -640,6 +640,7 @@ class FragmentCachingTest < ActionController::TestCase assert fragment_computed assert_equal 'generated till now -> ', buffer + ActiveSupport::Notifications.notifier.wait assert_equal [:fragment_exist?, :write_fragment], events.map(&:first) end -- cgit v1.2.3 From 61a31f3d3dae55b3ed2a49fafcbfe45b77ea3be2 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Tue, 1 Dec 2009 14:52:19 -0600 Subject: Fix generating params with optional defaults [#3404 state:resolved] --- actionpack/lib/action_dispatch/routing/deprecated_mapper.rb | 2 +- actionpack/test/controller/routing_test.rb | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb b/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb index dd76391870..87dfaba6c7 100644 --- a/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb +++ b/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb @@ -175,7 +175,7 @@ module ActionDispatch optional = false elsif segment =~ /^:(\w+)$/ if defaults.has_key?($1.to_sym) - defaults.delete($1.to_sym) + defaults.delete($1.to_sym) if defaults[$1.to_sym].nil? else optional = false end diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index b5effeda40..97fbd95e73 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -1639,9 +1639,7 @@ class RouteSetTest < ActiveSupport::TestCase map.connect ':controller/:action/:id' end - pending do - assert_equal '/ibocorp', set.generate({:controller => 'ibocorp', :page => 1}) - end + assert_equal '/ibocorp', set.generate({:controller => 'ibocorp', :page => 1}) end def test_generate_with_optional_params_recalls_last_request -- cgit v1.2.3 From 7fe19d415ab80727d685c163d7a0413ca6bfe585 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Tue, 1 Dec 2009 22:22:48 -0600 Subject: Make recognize try to constantize controller to see if it exists --- actionpack/lib/action_dispatch/routing/route_set.rb | 3 +++ actionpack/test/controller/routing_test.rb | 2 -- actionpack/test/lib/controller/fake_controllers.rb | 13 ++++++++++++- 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 79e15edeaa..18e18c5820 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -28,6 +28,7 @@ module ActionDispatch end if env['action_controller.recognize'] + controller(params) [200, {}, params] else controller = controller(params) @@ -41,6 +42,8 @@ module ActionDispatch controller = "#{params[:controller].camelize}Controller" ActiveSupport::Inflector.constantize(controller) end + rescue NameError => e + raise ActionController::RoutingError, e.message end def merge_default_action!(params) diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index 97fbd95e73..84564f4e43 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -1851,11 +1851,9 @@ class RackMountIntegrationTests < ActiveSupport::TestCase assert_equal({:controller => 'posts', :action => 'show_date', :year => '2009'}, @routes.recognize_path('/blog/2009', :method => :get)) assert_equal({:controller => 'posts', :action => 'show_date', :year => '2009', :month => '01'}, @routes.recognize_path('/blog/2009/01', :method => :get)) assert_equal({:controller => 'posts', :action => 'show_date', :year => '2009', :month => '01', :day => '01'}, @routes.recognize_path('/blog/2009/01/01', :method => :get)) - assert_raise(ActionController::ActionControllerError) { @routes.recognize_path('/blog/123456789', :method => :get) } assert_equal({:controller => 'archive', :action => 'index', :year => '2010'}, @routes.recognize_path('/archive/2010')) assert_equal({:controller => 'archive', :action => 'index'}, @routes.recognize_path('/archive')) - assert_raise(ActionController::ActionControllerError) { @routes.recognize_path('/archive/january') } assert_equal({:controller => 'people', :action => 'index'}, @routes.recognize_path('/people', :method => :get)) assert_equal({:controller => 'people', :action => 'index', :format => 'xml'}, @routes.recognize_path('/people.xml', :method => :get)) diff --git a/actionpack/test/lib/controller/fake_controllers.rb b/actionpack/test/lib/controller/fake_controllers.rb index 250327e6dc..09692f77b5 100644 --- a/actionpack/test/lib/controller/fake_controllers.rb +++ b/actionpack/test/lib/controller/fake_controllers.rb @@ -1,37 +1,48 @@ class << Object; alias_method :const_available?, :const_defined?; end class ContentController < ActionController::Base; end -class NotAController; end module Admin class << self; alias_method :const_available?, :const_defined?; end + class AccountsController < ActionController::Base; end class NewsFeedController < ActionController::Base; end class PostsController < ActionController::Base; end class StuffController < ActionController::Base; end class UserController < ActionController::Base; end + class UsersController < ActionController::Base; end end module Api + class UsersController < ActionController::Base; end class ProductsController < ActionController::Base; end end # TODO: Reduce the number of test controllers we use +class AccountController < ActionController::Base; end class AddressesController < ActionController::Base; end +class ArchiveController < ActionController::Base; end class ArticlesController < ActionController::Base; end class BarController < ActionController::Base; end +class BlogController < ActionController::Base; end class BooksController < ActionController::Base; end class BraveController < ActionController::Base; end +class CarsController < ActionController::Base; end +class CcController < ActionController::Base; end class CController < ActionController::Base; end class ElsewhereController < ActionController::Base; end class FooController < ActionController::Base; end +class GeocodeController < ActionController::Base; end class HiController < ActionController::Base; end class ImageController < ActionController::Base; end +class NewsController < ActionController::Base; end class NotesController < ActionController::Base; end class PeopleController < ActionController::Base; end class PostsController < ActionController::Base; end class SessionsController < ActionController::Base; end class StuffController < ActionController::Base; end class SubpathBooksController < ActionController::Base; end +class SymbolsController < ActionController::Base; end +class UserController < ActionController::Base; end class WeblogController < ActionController::Base; end # For speed test -- cgit v1.2.3 From 2fbd6f46fd00a334119f1a25394046963831ce3e Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Tue, 1 Dec 2009 22:48:42 -0600 Subject: Simply track controller namespaces instead of a complete list of possible controllers to route to --- actionpack/lib/action_dispatch/routing.rb | 59 ++++++---------------- .../lib/action_dispatch/routing/route_set.rb | 10 ++-- 2 files changed, 22 insertions(+), 47 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index 9b977800b4..9159bb6395 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -265,6 +265,7 @@ module ActionDispatch SEPARATORS = %w( / . ? ) HTTP_METHODS = [:get, :head, :post, :put, :delete, :options] + CONTROLLER_REGEXP = /[_a-zA-Z0-9]+/ # The root paths which may contain controller files mattr_accessor :controller_paths @@ -277,7 +278,11 @@ module ActionDispatch class << self def controller_constraints - @controller_constraints ||= Regexp.union(*possible_controllers.collect { |n| Regexp.escape(n) }) + @controller_constraints ||= begin + source = controller_namespaces.map { |ns| "#{Regexp.escape(ns)}/#{CONTROLLER_REGEXP.source}" } + source << CONTROLLER_REGEXP.source + Regexp.compile(source.sort.reverse.join('|')) + end end def clear_controller_cache! @@ -285,57 +290,25 @@ module ActionDispatch end private - # Returns the array of controller names currently available to ActionController::Routing. - def possible_controllers - possible_controllers = [] + def controller_namespaces + namespaces = Set.new - # Find any controller classes already in memory + # Find any nested controllers already in memory ActionController::Base.subclasses.each do |klass| controller_name = klass.underscore - controller_name.gsub!(/_controller\Z/, '') - possible_controllers << controller_name + namespaces << controller_name.split('/')[0...-1].join('/') end - # Find controllers in controllers/ directory - paths = controller_paths.select { |path| File.directory?(path) && path != "." } - seen_paths = Hash.new {|h, k| h[k] = true; false} - normalize_paths(paths).each do |load_path| + # Find namespaces in controllers/ directory + controller_paths.each do |load_path| + load_path = File.expand_path(load_path) Dir["#{load_path}/**/*_controller.rb"].collect do |path| - next if seen_paths[path.gsub(%r{^\.[/\\]}, "")] - - controller_name = path[(load_path.length + 1)..-1] - - controller_name.gsub!(/_controller\.rb\Z/, '') - possible_controllers << controller_name + namespaces << File.dirname(path).sub(/#{load_path}\/?/, '') end end - # remove duplicates - possible_controllers.uniq! - - possible_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. - def normalize_paths(paths) - # do the hokey-pokey of path normalization... - paths = paths.collect do |path| - path = path. - gsub("//", "/"). # replace double / chars with a single - gsub("\\\\", "\\"). # replace double \ chars with a single - gsub(%r{(.)[\\/]$}, '\1') # drop final / or \ if path ends with it - - # eliminate .. paths where possible - re = %r{[^/\\]+[/\\]\.\.[/\\]} - path.gsub!(re, "") while path.match(re) - path - end - - # start with longest path, first - paths = paths.uniq.sort_by { |path| - path.length } + namespaces.delete('') + namespaces end end end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 18e18c5820..c2f6531a74 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -27,11 +27,13 @@ module ActionDispatch end end + unless controller = controller(params) + return [417, {}, []] + end + if env['action_controller.recognize'] - controller(params) [200, {}, params] else - controller = controller(params) controller.action(params[:action]).call(env) end end @@ -42,8 +44,8 @@ module ActionDispatch controller = "#{params[:controller].camelize}Controller" ActiveSupport::Inflector.constantize(controller) end - rescue NameError => e - raise ActionController::RoutingError, e.message + rescue NameError + nil end def merge_default_action!(params) -- cgit v1.2.3 From 97be8537ebf33aa0c47fe1c6164e94c24acc3c19 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Tue, 1 Dec 2009 22:58:56 -0600 Subject: Fix @renderer warning --- actionpack/lib/action_view/render/partials.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index 2eb88ae3e5..aeaf1ee4ff 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -181,20 +181,20 @@ module ActionView def initialize(view_context, options, block) @view = view_context @partial_names = PARTIAL_NAMES[@view.controller.class] - + key = Thread.current[:format_locale_key] @templates = TEMPLATES[key] if key - + setup(options, block) end - + def setup(options, block) partial = options[:partial] - + @options = options @locals = options[:locals] || {} @block = block - + if String === partial @object = options[:object] @path = partial @@ -240,7 +240,7 @@ module ActionView segments << template.render(@view, locals) end - + @template = template segments end @@ -294,7 +294,7 @@ module ActionView path && @templates[path] ||= _find_template(path) end end - + def _find_template(path) if controller = @view.controller prefix = controller.controller_path unless path.include?(?/) @@ -319,7 +319,7 @@ module ActionView _evaluate_assigns_and_ivars details = options[:_details] - + # Is this needed self.formats = details[:formats] if details renderer = PartialRenderer.new(self, options, nil) @@ -329,12 +329,12 @@ module ActionView end def _render_partial(options, &block) #:nodoc: - if @renderer + if defined? @renderer @renderer.setup(options, block) else @renderer = PartialRenderer.new(self, options, block) end - + @renderer.render end -- cgit v1.2.3 From 75ae5bb0228ec8d8a144030573db2fd998299042 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Tue, 1 Dec 2009 23:14:03 -0600 Subject: cache_store and page_cache_directory are already defined in caching and pages --- actionpack/lib/action_controller/metal/compatibility.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/compatibility.rb b/actionpack/lib/action_controller/metal/compatibility.rb index c251d79f4e..0c264fcd09 100644 --- a/actionpack/lib/action_controller/metal/compatibility.rb +++ b/actionpack/lib/action_controller/metal/compatibility.rb @@ -46,11 +46,8 @@ module ActionController cattr_accessor :use_accept_header self.use_accept_header = true - cattr_accessor :page_cache_directory self.page_cache_directory = defined?(Rails.public_path) ? Rails.public_path : "" - cattr_reader :cache_store - cattr_accessor :consider_all_requests_local self.consider_all_requests_local = true @@ -116,7 +113,7 @@ module ActionController details[:prefix] = nil if name =~ /\blayouts/ super end - + # Move this into a "don't run in production" module def _default_layout(details, require_layout = false) super -- cgit v1.2.3 From 70d0b7c87a492aef141859127d1b9fec6b4b09f3 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Tue, 1 Dec 2009 23:19:41 -0600 Subject: Fix parens warning in ajax test --- actionpack/test/template/ajax_test.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/template/ajax_test.rb b/actionpack/test/template/ajax_test.rb index 670ba92697..aeb7c09b09 100644 --- a/actionpack/test/template/ajax_test.rb +++ b/actionpack/test/template/ajax_test.rb @@ -6,7 +6,7 @@ class AjaxTestCase < ActiveSupport::TestCase def assert_html(html, matches) matches.each do |match| - assert_match Regexp.new(Regexp.escape(match)), html + assert_match(Regexp.new(Regexp.escape(match)), html) end end @@ -52,18 +52,18 @@ class LinkToRemoteTest < AjaxTestCase test "with a hash for :update" do link = link(:update => {:success => "#posts", :failure => "#error"}) - assert_match /data-update-success="#posts"/, link - assert_match /data-update-failure="#error"/, link + assert_match(/data-update-success="#posts"/, link) + assert_match(/data-update-failure="#error"/, link) end test "with positional parameters" do link = link(:position => :top, :update => "#posts") - assert_match /data\-update\-position="top"/, link + assert_match(/data\-update\-position="top"/, link) end test "with an optional method" do link = link(:method => "delete") - assert_match /data-method="delete"/, link + assert_match(/data-method="delete"/, link) end class LegacyLinkToRemoteTest < AjaxTestCase @@ -99,7 +99,7 @@ class ButtonToRemoteTest < AjaxTestCase button = button({:url => {:action => "whatnot"}}, {:class => "fine"}) [/input/, /class="fine"/, /type="button"/, /value="Remote outpost"/, /data-url="\/whatnot"/].each do |match| - assert_match match, button + assert_match(match, button) end end end -- cgit v1.2.3 From f22db809c9da89adac0be60c5b70f37f75dc8376 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Tue, 1 Dec 2009 23:27:40 -0600 Subject: Response#cache_control is defined later --- actionpack/lib/action_dispatch/http/response.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index b3ed7c9d1a..c651f21f68 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -33,7 +33,6 @@ module ActionDispatch # :nodoc: # end class Response < Rack::Response attr_accessor :request, :blank - attr_reader :cache_control attr_writer :header, :sending_file alias_method :headers=, :header= -- cgit v1.2.3 From ad26f066fe94bad4219f235a0d65190e4d8d15c8 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Tue, 1 Dec 2009 23:29:28 -0600 Subject: Response#write is defined twice (this is why -w is good) --- actionpack/lib/action_dispatch/http/response.rb | 6 ------ 1 file changed, 6 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index c651f21f68..32f9a0031d 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -56,12 +56,6 @@ module ActionDispatch # :nodoc: @cache_control ||= {} end - def write(str) - s = str.to_s - @writer.call s - str - end - def status=(status) @status = status.to_i end -- cgit v1.2.3 From de40bc033a64c7074e01a8e8c585225f4cdaf81e Mon Sep 17 00:00:00 2001 From: Jeremy Kemper <jeremy@bitsweat.net> Date: Wed, 2 Dec 2009 03:23:00 -0800 Subject: Ensure Cache-Control max-age is an integer --- actionpack/lib/action_dispatch/http/response.rb | 2 +- actionpack/test/controller/render_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 32f9a0031d..4f35a00247 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -270,7 +270,7 @@ module ActionDispatch # :nodoc: max_age = control[:max_age] options = [] - options << "max-age=#{max_age}" if max_age + options << "max-age=#{max_age.to_i}" if max_age options << (control[:public] ? "public" : "private") options << "must-revalidate" if control[:must_revalidate] options.concat(extras) if extras diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index b32325fa20..cffa970011 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -54,7 +54,7 @@ class TestController < ActionController::Base end def conditional_hello_with_expires_in - expires_in 1.minute + expires_in 60.1.seconds render :action => 'hello_world' end -- cgit v1.2.3 From 84be6cfb6452a23d5617cd8a8b200d8fb0431d5a Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Wed, 2 Dec 2009 12:33:33 -0600 Subject: Fork rack build nested query to support to_param --- .../lib/action_dispatch/routing/route_set.rb | 45 +++++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index c2f6531a74..f029b634d6 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -379,7 +379,8 @@ module ActionDispatch end recall[:action] = options.delete(:action) if options[:action] == 'index' - parameterize = lambda { |name, value| + opts = {} + opts[:parameterize] = lambda { |name, value| if name == :controller value elsif value.is_a?(Array) @@ -389,7 +390,22 @@ module ActionDispatch end } - path = @set.url(named_route, options, recall, :parameterize => parameterize) + unless result = @set.generate(:path_info, named_route, options, recall, opts) + raise ActionController::RoutingError, "No route matches #{options.inspect}" + end + + uri, params = result + params.each do |k, v| + if v + params[k] = v + else + params.delete(k) + end + end + + uri << "?#{build_nested_query(params)}" if uri && params.any? + path = uri + if path && method == :generate_extras uri = URI(path) extras = uri.query ? @@ -456,6 +472,31 @@ module ActionDispatch def extract_request_environment(request) { :method => request.method } end + + private + def build_nested_query(value, prefix = nil) + case value + when Array + value.map { |v| + build_nested_query(v, "#{prefix}[]") + }.join("&") + when Hash + value.map { |k, v| + build_nested_query(v, prefix ? "#{prefix}[#{k}]" : k) + }.join("&") + when String + raise ArgumentError, "value must be a Hash" if prefix.nil? + "#{Rack::Utils.escape(prefix)}=#{Rack::Utils.escape(value)}" + when NilClass + Rack::Utils.escape(prefix) + else + if value.respond_to?(:to_param) + build_nested_query(value.to_param.to_s, prefix) + else + Rack::Utils.escape(prefix) + end + end + end end end end -- cgit v1.2.3 From c0949cc8f6c73111075e2c5b41f22f4b99a8ab26 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Wed, 2 Dec 2009 12:38:25 -0600 Subject: Rackmount 0.3.0 --- actionpack/actionpack.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index 936279ad12..e191a12997 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |s| s.add_dependency('activemodel', '= 3.0.pre') s.add_dependency('rack', '~> 1.0.1') s.add_dependency('rack-test', '~> 0.5.0') - s.add_dependency('rack-mount', '~> 0.2.3') + s.add_dependency('rack-mount', '~> 0.3.0') s.add_dependency('erubis', '~> 2.6.5') s.require_path = 'lib' -- cgit v1.2.3 From 4dee277a9bc05083de6c831cf9aae0846849ecda Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Wed, 2 Dec 2009 12:46:14 -0600 Subject: Stop escaping "[]" in query string --- actionpack/lib/action_dispatch/routing/route_set.rb | 4 +--- actionpack/test/controller/routing_test.rb | 6 +++--- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index f029b634d6..5e9c36bbaf 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -486,9 +486,7 @@ module ActionDispatch }.join("&") when String raise ArgumentError, "value must be a Hash" if prefix.nil? - "#{Rack::Utils.escape(prefix)}=#{Rack::Utils.escape(value)}" - when NilClass - Rack::Utils.escape(prefix) + "#{prefix}=#{Rack::Utils.escape(value)}" else if value.respond_to?(:to_param) build_nested_query(value.to_param.to_s, prefix) diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index 84564f4e43..b83c5792ba 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -1621,7 +1621,7 @@ class RouteSetTest < ActiveSupport::TestCase end def test_expand_array_build_query_string - assert_uri_equal '/foo?x%5B%5D=1&x%5B%5D=2', default_route_set.generate({:controller => 'foo', :x => [1, 2]}) + assert_uri_equal '/foo?x[]=1&x[]=2', default_route_set.generate({:controller => 'foo', :x => [1, 2]}) end def test_escape_spaces_build_query_string_selected_keys @@ -2012,9 +2012,9 @@ class RackMountIntegrationTests < ActiveSupport::TestCase assert_equal '/posts', @routes.generate({:controller => 'posts'}, {:controller => 'posts', :action => 'index'}) assert_equal '/posts/create', @routes.generate({:action => 'create'}, {:controller => 'posts'}) assert_equal '/posts?foo=bar', @routes.generate(:controller => 'posts', :foo => 'bar') - assert_equal '/posts?foo%5B%5D=bar&foo%5B%5D=baz', @routes.generate(:controller => 'posts', :foo => ['bar', 'baz']) + assert_equal '/posts?foo[]=bar&foo[]=baz', @routes.generate(:controller => 'posts', :foo => ['bar', 'baz']) assert_equal '/posts?page=2', @routes.generate(:controller => 'posts', :page => 2) - assert_equal '/posts?q%5Bfoo%5D%5Ba%5D=b', @routes.generate(:controller => 'posts', :q => { :foo => { :a => 'b'}}) + assert_equal '/posts?q[foo][a]=b', @routes.generate(:controller => 'posts', :q => { :foo => { :a => 'b'}}) assert_equal '/', @routes.generate(:controller => 'news', :action => 'index') assert_equal '/', @routes.generate(:controller => 'news', :action => 'index', :format => nil) -- cgit v1.2.3 From 8db038227ca4cbcba01a86ef5fb94cb13c780463 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Wed, 2 Dec 2009 14:10:22 -0600 Subject: Move controller namespace tracking into route set so it gets reloaded in dev mode --- actionpack/lib/action_dispatch/routing.rb | 41 ---------------------- .../action_dispatch/routing/deprecated_mapper.rb | 2 +- actionpack/lib/action_dispatch/routing/mapper.rb | 2 +- .../lib/action_dispatch/routing/route_set.rb | 36 +++++++++++++++++-- 4 files changed, 36 insertions(+), 45 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index 9159bb6395..e99f979197 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -265,51 +265,10 @@ module ActionDispatch SEPARATORS = %w( / . ? ) HTTP_METHODS = [:get, :head, :post, :put, :delete, :options] - CONTROLLER_REGEXP = /[_a-zA-Z0-9]+/ - - # The root paths which may contain controller files - mattr_accessor :controller_paths - self.controller_paths = [] # A helper module to hold URL related helpers. module Helpers include ActionController::PolymorphicRoutes end - - class << self - def controller_constraints - @controller_constraints ||= begin - source = controller_namespaces.map { |ns| "#{Regexp.escape(ns)}/#{CONTROLLER_REGEXP.source}" } - source << CONTROLLER_REGEXP.source - Regexp.compile(source.sort.reverse.join('|')) - end - end - - def clear_controller_cache! - @controller_constraints = nil - end - - private - def controller_namespaces - namespaces = Set.new - - # Find any nested controllers already in memory - ActionController::Base.subclasses.each do |klass| - controller_name = klass.underscore - namespaces << controller_name.split('/')[0...-1].join('/') - end - - # Find namespaces in controllers/ directory - controller_paths.each do |load_path| - load_path = File.expand_path(load_path) - Dir["#{load_path}/**/*_controller.rb"].collect do |path| - namespaces << File.dirname(path).sub(/#{load_path}\/?/, '') - end - end - - namespaces.delete('') - namespaces - end - end end end diff --git a/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb b/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb index 87dfaba6c7..8ce6b2f6d5 100644 --- a/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb +++ b/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb @@ -113,7 +113,7 @@ module ActionDispatch end end - requirements[:controller] ||= Routing.controller_constraints + requirements[:controller] ||= @set.controller_constraints if defaults[:controller] defaults[:action] ||= 'index' diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 34d75e55b6..400039353c 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -383,7 +383,7 @@ module ActionDispatch constraints.reject! { |k, v| segment_keys.include?(k.to_s) } conditions.merge!(constraints) - requirements[:controller] ||= Routing.controller_constraints + requirements[:controller] ||= @set.controller_constraints if via = options[:via] via = Array(via).map { |m| m.to_s.upcase } diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 5e9c36bbaf..201cf462e4 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -202,10 +202,11 @@ module ActionDispatch end end - attr_accessor :routes, :named_routes, :configuration_files + attr_accessor :routes, :named_routes, :configuration_files, :controller_paths def initialize self.configuration_files = [] + self.controller_paths = [] self.routes = [] self.named_routes = NamedRouteCollection.new @@ -252,7 +253,7 @@ module ActionDispatch def load! # Clear the controller cache so we may discover new ones - Routing.clear_controller_cache! + @controller_constraints = nil load_routes! end @@ -297,6 +298,37 @@ module ActionDispatch routes_changed_at end + CONTROLLER_REGEXP = /[_a-zA-Z0-9]+/ + + def controller_constraints + @controller_constraints ||= begin + source = controller_namespaces.map { |ns| "#{Regexp.escape(ns)}/#{CONTROLLER_REGEXP.source}" } + source << CONTROLLER_REGEXP.source + Regexp.compile(source.sort.reverse.join('|')) + end + end + + def controller_namespaces + namespaces = Set.new + + # Find any nested controllers already in memory + ActionController::Base.subclasses.each do |klass| + controller_name = klass.underscore + namespaces << controller_name.split('/')[0...-1].join('/') + end + + # Find namespaces in controllers/ directory + controller_paths.each do |load_path| + load_path = File.expand_path(load_path) + Dir["#{load_path}/**/*_controller.rb"].collect do |path| + namespaces << File.dirname(path).sub(/#{load_path}\/?/, '') + end + end + + namespaces.delete('') + namespaces + end + def add_route(app, conditions = {}, requirements = {}, defaults = {}, name = nil) route = Route.new(app, conditions, requirements, defaults, name) @set.add_route(*route) -- cgit v1.2.3 From 399909b11c094ab32542d300c72940b1b263b8e6 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Wed, 2 Dec 2009 15:23:26 -0600 Subject: Use to_query in route query string generation --- .../lib/action_dispatch/routing/route_set.rb | 25 +--------------------- 1 file changed, 1 insertion(+), 24 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 201cf462e4..a8073c2105 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -435,7 +435,7 @@ module ActionDispatch end end - uri << "?#{build_nested_query(params)}" if uri && params.any? + uri << "?#{params.to_query}" if uri && params.any? path = uri if path && method == :generate_extras @@ -504,29 +504,6 @@ module ActionDispatch def extract_request_environment(request) { :method => request.method } end - - private - def build_nested_query(value, prefix = nil) - case value - when Array - value.map { |v| - build_nested_query(v, "#{prefix}[]") - }.join("&") - when Hash - value.map { |k, v| - build_nested_query(v, prefix ? "#{prefix}[#{k}]" : k) - }.join("&") - when String - raise ArgumentError, "value must be a Hash" if prefix.nil? - "#{prefix}=#{Rack::Utils.escape(value)}" - else - if value.respond_to?(:to_param) - build_nested_query(value.to_param.to_s, prefix) - else - Rack::Utils.escape(prefix) - end - end - end end end end -- cgit v1.2.3 From c1304098cca8a9247a9ad1461a1a343354650843 Mon Sep 17 00:00:00 2001 From: Carlhuda <carlhuda@engineyard.com> Date: Wed, 2 Dec 2009 20:01:01 -0800 Subject: Reorganize autoloads: * A new module (ActiveSupport::Autoload) is provide that extends autoloading with new behavior. * All autoloads in modules that have extended ActiveSupport::Autoload will be eagerly required in threadsafe environments * Autoloads can optionally leave off the path if the path is the same as full_constant_name.underscore * It is possible to specify that a group of autoloads live under an additional path. For instance, all of ActionDispatch's middlewares are ActionDispatch::MiddlewareName, but they live under "action_dispatch/middlewares/middleware_name" * It is possible to specify that a group of autoloads are all found at the same path. For instance, a number of exceptions might all be declared there. * One consequence of this is that testing-related constants are not autoloaded. To get the testing helpers for a given component, require "component_name/test_case". For instance, "action_controller/test_case". * test_help.rb, which is automatically required by a Rails application's test helper, requires the test_case.rb for all active components, so this change will not be disruptive in existing or new applications. --- actionpack/lib/abstract_controller.rb | 25 +- .../abstract_controller/rendering_controller.rb | 2 +- actionpack/lib/action_controller.rb | 116 +++---- actionpack/lib/action_controller/base.rb | 2 +- actionpack/lib/action_controller/caching.rb | 7 +- .../deprecated/integration_test.rb | 2 + .../lib/action_controller/metal/compatibility.rb | 2 +- actionpack/lib/action_controller/metal/helpers.rb | 2 +- .../lib/action_controller/metal/rescuable.rb | 13 - actionpack/lib/action_controller/metal/rescue.rb | 13 + actionpack/lib/action_controller/test_case.rb | 348 +++++++++++++++++++++ .../lib/action_controller/testing/test_case.rb | 345 -------------------- .../lib/action_controller/vendor/html-scanner.rb | 2 + actionpack/lib/action_dispatch.rb | 41 +-- .../action_dispatch/middleware/show_exceptions.rb | 4 +- actionpack/lib/action_dispatch/test_case.rb | 6 + actionpack/lib/action_view.rb | 26 +- actionpack/lib/action_view/base.rb | 2 +- actionpack/lib/action_view/paths.rb | 2 +- actionpack/lib/action_view/template.rb | 138 ++++++++ actionpack/lib/action_view/template/error.rb | 152 ++++----- actionpack/lib/action_view/template/handler.rb | 47 +-- actionpack/lib/action_view/template/handlers.rb | 96 +++--- .../lib/action_view/template/handlers/builder.rb | 4 +- .../lib/action_view/template/handlers/erb.rb | 4 +- .../lib/action_view/template/handlers/rjs.rb | 4 +- actionpack/lib/action_view/template/resolver.rb | 6 +- actionpack/lib/action_view/template/template.rb | 131 -------- actionpack/lib/action_view/template/text.rb | 70 +++-- actionpack/lib/action_view/test_case.rb | 2 +- actionpack/test/abstract/layouts_test.rb | 26 +- actionpack/test/abstract/render_test.rb | 2 +- actionpack/test/controller/helper_test.rb | 2 +- actionpack/test/controller/layout_test.rb | 2 +- actionpack/test/template/render_test.rb | 8 +- 35 files changed, 848 insertions(+), 806 deletions(-) delete mode 100644 actionpack/lib/action_controller/metal/rescuable.rb create mode 100644 actionpack/lib/action_controller/metal/rescue.rb create mode 100644 actionpack/lib/action_controller/test_case.rb delete mode 100644 actionpack/lib/action_controller/testing/test_case.rb create mode 100644 actionpack/lib/action_dispatch/test_case.rb create mode 100644 actionpack/lib/action_view/template.rb delete mode 100644 actionpack/lib/action_view/template/template.rb (limited to 'actionpack') diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index 1a6c4278c9..688a2fe31c 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -2,15 +2,20 @@ require "active_support/core_ext/module/attr_internal" require "active_support/core_ext/module/delegation" module AbstractController - autoload :Base, "abstract_controller/base" - autoload :Callbacks, "abstract_controller/callbacks" - autoload :Helpers, "abstract_controller/helpers" - autoload :Layouts, "abstract_controller/layouts" - autoload :LocalizedCache, "abstract_controller/localized_cache" - autoload :Logger, "abstract_controller/logger" - autoload :RenderingController, "abstract_controller/rendering_controller" + extend ActiveSupport::Autoload + + autoload :Base + autoload :Callbacks + autoload :Helpers + autoload :Layouts + autoload :LocalizedCache + autoload :Logger + autoload :RenderingController + # === Exceptions - autoload :ActionNotFound, "abstract_controller/exceptions" - autoload :DoubleRenderError, "abstract_controller/exceptions" - autoload :Error, "abstract_controller/exceptions" + autoload_at "abstract_controller/exceptions" do + autoload :ActionNotFound + autoload :DoubleRenderError + autoload :Error + end end diff --git a/actionpack/lib/abstract_controller/rendering_controller.rb b/actionpack/lib/abstract_controller/rendering_controller.rb index 7054b9cf26..777e515d60 100644 --- a/actionpack/lib/abstract_controller/rendering_controller.rb +++ b/actionpack/lib/abstract_controller/rendering_controller.rb @@ -115,7 +115,7 @@ module AbstractController # _partial<TrueClass, FalseClass>:: Whether or not the file to look up is a partial def _determine_template(options) if options.key?(:text) - options[:_template] = ActionView::TextTemplate.new(options[:text], format_for_text) + options[:_template] = ActionView::Template::Text.new(options[:text], format_for_text) elsif options.key?(:inline) handler = ActionView::Template.handler_class_for_extension(options[:type] || "erb") template = ActionView::Template.new(options[:inline], "inline #{options[:inline].inspect}", handler, {}) diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 03a40e4fce..f830223058 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -1,66 +1,72 @@ +require "active_support" + module ActionController - autoload :Base, "action_controller/base" - autoload :Benchmarking, "action_controller/metal/benchmarking" - autoload :ConditionalGet, "action_controller/metal/conditional_get" - autoload :Configuration, "action_controller/metal/configuration" - autoload :Head, "action_controller/metal/head" - autoload :Helpers, "action_controller/metal/helpers" - autoload :HideActions, "action_controller/metal/hide_actions" - autoload :Layouts, "action_controller/metal/layouts" - autoload :Metal, "action_controller/metal" - autoload :Middleware, "action_controller/middleware" - autoload :RackConvenience, "action_controller/metal/rack_convenience" - autoload :Rails2Compatibility, "action_controller/metal/compatibility" - autoload :Redirector, "action_controller/metal/redirector" - autoload :RenderingController, "action_controller/metal/rendering_controller" - autoload :RenderOptions, "action_controller/metal/render_options" - autoload :Rescue, "action_controller/metal/rescuable" - autoload :Responder, "action_controller/metal/responder" - autoload :Session, "action_controller/metal/session" - autoload :Testing, "action_controller/metal/testing" - autoload :UrlFor, "action_controller/metal/url_for" + extend ActiveSupport::Autoload - autoload :Caching, 'action_controller/caching' - autoload :Dispatcher, 'action_controller/dispatch/dispatcher' - autoload :Integration, 'action_controller/deprecated/integration_test' - autoload :IntegrationTest, 'action_controller/deprecated/integration_test' - autoload :MimeResponds, 'action_controller/metal/mime_responds' - autoload :PerformanceTest, 'action_controller/deprecated/performance_test' - autoload :PolymorphicRoutes, 'action_controller/polymorphic_routes' - autoload :RecordIdentifier, 'action_controller/record_identifier' - autoload :Routing, 'action_controller/deprecated' - autoload :SessionManagement, 'action_controller/metal/session_management' - autoload :TestCase, 'action_controller/testing/test_case' - autoload :TestProcess, 'action_controller/testing/process' - autoload :UrlRewriter, 'action_controller/url_rewriter' - autoload :UrlWriter, 'action_controller/url_rewriter' + autoload :Base + autoload :Caching + autoload :PolymorphicRoutes + autoload :RecordIdentifier + autoload :UrlRewriter + autoload :Translation + autoload :Metal + autoload :Middleware - autoload :Verification, 'action_controller/metal/verification' - autoload :Flash, 'action_controller/metal/flash' - autoload :RequestForgeryProtection, 'action_controller/metal/request_forgery_protection' - autoload :Streaming, 'action_controller/metal/streaming' - autoload :HttpAuthentication, 'action_controller/metal/http_authentication' - autoload :FilterParameterLogging, 'action_controller/metal/filter_parameter_logging' - autoload :Translation, 'action_controller/translation' - autoload :Cookies, 'action_controller/metal/cookies' + autoload_under "metal" do + autoload :Benchmarking + autoload :ConditionalGet + autoload :Configuration + autoload :Head + autoload :Helpers + autoload :HideActions + autoload :Layouts + autoload :MimeResponds + autoload :RackConvenience + autoload :Compatibility + autoload :Redirector + autoload :RenderingController + autoload :RenderOptions + autoload :Rescue + autoload :Responder + autoload :Session + autoload :SessionManagement + autoload :UrlFor + autoload :Verification + autoload :Flash + autoload :RequestForgeryProtection + autoload :Streaming + autoload :HttpAuthentication + autoload :FilterParameterLogging + autoload :Cookies + end - autoload :ActionControllerError, 'action_controller/metal/exceptions' - autoload :RenderError, 'action_controller/metal/exceptions' - autoload :RoutingError, 'action_controller/metal/exceptions' - autoload :MethodNotAllowed, 'action_controller/metal/exceptions' - autoload :NotImplemented, 'action_controller/metal/exceptions' - autoload :UnknownController, 'action_controller/metal/exceptions' - autoload :MissingFile, 'action_controller/metal/exceptions' - autoload :RenderError, 'action_controller/metal/exceptions' - autoload :SessionOverflowError, 'action_controller/metal/exceptions' - autoload :UnknownHttpMethod, 'action_controller/metal/exceptions' -end + autoload :Dispatcher, 'action_controller/dispatch/dispatcher' + autoload :PerformanceTest, 'action_controller/deprecated/performance_test' + autoload :Routing, 'action_controller/deprecated' + autoload :Integration, 'action_controller/deprecated/integration_test' + autoload :IntegrationTest, 'action_controller/deprecated/integration_test' -autoload :HTML, 'action_controller/vendor/html-scanner' -autoload :AbstractController, 'abstract_controller' + autoload :UrlWriter, 'action_controller/url_rewriter' + + autoload_at "action_controller/metal/exceptions" do + autoload :ActionControllerError + autoload :RenderError + autoload :RoutingError + autoload :MethodNotAllowed + autoload :NotImplemented + autoload :UnknownController + autoload :MissingFile + autoload :RenderError + autoload :SessionOverflowError + autoload :UnknownHttpMethod + end +end +# All of these simply register additional autoloads +require 'abstract_controller' require 'action_dispatch' require 'action_view' +require 'action_controller/vendor/html-scanner' # Common ActiveSupport usage in ActionController require "active_support/concern" diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 4c026fe5f7..ed3984c9d4 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -24,7 +24,7 @@ module ActionController include ActionController::MimeResponds # Rails 2.x compatibility - include ActionController::Rails2Compatibility + include ActionController::Compatibility include ActionController::Cookies include ActionController::Session diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb index 3caf759032..ad357cceda 100644 --- a/actionpack/lib/action_controller/caching.rb +++ b/actionpack/lib/action_controller/caching.rb @@ -30,10 +30,11 @@ module ActionController #:nodoc: # config.action_controller.cache_store = MyOwnStore.new("parameter") module Caching extend ActiveSupport::Concern + extend ActiveSupport::Autoload - autoload :Actions, 'action_controller/caching/actions' - autoload :Fragments, 'action_controller/caching/fragments' - autoload :Pages, 'action_controller/caching/pages' + autoload :Actions + autoload :Fragments + autoload :Pages autoload :Sweeper, 'action_controller/caching/sweeping' autoload :Sweeping, 'action_controller/caching/sweeping' diff --git a/actionpack/lib/action_controller/deprecated/integration_test.rb b/actionpack/lib/action_controller/deprecated/integration_test.rb index 86336b6bc4..05c8c0f156 100644 --- a/actionpack/lib/action_controller/deprecated/integration_test.rb +++ b/actionpack/lib/action_controller/deprecated/integration_test.rb @@ -1,2 +1,4 @@ +require "action_dispatch/testing/integration" + ActionController::Integration = ActionDispatch::Integration ActionController::IntegrationTest = ActionDispatch::IntegrationTest diff --git a/actionpack/lib/action_controller/metal/compatibility.rb b/actionpack/lib/action_controller/metal/compatibility.rb index 0c264fcd09..a90f798cd5 100644 --- a/actionpack/lib/action_controller/metal/compatibility.rb +++ b/actionpack/lib/action_controller/metal/compatibility.rb @@ -1,5 +1,5 @@ module ActionController - module Rails2Compatibility + module Compatibility extend ActiveSupport::Concern class ::ActionController::ActionControllerError < StandardError #:nodoc: diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb index b4325e24ad..d0402e5bad 100644 --- a/actionpack/lib/action_controller/metal/helpers.rb +++ b/actionpack/lib/action_controller/metal/helpers.rb @@ -52,7 +52,7 @@ module ActionController included do # Set the default directory for helpers extlib_inheritable_accessor(:helpers_dir) do - defined?(Rails) ? "#{Rails.root}/app/helpers" : "app/helpers" + defined?(Rails.root) ? "#{Rails.root}/app/helpers" : "app/helpers" end end diff --git a/actionpack/lib/action_controller/metal/rescuable.rb b/actionpack/lib/action_controller/metal/rescuable.rb deleted file mode 100644 index bbca1b2179..0000000000 --- a/actionpack/lib/action_controller/metal/rescuable.rb +++ /dev/null @@ -1,13 +0,0 @@ -module ActionController #:nodoc: - module Rescue - extend ActiveSupport::Concern - include ActiveSupport::Rescuable - - private - def process_action(*args) - super - rescue Exception => exception - rescue_with_handler(exception) || raise(exception) - end - end -end diff --git a/actionpack/lib/action_controller/metal/rescue.rb b/actionpack/lib/action_controller/metal/rescue.rb new file mode 100644 index 0000000000..bbca1b2179 --- /dev/null +++ b/actionpack/lib/action_controller/metal/rescue.rb @@ -0,0 +1,13 @@ +module ActionController #:nodoc: + module Rescue + extend ActiveSupport::Concern + include ActiveSupport::Rescuable + + private + def process_action(*args) + super + rescue Exception => exception + rescue_with_handler(exception) || raise(exception) + end + end +end diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb new file mode 100644 index 0000000000..7533a22299 --- /dev/null +++ b/actionpack/lib/action_controller/test_case.rb @@ -0,0 +1,348 @@ +require 'active_support/test_case' +require 'rack/session/abstract/id' +require 'action_controller/metal/testing' +require 'action_controller/testing/process' +require 'action_dispatch/test_case' + +module ActionController + class TestRequest < ActionDispatch::TestRequest #:nodoc: + def initialize(env = {}) + super + + self.session = TestSession.new + self.session_options = TestSession::DEFAULT_OPTIONS.merge(:id => ActiveSupport::SecureRandom.hex(16)) + end + + class Result < ::Array #:nodoc: + def to_s() join '/' end + def self.new_escaped(strings) + new strings.collect {|str| URI.unescape str} + end + end + + def assign_parameters(controller_path, action, parameters = {}) + parameters = parameters.symbolize_keys.merge(:controller => controller_path, :action => action) + extra_keys = ActionController::Routing::Routes.extra_keys(parameters) + non_path_parameters = get? ? query_parameters : request_parameters + parameters.each do |key, value| + if value.is_a? Fixnum + value = value.to_s + elsif value.is_a? Array + value = Result.new(value) + end + + if extra_keys.include?(key.to_sym) + non_path_parameters[key] = value + else + path_parameters[key.to_s] = value + end + end + + params = self.request_parameters.dup + + %w(controller action only_path).each do |k| + params.delete(k) + params.delete(k.to_sym) + end + + data = params.to_query + @env['CONTENT_LENGTH'] = data.length.to_s + @env['rack.input'] = StringIO.new(data) + end + + def recycle! + @formats = nil + @env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ } + @env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ } + @env['action_dispatch.request.query_parameters'] = {} + end + end + + class TestResponse < ActionDispatch::TestResponse + def recycle! + @status = 200 + @header = {} + @writer = lambda { |x| @body << x } + @block = nil + @length = 0 + @body = [] + @charset = nil + @content_type = nil + + @request = @template = nil + end + end + + class TestSession < ActionDispatch::Session::AbstractStore::SessionHash #:nodoc: + DEFAULT_OPTIONS = ActionDispatch::Session::AbstractStore::DEFAULT_OPTIONS + + def initialize(session = {}) + replace(session.stringify_keys) + @loaded = true + end + end + + # Superclass for ActionController functional tests. Functional tests allow you to + # test a single controller action per test method. This should not be confused with + # integration tests (see ActionController::IntegrationTest), which are more like + # "stories" that can involve multiple controllers and mutliple actions (i.e. multiple + # different HTTP requests). + # + # == Basic example + # + # Functional tests are written as follows: + # 1. First, one uses the +get+, +post+, +put+, +delete+ or +head+ method to simulate + # an HTTP request. + # 2. Then, one asserts whether the current state is as expected. "State" can be anything: + # the controller's HTTP response, the database contents, etc. + # + # For example: + # + # class BooksControllerTest < ActionController::TestCase + # def test_create + # # Simulate a POST response with the given HTTP parameters. + # post(:create, :book => { :title => "Love Hina" }) + # + # # Assert that the controller tried to redirect us to + # # the created book's URI. + # assert_response :found + # + # # Assert that the controller really put the book in the database. + # assert_not_nil Book.find_by_title("Love Hina") + # end + # end + # + # == Special instance variables + # + # ActionController::TestCase will also automatically provide the following instance + # variables for use in the tests: + # + # <b>@controller</b>:: + # The controller instance that will be tested. + # <b>@request</b>:: + # An ActionController::TestRequest, representing the current HTTP + # request. You can modify this object before sending the HTTP request. For example, + # you might want to set some session properties before sending a GET request. + # <b>@response</b>:: + # An ActionController::TestResponse object, representing the response + # of the last HTTP response. In the above example, <tt>@response</tt> becomes valid + # after calling +post+. If the various assert methods are not sufficient, then you + # may use this object to inspect the HTTP response in detail. + # + # (Earlier versions of Rails required each functional test to subclass + # Test::Unit::TestCase and define @controller, @request, @response in +setup+.) + # + # == Controller is automatically inferred + # + # ActionController::TestCase will automatically infer the controller under test + # from the test class name. If the controller cannot be inferred from the test + # class name, you can explicitly set it with +tests+. + # + # class SpecialEdgeCaseWidgetsControllerTest < ActionController::TestCase + # tests WidgetController + # end + # + # == Testing controller internals + # + # In addition to these specific assertions, you also have easy access to various collections that the regular test/unit assertions + # can be used against. These collections are: + # + # * assigns: Instance variables assigned in the action that are available for the view. + # * session: Objects being saved in the session. + # * flash: The flash objects currently in the session. + # * cookies: Cookies being sent to the user on this request. + # + # These collections can be used just like any other hash: + # + # assert_not_nil assigns(:person) # makes sure that a @person instance variable was set + # assert_equal "Dave", cookies[:name] # makes sure that a cookie called :name was set as "Dave" + # assert flash.empty? # makes sure that there's nothing in the flash + # + # For historic reasons, the assigns hash uses string-based keys. So assigns[:person] won't work, but assigns["person"] will. To + # appease our yearning for symbols, though, an alternative accessor has been devised using a method call instead of index referencing. + # So assigns(:person) will work just like assigns["person"], but again, assigns[:person] will not work. + # + # On top of the collections, you have the complete url that a given action redirected to available in redirect_to_url. + # + # For redirects within the same controller, you can even call follow_redirect and the redirect will be followed, triggering another + # action call which can then be asserted against. + # + # == Manipulating the request collections + # + # The collections described above link to the response, so you can test if what the actions were expected to do happened. But + # sometimes you also want to manipulate these collections in the incoming request. This is really only relevant for sessions + # and cookies, though. For sessions, you just do: + # + # @request.session[:key] = "value" + # @request.cookies["key"] = "value" + # + # == Testing named routes + # + # If you're using named routes, they can be easily tested using the original named routes' methods straight in the test case. + # Example: + # + # assert_redirected_to page_url(:title => 'foo') + class TestCase < ActiveSupport::TestCase + include TestProcess + + # Executes a request simulating GET HTTP method and set/volley the response + def get(action, parameters = nil, session = nil, flash = nil) + process(action, parameters, session, flash, "GET") + end + + # Executes a request simulating POST HTTP method and set/volley the response + def post(action, parameters = nil, session = nil, flash = nil) + process(action, parameters, session, flash, "POST") + end + + # Executes a request simulating PUT HTTP method and set/volley the response + def put(action, parameters = nil, session = nil, flash = nil) + process(action, parameters, session, flash, "PUT") + end + + # Executes a request simulating DELETE HTTP method and set/volley the response + def delete(action, parameters = nil, session = nil, flash = nil) + process(action, parameters, session, flash, "DELETE") + end + + # Executes a request simulating HEAD HTTP method and set/volley the response + def head(action, parameters = nil, session = nil, flash = nil) + process(action, parameters, session, flash, "HEAD") + end + + def xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil) + @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' + @request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ') + returning __send__(request_method, action, parameters, session, flash) do + @request.env.delete 'HTTP_X_REQUESTED_WITH' + @request.env.delete 'HTTP_ACCEPT' + end + end + alias xhr :xml_http_request + + def process(action, parameters = nil, session = nil, flash = nil, http_method = 'GET') + # Sanity check for required instance variables so we can give an + # understandable error message. + %w(@controller @request @response).each do |iv_name| + if !(instance_variable_names.include?(iv_name) || instance_variable_names.include?(iv_name.to_sym)) || instance_variable_get(iv_name).nil? + raise "#{iv_name} is nil: make sure you set it in your test's setup method." + end + end + + @request.recycle! + @response.recycle! + @controller.response_body = nil + @controller.formats = nil + @controller.params = nil + + @html_document = nil + @request.env['REQUEST_METHOD'] = http_method + + parameters ||= {} + @request.assign_parameters(@controller.class.name.underscore.sub(/_controller$/, ''), action.to_s, parameters) + + @request.session = ActionController::TestSession.new(session) unless session.nil? + @request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash + + @controller.request = @request + @controller.params.merge!(parameters) + build_request_uri(action, parameters) + Base.class_eval { include Testing } + @controller.process_with_new_base_test(@request, @response) + @response + end + + include ActionDispatch::Assertions + + # When the request.remote_addr remains the default for testing, which is 0.0.0.0, the exception is simply raised inline + # (bystepping the regular exception handling from rescue_action). If the request.remote_addr is anything else, the regular + # rescue_action process takes place. This means you can test your rescue_action code by setting remote_addr to something else + # than 0.0.0.0. + # + # The exception is stored in the exception accessor for further inspection. + module RaiseActionExceptions + def self.included(base) + base.class_eval do + attr_accessor :exception + protected :exception, :exception= + end + end + + protected + def rescue_action_without_handler(e) + self.exception = e + + if request.remote_addr == "0.0.0.0" + raise(e) + else + super(e) + end + end + end + + setup :setup_controller_request_and_response + + @@controller_class = nil + + class << self + # Sets the controller class name. Useful if the name can't be inferred from test class. + # Expects +controller_class+ as a constant. Example: <tt>tests WidgetController</tt>. + def tests(controller_class) + self.controller_class = controller_class + end + + def controller_class=(new_class) + prepare_controller_class(new_class) if new_class + write_inheritable_attribute(:controller_class, new_class) + end + + def controller_class + if current_controller_class = read_inheritable_attribute(:controller_class) + current_controller_class + else + self.controller_class = determine_default_controller_class(name) + end + end + + def determine_default_controller_class(name) + name.sub(/Test$/, '').constantize + rescue NameError + nil + end + + def prepare_controller_class(new_class) + new_class.send :include, RaiseActionExceptions + end + end + + def setup_controller_request_and_response + @request = TestRequest.new + @response = TestResponse.new + + if klass = self.class.controller_class + @controller ||= klass.new rescue nil + end + + if @controller + @controller.request = @request + @controller.params = {} + end + end + + # Cause the action to be rescued according to the regular rules for rescue_action when the visitor is not local + def rescue_action_in_public! + @request.remote_addr = '208.77.188.166' # example.com + end + + private + def build_request_uri(action, parameters) + unless @request.env['REQUEST_URI'] + options = @controller.__send__(:rewrite_options, parameters) + options.update(:only_path => true, :action => action) + + url = ActionController::UrlRewriter.new(@request, parameters) + @request.request_uri = url.rewrite(options) + end + end + end +end diff --git a/actionpack/lib/action_controller/testing/test_case.rb b/actionpack/lib/action_controller/testing/test_case.rb deleted file mode 100644 index 01a55fe930..0000000000 --- a/actionpack/lib/action_controller/testing/test_case.rb +++ /dev/null @@ -1,345 +0,0 @@ -require 'active_support/test_case' -require 'rack/session/abstract/id' - -module ActionController - class TestRequest < ActionDispatch::TestRequest #:nodoc: - def initialize(env = {}) - super - - self.session = TestSession.new - self.session_options = TestSession::DEFAULT_OPTIONS.merge(:id => ActiveSupport::SecureRandom.hex(16)) - end - - class Result < ::Array #:nodoc: - def to_s() join '/' end - def self.new_escaped(strings) - new strings.collect {|str| URI.unescape str} - end - end - - def assign_parameters(controller_path, action, parameters = {}) - parameters = parameters.symbolize_keys.merge(:controller => controller_path, :action => action) - extra_keys = ActionController::Routing::Routes.extra_keys(parameters) - non_path_parameters = get? ? query_parameters : request_parameters - parameters.each do |key, value| - if value.is_a? Fixnum - value = value.to_s - elsif value.is_a? Array - value = Result.new(value) - end - - if extra_keys.include?(key.to_sym) - non_path_parameters[key] = value - else - path_parameters[key.to_s] = value - end - end - - params = self.request_parameters.dup - - %w(controller action only_path).each do |k| - params.delete(k) - params.delete(k.to_sym) - end - - data = params.to_query - @env['CONTENT_LENGTH'] = data.length.to_s - @env['rack.input'] = StringIO.new(data) - end - - def recycle! - @formats = nil - @env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ } - @env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ } - @env['action_dispatch.request.query_parameters'] = {} - end - end - - class TestResponse < ActionDispatch::TestResponse - def recycle! - @status = 200 - @header = {} - @writer = lambda { |x| @body << x } - @block = nil - @length = 0 - @body = [] - @charset = nil - @content_type = nil - - @request = @template = nil - end - end - - class TestSession < ActionDispatch::Session::AbstractStore::SessionHash #:nodoc: - DEFAULT_OPTIONS = ActionDispatch::Session::AbstractStore::DEFAULT_OPTIONS - - def initialize(session = {}) - replace(session.stringify_keys) - @loaded = true - end - end - - # Superclass for ActionController functional tests. Functional tests allow you to - # test a single controller action per test method. This should not be confused with - # integration tests (see ActionController::IntegrationTest), which are more like - # "stories" that can involve multiple controllers and mutliple actions (i.e. multiple - # different HTTP requests). - # - # == Basic example - # - # Functional tests are written as follows: - # 1. First, one uses the +get+, +post+, +put+, +delete+ or +head+ method to simulate - # an HTTP request. - # 2. Then, one asserts whether the current state is as expected. "State" can be anything: - # the controller's HTTP response, the database contents, etc. - # - # For example: - # - # class BooksControllerTest < ActionController::TestCase - # def test_create - # # Simulate a POST response with the given HTTP parameters. - # post(:create, :book => { :title => "Love Hina" }) - # - # # Assert that the controller tried to redirect us to - # # the created book's URI. - # assert_response :found - # - # # Assert that the controller really put the book in the database. - # assert_not_nil Book.find_by_title("Love Hina") - # end - # end - # - # == Special instance variables - # - # ActionController::TestCase will also automatically provide the following instance - # variables for use in the tests: - # - # <b>@controller</b>:: - # The controller instance that will be tested. - # <b>@request</b>:: - # An ActionController::TestRequest, representing the current HTTP - # request. You can modify this object before sending the HTTP request. For example, - # you might want to set some session properties before sending a GET request. - # <b>@response</b>:: - # An ActionController::TestResponse object, representing the response - # of the last HTTP response. In the above example, <tt>@response</tt> becomes valid - # after calling +post+. If the various assert methods are not sufficient, then you - # may use this object to inspect the HTTP response in detail. - # - # (Earlier versions of Rails required each functional test to subclass - # Test::Unit::TestCase and define @controller, @request, @response in +setup+.) - # - # == Controller is automatically inferred - # - # ActionController::TestCase will automatically infer the controller under test - # from the test class name. If the controller cannot be inferred from the test - # class name, you can explicitly set it with +tests+. - # - # class SpecialEdgeCaseWidgetsControllerTest < ActionController::TestCase - # tests WidgetController - # end - # - # == Testing controller internals - # - # In addition to these specific assertions, you also have easy access to various collections that the regular test/unit assertions - # can be used against. These collections are: - # - # * assigns: Instance variables assigned in the action that are available for the view. - # * session: Objects being saved in the session. - # * flash: The flash objects currently in the session. - # * cookies: Cookies being sent to the user on this request. - # - # These collections can be used just like any other hash: - # - # assert_not_nil assigns(:person) # makes sure that a @person instance variable was set - # assert_equal "Dave", cookies[:name] # makes sure that a cookie called :name was set as "Dave" - # assert flash.empty? # makes sure that there's nothing in the flash - # - # For historic reasons, the assigns hash uses string-based keys. So assigns[:person] won't work, but assigns["person"] will. To - # appease our yearning for symbols, though, an alternative accessor has been devised using a method call instead of index referencing. - # So assigns(:person) will work just like assigns["person"], but again, assigns[:person] will not work. - # - # On top of the collections, you have the complete url that a given action redirected to available in redirect_to_url. - # - # For redirects within the same controller, you can even call follow_redirect and the redirect will be followed, triggering another - # action call which can then be asserted against. - # - # == Manipulating the request collections - # - # The collections described above link to the response, so you can test if what the actions were expected to do happened. But - # sometimes you also want to manipulate these collections in the incoming request. This is really only relevant for sessions - # and cookies, though. For sessions, you just do: - # - # @request.session[:key] = "value" - # @request.cookies["key"] = "value" - # - # == Testing named routes - # - # If you're using named routes, they can be easily tested using the original named routes' methods straight in the test case. - # Example: - # - # assert_redirected_to page_url(:title => 'foo') - class TestCase < ActiveSupport::TestCase - include TestProcess - - # Executes a request simulating GET HTTP method and set/volley the response - def get(action, parameters = nil, session = nil, flash = nil) - process(action, parameters, session, flash, "GET") - end - - # Executes a request simulating POST HTTP method and set/volley the response - def post(action, parameters = nil, session = nil, flash = nil) - process(action, parameters, session, flash, "POST") - end - - # Executes a request simulating PUT HTTP method and set/volley the response - def put(action, parameters = nil, session = nil, flash = nil) - process(action, parameters, session, flash, "PUT") - end - - # Executes a request simulating DELETE HTTP method and set/volley the response - def delete(action, parameters = nil, session = nil, flash = nil) - process(action, parameters, session, flash, "DELETE") - end - - # Executes a request simulating HEAD HTTP method and set/volley the response - def head(action, parameters = nil, session = nil, flash = nil) - process(action, parameters, session, flash, "HEAD") - end - - def xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil) - @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' - @request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ') - returning __send__(request_method, action, parameters, session, flash) do - @request.env.delete 'HTTP_X_REQUESTED_WITH' - @request.env.delete 'HTTP_ACCEPT' - end - end - alias xhr :xml_http_request - - def process(action, parameters = nil, session = nil, flash = nil, http_method = 'GET') - # Sanity check for required instance variables so we can give an - # understandable error message. - %w(@controller @request @response).each do |iv_name| - if !(instance_variable_names.include?(iv_name) || instance_variable_names.include?(iv_name.to_sym)) || instance_variable_get(iv_name).nil? - raise "#{iv_name} is nil: make sure you set it in your test's setup method." - end - end - - @request.recycle! - @response.recycle! - @controller.response_body = nil - @controller.formats = nil - @controller.params = nil - - @html_document = nil - @request.env['REQUEST_METHOD'] = http_method - - parameters ||= {} - @request.assign_parameters(@controller.class.name.underscore.sub(/_controller$/, ''), action.to_s, parameters) - - @request.session = ActionController::TestSession.new(session) unless session.nil? - @request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash - - @controller.request = @request - @controller.params.merge!(parameters) - build_request_uri(action, parameters) - Base.class_eval { include Testing } - @controller.process_with_new_base_test(@request, @response) - @response - end - - include ActionDispatch::Assertions - - # When the request.remote_addr remains the default for testing, which is 0.0.0.0, the exception is simply raised inline - # (bystepping the regular exception handling from rescue_action). If the request.remote_addr is anything else, the regular - # rescue_action process takes place. This means you can test your rescue_action code by setting remote_addr to something else - # than 0.0.0.0. - # - # The exception is stored in the exception accessor for further inspection. - module RaiseActionExceptions - def self.included(base) - base.class_eval do - attr_accessor :exception - protected :exception, :exception= - end - end - - protected - def rescue_action_without_handler(e) - self.exception = e - - if request.remote_addr == "0.0.0.0" - raise(e) - else - super(e) - end - end - end - - setup :setup_controller_request_and_response - - @@controller_class = nil - - class << self - # Sets the controller class name. Useful if the name can't be inferred from test class. - # Expects +controller_class+ as a constant. Example: <tt>tests WidgetController</tt>. - def tests(controller_class) - self.controller_class = controller_class - end - - def controller_class=(new_class) - prepare_controller_class(new_class) if new_class - write_inheritable_attribute(:controller_class, new_class) - end - - def controller_class - if current_controller_class = read_inheritable_attribute(:controller_class) - current_controller_class - else - self.controller_class = determine_default_controller_class(name) - end - end - - def determine_default_controller_class(name) - name.sub(/Test$/, '').constantize - rescue NameError - nil - end - - def prepare_controller_class(new_class) - new_class.send :include, RaiseActionExceptions - end - end - - def setup_controller_request_and_response - @request = TestRequest.new - @response = TestResponse.new - - if klass = self.class.controller_class - @controller ||= klass.new rescue nil - end - - if @controller - @controller.request = @request - @controller.params = {} - end - end - - # Cause the action to be rescued according to the regular rules for rescue_action when the visitor is not local - def rescue_action_in_public! - @request.remote_addr = '208.77.188.166' # example.com - end - - private - def build_request_uri(action, parameters) - unless @request.env['REQUEST_URI'] - options = @controller.__send__(:rewrite_options, parameters) - options.update(:only_path => true, :action => action) - - url = ActionController::UrlRewriter.new(@request, parameters) - @request.request_uri = url.rewrite(options) - end - end - end -end diff --git a/actionpack/lib/action_controller/vendor/html-scanner.rb b/actionpack/lib/action_controller/vendor/html-scanner.rb index f622d195ee..2cb20ddd05 100644 --- a/actionpack/lib/action_controller/vendor/html-scanner.rb +++ b/actionpack/lib/action_controller/vendor/html-scanner.rb @@ -1,6 +1,8 @@ $LOAD_PATH << "#{File.dirname(__FILE__)}/html-scanner" module HTML + extend ActiveSupport::Autoload + autoload :CDATA, 'html/node' autoload :Document, 'html/document' autoload :FullSanitizer, 'html/sanitizer' diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 259814a322..e21dbc59cc 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -28,37 +28,38 @@ module Rack end module ActionDispatch - autoload :Request, 'action_dispatch/http/request' - autoload :Response, 'action_dispatch/http/response' - autoload :StatusCodes, 'action_dispatch/http/status_codes' - autoload :Utils, 'action_dispatch/http/utils' + extend ActiveSupport::Autoload - autoload :Callbacks, 'action_dispatch/middleware/callbacks' - autoload :MiddlewareStack, 'action_dispatch/middleware/stack' - autoload :ParamsParser, 'action_dispatch/middleware/params_parser' - autoload :Rescue, 'action_dispatch/middleware/rescue' - autoload :ShowExceptions, 'action_dispatch/middleware/show_exceptions' - autoload :Static, 'action_dispatch/middleware/static' - autoload :StringCoercion, 'action_dispatch/middleware/string_coercion' + autoload_under "http" do + autoload :Request + autoload :Response + autoload :StatusCodes + autoload :Utils + end - autoload :Routing, 'action_dispatch/routing' + autoload_under "middleware" do + autoload :Callbacks + autoload :ParamsParser + autoload :Rescue + autoload :ShowExceptions + autoload :Static + autoload :StringCoercion + end - autoload :Assertions, 'action_dispatch/testing/assertions' - autoload :Integration, 'action_dispatch/testing/integration' - autoload :IntegrationTest, 'action_dispatch/testing/integration' - autoload :PerformanceTest, 'action_dispatch/testing/performance_test' - autoload :TestRequest, 'action_dispatch/testing/test_request' - autoload :TestResponse, 'action_dispatch/testing/test_response' + autoload :MiddlewareStack, 'action_dispatch/middleware/stack' + autoload :Routing autoload :HTML, 'action_controller/vendor/html-scanner' module Http - autoload :Headers, 'action_dispatch/http/headers' + extend ActiveSupport::Autoload + + autoload :Headers end module Session autoload :AbstractStore, 'action_dispatch/middleware/session/abstract_store' - autoload :CookieStore, 'action_dispatch/middleware/session/cookie_store' + autoload :CookieStore, 'action_dispatch/middleware/session/cookie_store' autoload :MemCacheStore, 'action_dispatch/middleware/session/mem_cache_store' end end diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index 036deec6d2..67c70a0418 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -29,7 +29,7 @@ module ActionDispatch 'ActionView::MissingTemplate' => 'missing_template', 'ActionController::RoutingError' => 'routing_error', ActionController::UnknownAction.name => 'unknown_action', - 'ActionView::TemplateError' => 'template_error' + 'ActionView::Template::Error' => 'template_error' }) FAILSAFE_RESPONSE = [500, {'Content-Type' => 'text/html'}, @@ -119,7 +119,7 @@ module ActionDispatch return unless logger ActiveSupport::Deprecation.silence do - if ActionView::TemplateError === exception + if ActionView::Template::Error === exception logger.fatal(exception.to_s) else logger.fatal( diff --git a/actionpack/lib/action_dispatch/test_case.rb b/actionpack/lib/action_dispatch/test_case.rb new file mode 100644 index 0000000000..afd708f06f --- /dev/null +++ b/actionpack/lib/action_dispatch/test_case.rb @@ -0,0 +1,6 @@ +require "action_dispatch/testing/assertions" +require "action_dispatch/testing/integration" +require "action_dispatch/testing/performance_test" +require "action_dispatch/testing/test_request" +require "action_dispatch/testing/test_response" +require "action_dispatch/testing/integration" \ No newline at end of file diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index f6f7ec0c8c..81ee19d996 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -24,27 +24,25 @@ require File.join(File.dirname(__FILE__), "action_pack") module ActionView - def self.load_all! - [Context, Base, TemplateError] + extend ActiveSupport::Autoload + + autoload :Base + autoload :Context + autoload :Template + autoload :Helpers + autoload :SafeBuffer + + + autoload_under "render" do + autoload :Partials + autoload :Rendering end - autoload :Base, 'action_view/base' - autoload :Context, 'action_view/context' - autoload :Helpers, 'action_view/helpers' autoload :MissingTemplate, 'action_view/base' - autoload :Partials, 'action_view/render/partials' autoload :Resolver, 'action_view/template/resolver' autoload :PathResolver, 'action_view/template/resolver' autoload :PathSet, 'action_view/paths' - autoload :Rendering, 'action_view/render/rendering' - autoload :Template, 'action_view/template/template' - autoload :TemplateError, 'action_view/template/error' - autoload :TemplateHandler, 'action_view/template/handler' - autoload :TemplateHandlers, 'action_view/template/handlers' - autoload :TextTemplate, 'action_view/template/text' - autoload :Helpers, 'action_view/helpers' autoload :FileSystemResolverWithFallback, 'action_view/template/resolver' - autoload :SafeBuffer, 'action_view/safe_buffer' end require 'action_view/erb/util' diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index c33695770f..d69e5109fa 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -196,7 +196,7 @@ module ActionView #:nodoc: end class << self - delegate :erb_trim_mode=, :to => 'ActionView::TemplateHandlers::ERB' + delegate :erb_trim_mode=, :to => 'ActionView::Template::Handlers::ERB' delegate :logger, :to => 'ActionController::Base', :allow_nil => true end diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb index 23bde61f9c..0059b79e5f 100644 --- a/actionpack/lib/action_view/paths.rb +++ b/actionpack/lib/action_view/paths.rb @@ -4,7 +4,7 @@ module ActionView #:nodoc: # TODO: Clean this up if obj.is_a?(String) if cache.nil? - cache = !defined?(Rails) || Rails.application.config.cache_classes + cache = !defined?(Rails.application) || Rails.application.config.cache_classes end FileSystemResolverWithFallback.new(obj, :cache => cache) else diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb new file mode 100644 index 0000000000..210ad508f5 --- /dev/null +++ b/actionpack/lib/action_view/template.rb @@ -0,0 +1,138 @@ +# encoding: utf-8 +# This is so that templates compiled in this file are UTF-8 + +require 'set' +require "action_view/template/resolver" + +module ActionView + class Template + extend ActiveSupport::Autoload + + autoload :Error + autoload :Handler + autoload :Handlers + autoload :Text + + extend Template::Handlers + attr_reader :source, :identifier, :handler, :mime_type, :formats, :details + + def initialize(source, identifier, handler, details) + @source = source + @identifier = identifier + @handler = handler + @details = details + @method_names = {} + + format = details.delete(:format) || begin + # TODO: Clean this up + handler.respond_to?(:default_format) ? handler.default_format.to_sym.to_s : "html" + end + @mime_type = Mime::Type.lookup_by_extension(format.to_s) + @formats = [format.to_sym] + @formats << :html if format == :js + @details[:formats] = Array.wrap(format.to_sym) + end + + def render(view, locals, &block) + ActiveSupport::Notifications.instrument(:render_template, :identifier => identifier) do + method_name = compile(locals, view) + view.send(method_name, locals, &block) + end + rescue Exception => e + if e.is_a?(Template::Error) + e.sub_template_of(self) + raise e + else + raise Template::Error.new(self, view.assigns, e) + end + end + + # TODO: Figure out how to abstract this + def variable_name + @variable_name ||= identifier[%r'_?(\w+)(\.\w+)*$', 1].to_sym + end + + # TODO: Figure out how to abstract this + def counter_name + @counter_name ||= "#{variable_name}_counter".to_sym + end + + # TODO: kill hax + def partial? + @details[:partial] + end + + def inspect + if defined?(Rails.root) + identifier.sub("#{Rails.root}/", '') + else + identifier + end + end + + private + def compile(locals, view) + method_name = build_method_name(locals) + + return method_name if view.respond_to?(method_name) + + locals_code = locals.keys.map! { |key| "#{key} = local_assigns[:#{key}];" }.join + + code = @handler.call(self) + if code.sub!(/\A(#.*coding.*)\n/, '') + encoding_comment = $1 + elsif defined?(Encoding) && Encoding.respond_to?(:default_external) + encoding_comment = "#coding:#{Encoding.default_external}" + end + + source = <<-end_src + def #{method_name}(local_assigns) + old_output_buffer = output_buffer;#{locals_code};#{code} + ensure + self.output_buffer = old_output_buffer + end + end_src + + if encoding_comment + source = "#{encoding_comment}\n#{source}" + line = -1 + else + line = 0 + end + + begin + ActionView::CompiledTemplates.module_eval(source, identifier, line) + method_name + rescue Exception => e # errors from template code + if logger = (view && view.logger) + logger.debug "ERROR: compiling #{method_name} RAISED #{e}" + logger.debug "Function body: #{source}" + logger.debug "Backtrace: #{e.backtrace.join("\n")}" + end + + raise ActionView::Template::Error.new(self, {}, e) + end + end + + class LocalsKey + @hash_keys = Hash.new {|h,k| h[k] = Hash.new {|h,k| h[k] = {} } } + + def self.get(*locals) + @hash_keys[*locals] ||= new(klass, format, locale) + end + + attr_accessor :hash + def initialize(klass, format, locale) + @hash = locals.hash + end + + alias_method :eql?, :equal? + end + + def build_method_name(locals) + # TODO: is locals.keys.hash reliably the same? + @method_names[locals.keys.hash] ||= + "_render_template_#{@identifier.hash}_#{__id__}_#{locals.keys.hash}".gsub('-', "_") + end + end +end diff --git a/actionpack/lib/action_view/template/error.rb b/actionpack/lib/action_view/template/error.rb index aa21606f76..a136d4333b 100644 --- a/actionpack/lib/action_view/template/error.rb +++ b/actionpack/lib/action_view/template/error.rb @@ -1,101 +1,103 @@ require "active_support/core_ext/enumerable" module ActionView - # The TemplateError exception is raised when the compilation of the template fails. This exception then gathers a - # bunch of intimate details and uses it to report a very precise exception message. - class TemplateError < ActionViewError #:nodoc: - SOURCE_CODE_RADIUS = 3 + class Template + # The Template::Error exception is raised when the compilation of the template fails. This exception then gathers a + # bunch of intimate details and uses it to report a very precise exception message. + class Error < ActionViewError #:nodoc: + SOURCE_CODE_RADIUS = 3 - attr_reader :original_exception + attr_reader :original_exception - def initialize(template, assigns, original_exception) - @template, @assigns, @original_exception = template, assigns.dup, original_exception - @backtrace = compute_backtrace - end + def initialize(template, assigns, original_exception) + @template, @assigns, @original_exception = template, assigns.dup, original_exception + @backtrace = compute_backtrace + end - def file_name - @template.identifier - end + def file_name + @template.identifier + end - def message - ActiveSupport::Deprecation.silence { original_exception.message } - end + def message + ActiveSupport::Deprecation.silence { original_exception.message } + end - def clean_backtrace - if defined?(Rails) && Rails.respond_to?(:backtrace_cleaner) - Rails.backtrace_cleaner.clean(original_exception.backtrace) - else - original_exception.backtrace + def clean_backtrace + if defined?(Rails) && Rails.respond_to?(:backtrace_cleaner) + Rails.backtrace_cleaner.clean(original_exception.backtrace) + else + original_exception.backtrace + end end - end - def sub_template_message - if @sub_templates - "Trace of template inclusion: " + - @sub_templates.collect { |template| template.inspect }.join(", ") - else - "" + def sub_template_message + if @sub_templates + "Trace of template inclusion: " + + @sub_templates.collect { |template| template.inspect }.join(", ") + else + "" + end end - end - def source_extract(indentation = 0) - return unless num = line_number - num = num.to_i + def source_extract(indentation = 0) + return unless num = line_number + num = num.to_i - source_code = @template.source.split("\n") + source_code = @template.source.split("\n") - start_on_line = [ num - SOURCE_CODE_RADIUS - 1, 0 ].max - end_on_line = [ num + SOURCE_CODE_RADIUS - 1, source_code.length].min + start_on_line = [ num - SOURCE_CODE_RADIUS - 1, 0 ].max + end_on_line = [ num + SOURCE_CODE_RADIUS - 1, source_code.length].min - indent = ' ' * indentation - line_counter = start_on_line - return unless source_code = source_code[start_on_line..end_on_line] + indent = ' ' * indentation + line_counter = start_on_line + return unless source_code = source_code[start_on_line..end_on_line] - source_code.sum do |line| - line_counter += 1 - "#{indent}#{line_counter}: #{line}\n" + source_code.sum do |line| + line_counter += 1 + "#{indent}#{line_counter}: #{line}\n" + end end - end - def sub_template_of(template_path) - @sub_templates ||= [] - @sub_templates << template_path - end - - def line_number - @line_number ||= - if file_name - regexp = /#{Regexp.escape File.basename(file_name)}:(\d+)/ - - $1 if message =~ regexp or clean_backtrace.find { |line| line =~ regexp } - end - end + def sub_template_of(template_path) + @sub_templates ||= [] + @sub_templates << template_path + end - def to_s - "\n#{self.class} (#{message}) #{source_location}:\n" + - "#{source_extract}\n #{clean_backtrace.join("\n ")}\n\n" - end + def line_number + @line_number ||= + if file_name + regexp = /#{Regexp.escape File.basename(file_name)}:(\d+)/ - # don't do anything nontrivial here. Any raised exception from here becomes fatal - # (and can't be rescued). - def backtrace - @backtrace - end + $1 if message =~ regexp or clean_backtrace.find { |line| line =~ regexp } + end + end - private - def compute_backtrace - [ - "#{source_location.capitalize}\n\n#{source_extract(4)}\n " + - clean_backtrace.join("\n ") - ] + def to_s + "\n#{self.class} (#{message}) #{source_location}:\n" + + "#{source_extract}\n #{clean_backtrace.join("\n ")}\n\n" end - def source_location - if line_number - "on line ##{line_number} of " - else - 'in ' - end + file_name + # don't do anything nontrivial here. Any raised exception from here becomes fatal + # (and can't be rescued). + def backtrace + @backtrace end + + private + def compute_backtrace + [ + "#{source_location.capitalize}\n\n#{source_extract(4)}\n " + + clean_backtrace.join("\n ") + ] + end + + def source_location + if line_number + "on line ##{line_number} of " + else + 'in ' + end + file_name + end + end end end \ No newline at end of file diff --git a/actionpack/lib/action_view/template/handler.rb b/actionpack/lib/action_view/template/handler.rb index 4bf58b9fa8..5a46a27893 100644 --- a/actionpack/lib/action_view/template/handler.rb +++ b/actionpack/lib/action_view/template/handler.rb @@ -3,34 +3,39 @@ require "action_dispatch/http/mime_type" # Legacy TemplateHandler stub module ActionView - module TemplateHandlers #:nodoc: - module Compilable - def self.included(base) - base.extend(ClassMethods) - end + class Template + module Handlers #:nodoc: + module Compilable + def self.included(base) + base.extend(ClassMethods) + end - module ClassMethods - def call(template) - new.compile(template) + module ClassMethods + def call(template) + new.compile(template) + end end - end - def compile(template) - raise "Need to implement #{self.class.name}#compile(template)" - end + def compile(template) + raise "Need to implement #{self.class.name}#compile(template)" + end + end end - end - class TemplateHandler - extlib_inheritable_accessor :default_format - self.default_format = Mime::HTML + class Template::Handler + extlib_inheritable_accessor :default_format + self.default_format = Mime::HTML - def self.call(template) - raise "Need to implement #{self.class.name}#call(template)" - end + def self.call(template) + raise "Need to implement #{self.class.name}#call(template)" + end - def render(template, local_assigns) - raise "Need to implement #{self.class.name}#render(template, local_assigns)" + def render(template, local_assigns) + raise "Need to implement #{self.class.name}#render(template, local_assigns)" + end end end + + TemplateHandlers = Template::Handlers + TemplateHandler = Template::Handler end diff --git a/actionpack/lib/action_view/template/handlers.rb b/actionpack/lib/action_view/template/handlers.rb index faf54b9fe5..35488c0391 100644 --- a/actionpack/lib/action_view/template/handlers.rb +++ b/actionpack/lib/action_view/template/handlers.rb @@ -1,52 +1,54 @@ module ActionView #:nodoc: - module TemplateHandlers #:nodoc: - autoload :ERB, 'action_view/template/handlers/erb' - autoload :RJS, 'action_view/template/handlers/rjs' - autoload :Builder, 'action_view/template/handlers/builder' - - def self.extended(base) - base.register_default_template_handler :erb, TemplateHandlers::ERB - base.register_template_handler :rjs, TemplateHandlers::RJS - base.register_template_handler :builder, TemplateHandlers::Builder - - # TODO: Depreciate old template extensions - base.register_template_handler :rhtml, TemplateHandlers::ERB - base.register_template_handler :rxml, TemplateHandlers::Builder - end - - @@template_handlers = {} - @@default_template_handlers = nil + class Template + module Handlers #:nodoc: + autoload :ERB, 'action_view/template/handlers/erb' + autoload :RJS, 'action_view/template/handlers/rjs' + autoload :Builder, 'action_view/template/handlers/builder' + + def self.extended(base) + base.register_default_template_handler :erb, ERB + base.register_template_handler :rjs, RJS + base.register_template_handler :builder, Builder + + # TODO: Depreciate old template extensions + base.register_template_handler :rhtml, ERB + base.register_template_handler :rxml, Builder + end + + @@template_handlers = {} + @@default_template_handlers = nil - def self.extensions - @@template_handlers.keys - end - - # Register a class that knows how to handle template files with the given - # extension. This can be used to implement new template types. - # The constructor for the class must take the ActiveView::Base instance - # as a parameter, and the class must implement a +render+ method that - # takes the contents of the template to render as well as the Hash of - # local assigns available to the template. The +render+ method ought to - # return the rendered template as a string. - def register_template_handler(extension, klass) - @@template_handlers[extension.to_sym] = klass - end - - def template_handler_extensions - @@template_handlers.keys.map {|key| key.to_s }.sort - end - - def registered_template_handler(extension) - extension && @@template_handlers[extension.to_sym] - end - - def register_default_template_handler(extension, klass) - register_template_handler(extension, klass) - @@default_template_handlers = klass - end - - def handler_class_for_extension(extension) - (extension && registered_template_handler(extension.to_sym)) || @@default_template_handlers + def self.extensions + @@template_handlers.keys + end + + # Register a class that knows how to handle template files with the given + # extension. This can be used to implement new template types. + # The constructor for the class must take the ActiveView::Base instance + # as a parameter, and the class must implement a +render+ method that + # takes the contents of the template to render as well as the Hash of + # local assigns available to the template. The +render+ method ought to + # return the rendered template as a string. + def register_template_handler(extension, klass) + @@template_handlers[extension.to_sym] = klass + end + + def template_handler_extensions + @@template_handlers.keys.map {|key| key.to_s }.sort + end + + def registered_template_handler(extension) + extension && @@template_handlers[extension.to_sym] + end + + def register_default_template_handler(extension, klass) + register_template_handler(extension, klass) + @@default_template_handlers = klass + end + + def handler_class_for_extension(extension) + (extension && registered_template_handler(extension.to_sym)) || @@default_template_handlers + end end end end diff --git a/actionpack/lib/action_view/template/handlers/builder.rb b/actionpack/lib/action_view/template/handlers/builder.rb index 5f381f7bf0..a93cfca8aa 100644 --- a/actionpack/lib/action_view/template/handlers/builder.rb +++ b/actionpack/lib/action_view/template/handlers/builder.rb @@ -1,6 +1,6 @@ module ActionView - module TemplateHandlers - class Builder < TemplateHandler + module Template::Handlers + class Builder < Template::Handler include Compilable self.default_format = Mime::XML diff --git a/actionpack/lib/action_view/template/handlers/erb.rb b/actionpack/lib/action_view/template/handlers/erb.rb index 88aeb4b053..f8e6376589 100644 --- a/actionpack/lib/action_view/template/handlers/erb.rb +++ b/actionpack/lib/action_view/template/handlers/erb.rb @@ -3,7 +3,7 @@ require 'active_support/core_ext/string/output_safety' require 'erubis' module ActionView - module TemplateHandlers + module Template::Handlers class Erubis < ::Erubis::Eruby def add_preamble(src) src << "@output_buffer = ActionView::SafeBuffer.new;" @@ -26,7 +26,7 @@ module ActionView end end - class ERB < TemplateHandler + class ERB < Template::Handler include Compilable ## diff --git a/actionpack/lib/action_view/template/handlers/rjs.rb b/actionpack/lib/action_view/template/handlers/rjs.rb index b1d15dc209..63e7dc0902 100644 --- a/actionpack/lib/action_view/template/handlers/rjs.rb +++ b/actionpack/lib/action_view/template/handlers/rjs.rb @@ -1,6 +1,6 @@ module ActionView - module TemplateHandlers - class RJS < TemplateHandler + module Template::Handlers + class RJS < Template::Handler include Compilable self.default_format = Mime::JS diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index 7336114e1b..a2f4ab2ef5 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -1,6 +1,6 @@ require "pathname" require "active_support/core_ext/class" -require "action_view/template/template" +require "action_view/template" module ActionView # Abstract superclass @@ -20,7 +20,7 @@ module ActionView register_detail(:locale) { [I18n.locale] } register_detail(:formats) { Mime::SET.symbols } register_detail(:handlers, :allow_nil => false) do - TemplateHandlers.extensions + Template::Handlers.extensions end def initialize(options = {}) @@ -65,7 +65,7 @@ module ActionView # as well as incorrectly putting part of the path in the template # name instead of the prefix. def normalize_name(name, prefix) - handlers = TemplateHandlers.extensions.join('|') + handlers = Template::Handlers.extensions.join('|') name = name.to_s.gsub(/\.(?:#{handlers})$/, '') parts = name.split('/') diff --git a/actionpack/lib/action_view/template/template.rb b/actionpack/lib/action_view/template/template.rb deleted file mode 100644 index d1970ca3c7..0000000000 --- a/actionpack/lib/action_view/template/template.rb +++ /dev/null @@ -1,131 +0,0 @@ -# encoding: utf-8 -# This is so that templates compiled in this file are UTF-8 - -require 'set' -require "action_view/template/resolver" - -module ActionView - class Template - extend TemplateHandlers - attr_reader :source, :identifier, :handler, :mime_type, :formats, :details - - def initialize(source, identifier, handler, details) - @source = source - @identifier = identifier - @handler = handler - @details = details - @method_names = {} - - format = details.delete(:format) || begin - # TODO: Clean this up - handler.respond_to?(:default_format) ? handler.default_format.to_sym.to_s : "html" - end - @mime_type = Mime::Type.lookup_by_extension(format.to_s) - @formats = [format.to_sym] - @formats << :html if format == :js - @details[:formats] = Array.wrap(format.to_sym) - end - - def render(view, locals, &block) - ActiveSupport::Notifications.instrument(:render_template, :identifier => identifier) do - method_name = compile(locals, view) - view.send(method_name, locals, &block) - end - rescue Exception => e - if e.is_a?(TemplateError) - e.sub_template_of(self) - raise e - else - raise TemplateError.new(self, view.assigns, e) - end - end - - # TODO: Figure out how to abstract this - def variable_name - @variable_name ||= identifier[%r'_?(\w+)(\.\w+)*$', 1].to_sym - end - - # TODO: Figure out how to abstract this - def counter_name - @counter_name ||= "#{variable_name}_counter".to_sym - end - - # TODO: kill hax - def partial? - @details[:partial] - end - - def inspect - if defined?(Rails.root) - identifier.sub("#{Rails.root}/", '') - else - identifier - end - end - - private - def compile(locals, view) - method_name = build_method_name(locals) - - return method_name if view.respond_to?(method_name) - - locals_code = locals.keys.map! { |key| "#{key} = local_assigns[:#{key}];" }.join - - code = @handler.call(self) - if code.sub!(/\A(#.*coding.*)\n/, '') - encoding_comment = $1 - elsif defined?(Encoding) && Encoding.respond_to?(:default_external) - encoding_comment = "#coding:#{Encoding.default_external}" - end - - source = <<-end_src - def #{method_name}(local_assigns) - old_output_buffer = output_buffer;#{locals_code};#{code} - ensure - self.output_buffer = old_output_buffer - end - end_src - - if encoding_comment - source = "#{encoding_comment}\n#{source}" - line = -1 - else - line = 0 - end - - begin - ActionView::CompiledTemplates.module_eval(source, identifier, line) - method_name - rescue Exception => e # errors from template code - if logger = (view && view.logger) - logger.debug "ERROR: compiling #{method_name} RAISED #{e}" - logger.debug "Function body: #{source}" - logger.debug "Backtrace: #{e.backtrace.join("\n")}" - end - - raise ActionView::TemplateError.new(self, {}, e) - end - end - - class LocalsKey - @hash_keys = Hash.new {|h,k| h[k] = Hash.new {|h,k| h[k] = {} } } - - def self.get(*locals) - @hash_keys[*locals] ||= new(klass, format, locale) - end - - attr_accessor :hash - def initialize(klass, format, locale) - @hash = locals.hash - end - - alias_method :eql?, :equal? - end - - def build_method_name(locals) - # TODO: is locals.keys.hash reliably the same? - @method_names[locals.keys.hash] ||= - "_render_template_#{@identifier.hash}_#{__id__}_#{locals.keys.hash}".gsub('-', "_") - end - end -end diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb index f6e011a5ab..67e086d8bd 100644 --- a/actionpack/lib/action_view/template/text.rb +++ b/actionpack/lib/action_view/template/text.rb @@ -1,38 +1,40 @@ module ActionView #:nodoc: - class TextTemplate < String #:nodoc: - HTML = Mime[:html] - - def initialize(string, content_type = HTML) - super(string.to_s) - @content_type = Mime[content_type] || content_type - end - - def details - {:formats => [@content_type.to_sym]} - end - - def identifier - self - end - - def inspect - 'text template' - end - - def render(*args) - to_s - end - - def mime_type - @content_type - end - - def formats - [mime_type] - end - - def partial? - false + class Template + class Text < String #:nodoc: + HTML = Mime[:html] + + def initialize(string, content_type = HTML) + super(string.to_s) + @content_type = Mime[content_type] || content_type + end + + def details + {:formats => [@content_type.to_sym]} + end + + def identifier + self + end + + def inspect + 'text template' + end + + def render(*args) + to_s + end + + def mime_type + @content_type + end + + def formats + [mime_type] + end + + def partial? + false + end end end end diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index 86bbad822d..ab5bc49cf9 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -1,5 +1,5 @@ require 'active_support/test_case' -require 'action_controller/testing/test_case' +require 'action_controller/test_case' module ActionView class Base diff --git a/actionpack/test/abstract/layouts_test.rb b/actionpack/test/abstract/layouts_test.rb index ae2f1bf1f2..5028c19b80 100644 --- a/actionpack/test/abstract/layouts_test.rb +++ b/actionpack/test/abstract/layouts_test.rb @@ -23,7 +23,7 @@ module AbstractControllerTests self.view_paths = [] def index - render :_template => ActionView::TextTemplate.new("Hello blank!") + render :_template => ActionView::Template::Text.new("Hello blank!") end end @@ -31,19 +31,19 @@ module AbstractControllerTests layout "hello" def index - render :_template => ActionView::TextTemplate.new("Hello string!") + render :_template => ActionView::Template::Text.new("Hello string!") end def overwrite_default - render :_template => ActionView::TextTemplate.new("Hello string!"), :layout => :default + render :_template => ActionView::Template::Text.new("Hello string!"), :layout => :default end def overwrite_false - render :_template => ActionView::TextTemplate.new("Hello string!"), :layout => false + render :_template => ActionView::Template::Text.new("Hello string!"), :layout => false end def overwrite_string - render :_template => ActionView::TextTemplate.new("Hello string!"), :layout => "omg" + render :_template => ActionView::Template::Text.new("Hello string!"), :layout => "omg" end def overwrite_skip @@ -72,7 +72,7 @@ module AbstractControllerTests layout :hello def index - render :_template => ActionView::TextTemplate.new("Hello symbol!") + render :_template => ActionView::Template::Text.new("Hello symbol!") end private def hello @@ -84,7 +84,7 @@ module AbstractControllerTests layout :no_hello def index - render :_template => ActionView::TextTemplate.new("Hello missing symbol!") + render :_template => ActionView::Template::Text.new("Hello missing symbol!") end private def no_hello @@ -96,7 +96,7 @@ module AbstractControllerTests layout :nilz def index - render :_template => ActionView::TextTemplate.new("Hello nilz!") + render :_template => ActionView::Template::Text.new("Hello nilz!") end def nilz() end @@ -106,7 +106,7 @@ module AbstractControllerTests layout :objekt def index - render :_template => ActionView::TextTemplate.new("Hello nilz!") + render :_template => ActionView::Template::Text.new("Hello nilz!") end def objekt @@ -118,7 +118,7 @@ module AbstractControllerTests layout :omg_no_method def index - render :_template => ActionView::TextTemplate.new("Hello boom!") + render :_template => ActionView::Template::Text.new("Hello boom!") end end @@ -126,7 +126,7 @@ module AbstractControllerTests layout "missing" def index - render :_template => ActionView::TextTemplate.new("Hello missing!") + render :_template => ActionView::Template::Text.new("Hello missing!") end end @@ -134,7 +134,7 @@ module AbstractControllerTests layout false def index - render :_template => ActionView::TextTemplate.new("Hello false!") + render :_template => ActionView::Template::Text.new("Hello false!") end end @@ -142,7 +142,7 @@ module AbstractControllerTests layout nil def index - render :_template => ActionView::TextTemplate.new("Hello nil!") + render :_template => ActionView::Template::Text.new("Hello nil!") end end diff --git a/actionpack/test/abstract/render_test.rb b/actionpack/test/abstract/render_test.rb index 45a4763fe4..331cb6f769 100644 --- a/actionpack/test/abstract/render_test.rb +++ b/actionpack/test/abstract/render_test.rb @@ -38,7 +38,7 @@ module AbstractController end def object - render :_template => ActionView::TextTemplate.new("With Object") + render :_template => ActionView::Template::Text.new("With Object") end end diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb index b9be163904..9030e562bb 100644 --- a/actionpack/test/controller/helper_test.rb +++ b/actionpack/test/controller/helper_test.rb @@ -191,7 +191,7 @@ class IsolatedHelpersTest < Test::Unit::TestCase end def test_helper_in_a - assert_raise(ActionView::TemplateError) { call_controller(A, "index") } + assert_raise(ActionView::Template::Error) { call_controller(A, "index") } end def test_helper_in_b diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb index feb2f81cc1..f635253156 100644 --- a/actionpack/test/controller/layout_test.rb +++ b/actionpack/test/controller/layout_test.rb @@ -115,7 +115,7 @@ class RendersNoLayoutController < LayoutTest end class LayoutSetInResponseTest < ActionController::TestCase - include ActionView::TemplateHandlers + include ActionView::Template::Handlers def test_layout_set_when_using_default_layout @controller = DefaultLayoutController.new diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index 35c51ca7ea..fdf3db1cdb 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -106,8 +106,8 @@ module RenderTestCases def test_render_partial_with_errors @view.render(:partial => "test/raise") - flunk "Render did not raise TemplateError" - rescue ActionView::TemplateError => e + flunk "Render did not raise Template::Error" + rescue ActionView::Template::Error => e assert_match "undefined local variable or method `doesnt_exist'", e.message assert_equal "", e.sub_template_message assert_equal "1", e.line_number @@ -116,8 +116,8 @@ module RenderTestCases def test_render_sub_template_with_errors @view.render(:file => "test/sub_template_raise") - flunk "Render did not raise TemplateError" - rescue ActionView::TemplateError => e + flunk "Render did not raise Template::Error" + rescue ActionView::Template::Error => e assert_match "undefined local variable or method `doesnt_exist'", e.message assert_equal "Trace of template inclusion: #{File.expand_path("#{FIXTURE_LOAD_PATH}/test/sub_template_raise.html.erb")}", e.sub_template_message assert_equal "1", e.line_number -- cgit v1.2.3 From 96e0638ce2a287eb5c43266fb4eb3e656e9968cf Mon Sep 17 00:00:00 2001 From: Yehuda Katz <wycats@Yehuda-Katz.local> Date: Thu, 3 Dec 2009 09:06:01 -0800 Subject: Should fix a few Sam Ruby fails. --- .../action_dispatch/testing/performance_test.rb | 24 ++++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/testing/performance_test.rb b/actionpack/lib/action_dispatch/testing/performance_test.rb index b1ed9d31f4..1b9a6c18b7 100644 --- a/actionpack/lib/action_dispatch/testing/performance_test.rb +++ b/actionpack/lib/action_dispatch/testing/performance_test.rb @@ -1,15 +1,17 @@ require 'active_support/testing/performance' require 'active_support/testing/default' -module ActionDispatch - # An integration test that runs a code profiler on your test methods. - # Profiling output for combinations of each test method, measurement, and - # output format are written to your tmp/performance directory. - # - # By default, process_time is measured and both flat and graph_html output - # formats are written, so you'll have two output files per test method. - class PerformanceTest < ActionDispatch::IntegrationTest - include ActiveSupport::Testing::Performance - include ActiveSupport::Testing::Default +if defined?(ActiveSupport::Testing::Performance) + module ActionDispatch + # An integration test that runs a code profiler on your test methods. + # Profiling output for combinations of each test method, measurement, and + # output format are written to your tmp/performance directory. + # + # By default, process_time is measured and both flat and graph_html output + # formats are written, so you'll have two output files per test method. + class PerformanceTest < ActionDispatch::IntegrationTest + include ActiveSupport::Testing::Performance + include ActiveSupport::Testing::Default + end end -end +end \ No newline at end of file -- cgit v1.2.3 From 4663f75f6b1c1e1de35e165cf7d01b83331775ae Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Sat, 5 Dec 2009 13:10:00 -0600 Subject: Update rackmount to fix some pending tests --- actionpack/actionpack.gemspec | 2 +- actionpack/test/controller/routing_test.rb | 22 +++++++++------------- 2 files changed, 10 insertions(+), 14 deletions(-) (limited to 'actionpack') diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index e191a12997..23d478fd44 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |s| s.add_dependency('activemodel', '= 3.0.pre') s.add_dependency('rack', '~> 1.0.1') s.add_dependency('rack-test', '~> 0.5.0') - s.add_dependency('rack-mount', '~> 0.3.0') + s.add_dependency('rack-mount', '~> 0.3.2') s.add_dependency('erubis', '~> 2.6.5') s.require_path = 'lib' diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index b83c5792ba..4382227b47 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -1437,15 +1437,13 @@ class RouteSetTest < ActiveSupport::TestCase )/x} end - pending do - url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'}) - assert_equal "/page/david", url - assert_raise ActionController::RoutingError do - url = set.generate({:controller => 'pages', :action => 'show', :name => 'davidjamis'}) - end - assert_raise ActionController::RoutingError do - url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'}) - end + url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'}) + assert_equal "/page/david", url + assert_raise ActionController::RoutingError do + url = set.generate({:controller => 'pages', :action => 'show', :name => 'davidjamis'}) + end + assert_raise ActionController::RoutingError do + url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'}) end end @@ -1461,10 +1459,8 @@ class RouteSetTest < ActiveSupport::TestCase )/xi} end - pending do - url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'}) - assert_equal "/page/JAMIS", url - end + url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'}) + assert_equal "/page/JAMIS", url end def test_route_requirement_recognize_with_xi_modifiers -- cgit v1.2.3 From 48127c637c3cc0892d49f90a05b0034b9a625d73 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Sun, 6 Dec 2009 20:36:40 -0600 Subject: Deprecate recalling generation params when the defaults are nil --- actionpack/test/controller/routing_test.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index 4382227b47..ff8dfc2573 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -1668,9 +1668,7 @@ class RouteSetTest < ActiveSupport::TestCase assert_equal("/blog/2006/07/25", set.generate({:day => 25}, last_request)) assert_equal("/blog/2005", set.generate({:year => 2005}, last_request)) assert_equal("/blog/show/123", set.generate({:action => "show" , :id => 123}, last_request)) - pending do - assert_equal("/blog/2006/07/28", set.generate({:year => 2006}, last_request)) - end + assert_equal("/blog/2006", set.generate({:year => 2006}, last_request)) assert_equal("/blog/2006", set.generate({:year => 2006, :month => nil}, last_request)) end -- cgit v1.2.3 From 324fa688fcd8f5b6a8e9a0226b0cb3d2829e122c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= <jose.valim@gmail.com> Date: Wed, 2 Dec 2009 22:48:05 -0200 Subject: Make controller.flash public to be used in responders. Signed-off-by: Yehuda Katz <wycats@Yehuda-Katz.local> --- actionpack/lib/action_controller/metal/flash.rb | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/flash.rb b/actionpack/lib/action_controller/metal/flash.rb index f43900faa0..b2d44c6c63 100644 --- a/actionpack/lib/action_controller/metal/flash.rb +++ b/actionpack/lib/action_controller/metal/flash.rb @@ -133,8 +133,20 @@ module ActionController #:nodoc: Array(key || keys).each { |k| used ? @used << k : @used.delete(k) } return key ? self[key] : self end + end + + # Access the contents of the flash. Use <tt>flash["notice"]</tt> to + # read a notice you put there or <tt>flash["notice"] = "hello"</tt> + # to put a new one. + def flash #:doc: + unless @_flash + @_flash = session["flash"] || FlashHash.new + @_flash.sweep end + @_flash + end + protected def process_action(method_name) super @@ -146,17 +158,5 @@ module ActionController #:nodoc: super @_flash = nil end - - # Access the contents of the flash. Use <tt>flash["notice"]</tt> to - # read a notice you put there or <tt>flash["notice"] = "hello"</tt> - # to put a new one. - def flash #:doc: - unless @_flash - @_flash = session["flash"] || FlashHash.new - @_flash.sweep - end - - @_flash - end end end -- cgit v1.2.3 From 2ecfa817c95f98247d1bd7fb28b208d3f950b43f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= <jose.valim@gmail.com> Date: Wed, 2 Dec 2009 22:47:09 -0200 Subject: Responder redirects to resource if destroy fails. Signed-off-by: Yehuda Katz <wycats@Yehuda-Katz.local> --- .../lib/action_controller/metal/responder.rb | 9 +++-- actionpack/test/controller/mime_responds_test.rb | 42 +++++++++++++++++----- 2 files changed, 41 insertions(+), 10 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/responder.rb b/actionpack/lib/action_controller/metal/responder.rb index 6c76c57839..cb0e600871 100644 --- a/actionpack/lib/action_controller/metal/responder.rb +++ b/actionpack/lib/action_controller/metal/responder.rb @@ -80,6 +80,11 @@ module ActionController #:nodoc: class Responder attr_reader :controller, :request, :format, :resource, :resources, :options + ACTIONS_FOR_VERBS = { + :post => :new, + :put => :edit + } + def initialize(controller, resources, options={}) @controller = controller @request = controller.request @@ -138,7 +143,7 @@ module ActionController #:nodoc: def navigation_behavior(error) if get? raise error - elsif has_errors? + elsif has_errors? && default_action render :action => default_action else redirect_to resource_location @@ -209,7 +214,7 @@ module ActionController #:nodoc: # the verb is post. # def default_action - @action || (request.post? ? :new : :edit) + @action ||= ACTIONS_FOR_VERBS[request.method] end end end diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index c1fa74b8c8..c857d85c39 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -599,14 +599,18 @@ class RespondWithControllerTest < ActionController::TestCase end end - def test_using_resource_for_post_with_html + def test_using_resource_for_post_with_html_redirects_on_success with_test_route_set do post :using_resource assert_equal "text/html", @response.content_type assert_equal 302, @response.status assert_equal "http://www.example.com/customers/13", @response.location assert @response.redirect? + end + end + def test_using_resource_for_post_with_html_rerender_on_failure + with_test_route_set do errors = { :name => :invalid } Customer.any_instance.stubs(:errors).returns(errors) post :using_resource @@ -617,16 +621,20 @@ class RespondWithControllerTest < ActionController::TestCase end end - def test_using_resource_for_post_with_xml + def test_using_resource_for_post_with_xml_yields_created_on_success with_test_route_set do @request.accept = "application/xml" - post :using_resource assert_equal "application/xml", @response.content_type assert_equal 201, @response.status assert_equal "<name>david</name>", @response.body assert_equal "http://www.example.com/customers/13", @response.location + end + end + def test_using_resource_for_post_with_xml_yields_unprocessable_entity_on_failure + with_test_route_set do + @request.accept = "application/xml" errors = { :name => :invalid } Customer.any_instance.stubs(:errors).returns(errors) post :using_resource @@ -637,14 +645,18 @@ class RespondWithControllerTest < ActionController::TestCase end end - def test_using_resource_for_put_with_html + def test_using_resource_for_put_with_html_redirects_on_success with_test_route_set do put :using_resource assert_equal "text/html", @response.content_type assert_equal 302, @response.status assert_equal "http://www.example.com/customers/13", @response.location assert @response.redirect? + end + end + def test_using_resource_for_put_with_html_rerender_on_failure + with_test_route_set do errors = { :name => :invalid } Customer.any_instance.stubs(:errors).returns(errors) put :using_resource @@ -655,14 +667,16 @@ class RespondWithControllerTest < ActionController::TestCase end end - def test_using_resource_for_put_with_xml + def test_using_resource_for_put_with_xml_yields_ok_on_success @request.accept = "application/xml" - put :using_resource assert_equal "application/xml", @response.content_type assert_equal 200, @response.status assert_equal " ", @response.body + end + def test_using_resource_for_put_with_xml_yields_unprocessable_entity_on_failure + @request.accept = "application/xml" errors = { :name => :invalid } Customer.any_instance.stubs(:errors).returns(errors) put :using_resource @@ -672,7 +686,7 @@ class RespondWithControllerTest < ActionController::TestCase assert_nil @response.location end - def test_using_resource_for_delete_with_html + def test_using_resource_for_delete_with_html_redirects_on_success with_test_route_set do Customer.any_instance.stubs(:destroyed?).returns(true) delete :using_resource @@ -682,7 +696,7 @@ class RespondWithControllerTest < ActionController::TestCase end end - def test_using_resource_for_delete_with_xml + def test_using_resource_for_delete_with_xml_yields_ok_on_success Customer.any_instance.stubs(:destroyed?).returns(true) @request.accept = "application/xml" delete :using_resource @@ -691,6 +705,18 @@ class RespondWithControllerTest < ActionController::TestCase assert_equal " ", @response.body end + def test_using_resource_for_delete_with_html_redirects_on_failure + with_test_route_set do + errors = { :name => :invalid } + Customer.any_instance.stubs(:errors).returns(errors) + Customer.any_instance.stubs(:destroyed?).returns(false) + delete :using_resource + assert_equal "text/html", @response.content_type + assert_equal 302, @response.status + assert_equal "http://www.example.com/customers/13", @response.location + end + end + def test_using_resource_with_parent_for_get @request.accept = "application/xml" get :using_resource_with_parent -- cgit v1.2.3 From 66375434b6c7e03a396bbeda3f7029dea2a59f23 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Mon, 7 Dec 2009 17:22:09 -0600 Subject: Pass symbol in as route name when match is used with a symbol --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 400039353c..d9724161a9 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -349,7 +349,7 @@ module ActionDispatch options = args.extract_options! if args.length > 1 - args.each { |path| match(path, options) } + args.each { |path| match(path, options.reverse_merge(:as => path.to_sym)) } return self end -- cgit v1.2.3 From 40ad54e3811913c2bc60c7ee292fa48862f12001 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Mon, 7 Dec 2009 18:28:02 -0600 Subject: Allow scope to take :path and :controller options --- actionpack/lib/action_dispatch/routing/mapper.rb | 34 +++++++++++++++--------- actionpack/test/dispatch/routing_test.rb | 2 +- 2 files changed, 22 insertions(+), 14 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index d9724161a9..fab8a227bf 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -216,6 +216,27 @@ module ActionDispatch def scope(*args) options = args.extract_options! + case args.first + when String + options[:path] = args.first + when Symbol + options[:controller] = args.first + end + + if path = options.delete(:path) + path_set = true + path, @scope[:path] = @scope[:path], "#{@scope[:path]}#{Rack::Mount::Utils.normalize_path(path)}" + else + path_set = false + end + + if controller = options.delete(:controller) + controller_set = true + controller, @scope[:controller] = @scope[:controller], controller + else + controller_set = false + end + constraints = options.delete(:constraints) || {} unless constraints.is_a?(Hash) block, constraints = constraints, {} @@ -225,19 +246,6 @@ module ActionDispatch options, @scope[:options] = @scope[:options], (@scope[:options] || {}).merge(options) - path_set = controller_set = false - - case args.first - when String - path_set = true - path = args.first - path, @scope[:path] = @scope[:path], "#{@scope[:path]}#{Rack::Mount::Utils.normalize_path(path)}" - when Symbol - controller_set = true - controller = args.first - controller, @scope[:controller] = @scope[:controller], controller - end - yield self diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index b8bcdc2808..85616b5a59 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -94,7 +94,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest controller :articles do scope 'articles' do - scope ':title', :title => /[a-z]+/, :as => :with_title do + scope :path => ':title', :title => /[a-z]+/, :as => :with_title do match ':id', :to => :with_id end end -- cgit v1.2.3 From e8489b43e2746d9b3605eef86731232fa823ce69 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Mon, 7 Dec 2009 19:24:33 -0600 Subject: Allow name_prefix to be pass into scope --- actionpack/lib/action_dispatch/routing/mapper.rb | 60 ++++++++---------------- actionpack/test/dispatch/routing_test.rb | 12 ++--- 2 files changed, 24 insertions(+), 48 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index fab8a227bf..abcaa529ae 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -4,16 +4,12 @@ module ActionDispatch module Resources class Resource #:nodoc: attr_reader :plural, :singular - attr_reader :path_prefix, :name_prefix def initialize(entities, options = {}) entities = entities.to_s @plural = entities.pluralize @singular = entities.singularize - - @path_prefix = options[:path_prefix] - @name_prefix = options[:name_prefix] end def name @@ -25,41 +21,17 @@ module ActionDispatch end def member_name - if name_prefix - "#{name_prefix}_#{singular}" - else - singular - end + singular end def collection_name - if name_prefix - "#{name_prefix}_#{plural}" - else - plural - end - end - - def new_name - if name_prefix - "new_#{name_prefix}_#{singular}" - else - "new_#{singular}" - end - end - - def edit_name - if name_prefix - "edit_#{name_prefix}_#{singular}" - else - "edit_#{singular}" - end + plural end end class SingletonResource < Resource #:nodoc: def initialize(entity, options = {}) - super(entity) + super end def name @@ -76,8 +48,7 @@ module ActionDispatch return self end - name_prefix = @scope[:options][:name_prefix] if @scope[:options] - resource = SingletonResource.new(resources.pop, :name_prefix => name_prefix) + resource = SingletonResource.new(resources.pop) if @scope[:scope_level] == :resources parent_resource = @scope[:scope_level_options][:name] @@ -99,8 +70,8 @@ module ActionDispatch post "", :to => :create put "", :to => :update delete "", :to => :destroy - get "new", :to => :new, :as => resource.new_name - get "edit", :to => :edit, :as => resource.edit_name + get "new", :to => :new, :as => "new_#{resource.singular}" + get "edit", :to => :edit, :as => "edit_#{resource.singular}" end end end @@ -117,8 +88,7 @@ module ActionDispatch return self end - name_prefix = @scope[:options][:name_prefix] if @scope[:options] - resource = Resource.new(resources.pop, :name_prefix => name_prefix) + resource = Resource.new(resources.pop) if @scope[:scope_level] == :resources parent_resource = @scope[:scope_level_options][:name] @@ -139,14 +109,14 @@ module ActionDispatch collection do get "", :to => :index, :as => resource.collection_name post "", :to => :create - get "new", :to => :new, :as => resource.new_name + get "new", :to => :new, :as => "new_#{resource.singular}" end member do get "", :to => :show, :as => resource.member_name put "", :to => :update delete "", :to => :destroy - get "edit", :to => :edit, :as => resource.edit_name + get "edit", :to => :edit, :as => "edit_#{resource.singular}" end end end @@ -230,6 +200,13 @@ module ActionDispatch path_set = false end + if name_prefix = options.delete(:name_prefix) + name_prefix_set = true + name_prefix, @scope[:name_prefix] = @scope[:name_prefix], (@scope[:name_prefix] ? "#{@scope[:name_prefix]}_#{name_prefix}" : name_prefix) + else + name_prefix_set = false + end + if controller = options.delete(:controller) controller_set = true controller, @scope[:controller] = @scope[:controller], controller @@ -251,6 +228,7 @@ module ActionDispatch self ensure @scope[:path] = path if path_set + @scope[:name_prefix] = name_prefix if name_prefix_set @scope[:controller] = controller if controller_set @scope[:options] = options @scope[:blocks] = blocks @@ -404,7 +382,9 @@ module ActionDispatch validate_defaults!(app, defaults, segment_keys) app = Constraints.new(app, blocks) - @set.add_route(app, conditions, requirements, defaults, options[:as]) + name = @scope[:name_prefix] ? "#{@scope[:name_prefix]}_#{options[:as]}" : options[:as] + + @set.add_route(app, conditions, requirements, defaults, name) self end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 85616b5a59..86cf2ce335 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -93,7 +93,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end controller :articles do - scope 'articles' do + scope 'articles', :name_prefix => 'article' do scope :path => ':title', :title => /[a-z]+/, :as => :with_title do match ':id', :to => :with_id end @@ -255,9 +255,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get '/projects/1/companies/1/avatar' assert_equal 'avatars#show', @response.body - pending do - assert_equal '/projects/1/companies/1/avatar', project_company_avatar_path(:project_id => '1', :company_id => '1') - end + assert_equal '/projects/1/companies/1/avatar', project_company_avatar_path(:project_id => '1', :company_id => '1') end end @@ -337,9 +335,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get '/projects/1/posts/1/subscription' assert_equal 'subscriptions#show', @response.body - pending do - assert_equal '/projects/1/posts/1/subscription', project_post_subscription_path(:project_id => '1', :post_id => '1') - end + assert_equal '/projects/1/posts/1/subscription', project_post_subscription_path(:project_id => '1', :post_id => '1') get '/projects/1/posts/1/comments' assert_equal 'comments#index', @response.body @@ -407,7 +403,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_raise(ActionController::RoutingError) { get '/articles/123/1' } - assert_equal '/articles/rails/1', with_title_path(:title => 'rails', :id => 1) + assert_equal '/articles/rails/1', article_with_title_path(:title => 'rails', :id => 1) end end -- cgit v1.2.3 From 5835447b6fbc956f22011fc33bcc882db144c7c1 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Mon, 7 Dec 2009 19:31:29 -0600 Subject: named_prefix doesn't join with "_" --- actionpack/lib/action_dispatch/routing/mapper.rb | 8 ++++---- actionpack/test/dispatch/routing_test.rb | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index abcaa529ae..7eb648cedf 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -63,7 +63,7 @@ module ActionDispatch controller(resource.controller) do namespace(resource.name) do - with_scope_level(:resource, :name => resource.singular, :name_prefix => resource.member_name) do + with_scope_level(:resource, :name => resource.singular, :name_prefix => "#{resource.member_name}_") do yield if block_given? get "", :to => :show, :as => resource.member_name @@ -103,7 +103,7 @@ module ActionDispatch controller(resource.controller) do namespace(resource.name) do - with_scope_level(:resources, :name => resource.singular, :name_prefix => resource.member_name) do + with_scope_level(:resources, :name => resource.singular, :name_prefix => "#{resource.member_name}_") do yield if block_given? collection do @@ -202,7 +202,7 @@ module ActionDispatch if name_prefix = options.delete(:name_prefix) name_prefix_set = true - name_prefix, @scope[:name_prefix] = @scope[:name_prefix], (@scope[:name_prefix] ? "#{@scope[:name_prefix]}_#{name_prefix}" : name_prefix) + name_prefix, @scope[:name_prefix] = @scope[:name_prefix], (@scope[:name_prefix] ? "#{@scope[:name_prefix]}#{name_prefix}" : name_prefix) else name_prefix_set = false end @@ -382,7 +382,7 @@ module ActionDispatch validate_defaults!(app, defaults, segment_keys) app = Constraints.new(app, blocks) - name = @scope[:name_prefix] ? "#{@scope[:name_prefix]}_#{options[:as]}" : options[:as] + name = @scope[:name_prefix] ? "#{@scope[:name_prefix]}#{options[:as]}" : options[:as] @set.add_route(app, conditions, requirements, defaults, name) diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 86cf2ce335..0a35868d7c 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -93,7 +93,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end controller :articles do - scope 'articles', :name_prefix => 'article' do + scope 'articles', :name_prefix => 'article_' do scope :path => ':title', :title => /[a-z]+/, :as => :with_title do match ':id', :to => :with_id end -- cgit v1.2.3 From e600b41c7f2029b1fb4b75b90acc3379acf95d2b Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Mon, 7 Dec 2009 19:47:47 -0600 Subject: Cleanup resource scoping by passing down the parent resource object in the scope --- actionpack/lib/action_dispatch/routing/mapper.rb | 31 +++++++++++++++--------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 7eb648cedf..9ca4e16802 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -27,6 +27,14 @@ module ActionDispatch def collection_name plural end + + def id_segment + ":#{singular}_id" + end + + def member_name_prefix + "#{member_name}_" + end end class SingletonResource < Resource #:nodoc: @@ -51,10 +59,8 @@ module ActionDispatch resource = SingletonResource.new(resources.pop) if @scope[:scope_level] == :resources - parent_resource = @scope[:scope_level_options][:name] - parent_named_prefix = @scope[:scope_level_options][:name_prefix] with_scope_level(:member) do - scope(":#{parent_resource}_id", :name_prefix => parent_named_prefix) do + scope(parent_resource.id_segment, :name_prefix => parent_resource.member_name_prefix) do resource(resource.name, options, &block) end end @@ -63,7 +69,7 @@ module ActionDispatch controller(resource.controller) do namespace(resource.name) do - with_scope_level(:resource, :name => resource.singular, :name_prefix => "#{resource.member_name}_") do + with_scope_level(:resource, resource) do yield if block_given? get "", :to => :show, :as => resource.member_name @@ -91,10 +97,8 @@ module ActionDispatch resource = Resource.new(resources.pop) if @scope[:scope_level] == :resources - parent_resource = @scope[:scope_level_options][:name] - parent_named_prefix = @scope[:scope_level_options][:name_prefix] with_scope_level(:member) do - scope(":#{parent_resource}_id", :name_prefix => parent_named_prefix) do + scope(parent_resource.id_segment, :name_prefix => parent_resource.member_name_prefix) do resources(resource.name, options, &block) end end @@ -103,7 +107,7 @@ module ActionDispatch controller(resource.controller) do namespace(resource.name) do - with_scope_level(:resources, :name => resource.singular, :name_prefix => "#{resource.member_name}_") do + with_scope_level(:resources, resource) do yield if block_given? collection do @@ -165,14 +169,19 @@ module ActionDispatch super end + protected + def parent_resource + @scope[:scope_level_resource] + end + private - def with_scope_level(kind, options = {}) + def with_scope_level(kind, resource = parent_resource) old, @scope[:scope_level] = @scope[:scope_level], kind - old_options, @scope[:scope_level_options] = @scope[:scope_level_options], options + old_resource, @scope[:scope_level_resource] = @scope[:scope_level_resource], resource yield ensure @scope[:scope_level] = old - @scope[:scope_level_options] = old_options + @scope[:scope_level_resource] = old_resource end end -- cgit v1.2.3 From e86a82c52c2c5edb8c95f9fd882b491dd1f550f4 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Mon, 7 Dec 2009 19:50:13 -0600 Subject: Move name_prefix merging into Scoping concern --- actionpack/lib/action_dispatch/routing/mapper.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 9ca4e16802..8dbf33d5f9 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -258,7 +258,13 @@ module ActionDispatch def match(*args) options = args.extract_options! + options = (@scope[:options] || {}).merge(options) + + if @scope[:name_prefix] + options[:as] = "#{@scope[:name_prefix]}#{options[:as]}" + end + args.push(options) super(*args) end @@ -391,9 +397,7 @@ module ActionDispatch validate_defaults!(app, defaults, segment_keys) app = Constraints.new(app, blocks) - name = @scope[:name_prefix] ? "#{@scope[:name_prefix]}#{options[:as]}" : options[:as] - - @set.add_route(app, conditions, requirements, defaults, name) + @set.add_route(app, conditions, requirements, defaults, options[:as]) self end -- cgit v1.2.3 From 81d7227c9b8f4a74a74cf3b2cb183ce130b3f679 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Mon, 7 Dec 2009 19:59:23 -0600 Subject: Move base mapper methods into Base module so plugins can easily extend the mapper --- actionpack/lib/action_dispatch/routing/mapper.rb | 492 ++++++++++++----------- 1 file changed, 247 insertions(+), 245 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 8dbf33d5f9..1a742f61e6 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1,6 +1,249 @@ module ActionDispatch module Routing class Mapper + class Constraints + def new(app, constraints = []) + if constraints.any? + super(app, constraints) + else + app + end + end + + def initialize(app, constraints = []) + @app, @constraints = app, constraints + end + + def call(env) + req = Rack::Request.new(env) + + @constraints.each { |constraint| + if constraint.respond_to?(:matches?) && !constraint.matches?(req) + return [417, {}, []] + elsif constraint.respond_to?(:call) && !constraint.call(req) + return [417, {}, []] + end + } + + @app.call(env) + end + end + + module Base + def initialize(set) + @set = set + end + + def root(options = {}) + match '/', options.merge(:as => :root) + end + + def match(*args) + options = args.extract_options! + + if args.length > 1 + args.each { |path| match(path, options.reverse_merge(:as => path.to_sym)) } + return self + end + + if args.first.is_a?(Symbol) + return match(args.first.to_s, options.merge(:to => args.first.to_sym)) + end + + path = args.first + + conditions, defaults = {}, {} + + path = nil if path == "" + path = Rack::Mount::Utils.normalize_path(path) if path + path = "#{@scope[:path]}#{path}" if @scope[:path] + + raise ArgumentError, "path is required" unless path + + constraints = options[:constraints] || {} + unless constraints.is_a?(Hash) + block, constraints = constraints, {} + end + blocks = ((@scope[:blocks] || []) + [block]).compact + constraints = (@scope[:constraints] || {}).merge(constraints) + options.each { |k, v| constraints[k] = v if v.is_a?(Regexp) } + + conditions[:path_info] = path + requirements = constraints.dup + + path_regexp = Rack::Mount::Strexp.compile(path, constraints, SEPARATORS) + segment_keys = Rack::Mount::RegexpWithNamedGroups.new(path_regexp).names + constraints.reject! { |k, v| segment_keys.include?(k.to_s) } + conditions.merge!(constraints) + + requirements[:controller] ||= @set.controller_constraints + + if via = options[:via] + via = Array(via).map { |m| m.to_s.upcase } + conditions[:request_method] = Regexp.union(*via) + end + + defaults[:controller] ||= @scope[:controller].to_s if @scope[:controller] + + app = initialize_app_endpoint(options, defaults) + validate_defaults!(app, defaults, segment_keys) + app = Constraints.new(app, blocks) + + @set.add_route(app, conditions, requirements, defaults, options[:as]) + + self + end + + private + def initialize_app_endpoint(options, defaults) + app = nil + + if options[:to].respond_to?(:call) + app = options[:to] + defaults.delete(:controller) + defaults.delete(:action) + elsif options[:to].is_a?(String) + defaults[:controller], defaults[:action] = options[:to].split('#') + elsif options[:to].is_a?(Symbol) + defaults[:action] = options[:to].to_s + end + + app || Routing::RouteSet::Dispatcher.new(:defaults => defaults) + end + + def validate_defaults!(app, defaults, segment_keys) + return unless app.is_a?(Routing::RouteSet::Dispatcher) + + unless defaults.include?(:controller) || segment_keys.include?("controller") + raise ArgumentError, "missing :controller" + end + + unless defaults.include?(:action) || segment_keys.include?("action") + raise ArgumentError, "missing :action" + end + end + end + + module HttpHelpers + def get(*args, &block) + map_method(:get, *args, &block) + end + + def post(*args, &block) + map_method(:post, *args, &block) + end + + def put(*args, &block) + map_method(:put, *args, &block) + end + + def delete(*args, &block) + map_method(:delete, *args, &block) + end + + def redirect(path, options = {}) + status = options[:status] || 301 + lambda { |env| + req = Rack::Request.new(env) + url = req.scheme + '://' + req.host + path + [status, {'Location' => url, 'Content-Type' => 'text/html'}, ['Moved Permanently']] + } + end + + private + def map_method(method, *args, &block) + options = args.extract_options! + options[:via] = method + args.push(options) + match(*args, &block) + self + end + end + + module Scoping + def initialize(*args) + @scope = {} + super + end + + def scope(*args) + options = args.extract_options! + + case args.first + when String + options[:path] = args.first + when Symbol + options[:controller] = args.first + end + + if path = options.delete(:path) + path_set = true + path, @scope[:path] = @scope[:path], "#{@scope[:path]}#{Rack::Mount::Utils.normalize_path(path)}" + else + path_set = false + end + + if name_prefix = options.delete(:name_prefix) + name_prefix_set = true + name_prefix, @scope[:name_prefix] = @scope[:name_prefix], (@scope[:name_prefix] ? "#{@scope[:name_prefix]}#{name_prefix}" : name_prefix) + else + name_prefix_set = false + end + + if controller = options.delete(:controller) + controller_set = true + controller, @scope[:controller] = @scope[:controller], controller + else + controller_set = false + end + + constraints = options.delete(:constraints) || {} + unless constraints.is_a?(Hash) + block, constraints = constraints, {} + end + constraints, @scope[:constraints] = @scope[:constraints], (@scope[:constraints] || {}).merge(constraints) + blocks, @scope[:blocks] = @scope[:blocks], (@scope[:blocks] || []) + [block] + + options, @scope[:options] = @scope[:options], (@scope[:options] || {}).merge(options) + + yield + + self + ensure + @scope[:path] = path if path_set + @scope[:name_prefix] = name_prefix if name_prefix_set + @scope[:controller] = controller if controller_set + @scope[:options] = options + @scope[:blocks] = blocks + @scope[:constraints] = constraints + end + + def controller(controller) + scope(controller.to_sym) { yield } + end + + def namespace(path) + scope(path.to_s) { yield } + end + + def constraints(constraints = {}) + scope(:constraints => constraints) { yield } + end + + def match(*args) + options = args.extract_options! + + options = (@scope[:options] || {}).merge(options) + + if @scope[:name_prefix] + options[:as] = "#{@scope[:name_prefix]}#{options[:as]}" + end + + args.push(options) + super(*args) + end + end + module Resources class Resource #:nodoc: attr_reader :plural, :singular @@ -185,251 +428,10 @@ module ActionDispatch end end - module Scoping - def self.extended(object) - object.instance_eval do - @scope = {} - end - end - - def scope(*args) - options = args.extract_options! - - case args.first - when String - options[:path] = args.first - when Symbol - options[:controller] = args.first - end - - if path = options.delete(:path) - path_set = true - path, @scope[:path] = @scope[:path], "#{@scope[:path]}#{Rack::Mount::Utils.normalize_path(path)}" - else - path_set = false - end - - if name_prefix = options.delete(:name_prefix) - name_prefix_set = true - name_prefix, @scope[:name_prefix] = @scope[:name_prefix], (@scope[:name_prefix] ? "#{@scope[:name_prefix]}#{name_prefix}" : name_prefix) - else - name_prefix_set = false - end - - if controller = options.delete(:controller) - controller_set = true - controller, @scope[:controller] = @scope[:controller], controller - else - controller_set = false - end - - constraints = options.delete(:constraints) || {} - unless constraints.is_a?(Hash) - block, constraints = constraints, {} - end - constraints, @scope[:constraints] = @scope[:constraints], (@scope[:constraints] || {}).merge(constraints) - blocks, @scope[:blocks] = @scope[:blocks], (@scope[:blocks] || []) + [block] - - options, @scope[:options] = @scope[:options], (@scope[:options] || {}).merge(options) - - yield - - self - ensure - @scope[:path] = path if path_set - @scope[:name_prefix] = name_prefix if name_prefix_set - @scope[:controller] = controller if controller_set - @scope[:options] = options - @scope[:blocks] = blocks - @scope[:constraints] = constraints - end - - def controller(controller) - scope(controller.to_sym) { yield } - end - - def namespace(path) - scope(path.to_s) { yield } - end - - def constraints(constraints = {}) - scope(:constraints => constraints) { yield } - end - - def match(*args) - options = args.extract_options! - - options = (@scope[:options] || {}).merge(options) - - if @scope[:name_prefix] - options[:as] = "#{@scope[:name_prefix]}#{options[:as]}" - end - - args.push(options) - super(*args) - end - end - - module HttpHelpers - def get(*args, &block) - map_method(:get, *args, &block) - end - - def post(*args, &block) - map_method(:post, *args, &block) - end - - def put(*args, &block) - map_method(:put, *args, &block) - end - - def delete(*args, &block) - map_method(:delete, *args, &block) - end - - def redirect(path, options = {}) - status = options[:status] || 301 - lambda { |env| - req = Rack::Request.new(env) - url = req.scheme + '://' + req.host + path - [status, {'Location' => url, 'Content-Type' => 'text/html'}, ['Moved Permanently']] - } - end - - private - def map_method(method, *args, &block) - options = args.extract_options! - options[:via] = method - args.push(options) - match(*args, &block) - self - end - end - - class Constraints - def new(app, constraints = []) - if constraints.any? - super(app, constraints) - else - app - end - end - - def initialize(app, constraints = []) - @app, @constraints = app, constraints - end - - def call(env) - req = Rack::Request.new(env) - - @constraints.each { |constraint| - if constraint.respond_to?(:matches?) && !constraint.matches?(req) - return [417, {}, []] - elsif constraint.respond_to?(:call) && !constraint.call(req) - return [417, {}, []] - end - } - - @app.call(env) - end - end - - def initialize(set) - @set = set - - extend HttpHelpers - extend Scoping - extend Resources - end - - def root(options = {}) - match '/', options.merge(:as => :root) - end - - def match(*args) - options = args.extract_options! - - if args.length > 1 - args.each { |path| match(path, options.reverse_merge(:as => path.to_sym)) } - return self - end - - if args.first.is_a?(Symbol) - return match(args.first.to_s, options.merge(:to => args.first.to_sym)) - end - - path = args.first - - conditions, defaults = {}, {} - - path = nil if path == "" - path = Rack::Mount::Utils.normalize_path(path) if path - path = "#{@scope[:path]}#{path}" if @scope[:path] - - raise ArgumentError, "path is required" unless path - - constraints = options[:constraints] || {} - unless constraints.is_a?(Hash) - block, constraints = constraints, {} - end - blocks = ((@scope[:blocks] || []) + [block]).compact - constraints = (@scope[:constraints] || {}).merge(constraints) - options.each { |k, v| constraints[k] = v if v.is_a?(Regexp) } - - conditions[:path_info] = path - requirements = constraints.dup - - path_regexp = Rack::Mount::Strexp.compile(path, constraints, SEPARATORS) - segment_keys = Rack::Mount::RegexpWithNamedGroups.new(path_regexp).names - constraints.reject! { |k, v| segment_keys.include?(k.to_s) } - conditions.merge!(constraints) - - requirements[:controller] ||= @set.controller_constraints - - if via = options[:via] - via = Array(via).map { |m| m.to_s.upcase } - conditions[:request_method] = Regexp.union(*via) - end - - defaults[:controller] ||= @scope[:controller].to_s if @scope[:controller] - - app = initialize_app_endpoint(options, defaults) - validate_defaults!(app, defaults, segment_keys) - app = Constraints.new(app, blocks) - - @set.add_route(app, conditions, requirements, defaults, options[:as]) - - self - end - - private - def initialize_app_endpoint(options, defaults) - app = nil - - if options[:to].respond_to?(:call) - app = options[:to] - defaults.delete(:controller) - defaults.delete(:action) - elsif options[:to].is_a?(String) - defaults[:controller], defaults[:action] = options[:to].split('#') - elsif options[:to].is_a?(Symbol) - defaults[:action] = options[:to].to_s - end - - app || Routing::RouteSet::Dispatcher.new(:defaults => defaults) - end - - def validate_defaults!(app, defaults, segment_keys) - return unless app.is_a?(Routing::RouteSet::Dispatcher) - - unless defaults.include?(:controller) || segment_keys.include?("controller") - raise ArgumentError, "missing :controller" - end - - unless defaults.include?(:action) || segment_keys.include?("action") - raise ArgumentError, "missing :action" - end - end + include Base + include HttpHelpers + include Scoping + include Resources end end end -- cgit v1.2.3 From 0c34e3f41ae79bb675c74b697ef92bad59b25f7f Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Mon, 7 Dec 2009 20:11:57 -0600 Subject: Ignore name_prefix unless there is an explicit name --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 1a742f61e6..86470c2017 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -235,7 +235,7 @@ module ActionDispatch options = (@scope[:options] || {}).merge(options) - if @scope[:name_prefix] + if @scope[:name_prefix] && options[:as] options[:as] = "#{@scope[:name_prefix]}#{options[:as]}" end -- cgit v1.2.3 From 1fc58a889d72e9a36167b41fc3cd055c1f58774e Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Mon, 7 Dec 2009 20:57:01 -0600 Subject: Fixed named prefix scope in resource member and collection actions --- actionpack/lib/action_dispatch/routing/mapper.rb | 60 ++++++++++++++---------- actionpack/test/dispatch/routing_test.rb | 22 +++------ 2 files changed, 40 insertions(+), 42 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 86470c2017..7647bdeb5d 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -41,15 +41,6 @@ module ActionDispatch def match(*args) options = args.extract_options! - if args.length > 1 - args.each { |path| match(path, options.reverse_merge(:as => path.to_sym)) } - return self - end - - if args.first.is_a?(Symbol) - return match(args.first.to_s, options.merge(:to => args.first.to_sym)) - end - path = args.first conditions, defaults = {}, {} @@ -185,7 +176,7 @@ module ActionDispatch if name_prefix = options.delete(:name_prefix) name_prefix_set = true - name_prefix, @scope[:name_prefix] = @scope[:name_prefix], (@scope[:name_prefix] ? "#{@scope[:name_prefix]}#{name_prefix}" : name_prefix) + name_prefix, @scope[:name_prefix] = @scope[:name_prefix], (@scope[:name_prefix] ? "#{@scope[:name_prefix]}_#{name_prefix}" : name_prefix) else name_prefix_set = false end @@ -235,8 +226,10 @@ module ActionDispatch options = (@scope[:options] || {}).merge(options) - if @scope[:name_prefix] && options[:as] - options[:as] = "#{@scope[:name_prefix]}#{options[:as]}" + if @scope[:name_prefix] && !options[:as].blank? + options[:as] = "#{@scope[:name_prefix]}_#{options[:as]}" + elsif @scope[:name_prefix] && options[:as].blank? + options[:as] = @scope[:name_prefix].to_s end args.push(options) @@ -274,10 +267,6 @@ module ActionDispatch def id_segment ":#{singular}_id" end - - def member_name_prefix - "#{member_name}_" - end end class SingletonResource < Resource #:nodoc: @@ -303,7 +292,7 @@ module ActionDispatch if @scope[:scope_level] == :resources with_scope_level(:member) do - scope(parent_resource.id_segment, :name_prefix => parent_resource.member_name_prefix) do + scope(parent_resource.id_segment, :name_prefix => parent_resource.member_name) do resource(resource.name, options, &block) end end @@ -341,7 +330,7 @@ module ActionDispatch if @scope[:scope_level] == :resources with_scope_level(:member) do - scope(parent_resource.id_segment, :name_prefix => parent_resource.member_name_prefix) do + scope(parent_resource.id_segment, :name_prefix => parent_resource.member_name) do resources(resource.name, options, &block) end end @@ -353,17 +342,19 @@ module ActionDispatch with_scope_level(:resources, resource) do yield if block_given? - collection do + with_scope_level(:collection) do get "", :to => :index, :as => resource.collection_name post "", :to => :create get "new", :to => :new, :as => "new_#{resource.singular}" end - member do - get "", :to => :show, :as => resource.member_name - put "", :to => :update - delete "", :to => :destroy - get "edit", :to => :edit, :as => "edit_#{resource.singular}" + with_scope_level(:member) do + scope(":id") do + get "", :to => :show, :as => resource.member_name + put "", :to => :update + delete "", :to => :destroy + get "edit", :to => :edit, :as => "edit_#{resource.singular}" + end end end end @@ -378,7 +369,9 @@ module ActionDispatch end with_scope_level(:collection) do - yield + scope(:name_prefix => parent_resource.member_name, :as => "") do + yield + end end end @@ -388,7 +381,7 @@ module ActionDispatch end with_scope_level(:member) do - scope(":id") do + scope(":id", :name_prefix => parent_resource.member_name, :as => "") do yield end end @@ -396,6 +389,21 @@ module ActionDispatch def match(*args) options = args.extract_options! + + if args.length > 1 + args.each { |path| match(path, options) } + return self + end + + if args.first.is_a?(Symbol) + begin + old_name_prefix, @scope[:name_prefix] = @scope[:name_prefix], "#{args.first}_#{@scope[:name_prefix]}" + return match(args.first.to_s, options.merge(:to => args.first.to_sym)) + ensure + @scope[:name_prefix] = old_name_prefix + end + end + args.push(options) case options.delete(:on) diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 0a35868d7c..9262b1c7db 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -93,7 +93,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end controller :articles do - scope 'articles', :name_prefix => 'article_' do + scope 'articles', :name_prefix => 'article' do scope :path => ':title', :title => /[a-z]+/, :as => :with_title do match ':id', :to => :with_id end @@ -267,9 +267,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest post '/projects/1/images/1/revise' assert_equal 'images#revise', @response.body - pending do - assert_equal '/projects/1/images/1/revise', revise_project_image_path(:project_id => '1', :id => '1') - end + assert_equal '/projects/1/images/1/revise', revise_project_image_path(:project_id => '1', :id => '1') end end @@ -291,21 +289,15 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest put '/projects/1/people/1/accessible_projects' assert_equal 'people#accessible_projects', @response.body - pending do - assert_equal '/projects/1/people/1/accessible_projects', accessible_projects_project_person_path(:project_id => '1', :id => '1') - end + assert_equal '/projects/1/people/1/accessible_projects', accessible_projects_project_person_path(:project_id => '1', :id => '1') post '/projects/1/people/1/resend' assert_equal 'people#resend', @response.body - pending do - assert_equal '/projects/1/people/1/resend', resend_project_person_path(:project_id => '1', :id => '1') - end + assert_equal '/projects/1/people/1/resend', resend_project_person_path(:project_id => '1', :id => '1') post '/projects/1/people/1/generate_new_password' assert_equal 'people#generate_new_password', @response.body - pending do - assert_equal '/projects/1/people/1/generate_new_password', generate_new_password_project_person_path(:project_id => '1', :id => '1') - end + assert_equal '/projects/1/people/1/generate_new_password', generate_new_password_project_person_path(:project_id => '1', :id => '1') end end @@ -329,9 +321,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest post '/projects/1/posts/1/preview' assert_equal 'posts#preview', @response.body - pending do - assert_equal '/projects/1/posts/1/preview', preview_project_post_path(:project_id => '1', :id => '1') - end + assert_equal '/projects/1/posts/1/preview', preview_project_post_path(:project_id => '1', :id => '1') get '/projects/1/posts/1/subscription' assert_equal 'subscriptions#show', @response.body -- cgit v1.2.3 From 3d91d7f0a2bd4b1e104dd8847a2fe9f206c916ca Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Tue, 8 Dec 2009 15:31:56 -0600 Subject: Routes added under resource collection should be prefixed with resource collection name --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 +- actionpack/test/dispatch/routing_test.rb | 17 ++++------------- 2 files changed, 5 insertions(+), 14 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 7647bdeb5d..513c6a5c5f 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -369,7 +369,7 @@ module ActionDispatch end with_scope_level(:collection) do - scope(:name_prefix => parent_resource.member_name, :as => "") do + scope(:name_prefix => parent_resource.collection_name, :as => "") do yield end end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 9262b1c7db..029bec2124 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -236,10 +236,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest put '/projects/1/participants/update_all' assert_equal 'participants#update_all', @response.body - - pending do - assert_equal '/projects/1/participants/update_all', update_all_project_participants_path(:project_id => '1') - end + assert_equal '/projects/1/participants/update_all', update_all_project_participants_path(:project_id => '1') end end @@ -309,15 +306,11 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get '/projects/1/posts/archive' assert_equal 'posts#archive', @response.body - pending do - assert_equal '/projects/1/posts/archive', archive_project_posts_path(:project_id => '1') - end + assert_equal '/projects/1/posts/archive', archive_project_posts_path(:project_id => '1') get '/projects/1/posts/toggle_view' assert_equal 'posts#toggle_view', @response.body - pending do - assert_equal '/projects/1/posts/toggle_view', toggle_view_project_posts_path(:project_id => '1') - end + assert_equal '/projects/1/posts/toggle_view', toggle_view_project_posts_path(:project_id => '1') post '/projects/1/posts/1/preview' assert_equal 'posts#preview', @response.body @@ -333,9 +326,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest post '/projects/1/posts/1/comments/preview' assert_equal 'comments#preview', @response.body - pending do - assert_equal '/projects/1/posts/1/comments/preview', preview_project_post_comments_path(:project_id => '1', :post_id => '1') - end + assert_equal '/projects/1/posts/1/comments/preview', preview_project_post_comments_path(:project_id => '1', :post_id => '1') end end -- cgit v1.2.3 From 33658ea1ae4170f4b0b5123e240d79bb292719e7 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Tue, 8 Dec 2009 15:50:44 -0600 Subject: Don't use name prefix by itself unless as is an empty string --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 513c6a5c5f..e05845a04f 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -228,7 +228,7 @@ module ActionDispatch if @scope[:name_prefix] && !options[:as].blank? options[:as] = "#{@scope[:name_prefix]}_#{options[:as]}" - elsif @scope[:name_prefix] && options[:as].blank? + elsif @scope[:name_prefix] && options[:as] == "" options[:as] = @scope[:name_prefix].to_s end -- cgit v1.2.3 From c4df6332a4d8292dd7d6bd6a1badc896a2323d11 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Tue, 8 Dec 2009 16:06:46 -0600 Subject: Seperate scope level for nesting resources --- actionpack/lib/action_dispatch/routing/mapper.rb | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index e05845a04f..24b04088e6 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -291,10 +291,8 @@ module ActionDispatch resource = SingletonResource.new(resources.pop) if @scope[:scope_level] == :resources - with_scope_level(:member) do - scope(parent_resource.id_segment, :name_prefix => parent_resource.member_name) do - resource(resource.name, options, &block) - end + nested do + resource(resource.name, options, &block) end return self end @@ -329,10 +327,8 @@ module ActionDispatch resource = Resource.new(resources.pop) if @scope[:scope_level] == :resources - with_scope_level(:member) do - scope(parent_resource.id_segment, :name_prefix => parent_resource.member_name) do - resources(resource.name, options, &block) - end + nested do + resources(resource.name, options, &block) end return self end @@ -387,6 +383,18 @@ module ActionDispatch end end + def nested + unless @scope[:scope_level] == :resources + raise ArgumentError, "can't use nested outside resources scope" + end + + with_scope_level(:nested) do + scope(parent_resource.id_segment, :name_prefix => parent_resource.member_name) do + yield + end + end + end + def match(*args) options = args.extract_options! -- cgit v1.2.3 From ce5f27b04b1ff25eed520a3d06b3b9c150536e21 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Tue, 8 Dec 2009 16:13:00 -0600 Subject: Remove double scoping blocks and just use one --- actionpack/lib/action_dispatch/routing/mapper.rb | 52 +++++++++++------------- 1 file changed, 24 insertions(+), 28 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 24b04088e6..8cb7745aff 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -297,18 +297,16 @@ module ActionDispatch return self end - controller(resource.controller) do - namespace(resource.name) do - with_scope_level(:resource, resource) do - yield if block_given? - - get "", :to => :show, :as => resource.member_name - post "", :to => :create - put "", :to => :update - delete "", :to => :destroy - get "new", :to => :new, :as => "new_#{resource.singular}" - get "edit", :to => :edit, :as => "edit_#{resource.singular}" - end + scope(:path => resource.name, :controller => resource.controller) do + with_scope_level(:resource, resource) do + yield if block_given? + + get "", :to => :show, :as => resource.member_name + post "", :to => :create + put "", :to => :update + delete "", :to => :destroy + get "new", :to => :new, :as => "new_#{resource.singular}" + get "edit", :to => :edit, :as => "edit_#{resource.singular}" end end @@ -333,24 +331,22 @@ module ActionDispatch return self end - controller(resource.controller) do - namespace(resource.name) do - with_scope_level(:resources, resource) do - yield if block_given? + scope(:path => resource.name, :controller => resource.controller) do + with_scope_level(:resources, resource) do + yield if block_given? - with_scope_level(:collection) do - get "", :to => :index, :as => resource.collection_name - post "", :to => :create - get "new", :to => :new, :as => "new_#{resource.singular}" - end + with_scope_level(:collection) do + get "", :to => :index, :as => resource.collection_name + post "", :to => :create + get "new", :to => :new, :as => "new_#{resource.singular}" + end - with_scope_level(:member) do - scope(":id") do - get "", :to => :show, :as => resource.member_name - put "", :to => :update - delete "", :to => :destroy - get "edit", :to => :edit, :as => "edit_#{resource.singular}" - end + with_scope_level(:member) do + scope(":id") do + get "", :to => :show, :as => resource.member_name + put "", :to => :update + delete "", :to => :destroy + get "edit", :to => :edit, :as => "edit_#{resource.singular}" end end end -- cgit v1.2.3 From ac711043ecec0dd15a159eff8081be8f10584be0 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Tue, 8 Dec 2009 16:15:25 -0600 Subject: Fix ambiguous access_token scoping example --- actionpack/test/dispatch/routing_test.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 029bec2124..97cacc4a02 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -58,8 +58,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end resources :people do - namespace ":access_token" do - resource :avatar + nested do + namespace ":access_token" do + resource :avatar + end end member do @@ -280,9 +282,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get '/projects/1/people/1/7a2dec8/avatar' assert_equal 'avatars#show', @response.body - pending do - assert_equal '/projects/1/people/1/7a2dec8/avatar', project_person_avatar_path(:project_id => '1', :person_id => '1', :access_token => '7a2dec8') - end + assert_equal '/projects/1/people/1/7a2dec8/avatar', project_person_avatar_path(:project_id => '1', :person_id => '1', :access_token => '7a2dec8') put '/projects/1/people/1/accessible_projects' assert_equal 'people#accessible_projects', @response.body -- cgit v1.2.3 From 2be5e088d27f17cd7210cbfd227aff2e5be6b800 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Tue, 8 Dec 2009 16:52:26 -0600 Subject: Use new routing dsl in tests --- actionpack/test/abstract_unit.rb | 2 +- .../test/activerecord/active_record_store_test.rb | 2 +- .../test/controller/action_pack_assertions_test.rb | 22 ++++++++-------- actionpack/test/controller/base_test.rb | 6 ++--- actionpack/test/controller/mime_responds_test.rb | 8 +++--- actionpack/test/controller/redirect_test.rb | 4 +-- actionpack/test/controller/render_test.rb | 30 +++++++++++----------- actionpack/test/controller/render_xml_test.rb | 4 +-- actionpack/test/controller/test_test.rb | 11 -------- actionpack/test/controller/url_rewriter_test.rb | 4 +-- actionpack/test/controller/webservice_test.rb | 4 +-- .../request/multipart_params_parsing_test.rb | 2 +- actionpack/test/template/atom_feed_helper_test.rb | 12 ++++----- actionpack/test/template/test_case_test.rb | 4 +-- actionpack/test/template/url_helper_test.rb | 8 +++--- 15 files changed, 56 insertions(+), 67 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 9d055da4b9..eab9f8b83d 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -83,7 +83,7 @@ class ActiveSupport::TestCase # have been loaded. setup_once do ActionController::Routing::Routes.draw do |map| - map.connect ':controller/:action/:id' + match ':controller(/:action(/:id))' end end end diff --git a/actionpack/test/activerecord/active_record_store_test.rb b/actionpack/test/activerecord/active_record_store_test.rb index c6c079f88c..61bee1b66c 100644 --- a/actionpack/test/activerecord/active_record_store_test.rb +++ b/actionpack/test/activerecord/active_record_store_test.rb @@ -155,7 +155,7 @@ class ActiveRecordStoreTest < ActionController::IntegrationTest def with_test_route_set(options = {}) with_routing do |set| set.draw do |map| - map.connect "/:action", :controller => "active_record_store_test/test" + match ':action', :to => 'active_record_store_test/test' end @app = ActiveRecord::SessionStore.new(set, options.reverse_merge(:key => '_session_id')) yield diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb index 901cb940ea..d54be9bdc0 100644 --- a/actionpack/test/controller/action_pack_assertions_test.rb +++ b/actionpack/test/controller/action_pack_assertions_test.rb @@ -221,8 +221,8 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase def test_assert_redirect_to_named_route with_routing do |set| set.draw do |map| - map.route_one 'route_one', :controller => 'action_pack_assertions', :action => 'nothing' - map.connect ':controller/:action/:id' + match 'route_one', :to => 'action_pack_assertions#nothing', :as => :route_one + match ':controller/:action' end set.install_helpers @@ -235,9 +235,9 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase def test_assert_redirect_to_named_route_failure with_routing do |set| set.draw do |map| - map.route_one 'route_one', :controller => 'action_pack_assertions', :action => 'nothing', :id => 'one' - map.route_two 'route_two', :controller => 'action_pack_assertions', :action => 'nothing', :id => 'two' - map.connect ':controller/:action/:id' + match 'route_one', :to => 'action_pack_assertions#nothing', :as => :route_one + match 'route_two', :to => 'action_pack_assertions#nothing', :id => 'two', :as => :route_two + match ':controller/:action' end process :redirect_to_named_route assert_raise(ActiveSupport::TestCase::Assertion) do @@ -255,8 +255,8 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase def test_assert_redirect_to_nested_named_route with_routing do |set| set.draw do |map| - map.admin_inner_module 'admin/inner_module', :controller => 'admin/inner_module', :action => 'index' - map.connect ':controller/:action/:id' + match 'admin/inner_module', :to => 'admin/inner_module#index', :as => :admin_inner_module + match ':controller/:action' end @controller = Admin::InnerModuleController.new process :redirect_to_index @@ -268,8 +268,8 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase def test_assert_redirected_to_top_level_named_route_from_nested_controller with_routing do |set| set.draw do |map| - map.top_level '/action_pack_assertions/:id', :controller => 'action_pack_assertions', :action => 'index' - map.connect ':controller/:action/:id' + match '/action_pack_assertions/:id', :to => 'action_pack_assertions#index', :as => :top_level + match ':controller/:action' end @controller = Admin::InnerModuleController.new process :redirect_to_top_level_named_route @@ -282,8 +282,8 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase with_routing do |set| set.draw do |map| # this controller exists in the admin namespace as well which is the only difference from previous test - map.top_level '/user/:id', :controller => 'user', :action => 'index' - map.connect ':controller/:action/:id' + match '/user/:id', :to => 'user#index', :as => :top_level + match ':controller/:action' end @controller = Admin::InnerModuleController.new process :redirect_to_top_level_named_route diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb index b57550a69a..8f8ada8d8c 100644 --- a/actionpack/test/controller/base_test.rb +++ b/actionpack/test/controller/base_test.rb @@ -179,8 +179,8 @@ class DefaultUrlOptionsTest < ActionController::TestCase def test_default_url_options_are_used_if_set with_routing do |set| set.draw do |map| - map.default_url_options 'default_url_options', :controller => 'default_url_options' - map.connect ':controller/:action/:id' + match 'default_url_options', :to => 'default_url_options#default_url_options_action', :as => :default_url_options + match ':controller/:action' end get :default_url_options_action # Make a dummy request so that the controller is initialized properly. @@ -210,7 +210,7 @@ class EnsureNamedRoutesWorksTicket22BugTest < ActionController::TestCase def test_named_routes_still_work with_routing do |set| set.draw do |map| - map.resources :things + resources :things end EmptyController.send :include, ActionController::UrlWriter diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index c1fa74b8c8..dd1f2f3d3c 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -827,9 +827,11 @@ class RespondWithControllerTest < ActionController::TestCase def with_test_route_set with_routing do |set| set.draw do |map| - map.resources :customers - map.resources :quiz_stores, :has_many => :customers - map.connect ":controller/:action/:id" + resources :customers + resources :quiz_stores do + resources :customers + end + match ":controller/:action" end yield end diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb index ea278fd8f0..570ff4a41b 100644 --- a/actionpack/test/controller/redirect_test.rb +++ b/actionpack/test/controller/redirect_test.rb @@ -233,8 +233,8 @@ class RedirectTest < ActionController::TestCase def test_redirect_to_record with_routing do |set| set.draw do |map| - map.resources :workshops - map.connect ':controller/:action/:id' + resources :workshops + match ':controller/:action' end get :redirect_to_existing_record diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index cffa970011..f26b15d2e0 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -39,35 +39,35 @@ class TestController < ActionController::Base render :action => 'hello_world' end end - + def conditional_hello_with_public_header if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123], :public => true) render :action => 'hello_world' end end - + def conditional_hello_with_public_header_and_expires_at expires_in 1.minute if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123], :public => true) render :action => 'hello_world' end end - + def conditional_hello_with_expires_in expires_in 60.1.seconds render :action => 'hello_world' end - + def conditional_hello_with_expires_in_with_public expires_in 1.minute, :public => true render :action => 'hello_world' end - + def conditional_hello_with_expires_in_with_public_with_more_keys expires_in 1.minute, :public => true, 'max-stale' => 5.hours render :action => 'hello_world' end - + def conditional_hello_with_expires_in_with_public_with_more_keys_old_syntax expires_in 1.minute, :public => true, :private => nil, 'max-stale' => 5.hours render :action => 'hello_world' @@ -272,7 +272,7 @@ class TestController < ActionController::Base def builder_layout_test render :action => "hello", :layout => "layouts/builder" end - + # :move: test this in ActionView def builder_partial_test render :action => "hello_world_container" @@ -1093,8 +1093,8 @@ class RenderTest < ActionController::TestCase def test_head_with_location_object with_routing do |set| set.draw do |map| - map.resources :customers - map.connect ':controller/:action/:id' + resources :customers + match ':controller/:action' end get :head_with_location_object @@ -1306,22 +1306,22 @@ class ExpiresInRenderTest < ActionController::TestCase def setup @request.host = "www.nextangle.com" end - + def test_expires_in_header get :conditional_hello_with_expires_in assert_equal "max-age=60, private", @response.headers["Cache-Control"] end - + def test_expires_in_header_with_public get :conditional_hello_with_expires_in_with_public assert_equal "max-age=60, public", @response.headers["Cache-Control"] end - + def test_expires_in_header_with_additional_headers get :conditional_hello_with_expires_in_with_public_with_more_keys assert_equal "max-age=60, public, max-stale=18000", @response.headers["Cache-Control"] end - + def test_expires_in_old_syntax get :conditional_hello_with_expires_in_with_public_with_more_keys_old_syntax assert_equal "max-age=60, public, max-stale=18000", @response.headers["Cache-Control"] @@ -1425,12 +1425,12 @@ class EtagRenderTest < ActionController::TestCase get :conditional_hello_with_bangs assert_response :not_modified end - + def test_etag_with_public_true_should_set_header get :conditional_hello_with_public_header assert_equal "public", @response.headers['Cache-Control'] end - + def test_etag_with_public_true_should_set_header_and_retain_other_headers get :conditional_hello_with_public_header_and_expires_at assert_equal "max-age=60, public", @response.headers['Cache-Control'] diff --git a/actionpack/test/controller/render_xml_test.rb b/actionpack/test/controller/render_xml_test.rb index 68a52c3e8c..b5b0d0b9d5 100644 --- a/actionpack/test/controller/render_xml_test.rb +++ b/actionpack/test/controller/render_xml_test.rb @@ -61,8 +61,8 @@ class RenderXmlTest < ActionController::TestCase def test_rendering_with_object_location_should_set_header_with_url_for with_routing do |set| set.draw do |map| - map.resources :customers - map.connect ':controller/:action/:id' + resources :customers + match ':controller/:action' end get :render_with_object_location diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb index 375878b755..52020922f2 100644 --- a/actionpack/test/controller/test_test.rb +++ b/actionpack/test/controller/test_test.rb @@ -628,17 +628,6 @@ XML assert_nothing_raised(NoMethodError) { @response.binary_content } end end - - protected - def with_foo_routing - with_routing do |set| - set.draw do |map| - map.generate_url 'foo', :controller => 'test' - map.connect ':controller/:action/:id' - end - yield set - end - end end class InferringClassNameTest < ActionController::TestCase diff --git a/actionpack/test/controller/url_rewriter_test.rb b/actionpack/test/controller/url_rewriter_test.rb index 3b14cbb2d8..ffc0353b00 100644 --- a/actionpack/test/controller/url_rewriter_test.rb +++ b/actionpack/test/controller/url_rewriter_test.rb @@ -247,7 +247,7 @@ class UrlWriterTests < ActionController::TestCase with_routing do |set| set.draw do |map| - map.home '/home/sweet/home/:user', :controller => 'home', :action => 'index' + match '/home/sweet/home/:user', :to => 'home#index', :as => :home end kls = Class.new { include ActionController::UrlWriter } @@ -264,7 +264,7 @@ class UrlWriterTests < ActionController::TestCase with_routing do |set| set.draw do |map| match 'home/sweet/home/:user', :to => 'home#index', :as => :home - map.connect ':controller/:action/:id' + match ':controller/:action/:id' end # We need to create a new class in order to install the new named route. diff --git a/actionpack/test/controller/webservice_test.rb b/actionpack/test/controller/webservice_test.rb index 0514c098bf..5882a8cfa3 100644 --- a/actionpack/test/controller/webservice_test.rb +++ b/actionpack/test/controller/webservice_test.rb @@ -255,9 +255,7 @@ class WebServiceTest < ActionController::IntegrationTest def with_test_route_set with_routing do |set| set.draw do |map| - map.with_options :controller => "web_service_test/test" do |c| - c.connect "/", :action => "assign_parameters" - end + match '/', :to => 'web_service_test/test#assign_parameters' end yield end diff --git a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb index 301080842e..40c5ac2d09 100644 --- a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb @@ -151,7 +151,7 @@ class MultipartParamsParsingTest < ActionController::IntegrationTest def with_test_routing with_routing do |set| set.draw do |map| - map.connect ':action', :controller => "multipart_params_parsing_test/test" + match ':action', :to => 'multipart_params_parsing_test/test' end yield end diff --git a/actionpack/test/template/atom_feed_helper_test.rb b/actionpack/test/template/atom_feed_helper_test.rb index 6a5fb0acff..347cb98303 100644 --- a/actionpack/test/template/atom_feed_helper_test.rb +++ b/actionpack/test/template/atom_feed_helper_test.rb @@ -187,10 +187,9 @@ class ScrollsController < ActionController::Base end protected - - def rescue_action(e) - raise(e) - end + def rescue_action(e) + raise(e) + end end class AtomFeedTest < ActionController::TestCase @@ -311,11 +310,12 @@ class AtomFeedTest < ActionController::TestCase assert_select "summary div p", :text => "after 2" end end -private + + private def with_restful_routing(resources) with_routing do |set| set.draw do |map| - map.resources(resources) + resources(resources) end yield end diff --git a/actionpack/test/template/test_case_test.rb b/actionpack/test/template/test_case_test.rb index 05a409d05a..9a448ce328 100644 --- a/actionpack/test/template/test_case_test.rb +++ b/actionpack/test/template/test_case_test.rb @@ -114,7 +114,7 @@ module ActionView test "is able to use named routes" do with_routing do |set| - set.draw { |map| map.resources :contents } + set.draw { |map| resources :contents } assert_equal 'http://test.host/contents/new', new_content_url assert_equal 'http://test.host/contents/1', content_url(:id => 1) end @@ -122,7 +122,7 @@ module ActionView test "named routes can be used from helper included in view" do with_routing do |set| - set.draw { |map| map.resources :contents } + set.draw { |map| resources :contents } _helpers.module_eval do def render_from_helper new_content_url diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb index 5c463a4f60..d4b58efe1e 100644 --- a/actionpack/test/template/url_helper_test.rb +++ b/actionpack/test/template/url_helper_test.rb @@ -451,7 +451,7 @@ class UrlHelperControllerTest < ActionController::TestCase def with_url_helper_routing with_routing do |set| set.draw do |map| - map.show_named_route 'url_helper_controller_test/url_helper/show_named_route', :controller => 'url_helper_controller_test/url_helper', :action => 'show_named_route' + match 'url_helper_controller_test/url_helper/show_named_route', :to => 'url_helper_controller_test/url_helper#show_named_route', :as => :show_named_route end yield end @@ -505,7 +505,7 @@ class LinkToUnlessCurrentWithControllerTest < ActionController::TestCase def with_restful_routing with_routing do |set| set.draw do |map| - map.resources :tasks + resources :tasks end yield end @@ -625,8 +625,8 @@ class PolymorphicControllerTest < ActionController::TestCase def with_restful_routing with_routing do |set| set.draw do |map| - map.resources :workshops do |w| - w.resources :sessions + resources :workshops do + resources :sessions end end yield -- cgit v1.2.3 From 511cef296bd07fa43794e029e12e4cd1053aa8d1 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Tue, 8 Dec 2009 17:19:49 -0600 Subject: Tack format onto resource routes --- actionpack/lib/action_dispatch/routing/mapper.rb | 44 ++++++++++++------------ actionpack/test/dispatch/routing_test.rb | 18 ++++++++-- 2 files changed, 37 insertions(+), 25 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 8cb7745aff..3b185c2576 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -46,8 +46,8 @@ module ActionDispatch conditions, defaults = {}, {} path = nil if path == "" - path = Rack::Mount::Utils.normalize_path(path) if path path = "#{@scope[:path]}#{path}" if @scope[:path] + path = Rack::Mount::Utils.normalize_path(path) if path raise ArgumentError, "path is required" unless path @@ -169,7 +169,7 @@ module ActionDispatch if path = options.delete(:path) path_set = true - path, @scope[:path] = @scope[:path], "#{@scope[:path]}#{Rack::Mount::Utils.normalize_path(path)}" + path, @scope[:path] = @scope[:path], Rack::Mount::Utils.normalize_path(@scope[:path].to_s + path.to_s) else path_set = false end @@ -214,7 +214,7 @@ module ActionDispatch end def namespace(path) - scope(path.to_s) { yield } + scope("/#{path}") { yield } end def constraints(constraints = {}) @@ -297,16 +297,16 @@ module ActionDispatch return self end - scope(:path => resource.name, :controller => resource.controller) do + scope(:path => "/#{resource.name}", :controller => resource.controller) do with_scope_level(:resource, resource) do yield if block_given? - get "", :to => :show, :as => resource.member_name - post "", :to => :create - put "", :to => :update - delete "", :to => :destroy - get "new", :to => :new, :as => "new_#{resource.singular}" - get "edit", :to => :edit, :as => "edit_#{resource.singular}" + get "(.:format)", :to => :show, :as => resource.member_name + post "(.:format)", :to => :create + put "(.:format)", :to => :update + delete "(.:format)", :to => :destroy + get "/new(.:format)", :to => :new, :as => "new_#{resource.singular}" + get "/edit(.:format)", :to => :edit, :as => "edit_#{resource.singular}" end end @@ -331,22 +331,22 @@ module ActionDispatch return self end - scope(:path => resource.name, :controller => resource.controller) do + scope(:path => "/#{resource.name}", :controller => resource.controller) do with_scope_level(:resources, resource) do yield if block_given? with_scope_level(:collection) do - get "", :to => :index, :as => resource.collection_name - post "", :to => :create - get "new", :to => :new, :as => "new_#{resource.singular}" + get "(.:format)", :to => :index, :as => resource.collection_name + post "(.:format)", :to => :create + get "/new(.:format)", :to => :new, :as => "new_#{resource.singular}" end with_scope_level(:member) do - scope(":id") do - get "", :to => :show, :as => resource.member_name - put "", :to => :update - delete "", :to => :destroy - get "edit", :to => :edit, :as => "edit_#{resource.singular}" + scope("/:id") do + get "(.:format)", :to => :show, :as => resource.member_name + put "(.:format)", :to => :update + delete "(.:format)", :to => :destroy + get "/edit(.:format)", :to => :edit, :as => "edit_#{resource.singular}" end end end @@ -373,7 +373,7 @@ module ActionDispatch end with_scope_level(:member) do - scope(":id", :name_prefix => parent_resource.member_name, :as => "") do + scope("/:id", :name_prefix => parent_resource.member_name, :as => "") do yield end end @@ -385,7 +385,7 @@ module ActionDispatch end with_scope_level(:nested) do - scope(parent_resource.id_segment, :name_prefix => parent_resource.member_name) do + scope("/#{parent_resource.id_segment}", :name_prefix => parent_resource.member_name) do yield end end @@ -402,7 +402,7 @@ module ActionDispatch if args.first.is_a?(Symbol) begin old_name_prefix, @scope[:name_prefix] = @scope[:name_prefix], "#{args.first}_#{@scope[:name_prefix]}" - return match(args.first.to_s, options.merge(:to => args.first.to_sym)) + return match("/#{args.first}(.:format)", options.merge(:to => args.first.to_sym)) ensure @scope[:name_prefix] = old_name_prefix end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 97cacc4a02..01088e9d8f 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -95,9 +95,9 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end controller :articles do - scope 'articles', :name_prefix => 'article' do - scope :path => ':title', :title => /[a-z]+/, :as => :with_title do - match ':id', :to => :with_id + scope '/articles', :name_prefix => 'article' do + scope :path => '/:title', :title => /[a-z]+/, :as => :with_title do + match '/:id', :to => :with_id end end end @@ -196,14 +196,26 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal 'projects#index', @response.body assert_equal '/projects', projects_path + get '/projects.xml' + assert_equal 'projects#index', @response.body + assert_equal '/projects.xml', projects_path(:format => 'xml') + get '/projects/new' assert_equal 'projects#new', @response.body assert_equal '/projects/new', new_project_path + get '/projects/new.xml' + assert_equal 'projects#new', @response.body + assert_equal '/projects/new.xml', new_project_path(:format => 'xml') + get '/projects/1' assert_equal 'projects#show', @response.body assert_equal '/projects/1', project_path(:id => '1') + get '/projects/1.xml' + assert_equal 'projects#show', @response.body + assert_equal '/projects/1.xml', project_path(:id => '1', :format => 'xml') + get '/projects/1/edit' assert_equal 'projects#edit', @response.body assert_equal '/projects/1/edit', edit_project_path(:id => '1') -- cgit v1.2.3 From 9fbde11b8b2a43206bcd1a135e763751cae98264 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Tue, 8 Dec 2009 17:41:00 -0600 Subject: More test porting --- actionpack/test/controller/caching_test.rb | 7 +++---- actionpack/test/controller/test_test.rb | 6 +++--- actionpack/test/controller/url_rewriter_test.rb | 6 +++--- 3 files changed, 9 insertions(+), 10 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index 682a8f3995..4ea2e57741 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -70,8 +70,8 @@ class PageCachingTest < ActionController::TestCase def test_page_caching_resources_saves_to_correct_path_with_extension_even_if_default_route with_routing do |set| set.draw do |map| - map.main '', :controller => 'posts', :format => nil - map.formatted_posts 'posts.:format', :controller => 'posts' + match 'posts.:format', :to => 'posts#index', :as => :formatted_posts + match '/', :to => 'posts#index', :as => :main end @params[:format] = 'rss' assert_equal '/posts.rss', @rewriter.rewrite(@params) @@ -422,8 +422,7 @@ class ActionCacheTest < ActionController::TestCase def test_xml_version_of_resource_is_treated_as_different_cache with_routing do |set| set.draw do |map| - map.connect ':controller/:action.:format' - map.connect ':controller/:action' + match ':controller(/:action(.:format))' end get :index, :format => 'xml' diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb index 52020922f2..a788b2495e 100644 --- a/actionpack/test/controller/test_test.rb +++ b/actionpack/test/controller/test_test.rb @@ -456,8 +456,8 @@ XML def test_array_path_parameter_handled_properly with_routing do |set| set.draw do |map| - map.connect 'file/*path', :controller => 'test_test/test', :action => 'test_params' - map.connect ':controller/:action/:id' + match 'file/*path', :to => 'test_test/test#test_params' + match ':controller/:action' end get :test_params, :path => ['hello', 'world'] @@ -662,7 +662,7 @@ class NamedRoutesControllerTest < ActionController::TestCase def test_should_be_able_to_use_named_routes_before_a_request_is_done with_routing do |set| - set.draw { |map| map.resources :contents } + set.draw { |map| resources :contents } assert_equal 'http://test.host/contents/new', new_content_url assert_equal 'http://test.host/contents/1', content_url(:id => 1) end diff --git a/actionpack/test/controller/url_rewriter_test.rb b/actionpack/test/controller/url_rewriter_test.rb index ffc0353b00..428f40b9f8 100644 --- a/actionpack/test/controller/url_rewriter_test.rb +++ b/actionpack/test/controller/url_rewriter_test.rb @@ -331,8 +331,8 @@ class UrlWriterTests < ActionController::TestCase def test_named_routes_with_nil_keys with_routing do |set| set.draw do |map| - map.main '', :controller => 'posts', :format => nil - map.resources :posts + match 'posts.:format', :to => 'posts#index', :as => :posts + match '/', :to => 'posts#index', :as => :main end # We need to create a new class in order to install the new named route. @@ -350,7 +350,7 @@ class UrlWriterTests < ActionController::TestCase def test_formatted_url_methods_are_deprecated with_routing do |set| set.draw do |map| - map.resources :posts + resources :posts end # We need to create a new class in order to install the new named route. kls = Class.new { include ActionController::UrlWriter } -- cgit v1.2.3 From f9d570bdd80010825c21eb32204471ba525915fa Mon Sep 17 00:00:00 2001 From: Carlhuda <carlhuda@engineyard.com> Date: Wed, 9 Dec 2009 13:38:47 -0800 Subject: Simpler RenderOption API -- removes the need for registering the types and extending a module --- .../lib/action_controller/metal/render_options.rb | 101 +++++++++------------ actionpack/test/controller/render_other_test.rb | 14 +++ 2 files changed, 59 insertions(+), 56 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/render_options.rb b/actionpack/lib/action_controller/metal/render_options.rb index 0d69ca10df..b6a7ca0eda 100644 --- a/actionpack/lib/action_controller/metal/render_options.rb +++ b/actionpack/lib/action_controller/metal/render_options.rb @@ -1,19 +1,24 @@ module ActionController + + def self.add_renderer(key, &block) + RenderOptions.add(key, &block) + end + module RenderOptions extend ActiveSupport::Concern included do extlib_inheritable_accessor :_renderers - self._renderers = [] + self._renderers = {} end module ClassMethods def _write_render_options - renderers = _renderers.map do |r| + renderers = _renderers.map do |name, value| <<-RUBY_EVAL - if options.key?(:#{r}) + if options.key?(:#{name}) _process_options(options) - return render_#{r}(options[:#{r}], options) + return _render_option_#{name}(options[:#{name}], options) end RUBY_EVAL end @@ -25,79 +30,63 @@ module ActionController RUBY_EVAL end - def _add_render_option(name) - _renderers << name + def use_renderers(*args) + args.each do |key| + _renderers[key] = RENDERERS[key] + end _write_render_options end + alias use_renderer use_renderers end def render_to_body(options) _handle_render_options(options) || super end - end - - module RenderOption #:nodoc: - def self.extended(base) - base.extend ActiveSupport::Concern - base.send :include, ::ActionController::RenderOptions - def base.register_renderer(name) - included { _add_render_option(name) } - end + RENDERERS = {} + def self.add(key, &block) + define_method("_render_option_#{key}", &block) + RENDERERS[key] = block + All._write_render_options end - end - module RenderOptions - module Json - extend RenderOption - register_renderer :json + module All + extend ActiveSupport::Concern + include RenderOptions - def render_json(json, options) - json = ActiveSupport::JSON.encode(json) unless json.respond_to?(:to_str) - json = "#{options[:callback]}(#{json})" unless options[:callback].blank? - self.content_type ||= Mime::JSON - self.response_body = json + INCLUDED = [] + included do + self._renderers = RENDERERS + _write_render_options + INCLUDED << self end - end - - module Js - extend RenderOption - register_renderer :js - def render_js(js, options) - self.content_type ||= Mime::JS - self.response_body = js.respond_to?(:to_js) ? js.to_js : js + def self._write_render_options + INCLUDED.each(&:_write_render_options) end end - module Xml - extend RenderOption - register_renderer :xml - - def render_xml(xml, options) - self.content_type ||= Mime::XML - self.response_body = xml.respond_to?(:to_xml) ? xml.to_xml : xml - end + add :json do |json, options| + json = ActiveSupport::JSON.encode(json) unless json.respond_to?(:to_str) + json = "#{options[:callback]}(#{json})" unless options[:callback].blank? + self.content_type ||= Mime::JSON + self.response_body = json end - module RJS - extend RenderOption - register_renderer :update - - def render_update(proc, options) - generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(view_context, &proc) - self.content_type = Mime::JS - self.response_body = generator.to_s - end + add :js do |js, options| + self.content_type ||= Mime::JS + self.response_body = js.respond_to?(:to_js) ? js.to_js : js end - module All - extend ActiveSupport::Concern + add :xml do |xml, options| + self.content_type ||= Mime::XML + self.response_body = xml.respond_to?(:to_xml) ? xml.to_xml : xml + end - include ActionController::RenderOptions::Json - include ActionController::RenderOptions::Js - include ActionController::RenderOptions::Xml - include ActionController::RenderOptions::RJS + add :update do |proc, options| + generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(view_context, &proc) + self.content_type = Mime::JS + self.response_body = generator.to_s end end end diff --git a/actionpack/test/controller/render_other_test.rb b/actionpack/test/controller/render_other_test.rb index 51c3c55545..dfc4f2db8c 100644 --- a/actionpack/test/controller/render_other_test.rb +++ b/actionpack/test/controller/render_other_test.rb @@ -2,6 +2,11 @@ require 'abstract_unit' require 'controller/fake_models' require 'pathname' +ActionController.add_renderer :simon do |says, options| + self.content_type = Mime::TEXT + self.response_body = "Simon says: #{says}" +end + class RenderOtherTest < ActionController::TestCase class TestController < ActionController::Base protect_from_forgery @@ -109,6 +114,10 @@ class RenderOtherTest < ActionController::TestCase end end + def render_simon_says + render :simon => "foo" + end + private def default_render if @alternate_default_render @@ -240,4 +249,9 @@ class RenderOtherTest < ActionController::TestCase xhr :get, :render_alternate_default assert_equal %(Element.replace("foo", "partial html");), @response.body end + + def test_using_custom_render_option + get :render_simon_says + assert_equal "Simon says: foo", @response.body + end end -- cgit v1.2.3 From ec5434c3c2631bb47b568eede397c3bd596eeb88 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Wed, 9 Dec 2009 20:46:32 -0600 Subject: Check block arity passed to routes draw so you don't need to use |map| --- actionpack/lib/action_dispatch/routing/route_set.rb | 9 ++++++++- actionpack/test/dispatch/routing_test.rb | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index a8073c2105..0e83ea3b7e 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -216,7 +216,14 @@ module ActionDispatch def draw(&block) clear! - Mapper.new(self).instance_exec(DeprecatedMapper.new(self), &block) + + mapper = Mapper.new(self) + if block.arity == 1 + mapper.instance_exec(DeprecatedMapper.new(self), &block) + else + mapper.instance_exec(&block) + end + @set.add_route(NotFound) install_helpers @set.freeze diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 01088e9d8f..22ef48b668 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -14,7 +14,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest stub_controllers do |routes| Routes = routes - Routes.draw do |map| + Routes.draw do controller :sessions do get 'login', :to => :new, :as => :login post 'login', :to => :create -- cgit v1.2.3 From c517a4fb9a6388ab561615f8556043ce03d531bd Mon Sep 17 00:00:00 2001 From: Nathan Weizenbaum <nex342@gmail.com> Date: Thu, 10 Dec 2009 13:07:22 -0800 Subject: Add autoloads for ActionView::Template* classes, and an ActionView::TemplateError alias for ActionView::Template::Error. Signed-off-by: Yehuda Katz <wycats@Yehuda-Katz.local> --- actionpack/lib/action_view.rb | 4 ++++ actionpack/lib/action_view/template/error.rb | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index 81ee19d996..06238ca747 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -43,6 +43,10 @@ module ActionView autoload :PathResolver, 'action_view/template/resolver' autoload :PathSet, 'action_view/paths' autoload :FileSystemResolverWithFallback, 'action_view/template/resolver' + + autoload :TemplateError, 'action_view/template/error' + autoload :TemplateHandler, 'action_view/template' + autoload :TemplateHandlers, 'action_view/template' end require 'action_view/erb/util' diff --git a/actionpack/lib/action_view/template/error.rb b/actionpack/lib/action_view/template/error.rb index a136d4333b..648f708d3d 100644 --- a/actionpack/lib/action_view/template/error.rb +++ b/actionpack/lib/action_view/template/error.rb @@ -100,4 +100,6 @@ module ActionView end end end -end \ No newline at end of file + + TemplateError = Template::Error +end -- cgit v1.2.3 From 1b82590c36bb1404f7b7a9aa9cf196253685d73f Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Thu, 10 Dec 2009 22:02:50 -0600 Subject: Reduce usage of interpret_status. It should also return a integer not a string. --- actionpack/lib/action_controller/base.rb | 16 ++++++++++++---- actionpack/lib/action_dispatch/http/status_codes.rb | 17 ----------------- .../lib/action_dispatch/middleware/show_exceptions.rb | 4 +--- 3 files changed, 13 insertions(+), 24 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index ed3984c9d4..48bfbab215 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -19,7 +19,6 @@ module ActionController # Legacy modules include SessionManagement - include ActionDispatch::StatusCodes include ActionController::Caching include ActionController::MimeResponds @@ -91,7 +90,7 @@ module ActionController end if options[:status] - options[:status] = interpret_status(options[:status]).to_i + options[:status] = _interpret_status(options[:status]) end options[:update] = blk if block_given? @@ -140,9 +139,9 @@ module ActionController raise ActionControllerError.new("Cannot redirect to nil!") if options.nil? status = if options.is_a?(Hash) && options.key?(:status) - interpret_status(options.delete(:status)) + _interpret_status(options.delete(:status)) elsif response_status.key?(:status) - interpret_status(response_status[:status]) + _interpret_status(response_status[:status]) else 302 end @@ -164,5 +163,14 @@ module ActionController super(url, status) end + + private + def _interpret_status(status) + if status.is_a?(Symbol) + (ActionDispatch::StatusCodes::SYMBOL_TO_STATUS_CODE[status] || 500) + else + status.to_i + end + end end end diff --git a/actionpack/lib/action_dispatch/http/status_codes.rb b/actionpack/lib/action_dispatch/http/status_codes.rb index 5bac842ec1..ea1475e827 100644 --- a/actionpack/lib/action_dispatch/http/status_codes.rb +++ b/actionpack/lib/action_dispatch/http/status_codes.rb @@ -21,22 +21,5 @@ module ActionDispatch hash[ActiveSupport::Inflector.underscore(message.gsub(/ /, "")).to_sym] = code hash }.freeze - - private - # Given a status parameter, determine whether it needs to be converted - # to a string. If it is a fixnum, use the STATUS_CODES hash to lookup - # the default message. If it is a symbol, use the SYMBOL_TO_STATUS_CODE - # hash to convert it. - def interpret_status(status) - case status - when Fixnum then - "#{status} #{STATUS_CODES[status]}".strip - when Symbol then - interpret_status(SYMBOL_TO_STATUS_CODE[status] || - "500 Unknown Status #{status.inspect}") - else - status.to_s - end - end end end diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index 67c70a0418..471d18491c 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -2,8 +2,6 @@ require "active_support/core_ext/exception" module ActionDispatch class ShowExceptions - include StatusCodes - LOCALHOST = '127.0.0.1'.freeze RESCUES_TEMPLATE_PATH = File.join(File.dirname(__FILE__), 'templates') @@ -104,7 +102,7 @@ module ActionDispatch end def status_code(exception) - interpret_status(@@rescue_responses[exception.class.name]).to_i + ActionDispatch::StatusCodes::SYMBOL_TO_STATUS_CODE[@@rescue_responses[exception.class.name]] end def render(status, body) -- cgit v1.2.3 From d1191507bc8ffa4f7fe59b1cfb03dfbf6b73a798 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Thu, 10 Dec 2009 22:57:07 -0600 Subject: Cleanup generate_extras build/parse mess --- actionpack/lib/action_dispatch/routing/route_set.rb | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 0e83ea3b7e..664babd12e 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -433,7 +433,7 @@ module ActionDispatch raise ActionController::RoutingError, "No route matches #{options.inspect}" end - uri, params = result + path, params = result params.each do |k, v| if v params[k] = v @@ -442,16 +442,10 @@ module ActionDispatch end end - uri << "?#{params.to_query}" if uri && params.any? - path = uri - if path && method == :generate_extras - uri = URI(path) - extras = uri.query ? - Rack::Utils.parse_nested_query(uri.query).keys.map { |k| k.to_sym } : - [] - [uri.path, extras] + [path, params.keys] elsif path + path << "?#{params.to_query}" if params.any? path else raise ActionController::RoutingError, "No route matches #{options.inspect}" -- cgit v1.2.3 From 2f90d700498294a9a4da0baa5317c0e6feaaf176 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Thu, 10 Dec 2009 23:45:04 -0600 Subject: Kill RouteSet#recognize --- .../lib/action_dispatch/routing/route_set.rb | 12 -- .../action_dispatch/testing/assertions/routing.rb | 6 +- actionpack/test/controller/routing_test.rb | 194 ++++++++------------- 3 files changed, 72 insertions(+), 140 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 664babd12e..8d56c4d087 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -479,12 +479,6 @@ module ActionDispatch end end - def recognize(request) - params = recognize_path(request.path, extract_request_environment(request)) - request.path_parameters = params.with_indifferent_access - "#{params[:controller].to_s.camelize}Controller".constantize - end - def recognize_path(path, environment = {}, rescue_error = true) method = (environment[:method] || "GET").to_s.upcase @@ -499,12 +493,6 @@ module ActionDispatch status, headers, body = call(env) body end - - # Subclasses and plugins may override this method to extract further attributes - # from the request, for use by route conditions and such. - def extract_request_environment(request) - { :method => request.method } - end end end end diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb index e6d6b5a3ef..4bc5275e04 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb @@ -134,9 +134,11 @@ module ActionDispatch # Assume given controller request = ActionController::TestRequest.new request.env["REQUEST_METHOD"] = request_method.to_s.upcase if request_method - request.path = path + request.path = path + + params = ActionController::Routing::Routes.recognize_path(path, { :method => request.method }) + request.path_parameters = params.with_indifferent_access - ActionController::Routing::Routes.recognize(request) request end end diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index ff8dfc2573..d52da58807 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -554,10 +554,6 @@ class LegacyRouteSetTests < Test::Unit::TestCase end def setup_request_method_routes_for(method) - @request = ActionController::TestRequest.new - @request.env["REQUEST_METHOD"] = method - @request.request_uri = "/match" - rs.draw do |r| r.connect '/match', :controller => 'books', :action => 'get', :conditions => { :method => :get } r.connect '/match', :controller => 'books', :action => 'post', :conditions => { :method => :post } @@ -569,8 +565,8 @@ class LegacyRouteSetTests < Test::Unit::TestCase %w(GET POST PUT DELETE).each do |request_method| define_method("test_request_method_recognized_with_#{request_method}") do setup_request_method_routes_for(request_method) - assert_nothing_raised { rs.recognize(@request) } - assert_equal request_method.downcase, @request.path_parameters[:action] + params = rs.recognize_path("/match", :method => request_method) + assert_equal request_method.downcase, params[:action] end end @@ -580,18 +576,11 @@ class LegacyRouteSetTests < Test::Unit::TestCase 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] + params = rs.recognize_path("/match", :method => :post) + assert_equal 'get_or_post', params[: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] + params = rs.recognize_path("/match", :method => :put) + assert_equal 'not_get_or_post', params[:action] end def test_subpath_recognized @@ -745,9 +734,7 @@ class RouteSetTest < ActiveSupport::TestCase set.draw do |map| map.connect '/users/index', :controller => :users, :action => :index end - @request = ActionController::TestRequest.new - @request.request_uri = '/users/index' - assert_nothing_raised { set.recognize(@request) } + params = set.recognize_path('/users/index', :method => :get) assert_equal 1, set.routes.size end @@ -980,55 +967,37 @@ class RouteSetTest < ActiveSupport::TestCase end end - request.request_uri = "/people" - request.env["REQUEST_METHOD"] = "GET" - assert_nothing_raised { set.recognize(request) } - assert_equal("index", request.path_parameters[:action]) - request.recycle! + params = set.recognize_path("/people", :method => :get) + assert_equal("index", params[:action]) - request.env["REQUEST_METHOD"] = "POST" - assert_nothing_raised { set.recognize(request) } - assert_equal("create", request.path_parameters[:action]) - request.recycle! + params = set.recognize_path("/people", :method => :post) + assert_equal("create", params[:action]) - request.env["REQUEST_METHOD"] = "PUT" - assert_nothing_raised { set.recognize(request) } - assert_equal("update", request.path_parameters[:action]) - request.recycle! + params = set.recognize_path("/people", :method => :put) + assert_equal("update", params[:action]) - assert_raise(ActionController::UnknownHttpMethod) { - request.env["REQUEST_METHOD"] = "BACON" - set.recognize(request) + assert_raise(ActionController::NotImplemented) { + set.recognize_path("/people", :method => :bacon) } - request.recycle! - - request.request_uri = "/people/5" - request.env["REQUEST_METHOD"] = "GET" - assert_nothing_raised { set.recognize(request) } - assert_equal("show", request.path_parameters[:action]) - assert_equal("5", request.path_parameters[:id]) - request.recycle! - - request.env["REQUEST_METHOD"] = "PUT" - assert_nothing_raised { set.recognize(request) } - assert_equal("update", request.path_parameters[:action]) - assert_equal("5", request.path_parameters[:id]) - request.recycle! - - request.env["REQUEST_METHOD"] = "DELETE" - assert_nothing_raised { set.recognize(request) } - assert_equal("destroy", request.path_parameters[:action]) - assert_equal("5", request.path_parameters[:id]) - request.recycle! + + params = set.recognize_path("/people/5", :method => :get) + assert_equal("show", params[:action]) + assert_equal("5", params[:id]) + + params = set.recognize_path("/people/5", :method => :put) + assert_equal("update", params[:action]) + assert_equal("5", params[:id]) + + params = set.recognize_path("/people/5", :method => :delete) + assert_equal("destroy", params[:action]) + assert_equal("5", params[:id]) begin - request.env["REQUEST_METHOD"] = "POST" - set.recognize(request) + set.recognize_path("/people/5", :method => :post) flunk 'Should have raised MethodNotAllowed' rescue ActionController::MethodNotAllowed => e assert_equal [:get, :put, :delete], e.allowed_methods end - request.recycle! end def test_recognize_with_alias_in_conditions @@ -1038,17 +1007,13 @@ class RouteSetTest < ActiveSupport::TestCase map.root :people end - request.path = "/people" - request.env["REQUEST_METHOD"] = "GET" - assert_nothing_raised { set.recognize(request) } - assert_equal("people", request.path_parameters[:controller]) - assert_equal("index", request.path_parameters[:action]) + params = set.recognize_path("/people", :method => :get) + assert_equal("people", params[:controller]) + assert_equal("index", params[:action]) - request.path = "/" - request.env["REQUEST_METHOD"] = "GET" - assert_nothing_raised { set.recognize(request) } - assert_equal("people", request.path_parameters[:controller]) - assert_equal("index", request.path_parameters[:action]) + params = set.recognize_path("/", :method => :get) + assert_equal("people", params[:controller]) + assert_equal("index", params[:action]) end def test_typo_recognition @@ -1058,14 +1023,12 @@ class RouteSetTest < ActiveSupport::TestCase :year => /\d{4}/, :day => /\d{1,2}/, :month => /\d{1,2}/ end - request.path = "/articles/2005/11/05/a-very-interesting-article" - request.env["REQUEST_METHOD"] = "GET" - assert_nothing_raised { set.recognize(request) } - assert_equal("permalink", request.path_parameters[:action]) - assert_equal("2005", request.path_parameters[:year]) - assert_equal("11", request.path_parameters[:month]) - assert_equal("05", request.path_parameters[:day]) - assert_equal("a-very-interesting-article", request.path_parameters[:title]) + params = set.recognize_path("/articles/2005/11/05/a-very-interesting-article", :method => :get) + assert_equal("permalink", params[:action]) + assert_equal("2005", params[:year]) + assert_equal("11", params[:month]) + assert_equal("05", params[:day]) + assert_equal("a-very-interesting-article", params[:title]) end def test_routing_traversal_does_not_load_extra_classes @@ -1074,9 +1037,7 @@ class RouteSetTest < ActiveSupport::TestCase map.connect '/profile', :controller => 'profile' end - request.path = '/profile' - - set.recognize(request) rescue nil + params = set.recognize_path("/profile") rescue nil assert !Object.const_defined?("Profiler__"), "Profiler should not be loaded" end @@ -1090,24 +1051,17 @@ class RouteSetTest < ActiveSupport::TestCase end end - request.request_uri = "/people/5" - request.env["REQUEST_METHOD"] = "GET" - assert_nothing_raised { set.recognize(request) } - assert_equal("show", request.path_parameters[:action]) - assert_equal("5", request.path_parameters[:id]) - request.recycle! + params = set.recognize_path("/people/5", :method => :get) + assert_equal("show", params[:action]) + assert_equal("5", params[:id]) - request.env["REQUEST_METHOD"] = "PUT" - assert_nothing_raised { set.recognize(request) } - assert_equal("update", request.path_parameters[:action]) - request.recycle! + params = set.recognize_path("/people/5", :method => :put) + assert_equal("update", params[:action]) - request.request_uri = "/people/5.png" - request.env["REQUEST_METHOD"] = "GET" - assert_nothing_raised { set.recognize(request) } - assert_equal("show", request.path_parameters[:action]) - assert_equal("5", request.path_parameters[:id]) - assert_equal("png", request.path_parameters[:_format]) + params = set.recognize_path("/people/5.png", :method => :get) + assert_equal("show", params[:action]) + assert_equal("5", params[:id]) + assert_equal("png", params[:_format]) end def test_generate_with_default_action @@ -1123,11 +1077,9 @@ class RouteSetTest < ActiveSupport::TestCase def test_root_map set.draw { |map| map.root :controller => "people" } - request.path = "" - request.env["REQUEST_METHOD"] = "GET" - assert_nothing_raised { set.recognize(request) } - assert_equal("people", request.path_parameters[:controller]) - assert_equal("index", request.path_parameters[:action]) + params = set.recognize_path("", :method => :get) + assert_equal("people", params[:controller]) + assert_equal("index", params[:action]) end def test_namespace @@ -1139,11 +1091,9 @@ class RouteSetTest < ActiveSupport::TestCase end - request.path = "/api/inventory" - request.env["REQUEST_METHOD"] = "GET" - assert_nothing_raised { set.recognize(request) } - assert_equal("api/products", request.path_parameters[:controller]) - assert_equal("inventory", request.path_parameters[:action]) + params = set.recognize_path("/api/inventory", :method => :get) + assert_equal("api/products", params[:controller]) + assert_equal("inventory", params[:action]) end def test_namespaced_root_map @@ -1155,11 +1105,9 @@ class RouteSetTest < ActiveSupport::TestCase end - request.path = "/api" - request.env["REQUEST_METHOD"] = "GET" - assert_nothing_raised { set.recognize(request) } - assert_equal("api/products", request.path_parameters[:controller]) - assert_equal("index", request.path_parameters[:action]) + params = set.recognize_path("/api", :method => :get) + assert_equal("api/products", params[:controller]) + assert_equal("index", params[:action]) end def test_namespace_with_path_prefix @@ -1169,11 +1117,9 @@ class RouteSetTest < ActiveSupport::TestCase end end - request.path = "/prefix/inventory" - request.env["REQUEST_METHOD"] = "GET" - assert_nothing_raised { set.recognize(request) } - assert_equal("api/products", request.path_parameters[:controller]) - assert_equal("inventory", request.path_parameters[:action]) + params = set.recognize_path("/prefix/inventory", :method => :get) + assert_equal("api/products", params[:controller]) + assert_equal("inventory", params[:action]) end def test_namespace_with_blank_path_prefix @@ -1183,11 +1129,9 @@ class RouteSetTest < ActiveSupport::TestCase end end - request.path = "/inventory" - request.env["REQUEST_METHOD"] = "GET" - assert_nothing_raised { set.recognize(request) } - assert_equal("api/products", request.path_parameters[:controller]) - assert_equal("inventory", request.path_parameters[:action]) + params = set.recognize_path("/inventory", :method => :get) + assert_equal("api/products", params[:controller]) + assert_equal("inventory", params[:action]) end def test_generate_changes_controller_module @@ -1316,11 +1260,9 @@ class RouteSetTest < ActiveSupport::TestCase end end - request.path = "/projects/1/milestones" - request.env["REQUEST_METHOD"] = "GET" - assert_nothing_raised { set.recognize(request) } - assert_equal("milestones", request.path_parameters[:controller]) - assert_equal("index", request.path_parameters[:action]) + params = set.recognize_path("/projects/1/milestones", :method => :get) + assert_equal("milestones", params[:controller]) + assert_equal("index", params[:action]) end def test_setting_root_in_namespace_using_symbol -- cgit v1.2.3 From 588225f8852c4b60bfba38f16d8797a41e175400 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Fri, 11 Dec 2009 00:01:22 -0600 Subject: Remove fancy method not allowed resource exceptions since they are too much of a hack --- .../lib/action_controller/metal/exceptions.rb | 11 +--------- .../lib/action_dispatch/routing/route_set.rb | 24 +--------------------- actionpack/test/controller/resources_test.rb | 8 ++++---- actionpack/test/controller/routing_test.rb | 9 +++----- 4 files changed, 9 insertions(+), 43 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/exceptions.rb b/actionpack/lib/action_controller/metal/exceptions.rb index b9d23da3e0..07024d0a9a 100644 --- a/actionpack/lib/action_controller/metal/exceptions.rb +++ b/actionpack/lib/action_controller/metal/exceptions.rb @@ -18,18 +18,9 @@ module ActionController def initialize(*allowed_methods) super("Only #{allowed_methods.to_sentence(:locale => :en)} requests are allowed.") - @allowed_methods = allowed_methods - end - - def allowed_methods_header - allowed_methods.map { |method_symbol| method_symbol.to_s.upcase } * ', ' - end - - def handle_response!(response) - response.headers['Allow'] ||= allowed_methods_header end end - + class NotImplemented < MethodNotAllowed #:nodoc: end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 8d56c4d087..d71ed1d1db 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -456,30 +456,9 @@ module ActionDispatch def call(env) @set.call(env) - rescue ActionController::RoutingError => e - raise e if env['action_controller.rescue_error'] == false - - method, path = env['REQUEST_METHOD'].downcase.to_sym, env['PATH_INFO'] - - # Route was not recognized. Try to find out why (maybe wrong verb). - allows = HTTP_METHODS.select { |verb| - begin - recognize_path(path, {:method => verb}, false) - rescue ActionController::RoutingError - nil - end - } - - if !HTTP_METHODS.include?(method) - raise ActionController::NotImplemented.new(*allows) - elsif !allows.empty? - raise ActionController::MethodNotAllowed.new(*allows) - else - raise e - end end - def recognize_path(path, environment = {}, rescue_error = true) + def recognize_path(path, environment = {}) method = (environment[:method] || "GET").to_s.upcase begin @@ -489,7 +468,6 @@ module ActionDispatch end env['action_controller.recognize'] = true - env['action_controller.rescue_error'] = rescue_error status, headers, body = call(env) body end diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index 04e9acf855..1a03396ae9 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -403,7 +403,7 @@ class ResourcesTest < ActionController::TestCase with_restful_routing :messages do assert_restful_routes_for :messages do |options| assert_recognizes(options.merge(:action => "new"), :path => "/messages/new", :method => :get) - assert_raise(ActionController::MethodNotAllowed) do + assert_raise(ActionController::RoutingError) do ActionController::Routing::Routes.recognize_path("/messages/new", :method => :post) end end @@ -689,11 +689,11 @@ class ResourcesTest < ActionController::TestCase options = { :controller => controller_name.to_s } collection_path = "/#{controller_name}" - assert_raise(ActionController::MethodNotAllowed) do + assert_raise(ActionController::RoutingError) do assert_recognizes(options.merge(:action => 'update'), :path => collection_path, :method => :put) end - assert_raise(ActionController::MethodNotAllowed) do + assert_raise(ActionController::RoutingError) do assert_recognizes(options.merge(:action => 'destroy'), :path => collection_path, :method => :delete) end end @@ -1378,7 +1378,7 @@ class ResourcesTest < ActionController::TestCase end def assert_not_recognizes(expected_options, path) - assert_raise ActionController::RoutingError, ActionController::MethodNotAllowed, Assertion do + assert_raise ActionController::RoutingError, Assertion do assert_recognizes(expected_options, path) end end diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index d52da58807..a9a970d67d 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -976,7 +976,7 @@ class RouteSetTest < ActiveSupport::TestCase params = set.recognize_path("/people", :method => :put) assert_equal("update", params[:action]) - assert_raise(ActionController::NotImplemented) { + assert_raise(ActionController::RoutingError) { set.recognize_path("/people", :method => :bacon) } @@ -992,12 +992,9 @@ class RouteSetTest < ActiveSupport::TestCase assert_equal("destroy", params[:action]) assert_equal("5", params[:id]) - begin + assert_raise(ActionController::RoutingError) { set.recognize_path("/people/5", :method => :post) - flunk 'Should have raised MethodNotAllowed' - rescue ActionController::MethodNotAllowed => e - assert_equal [:get, :put, :delete], e.allowed_methods - end + } end def test_recognize_with_alias_in_conditions -- cgit v1.2.3 From 61e9f2023baead046c7f8ba7c89a7496bf49d1be Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Fri, 11 Dec 2009 00:11:16 -0600 Subject: Use rackmounts recognize api and don't piggyback recognize_path on top of rack call --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 +- .../lib/action_dispatch/routing/route_set.rb | 49 +++++++++++++--------- 2 files changed, 30 insertions(+), 21 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 3b185c2576..2fa0aab5df 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -2,7 +2,7 @@ module ActionDispatch module Routing class Mapper class Constraints - def new(app, constraints = []) + def self.new(app, constraints = []) if constraints.any? super(app, constraints) else diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index d71ed1d1db..8afd42a293 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -18,36 +18,37 @@ module ActionDispatch def call(env) params = env[PARAMETERS_KEY] + prepare_params!(params) + + unless controller = controller(params) + return [417, {}, []] + end + + controller.action(params[:action]).call(env) + end + + def prepare_params!(params) merge_default_action!(params) split_glob_param!(params) if @glob_param + params.each do |key, value| if value.is_a?(String) value = value.dup.force_encoding(Encoding::BINARY) if value.respond_to?(:force_encoding) params[key] = URI.unescape(value) end end + end - unless controller = controller(params) - return [417, {}, []] - end - - if env['action_controller.recognize'] - [200, {}, params] - else - controller.action(params[:action]).call(env) + def controller(params) + if params && params.has_key?(:controller) + controller = "#{params[:controller].camelize}Controller" + ActiveSupport::Inflector.constantize(controller) end + rescue NameError + nil end private - def controller(params) - if params && params.has_key?(:controller) - controller = "#{params[:controller].camelize}Controller" - ActiveSupport::Inflector.constantize(controller) - end - rescue NameError - nil - end - def merge_default_action!(params) params[:action] ||= 'index' end @@ -460,6 +461,7 @@ module ActionDispatch def recognize_path(path, environment = {}) method = (environment[:method] || "GET").to_s.upcase + path = Rack::Mount::Utils.normalize_path(path) begin env = Rack::MockRequest.env_for(path, {:method => method}) @@ -467,9 +469,16 @@ module ActionDispatch raise ActionController::RoutingError, e.message end - env['action_controller.recognize'] = true - status, headers, body = call(env) - body + req = Rack::Request.new(env) + @set.recognize(req) do |route, params| + dispatcher = route.app + if dispatcher.is_a?(Dispatcher) && dispatcher.controller(params) + dispatcher.prepare_params!(params) + return params + end + end + + raise ActionController::RoutingError, "No route matches #{path.inspect} with #{environment.inspect}" end end end -- cgit v1.2.3 From 2297eaed5b195ea42b99d062ad45f87dde9d3c60 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Fri, 11 Dec 2009 12:46:50 -0600 Subject: "new" and "edit" name routes always need to be prepend to the named_route [#3561 state:resolved] --- actionpack/lib/action_dispatch/routing/mapper.rb | 29 +++++++++++++++++++----- actionpack/test/dispatch/routing_test.rb | 14 ++++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 2fa0aab5df..d480af876d 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -338,7 +338,9 @@ module ActionDispatch with_scope_level(:collection) do get "(.:format)", :to => :index, :as => resource.collection_name post "(.:format)", :to => :create - get "/new(.:format)", :to => :new, :as => "new_#{resource.singular}" + with_exclusive_name_prefix :new do + get "/new(.:format)", :to => :new, :as => resource.singular + end end with_scope_level(:member) do @@ -346,7 +348,9 @@ module ActionDispatch get "(.:format)", :to => :show, :as => resource.member_name put "(.:format)", :to => :update delete "(.:format)", :to => :destroy - get "/edit(.:format)", :to => :edit, :as => "edit_#{resource.singular}" + with_exclusive_name_prefix :edit do + get "/edit(.:format)", :to => :edit, :as => resource.singular + end end end end @@ -400,11 +404,8 @@ module ActionDispatch end if args.first.is_a?(Symbol) - begin - old_name_prefix, @scope[:name_prefix] = @scope[:name_prefix], "#{args.first}_#{@scope[:name_prefix]}" + with_exclusive_name_prefix(args.first) do return match("/#{args.first}(.:format)", options.merge(:to => args.first.to_sym)) - ensure - @scope[:name_prefix] = old_name_prefix end end @@ -430,6 +431,22 @@ module ActionDispatch end private + def with_exclusive_name_prefix(prefix) + begin + old_name_prefix = @scope[:name_prefix] + + if !old_name_prefix.blank? + @scope[:name_prefix] = "#{prefix}_#{@scope[:name_prefix]}" + else + @scope[:name_prefix] = prefix.to_s + end + + yield + ensure + @scope[:name_prefix] = old_name_prefix + end + end + def with_scope_level(kind, resource = parent_resource) old, @scope[:scope_level] = @scope[:scope_level], kind old_resource, @scope[:scope_level_resource] = @scope[:scope_level_resource], resource diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 22ef48b668..425796b460 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -228,9 +228,23 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal 'involvements#index', @response.body assert_equal '/projects/1/involvements', project_involvements_path(:project_id => '1') + get '/projects/1/involvements/new' + assert_equal 'involvements#new', @response.body + assert_equal '/projects/1/involvements/new', new_project_involvement_path(:project_id => '1') + get '/projects/1/involvements/1' assert_equal 'involvements#show', @response.body assert_equal '/projects/1/involvements/1', project_involvement_path(:project_id => '1', :id => '1') + + put '/projects/1/involvements/1' + assert_equal 'involvements#update', @response.body + + delete '/projects/1/involvements/1' + assert_equal 'involvements#destroy', @response.body + + get '/projects/1/involvements/1/edit' + assert_equal 'involvements#edit', @response.body + assert_equal '/projects/1/involvements/1/edit', edit_project_involvement_path(:project_id => '1', :id => '1') end end -- cgit v1.2.3 From ee395fe626760e897abd9e881b54d3cc3f407d31 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Sat, 12 Dec 2009 18:09:44 -0600 Subject: TestProcess belongs in AD --- actionpack/lib/action_controller/test_case.rb | 3 +- .../lib/action_controller/testing/process.rb | 111 --------------------- actionpack/lib/action_dispatch/test_case.rb | 1 + .../action_dispatch/testing/assertions/routing.rb | 40 ++++++++ .../lib/action_dispatch/testing/assertions/tag.rb | 19 +++- .../lib/action_dispatch/testing/integration.rb | 9 +- .../lib/action_dispatch/testing/test_process.rb | 42 ++++++++ actionpack/lib/action_view/test_case.rb | 3 +- actionpack/test/abstract_unit.rb | 2 +- actionpack/test/controller/test_test.rb | 8 +- 10 files changed, 109 insertions(+), 129 deletions(-) delete mode 100644 actionpack/lib/action_controller/testing/process.rb create mode 100644 actionpack/lib/action_dispatch/testing/test_process.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 7533a22299..14cd0dc7e0 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -1,7 +1,6 @@ require 'active_support/test_case' require 'rack/session/abstract/id' require 'action_controller/metal/testing' -require 'action_controller/testing/process' require 'action_dispatch/test_case' module ActionController @@ -183,7 +182,7 @@ module ActionController # # assert_redirected_to page_url(:title => 'foo') class TestCase < ActiveSupport::TestCase - include TestProcess + include ActionDispatch::TestProcess # Executes a request simulating GET HTTP method and set/volley the response def get(action, parameters = nil, session = nil, flash = nil) diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb deleted file mode 100644 index 323cce6a2f..0000000000 --- a/actionpack/lib/action_controller/testing/process.rb +++ /dev/null @@ -1,111 +0,0 @@ -require 'active_support/core_ext/object/conversions' -require "rack/test" - -module ActionController #:nodoc: - # Essentially generates a modified Tempfile object similar to the object - # you'd get from the standard library CGI module in a multipart - # request. This means you can use an ActionController::TestUploadedFile - # object in the params of a test request in order to simulate - # a file upload. - # - # Usage example, within a functional test: - # post :change_avatar, :avatar => ActionController::TestUploadedFile.new(ActionController::TestCase.fixture_path + '/files/spongebob.png', 'image/png') - # - # Pass a true third parameter to ensure the uploaded file is opened in binary mode (only required for Windows): - # post :change_avatar, :avatar => ActionController::TestUploadedFile.new(ActionController::TestCase.fixture_path + '/files/spongebob.png', 'image/png', :binary) - TestUploadedFile = Rack::Test::UploadedFile - - module TestProcess - def assigns(key = nil) - assigns = {} - @controller.instance_variable_names.each do |ivar| - next if ActionController::Base.protected_instance_variables.include?(ivar) - assigns[ivar[1..-1]] = @controller.instance_variable_get(ivar) - end - - key.nil? ? assigns : assigns[key.to_s] - end - - def session - @request.session - end - - def flash - @request.flash - end - - def cookies - @request.cookies.merge(@response.cookies) - end - - def redirect_to_url - @response.redirect_url - end - - def html_document - xml = @response.content_type =~ /xml$/ - @html_document ||= HTML::Document.new(@response.body, false, xml) - end - - def find_tag(conditions) - html_document.find(conditions) - end - - def find_all_tag(conditions) - html_document.find_all(conditions) - end - - def method_missing(selector, *args, &block) - if @controller && ActionController::Routing::Routes.named_routes.helpers.include?(selector) - @controller.send(selector, *args, &block) - else - super - end - end - - # Shortcut for <tt>ActionController::TestUploadedFile.new(ActionController::TestCase.fixture_path + path, type)</tt>: - # - # post :change_avatar, :avatar => fixture_file_upload('/files/spongebob.png', 'image/png') - # - # To upload binary files on Windows, pass <tt>:binary</tt> as the last parameter. - # This will not affect other platforms: - # - # post :change_avatar, :avatar => fixture_file_upload('/files/spongebob.png', 'image/png', :binary) - def fixture_file_upload(path, mime_type = nil, binary = false) - fixture_path = ActionController::TestCase.send(:fixture_path) if ActionController::TestCase.respond_to?(:fixture_path) - ActionController::TestUploadedFile.new("#{fixture_path}#{path}", mime_type, binary) - end - - # A helper to make it easier to test different route configurations. - # This method temporarily replaces ActionController::Routing::Routes - # with a new RouteSet instance. - # - # The new instance is yielded to the passed block. Typically the block - # will create some routes using <tt>map.draw { map.connect ... }</tt>: - # - # with_routing do |set| - # set.draw do |map| - # map.connect ':controller/:action/:id' - # assert_equal( - # ['/content/10/show', {}], - # map.generate(:controller => 'content', :id => 10, :action => 'show') - # end - # end - # end - # - def with_routing - real_routes = ActionController::Routing::Routes - ActionController::Routing.module_eval { remove_const :Routes } - - temporary_routes = ActionController::Routing::RouteSet.new - ActionController::Routing.module_eval { const_set :Routes, temporary_routes } - - yield temporary_routes - ensure - if ActionController::Routing.const_defined? :Routes - ActionController::Routing.module_eval { remove_const :Routes } - end - ActionController::Routing.const_set(:Routes, real_routes) if real_routes - end - end -end diff --git a/actionpack/lib/action_dispatch/test_case.rb b/actionpack/lib/action_dispatch/test_case.rb index afd708f06f..0b3dfaae79 100644 --- a/actionpack/lib/action_dispatch/test_case.rb +++ b/actionpack/lib/action_dispatch/test_case.rb @@ -1,3 +1,4 @@ +require "rack/test" require "action_dispatch/testing/assertions" require "action_dispatch/testing/integration" require "action_dispatch/testing/performance_test" diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb index 4bc5275e04..794fb888b7 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb @@ -126,6 +126,46 @@ module ActionDispatch assert_generates(path.is_a?(Hash) ? path[:path] : path, options, defaults, extras, message) end + # A helper to make it easier to test different route configurations. + # This method temporarily replaces ActionController::Routing::Routes + # with a new RouteSet instance. + # + # The new instance is yielded to the passed block. Typically the block + # will create some routes using <tt>map.draw { map.connect ... }</tt>: + # + # with_routing do |set| + # set.draw do |map| + # map.connect ':controller/:action/:id' + # assert_equal( + # ['/content/10/show', {}], + # map.generate(:controller => 'content', :id => 10, :action => 'show') + # end + # end + # end + # + def with_routing + real_routes = ActionController::Routing::Routes + ActionController::Routing.module_eval { remove_const :Routes } + + temporary_routes = ActionController::Routing::RouteSet.new + ActionController::Routing.module_eval { const_set :Routes, temporary_routes } + + yield temporary_routes + ensure + if ActionController::Routing.const_defined? :Routes + ActionController::Routing.module_eval { remove_const :Routes } + end + ActionController::Routing.const_set(:Routes, real_routes) if real_routes + end + + def method_missing(selector, *args, &block) + if @controller && ActionController::Routing::Routes.named_routes.helpers.include?(selector) + @controller.send(selector, *args, &block) + else + super + end + end + private # Recognizes the route for a given path. def recognized_request_for(path, request_method = nil) diff --git a/actionpack/lib/action_dispatch/testing/assertions/tag.rb b/actionpack/lib/action_dispatch/testing/assertions/tag.rb index ef6867576e..b74dcb1fe4 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/tag.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/tag.rb @@ -76,10 +76,10 @@ module ActionDispatch # # Assert that there is a "span" containing between 2 and 4 "em" tags # # as immediate children # assert_tag :tag => "span", - # :children => { :count => 2..4, :only => { :tag => "em" } } + # :children => { :count => 2..4, :only => { :tag => "em" } } # # # Get funky: assert that there is a "div", with an "ul" ancestor - # # and an "li" parent (with "class" = "enum"), and containing a + # # and an "li" parent (with "class" = "enum"), and containing a # # "span" descendant that contains text matching /hello world/ # assert_tag :tag => "div", # :ancestor => { :tag => "ul" }, @@ -98,7 +98,7 @@ module ActionDispatch tag = find_tag(opts) assert tag, "expected tag, but no tag found matching #{opts.inspect} in:\n#{@response.body.inspect}" end - + # Identical to +assert_tag+, but asserts that a matching tag does _not_ # exist. (See +assert_tag+ for a full discussion of the syntax.) # @@ -118,6 +118,19 @@ module ActionDispatch tag = find_tag(opts) assert !tag, "expected no tag, but found tag matching #{opts.inspect} in:\n#{@response.body.inspect}" end + + def find_tag(conditions) + html_document.find(conditions) + end + + def find_all_tag(conditions) + html_document.find_all(conditions) + end + + def html_document + xml = @response.content_type =~ /xml$/ + @html_document ||= HTML::Document.new(@response.body, false, xml) + end end end end diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb index 40d6f97b2a..76021dc059 100644 --- a/actionpack/lib/action_dispatch/testing/integration.rb +++ b/actionpack/lib/action_dispatch/testing/integration.rb @@ -2,9 +2,8 @@ require 'stringio' require 'uri' require 'active_support/test_case' require 'active_support/core_ext/object/metaclass' - -# TODO: Remove circular dependency on ActionController -require 'action_controller/testing/process' +require 'action_dispatch/testing/test_process' +require 'rack/test' module ActionDispatch module Integration #:nodoc: @@ -128,9 +127,7 @@ module ActionDispatch DEFAULT_HOST = "www.example.com" include Test::Unit::Assertions - include ActionDispatch::Assertions - include ActionController::TestProcess - include RequestHelpers + include TestProcess, RequestHelpers, Assertions %w( status status_message headers body redirect? ).each do |method| delegate method, :to => :response, :allow_nil => true diff --git a/actionpack/lib/action_dispatch/testing/test_process.rb b/actionpack/lib/action_dispatch/testing/test_process.rb new file mode 100644 index 0000000000..eae703e1b6 --- /dev/null +++ b/actionpack/lib/action_dispatch/testing/test_process.rb @@ -0,0 +1,42 @@ +module ActionDispatch + module TestProcess + def assigns(key = nil) + assigns = {} + @controller.instance_variable_names.each do |ivar| + next if ActionController::Base.protected_instance_variables.include?(ivar) + assigns[ivar[1..-1]] = @controller.instance_variable_get(ivar) + end + + key.nil? ? assigns : assigns[key.to_s] + end + + def session + @request.session + end + + def flash + @request.flash + end + + def cookies + @request.cookies.merge(@response.cookies) + end + + def redirect_to_url + @response.redirect_url + end + + # Shortcut for <tt>ARack::Test::UploadedFile.new(ActionController::TestCase.fixture_path + path, type)</tt>: + # + # post :change_avatar, :avatar => fixture_file_upload('/files/spongebob.png', 'image/png') + # + # To upload binary files on Windows, pass <tt>:binary</tt> as the last parameter. + # This will not affect other platforms: + # + # post :change_avatar, :avatar => fixture_file_upload('/files/spongebob.png', 'image/png', :binary) + def fixture_file_upload(path, mime_type = nil, binary = false) + fixture_path = ActionController::TestCase.send(:fixture_path) if ActionController::TestCase.respond_to?(:fixture_path) + Rack::Test::UploadedFile.new("#{fixture_path}#{path}", mime_type, binary) + end + end +end diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index ab5bc49cf9..be9a2ed50d 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -39,8 +39,7 @@ module ActionView end end - include ActionDispatch::Assertions - include ActionController::TestProcess + include ActionDispatch::Assertions, ActionDispatch::TestProcess include ActionView::Context include ActionController::PolymorphicRoutes diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index eab9f8b83d..4dae1ab873 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -198,7 +198,7 @@ module ActionController Base.view_paths = FIXTURE_LOAD_PATH class TestCase - include TestProcess + include ActionDispatch::TestProcess def assert_template(options = {}, message = nil) validate_request! diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb index a788b2495e..0f074b32e6 100644 --- a/actionpack/test/controller/test_test.rb +++ b/actionpack/test/controller/test_test.rb @@ -563,7 +563,7 @@ XML expected = File.read(path) expected.force_encoding(Encoding::BINARY) if expected.respond_to?(:force_encoding) - file = ActionController::TestUploadedFile.new(path, content_type) + file = Rack::Test::UploadedFile.new(path, content_type) assert_equal filename, file.original_filename assert_equal content_type, file.content_type assert_equal file.path, file.local_path @@ -580,10 +580,10 @@ XML path = "#{FILES_DIR}/#{filename}" content_type = 'image/png' - binary_uploaded_file = ActionController::TestUploadedFile.new(path, content_type, :binary) + binary_uploaded_file = Rack::Test::UploadedFile.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) + plain_uploaded_file = Rack::Test::UploadedFile.new(path, content_type) assert_equal File.open(path, READ_PLAIN).read, plain_uploaded_file.read end @@ -605,7 +605,7 @@ XML end def test_test_uploaded_file_exception_when_file_doesnt_exist - assert_raise(RuntimeError) { ActionController::TestUploadedFile.new('non_existent_file') } + assert_raise(RuntimeError) { Rack::Test::UploadedFile.new('non_existent_file') } end def test_redirect_url_only_cares_about_location_header -- cgit v1.2.3 From 018dafe574d370165547516ffef43394e11ab4da Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Sat, 12 Dec 2009 18:41:26 -0600 Subject: Allow autoloads to opt out of eager loading --- .../deprecated/integration_test.rb | 2 - actionpack/lib/action_controller/test_case.rb | 1 - actionpack/lib/action_dispatch.rb | 49 +++++++++++++--------- actionpack/lib/action_dispatch/http/request.rb | 3 +- actionpack/lib/action_dispatch/test_case.rb | 7 ---- .../lib/action_dispatch/testing/integration.rb | 1 - 6 files changed, 31 insertions(+), 32 deletions(-) delete mode 100644 actionpack/lib/action_dispatch/test_case.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/deprecated/integration_test.rb b/actionpack/lib/action_controller/deprecated/integration_test.rb index 05c8c0f156..86336b6bc4 100644 --- a/actionpack/lib/action_controller/deprecated/integration_test.rb +++ b/actionpack/lib/action_controller/deprecated/integration_test.rb @@ -1,4 +1,2 @@ -require "action_dispatch/testing/integration" - ActionController::Integration = ActionDispatch::Integration ActionController::IntegrationTest = ActionDispatch::IntegrationTest diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 14cd0dc7e0..398ea52495 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -1,7 +1,6 @@ require 'active_support/test_case' require 'rack/session/abstract/id' require 'action_controller/metal/testing' -require 'action_dispatch/test_case' module ActionController class TestRequest < ActionDispatch::TestRequest #:nodoc: diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index e21dbc59cc..d1c191d652 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -30,38 +30,47 @@ end module ActionDispatch extend ActiveSupport::Autoload - autoload_under "http" do + autoload_under 'http' do autoload :Request autoload :Response autoload :StatusCodes autoload :Utils end - autoload_under "middleware" do - autoload :Callbacks - autoload :ParamsParser - autoload :Rescue - autoload :ShowExceptions - autoload :Static - autoload :StringCoercion - end + deferrable do + autoload_under 'middleware' do + autoload :Callbacks + autoload :ParamsParser + autoload :Rescue + autoload :ShowExceptions + autoload :Static + autoload :StringCoercion + end - autoload :MiddlewareStack, 'action_dispatch/middleware/stack' - autoload :Routing + autoload :MiddlewareStack, 'action_dispatch/middleware/stack' + autoload :Routing - autoload :HTML, 'action_controller/vendor/html-scanner' + module Http + autoload :Headers, 'action_dispatch/http/headers' + end - module Http - extend ActiveSupport::Autoload + module Session + autoload :AbstractStore, 'action_dispatch/middleware/session/abstract_store' + autoload :CookieStore, 'action_dispatch/middleware/session/cookie_store' + autoload :MemCacheStore, 'action_dispatch/middleware/session/mem_cache_store' + end - autoload :Headers + autoload_under 'testing' do + autoload :Assertions + autoload :Integration + autoload :PerformanceTest + autoload :TestProcess + autoload :TestRequest + autoload :TestResponse + end end - module Session - autoload :AbstractStore, 'action_dispatch/middleware/session/abstract_store' - autoload :CookieStore, 'action_dispatch/middleware/session/cookie_store' - autoload :MemCacheStore, 'action_dispatch/middleware/session/mem_cache_store' - end + autoload :HTML, 'action_controller/vendor/html-scanner' end autoload :Mime, 'action_dispatch/http/mime_type' diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 6a52854961..7d1f5a4504 100755 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -6,6 +6,7 @@ require 'active_support/memoizable' require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/hash/indifferent_access' require 'active_support/core_ext/string/access' +require 'action_dispatch/http/headers' module ActionDispatch class Request < Rack::Request @@ -117,7 +118,7 @@ module ActionDispatch end end end - + def if_modified_since if since = env['HTTP_IF_MODIFIED_SINCE'] Time.rfc2822(since) rescue nil diff --git a/actionpack/lib/action_dispatch/test_case.rb b/actionpack/lib/action_dispatch/test_case.rb deleted file mode 100644 index 0b3dfaae79..0000000000 --- a/actionpack/lib/action_dispatch/test_case.rb +++ /dev/null @@ -1,7 +0,0 @@ -require "rack/test" -require "action_dispatch/testing/assertions" -require "action_dispatch/testing/integration" -require "action_dispatch/testing/performance_test" -require "action_dispatch/testing/test_request" -require "action_dispatch/testing/test_response" -require "action_dispatch/testing/integration" \ No newline at end of file diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb index 76021dc059..5c127dfe37 100644 --- a/actionpack/lib/action_dispatch/testing/integration.rb +++ b/actionpack/lib/action_dispatch/testing/integration.rb @@ -2,7 +2,6 @@ require 'stringio' require 'uri' require 'active_support/test_case' require 'active_support/core_ext/object/metaclass' -require 'action_dispatch/testing/test_process' require 'rack/test' module ActionDispatch -- cgit v1.2.3 From 4b4e517bf1d51e749a6cedb2dd5203b19ab080e5 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Sat, 12 Dec 2009 18:48:34 -0600 Subject: Relocate AbstractController exceptions into their proper parent modules --- actionpack/lib/abstract_controller.rb | 7 ------- actionpack/lib/abstract_controller/base.rb | 4 +++- actionpack/lib/abstract_controller/exceptions.rb | 12 ------------ .../lib/abstract_controller/rendering_controller.rb | 20 ++++++++++++++------ 4 files changed, 17 insertions(+), 26 deletions(-) delete mode 100644 actionpack/lib/abstract_controller/exceptions.rb (limited to 'actionpack') diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index 688a2fe31c..af3623e97e 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -11,11 +11,4 @@ module AbstractController autoload :LocalizedCache autoload :Logger autoload :RenderingController - - # === Exceptions - autoload_at "abstract_controller/exceptions" do - autoload :ActionNotFound - autoload :DoubleRenderError - autoload :Error - end end diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index f5b1c9e4d1..70b5f5b3ef 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -1,4 +1,6 @@ module AbstractController + class Error < StandardError; end + class ActionNotFound < StandardError; end class Base attr_internal :response_body @@ -74,7 +76,7 @@ module AbstractController abstract! # Calls the action going through the entire action dispatch stack. - # + # # The actual method that is called is determined by calling # #method_for_action. If no method can handle the action, then an # ActionNotFound error is raised. diff --git a/actionpack/lib/abstract_controller/exceptions.rb b/actionpack/lib/abstract_controller/exceptions.rb deleted file mode 100644 index b671516de1..0000000000 --- a/actionpack/lib/abstract_controller/exceptions.rb +++ /dev/null @@ -1,12 +0,0 @@ -module AbstractController - class Error < StandardError; end - class ActionNotFound < StandardError; end - - class DoubleRenderError < Error - DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\"." - - def initialize(message = nil) - super(message || DEFAULT_MESSAGE) - end - end -end diff --git a/actionpack/lib/abstract_controller/rendering_controller.rb b/actionpack/lib/abstract_controller/rendering_controller.rb index 777e515d60..d6d2c3e191 100644 --- a/actionpack/lib/abstract_controller/rendering_controller.rb +++ b/actionpack/lib/abstract_controller/rendering_controller.rb @@ -1,6 +1,14 @@ require "abstract_controller/logger" module AbstractController + class DoubleRenderError < Error + DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\"." + + def initialize(message = nil) + super(message || DEFAULT_MESSAGE) + end + end + module RenderingController extend ActiveSupport::Concern @@ -21,7 +29,7 @@ module AbstractController # An instance of a view class. The default view class is ActionView::Base # # The view class must have the following methods: - # View.for_controller[controller] Create a new ActionView instance for a + # View.for_controller[controller] Create a new ActionView instance for a # controller # View#render_partial[options] # - responsible for setting options[:_template] @@ -152,12 +160,12 @@ module AbstractController module ClassMethods def clear_template_caches! end - + # Append a path to the list of view paths for this controller. # # ==== Parameters - # path<String, ViewPath>:: If a String is provided, it gets converted into - # the default view path. You may also provide a custom view path + # path<String, ViewPath>:: If a String is provided, it gets converted into + # the default view path. You may also provide a custom view path # (see ActionView::ViewPathSet for more information) def append_view_path(path) self.view_paths << path @@ -166,8 +174,8 @@ module AbstractController # Prepend a path to the list of view paths for this controller. # # ==== Parameters - # path<String, ViewPath>:: If a String is provided, it gets converted into - # the default view path. You may also provide a custom view path + # path<String, ViewPath>:: If a String is provided, it gets converted into + # the default view path. You may also provide a custom view path # (see ActionView::ViewPathSet for more information) def prepend_view_path(path) clear_template_caches! -- cgit v1.2.3 From 9cc99498178f1e71da8b54f985d0483ea377421d Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Sat, 12 Dec 2009 19:28:03 -0600 Subject: All AbstractController modules are deferrable --- actionpack/lib/abstract_controller.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index af3623e97e..92d2971ec3 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -4,11 +4,13 @@ require "active_support/core_ext/module/delegation" module AbstractController extend ActiveSupport::Autoload - autoload :Base - autoload :Callbacks - autoload :Helpers - autoload :Layouts - autoload :LocalizedCache - autoload :Logger - autoload :RenderingController + deferrable do + autoload :Base + autoload :Callbacks + autoload :Helpers + autoload :Layouts + autoload :LocalizedCache + autoload :Logger + autoload :RenderingController + end end -- cgit v1.2.3 From 289c9a24fcd27665f5544c4d647f3a60ae9c790e Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Sat, 12 Dec 2009 19:41:58 -0600 Subject: Nearly all AC modules can be deferred --- actionpack/lib/action_controller.rb | 84 +++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 40 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index f830223058..2113d791f5 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -3,51 +3,55 @@ require "active_support" module ActionController extend ActiveSupport::Autoload - autoload :Base - autoload :Caching - autoload :PolymorphicRoutes - autoload :RecordIdentifier - autoload :UrlRewriter - autoload :Translation - autoload :Metal - autoload :Middleware + deferrable do + autoload :Base + autoload :Caching + autoload :PolymorphicRoutes + autoload :Translation + autoload :Metal + autoload :Middleware - autoload_under "metal" do - autoload :Benchmarking - autoload :ConditionalGet - autoload :Configuration - autoload :Head - autoload :Helpers - autoload :HideActions - autoload :Layouts - autoload :MimeResponds - autoload :RackConvenience - autoload :Compatibility - autoload :Redirector - autoload :RenderingController - autoload :RenderOptions - autoload :Rescue - autoload :Responder - autoload :Session - autoload :SessionManagement - autoload :UrlFor - autoload :Verification - autoload :Flash - autoload :RequestForgeryProtection - autoload :Streaming - autoload :HttpAuthentication - autoload :FilterParameterLogging - autoload :Cookies - end + autoload_under "metal" do + autoload :Benchmarking + autoload :ConditionalGet + autoload :Configuration + autoload :Head + autoload :Helpers + autoload :HideActions + autoload :Layouts + autoload :MimeResponds + autoload :RackConvenience + autoload :Compatibility + autoload :Redirector + autoload :RenderingController + autoload :RenderOptions + autoload :Rescue + autoload :Responder + autoload :Session + autoload :SessionManagement + autoload :UrlFor + autoload :Verification + autoload :Flash + autoload :RequestForgeryProtection + autoload :Streaming + autoload :HttpAuthentication + autoload :FilterParameterLogging + autoload :Cookies + end - autoload :Dispatcher, 'action_controller/dispatch/dispatcher' - autoload :PerformanceTest, 'action_controller/deprecated/performance_test' - autoload :Routing, 'action_controller/deprecated' - autoload :Integration, 'action_controller/deprecated/integration_test' - autoload :IntegrationTest, 'action_controller/deprecated/integration_test' + autoload :Dispatcher, 'action_controller/dispatch/dispatcher' + autoload :PerformanceTest, 'action_controller/deprecated/performance_test' + autoload :Routing, 'action_controller/deprecated' + autoload :Integration, 'action_controller/deprecated/integration_test' + autoload :IntegrationTest, 'action_controller/deprecated/integration_test' + end + autoload :RecordIdentifier + autoload :UrlRewriter autoload :UrlWriter, 'action_controller/url_rewriter' + # TODO: Don't autoload exceptions, setup explicit + # requires for files that need them autoload_at "action_controller/metal/exceptions" do autoload :ActionControllerError autoload :RenderError -- cgit v1.2.3 From 39b708be96f470555bdc6d2c81f252f9f175f899 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Sat, 12 Dec 2009 19:50:12 -0600 Subject: rendering controller needs base --- actionpack/lib/abstract_controller/rendering_controller.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'actionpack') diff --git a/actionpack/lib/abstract_controller/rendering_controller.rb b/actionpack/lib/abstract_controller/rendering_controller.rb index d6d2c3e191..7f2243d4ef 100644 --- a/actionpack/lib/abstract_controller/rendering_controller.rb +++ b/actionpack/lib/abstract_controller/rendering_controller.rb @@ -1,3 +1,4 @@ +require "abstract_controller/base" require "abstract_controller/logger" module AbstractController -- cgit v1.2.3 From 2130566acf5ebe73217af40d25a18507dfb0fd99 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Mon, 14 Dec 2009 15:47:52 -0600 Subject: Fix warnings in AD::Response --- actionpack/lib/action_dispatch/http/response.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 4f35a00247..378fd5e61d 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -49,6 +49,9 @@ module ActionDispatch # :nodoc: @body, @cookie = [], [] @sending_file = false + @blank = false + @etag = nil + yield self if block_given? end -- cgit v1.2.3 From 1c52bca2664457af5c004545f90c1eb3d47c487c Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Mon, 14 Dec 2009 15:54:27 -0600 Subject: Fix warning in AC flash --- actionpack/lib/action_controller/metal/flash.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/flash.rb b/actionpack/lib/action_controller/metal/flash.rb index b2d44c6c63..9d08ed6081 100644 --- a/actionpack/lib/action_controller/metal/flash.rb +++ b/actionpack/lib/action_controller/metal/flash.rb @@ -149,6 +149,7 @@ module ActionController #:nodoc: protected def process_action(method_name) + @_flash = nil super @_flash.store(session) if @_flash @_flash = nil -- cgit v1.2.3 From 819a353c444569b7db7d0795dc3b40c745c5bc17 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Mon, 14 Dec 2009 15:55:05 -0600 Subject: Hush AP test suite --- actionpack/Rakefile | 2 -- 1 file changed, 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/Rakefile b/actionpack/Rakefile index 99bdcc95fa..863daa4b44 100644 --- a/actionpack/Rakefile +++ b/actionpack/Rakefile @@ -31,7 +31,6 @@ Rake::TestTask.new(:test_action_pack) do |t| # this will not happen automatically and the tests (as a whole) will error t.test_files = Dir.glob('test/{abstract,controller,dispatch,template}/**/*_test.rb').sort - t.verbose = true # t.warning = true end @@ -45,7 +44,6 @@ desc 'ActiveRecord Integration Tests' Rake::TestTask.new(:test_active_record_integration) do |t| t.libs << 'test' t.test_files = Dir.glob("test/activerecord/*_test.rb") - t.verbose = true end # Genereate the RDoc documentation -- cgit v1.2.3 From bcb686054a101c346eb13fee2053f08a585a7b55 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Mon, 14 Dec 2009 16:01:23 -0600 Subject: Hush loading AR unless it fails --- actionpack/test/active_record_unit.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/active_record_unit.rb b/actionpack/test/active_record_unit.rb index 9e0c66055d..9a094cf66b 100644 --- a/actionpack/test/active_record_unit.rb +++ b/actionpack/test/active_record_unit.rb @@ -11,19 +11,15 @@ class ActiveRecordTestConnector end # Try to grab AR -if defined?(ActiveRecord) && defined?(Fixtures) - $stderr.puts 'Active Record is already loaded, running tests' -else - $stderr.print 'Attempting to load Active Record... ' +unless defined?(ActiveRecord) && defined?(Fixtures) begin PATH_TO_AR = "#{File.dirname(__FILE__)}/../../activerecord/lib" raise LoadError, "#{PATH_TO_AR} doesn't exist" unless File.directory?(PATH_TO_AR) $LOAD_PATH.unshift PATH_TO_AR require 'active_record' require 'active_record/fixtures' - $stderr.puts 'success' rescue LoadError => e - $stderr.print "failed. Skipping Active Record assertion tests: #{e}" + $stderr.print "Failed to load Active Record. Skipping Active Record assertion tests: #{e}" ActiveRecordTestConnector.able_to_connect = false end end -- cgit v1.2.3 From 70c3e825fc184c7267d226c7b365af4db17f58b7 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Mon, 14 Dec 2009 16:07:46 -0600 Subject: Fix response_body warning in AC --- actionpack/lib/abstract_controller/base.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'actionpack') diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index 70b5f5b3ef..905d04e20d 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -90,6 +90,8 @@ module AbstractController raise ActionNotFound, "The action '#{action}' could not be found" end + @_response_body = nil + process_action(action_name) end -- cgit v1.2.3 From ec99eca013ce96fa1fa628510038a9eafa46d3c5 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Mon, 14 Dec 2009 16:51:13 -0600 Subject: Fix loading plugin and engine route sets --- .../lib/action_dispatch/routing/route_set.rb | 25 +++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 8afd42a293..6f35e9b4e3 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -212,11 +212,14 @@ module ActionDispatch self.routes = [] self.named_routes = NamedRouteCollection.new + @clear_before_draw = true + @finalize_set_on_draw = true + clear! end def draw(&block) - clear! + clear! if @clear_before_draw mapper = Mapper.new(self) if block.arity == 1 @@ -225,9 +228,13 @@ module ActionDispatch mapper.instance_exec(&block) end - @set.add_route(NotFound) - install_helpers - @set.freeze + if @finalize_set_on_draw + @set.add_route(NotFound) + install_helpers + @set.freeze + end + + nil end def clear! @@ -283,7 +290,15 @@ module ActionDispatch def load_routes! if configuration_files.any? - configuration_files.each { |config| load(config) } + @finalize_set_on_draw = false + configuration_files.each_with_index do |config, index| + @finalize_set_on_draw = true if index == (configuration_files.length - 1) + load(config) + @clear_before_draw = false if index == 0 + end + @clear_before_draw = true + @finalize_set_on_draw = true + @routes_last_modified = routes_changed_at else draw do |map| -- cgit v1.2.3 From ce970a8bb9f124d19d28270b1ffc8c4532bbbcc1 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Mon, 14 Dec 2009 16:52:22 -0600 Subject: Remove route loading tests since it should be tested by railties --- actionpack/test/controller/routing_test.rb | 72 ------------------------------ 1 file changed, 72 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index a9a970d67d..c15eaade58 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -1623,78 +1623,6 @@ class RouteSetTest < ActiveSupport::TestCase end end -class RouteLoadingTest < Test::Unit::TestCase - def setup - routes.instance_variable_set '@routes_last_modified', nil - Object.remove_const(:RAILS_ROOT) if defined?(::RAILS_ROOT) - Object.const_set :RAILS_ROOT, '.' - routes.add_configuration_file(File.join(RAILS_ROOT, 'config', 'routes.rb')) - - @stat = stub_everything - end - - def teardown - ActionController::Routing::Routes.configuration_files.clear - Object.send :remove_const, :RAILS_ROOT - end - - def test_load - File.expects(:stat).returns(@stat) - routes.expects(:load).with(regexp_matches(/routes\.rb$/)) - - routes.reload - end - - def test_no_reload_when_not_modified - @stat.expects(:mtime).times(2).returns(1) - File.expects(:stat).times(2).returns(@stat) - routes.expects(:load).with(regexp_matches(/routes\.rb$/)).at_most_once - - 2.times { routes.reload } - end - - def test_reload_when_modified - @stat.expects(:mtime).at_least(2).returns(1, 2) - File.expects(:stat).at_least(2).returns(@stat) - routes.expects(:load).with(regexp_matches(/routes\.rb$/)).times(2) - - 2.times { routes.reload } - end - - def test_bang_forces_reload - @stat.expects(:mtime).at_least(2).returns(1) - File.expects(:stat).at_least(2).returns(@stat) - routes.expects(:load).with(regexp_matches(/routes\.rb$/)).times(2) - - 2.times { routes.reload! } - end - - def test_load_with_configuration - routes.configuration_files.clear - routes.add_configuration_file("foobarbaz") - File.expects(:stat).returns(@stat) - routes.expects(:load).with("foobarbaz") - - routes.reload - end - - def test_load_multiple_configurations - routes.add_configuration_file("engines.rb") - - File.expects(:stat).at_least_once.returns(@stat) - - routes.expects(:load).with('./config/routes.rb') - routes.expects(:load).with('engines.rb') - - routes.reload - end - - private - def routes - ActionController::Routing::Routes - end -end - class RackMountIntegrationTests < ActiveSupport::TestCase Model = Struct.new(:to_param) -- cgit v1.2.3 From 5f8e48cbd297aca4add4b48efa2136ba6ac851b1 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Mon, 14 Dec 2009 17:54:41 -0600 Subject: Move route reloading into railties --- .../lib/action_controller/dispatch/dispatcher.rb | 5 - .../lib/action_dispatch/routing/route_set.rb | 109 ++++----------------- .../action_dispatch/testing/assertions/routing.rb | 2 - actionpack/test/controller/dispatcher_test.rb | 13 --- 4 files changed, 21 insertions(+), 108 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/dispatch/dispatcher.rb b/actionpack/lib/action_controller/dispatch/dispatcher.rb index e04da42637..cf02757cf6 100644 --- a/actionpack/lib/action_controller/dispatch/dispatcher.rb +++ b/actionpack/lib/action_controller/dispatch/dispatcher.rb @@ -13,11 +13,6 @@ module ActionController # Run prepare callbacks before every request in development mode self.prepare_each_request = true - # Development mode callbacks - ActionDispatch::Callbacks.before_dispatch do |app| - ActionController::Routing::Routes.reload - end - ActionDispatch::Callbacks.after_dispatch do # Cleanup the application before processing the current request. ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord) diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 6f35e9b4e3..bf2443c1be 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -203,23 +203,18 @@ module ActionDispatch end end - attr_accessor :routes, :named_routes, :configuration_files, :controller_paths + attr_accessor :routes, :named_routes + attr_accessor :disable_clear_and_finalize def initialize - self.configuration_files = [] - self.controller_paths = [] - self.routes = [] self.named_routes = NamedRouteCollection.new - @clear_before_draw = true - @finalize_set_on_draw = true - - clear! + @disable_clear_and_finalize = false end def draw(&block) - clear! if @clear_before_draw + clear! unless @disable_clear_and_finalize mapper = Mapper.new(self) if block.arity == 1 @@ -228,16 +223,20 @@ module ActionDispatch mapper.instance_exec(&block) end - if @finalize_set_on_draw - @set.add_route(NotFound) - install_helpers - @set.freeze - end + finalize! unless @disable_clear_and_finalize nil end + def finalize! + @set.add_route(NotFound) + install_helpers + @set.freeze + end + def clear! + # Clear the controller cache so we may discover new ones + @controller_constraints = nil routes.clear named_routes.clear @set = ::Rack::Mount::RouteSet.new(:parameters_key => PARAMETERS_KEY) @@ -252,75 +251,6 @@ module ActionDispatch routes.empty? end - def add_configuration_file(path) - self.configuration_files << path - end - - # Deprecated accessor - def configuration_file=(path) - add_configuration_file(path) - end - - # Deprecated accessor - def configuration_file - configuration_files - end - - def load! - # Clear the controller cache so we may discover new ones - @controller_constraints = nil - - load_routes! - end - - # reload! will always force a reload whereas load checks the timestamp first - alias reload! load! - - def reload - if configuration_files.any? && @routes_last_modified - if routes_changed_at == @routes_last_modified - return # routes didn't change, don't reload - else - @routes_last_modified = routes_changed_at - end - end - - load! - end - - def load_routes! - if configuration_files.any? - @finalize_set_on_draw = false - configuration_files.each_with_index do |config, index| - @finalize_set_on_draw = true if index == (configuration_files.length - 1) - load(config) - @clear_before_draw = false if index == 0 - end - @clear_before_draw = true - @finalize_set_on_draw = true - - @routes_last_modified = routes_changed_at - else - draw do |map| - map.connect ":controller/:action/:id" - end - end - end - - def routes_changed_at - routes_changed_at = nil - - configuration_files.each do |config| - config_changed_at = File.stat(config).mtime - - if routes_changed_at.nil? || config_changed_at > routes_changed_at - routes_changed_at = config_changed_at - end - end - - routes_changed_at - end - CONTROLLER_REGEXP = /[_a-zA-Z0-9]+/ def controller_constraints @@ -340,11 +270,14 @@ module ActionDispatch namespaces << controller_name.split('/')[0...-1].join('/') end - # Find namespaces in controllers/ directory - controller_paths.each do |load_path| - load_path = File.expand_path(load_path) - Dir["#{load_path}/**/*_controller.rb"].collect do |path| - namespaces << File.dirname(path).sub(/#{load_path}\/?/, '') + # TODO: Move this into Railties + if defined?(Rails.application) + # Find namespaces in controllers/ directory + Rails.application.configuration.controller_paths.each do |load_path| + load_path = File.expand_path(load_path) + Dir["#{load_path}/**/*_controller.rb"].collect do |path| + namespaces << File.dirname(path).sub(/#{load_path}\/?/, '') + end end end diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb index 794fb888b7..fc477afb17 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb @@ -46,7 +46,6 @@ module ActionDispatch request_method = nil end - ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty? request = recognized_request_for(path, request_method) expected_options = expected_options.clone @@ -80,7 +79,6 @@ module ActionDispatch def assert_generates(expected_path, options, defaults={}, extras = {}, message=nil) 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? generated_path, extra_keys = ActionController::Routing::Routes.generate_extras(options, defaults) found_extras = options.reject {|k, v| ! extra_keys.include? k} diff --git a/actionpack/test/controller/dispatcher_test.rb b/actionpack/test/controller/dispatcher_test.rb index 622d67287d..64f1ad7610 100644 --- a/actionpack/test/controller/dispatcher_test.rb +++ b/actionpack/test/controller/dispatcher_test.rb @@ -15,7 +15,6 @@ class DispatcherTest < Test::Unit::TestCase ActionDispatch::Callbacks.reset_callbacks(:call) ActionController::Routing::Routes.stubs(:call).returns([200, {}, 'response']) - ActionController::Routing::Routes.stubs(:reload) Dispatcher.stubs(:require_dependency) end @@ -28,18 +27,6 @@ class DispatcherTest < Test::Unit::TestCase dispatch(false) end - def test_reloads_routes_before_dispatch_if_in_loading_mode - ActionController::Routing::Routes.expects(:reload).once - dispatch(false) - end - - def test_leaves_dependencies_after_dispatch_if_not_in_loading_mode - ActionController::Routing::Routes.expects(:reload).never - ActiveSupport::Dependencies.expects(:clear).never - - dispatch - end - def test_prepare_callbacks a = b = c = nil ActionDispatch::Callbacks.to_prepare { |*args| a = b = c = 1 } -- cgit v1.2.3 From 7ee5843c3cedfe36a680d5b28aa31eef45296c50 Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Wed, 16 Dec 2009 11:56:51 -0600 Subject: Fully expand relative rails framework paths and make sure we aren't adding any to the load path more than once. --- actionpack/lib/abstract_controller.rb | 8 ++++++-- actionpack/lib/action_controller.rb | 4 +++- actionpack/lib/action_dispatch.rb | 8 ++++---- actionpack/lib/action_view.rb | 13 ++++++------- actionpack/test/abstract_unit.rb | 15 +++++++-------- 5 files changed, 26 insertions(+), 22 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index 92d2971ec3..109a3a3385 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -1,5 +1,9 @@ -require "active_support/core_ext/module/attr_internal" -require "active_support/core_ext/module/delegation" +activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__) +$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path) + +require 'active_support' +require 'active_support/core_ext/module/attr_internal' +require 'active_support/core_ext/module/delegation' module AbstractController extend ActiveSupport::Autoload diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 2113d791f5..37ff10e852 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -1,4 +1,6 @@ -require "active_support" +activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__) +$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path) +require 'active_support' module ActionController extend ActiveSupport::Autoload diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index d1c191d652..feed6a8e25 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -21,6 +21,10 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ +activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__) +$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path) +require 'active_support' + require 'rack' module Rack @@ -74,7 +78,3 @@ module ActionDispatch end autoload :Mime, 'action_dispatch/http/mime_type' - -activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" -$:.unshift activesupport_path if File.directory?(activesupport_path) -require 'active_support' diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index 06238ca747..c3e42ac0d5 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -21,7 +21,12 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ -require File.join(File.dirname(__FILE__), "action_pack") +activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__) +$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path) +require 'active_support' +require 'active_support/core_ext/class/attribute_accessors' + +require 'action_pack' module ActionView extend ActiveSupport::Autoload @@ -51,10 +56,4 @@ end require 'action_view/erb/util' - I18n.load_path << "#{File.dirname(__FILE__)}/action_view/locale/en.yml" - -activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" -$:.unshift activesupport_path if File.directory?(activesupport_path) -require 'active_support' -require 'active_support/core_ext/class/attribute_accessors' diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 4dae1ab873..a9341b60df 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -1,12 +1,9 @@ -root = File.expand_path('../../..', __FILE__) begin - require "#{root}/vendor/gems/environment" + require File.expand_path('../../../vendor/gems/environment', __FILE__) rescue LoadError - $:.unshift "#{root}/activesupport/lib" - $:.unshift "#{root}/activemodel/lib" end -lib = File.expand_path("#{File.dirname(__FILE__)}/../lib") +lib = File.expand_path('../../lib', __FILE__) $:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) $:.unshift(File.dirname(__FILE__) + '/lib') @@ -16,18 +13,20 @@ $:.unshift(File.dirname(__FILE__) + '/fixtures/alternate_helpers') ENV['TMPDIR'] = File.join(File.dirname(__FILE__), 'tmp') require 'test/unit' -require 'active_support' -require 'active_support/test_case' require 'abstract_controller' require 'action_controller' require 'action_view' require 'action_view/base' require 'action_dispatch' -require 'active_model' require 'fixture_template' +require 'active_support/test_case' require 'action_view/test_case' require 'active_support/dependencies' +activemodel_path = File.expand_path('../../../activemodel/lib', __FILE__) +$:.unshift(activemodel_path) if File.directory?(activemodel_path) && !$:.include?(activemodel_path) +require 'active_model' + begin require 'ruby-debug' Debugger.settings[:autoeval] = true -- cgit v1.2.3 From 7217d64f615ec064f15c9b2999e98e54997fe67c Mon Sep 17 00:00:00 2001 From: Joshua Peek <josh@joshpeek.com> Date: Wed, 16 Dec 2009 16:11:42 -0600 Subject: Use AbstractController error constants --- actionpack/lib/action_dispatch/middleware/show_exceptions.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index 471d18491c..bd87764f5b 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -10,8 +10,7 @@ module ActionDispatch @@rescue_responses = Hash.new(:internal_server_error) @@rescue_responses.update({ 'ActionController::RoutingError' => :not_found, - # TODO: Clean this up after the switch - ActionController::UnknownAction.name => :not_found, + 'AbstractController::ActionNotFound' => :not_found, 'ActiveRecord::RecordNotFound' => :not_found, 'ActiveRecord::StaleObjectError' => :conflict, 'ActiveRecord::RecordInvalid' => :unprocessable_entity, @@ -26,7 +25,7 @@ module ActionDispatch @@rescue_templates.update({ 'ActionView::MissingTemplate' => 'missing_template', 'ActionController::RoutingError' => 'routing_error', - ActionController::UnknownAction.name => 'unknown_action', + 'AbstractController::ActionNotFound' => 'unknown_action', 'ActionView::Template::Error' => 'template_error' }) -- cgit v1.2.3