From e1385be025263fad6d339010d42fe553d1de64af Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 17 Nov 2009 23:36:48 -0800 Subject: Extract form_authenticity_param instance method so it's overridable in subclasses --- actionpack/lib/action_controller/metal/request_forgery_protection.rb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index 113c20a758..173df79ee7 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -101,6 +101,11 @@ module ActionController #:nodoc: session[:_csrf_token] ||= ActiveSupport::SecureRandom.base64(32) end + # The form's authenticity parameter. Override to provide your own. + def form_authenticity_param + params[request_forgery_protection_token] + end + def protect_against_forgery? allow_forgery_protection end -- cgit v1.2.3 From 5df26dd7a91bb6d248b96c4308242a51ab59aa5c Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 18 Nov 2009 16:39:40 -0600 Subject: Add basic nested named route support to new routing dsl. Also add a bunch of pending tests. --- actionpack/lib/action_dispatch/routing/mapper.rb | 26 ++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 7d770dedd0..6e112c9b54 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -52,30 +52,38 @@ module ActionDispatch resource = resources.pop + plural = resource.to_s + singular = plural.singularize + if @scope[:scope_level] == :resources - member do - resources(resource, options, &block) + 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) + end end return self end - plural = resource.to_s - singular = plural.singularize + 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) do + with_scope_level(:resources, :name => singular) do yield if block_given? member do - get "", :to => :show, :as => "#{singular}" + 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}" + get "", :to => :index, :as => plural post "", :to => :create get "new", :to => :new, :as => "new_#{singular}" end @@ -127,11 +135,13 @@ module ActionDispatch end private - def with_scope_level(kind) + def with_scope_level(kind, options = {}) old, @scope[:scope_level] = @scope[:scope_level], kind + old_options, @scope[:scope_level_options] = @scope[:scope_level_options], options yield ensure @scope[:scope_level] = old + @scope[:scope_level_options] = old_options end end -- cgit v1.2.3 From 4b325fcd1af4eeb44dae5a741d85ea09d3845e4e Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 14 Nov 2009 22:00:38 -0600 Subject: Update routing for rackmount 0.2 api changes --- .../lib/action_dispatch/routing/route_set.rb | 65 ++++------------------ 1 file changed, 11 insertions(+), 54 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index c28df76f3f..c15aaceb5b 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -372,7 +372,17 @@ module ActionDispatch end recall[:action] = options.delete(:action) if options[:action] == 'index' - path = _uri(named_route, options, recall) + parameterize = lambda { |name, value| + if name == :controller + value + elsif value.is_a?(Array) + value.map { |v| Rack::Mount::Utils.escape_uri(v.to_param) }.join('/') + else + Rack::Mount::Utils.escape_uri(value.to_param) + end + } + + path = @set.url(named_route, options, recall, :parameterize => parameterize) if path && method == :generate_extras uri = URI(path) extras = uri.query ? @@ -439,59 +449,6 @@ module ActionDispatch def extract_request_environment(request) { :method => request.method } end - - private - def _uri(named_route, params, recall) - params = URISegment.wrap_values(params) - recall = URISegment.wrap_values(recall) - - unless result = @set.generate(:path_info, named_route, params, recall) - return - end - - uri, params = result - params.each do |k, v| - if v._value - params[k] = v._value - else - params.delete(k) - end - end - - uri << "?#{Rack::Mount::Utils.build_nested_query(params)}" if uri && params.any? - uri - end - - class URISegment < Struct.new(:_value, :_escape) - EXCLUDED = [:controller] - - def self.wrap_values(hash) - hash.inject({}) { |h, (k, v)| - h[k] = new(v, !EXCLUDED.include?(k.to_sym)) - h - } - end - - extend Forwardable - def_delegators :_value, :==, :eql?, :hash - - def to_param - @to_param ||= begin - if _value.is_a?(Array) - _value.map { |v| _escaped(v) }.join('/') - else - _escaped(_value) - end - end - end - alias_method :to_s, :to_param - - private - def _escaped(value) - v = value.respond_to?(:to_param) ? value.to_param : value - _escape ? Rack::Mount::Utils.escape_uri(v) : v.to_s - end - end end end end -- cgit v1.2.3 From ef771552b74aa03925c201603f9430602192e818 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 23 Nov 2009 18:59:17 -0600 Subject: Don't really care about reloading routes when inflections are changed. --- actionpack/lib/action_dispatch/routing.rb | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index 68ed1e3340..016cf62ce7 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -366,16 +366,5 @@ module ActionDispatch end end end - - ActiveSupport::Inflector.module_eval do - # Ensures that routes are reloaded when Rails inflections are updated. - def inflections_with_route_reloading(&block) - returning(inflections_without_route_reloading(&block)) { - ActionDispatch::Routing::Routes.reload! if block_given? - } - end - - alias_method_chain :inflections, :route_reloading - end end end -- cgit v1.2.3 From 01c9f99c5370031fcce32931d45b4ca3070cbb3d Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 23 Nov 2009 19:17:53 -0600 Subject: Kill dead routing internals helpers --- actionpack/lib/action_dispatch/routing.rb | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index 016cf62ce7..751dbb88d3 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -264,11 +264,8 @@ module ActionDispatch autoload :RouteSet, 'action_dispatch/routing/route_set' SEPARATORS = %w( / . ? ) - HTTP_METHODS = [:get, :head, :post, :put, :delete, :options] - ALLOWED_REQUIREMENTS_FOR_OPTIMISATION = [:controller, :action].to_set - # The root paths which may contain controller files mattr_accessor :controller_paths self.controller_paths = [] @@ -342,29 +339,6 @@ module ActionDispatch def use_controllers!(controller_names) @possible_controllers = controller_names end - - # Returns a controller path for a new +controller+ based on a +previous+ controller path. - # Handles 4 scenarios: - # - # * stay in the previous controller: - # controller_relative_to( nil, "groups/discussion" ) # => "groups/discussion" - # - # * stay in the previous namespace: - # controller_relative_to( "posts", "groups/discussion" ) # => "groups/posts" - # - # * forced move to the root namespace: - # controller_relative_to( "/posts", "groups/discussion" ) # => "posts" - # - # * previous namespace is root: - # controller_relative_to( "posts", "anything_with_no_slashes" ) # =>"posts" - # - def controller_relative_to(controller, previous) - if controller.nil? then previous - elsif controller[0] == ?/ then controller[1..-1] - elsif %r{^(.*)/} =~ previous then "#{$1}/#{controller}" - else controller - end - end end end end -- cgit v1.2.3 From 8d351eac078642505057351e7113100550ed8bc7 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 23 Nov 2009 19:44:43 -0600 Subject: Extract Routing.controller_constraints --- actionpack/lib/action_dispatch/routing.rb | 4 ++++ actionpack/lib/action_dispatch/routing/deprecated_mapper.rb | 3 +-- actionpack/lib/action_dispatch/routing/mapper.rb | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index 751dbb88d3..e0857fb2b1 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -276,6 +276,10 @@ module ActionDispatch end class << self + def controller_constraints + Regexp.union(*possible_controllers.collect { |n| Regexp.escape(n) }) + end + # Expects an array of controller names as the first argument. # Executes the passed block with only the named controllers named available. # This method is used in internal Rails testing. diff --git a/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb b/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb index 0564ba9797..dd76391870 100644 --- a/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb +++ b/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb @@ -113,8 +113,7 @@ module ActionDispatch end end - possible_names = Routing.possible_controllers.collect { |n| Regexp.escape(n) } - requirements[:controller] ||= Regexp.union(*possible_names) + requirements[:controller] ||= Routing.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 6e112c9b54..cfe7425a61 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -282,6 +282,8 @@ module ActionDispatch constraints.reject! { |k, v| segment_keys.include?(k.to_s) } conditions.merge!(constraints) + requirements[:controller] ||= Routing.controller_constraints + if via = options[:via] via = Array(via).map { |m| m.to_s.upcase } conditions[:request_method] = Regexp.union(*via) -- cgit v1.2.3 From f987e8561c2fdbf5f6ade34d68f66b6e7e19d8d3 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 23 Nov 2009 19:45:42 -0600 Subject: with_controllers is no longer used --- actionpack/lib/action_dispatch/routing.rb | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index e0857fb2b1..4bb7713c98 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -280,17 +280,6 @@ module ActionDispatch Regexp.union(*possible_controllers.collect { |n| Regexp.escape(n) }) end - # Expects an array of controller names as the first argument. - # Executes the passed block with only the named controllers named available. - # This method is used in internal Rails testing. - def with_controllers(names) - prior_controllers = @possible_controllers - use_controllers! names - yield - ensure - use_controllers! prior_controllers - end - # Returns an array of paths, cleaned of double-slashes and relative path references. # * "\\\" and "//" become "\\" or "/". # * "/foo/bar/../config" becomes "/foo/config". -- cgit v1.2.3 From 15ab3a98a1b6f9b829060ba974048b33466f6814 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 23 Nov 2009 20:20:50 -0600 Subject: Find all controllers in memory to use for routing --- actionpack/lib/action_dispatch/routing.rb | 19 ++++++++++++------- actionpack/lib/action_dispatch/routing/route_set.rb | 4 +++- 2 files changed, 15 insertions(+), 8 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index 4bb7713c98..b43b77fecb 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -280,6 +280,10 @@ module ActionDispatch Regexp.union(*possible_controllers.collect { |n| Regexp.escape(n) }) end + def clear_controller_cache! + @possible_controllers = nil + end + # Returns an array of paths, cleaned of double-slashes and relative path references. # * "\\\" and "//" become "\\" or "/". # * "/foo/bar/../config" becomes "/foo/config". @@ -307,8 +311,15 @@ module ActionDispatch unless @possible_controllers @possible_controllers = [] - paths = controller_paths.select { |path| File.directory?(path) && path != "." } + # Find any controller classes already in memory + ActionController::Base.subclasses.each do |klass| + controller_name = klass.underscore + controller_name.gsub!(/_controller\Z/, '') + @possible_controllers << controller_name + 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| Dir["#{load_path}/**/*_controller.rb"].collect do |path| @@ -326,12 +337,6 @@ module ActionDispatch end @possible_controllers end - - # Replaces the internal list of controllers available to ActionController::Routing with the passed argument. - # ActionController::Routing.use_controllers!([ "posts", "comments", "admin/comments" ]) - def use_controllers!(controller_names) - @possible_controllers = controller_names - end end end end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index c15aaceb5b..79e15edeaa 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -246,7 +246,9 @@ module ActionDispatch end def load! - Routing.use_controllers!(nil) # Clear the controller cache so we may discover new ones + # Clear the controller cache so we may discover new ones + Routing.clear_controller_cache! + load_routes! end -- cgit v1.2.3 From 59dbae145b939ca733b7fc9ed0205b01c3d6799c Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 23 Nov 2009 21:50:21 -0600 Subject: Privatize Routing.possible_controllers and fix brittle url helper controller test loading. --- actionpack/lib/action_dispatch/routing.rb | 66 +++++++++++++++---------------- 1 file changed, 33 insertions(+), 33 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index b43b77fecb..9b977800b4 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -277,45 +277,23 @@ module ActionDispatch class << self def controller_constraints - Regexp.union(*possible_controllers.collect { |n| Regexp.escape(n) }) + @controller_constraints ||= Regexp.union(*possible_controllers.collect { |n| Regexp.escape(n) }) end def clear_controller_cache! - @possible_controllers = nil + @controller_constraints = nil 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 } - end - - # Returns the array of controller names currently available to ActionController::Routing. - def possible_controllers - unless @possible_controllers - @possible_controllers = [] + private + # Returns the array of controller names currently available to ActionController::Routing. + def possible_controllers + possible_controllers = [] # Find any controller classes already in memory ActionController::Base.subclasses.each do |klass| controller_name = klass.underscore controller_name.gsub!(/_controller\Z/, '') - @possible_controllers << controller_name + possible_controllers << controller_name end # Find controllers in controllers/ directory @@ -328,15 +306,37 @@ module ActionDispatch controller_name = path[(load_path.length + 1)..-1] controller_name.gsub!(/_controller\.rb\Z/, '') - @possible_controllers << controller_name + possible_controllers << controller_name end end # remove duplicates - @possible_controllers.uniq! + 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 } end - @possible_controllers - end end end end -- cgit v1.2.3 From 45d8ff08a449d694f33e42ec2f97515d790e3cf7 Mon Sep 17 00:00:00 2001 From: Yehuda Katz 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/lib') 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 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/lib') 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} %> -

RAILS_ROOT: <%= defined?(RAILS_ROOT) ? RAILS_ROOT : "unset" %>

+

Rails.root: <%= defined?(Rails) && Rails.respond_to?(:root) ? Rails.root : "unset" %>

<% names.each do |name| %> -- cgit v1.2.3 From 3f025e64083c4a0cde4841254a88ef54780824f9 Mon Sep 17 00:00:00 2001 From: Joshua Peek 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/lib') 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 40ae2070d57867bac1c9e7f77c25ac7ac7b5a647 Mon Sep 17 00:00:00 2001 From: Joshua Peek 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/lib') 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 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/lib') 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 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/lib') 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 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/lib') 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 Date: Sun, 29 Nov 2009 18:17:14 -0600 Subject: Fix some nested resource generation tests --- actionpack/lib/action_dispatch/routing/mapper.rb | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'actionpack/lib') 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 -- cgit v1.2.3 From 6e30361260205cb7029fbc78b4a98b66a884ce45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= 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 --- actionpack/lib/action_controller/metal/responder.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'actionpack/lib') 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 -- cgit v1.2.3 From 61a31f3d3dae55b3ed2a49fafcbfe45b77ea3be2 Mon Sep 17 00:00:00 2001 From: Joshua Peek 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') 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 -- cgit v1.2.3 From 7fe19d415ab80727d685c163d7a0413ca6bfe585 Mon Sep 17 00:00:00 2001 From: Joshua Peek 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 +++ 1 file changed, 3 insertions(+) (limited to 'actionpack/lib') 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) -- cgit v1.2.3 From 2fbd6f46fd00a334119f1a25394046963831ce3e Mon Sep 17 00:00:00 2001 From: Joshua Peek 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/lib') 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 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/lib') 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 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/lib') 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 f22db809c9da89adac0be60c5b70f37f75dc8376 Mon Sep 17 00:00:00 2001 From: Joshua Peek 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/lib') 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 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/lib') 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 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') 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 -- cgit v1.2.3 From 84be6cfb6452a23d5617cd8a8b200d8fb0431d5a Mon Sep 17 00:00:00 2001 From: Joshua Peek 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/lib') 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 4dee277a9bc05083de6c831cf9aae0846849ecda Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 2 Dec 2009 12:46:14 -0600 Subject: Stop escaping "[]" in query string --- actionpack/lib/action_dispatch/routing/route_set.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'actionpack/lib') 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) -- cgit v1.2.3 From 8db038227ca4cbcba01a86ef5fb94cb13c780463 Mon Sep 17 00:00:00 2001 From: Joshua Peek 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/lib') 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 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/lib') 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 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 +- 30 files changed, 828 insertions(+), 786 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/lib') 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:: 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: + # + # @controller:: + # The controller instance that will be tested. + # @request:: + # 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. + # @response:: + # An ActionController::TestResponse object, representing the response + # of the last HTTP response. In the above example, @response 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: tests WidgetController. + 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: - # - # @controller:: - # The controller instance that will be tested. - # @request:: - # 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. - # @response:: - # An ActionController::TestResponse object, representing the response - # of the last HTTP response. In the above example, @response 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: tests WidgetController. - 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 -- cgit v1.2.3 From 96e0638ce2a287eb5c43266fb4eb3e656e9968cf Mon Sep 17 00:00:00 2001 From: Yehuda Katz 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/lib') 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 324fa688fcd8f5b6a8e9a0226b0cb3d2829e122c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 2 Dec 2009 22:48:05 -0200 Subject: Make controller.flash public to be used in responders. Signed-off-by: Yehuda Katz --- actionpack/lib/action_controller/metal/flash.rb | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'actionpack/lib') 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 flash["notice"] to + # read a notice you put there or flash["notice"] = "hello" + # 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 flash["notice"] to - # read a notice you put there or flash["notice"] = "hello" - # 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?= Date: Wed, 2 Dec 2009 22:47:09 -0200 Subject: Responder redirects to resource if destroy fails. Signed-off-by: Yehuda Katz --- actionpack/lib/action_controller/metal/responder.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') 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 -- cgit v1.2.3 From 66375434b6c7e03a396bbeda3f7029dea2a59f23 Mon Sep 17 00:00:00 2001 From: Joshua Peek 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/lib') 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 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 +++++++++++++++--------- 1 file changed, 21 insertions(+), 13 deletions(-) (limited to 'actionpack/lib') 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 -- cgit v1.2.3 From e8489b43e2746d9b3605eef86731232fa823ce69 Mon Sep 17 00:00:00 2001 From: Joshua Peek 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 ++++++++---------------- 1 file changed, 20 insertions(+), 40 deletions(-) (limited to 'actionpack/lib') 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 -- cgit v1.2.3 From 5835447b6fbc956f22011fc33bcc882db144c7c1 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 7 Dec 2009 19:31:29 -0600 Subject: named_prefix doesn't join with "_" --- actionpack/lib/action_dispatch/routing/mapper.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'actionpack/lib') 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) -- cgit v1.2.3 From e600b41c7f2029b1fb4b75b90acc3379acf95d2b Mon Sep 17 00:00:00 2001 From: Joshua Peek 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/lib') 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 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/lib') 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 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/lib') 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 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/lib') 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 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 ++++++++++++++---------- 1 file changed, 34 insertions(+), 26 deletions(-) (limited to 'actionpack/lib') 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) -- cgit v1.2.3 From 3d91d7f0a2bd4b1e104dd8847a2fe9f206c916ca Mon Sep 17 00:00:00 2001 From: Joshua Peek 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') 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 -- cgit v1.2.3 From 33658ea1ae4170f4b0b5123e240d79bb292719e7 Mon Sep 17 00:00:00 2001 From: Joshua Peek 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/lib') 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 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/lib') 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 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/lib') 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 511cef296bd07fa43794e029e12e4cd1053aa8d1 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 8 Dec 2009 17:19:49 -0600 Subject: Tack format onto resource routes --- actionpack/lib/action_dispatch/routing/mapper.rb | 44 ++++++++++++------------ 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'actionpack/lib') 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 -- cgit v1.2.3 From f9d570bdd80010825c21eb32204471ba525915fa Mon Sep 17 00:00:00 2001 From: Carlhuda 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 +++++++++------------ 1 file changed, 45 insertions(+), 56 deletions(-) (limited to 'actionpack/lib') 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 -- cgit v1.2.3 From ec5434c3c2631bb47b568eede397c3bd596eeb88 Mon Sep 17 00:00:00 2001 From: Joshua Peek 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 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'actionpack/lib') 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 -- cgit v1.2.3 From c517a4fb9a6388ab561615f8556043ce03d531bd Mon Sep 17 00:00:00 2001 From: Nathan Weizenbaum 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 --- actionpack/lib/action_view.rb | 4 ++++ actionpack/lib/action_view/template/error.rb | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'actionpack/lib') 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 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/lib') 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 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/lib') 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 Date: Thu, 10 Dec 2009 23:45:04 -0600 Subject: Kill RouteSet#recognize --- actionpack/lib/action_dispatch/routing/route_set.rb | 12 ------------ actionpack/lib/action_dispatch/testing/assertions/routing.rb | 6 ++++-- 2 files changed, 4 insertions(+), 14 deletions(-) (limited to 'actionpack/lib') 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 -- cgit v1.2.3 From 588225f8852c4b60bfba38f16d8797a41e175400 Mon Sep 17 00:00:00 2001 From: Joshua Peek 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 +--------------------- 2 files changed, 2 insertions(+), 33 deletions(-) (limited to 'actionpack/lib') 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 -- cgit v1.2.3 From 61e9f2023baead046c7f8ba7c89a7496bf49d1be Mon Sep 17 00:00:00 2001 From: Joshua Peek 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/lib') 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 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 +++++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'actionpack/lib') 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 -- cgit v1.2.3 From ee395fe626760e897abd9e881b54d3cc3f407d31 Mon Sep 17 00:00:00 2001 From: Joshua Peek 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 +- 8 files changed, 104 insertions(+), 124 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/lib') 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 ActionController::TestUploadedFile.new(ActionController::TestCase.fixture_path + path, type): - # - # post :change_avatar, :avatar => fixture_file_upload('/files/spongebob.png', 'image/png') - # - # To upload binary files on Windows, pass :binary 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 map.draw { map.connect ... }: - # - # 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 map.draw { map.connect ... }: + # + # 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 ARack::Test::UploadedFile.new(ActionController::TestCase.fixture_path + path, type): + # + # post :change_avatar, :avatar => fixture_file_upload('/files/spongebob.png', 'image/png') + # + # To upload binary files on Windows, pass :binary 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 -- cgit v1.2.3 From 018dafe574d370165547516ffef43394e11ab4da Mon Sep 17 00:00:00 2001 From: Joshua Peek 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/lib') 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 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/lib') 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:: If a String is provided, it gets converted into - # the default view path. You may also provide a custom view path + # path:: 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:: If a String is provided, it gets converted into - # the default view path. You may also provide a custom view path + # path:: 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 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/lib') 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 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/lib') 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 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/lib') 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 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/lib') 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 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/lib') 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 70c3e825fc184c7267d226c7b365af4db17f58b7 Mon Sep 17 00:00:00 2001 From: Joshua Peek 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/lib') 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 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/lib') 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 5f8e48cbd297aca4add4b48efa2136ba6ac851b1 Mon Sep 17 00:00:00 2001 From: Joshua Peek 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 - 3 files changed, 21 insertions(+), 95 deletions(-) (limited to 'actionpack/lib') 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} -- cgit v1.2.3 From 7ee5843c3cedfe36a680d5b28aa31eef45296c50 Mon Sep 17 00:00:00 2001 From: Joshua Peek 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 ++++++------- 4 files changed, 19 insertions(+), 14 deletions(-) (limited to 'actionpack/lib') 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' -- cgit v1.2.3 From 7217d64f615ec064f15c9b2999e98e54997fe67c Mon Sep 17 00:00:00 2001 From: Joshua Peek 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/lib') 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 From fa575973b1ad5adb7115a18c4c1c7c31500e73b2 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 17 Dec 2009 16:37:11 -0800 Subject: Added alert/notice from 2-3-stable and refactored redirect_to into just living in Redirector [DHH] --- actionpack/lib/action_controller/base.rb | 66 ----------------- actionpack/lib/action_controller/metal/flash.rb | 41 +++++++++++ .../lib/action_controller/metal/redirector.rb | 86 ++++++++++++++++++++-- 3 files changed, 122 insertions(+), 71 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 48bfbab215..e49be371a6 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -106,71 +106,5 @@ module ActionController options = _normalize_options(action, options, &blk) super(options) end - - # Redirects the browser to the target specified in +options+. This parameter can take one of three forms: - # - # * Hash - The URL will be generated by calling url_for with the +options+. - # * Record - The URL will be generated by calling url_for with the +options+, which will reference a named URL for that record. - # * String starting with protocol:// (like http://) - Is passed straight through as the target for redirection. - # * String not containing a protocol - The current protocol and host is prepended to the string. - # * :back - Back to the page that issued the request. Useful for forms that are triggered from multiple places. - # Short-hand for redirect_to(request.env["HTTP_REFERER"]) - # - # Examples: - # redirect_to :action => "show", :id => 5 - # redirect_to post - # redirect_to "http://www.rubyonrails.org" - # redirect_to "/images/screenshot.jpg" - # redirect_to articles_url - # redirect_to :back - # - # The redirection happens as a "302 Moved" header unless otherwise specified. - # - # Examples: - # redirect_to post_url(@post), :status=>:found - # redirect_to :action=>'atom', :status=>:moved_permanently - # redirect_to post_url(@post), :status=>301 - # redirect_to :action=>'atom', :status=>302 - # - # When using redirect_to :back, if there is no referrer, - # RedirectBackError will be raised. You may specify some fallback - # behavior for this case by rescuing RedirectBackError. - def redirect_to(options = {}, response_status = {}) #:doc: - raise ActionControllerError.new("Cannot redirect to nil!") if options.nil? - - status = if options.is_a?(Hash) && options.key?(:status) - _interpret_status(options.delete(:status)) - elsif response_status.key?(:status) - _interpret_status(response_status[:status]) - else - 302 - end - - url = case options - # The scheme name consist of a letter followed by any combination of - # letters, digits, and the plus ("+"), period ("."), or hyphen ("-") - # characters; and is terminated by a colon (":"). - when %r{^\w[\w\d+.-]*:.*} - options - when String - request.protocol + request.host_with_port + options - when :back - raise RedirectBackError unless refer = request.headers["Referer"] - refer - else - url_for(options) - end - - 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_controller/metal/flash.rb b/actionpack/lib/action_controller/metal/flash.rb index 9d08ed6081..ae343444e2 100644 --- a/actionpack/lib/action_controller/metal/flash.rb +++ b/actionpack/lib/action_controller/metal/flash.rb @@ -30,6 +30,10 @@ module ActionController #:nodoc: include Session + included do + helper_method :alert, :notice + end + class FlashNow #:nodoc: def initialize(flash) @flash = flash @@ -147,6 +151,27 @@ module ActionController #:nodoc: @_flash end + # Convenience accessor for flash[:alert] + def alert + flash[:alert] + end + + # Convenience accessor for flash[:alert]= + def alert=(message) + flash[:alert] = message + end + + # Convenience accessor for flash[:notice] + def notice + flash[:notice] + end + + # Convenience accessor for flash[:notice]= + def notice=(message) + flash[:notice] = message + end + + protected def process_action(method_name) @_flash = nil @@ -159,5 +184,21 @@ module ActionController #:nodoc: super @_flash = nil end + + def redirect_to(options = {}, response_status_and_flash = {}) #:doc: + if alert = response_status_and_flash.delete(:alert) + flash[:alert] = alert + end + + if notice = response_status_and_flash.delete(:notice) + flash[:notice] = notice + end + + if other_flashes = response_status_and_flash.delete(:flash) + flash.update(other_flashes) + end + + super(options, response_status_and_flash) + end end end diff --git a/actionpack/lib/action_controller/metal/redirector.rb b/actionpack/lib/action_controller/metal/redirector.rb index b55f5e7bfc..a7bd5ee981 100644 --- a/actionpack/lib/action_controller/metal/redirector.rb +++ b/actionpack/lib/action_controller/metal/redirector.rb @@ -11,12 +11,88 @@ module ActionController extend ActiveSupport::Concern include AbstractController::Logger - def redirect_to(url, status) #:doc: + # Redirects the browser to the target specified in +options+. This parameter can take one of three forms: + # + # * Hash - The URL will be generated by calling url_for with the +options+. + # * Record - The URL will be generated by calling url_for with the +options+, which will reference a named URL for that record. + # * String starting with protocol:// (like http://) - Is passed straight through as the target for redirection. + # * String not containing a protocol - The current protocol and host is prepended to the string. + # * :back - Back to the page that issued the request. Useful for forms that are triggered from multiple places. + # Short-hand for redirect_to(request.env["HTTP_REFERER"]) + # + # Examples: + # redirect_to :action => "show", :id => 5 + # redirect_to post + # redirect_to "http://www.rubyonrails.org" + # redirect_to "/images/screenshot.jpg" + # redirect_to articles_url + # redirect_to :back + # + # The redirection happens as a "302 Moved" header unless otherwise specified. + # + # Examples: + # redirect_to post_url(@post), :status => :found + # redirect_to :action=>'atom', :status => :moved_permanently + # redirect_to post_url(@post), :status => 301 + # redirect_to :action=>'atom', :status => 302 + # + # It is also possible to assign a flash message as part of the redirection. There are two special accessors for commonly used the flash names + # +alert+ and +notice+ as well as a general purpose +flash+ bucket. + # + # Examples: + # redirect_to post_url(@post), :alert => "Watch it, mister!" + # redirect_to post_url(@post), :status=> :found, :notice => "Pay attention to the road" + # redirect_to post_url(@post), :status => 301, :flash => { :updated_post_id => @post.id } + # redirect_to { :action=>'atom' }, :alert => "Something serious happened" + # + # When using redirect_to :back, if there is no referrer, + # RedirectBackError will be raised. You may specify some fallback + # behavior for this case by rescuing RedirectBackError. + def redirect_to(options = {}, response_status = {}) #:doc: + raise ActionControllerError.new("Cannot redirect to nil!") if options.nil? raise AbstractController::DoubleRenderError if response_body - logger.info("Redirected to #{url}") if logger && logger.info? - self.status = status - self.location = url.gsub(/[\r\n]/, '') - self.response_body = "You are being redirected." + + self.status = _extract_redirect_to_status(options, response_status) + self.location = _compute_redirect_to_location(options) + self.response_body = "You are being redirected." + + logger.info("Redirected to #{location}") if logger && logger.info? end + + private + def _extract_redirect_to_status(options, response_status) + status = if options.is_a?(Hash) && options.key?(:status) + _interpret_status(options.delete(:status)) + elsif response_status.key?(:status) + _interpret_status(response_status[:status]) + else + 302 + end + end + + def _compute_redirect_to_location(options) + case options + # The scheme name consist of a letter followed by any combination of + # letters, digits, and the plus ("+"), period ("."), or hyphen ("-") + # characters; and is terminated by a colon (":"). + when %r{^\w[\w\d+.-]*:.*} + options + when String + request.protocol + request.host_with_port + options + when :back + raise RedirectBackError unless refer = request.headers["Referer"] + refer + else + url_for(options) + end.gsub(/[\r\n]/, '') + end + + 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 -- cgit v1.2.3 From 2419fae092ec207185f9ed69c2aa1ba1cd53fffe Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Thu, 17 Dec 2009 22:10:06 -0600 Subject: Pending tests for AD Response --- actionpack/lib/action_dispatch/http/response.rb | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 378fd5e61d..6e63fc0067 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -145,18 +145,6 @@ module ActionDispatch # :nodoc: cattr_accessor(:default_charset) { "utf-8" } - def assign_default_content_type_and_charset! - return if headers[CONTENT_TYPE].present? - - @content_type ||= Mime::HTML - @charset ||= self.class.default_charset - - type = @content_type.to_s.dup - type << "; charset=#{@charset}" unless @sending_file - - headers[CONTENT_TYPE] = type - end - def to_a assign_default_content_type_and_charset! handle_conditional_get! @@ -259,6 +247,18 @@ module ActionDispatch # :nodoc: !@blank && @body.respond_to?(:all?) && @body.all? { |part| part.is_a?(String) } end + def assign_default_content_type_and_charset! + return if headers[CONTENT_TYPE].present? + + @content_type ||= Mime::HTML + @charset ||= self.class.default_charset + + type = @content_type.to_s.dup + type << "; charset=#{@charset}" unless @sending_file + + headers[CONTENT_TYPE] = type + end + DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate" def set_conditional_cache_control! @@ -280,7 +280,6 @@ module ActionDispatch # :nodoc: headers["Cache-Control"] = options.join(", ") end - end end end -- cgit v1.2.3 From 8b4735fbd9d5f6bd0c5d04688cc5edcd9b00ccf0 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Sun, 20 Dec 2009 14:06:40 -0800 Subject: Add active_support/ruby/shim to the default requirements for AP components --- actionpack/lib/abstract_controller.rb | 2 +- actionpack/lib/action_controller.rb | 2 +- actionpack/lib/action_dispatch.rb | 2 +- actionpack/lib/action_view.rb | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index 109a3a3385..d13a56a859 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -1,7 +1,7 @@ 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/ruby/shim' require 'active_support/core_ext/module/attr_internal' require 'active_support/core_ext/module/delegation' diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 37ff10e852..144850da62 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -1,6 +1,6 @@ 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/ruby/shim' module ActionController extend ActiveSupport::Autoload diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index feed6a8e25..a7be49a273 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -23,7 +23,7 @@ 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/ruby/shim' require 'rack' diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index c3e42ac0d5..aabe8c4314 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -23,7 +23,7 @@ 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/ruby/shim' require 'active_support/core_ext/class/attribute_accessors' require 'action_pack' -- cgit v1.2.3 From e48b4c2dd01877ace901e1c186d04605b53b40d0 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Sun, 20 Dec 2009 14:07:19 -0800 Subject: :to => redirect() can take a String using 1.9-style interpolation or proc that takes the path parameters as a Hash --- actionpack/lib/action_dispatch/routing/mapper.rb | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index d480af876d..57e992d7dc 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -132,13 +132,19 @@ module ActionDispatch map_method(:delete, *args, &block) end - def redirect(path, options = {}) + def redirect(*args, &block) + options = args.last.is_a?(Hash) ? args.pop : {} + + path = args.shift || block + path_proc = path.is_a?(Proc) ? path : proc {|params| path % params } status = options[:status] || 301 - lambda { |env| + + lambda do |env| req = Rack::Request.new(env) - url = req.scheme + '://' + req.host + path + params = path_proc.call(env["action_dispatch.request.path_parameters"]) + url = req.scheme + '://' + req.host + params [status, {'Location' => url, 'Content-Type' => 'text/html'}, ['Moved Permanently']] - } + end end private -- cgit v1.2.3 From c06aff0a7e42868e9788d6cefe5ce49e93cbf45b Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 20 Dec 2009 14:33:13 -0800 Subject: Added cookies.permanent, cookies.signed, and cookies.permanent.signed accessor for common cookie actions [DHH] --- actionpack/lib/action_controller/metal/cookies.rb | 168 +++++++++++++++++----- 1 file changed, 130 insertions(+), 38 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/metal/cookies.rb b/actionpack/lib/action_controller/metal/cookies.rb index 6855ca1478..8db665e929 100644 --- a/actionpack/lib/action_controller/metal/cookies.rb +++ b/actionpack/lib/action_controller/metal/cookies.rb @@ -50,56 +50,148 @@ module ActionController #:nodoc: included do helper_method :cookies + cattr_accessor :cookie_verifier_secret end - protected - # Returns the cookie container, which operates as described above. - def cookies - @cookies ||= CookieJar.build(request, response) + protected + # Returns the cookie container, which operates as described above. + def cookies + @cookies ||= CookieJar.build(request, response) + end end - end - class CookieJar < Hash #:nodoc: - def self.build(request, response) - new.tap do |hash| - hash.update(request.cookies) - hash.response = response + class CookieJar < Hash #:nodoc: + def self.build(request, response) + new.tap do |hash| + hash.update(request.cookies) + hash.response = response + end end - end - attr_accessor :response + attr_accessor :response - # Returns the value of the cookie by +name+, or +nil+ if no such cookie exists. - def [](name) - super(name.to_s) - end + # Returns the value of the cookie by +name+, or +nil+ if no such cookie exists. + def [](name) + super(name.to_s) + end + + # Sets the cookie named +name+. The second argument may be the very cookie + # value, or a hash of options as documented above. + def []=(key, options) + if options.is_a?(Hash) + options.symbolize_keys! + value = options[:value] + else + value = options + options = { :value => value } + end - # Sets the cookie named +name+. The second argument may be the very cookie - # value, or a hash of options as documented above. - def []=(key, options) - if options.is_a?(Hash) + super(key.to_s, value) + + options[:path] ||= "/" + response.set_cookie(key, options) + end + + # Removes the cookie on the client machine by setting the value to an empty string + # and setting its expiration date into the past. Like []=, you can pass in + # an options hash to delete cookies with extra data such as a :path. + def delete(key, options = {}) options.symbolize_keys! - value = options[:value] - else - value = options - options = { :value => value } + options[:path] ||= "/" + value = super(key.to_s) + response.delete_cookie(key, options) + value end - super(key.to_s, value) - - options[:path] ||= "/" - response.set_cookie(key, options) + # Returns a jar that'll automatically set the assigned cookies to have an expiration date 20 years from now. Example: + # + # cookies.permanent[:prefers_open_id] = true + # # => Set-Cookie: prefers_open_id=true; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT + # + # This jar is only meant for writing. You'll read permanent cookies through the regular accessor. + # + # This jar allows chaining with the signed jar as well, so you can set permanent, signed cookies. Examples: + # + # cookies.permanent.signed[:remember_me] = current_user.id + # # => Set-Cookie: discount=BAhU--848956038e692d7046deab32b7131856ab20e14e; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT + def permanent + @permanent ||= PermanentCookieJar.new(self) + end + + # Returns a jar that'll automatically generate a signed representation of cookie value and verify it when reading from + # the cookie again. This is useful for creating cookies with values that the user is not supposed to change. If a signed + # cookie was tampered with by the user (or a 3rd party), an ActiveSupport::MessageVerifier::InvalidSignature exception will + # be raised. + # + # This jar requires that you set a suitable secret for the verification on ActionController::Base.cookie_verifier_secret. + # + # Example: + # + # cookies.signed[:discount] = 45 + # # => Set-Cookie: discount=BAhpMg==--2c1c6906c90a3bc4fd54a51ffb41dffa4bf6b5f7; path=/ + # + # cookies.signed[:discount] # => 45 + def signed + @signed ||= SignedCookieJar.new(self) + end end - - # Removes the cookie on the client machine by setting the value to an empty string - # and setting its expiration date into the past. Like []=, you can pass in - # an options hash to delete cookies with extra data such as a :path. - def delete(key, options = {}) - options.symbolize_keys! - options[:path] ||= "/" - value = super(key.to_s) - response.delete_cookie(key, options) - value + + class PermanentCookieJar < CookieJar #:nodoc: + def initialize(parent_jar) + @parent_jar = parent_jar + end + + def []=(key, options) + if options.is_a?(Hash) + options.symbolize_keys! + else + options = { :value => options } + end + + options[:expires] = 20.years.from_now + @parent_jar[key] = options + end + + def signed + @signed ||= SignedCookieJar.new(self) + end + + def controller + @parent_jar.controller + end + + def method_missing(method, *arguments, &block) + @parent_jar.send(method, *arguments, &block) + end end + + class SignedCookieJar < CookieJar #:nodoc: + def initialize(parent_jar) + unless ActionController::Base.cookie_verifier_secret + raise "You must set ActionController::Base.cookie_verifier_secret to use signed cookies" + end + + @parent_jar = parent_jar + @verifier = ActiveSupport::MessageVerifier.new(ActionController::Base.cookie_verifier_secret) + end + + def [](name) + @verifier.verify(@parent_jar[name]) + end + + def []=(key, options) + if options.is_a?(Hash) + options.symbolize_keys! + options[:value] = @verifier.generate(options[:value]) + else + options = { :value => @verifier.generate(options) } + end + + @parent_jar[key] = options + end + + def method_missing(method, *arguments, &block) + @parent_jar.send(method, *arguments, &block) + end end end -- cgit v1.2.3 From 83f4d86a9330533ec9af21ba18b4ab28011b8981 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 20 Dec 2009 17:15:31 -0800 Subject: Rename the RenderingController module to just plain Rendering --- actionpack/lib/abstract_controller.rb | 2 +- actionpack/lib/abstract_controller/helpers.rb | 2 +- actionpack/lib/abstract_controller/layouts.rb | 2 +- actionpack/lib/abstract_controller/rendering.rb | 203 +++++++++++++++++++++ .../abstract_controller/rendering_controller.rb | 203 --------------------- actionpack/lib/action_controller.rb | 2 +- actionpack/lib/action_controller/base.rb | 2 +- actionpack/lib/action_controller/metal/layouts.rb | 2 +- .../lib/action_controller/metal/rendering.rb | 57 ++++++ .../metal/rendering_controller.rb | 57 ------ .../lib/action_controller/metal/streaming.rb | 2 +- .../lib/action_controller/metal/verification.rb | 2 +- 12 files changed, 268 insertions(+), 268 deletions(-) create mode 100644 actionpack/lib/abstract_controller/rendering.rb delete mode 100644 actionpack/lib/abstract_controller/rendering_controller.rb create mode 100644 actionpack/lib/action_controller/metal/rendering.rb delete mode 100644 actionpack/lib/action_controller/metal/rendering_controller.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index d13a56a859..c15a1da98a 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -15,6 +15,6 @@ module AbstractController autoload :Layouts autoload :LocalizedCache autoload :Logger - autoload :RenderingController + autoload :Rendering end end diff --git a/actionpack/lib/abstract_controller/helpers.rb b/actionpack/lib/abstract_controller/helpers.rb index d3b492ad09..1d898d1a4c 100644 --- a/actionpack/lib/abstract_controller/helpers.rb +++ b/actionpack/lib/abstract_controller/helpers.rb @@ -4,7 +4,7 @@ module AbstractController module Helpers extend ActiveSupport::Concern - include RenderingController + include Rendering def self.next_serial @helper_serial ||= 0 diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb index c71cef42b2..46760bba7c 100644 --- a/actionpack/lib/abstract_controller/layouts.rb +++ b/actionpack/lib/abstract_controller/layouts.rb @@ -2,7 +2,7 @@ module AbstractController module Layouts extend ActiveSupport::Concern - include RenderingController + include Rendering included do extlib_inheritable_accessor(:_layout_conditions) { Hash.new } diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb new file mode 100644 index 0000000000..8ef2526df0 --- /dev/null +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -0,0 +1,203 @@ +require "abstract_controller/base" +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 Rendering + extend ActiveSupport::Concern + + include AbstractController::Logger + + included do + attr_internal :formats + extlib_inheritable_accessor :_view_paths + self._view_paths ||= ActionView::PathSet.new + end + + # Initialize controller with nil formats. + def initialize(*) #:nodoc: + @_formats = nil + super + end + + # 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 + # controller + # View#render_partial[options] + # - responsible for setting options[:_template] + # - Returns String with the rendered partial + # options:: see _render_partial in ActionView::Base + # View#render_template[template, layout, options, partial] + # - Returns String with the rendered template + # template:: The template to render + # layout:: The layout to render around the template + # options:: See _render_template_with_layout in ActionView::Base + # partial:: Whether or not the template to render is a partial + # + # Override this method in a to change the default behavior. + def view_context + @_view_context ||= ActionView::Base.for_controller(self) + end + + # Mostly abstracts the fact that calling render twice is a DoubleRenderError. + # Delegates render_to_body and sticks the result in self.response_body. + def render(*args) + if response_body + raise AbstractController::DoubleRenderError, "OMG" + end + + self.response_body = render_to_body(*args) + end + + # Raw rendering of a template to a Rack-compatible body. + # + # ==== Options + # _partial_object:: The object that is being rendered. If this + # exists, we are in the special case of rendering an object as a partial. + # + # :api: plugin + def render_to_body(options = {}) + # TODO: Refactor so we can just use the normal template logic for this + if options.key?(:partial) + view_context.render_partial(options) + else + _determine_template(options) + _render_template(options) + end + end + + # Raw rendering of a template to a string. Just convert the results of + # render_to_body into a String. + # + # :api: plugin + def render_to_string(options = {}) + AbstractController::Rendering.body_to_s(render_to_body(options)) + end + + # Renders the template from an object. + # + # ==== Options + # _template:: The template to render + # _layout:: The layout to wrap the template in (optional) + # _partial:: Whether or not the template to be rendered is a partial + def _render_template(options) + view_context.render_template(options) + end + + # The list of view paths for this controller. See ActionView::ViewPathSet for + # more details about writing custom view paths. + def view_paths + _view_paths + end + + # Return a string representation of a Rack-compatible response body. + def self.body_to_s(body) + if body.respond_to?(:to_str) + body + else + strings = [] + body.each { |part| strings << part.to_s } + body.close if body.respond_to?(:close) + strings.join + end + end + + private + + # Take in a set of options and determine the template to render + # + # ==== Options + # _template:: If this is provided, the search is over + # _template_name<#to_s>:: The name of the template to look up. Otherwise, + # use the current action name. + # _prefix:: The prefix to look inside of. In a file system, this corresponds + # to a directory. + # _partial:: Whether or not the file to look up is a partial + def _determine_template(options) + if options.key?(: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, {}) + options[:_template] = template + elsif options.key?(:template) + options[:_template_name] = options[:template] + elsif options.key?(:file) + options[:_template_name] = options[:file] + end + + name = (options[:_template_name] || action_name).to_s + + options[:_template] ||= with_template_cache(name) do + find_template(name, { :formats => formats }, options) + end + end + + def find_template(name, details, options) + view_paths.find(name, details, options[:_prefix], options[:_partial]) + end + + def template_exists?(name, details, options) + view_paths.exists?(name, details, options[:_prefix], options[:_partial]) + end + + def with_template_cache(name) + yield + end + + def format_for_text + Mime[:text] + end + + module ClassMethods + def clear_template_caches! + end + + # Append a path to the list of view paths for this controller. + # + # ==== Parameters + # path:: 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 + end + + # Prepend a path to the list of view paths for this controller. + # + # ==== Parameters + # path:: 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! + self.view_paths.unshift(path) + end + + # A list of all of the default view paths for this controller. + def view_paths + self._view_paths + end + + # Set the view paths. + # + # ==== Parameters + # paths:: If a ViewPathSet is provided, use that; + # otherwise, process the parameter into a ViewPathSet. + def view_paths=(paths) + clear_template_caches! + self._view_paths = paths.is_a?(ActionView::PathSet) ? + paths : ActionView::Base.process_view_paths(paths) + end + end + end +end diff --git a/actionpack/lib/abstract_controller/rendering_controller.rb b/actionpack/lib/abstract_controller/rendering_controller.rb deleted file mode 100644 index 7f2243d4ef..0000000000 --- a/actionpack/lib/abstract_controller/rendering_controller.rb +++ /dev/null @@ -1,203 +0,0 @@ -require "abstract_controller/base" -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 - - include AbstractController::Logger - - included do - attr_internal :formats - extlib_inheritable_accessor :_view_paths - self._view_paths ||= ActionView::PathSet.new - end - - # Initialize controller with nil formats. - def initialize(*) #:nodoc: - @_formats = nil - super - end - - # 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 - # controller - # View#render_partial[options] - # - responsible for setting options[:_template] - # - Returns String with the rendered partial - # options:: see _render_partial in ActionView::Base - # View#render_template[template, layout, options, partial] - # - Returns String with the rendered template - # template:: The template to render - # layout:: The layout to render around the template - # options:: See _render_template_with_layout in ActionView::Base - # partial:: Whether or not the template to render is a partial - # - # Override this method in a to change the default behavior. - def view_context - @_view_context ||= ActionView::Base.for_controller(self) - end - - # Mostly abstracts the fact that calling render twice is a DoubleRenderError. - # Delegates render_to_body and sticks the result in self.response_body. - def render(*args) - if response_body - raise AbstractController::DoubleRenderError, "OMG" - end - - self.response_body = render_to_body(*args) - end - - # Raw rendering of a template to a Rack-compatible body. - # - # ==== Options - # _partial_object:: The object that is being rendered. If this - # exists, we are in the special case of rendering an object as a partial. - # - # :api: plugin - def render_to_body(options = {}) - # TODO: Refactor so we can just use the normal template logic for this - if options.key?(:partial) - view_context.render_partial(options) - else - _determine_template(options) - _render_template(options) - end - end - - # Raw rendering of a template to a string. Just convert the results of - # render_to_body into a String. - # - # :api: plugin - def render_to_string(options = {}) - AbstractController::RenderingController.body_to_s(render_to_body(options)) - end - - # Renders the template from an object. - # - # ==== Options - # _template:: The template to render - # _layout:: The layout to wrap the template in (optional) - # _partial:: Whether or not the template to be rendered is a partial - def _render_template(options) - view_context.render_template(options) - end - - # The list of view paths for this controller. See ActionView::ViewPathSet for - # more details about writing custom view paths. - def view_paths - _view_paths - end - - # Return a string representation of a Rack-compatible response body. - def self.body_to_s(body) - if body.respond_to?(:to_str) - body - else - strings = [] - body.each { |part| strings << part.to_s } - body.close if body.respond_to?(:close) - strings.join - end - end - - private - - # Take in a set of options and determine the template to render - # - # ==== Options - # _template:: If this is provided, the search is over - # _template_name<#to_s>:: The name of the template to look up. Otherwise, - # use the current action name. - # _prefix:: The prefix to look inside of. In a file system, this corresponds - # to a directory. - # _partial:: Whether or not the file to look up is a partial - def _determine_template(options) - if options.key?(: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, {}) - options[:_template] = template - elsif options.key?(:template) - options[:_template_name] = options[:template] - elsif options.key?(:file) - options[:_template_name] = options[:file] - end - - name = (options[:_template_name] || action_name).to_s - - options[:_template] ||= with_template_cache(name) do - find_template(name, { :formats => formats }, options) - end - end - - def find_template(name, details, options) - view_paths.find(name, details, options[:_prefix], options[:_partial]) - end - - def template_exists?(name, details, options) - view_paths.exists?(name, details, options[:_prefix], options[:_partial]) - end - - def with_template_cache(name) - yield - end - - def format_for_text - Mime[:text] - end - - module ClassMethods - def clear_template_caches! - end - - # Append a path to the list of view paths for this controller. - # - # ==== Parameters - # path:: 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 - end - - # Prepend a path to the list of view paths for this controller. - # - # ==== Parameters - # path:: 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! - self.view_paths.unshift(path) - end - - # A list of all of the default view paths for this controller. - def view_paths - self._view_paths - end - - # Set the view paths. - # - # ==== Parameters - # paths:: If a ViewPathSet is provided, use that; - # otherwise, process the parameter into a ViewPathSet. - def view_paths=(paths) - clear_template_caches! - self._view_paths = paths.is_a?(ActionView::PathSet) ? - paths : ActionView::Base.process_view_paths(paths) - end - end - end -end diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 144850da62..6794596ae6 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -25,7 +25,7 @@ module ActionController autoload :RackConvenience autoload :Compatibility autoload :Redirector - autoload :RenderingController + autoload :Rendering autoload :RenderOptions autoload :Rescue autoload :Responder diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index e49be371a6..ee10584548 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -9,7 +9,7 @@ module ActionController include ActionController::HideActions include ActionController::UrlFor include ActionController::Redirector - include ActionController::RenderingController + include ActionController::Rendering include ActionController::RenderOptions::All include ActionController::Layouts include ActionController::ConditionalGet diff --git a/actionpack/lib/action_controller/metal/layouts.rb b/actionpack/lib/action_controller/metal/layouts.rb index cc7088248a..f44498a884 100644 --- a/actionpack/lib/action_controller/metal/layouts.rb +++ b/actionpack/lib/action_controller/metal/layouts.rb @@ -158,7 +158,7 @@ module ActionController module Layouts extend ActiveSupport::Concern - include ActionController::RenderingController + include ActionController::Rendering include AbstractController::Layouts module ClassMethods diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb new file mode 100644 index 0000000000..20eb524e50 --- /dev/null +++ b/actionpack/lib/action_controller/metal/rendering.rb @@ -0,0 +1,57 @@ +module ActionController + module Rendering + extend ActiveSupport::Concern + + included do + include AbstractController::Rendering + include AbstractController::LocalizedCache + end + + def process_action(*) + self.formats = request.formats.map {|x| x.to_sym} + super + end + + def render(options) + super + self.content_type ||= options[:_template].mime_type.to_s + response_body + end + + def render_to_body(options) + _process_options(options) + + if options.key?(:partial) + options[:partial] = action_name if options[:partial] == true + options[:_details] = {:formats => formats} + end + + super + end + + private + def _prefix + controller_path + end + + def _determine_template(options) + if (options.keys & [:partial, :file, :template, :text, :inline]).empty? + options[:_template_name] ||= options[:action] + options[:_prefix] = _prefix + end + + super + end + + def format_for_text + formats.first + end + + def _process_options(options) + status, content_type, location = options.values_at(:status, :content_type, :location) + self.status = status if status + self.content_type = content_type if content_type + self.headers["Location"] = url_for(location) if location + end + end +end diff --git a/actionpack/lib/action_controller/metal/rendering_controller.rb b/actionpack/lib/action_controller/metal/rendering_controller.rb deleted file mode 100644 index 237299cd30..0000000000 --- a/actionpack/lib/action_controller/metal/rendering_controller.rb +++ /dev/null @@ -1,57 +0,0 @@ -module ActionController - module RenderingController - extend ActiveSupport::Concern - - included do - include AbstractController::RenderingController - include AbstractController::LocalizedCache - end - - def process_action(*) - self.formats = request.formats.map {|x| x.to_sym} - super - end - - def render(options) - super - self.content_type ||= options[:_template].mime_type.to_s - response_body - end - - def render_to_body(options) - _process_options(options) - - if options.key?(:partial) - options[:partial] = action_name if options[:partial] == true - options[:_details] = {:formats => formats} - end - - super - end - - private - def _prefix - controller_path - end - - def _determine_template(options) - if (options.keys & [:partial, :file, :template, :text, :inline]).empty? - options[:_template_name] ||= options[:action] - options[:_prefix] = _prefix - end - - super - end - - def format_for_text - formats.first - end - - def _process_options(options) - status, content_type, location = options.values_at(:status, :content_type, :location) - self.status = status if status - self.content_type = content_type if content_type - self.headers["Location"] = url_for(location) if location - end - end -end diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb index 43c661bef4..288b5d7c99 100644 --- a/actionpack/lib/action_controller/metal/streaming.rb +++ b/actionpack/lib/action_controller/metal/streaming.rb @@ -4,7 +4,7 @@ module ActionController #:nodoc: module Streaming extend ActiveSupport::Concern - include ActionController::RenderingController + include ActionController::Rendering DEFAULT_SEND_FILE_OPTIONS = { :type => 'application/octet-stream'.freeze, diff --git a/actionpack/lib/action_controller/metal/verification.rb b/actionpack/lib/action_controller/metal/verification.rb index 500cced539..cbd169b641 100644 --- a/actionpack/lib/action_controller/metal/verification.rb +++ b/actionpack/lib/action_controller/metal/verification.rb @@ -2,7 +2,7 @@ module ActionController #:nodoc: module Verification #:nodoc: extend ActiveSupport::Concern - include AbstractController::Callbacks, Session, Flash, RenderingController + include AbstractController::Callbacks, Session, Flash, Rendering # This module provides a class-level method for specifying that certain # actions are guarded against being called without certain prerequisites -- cgit v1.2.3 From 9b41e1e4d8b9d159254dc4ad4bbd3207f1b49eb5 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 20 Dec 2009 17:25:13 -0800 Subject: Renamed Redirector to Redirecting (its a module, not a class) --- actionpack/lib/action_controller.rb | 2 +- actionpack/lib/action_controller/base.rb | 2 +- actionpack/lib/action_controller/metal.rb | 2 +- .../lib/action_controller/metal/redirecting.rb | 98 ++++++++++++++++++++++ .../lib/action_controller/metal/redirector.rb | 98 ---------------------- 5 files changed, 101 insertions(+), 101 deletions(-) create mode 100644 actionpack/lib/action_controller/metal/redirecting.rb delete mode 100644 actionpack/lib/action_controller/metal/redirector.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 6794596ae6..514b4e7fe9 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -24,7 +24,7 @@ module ActionController autoload :MimeResponds autoload :RackConvenience autoload :Compatibility - autoload :Redirector + autoload :Redirecting autoload :Rendering autoload :RenderOptions autoload :Rescue diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index ee10584548..ec64cc1a39 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -8,7 +8,7 @@ module ActionController include ActionController::Helpers include ActionController::HideActions include ActionController::UrlFor - include ActionController::Redirector + include ActionController::Redirecting include ActionController::Rendering include ActionController::RenderOptions::All include ActionController::Layouts diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index 60b3f9a89b..a1d857d2ce 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -58,7 +58,7 @@ module ActionController # Basic implementations for content_type=, location=, and headers are # provided to reduce the dependency on the RackConvenience module - # in Renderer and Redirector. + # in Rendering and Redirecting. def content_type=(type) headers["Content-Type"] = type.to_s diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb new file mode 100644 index 0000000000..d101f920e3 --- /dev/null +++ b/actionpack/lib/action_controller/metal/redirecting.rb @@ -0,0 +1,98 @@ +module ActionController + class RedirectBackError < AbstractController::Error #:nodoc: + DEFAULT_MESSAGE = 'No HTTP_REFERER was set in the request to this action, so redirect_to :back could not be called successfully. If this is a test, make sure to specify request.env["HTTP_REFERER"].' + + def initialize(message = nil) + super(message || DEFAULT_MESSAGE) + end + end + + module Redirecting + extend ActiveSupport::Concern + include AbstractController::Logger + + # Redirects the browser to the target specified in +options+. This parameter can take one of three forms: + # + # * Hash - The URL will be generated by calling url_for with the +options+. + # * Record - The URL will be generated by calling url_for with the +options+, which will reference a named URL for that record. + # * String starting with protocol:// (like http://) - Is passed straight through as the target for redirection. + # * String not containing a protocol - The current protocol and host is prepended to the string. + # * :back - Back to the page that issued the request. Useful for forms that are triggered from multiple places. + # Short-hand for redirect_to(request.env["HTTP_REFERER"]) + # + # Examples: + # redirect_to :action => "show", :id => 5 + # redirect_to post + # redirect_to "http://www.rubyonrails.org" + # redirect_to "/images/screenshot.jpg" + # redirect_to articles_url + # redirect_to :back + # + # The redirection happens as a "302 Moved" header unless otherwise specified. + # + # Examples: + # redirect_to post_url(@post), :status => :found + # redirect_to :action=>'atom', :status => :moved_permanently + # redirect_to post_url(@post), :status => 301 + # redirect_to :action=>'atom', :status => 302 + # + # It is also possible to assign a flash message as part of the redirection. There are two special accessors for commonly used the flash names + # +alert+ and +notice+ as well as a general purpose +flash+ bucket. + # + # Examples: + # redirect_to post_url(@post), :alert => "Watch it, mister!" + # redirect_to post_url(@post), :status=> :found, :notice => "Pay attention to the road" + # redirect_to post_url(@post), :status => 301, :flash => { :updated_post_id => @post.id } + # redirect_to { :action=>'atom' }, :alert => "Something serious happened" + # + # When using redirect_to :back, if there is no referrer, + # RedirectBackError will be raised. You may specify some fallback + # behavior for this case by rescuing RedirectBackError. + def redirect_to(options = {}, response_status = {}) #:doc: + raise ActionControllerError.new("Cannot redirect to nil!") if options.nil? + raise AbstractController::DoubleRenderError if response_body + + self.status = _extract_redirect_to_status(options, response_status) + self.location = _compute_redirect_to_location(options) + self.response_body = "You are being redirected." + + logger.info("Redirected to #{location}") if logger && logger.info? + end + + private + def _extract_redirect_to_status(options, response_status) + status = if options.is_a?(Hash) && options.key?(:status) + _interpret_status(options.delete(:status)) + elsif response_status.key?(:status) + _interpret_status(response_status[:status]) + else + 302 + end + end + + def _compute_redirect_to_location(options) + case options + # The scheme name consist of a letter followed by any combination of + # letters, digits, and the plus ("+"), period ("."), or hyphen ("-") + # characters; and is terminated by a colon (":"). + when %r{^\w[\w\d+.-]*:.*} + options + when String + request.protocol + request.host_with_port + options + when :back + raise RedirectBackError unless refer = request.headers["Referer"] + refer + else + url_for(options) + end.gsub(/[\r\n]/, '') + end + + 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_controller/metal/redirector.rb b/actionpack/lib/action_controller/metal/redirector.rb deleted file mode 100644 index a7bd5ee981..0000000000 --- a/actionpack/lib/action_controller/metal/redirector.rb +++ /dev/null @@ -1,98 +0,0 @@ -module ActionController - class RedirectBackError < AbstractController::Error #:nodoc: - DEFAULT_MESSAGE = 'No HTTP_REFERER was set in the request to this action, so redirect_to :back could not be called successfully. If this is a test, make sure to specify request.env["HTTP_REFERER"].' - - def initialize(message = nil) - super(message || DEFAULT_MESSAGE) - end - end - - module Redirector - extend ActiveSupport::Concern - include AbstractController::Logger - - # Redirects the browser to the target specified in +options+. This parameter can take one of three forms: - # - # * Hash - The URL will be generated by calling url_for with the +options+. - # * Record - The URL will be generated by calling url_for with the +options+, which will reference a named URL for that record. - # * String starting with protocol:// (like http://) - Is passed straight through as the target for redirection. - # * String not containing a protocol - The current protocol and host is prepended to the string. - # * :back - Back to the page that issued the request. Useful for forms that are triggered from multiple places. - # Short-hand for redirect_to(request.env["HTTP_REFERER"]) - # - # Examples: - # redirect_to :action => "show", :id => 5 - # redirect_to post - # redirect_to "http://www.rubyonrails.org" - # redirect_to "/images/screenshot.jpg" - # redirect_to articles_url - # redirect_to :back - # - # The redirection happens as a "302 Moved" header unless otherwise specified. - # - # Examples: - # redirect_to post_url(@post), :status => :found - # redirect_to :action=>'atom', :status => :moved_permanently - # redirect_to post_url(@post), :status => 301 - # redirect_to :action=>'atom', :status => 302 - # - # It is also possible to assign a flash message as part of the redirection. There are two special accessors for commonly used the flash names - # +alert+ and +notice+ as well as a general purpose +flash+ bucket. - # - # Examples: - # redirect_to post_url(@post), :alert => "Watch it, mister!" - # redirect_to post_url(@post), :status=> :found, :notice => "Pay attention to the road" - # redirect_to post_url(@post), :status => 301, :flash => { :updated_post_id => @post.id } - # redirect_to { :action=>'atom' }, :alert => "Something serious happened" - # - # When using redirect_to :back, if there is no referrer, - # RedirectBackError will be raised. You may specify some fallback - # behavior for this case by rescuing RedirectBackError. - def redirect_to(options = {}, response_status = {}) #:doc: - raise ActionControllerError.new("Cannot redirect to nil!") if options.nil? - raise AbstractController::DoubleRenderError if response_body - - self.status = _extract_redirect_to_status(options, response_status) - self.location = _compute_redirect_to_location(options) - self.response_body = "You are being redirected." - - logger.info("Redirected to #{location}") if logger && logger.info? - end - - private - def _extract_redirect_to_status(options, response_status) - status = if options.is_a?(Hash) && options.key?(:status) - _interpret_status(options.delete(:status)) - elsif response_status.key?(:status) - _interpret_status(response_status[:status]) - else - 302 - end - end - - def _compute_redirect_to_location(options) - case options - # The scheme name consist of a letter followed by any combination of - # letters, digits, and the plus ("+"), period ("."), or hyphen ("-") - # characters; and is terminated by a colon (":"). - when %r{^\w[\w\d+.-]*:.*} - options - when String - request.protocol + request.host_with_port + options - when :back - raise RedirectBackError unless refer = request.headers["Referer"] - refer - else - url_for(options) - end.gsub(/[\r\n]/, '') - end - - 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 -- cgit v1.2.3 From 0f8a5c7954bfc134f46eeb72c4cc8744825cbb5a Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 20 Dec 2009 20:00:04 -0600 Subject: Merge Session stuff into RackConvenience --- actionpack/lib/action_controller.rb | 1 - actionpack/lib/action_controller/base.rb | 1 - actionpack/lib/action_controller/metal/flash.rb | 10 ++-- .../action_controller/metal/rack_convenience.rb | 1 + .../metal/request_forgery_protection.rb | 32 +++++----- actionpack/lib/action_controller/metal/session.rb | 15 ----- .../lib/action_controller/metal/verification.rb | 70 +++++++++++----------- 7 files changed, 56 insertions(+), 74 deletions(-) delete mode 100644 actionpack/lib/action_controller/metal/session.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 514b4e7fe9..2e4d8d20ef 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -29,7 +29,6 @@ module ActionController autoload :RenderOptions autoload :Rescue autoload :Responder - autoload :Session autoload :SessionManagement autoload :UrlFor autoload :Verification diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index ec64cc1a39..d24c01c983 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -26,7 +26,6 @@ module ActionController include ActionController::Compatibility include ActionController::Cookies - include ActionController::Session include ActionController::Flash include ActionController::Verification include ActionController::RequestForgeryProtection diff --git a/actionpack/lib/action_controller/metal/flash.rb b/actionpack/lib/action_controller/metal/flash.rb index ae343444e2..581ff6109e 100644 --- a/actionpack/lib/action_controller/metal/flash.rb +++ b/actionpack/lib/action_controller/metal/flash.rb @@ -28,8 +28,6 @@ module ActionController #:nodoc: module Flash extend ActiveSupport::Concern - include Session - included do helper_method :alert, :notice end @@ -155,7 +153,7 @@ module ActionController #:nodoc: def alert flash[:alert] end - + # Convenience accessor for flash[:alert]= def alert=(message) flash[:alert] = message @@ -165,7 +163,7 @@ module ActionController #:nodoc: def notice flash[:notice] end - + # Convenience accessor for flash[:notice]= def notice=(message) flash[:notice] = message @@ -193,11 +191,11 @@ module ActionController #:nodoc: if notice = response_status_and_flash.delete(:notice) flash[:notice] = notice end - + if other_flashes = response_status_and_flash.delete(:flash) flash.update(other_flashes) end - + super(options, response_status_and_flash) end end diff --git a/actionpack/lib/action_controller/metal/rack_convenience.rb b/actionpack/lib/action_controller/metal/rack_convenience.rb index 131d20114d..f0837c10e8 100644 --- a/actionpack/lib/action_controller/metal/rack_convenience.rb +++ b/actionpack/lib/action_controller/metal/rack_convenience.rb @@ -3,6 +3,7 @@ module ActionController extend ActiveSupport::Concern included do + delegate :session, :reset_session, :to => "@_request" delegate :headers, :status=, :location=, :content_type=, :status, :location, :content_type, :to => "@_response" attr_internal :request diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index 173df79ee7..2826b1e34c 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -5,7 +5,7 @@ module ActionController #:nodoc: module RequestForgeryProtection extend ActiveSupport::Concern - include AbstractController::Helpers, Session + include AbstractController::Helpers included do # Sets the token parameter name for RequestForgery. Calling +protect_from_forgery+ @@ -19,31 +19,31 @@ module ActionController #:nodoc: helper_method :form_authenticity_token helper_method :protect_against_forgery? end - - # Protecting controller actions from CSRF attacks by ensuring that all forms are coming from the current - # web application, not a forged link from another site, is done by embedding a token based on a random + + # Protecting controller actions from CSRF attacks by ensuring that all forms are coming from the current + # web application, not a forged link from another site, is done by embedding a token based on a random # string stored in the session (which an attacker wouldn't know) in all forms and Ajax requests generated - # by Rails and then verifying the authenticity of that token in the controller. Only HTML/JavaScript - # requests are checked, so this will not protect your XML API (presumably you'll have a different - # authentication scheme there anyway). Also, GET requests are not protected as these should be + # by Rails and then verifying the authenticity of that token in the controller. Only HTML/JavaScript + # requests are checked, so this will not protect your XML API (presumably you'll have a different + # authentication scheme there anyway). Also, GET requests are not protected as these should be # idempotent anyway. # # This is turned on with the protect_from_forgery method, which will check the token and raise an - # ActionController::InvalidAuthenticityToken if it doesn't match what was expected. You can customize the + # ActionController::InvalidAuthenticityToken if it doesn't match what was expected. You can customize the # error message in production by editing public/422.html. A call to this method in ApplicationController is # generated by default in post-Rails 2.0 applications. # - # The token parameter is named authenticity_token by default. If you are generating an HTML form - # manually (without the use of Rails' form_for, form_tag or other helpers), you have to - # include a hidden field named like that and set its value to what is returned by + # The token parameter is named authenticity_token by default. If you are generating an HTML form + # manually (without the use of Rails' form_for, form_tag or other helpers), you have to + # include a hidden field named like that and set its value to what is returned by # form_authenticity_token. # - # Request forgery protection is disabled by default in test environment. If you are upgrading from Rails + # Request forgery protection is disabled by default in test environment. If you are upgrading from Rails # 1.x, add this to config/environments/test.rb: # # # Disable request forgery protection in test environment # config.action_controller.allow_forgery_protection = false - # + # # == Learn more about CSRF (Cross-Site Request Forgery) attacks # # Here are some resources: @@ -52,11 +52,11 @@ module ActionController #:nodoc: # # Keep in mind, this is NOT a silver-bullet, plug 'n' play, warm security blanket for your rails application. # There are a few guidelines you should follow: - # + # # * Keep your GET requests safe and idempotent. More reading material: # * http://www.xml.com/pub/a/2002/04/24/deviant.html # * http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1 - # * Make sure the session cookies that Rails creates are non-persistent. Check in Firefox and look + # * Make sure the session cookies that Rails creates are non-persistent. Check in Firefox and look # for "Expires: at end of session" # module ClassMethods @@ -92,7 +92,7 @@ module ActionController #:nodoc: # * is it a GET request? Gets should be safe and idempotent # * Does the form_authenticity_token match the given token value from the params? def verified_request? - !protect_against_forgery? || request.forgery_whitelisted? || + !protect_against_forgery? || request.forgery_whitelisted? || form_authenticity_token == params[request_forgery_protection_token] end diff --git a/actionpack/lib/action_controller/metal/session.rb b/actionpack/lib/action_controller/metal/session.rb deleted file mode 100644 index bcedd6e1c7..0000000000 --- a/actionpack/lib/action_controller/metal/session.rb +++ /dev/null @@ -1,15 +0,0 @@ -module ActionController - module Session - extend ActiveSupport::Concern - - include RackConvenience - - def session - @_request.session - end - - def reset_session - @_request.reset_session - end - end -end diff --git a/actionpack/lib/action_controller/metal/verification.rb b/actionpack/lib/action_controller/metal/verification.rb index cbd169b641..bce942b588 100644 --- a/actionpack/lib/action_controller/metal/verification.rb +++ b/actionpack/lib/action_controller/metal/verification.rb @@ -2,7 +2,7 @@ module ActionController #:nodoc: module Verification #:nodoc: extend ActiveSupport::Concern - include AbstractController::Callbacks, Session, Flash, Rendering + include AbstractController::Callbacks, Flash, Rendering # This module provides a class-level method for specifying that certain # actions are guarded against being called without certain prerequisites @@ -35,7 +35,7 @@ module ActionController #:nodoc: # :add_flash => { "alert" => "Failed to create your message" }, # :redirect_to => :category_url # - # Note that these prerequisites are not business rules. They do not examine + # Note that these prerequisites are not business rules. They do not examine # the content of the session or the parameters. That level of validation should # be encapsulated by your domain model or helper methods in the controller. module ClassMethods @@ -43,40 +43,40 @@ module ActionController #:nodoc: # the user is redirected to a different action. The +options+ parameter # is a hash consisting of the following key/value pairs: # - # :params:: - # a single key or an array of keys that must be in the params + # :params:: + # a single key or an array of keys that must be in the params # hash in order for the action(s) to be safely called. - # :session:: - # a single key or an array of keys that must be in the session + # :session:: + # a single key or an array of keys that must be in the session # in order for the action(s) to be safely called. - # :flash:: - # a single key or an array of keys that must be in the flash in order + # :flash:: + # a single key or an array of keys that must be in the flash in order # for the action(s) to be safely called. - # :method:: - # a single key or an array of keys--any one of which must match the - # current request method in order for the action(s) to be safely called. - # (The key should be a symbol: :get or :post, for + # :method:: + # a single key or an array of keys--any one of which must match the + # current request method in order for the action(s) to be safely called. + # (The key should be a symbol: :get or :post, for # example.) - # :xhr:: - # true/false option to ensure that the request is coming from an Ajax - # call or not. - # :add_flash:: - # a hash of name/value pairs that should be merged into the session's + # :xhr:: + # true/false option to ensure that the request is coming from an Ajax + # call or not. + # :add_flash:: + # a hash of name/value pairs that should be merged into the session's # flash if the prerequisites cannot be satisfied. - # :add_headers:: - # a hash of name/value pairs that should be merged into the response's + # :add_headers:: + # a hash of name/value pairs that should be merged into the response's # headers hash if the prerequisites cannot be satisfied. - # :redirect_to:: - # the redirection parameters to be used when redirecting if the - # prerequisites cannot be satisfied. You can redirect either to named + # :redirect_to:: + # the redirection parameters to be used when redirecting if the + # prerequisites cannot be satisfied. You can redirect either to named # route or to the action in some controller. - # :render:: + # :render:: # the render parameters to be used when the prerequisites cannot be satisfied. - # :only:: - # only apply this verification to the actions specified in the associated + # :only:: + # only apply this verification to the actions specified in the associated # array (may also be a single value). - # :except:: - # do not apply this verification to the actions specified in the associated + # :except:: + # do not apply this verification to the actions specified in the associated # array (may also be a single value). def verify(options={}) before_filter :only => options[:only], :except => options[:except] do @@ -94,31 +94,31 @@ module ActionController #:nodoc: apply_remaining_actions(options) unless performed? end end - + def prereqs_invalid?(options) # :nodoc: - verify_presence_of_keys_in_hash_flash_or_params(options) || - verify_method(options) || + verify_presence_of_keys_in_hash_flash_or_params(options) || + verify_method(options) || verify_request_xhr_status(options) end - + def verify_presence_of_keys_in_hash_flash_or_params(options) # :nodoc: [*options[:params] ].find { |v| v && params[v.to_sym].nil? } || [*options[:session]].find { |v| session[v].nil? } || [*options[:flash] ].find { |v| flash[v].nil? } end - + def verify_method(options) # :nodoc: [*options[:method]].all? { |v| request.method != v.to_sym } if options[:method] end - + def verify_request_xhr_status(options) # :nodoc: request.xhr? != options[:xhr] unless options[:xhr].nil? end - + def apply_redirect_to(redirect_to_option) # :nodoc: (redirect_to_option.is_a?(Symbol) && redirect_to_option != :back) ? self.__send__(redirect_to_option) : redirect_to_option end - + def apply_remaining_actions(options) # :nodoc: case when options[:render] ; render(options[:render]) -- cgit v1.2.3 From 29c8a43056f40759a8c64cbcbd4e71d4283b233d Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 20 Dec 2009 20:05:26 -0600 Subject: Rename RackConvenience => RackDelegation --- actionpack/lib/action_controller.rb | 2 +- actionpack/lib/action_controller/base.rb | 2 +- actionpack/lib/action_controller/metal.rb | 6 ++--- .../lib/action_controller/metal/conditional_get.rb | 2 +- actionpack/lib/action_controller/metal/cookies.rb | 2 +- .../action_controller/metal/rack_convenience.rb | 28 ---------------------- .../lib/action_controller/metal/rack_delegation.rb | 28 ++++++++++++++++++++++ actionpack/lib/action_controller/metal/testing.rb | 2 +- actionpack/lib/action_controller/metal/url_for.rb | 2 +- 9 files changed, 37 insertions(+), 37 deletions(-) delete mode 100644 actionpack/lib/action_controller/metal/rack_convenience.rb create mode 100644 actionpack/lib/action_controller/metal/rack_delegation.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 2e4d8d20ef..029887c96e 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -22,7 +22,7 @@ module ActionController autoload :HideActions autoload :Layouts autoload :MimeResponds - autoload :RackConvenience + autoload :RackDelegation autoload :Compatibility autoload :Redirecting autoload :Rendering diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index d24c01c983..6eda653cb2 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -13,7 +13,7 @@ module ActionController include ActionController::RenderOptions::All include ActionController::Layouts include ActionController::ConditionalGet - include ActionController::RackConvenience + include ActionController::RackDelegation include ActionController::Benchmarking include ActionController::Configuration diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index a1d857d2ce..8433be2320 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -45,7 +45,7 @@ module ActionController # The details below can be overridden to support a specific # Request and Response object. The default ActionController::Base - # implementation includes RackConvenience, which makes a request + # implementation includes RackDelegation, which makes a request # and response object available. You might wish to control the # environment and response manually for performance reasons. @@ -57,8 +57,8 @@ module ActionController end # Basic implementations for content_type=, location=, and headers are - # provided to reduce the dependency on the RackConvenience module - # in Rendering and Redirecting. + # provided to reduce the dependency on the RackDelegation module + # in Renderer and Redirector. def content_type=(type) headers["Content-Type"] = type.to_s diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb index 5156fbc1d5..61e7ece90d 100644 --- a/actionpack/lib/action_controller/metal/conditional_get.rb +++ b/actionpack/lib/action_controller/metal/conditional_get.rb @@ -2,7 +2,7 @@ module ActionController module ConditionalGet extend ActiveSupport::Concern - include RackConvenience + include RackDelegation include Head # Sets the etag, last_modified, or both on the response and renders a diff --git a/actionpack/lib/action_controller/metal/cookies.rb b/actionpack/lib/action_controller/metal/cookies.rb index 6855ca1478..e27374e4c4 100644 --- a/actionpack/lib/action_controller/metal/cookies.rb +++ b/actionpack/lib/action_controller/metal/cookies.rb @@ -46,7 +46,7 @@ module ActionController #:nodoc: module Cookies extend ActiveSupport::Concern - include RackConvenience + include RackDelegation included do helper_method :cookies diff --git a/actionpack/lib/action_controller/metal/rack_convenience.rb b/actionpack/lib/action_controller/metal/rack_convenience.rb deleted file mode 100644 index f0837c10e8..0000000000 --- a/actionpack/lib/action_controller/metal/rack_convenience.rb +++ /dev/null @@ -1,28 +0,0 @@ -module ActionController - module RackConvenience - extend ActiveSupport::Concern - - included do - delegate :session, :reset_session, :to => "@_request" - delegate :headers, :status=, :location=, :content_type=, - :status, :location, :content_type, :to => "@_response" - attr_internal :request - end - - def dispatch(action, env) - @_request = ActionDispatch::Request.new(env) - @_response = ActionDispatch::Response.new - @_response.request = request - super - end - - def params - @_params ||= @_request.parameters - end - - def response_body=(body) - response.body = body if response - super - end - end -end diff --git a/actionpack/lib/action_controller/metal/rack_delegation.rb b/actionpack/lib/action_controller/metal/rack_delegation.rb new file mode 100644 index 0000000000..5141918499 --- /dev/null +++ b/actionpack/lib/action_controller/metal/rack_delegation.rb @@ -0,0 +1,28 @@ +module ActionController + module RackDelegation + extend ActiveSupport::Concern + + included do + delegate :session, :reset_session, :to => "@_request" + delegate :headers, :status=, :location=, :content_type=, + :status, :location, :content_type, :to => "@_response" + attr_internal :request + end + + def dispatch(action, env) + @_request = ActionDispatch::Request.new(env) + @_response = ActionDispatch::Response.new + @_response.request = request + super + end + + def params + @_params ||= @_request.parameters + end + + def response_body=(body) + response.body = body if response + super + end + end +end diff --git a/actionpack/lib/action_controller/metal/testing.rb b/actionpack/lib/action_controller/metal/testing.rb index a4a1116d9e..c193a5eff4 100644 --- a/actionpack/lib/action_controller/metal/testing.rb +++ b/actionpack/lib/action_controller/metal/testing.rb @@ -2,7 +2,7 @@ module ActionController module Testing extend ActiveSupport::Concern - include RackConvenience + include RackDelegation # OMG MEGA HAX def process_with_new_base_test(request, response) diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb index 14c6523045..8c3810ebcb 100644 --- a/actionpack/lib/action_controller/metal/url_for.rb +++ b/actionpack/lib/action_controller/metal/url_for.rb @@ -2,7 +2,7 @@ module ActionController module UrlFor extend ActiveSupport::Concern - include RackConvenience + include RackDelegation # Overwrite to implement a number of default options that all url_for-based methods will use. The default options should come in # the form of a hash, just like the one you would use for url_for directly. Example: -- cgit v1.2.3 From 36c13cc07a45cbfa5d06c89001a092c70b07e253 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 20 Dec 2009 18:15:20 -0800 Subject: Rename RenderOptions to Renderers --- actionpack/lib/action_controller.rb | 2 +- actionpack/lib/action_controller/base.rb | 2 +- .../lib/action_controller/metal/render_options.rb | 92 ---------------------- .../lib/action_controller/metal/renderers.rb | 91 +++++++++++++++++++++ 4 files changed, 93 insertions(+), 94 deletions(-) delete mode 100644 actionpack/lib/action_controller/metal/render_options.rb create mode 100644 actionpack/lib/action_controller/metal/renderers.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 514b4e7fe9..e479ded8b3 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -26,7 +26,7 @@ module ActionController autoload :Compatibility autoload :Redirecting autoload :Rendering - autoload :RenderOptions + autoload :Renderers autoload :Rescue autoload :Responder autoload :Session diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index ec64cc1a39..d84705434d 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -10,7 +10,7 @@ module ActionController include ActionController::UrlFor include ActionController::Redirecting include ActionController::Rendering - include ActionController::RenderOptions::All + include ActionController::Renderers::All include ActionController::Layouts include ActionController::ConditionalGet include ActionController::RackConvenience diff --git a/actionpack/lib/action_controller/metal/render_options.rb b/actionpack/lib/action_controller/metal/render_options.rb deleted file mode 100644 index b6a7ca0eda..0000000000 --- a/actionpack/lib/action_controller/metal/render_options.rb +++ /dev/null @@ -1,92 +0,0 @@ -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 = {} - end - - module ClassMethods - def _write_render_options - renderers = _renderers.map do |name, value| - <<-RUBY_EVAL - if options.key?(:#{name}) - _process_options(options) - return _render_option_#{name}(options[:#{name}], options) - end - RUBY_EVAL - end - - class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 - def _handle_render_options(options) - #{renderers.join} - end - RUBY_EVAL - end - - 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 - - RENDERERS = {} - def self.add(key, &block) - define_method("_render_option_#{key}", &block) - RENDERERS[key] = block - All._write_render_options - end - - module All - extend ActiveSupport::Concern - include RenderOptions - - INCLUDED = [] - included do - self._renderers = RENDERERS - _write_render_options - INCLUDED << self - end - - def self._write_render_options - INCLUDED.each(&:_write_render_options) - end - 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 - - add :js do |js, options| - self.content_type ||= Mime::JS - self.response_body = js.respond_to?(:to_js) ? js.to_js : js - end - - add :xml do |xml, options| - self.content_type ||= Mime::XML - self.response_body = xml.respond_to?(:to_xml) ? xml.to_xml : xml - end - - 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/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb new file mode 100644 index 0000000000..c1ba47927a --- /dev/null +++ b/actionpack/lib/action_controller/metal/renderers.rb @@ -0,0 +1,91 @@ +module ActionController + def self.add_renderer(key, &block) + Renderers.add(key, &block) + end + + module Renderers + extend ActiveSupport::Concern + + included do + extlib_inheritable_accessor :_renderers + self._renderers = {} + end + + module ClassMethods + def _write_render_options + renderers = _renderers.map do |name, value| + <<-RUBY_EVAL + if options.key?(:#{name}) + _process_options(options) + return _render_option_#{name}(options[:#{name}], options) + end + RUBY_EVAL + end + + class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 + def _handle_render_options(options) + #{renderers.join} + end + RUBY_EVAL + end + + 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 + + RENDERERS = {} + def self.add(key, &block) + define_method("_render_option_#{key}", &block) + RENDERERS[key] = block + All._write_render_options + end + + module All + extend ActiveSupport::Concern + include Renderers + + INCLUDED = [] + included do + self._renderers = RENDERERS + _write_render_options + INCLUDED << self + end + + def self._write_render_options + INCLUDED.each(&:_write_render_options) + end + 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 + + add :js do |js, options| + self.content_type ||= Mime::JS + self.response_body = js.respond_to?(:to_js) ? js.to_js : js + end + + add :xml do |xml, options| + self.content_type ||= Mime::XML + self.response_body = xml.respond_to?(:to_xml) ? xml.to_xml : xml + end + + 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 -- cgit v1.2.3 From cf9d6a95e805bdddfa9c6b541631d51b3165bf23 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 20 Dec 2009 18:30:50 -0800 Subject: Added ActionDispatch::Request#authorization to access the http authentication header regardless of its proxy hiding [DHH] --- actionpack/lib/action_dispatch/http/request.rb | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 7d1f5a4504..bc17cadb38 100755 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -465,6 +465,15 @@ EOM session['flash'] || {} end + # Returns the authorization header regardless of whether it was specified directly or through one of the + # proxy alternatives. + def authorization + @env['HTTP_AUTHORIZATION'] || + @env['X-HTTP_AUTHORIZATION'] || + @env['X_HTTP_AUTHORIZATION'] || + @env['REDIRECT_X_HTTP_AUTHORIZATION'] + end + # Receives an array of mimes and return the first user sent mime that # matches the order array. # -- cgit v1.2.3 From eeda059818ae95620a7c7b86ad0ff2fa621cbe88 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 20 Dec 2009 18:37:09 -0800 Subject: Just a little tidying --- .../action_dispatch/middleware/params_parser.rb | 46 +++++++++++----------- 1 file changed, 22 insertions(+), 24 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb index 32ccb5c931..8970ccaf07 100644 --- a/actionpack/lib/action_dispatch/middleware/params_parser.rb +++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb @@ -31,41 +31,39 @@ module ActionDispatch return false unless strategy case strategy - when Proc - strategy.call(request.raw_post) - when :xml_simple, :xml_node - request.body.size == 0 ? {} : Hash.from_xml(request.body).with_indifferent_access - when :yaml - YAML.load(request.body) - when :json - if request.body.size == 0 - {} - else - data = ActiveSupport::JSON.decode(request.body) - data = {:_json => data} unless data.is_a?(Hash) - data.with_indifferent_access - end + when Proc + strategy.call(request.raw_post) + when :xml_simple, :xml_node + request.body.size == 0 ? {} : Hash.from_xml(request.body).with_indifferent_access + when :yaml + YAML.load(request.body) + when :json + if request.body.size == 0 + {} else - false + data = ActiveSupport::JSON.decode(request.body) + data = {:_json => data} unless data.is_a?(Hash) + data.with_indifferent_access + end + else + false end rescue Exception => e # YAML, XML or Ruby code block errors logger.debug "Error occurred while parsing request parameters.\nContents:\n\n#{request.raw_post}" raise - { "body" => request.raw_post, - "content_type" => request.content_type, + { "body" => request.raw_post, + "content_type" => request.content_type, "content_length" => request.content_length, - "exception" => "#{e.message} (#{e.class})", - "backtrace" => e.backtrace } + "exception" => "#{e.message} (#{e.class})", + "backtrace" => e.backtrace } end def content_type_from_legacy_post_data_format_header(env) if x_post_format = env['HTTP_X_POST_DATA_FORMAT'] case x_post_format.to_s.downcase - when 'yaml' - return Mime::YAML - when 'xml' - return Mime::XML + when 'yaml' then return Mime::YAML + when 'xml' then return Mime::XML end end @@ -76,4 +74,4 @@ module ActionDispatch defined?(Rails.logger) ? Rails.logger : Logger.new($stderr) end end -end +end \ No newline at end of file -- cgit v1.2.3 From 17f66473bce0decb2e5ff23142d4046056ccca1b Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Sun, 20 Dec 2009 18:50:47 -0800 Subject: AC::Head now doesn't have an unfulfilled Rendering dependency, and instead works just fine standalone (which means that ConditionalGet also doesn't have a Rendering dependency) --- actionpack/lib/abstract_controller/base.rb | 1 + actionpack/lib/abstract_controller/rendering.rb | 1 - actionpack/lib/action_controller/base.rb | 2 +- actionpack/lib/action_controller/metal.rb | 5 +++++ actionpack/lib/action_controller/metal/head.rb | 7 ++++++- actionpack/lib/action_controller/metal/redirecting.rb | 12 ++---------- actionpack/lib/action_dispatch/http/response.rb | 2 +- actionpack/lib/action_dispatch/http/status_codes.rb | 8 ++++++++ 8 files changed, 24 insertions(+), 14 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index 905d04e20d..9d57c52429 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -5,6 +5,7 @@ module AbstractController class Base attr_internal :response_body attr_internal :action_name + attr_internal :formats class << self attr_reader :abstract diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index 8ef2526df0..f4e1580977 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -16,7 +16,6 @@ module AbstractController include AbstractController::Logger included do - attr_internal :formats extlib_inheritable_accessor :_view_paths self._view_paths ||= ActionView::PathSet.new end diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index e6cde7fd35..452f0cd4f0 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -89,7 +89,7 @@ module ActionController end if options[:status] - options[:status] = _interpret_status(options[:status]) + options[:status] = ActionDispatch::StatusCodes[options[:status]] end options[:update] = blk if block_given? diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index 8433be2320..93a19f8f93 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -68,6 +68,10 @@ module ActionController headers["Location"] = url end + def status=(status) + @_status = ActionDispatch::StatusCodes[status] + end + # :api: private def dispatch(name, env) @_env = env @@ -92,6 +96,7 @@ module ActionController def initialize(controller, action) @controller, @action = controller, action + @_formats = [Mime::HTML] end def call(env) diff --git a/actionpack/lib/action_controller/metal/head.rb b/actionpack/lib/action_controller/metal/head.rb index 68fa0a0402..c82d9cf369 100644 --- a/actionpack/lib/action_controller/metal/head.rb +++ b/actionpack/lib/action_controller/metal/head.rb @@ -1,5 +1,7 @@ module ActionController module Head + include UrlFor + # Return a response that has no content (merely headers). The options # argument is interpreted to be a hash of header names and values. # This allows you to easily return a response that consists only of @@ -21,7 +23,10 @@ module ActionController headers[key.to_s.dasherize.split(/-/).map { |v| v.capitalize }.join("-")] = value.to_s end - render :nothing => true, :status => status, :location => location + self.status = status + self.location = url_for(location) if location + self.content_type = Mime[formats.first] + self.response_body = " " end end end \ No newline at end of file diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb index d101f920e3..39dc23024c 100644 --- a/actionpack/lib/action_controller/metal/redirecting.rb +++ b/actionpack/lib/action_controller/metal/redirecting.rb @@ -62,9 +62,9 @@ module ActionController private def _extract_redirect_to_status(options, response_status) status = if options.is_a?(Hash) && options.key?(:status) - _interpret_status(options.delete(:status)) + ActionDispatch::StatusCodes[options.delete(:status)] elsif response_status.key?(:status) - _interpret_status(response_status[:status]) + ActionDispatch::StatusCodes[response_status[:status]] else 302 end @@ -86,13 +86,5 @@ module ActionController url_for(options) end.gsub(/[\r\n]/, '') end - - 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/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 6e63fc0067..6dc563264f 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -60,7 +60,7 @@ module ActionDispatch # :nodoc: end def status=(status) - @status = status.to_i + @status = ActionDispatch::StatusCodes[status] end # The response code of the request diff --git a/actionpack/lib/action_dispatch/http/status_codes.rb b/actionpack/lib/action_dispatch/http/status_codes.rb index ea1475e827..3d6ee685ea 100644 --- a/actionpack/lib/action_dispatch/http/status_codes.rb +++ b/actionpack/lib/action_dispatch/http/status_codes.rb @@ -14,6 +14,14 @@ module ActionDispatch 510 => "Not Extended" }).freeze + def self.[](status) + if status.is_a?(Symbol) + SYMBOL_TO_STATUS_CODE[status] || 500 + else + status.to_i + end + end + # Provides a symbol-to-fixnum lookup for converting a symbol (like # :created or :not_implemented) into its corresponding HTTP status # code (like 200 or 501). -- cgit v1.2.3 From 15f95621d5b472959215cdc258491934e5f05f2e Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 20 Dec 2009 21:11:42 -0600 Subject: We don't need AD parse_config --- actionpack/lib/action_dispatch.rb | 1 - actionpack/lib/action_dispatch/http/utils.rb | 20 -------------------- 2 files changed, 21 deletions(-) delete mode 100644 actionpack/lib/action_dispatch/http/utils.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index a7be49a273..48b5652a89 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -38,7 +38,6 @@ module ActionDispatch autoload :Request autoload :Response autoload :StatusCodes - autoload :Utils end deferrable do diff --git a/actionpack/lib/action_dispatch/http/utils.rb b/actionpack/lib/action_dispatch/http/utils.rb deleted file mode 100644 index e04a39935e..0000000000 --- a/actionpack/lib/action_dispatch/http/utils.rb +++ /dev/null @@ -1,20 +0,0 @@ -module ActionDispatch - module Utils - # TODO: Pull this into rack core - # http://github.com/halorgium/rack/commit/feaf071c1de743fbd10bc316830180a9af607278 - def parse_config(config) - if config =~ /\.ru$/ - cfgfile = ::File.read(config) - if cfgfile[/^#\\(.*)/] - opts.parse! $1.split(/\s+/) - end - inner_app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app", - nil, config - else - require config - inner_app = Object.const_get(::File.basename(config, '.rb').capitalize) - end - end - module_function :parse_config - end -end -- cgit v1.2.3 From 3ff9e9ee147b682cb13aed4c057e750228892f42 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 20 Dec 2009 20:37:36 -0800 Subject: Its now possible to use match 'stuff' => 'what#stuff' instead of using the :to for simple routes --- actionpack/lib/action_dispatch/routing/mapper.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 57e992d7dc..46163706c3 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -39,9 +39,13 @@ module ActionDispatch end def match(*args) - options = args.extract_options! - - path = args.first + if args.one? && args.first.is_a?(Hash) + path = args.first.keys.first + options = { :to => args.first.values.first } + else + path = args.first + options = args.extract_options! + end conditions, defaults = {}, {} -- cgit v1.2.3 From f82e1046f893c80c6234495f1bca28b4fb6520c9 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 21 Dec 2009 17:29:59 -0600 Subject: reset_session needs to be a real method so flash can override it --- actionpack/lib/action_controller/metal/rack_delegation.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/metal/rack_delegation.rb b/actionpack/lib/action_controller/metal/rack_delegation.rb index 5141918499..833475cff7 100644 --- a/actionpack/lib/action_controller/metal/rack_delegation.rb +++ b/actionpack/lib/action_controller/metal/rack_delegation.rb @@ -3,7 +3,7 @@ module ActionController extend ActiveSupport::Concern included do - delegate :session, :reset_session, :to => "@_request" + delegate :session, :to => "@_request" delegate :headers, :status=, :location=, :content_type=, :status, :location, :content_type, :to => "@_response" attr_internal :request @@ -24,5 +24,9 @@ module ActionController response.body = body if response super end + + def reset_session + @_request.reset_session + end end end -- cgit v1.2.3 From 715dd10961cefd1d8039cb81f47788d0a5b97d0d Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 21 Dec 2009 17:34:53 -0600 Subject: Less annoying RoutingError message --- actionpack/lib/action_dispatch/routing/route_set.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index bf2443c1be..a4dc5e0956 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -5,7 +5,7 @@ module ActionDispatch module Routing class RouteSet #:nodoc: NotFound = lambda { |env| - raise ActionController::RoutingError, "No route matches #{env['PATH_INFO'].inspect} with #{env.inspect}" + raise ActionController::RoutingError, "No route matches #{env['PATH_INFO'].inspect}" } PARAMETERS_KEY = 'action_dispatch.request.path_parameters' @@ -426,7 +426,7 @@ module ActionDispatch end end - raise ActionController::RoutingError, "No route matches #{path.inspect} with #{environment.inspect}" + raise ActionController::RoutingError, "No route matches #{path.inspect}" end end end -- cgit v1.2.3 From a110ff0fca45c6cc74c0da5d8dcdabeed43e78b1 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 21 Dec 2009 16:03:04 -0800 Subject: Dont introspect inline templates for the logger and cleanup a few styling issues --- actionpack/lib/abstract_controller/rendering.rb | 9 ++++----- actionpack/lib/action_view/render/rendering.rb | 22 +++++++++------------- 2 files changed, 13 insertions(+), 18 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index f4e1580977..64a8a5f241 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -125,8 +125,8 @@ module AbstractController if options.key?(: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, {}) + handler = ActionView::Template.handler_class_for_extension(options[:type] || "erb") + template = ActionView::Template.new(options[:inline], "inline template", handler, {}) options[:_template] = template elsif options.key?(:template) options[:_template_name] = options[:template] @@ -194,9 +194,8 @@ module AbstractController # otherwise, process the parameter into a ViewPathSet. def view_paths=(paths) clear_template_caches! - self._view_paths = paths.is_a?(ActionView::PathSet) ? - paths : ActionView::Base.process_view_paths(paths) + self._view_paths = paths.is_a?(ActionView::PathSet) ? paths : ActionView::Base.process_view_paths(paths) end end end -end +end \ No newline at end of file diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index 7006a5b968..d4d16b4d98 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -78,12 +78,12 @@ module ActionView end def _render_inline(inline, layout, options) - handler = Template.handler_class_for_extension(options[:type] || "erb") - template = Template.new(options[:inline], - "inline #{options[:inline].inspect}", handler, {}) + handler = Template.handler_class_for_extension(options[:type] || "erb") + template = Template.new(options[:inline], "inline template", handler, {}) - locals = options[:locals] + locals = options[:locals] content = template.render(self, locals) + _render_text(content, layout, locals) end @@ -91,6 +91,7 @@ module ActionView content = layout.render(self, locals) do |*name| _layout_for(*name) { content } end if layout + content end @@ -113,21 +114,16 @@ module ActionView msg end - locals = options[:locals] || {} - - content = if partial - _render_partial_object(template, options) - else - template.render(self, locals) - end - + locals = options[:locals] || {} + content = partial ? _render_partial_object(template, options) : template.render(self, locals) @_content_for[:layout] = content if layout @_layout = layout.identifier logger.info("Rendering template within #{layout.inspect}") if logger - content = layout.render(self, locals) {|*name| _layout_for(*name) } + content = layout.render(self, locals) { |*name| _layout_for(*name) } end + content end end -- cgit v1.2.3 From 4964d3b02cd5c87d821ab7d41d243154c727185d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Tue, 22 Dec 2009 20:17:27 +0100 Subject: Make ActionMailer::Base inherit from AbstractController::Base Signed-off-by: Yehuda Katz --- actionpack/lib/abstract_controller/base.rb | 8 +++--- actionpack/lib/abstract_controller/logger.rb | 28 ------------------- actionpack/lib/action_controller.rb | 1 + actionpack/lib/action_controller/base.rb | 1 + actionpack/lib/action_controller/metal/logger.rb | 34 ++++++++++++++++++++++++ 5 files changed, 40 insertions(+), 32 deletions(-) create mode 100644 actionpack/lib/action_controller/metal/logger.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index 9d57c52429..efea81aa71 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -84,7 +84,7 @@ module AbstractController # # ==== Returns # self - def process(action) + def process(action, *args) @_action_name = action_name = action.to_s unless action_name = method_for_action(action_name) @@ -93,7 +93,7 @@ module AbstractController @_response_body = nil - process_action(action_name) + process_action(action_name, *args) end private @@ -113,8 +113,8 @@ module AbstractController # Call the action. Override this in a subclass to modify the # behavior around processing an action. This, and not #process, # is the intended way to override action dispatching. - def process_action(method_name) - send_action(method_name) + def process_action(method_name, *args) + send_action(method_name, *args) end # Actually call the method associated with the action. Override diff --git a/actionpack/lib/abstract_controller/logger.rb b/actionpack/lib/abstract_controller/logger.rb index 27ba5be45f..e3bcd28da7 100644 --- a/actionpack/lib/abstract_controller/logger.rb +++ b/actionpack/lib/abstract_controller/logger.rb @@ -29,33 +29,5 @@ module AbstractController @str.send(*args, &block) end end - - # Override process_action in the AbstractController::Base - # to log details about the method. - def process_action(action) - result = ActiveSupport::Notifications.instrument(:process_action, - :controller => self, :action => action) do - super - end - - if logger - log = DelayedLog.new do - "\n\nProcessing #{self.class.name}\##{action_name} " \ - "to #{request.formats} (for #{request_origin}) " \ - "[#{request.method.to_s.upcase}]" - end - - logger.info(log) - end - - result - end - - private - # Returns the request origin with the IP and time. This needs to be cached, - # otherwise we would get different results for each time it calls. - def request_origin - @request_origin ||= "#{request.remote_ip} at #{Time.now.to_s(:db)}" - end end end diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index e31b795cd2..8b3a444cda 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -21,6 +21,7 @@ module ActionController autoload :Helpers autoload :HideActions autoload :Layouts + autoload :Logger autoload :MimeResponds autoload :RackDelegation autoload :Compatibility diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 452f0cd4f0..f75b6ed641 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -14,6 +14,7 @@ module ActionController include ActionController::Layouts include ActionController::ConditionalGet include ActionController::RackDelegation + include ActionController::Logger include ActionController::Benchmarking include ActionController::Configuration diff --git a/actionpack/lib/action_controller/metal/logger.rb b/actionpack/lib/action_controller/metal/logger.rb new file mode 100644 index 0000000000..956d7dd371 --- /dev/null +++ b/actionpack/lib/action_controller/metal/logger.rb @@ -0,0 +1,34 @@ +require 'abstract_controller/logger' + +module ActionController + module Logger + # Override process_action in the AbstractController::Base + # to log details about the method. + def process_action(action) + result = ActiveSupport::Notifications.instrument(:process_action, + :controller => self, :action => action) do + super + end + + if logger + log = AbstractController::Logger::DelayedLog.new do + "\n\nProcessing #{self.class.name}\##{action_name} " \ + "to #{request.formats} (for #{request_origin}) " \ + "[#{request.method.to_s.upcase}]" + end + + logger.info(log) + end + + result + end + + private + + # Returns the request origin with the IP and time. This needs to be cached, + # otherwise we would get different results for each time it calls. + def request_origin + @request_origin ||= "#{request.remote_ip} at #{Time.now.to_s(:db)}" + end + end +end -- cgit v1.2.3 From a1bf2f96ce6f086de8519e344ee7e396ae3da9bb Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 22 Dec 2009 16:08:03 -0600 Subject: AD::StatusCodes support is now part of rack --- actionpack/lib/action_controller/base.rb | 2 +- actionpack/lib/action_controller/metal.rb | 2 +- .../lib/action_controller/metal/redirecting.rb | 8 +++--- actionpack/lib/action_dispatch.rb | 1 - actionpack/lib/action_dispatch/http/response.rb | 4 +-- .../lib/action_dispatch/http/status_codes.rb | 33 ---------------------- .../action_dispatch/middleware/show_exceptions.rb | 2 +- .../action_dispatch/testing/assertions/response.rb | 2 +- 8 files changed, 10 insertions(+), 44 deletions(-) delete mode 100644 actionpack/lib/action_dispatch/http/status_codes.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index f75b6ed641..dbba69f637 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -90,7 +90,7 @@ module ActionController end if options[:status] - options[:status] = ActionDispatch::StatusCodes[options[:status]] + options[:status] = Rack::Utils.status_code(options[:status]) end options[:update] = blk if block_given? diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index 93a19f8f93..b436de9878 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -69,7 +69,7 @@ module ActionController end def status=(status) - @_status = ActionDispatch::StatusCodes[status] + @_status = Rack::Utils.status_code(status) end # :api: private diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb index 39dc23024c..7a2f9a6fc5 100644 --- a/actionpack/lib/action_controller/metal/redirecting.rb +++ b/actionpack/lib/action_controller/metal/redirecting.rb @@ -58,18 +58,18 @@ module ActionController logger.info("Redirected to #{location}") if logger && logger.info? end - + private def _extract_redirect_to_status(options, response_status) status = if options.is_a?(Hash) && options.key?(:status) - ActionDispatch::StatusCodes[options.delete(:status)] + Rack::Utils.status_code(options.delete(:status)) elsif response_status.key?(:status) - ActionDispatch::StatusCodes[response_status[:status]] + Rack::Utils.status_code(response_status[:status]) else 302 end end - + def _compute_redirect_to_location(options) case options # The scheme name consist of a letter followed by any combination of diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 48b5652a89..ed04980ab0 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -37,7 +37,6 @@ module ActionDispatch autoload_under 'http' do autoload :Request autoload :Response - autoload :StatusCodes end deferrable do diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 6dc563264f..8524bbd993 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -60,7 +60,7 @@ module ActionDispatch # :nodoc: end def status=(status) - @status = ActionDispatch::StatusCodes[status] + @status = Rack::Utils.status_code(status) end # The response code of the request @@ -74,7 +74,7 @@ module ActionDispatch # :nodoc: end def message - StatusCodes::STATUS_CODES[@status] + Rack::Utils::HTTP_STATUS_CODES[@status] end alias_method :status_message, :message diff --git a/actionpack/lib/action_dispatch/http/status_codes.rb b/actionpack/lib/action_dispatch/http/status_codes.rb deleted file mode 100644 index 3d6ee685ea..0000000000 --- a/actionpack/lib/action_dispatch/http/status_codes.rb +++ /dev/null @@ -1,33 +0,0 @@ -require 'active_support/inflector' - -module ActionDispatch - module StatusCodes #:nodoc: - STATUS_CODES = Rack::Utils::HTTP_STATUS_CODES.merge({ - 102 => "Processing", - 207 => "Multi-Status", - 226 => "IM Used", - 422 => "Unprocessable Entity", - 423 => "Locked", - 424 => "Failed Dependency", - 426 => "Upgrade Required", - 507 => "Insufficient Storage", - 510 => "Not Extended" - }).freeze - - def self.[](status) - if status.is_a?(Symbol) - SYMBOL_TO_STATUS_CODE[status] || 500 - else - status.to_i - end - end - - # Provides a symbol-to-fixnum lookup for converting a symbol (like - # :created or :not_implemented) into its corresponding HTTP status - # code (like 200 or 501). - SYMBOL_TO_STATUS_CODE = STATUS_CODES.inject({}) { |hash, (code, message)| - hash[ActiveSupport::Inflector.underscore(message.gsub(/ /, "")).to_sym] = code - hash - }.freeze - end -end diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index bd87764f5b..5c7f78b0e4 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -101,7 +101,7 @@ module ActionDispatch end def status_code(exception) - ActionDispatch::StatusCodes::SYMBOL_TO_STATUS_CODE[@@rescue_responses[exception.class.name]] + Rack::Utils.status_code(@@rescue_responses[exception.class.name]) end def render(status, body) diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb index 501a7c4dfb..5686bbdbde 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/response.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb @@ -28,7 +28,7 @@ module ActionDispatch assert_block("") { true } # to count the assertion elsif type.is_a?(Fixnum) && @response.response_code == type assert_block("") { true } # to count the assertion - elsif type.is_a?(Symbol) && @response.response_code == ActionDispatch::StatusCodes::SYMBOL_TO_STATUS_CODE[type] + elsif type.is_a?(Symbol) && @response.response_code == Rack::Utils::SYMBOL_TO_STATUS_CODE[type] assert_block("") { true } # to count the assertion else assert_block(build_message(message, "Expected response to be a , but was ", type, @response.response_code)) { false } -- cgit v1.2.3 From df7faef68e833efeef0dca3e07e0355f5042bb36 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 22 Dec 2009 16:09:41 -0600 Subject: Referer and user agent are in Rack::Request --- actionpack/lib/action_dispatch/http/request.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index bc17cadb38..6e8a5dcb8a 100755 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -18,7 +18,7 @@ module ActionDispatch HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM - HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_USER_AGENT ].each do |env| + HTTP_NEGOTIATE HTTP_PRAGMA ].each do |env| define_method(env.sub(/^HTTP_/n, '').downcase) do @env[env] end -- cgit v1.2.3 From 2d0c703c922758dc36df8a20a56894484013b0f1 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 22 Dec 2009 16:18:22 -0600 Subject: Use Rack::Runtime middleware so the reported time includes the entire middleware stack --- actionpack/lib/action_controller/metal/benchmarking.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/metal/benchmarking.rb b/actionpack/lib/action_controller/metal/benchmarking.rb index e58df69172..f73f635b0d 100644 --- a/actionpack/lib/action_controller/metal/benchmarking.rb +++ b/actionpack/lib/action_controller/metal/benchmarking.rb @@ -53,7 +53,6 @@ module ActionController #:nodoc: log_message << " [#{complete_request_uri rescue "unknown"}]" logger.info(log_message) - response.headers["X-Runtime"] = "%.0f" % ms else super end -- cgit v1.2.3 From b1aee9f4eebdae4fad38572359649c097c731b77 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 22 Dec 2009 17:11:21 -0600 Subject: All AD modules are "deferrable" --- .../lib/action_controller/metal/rack_delegation.rb | 3 +++ actionpack/lib/action_dispatch.rb | 12 +++++------- .../action_dispatch/middleware/params_parser.rb | 1 + .../middleware/session/abstract_store.rb | 1 + .../middleware/session/cookie_store.rb | 9 +++++---- .../action_dispatch/middleware/show_exceptions.rb | 3 ++- .../lib/action_dispatch/testing/assertions/dom.rb | 4 +++- .../action_dispatch/testing/assertions/selector.rb | 22 ++++++++++++---------- .../lib/action_dispatch/testing/assertions/tag.rb | 2 ++ .../lib/action_view/helpers/sanitize_helper.rb | 1 + 10 files changed, 35 insertions(+), 23 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/metal/rack_delegation.rb b/actionpack/lib/action_controller/metal/rack_delegation.rb index 833475cff7..bb55383631 100644 --- a/actionpack/lib/action_controller/metal/rack_delegation.rb +++ b/actionpack/lib/action_controller/metal/rack_delegation.rb @@ -1,3 +1,6 @@ +require 'action_dispatch/http/request' +require 'action_dispatch/http/response' + module ActionController module RackDelegation extend ActiveSupport::Concern diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index ed04980ab0..4e04e2a17c 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -34,12 +34,12 @@ end module ActionDispatch extend ActiveSupport::Autoload - autoload_under 'http' do - autoload :Request - autoload :Response - end - deferrable do + autoload_under 'http' do + autoload :Request + autoload :Response + end + autoload_under 'middleware' do autoload :Callbacks autoload :ParamsParser @@ -71,8 +71,6 @@ module ActionDispatch autoload :TestResponse end end - - autoload :HTML, 'action_controller/vendor/html-scanner' end autoload :Mime, 'action_dispatch/http/mime_type' diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb index 8970ccaf07..534390d4aa 100644 --- a/actionpack/lib/action_dispatch/middleware/params_parser.rb +++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb @@ -1,4 +1,5 @@ require 'active_support/json' +require 'action_dispatch/http/request' module ActionDispatch class ParamsParser diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index c5c06f74a2..7d4f0998ce 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -1,4 +1,5 @@ require 'rack/utils' +require 'rack/request' module ActionDispatch module Session diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb index bd552b458a..f27f22c7e7 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb @@ -1,4 +1,5 @@ -require "active_support/core_ext/hash/keys" +require 'active_support/core_ext/hash/keys' +require 'rack/request' module ActionDispatch module Session @@ -49,7 +50,7 @@ module ActionDispatch :expire_after => nil, :httponly => true }.freeze - + class OptionsHash < Hash def initialize(by, env, default_options) @session_data = env[CookieStore::ENV_SESSION_KEY] @@ -60,7 +61,7 @@ module ActionDispatch key == :id ? @session_data[:session_id] : super(key) end end - + ENV_SESSION_KEY = "rack.session".freeze ENV_SESSION_OPTIONS_KEY = "rack.session.options".freeze HTTP_SET_COOKIE = "Set-Cookie".freeze @@ -102,7 +103,7 @@ module ActionDispatch def call(env) env[ENV_SESSION_KEY] = AbstractStore::SessionHash.new(self, env) env[ENV_SESSION_OPTIONS_KEY] = OptionsHash.new(self, env, @default_options) - + status, headers, body = @app.call(env) session_data = env[ENV_SESSION_KEY] diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index 5c7f78b0e4..4ebc8a2ab9 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -1,4 +1,5 @@ -require "active_support/core_ext/exception" +require 'active_support/core_ext/exception' +require 'action_dispatch/http/request' module ActionDispatch class ShowExceptions diff --git a/actionpack/lib/action_dispatch/testing/assertions/dom.rb b/actionpack/lib/action_dispatch/testing/assertions/dom.rb index 9a917f704a..9c215de743 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/dom.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/dom.rb @@ -1,3 +1,5 @@ +require 'action_controller/vendor/html-scanner' + module ActionDispatch module Assertions module DomAssertions @@ -15,7 +17,7 @@ module ActionDispatch assert_block(full_message) { expected_dom == actual_dom } end - + # The negated form of +assert_dom_equivalent+. # # ==== Examples diff --git a/actionpack/lib/action_dispatch/testing/assertions/selector.rb b/actionpack/lib/action_dispatch/testing/assertions/selector.rb index d22adfa749..c2dc591ff7 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/selector.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/selector.rb @@ -1,3 +1,5 @@ +require 'action_controller/vendor/html-scanner' + #-- # Copyright (c) 2006 Assaf Arkin (http://labnotes.org) # Under MIT and/or CC By license. @@ -16,7 +18,7 @@ module ActionDispatch # # Use +css_select+ to select elements without making an assertions, either # from the response HTML or elements selected by the enclosing assertion. - # + # # In addition to HTML responses, you can make the following assertions: # * +assert_select_rjs+ - Assertions on HTML content of RJS update and insertion operations. # * +assert_select_encoded+ - Assertions on HTML encoded inside XML, for example for dealing with feed item descriptions. @@ -53,8 +55,8 @@ module ActionDispatch # end # # # Selects all list items in unordered lists - # items = css_select("ul>li") - # + # items = css_select("ul>li") + # # # Selects all form tags and then all inputs inside the form # forms = css_select("form") # forms.each do |form| @@ -212,7 +214,7 @@ module ActionDispatch # Otherwise just operate on the response document. root = response_from_page_or_rjs end - + # First or second argument is the selector: string and we pass # all remaining arguments. Array and we pass the argument. Also # accepts selector itself. @@ -225,7 +227,7 @@ module ActionDispatch selector = arg else raise ArgumentError, "Expecting a selector as the first argument" end - + # Next argument is used for equality tests. equals = {} case arg = args.shift @@ -315,10 +317,10 @@ module ActionDispatch # Returns all matches elements. matches end - + def count_description(min, max) #:nodoc: pluralize = lambda {|word, quantity| word << (quantity == 1 ? '' : 's')} - + if min && max && (max != min) "between #{min} and #{max} elements" elsif min && !(min == 1 && max == 1) @@ -327,7 +329,7 @@ module ActionDispatch "at most #{max} #{pluralize['element', max]}" end end - + # :call-seq: # assert_select_rjs(id?) { |elements| ... } # assert_select_rjs(statement, id?) { |elements| ... } @@ -344,7 +346,7 @@ module ActionDispatch # that update or insert an element with that identifier. # # Use the first argument to narrow down assertions to only statements - # of that type. Possible values are :replace, :replace_html, + # of that type. Possible values are :replace, :replace_html, # :show, :hide, :toggle, :remove, # :insert_html and :redirect. # @@ -494,7 +496,7 @@ module ActionDispatch # end # end # end - # + # # # # Selects all paragraph tags from within the description of an RSS feed # assert_select_feed :rss, 2.0 do diff --git a/actionpack/lib/action_dispatch/testing/assertions/tag.rb b/actionpack/lib/action_dispatch/testing/assertions/tag.rb index b74dcb1fe4..5c735e61b2 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/tag.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/tag.rb @@ -1,3 +1,5 @@ +require 'action_controller/vendor/html-scanner' + module ActionDispatch module Assertions # Pair of assertions to testing elements in the HTML output of the response. diff --git a/actionpack/lib/action_view/helpers/sanitize_helper.rb b/actionpack/lib/action_view/helpers/sanitize_helper.rb index 69d0d0fb67..f03ffe5ef4 100644 --- a/actionpack/lib/action_view/helpers/sanitize_helper.rb +++ b/actionpack/lib/action_view/helpers/sanitize_helper.rb @@ -1,3 +1,4 @@ +require 'action_controller/vendor/html-scanner' require 'action_view/helpers/tag_helper' module ActionView -- cgit v1.2.3 From ace20bd25e3818b7f29c222643dd445c48b36425 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 22 Dec 2009 17:27:37 -0600 Subject: Flip deferrable autoload convention --- actionpack/lib/abstract_controller.rb | 16 ++- actionpack/lib/action_controller.rb | 112 ++++++++++----------- actionpack/lib/action_controller/caching.rb | 12 ++- .../lib/action_controller/vendor/html-scanner.rb | 26 ++--- actionpack/lib/action_dispatch.rb | 60 ++++++----- actionpack/lib/action_view.rb | 41 ++++---- actionpack/lib/action_view/template.rb | 14 +-- 7 files changed, 142 insertions(+), 139 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index c15a1da98a..237ab577ba 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -8,13 +8,11 @@ require 'active_support/core_ext/module/delegation' module AbstractController extend ActiveSupport::Autoload - deferrable do - autoload :Base - autoload :Callbacks - autoload :Helpers - autoload :Layouts - autoload :LocalizedCache - autoload :Logger - autoload :Rendering - end + autoload :Base + autoload :Callbacks + autoload :Helpers + autoload :Layouts + autoload :LocalizedCache + autoload :Logger + autoload :Rendering end diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 8b3a444cda..26a85d4de8 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -5,66 +5,66 @@ require 'active_support/ruby/shim' module ActionController extend ActiveSupport::Autoload - deferrable do - autoload :Base - autoload :Caching - autoload :PolymorphicRoutes - autoload :Translation - autoload :Metal - autoload :Middleware + 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 :Logger - autoload :MimeResponds - autoload :RackDelegation - autoload :Compatibility - autoload :Redirecting - autoload :Rendering - autoload :Renderers - autoload :Rescue - autoload :Responder - 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_under "metal" do + autoload :Benchmarking + autoload :ConditionalGet + autoload :Configuration + autoload :Head + autoload :Helpers + autoload :HideActions + autoload :Layouts + autoload :Logger + autoload :MimeResponds + autoload :RackDelegation + autoload :Compatibility + autoload :Redirecting + autoload :Rendering + autoload :Renderers + autoload :Rescue + autoload :Responder + autoload :SessionManagement + autoload :UrlFor + autoload :Verification + autoload :Flash + autoload :RequestForgeryProtection + autoload :Streaming + autoload :HttpAuthentication + autoload :FilterParameterLogging + autoload :Cookies end - autoload :RecordIdentifier - autoload :UrlRewriter - autoload :UrlWriter, 'action_controller/url_rewriter' + 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' - # TODO: Don't autoload exceptions, setup explicit - # requires for files that need them - 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 + eager_autoload do + 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 + autoload :RoutingError + autoload :MethodNotAllowed + autoload :NotImplemented + autoload :UnknownController + autoload :MissingFile + autoload :RenderError + autoload :SessionOverflowError + autoload :UnknownHttpMethod + end end end diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb index ad357cceda..d784138ebe 100644 --- a/actionpack/lib/action_controller/caching.rb +++ b/actionpack/lib/action_controller/caching.rb @@ -32,11 +32,13 @@ module ActionController #:nodoc: extend ActiveSupport::Concern extend ActiveSupport::Autoload - autoload :Actions - autoload :Fragments - autoload :Pages - autoload :Sweeper, 'action_controller/caching/sweeping' - autoload :Sweeping, 'action_controller/caching/sweeping' + eager_autoload do + autoload :Actions + autoload :Fragments + autoload :Pages + autoload :Sweeper, 'action_controller/caching/sweeping' + autoload :Sweeping, 'action_controller/caching/sweeping' + end included do @@cache_store = nil diff --git a/actionpack/lib/action_controller/vendor/html-scanner.rb b/actionpack/lib/action_controller/vendor/html-scanner.rb index 2cb20ddd05..879b31e60e 100644 --- a/actionpack/lib/action_controller/vendor/html-scanner.rb +++ b/actionpack/lib/action_controller/vendor/html-scanner.rb @@ -3,16 +3,18 @@ $LOAD_PATH << "#{File.dirname(__FILE__)}/html-scanner" module HTML extend ActiveSupport::Autoload - autoload :CDATA, 'html/node' - autoload :Document, 'html/document' - autoload :FullSanitizer, 'html/sanitizer' - autoload :LinkSanitizer, 'html/sanitizer' - autoload :Node, 'html/node' - autoload :Sanitizer, 'html/sanitizer' - autoload :Selector, 'html/selector' - autoload :Tag, 'html/node' - autoload :Text, 'html/node' - autoload :Tokenizer, 'html/tokenizer' - autoload :Version, 'html/version' - autoload :WhiteListSanitizer, 'html/sanitizer' + eager_autoload do + autoload :CDATA, 'html/node' + autoload :Document, 'html/document' + autoload :FullSanitizer, 'html/sanitizer' + autoload :LinkSanitizer, 'html/sanitizer' + autoload :Node, 'html/node' + autoload :Sanitizer, 'html/sanitizer' + autoload :Selector, 'html/selector' + autoload :Tag, 'html/node' + autoload :Text, 'html/node' + autoload :Tokenizer, 'html/tokenizer' + autoload :Version, 'html/version' + autoload :WhiteListSanitizer, 'html/sanitizer' + end end diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 4e04e2a17c..fafcf7dc4e 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -34,42 +34,40 @@ end module ActionDispatch extend ActiveSupport::Autoload - deferrable do - autoload_under 'http' do - autoload :Request - autoload :Response - end + autoload_under 'http' do + autoload :Request + autoload :Response + end - autoload_under 'middleware' do - autoload :Callbacks - autoload :ParamsParser - autoload :Rescue - autoload :ShowExceptions - autoload :Static - autoload :StringCoercion - end + 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 - module Http - autoload :Headers, 'action_dispatch/http/headers' - end + module Http + autoload :Headers, 'action_dispatch/http/headers' + 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 + 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_under 'testing' do - autoload :Assertions - autoload :Integration - autoload :PerformanceTest - autoload :TestProcess - autoload :TestRequest - autoload :TestResponse - end + autoload_under 'testing' do + autoload :Assertions + autoload :Integration + autoload :PerformanceTest + autoload :TestProcess + autoload :TestRequest + autoload :TestResponse end end diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index aabe8c4314..f57f9ca229 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -31,27 +31,28 @@ require 'action_pack' module ActionView extend ActiveSupport::Autoload - autoload :Base - autoload :Context - autoload :Template - autoload :Helpers - autoload :SafeBuffer - - - autoload_under "render" do - autoload :Partials - autoload :Rendering + eager_autoload do + autoload :Base + autoload :Context + autoload :Template + autoload :Helpers + autoload :SafeBuffer + + autoload_under "render" do + autoload :Partials + autoload :Rendering + end + + autoload :MissingTemplate, 'action_view/base' + autoload :Resolver, 'action_view/template/resolver' + 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 - - autoload :MissingTemplate, 'action_view/base' - autoload :Resolver, 'action_view/template/resolver' - 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.rb b/actionpack/lib/action_view/template.rb index 210ad508f5..a64ee09245 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -7,12 +7,14 @@ require "action_view/template/resolver" module ActionView class Template extend ActiveSupport::Autoload - - autoload :Error - autoload :Handler - autoload :Handlers - autoload :Text - + + eager_autoload do + autoload :Error + autoload :Handler + autoload :Handlers + autoload :Text + end + extend Template::Handlers attr_reader :source, :identifier, :handler, :mime_type, :formats, :details -- cgit v1.2.3 From fe5f66041395f7afa0359af6b075604c63574c85 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Tue, 22 Dec 2009 17:25:34 -0800 Subject: Dont encourage __FILE__ bullshit --- actionpack/lib/action_dispatch/testing/integration.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb index 5c127dfe37..2a5f5dcd5c 100644 --- a/actionpack/lib/action_dispatch/testing/integration.rb +++ b/actionpack/lib/action_dispatch/testing/integration.rb @@ -411,7 +411,7 @@ module ActionDispatch # At its simplest, you simply extend IntegrationTest and write your tests # using the get/post methods: # - # require "#{File.dirname(__FILE__)}/test_helper" + # require "test_helper" # # class ExampleTest < ActionController::IntegrationTest # fixtures :people @@ -435,7 +435,7 @@ module ActionDispatch # powerful testing DSL that is specific for your application. You can even # reference any named routes you happen to have defined! # - # require "#{File.dirname(__FILE__)}/test_helper" + # require "test_helper" # # class AdvancedTest < ActionController::IntegrationTest # fixtures :people, :rooms -- cgit v1.2.3 From 38aeb1528c376f7a058beea6db0a328720b85f01 Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Wed, 23 Dec 2009 14:55:12 -0800 Subject: Moving out some framework specific initializers into the framework libraries. --- actionpack/lib/action_controller/rails.rb | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 actionpack/lib/action_controller/rails.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/rails.rb b/actionpack/lib/action_controller/rails.rb new file mode 100644 index 0000000000..c2d753f9ef --- /dev/null +++ b/actionpack/lib/action_controller/rails.rb @@ -0,0 +1,27 @@ +module ActionController + class Plugin < Rails::Plugin + plugin_name :action_controller + + initializer "action_controller.set_configs" do |app| + app.config.action_controller.each do |k,v| + ActionController::Base.send "#{k}=", v + end + end + + # TODO: ActionController::Base.logger should delegate to its own config.logger + initializer "action_controller.logger" do + ActionController::Base.logger ||= Rails.logger + end + + # Routing must be initialized after plugins to allow the former to extend the routes + # --- + # If Action Controller is not one of the loaded frameworks (Configuration#frameworks) + # this does nothing. Otherwise, it loads the routing definitions and sets up + # loading module used to lazily load controllers (Configuration#controller_paths). + initializer "action_controller.initialize_routing" do |app| + app.route_configuration_files << app.config.routes_configuration_file + app.route_configuration_files << app.config.builtin_routes_configuration_file + app.reload_routes! + end + end +end \ No newline at end of file -- cgit v1.2.3 From 94bb3316353ace661a83563f44a9c47baf438f26 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 23 Dec 2009 17:11:17 -0800 Subject: Shift more responsibility from application class to its singleton instance. Treat instantiation and boot as separate steps. Use app.config rather than app.configuration. --- actionpack/lib/action_dispatch/routing/route_set.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index a4dc5e0956..498ad3268c 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -273,7 +273,7 @@ module ActionDispatch # TODO: Move this into Railties if defined?(Rails.application) # Find namespaces in controllers/ directory - Rails.application.configuration.controller_paths.each do |load_path| + Rails.application.config.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}\/?/, '') -- cgit v1.2.3 From d2bd71a145ddc5e3e3750edc9a09eab742aaf02a Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Wed, 23 Dec 2009 17:01:07 -0800 Subject: Finish moving config.frameworks-dependent code to the framework plugin --- actionpack/lib/action_controller/notifications.rb | 10 --- actionpack/lib/action_controller/rails.rb | 75 +++++++++++++++++++++++ 2 files changed, 75 insertions(+), 10 deletions(-) delete mode 100644 actionpack/lib/action_controller/notifications.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/notifications.rb b/actionpack/lib/action_controller/notifications.rb deleted file mode 100644 index 1a4f29e0e2..0000000000 --- a/actionpack/lib/action_controller/notifications.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'active_support/notifications' - -ActiveSupport::Notifications.subscribe(/(read|write|cache|expire|exist)_(fragment|page)\??/) do |*args| - event = ActiveSupport::Notifications::Event.new(*args) - - if logger = ActionController::Base.logger - human_name = event.name.to_s.humanize - logger.info("#{human_name} (%.1fms)" % event.duration) - end -end diff --git a/actionpack/lib/action_controller/rails.rb b/actionpack/lib/action_controller/rails.rb index c2d753f9ef..36a52b3149 100644 --- a/actionpack/lib/action_controller/rails.rb +++ b/actionpack/lib/action_controller/rails.rb @@ -23,5 +23,80 @@ module ActionController app.route_configuration_files << app.config.builtin_routes_configuration_file app.reload_routes! end + + # Include middleware to serve up static assets + initializer "action_controller.initialize_static_server" do |app| + if app.config.serve_static_assets + app.config.middleware.use(ActionDispatch::Static, Rails.public_path) + end + end + + initializer "action_controller.initialize_middleware_stack" do |app| + middleware = app.config.middleware + middleware.use(::Rack::Lock, :if => lambda { ActionController::Base.allow_concurrency }) + middleware.use(::Rack::Runtime) + middleware.use(ActionDispatch::ShowExceptions, lambda { ActionController::Base.consider_all_requests_local }) + middleware.use(ActionDispatch::Callbacks, lambda { ActionController::Dispatcher.prepare_each_request }) + middleware.use(lambda { ActionController::Base.session_store }, lambda { ActionController::Base.session_options }) + middleware.use(ActionDispatch::ParamsParser) + middleware.use(::Rack::MethodOverride) + middleware.use(::Rack::Head) + middleware.use(ActionDispatch::StringCoercion) + end + + initializer "action_controller.initialize_framework_caches" do + ActionController::Base.cache_store ||= RAILS_CACHE + end + + # Sets +ActionController::Base#view_paths+ and +ActionMailer::Base#template_root+ + # (but only for those frameworks that are to be loaded). If the framework's + # paths have already been set, it is not changed, otherwise it is + # set to use Configuration#view_path. + initializer "action_controller.initialize_framework_views" do |app| + # TODO: this should be combined with the logic for default config.action_controller.view_paths + view_path = ActionView::PathSet.type_cast(app.config.view_path, app.config.cache_classes) + ActionController::Base.view_paths = view_path if ActionController::Base.view_paths.blank? + end + + initializer "action_controller.initialize_metal" do |app| + Rails::Rack::Metal.requested_metals = app.config.metals + + app.config.middleware.insert_before(:"ActionDispatch::ParamsParser", + Rails::Rack::Metal, :if => Rails::Rack::Metal.metals.any?) + end + + # # Prepare dispatcher callbacks and run 'prepare' callbacks + initializer "action_controller.prepare_dispatcher" do |app| + # TODO: This used to say unless defined?(Dispatcher). Find out why and fix. + require 'rails/dispatcher' + + Dispatcher.define_dispatcher_callbacks(app.config.cache_classes) + + unless app.config.cache_classes + # Setup dev mode route reloading + routes_last_modified = app.routes_changed_at + reload_routes = lambda do + unless app.routes_changed_at == routes_last_modified + routes_last_modified = app.routes_changed_at + app.reload_routes! + end + end + ActionDispatch::Callbacks.before_dispatch { |callbacks| reload_routes.call } + end + end + + initializer "action_controller.notifications" do |app| + require 'active_support/notifications' + + ActiveSupport::Notifications.subscribe(/(read|write|cache|expire|exist)_(fragment|page)\??/) do |*args| + event = ActiveSupport::Notifications::Event.new(*args) + + if logger = ActionController::Base.logger + human_name = event.name.to_s.humanize + logger.info("#{human_name} (%.1fms)" % event.duration) + end + end + end + end end \ No newline at end of file -- cgit v1.2.3 From 4d3602a8c4b38052c70655cd7d9dea42ae10ea8d Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 23 Dec 2009 17:42:30 -0800 Subject: Routing: fix that route shorthand shouldn't ignore other options. Raise if :as option is given to root method since its name is always 'root' --- actionpack/lib/action_dispatch/routing/mapper.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 46163706c3..40e30bca6f 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -35,13 +35,15 @@ module ActionDispatch end def root(options = {}) + raise "Can't rename root to #{options[:as].inspect}: root is always named 'root'" if options.include?(:as) match '/', options.merge(:as => :root) end def match(*args) if args.one? && args.first.is_a?(Hash) - path = args.first.keys.first - options = { :to => args.first.values.first } + options = args.first + path = options.keys.first + options[:to] = options.delete(path) else path = args.first options = args.extract_options! -- cgit v1.2.3 From 9653599a798b66fe19b70cd8ed33b3d344b26883 Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Wed, 23 Dec 2009 18:59:49 -0800 Subject: Remove the ActionView::Base autoload because it creates crazy circular autoload insanity --- actionpack/lib/action_view.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index f57f9ca229..8ce6e82524 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -32,7 +32,6 @@ module ActionView extend ActiveSupport::Autoload eager_autoload do - autoload :Base autoload :Context autoload :Template autoload :Helpers @@ -56,5 +55,6 @@ module ActionView end require 'action_view/erb/util' +require 'action_view/base' I18n.load_path << "#{File.dirname(__FILE__)}/action_view/locale/en.yml" -- cgit v1.2.3 From aa3565f3a6327c947ded314525ba1d0674d5a71e Mon Sep 17 00:00:00 2001 From: Sam Ruby Date: Wed, 23 Dec 2009 23:33:14 -0500 Subject: Allow named_routes to be used with root, and with new DSL short-form. The real use case it to make all of the following act the same: root 'store#index', :as => 'store' match '/' => 'store#index', :as => 'store' match '/', :to => 'store#index', :as => 'store' The test case provided deviates from this in order to demonstrate all three forms in a single set of test routes. Signed-off-by: Jeremy Kemper --- actionpack/lib/action_dispatch/routing/mapper.rb | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 40e30bca6f..3eadb0e9fe 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -35,18 +35,17 @@ module ActionDispatch end def root(options = {}) - raise "Can't rename root to #{options[:as].inspect}: root is always named 'root'" if options.include?(:as) - match '/', options.merge(:as => :root) + match '/', options.reverse_merge(:as => :root) end def match(*args) - if args.one? && args.first.is_a?(Hash) - options = args.first - path = options.keys.first - options[:to] = options.delete(path) + options = args.extract_options! + + if args.empty? + path, to = options.find {|name,value| name.is_a?(String)} + options.merge!(:to => to).delete(path) if path else - path = args.first - options = args.extract_options! + path = args.first end conditions, defaults = {}, {} -- cgit v1.2.3 From 2b7256a42e63640d6e94fe80ee67093ed0f06e4c Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 24 Dec 2009 15:23:39 -0800 Subject: Extract Mapping class from monster match method --- actionpack/lib/action_dispatch/routing/mapper.rb | 227 ++++++++++++++--------- 1 file changed, 137 insertions(+), 90 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 46163706c3..a6b32e0152 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -19,9 +19,9 @@ module ActionDispatch @constraints.each { |constraint| if constraint.respond_to?(:matches?) && !constraint.matches?(req) - return [417, {}, []] + return [ 417, {}, [] ] elsif constraint.respond_to?(:call) && !constraint.call(req) - return [417, {}, []] + return [ 417, {}, [] ] end } @@ -29,94 +29,138 @@ module ActionDispatch end end - module Base - def initialize(set) - @set = set + class Mapping + def initialize(set, scope, args) + @set, @scope = set, scope + @path, @options = extract_path_and_options(args) end - - def root(options = {}) - match '/', options.merge(:as => :root) + + def to_route + [ app, conditions, requirements, defaults, @options[:as] ] end - - def match(*args) - if args.one? && args.first.is_a?(Hash) - path = args.first.keys.first - options = { :to => args.first.values.first } - else - path = args.first + + private + def extract_path_and_options(args) options = args.extract_options! - end - - conditions, defaults = {}, {} - - path = nil 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 - constraints = options[:constraints] || {} - unless constraints.is_a?(Hash) - block, constraints = constraints, {} + if args.empty? + path, to = options.find { |name, value| name.is_a?(String) } + options.merge!(:to => to).delete(path) if path + else + path = args.first + end + + [ normalize_path(path), options ] 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 + def normalize_path(path) + path = nil if path == "" + path = "#{@scope[:path]}#{path}" if @scope[:path] + path = Rack::Mount::Utils.normalize_path(path) if path - 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) + raise ArgumentError, "path is required" unless path + + path + end - requirements[:controller] ||= @set.controller_constraints - if via = options[:via] - via = Array(via).map { |m| m.to_s.upcase } - conditions[:request_method] = Regexp.union(*via) + def app + Constraints.new( + to.respond_to?(:call) ? to : Routing::RouteSet::Dispatcher.new(:defaults => defaults), + blocks + ) 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) + def conditions + { :path_info => @path }.merge(constraints).merge(request_method_condition) + end + + def requirements + @requirements ||= returning(@options[:constraints] || {}) do |requirements| + requirements.reverse_merge!(@scope[:constraints]) if @scope[:constraints] + @options.each { |k, v| requirements[k] = v if v.is_a?(Regexp) } + requirements[:controller] ||= @set.controller_constraints + end + end - @set.add_route(app, conditions, requirements, defaults, options[:as]) + def defaults + @defaults ||= if to.respond_to?(:call) + { } + else + defaults = case to + when String + controller, action = to.split('#') + { :controller => controller, :action => action } + when Symbol + { :controller => default_controller, :action => to.to_s } + else + { :controller => default_controller } + end + + if defaults[:controller].blank? && segment_keys.exclude?("controller") + raise ArgumentError, "missing :controller" + end + + if defaults[:action].blank? && segment_keys.exclude?("action") + raise ArgumentError, "missing :action" + end + + defaults + end + end - self - end + + def blocks + if @options[:constraints].present? && !@options[:constraints].is_a?(Hash) + block = @options[:constraints] + else + block = nil + end + + ((@scope[:blocks] || []) + [ block ]).compact + end + + def constraints + @constraints ||= requirements.reject { |k, v| segment_keys.include?(k.to_s) || k == :controller } + 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 + def request_method_condition + if via = @options[:via] + via = Array(via).map { |m| m.to_s.upcase } + { :request_method => Regexp.union(*via) } + else + { } end + end + + def segment_keys + @segment_keys ||= Rack::Mount::RegexpWithNamedGroups.new( + Rack::Mount::Strexp.compile(@path, requirements, SEPARATORS) + ).names + end - app || Routing::RouteSet::Dispatcher.new(:defaults => defaults) + def to + @options[:to] + end + + def default_controller + @scope[:controller].to_s if @scope[:controller] end + end - def validate_defaults!(app, defaults, segment_keys) - return unless app.is_a?(Routing::RouteSet::Dispatcher) + module Base + def initialize(set) + @set = set + end - unless defaults.include?(:controller) || segment_keys.include?("controller") - raise ArgumentError, "missing :controller" - end + def root(options = {}) + match '/', options.reverse_merge(:as => :root) + end - unless defaults.include?(:action) || segment_keys.include?("action") - raise ArgumentError, "missing :action" - end - end + def match(*args) + @set.add_route(*Mapping.new(@set, @scope, args).to_route) + self + end end module HttpHelpers @@ -139,15 +183,16 @@ module ActionDispatch def redirect(*args, &block) options = args.last.is_a?(Hash) ? args.pop : {} - path = args.shift || block - path_proc = path.is_a?(Proc) ? path : proc {|params| path % params } - status = options[:status] || 301 + path = args.shift || block + path_proc = path.is_a?(Proc) ? path : proc { |params| path % params } + status = options[:status] || 301 lambda do |env| - req = Rack::Request.new(env) + req = Rack::Request.new(env) params = path_proc.call(env["action_dispatch.request.path_parameters"]) - url = req.scheme + '://' + req.host + params - [status, {'Location' => url, 'Content-Type' => 'text/html'}, ['Moved Permanently']] + url = req.scheme + '://' + req.host + params + + [ status, {'Location' => url, 'Content-Type' => 'text/html'}, ['Moved Permanently'] ] end end @@ -211,11 +256,11 @@ module ActionDispatch self ensure - @scope[:path] = path if path_set + @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[:controller] = controller if controller_set + @scope[:options] = options + @scope[:blocks] = blocks @scope[:constraints] = constraints end @@ -311,12 +356,12 @@ module ActionDispatch with_scope_level(:resource, resource) do yield if block_given? - 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}" + 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 @@ -346,8 +391,9 @@ module ActionDispatch yield if block_given? with_scope_level(:collection) do - get "(.:format)", :to => :index, :as => resource.collection_name + get "(.:format)", :to => :index, :as => resource.collection_name post "(.:format)", :to => :create + with_exclusive_name_prefix :new do get "/new(.:format)", :to => :new, :as => resource.singular end @@ -355,9 +401,10 @@ module ActionDispatch with_scope_level(:member) do scope("/:id") do - get "(.:format)", :to => :show, :as => resource.member_name - put "(.:format)", :to => :update + get "(.:format)", :to => :show, :as => resource.member_name + put "(.:format)", :to => :update delete "(.:format)", :to => :destroy + with_exclusive_name_prefix :edit do get "/edit(.:format)", :to => :edit, :as => resource.singular end @@ -473,4 +520,4 @@ module ActionDispatch include Resources end end -end +end \ No newline at end of file -- cgit v1.2.3 From 6ce5982afa4e368a3baf9c8049824fd0c6d2d8fb Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 24 Dec 2009 16:13:50 -0800 Subject: Stray carrier return --- actionpack/lib/action_view/safe_buffer.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/safe_buffer.rb b/actionpack/lib/action_view/safe_buffer.rb index 09f44ab26f..6be05b9e1e 100644 --- a/actionpack/lib/action_view/safe_buffer.rb +++ b/actionpack/lib/action_view/safe_buffer.rb @@ -1,4 +1,3 @@ - module ActionView #:nodoc: class SafeBuffer < String def <<(value) -- cgit v1.2.3 From 0a365d63f6fc99ce63781a15aefda87c4074108d Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 24 Dec 2009 20:32:53 -0800 Subject: Translated strings in the view are assumed html_safe (Closes #3401) --- actionpack/lib/action_view/helpers/translation_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb index 564f12c955..35c431d78d 100644 --- a/actionpack/lib/action_view/helpers/translation_helper.rb +++ b/actionpack/lib/action_view/helpers/translation_helper.rb @@ -12,7 +12,7 @@ module ActionView # prepend the key with a period, nothing is converted. def translate(key, options = {}) options[:raise] = true - I18n.translate(scope_key_by_partial(key), options) + I18n.translate(scope_key_by_partial(key), options).html_safe! rescue I18n::MissingTranslationData => e keys = I18n.send(:normalize_translation_keys, e.locale, e.key, e.options[:scope]) content_tag('span', keys.join(', '), :class => 'translation_missing') -- cgit v1.2.3 From baaaf2acaa58748bf9dc49859d1bca3ed273dc65 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 24 Dec 2009 21:46:47 -0800 Subject: Dead code --- actionpack/lib/action_view/template.rb | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index a64ee09245..d46c989d11 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -116,21 +116,6 @@ module ActionView 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] ||= -- cgit v1.2.3 From f3b072189a6a77717f99e38403392a68f5818a49 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 24 Dec 2009 21:49:50 -0800 Subject: Instead of marking raw text in templates as safe, and then putting them through String#<< which checks if the String is safe, use safe_concat, which uses the original (internal) String#<< and leaves the safe flag as is. Results in a significant performance improvement. --- actionpack/lib/action_view/template/handlers/erb.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/template/handlers/erb.rb b/actionpack/lib/action_view/template/handlers/erb.rb index f8e6376589..93a4315108 100644 --- a/actionpack/lib/action_view/template/handlers/erb.rb +++ b/actionpack/lib/action_view/template/handlers/erb.rb @@ -10,7 +10,8 @@ module ActionView end def add_text(src, text) - src << "@output_buffer << ('" << escape_text(text) << "'.html_safe!);" + return if text.empty? + src << "@output_buffer.safe_concat('" << escape_text(text) << "');" end def add_expr_literal(src, code) -- cgit v1.2.3 From 7f5d44bac548c9f80e2ea88e191356dbb099593e Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 25 Dec 2009 10:14:44 -0800 Subject: The controller key shouldnt be part of the mapping if its not used --- actionpack/lib/action_dispatch/routing/mapper.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index a6b32e0152..b48fc6edc5 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -92,9 +92,9 @@ module ActionDispatch controller, action = to.split('#') { :controller => controller, :action => action } when Symbol - { :controller => default_controller, :action => to.to_s } + { :action => to.to_s }.merge(default_controller ? { :controller => default_controller } : {}) else - { :controller => default_controller } + default_controller ? { :controller => default_controller } : {} end if defaults[:controller].blank? && segment_keys.exclude?("controller") -- cgit v1.2.3 From 48273a44c6176b72e432f365c7905fd8c4d4b754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 25 Dec 2009 20:25:18 +0100 Subject: Wrap layout rendering in one method: _render_layout (this should make partial instrumentation easier). --- actionpack/lib/action_view/render/partials.rb | 2 +- actionpack/lib/action_view/render/rendering.rb | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index aeaf1ee4ff..00b12ad3a9 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -274,7 +274,7 @@ module ActionView if @block || !options[:layout] content else - find_template(options[:layout]).render(@view, @locals) { content } + @view._render_layout(find_template(options[:layout]), @locals){ content } end end diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index d4d16b4d98..c4033fad9e 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -73,7 +73,6 @@ module ActionView # would be Hello David. def _layout_for(name = nil, &block) return @_content_for[name || :layout] if !block_given? || name - capture(&block) end @@ -88,10 +87,7 @@ module ActionView end def _render_text(content, layout, locals) - content = layout.render(self, locals) do |*name| - _layout_for(*name) { content } - end if layout - + content = _render_layout(layout, locals){ content } if layout content end @@ -121,10 +117,14 @@ module ActionView if layout @_layout = layout.identifier logger.info("Rendering template within #{layout.inspect}") if logger - content = layout.render(self, locals) { |*name| _layout_for(*name) } + content = _render_layout(layout, locals) end content end + + def _render_layout(layout, locals, &block) + layout.render(self, locals){ |*name| _layout_for(*name, &block) } + end end end -- cgit v1.2.3 From c86424a72d229c519179a6cdf1d37e93b46e1e38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 25 Dec 2009 23:37:16 +0100 Subject: Break instrumentation into several end-points so rendering of partials can be optimized. --- actionpack/lib/action_view/render/partials.rb | 42 ++++++++++++++------------ actionpack/lib/action_view/render/rendering.rb | 24 ++++++++++----- actionpack/lib/action_view/template.rb | 6 ++-- 3 files changed, 42 insertions(+), 30 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index 00b12ad3a9..04edb9ab44 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -205,11 +205,22 @@ module ActionView end def render + options = @options + if @collection = collection - render_collection + ActiveSupport::Notifications.instrument(:render_collection, :path => @path, + :count => @collection.size) do + render_collection + end else - @template = template = find_template - render_template(template, @object || @locals[template.variable_name]) + content = ActiveSupport::Notifications.instrument(:render_partial, :path => @path) do + render_partial + end + + if !@block && options[:layout] + content = @view._render_layout(find_template(options[:layout]), @locals){ content } + end + content end end @@ -227,9 +238,7 @@ module ActionView end def collection_with_template(template) - options = @options - - segments, locals, as = [], @locals, options[:as] || template.variable_name + segments, locals, as = [], @locals, @options[:as] || template.variable_name counter_name = template.counter_name locals[counter_name] = -1 @@ -246,9 +255,7 @@ module ActionView end def collection_without_template - options = @options - - segments, locals, as = [], @locals, options[:as] + segments, locals, as = [], @locals, @options[:as] index, template = -1, nil @collection.each do |object| @@ -263,18 +270,15 @@ module ActionView segments end - def render_template(template, object = @object) - options, locals, view = @options, @locals, @view - locals[options[:as] || template.variable_name] = object + def render_partial(object = @object) + @template = template = find_template + locals, view = @locals, @view - content = template.render(view, locals) do |*name| - @view._layout_for(*name, &@block) - end + object ||= locals[template.variable_name] + locals[@options[:as] || template.variable_name] = object - if @block || !options[:layout] - content - else - @view._render_layout(find_template(options[:layout]), @locals){ content } + template.render(view, locals) do |*name| + view._layout_for(*name, &@block) end end diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index c4033fad9e..5e7dd3e2df 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -77,16 +77,19 @@ module ActionView end def _render_inline(inline, layout, options) - handler = Template.handler_class_for_extension(options[:type] || "erb") - template = Template.new(options[:inline], "inline template", handler, {}) + locals = options[:locals] - locals = options[:locals] - content = template.render(self, locals) + content = ActiveSupport::Notifications.instrument(:render_inline) do + handler = Template.handler_class_for_extension(options[:type] || "erb") + template = Template.new(options[:inline], "inline template", handler, {}) + template.render(self, locals) + end _render_text(content, layout, locals) end def _render_text(content, layout, locals) + ActiveSupport::Notifications.instrument(:render_text) content = _render_layout(layout, locals){ content } if layout content end @@ -110,8 +113,13 @@ module ActionView msg end - locals = options[:locals] || {} - content = partial ? _render_partial_object(template, options) : template.render(self, locals) + locals = options[:locals] || {} + + content = ActiveSupport::Notifications.instrument(:render_template, + :identifier => template.identifier, :layout => (layout ? layout.identifier : nil)) do + partial ? _render_partial_object(template, options) : template.render(self, locals) + end + @_content_for[:layout] = content if layout @@ -124,7 +132,9 @@ module ActionView end def _render_layout(layout, locals, &block) - layout.render(self, locals){ |*name| _layout_for(*name, &block) } + ActiveSupport::Notifications.instrument(:render_layout, :identifier => layout.identifier) do + layout.render(self, locals){ |*name| _layout_for(*name, &block) } + end end end end diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index d46c989d11..adaf6544a7 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -36,10 +36,8 @@ module ActionView 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 + method_name = compile(locals, view) + view.send(method_name, locals, &block) rescue Exception => e if e.is_a?(Template::Error) e.sub_template_of(self) -- cgit v1.2.3 From ff1a1c0b4d08567e8aeaef698003b5cd96d79686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 26 Dec 2009 11:02:41 +0100 Subject: Optimize <%= render(@posts) %>. --- actionpack/lib/action_view/render/partials.rb | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index 04edb9ab44..eb035ae2dd 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -233,7 +233,17 @@ module ActionView spacer = find_template(@options[:spacer_template]).render(@view, @locals) end - result = template ? collection_with_template(template) : collection_without_template + result = if template + collection_with_template(template) + else + paths = @collection.map { |o| partial_path(o) } + + if paths.uniq.size == 1 + collection_with_template(find_template(paths.first)) + else + collection_without_template(paths) + end + end result.join(spacer).html_safe! end @@ -254,12 +264,12 @@ module ActionView segments end - def collection_without_template + def collection_without_template(collection_paths) segments, locals, as = [], @locals, @options[:as] index, template = -1, nil - @collection.each do |object| - template = find_template(partial_path(object)) + @collection.each_with_index do |object, i| + template = find_template(collection_paths[i]) locals[template.counter_name] = (index += 1) locals[template.variable_name] = object -- cgit v1.2.3 From 8a36e907d2a0a28be1fa8334221cc2e195d75168 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 26 Dec 2009 12:43:48 +0100 Subject: More <%= render(@posts) %> optimization. --- actionpack/lib/action_view/render/partials.rb | 44 ++++++++++++--------------- 1 file changed, 20 insertions(+), 24 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index eb035ae2dd..5158415c20 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -191,23 +191,30 @@ module ActionView def setup(options, block) partial = options[:partial] - @options = options - @locals = options[:locals] || {} - @block = block + @options = options + @locals = options[:locals] || {} + @block = block if String === partial - @object = options[:object] - @path = partial + @object = options[:object] + @path = partial + @collection = collection else @object = partial - @path = partial_path(partial) + + if @collection = collection + paths = @collection_paths = @collection.map { |o| partial_path(o) } + @path = paths.uniq.size == 1 ? paths.first : nil + else + @path = partial_path + end end end def render options = @options - if @collection = collection + if @collection ActiveSupport::Notifications.instrument(:render_collection, :path => @path, :count => @collection.size) do render_collection @@ -226,28 +233,17 @@ module ActionView def render_collection @template = template = find_template - return nil if @collection.blank? if @options.key?(:spacer_template) spacer = find_template(@options[:spacer_template]).render(@view, @locals) end - result = if template - collection_with_template(template) - else - paths = @collection.map { |o| partial_path(o) } - - if paths.uniq.size == 1 - collection_with_template(find_template(paths.first)) - else - collection_without_template(paths) - end - end + result = template ? collection_with_template : collection_without_template result.join(spacer).html_safe! end - def collection_with_template(template) + def collection_with_template(template = @template) segments, locals, as = [], @locals, @options[:as] || template.variable_name counter_name = template.counter_name @@ -264,14 +260,14 @@ module ActionView segments end - def collection_without_template(collection_paths) + def collection_without_template(collection_paths = @collection_paths) segments, locals, as = [], @locals, @options[:as] index, template = -1, nil @collection.each_with_index do |object, i| template = find_template(collection_paths[i]) locals[template.counter_name] = (index += 1) - locals[template.variable_name] = object + locals[as || template.variable_name] = object segments << template.render(@view, locals) end @@ -319,9 +315,9 @@ module ActionView def partial_path(object = @object) @partial_names[object.class] ||= begin - return nil unless object.respond_to?(:to_model) + object = object.to_model if object.respond_to?(:to_model) - object.to_model.class.model_name.partial_path.dup.tap do |partial| + object.class.model_name.partial_path.dup.tap do |partial| path = @view.controller_path partial.insert(0, "#{File.dirname(path)}/") if path.include?(?/) end -- cgit v1.2.3 From 673fa7f06608151aa4a5e6e754894978b4000b63 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 26 Dec 2009 12:43:50 -0600 Subject: rack-mount 0.4 --- actionpack/lib/action_dispatch/routing/mapper.rb | 38 +++++++++++----------- .../lib/action_dispatch/routing/route_set.rb | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index b48fc6edc5..e655d6a708 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -19,9 +19,9 @@ module ActionDispatch @constraints.each { |constraint| if constraint.respond_to?(:matches?) && !constraint.matches?(req) - return [ 417, {}, [] ] + return [ 404, {'X-Cascade' => 'pass'}, [] ] elsif constraint.respond_to?(:call) && !constraint.call(req) - return [ 417, {}, [] ] + return [ 404, {'X-Cascade' => 'pass'}, [] ] end } @@ -34,11 +34,11 @@ module ActionDispatch @set, @scope = set, scope @path, @options = extract_path_and_options(args) end - + def to_route [ app, conditions, requirements, defaults, @options[:as] ] end - + private def extract_path_and_options(args) options = args.extract_options! @@ -49,18 +49,18 @@ module ActionDispatch else path = args.first end - + [ normalize_path(path), options ] end def normalize_path(path) path = nil if path == "" path = "#{@scope[:path]}#{path}" if @scope[:path] - path = Rack::Mount::Utils.normalize_path(path) if path + path = Rack::Mount::Utils.normalize_path(path) if path raise ArgumentError, "path is required" unless path - - path + + path end @@ -74,7 +74,7 @@ module ActionDispatch def conditions { :path_info => @path }.merge(constraints).merge(request_method_condition) end - + def requirements @requirements ||= returning(@options[:constraints] || {}) do |requirements| requirements.reverse_merge!(@scope[:constraints]) if @scope[:constraints] @@ -96,30 +96,30 @@ module ActionDispatch else default_controller ? { :controller => default_controller } : {} end - + if defaults[:controller].blank? && segment_keys.exclude?("controller") raise ArgumentError, "missing :controller" end - + if defaults[:action].blank? && segment_keys.exclude?("action") raise ArgumentError, "missing :action" end - + defaults end end - + def blocks if @options[:constraints].present? && !@options[:constraints].is_a?(Hash) block = @options[:constraints] else block = nil end - - ((@scope[:blocks] || []) + [ block ]).compact + + ((@scope[:blocks] || []) + [ block ]).compact end - + def constraints @constraints ||= requirements.reject { |k, v| segment_keys.include?(k.to_s) || k == :controller } end @@ -132,7 +132,7 @@ module ActionDispatch { } end end - + def segment_keys @segment_keys ||= Rack::Mount::RegexpWithNamedGroups.new( Rack::Mount::Strexp.compile(@path, requirements, SEPARATORS) @@ -142,7 +142,7 @@ module ActionDispatch def to @options[:to] end - + def default_controller @scope[:controller].to_s if @scope[:controller] end @@ -520,4 +520,4 @@ module ActionDispatch include Resources end end -end \ No newline at end of file +end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 498ad3268c..bd397432ce 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -21,7 +21,7 @@ module ActionDispatch prepare_params!(params) unless controller = controller(params) - return [417, {}, []] + return [404, {'X-Cascade' => 'pass'}, []] end controller.action(params[:action]).call(env) -- cgit v1.2.3 From feb7382047bf5e354edd12aa89895ec4591a5614 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 26 Dec 2009 13:28:06 -0600 Subject: AD::Cascade that supports X-Cascade --- actionpack/lib/action_dispatch.rb | 1 + .../lib/action_dispatch/middleware/cascade.rb | 29 ++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 actionpack/lib/action_dispatch/middleware/cascade.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index fafcf7dc4e..0696cb017c 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -41,6 +41,7 @@ module ActionDispatch autoload_under 'middleware' do autoload :Callbacks + autoload :Cascade autoload :ParamsParser autoload :Rescue autoload :ShowExceptions diff --git a/actionpack/lib/action_dispatch/middleware/cascade.rb b/actionpack/lib/action_dispatch/middleware/cascade.rb new file mode 100644 index 0000000000..9f5c9891f0 --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/cascade.rb @@ -0,0 +1,29 @@ +module ActionDispatch + class Cascade + def self.new(*apps) + apps = apps.flatten + + case apps.length + when 0 + raise ArgumentError, "app is required" + when 1 + apps.first + else + super(apps) + end + end + + def initialize(apps) + @apps = apps + end + + def call(env) + result = nil + @apps.each do |app| + result = app.call(env) + break unless result[1]["X-Cascade"] == "pass" + end + result + end + end +end -- cgit v1.2.3 From 75ba102a80965b2612df0253d1278581a88b8d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 26 Dec 2009 20:28:53 +0100 Subject: Remove ActionView inline logging to ActiveSupport::Notifications and create ActionController::Base#log_event, so everything can be logged within one listener. Also expose log_process_action as a hook for different modules to include their own information during the action processing. This allow ActiveRecord to hook and any other ORM. Finally, this commit changes 'Processing' and 'Rendering' in logs to 'Processed' and 'Rendered' because at the point it's logged, everying already happened. --- actionpack/lib/abstract_controller/logger.rb | 20 ------ actionpack/lib/action_controller/base.rb | 1 - actionpack/lib/action_controller/caching.rb | 11 ++++ .../lib/action_controller/caching/fragments.rb | 2 +- .../metal/active_record_runtime.rb | 27 ++++++++ .../lib/action_controller/metal/benchmarking.rb | 72 ---------------------- .../metal/filter_parameter_logging.rb | 22 +++---- actionpack/lib/action_controller/metal/logger.rb | 70 ++++++++++++++++----- actionpack/lib/action_controller/rails.rb | 13 +--- actionpack/lib/action_view/render/rendering.rb | 9 +-- 10 files changed, 108 insertions(+), 139 deletions(-) create mode 100644 actionpack/lib/action_controller/metal/active_record_runtime.rb delete mode 100644 actionpack/lib/action_controller/metal/benchmarking.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/abstract_controller/logger.rb b/actionpack/lib/abstract_controller/logger.rb index e3bcd28da7..a23a13e1d6 100644 --- a/actionpack/lib/abstract_controller/logger.rb +++ b/actionpack/lib/abstract_controller/logger.rb @@ -9,25 +9,5 @@ module AbstractController cattr_accessor :logger extend ActiveSupport::Benchmarkable end - - # A class that allows you to defer expensive processing - # until the logger actually tries to log. Otherwise, you are - # forced to do the processing in advance, and send the - # entire processed String to the logger, which might - # just discard the String if the log level is too low. - # - # TODO: Require that Rails loggers accept a block. - class DelayedLog < ActiveSupport::BasicObject - def initialize(&block) - @str, @block = nil, block - end - - def method_missing(*args, &block) - unless @str - @str, @block = @block.call, nil - end - @str.send(*args, &block) - end - end end end diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index dbba69f637..67656110c4 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -15,7 +15,6 @@ module ActionController include ActionController::ConditionalGet include ActionController::RackDelegation include ActionController::Logger - include ActionController::Benchmarking include ActionController::Configuration # Legacy modules diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb index d784138ebe..69ed84da95 100644 --- a/actionpack/lib/action_controller/caching.rb +++ b/actionpack/lib/action_controller/caching.rb @@ -60,6 +60,17 @@ module ActionController #:nodoc: def cache_configured? perform_caching && cache_store end + + def log_event(name, before, after, instrumenter_id, payload) + if name.to_s =~ /(read|write|cache|expire|exist)_(fragment|page)\??/ + key_or_path = payload[:key] || payload[:path] + human_name = name.to_s.humanize + duration = (after - before) * 1000 + logger.info("#{human_name} #{key_or_path.inspect} (%.1fms)" % duration) + else + super + end + end end def caching_allowed? diff --git a/actionpack/lib/action_controller/caching/fragments.rb b/actionpack/lib/action_controller/caching/fragments.rb index 8c1167d526..f569d0dd8b 100644 --- a/actionpack/lib/action_controller/caching/fragments.rb +++ b/actionpack/lib/action_controller/caching/fragments.rb @@ -74,7 +74,7 @@ module ActionController #:nodoc: return unless cache_configured? key = fragment_cache_key(key) - ActiveSupport::Notifications.instrument(:fragment_exist?, :key => key) do + ActiveSupport::Notifications.instrument(:exist_fragment?, :key => key) do cache_store.exist?(key, options) end end diff --git a/actionpack/lib/action_controller/metal/active_record_runtime.rb b/actionpack/lib/action_controller/metal/active_record_runtime.rb new file mode 100644 index 0000000000..29f6dcc783 --- /dev/null +++ b/actionpack/lib/action_controller/metal/active_record_runtime.rb @@ -0,0 +1,27 @@ +module ActionController + module ActiveRecordRuntime + extend ActiveSupport::Concern + + attr_internal :db_runtime + + def cleanup_view_runtime + if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected? + db_rt_before_render = ActiveRecord::Base.connection.reset_runtime + runtime = super + db_rt_after_render = ActiveRecord::Base.connection.reset_runtime + self.db_runtime = db_rt_before_render + db_rt_after_render + runtime - db_rt_after_render + else + super + end + end + + module ClassMethods + def process_log_action(controller) + super + db_runtime = controller.send :db_runtime + logger.info(" ActiveRecord runtime: %.1fms" % db_runtime.to_f) if db_runtime + end + end + end +end \ No newline at end of file diff --git a/actionpack/lib/action_controller/metal/benchmarking.rb b/actionpack/lib/action_controller/metal/benchmarking.rb deleted file mode 100644 index f73f635b0d..0000000000 --- a/actionpack/lib/action_controller/metal/benchmarking.rb +++ /dev/null @@ -1,72 +0,0 @@ -require 'active_support/core_ext/benchmark' - -module ActionController #:nodoc: - # The benchmarking module times the performance of actions and reports to the logger. If the Active Record - # package has been included, a separate timing section for database calls will be added as well. - module Benchmarking #:nodoc: - extend ActiveSupport::Concern - - protected - def render(*args, &block) - if logger - if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected? - db_runtime = ActiveRecord::Base.connection.reset_runtime - end - - render_output = nil - @view_runtime = Benchmark.ms { render_output = super } - - if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected? - @db_rt_before_render = db_runtime - @db_rt_after_render = ActiveRecord::Base.connection.reset_runtime - @view_runtime -= @db_rt_after_render - end - - render_output - else - super - end - end - - private - def process_action(*args) - if logger - ms = [Benchmark.ms { super }, 0.01].max - logging_view = defined?(@view_runtime) - logging_active_record = Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected? - - log_message = 'Completed in %.0fms' % ms - - if logging_view || logging_active_record - log_message << " (" - log_message << view_runtime if logging_view - - if logging_active_record - log_message << ", " if logging_view - log_message << active_record_runtime + ")" - else - ")" - end - end - - log_message << " | #{response.status}" - log_message << " [#{complete_request_uri rescue "unknown"}]" - - logger.info(log_message) - else - super - end - end - - def view_runtime - "View: %.0f" % @view_runtime - end - - def active_record_runtime - db_runtime = ActiveRecord::Base.connection.reset_runtime - db_runtime += @db_rt_before_render if @db_rt_before_render - db_runtime += @db_rt_after_render if @db_rt_after_render - "DB: %.0f" % db_runtime - end - end -end diff --git a/actionpack/lib/action_controller/metal/filter_parameter_logging.rb b/actionpack/lib/action_controller/metal/filter_parameter_logging.rb index a53c052075..59e200396a 100644 --- a/actionpack/lib/action_controller/metal/filter_parameter_logging.rb +++ b/actionpack/lib/action_controller/metal/filter_parameter_logging.rb @@ -2,8 +2,6 @@ module ActionController module FilterParameterLogging extend ActiveSupport::Concern - include AbstractController::Logger - module ClassMethods # Replace sensitive parameter data from the request log. # Filters parameters that have any of the arguments as a substring. @@ -54,23 +52,25 @@ module ActionController end protected :filter_parameters end - end - INTERNAL_PARAMS = [:controller, :action, :format, :_method, :only_path] + protected - def process(*) - response = super - if logger - parameters = filter_parameters(params).except!(*INTERNAL_PARAMS) - logger.info { " Parameters: #{parameters.inspect}" } unless parameters.empty? + # Overwrite log_process_action to include parameters information. + # If this method is invoked, it means logger is defined, so don't + # worry with such scenario here. + def log_process_action(controller) #:nodoc: + params = controller.send(:filter_parameters, controller.request.params) + logger.info " Parameters: #{params.inspect}" unless params.empty? + super end - response end + INTERNAL_PARAMS = [:controller, :action, :format, :_method, :only_path] + protected def filter_parameters(params) - params.dup + params.dup.except!(*INTERNAL_PARAMS) end end diff --git a/actionpack/lib/action_controller/metal/logger.rb b/actionpack/lib/action_controller/metal/logger.rb index 956d7dd371..5d14f6c9c9 100644 --- a/actionpack/lib/action_controller/metal/logger.rb +++ b/actionpack/lib/action_controller/metal/logger.rb @@ -1,34 +1,74 @@ require 'abstract_controller/logger' module ActionController + # Adds instrumentation to process_action and a log_event method + # responsible to log events from ActiveSupport::Notifications. This module handles + # :process_action and :render_template events but allows any other module to hook + # into log_event and provide its own logging facilities (as in ActionController::Caching). module Logger - # Override process_action in the AbstractController::Base - # to log details about the method. + extend ActiveSupport::Concern + + attr_internal :view_runtime + def process_action(action) - result = ActiveSupport::Notifications.instrument(:process_action, - :controller => self, :action => action) do + ActiveSupport::Notifications.instrument(:process_action, :controller => self, :action => action) do super end + end + def render(*args, &block) if logger - log = AbstractController::Logger::DelayedLog.new do - "\n\nProcessing #{self.class.name}\##{action_name} " \ - "to #{request.formats} (for #{request_origin}) " \ - "[#{request.method.to_s.upcase}]" + render_output = nil + + self.view_runtime = cleanup_view_runtime do + Benchmark.ms { render_output = super } end - logger.info(log) + render_output + else + super end + end - result + def cleanup_view_runtime + yield end - private + module ClassMethods + def log_event(name, before, after, instrumenter_id, payload) + if name == :process_action + duration = [(after - before) * 1000, 0.01].max + controller = payload[:controller] + request = controller.request + + logger.info "\n\nProcessed #{controller.class.name}##{payload[:action]} " \ + "to #{request.formats} (for #{request.remote_ip} at #{before.to_s(:db)}) " \ + "[#{request.method.to_s.upcase}]" - # Returns the request origin with the IP and time. This needs to be cached, - # otherwise we would get different results for each time it calls. - def request_origin - @request_origin ||= "#{request.remote_ip} at #{Time.now.to_s(:db)}" + log_process_action(controller) + + message = "Completed in %.0fms" % duration + message << " | #{controller.response.status}" + message << " [#{request.request_uri rescue "unknown"}]" + + logger.info(message) + elsif name == :render_template + # TODO Make render_template logging work if you are using just ActionView + duration = (after - before) * 1000 + message = "Rendered #{payload[:identifier]}" + message << " within #{payload[:layout]}" if payload[:layout] + message << (" (%.1fms)" % duration) + logger.info(message) + end + end + + protected + + # A hook which allows logging what happened during controller process action. + def log_process_action(controller) #:nodoc: + view_runtime = controller.send :view_runtime + logger.info(" View runtime: %.1fms" % view_runtime.to_f) if view_runtime + end end end end diff --git a/actionpack/lib/action_controller/rails.rb b/actionpack/lib/action_controller/rails.rb index 36a52b3149..e381828ee4 100644 --- a/actionpack/lib/action_controller/rails.rb +++ b/actionpack/lib/action_controller/rails.rb @@ -14,10 +14,6 @@ module ActionController end # Routing must be initialized after plugins to allow the former to extend the routes - # --- - # If Action Controller is not one of the loaded frameworks (Configuration#frameworks) - # this does nothing. Otherwise, it loads the routing definitions and sets up - # loading module used to lazily load controllers (Configuration#controller_paths). initializer "action_controller.initialize_routing" do |app| app.route_configuration_files << app.config.routes_configuration_file app.route_configuration_files << app.config.builtin_routes_configuration_file @@ -88,13 +84,8 @@ module ActionController initializer "action_controller.notifications" do |app| require 'active_support/notifications' - ActiveSupport::Notifications.subscribe(/(read|write|cache|expire|exist)_(fragment|page)\??/) do |*args| - event = ActiveSupport::Notifications::Event.new(*args) - - if logger = ActionController::Base.logger - human_name = event.name.to_s.humanize - logger.info("#{human_name} (%.1fms)" % event.duration) - end + ActiveSupport::Notifications.subscribe do |*args| + ActionController::Base.log_event(*args) if ActionController::Base.logger end end diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index 5e7dd3e2df..0302e44b4e 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -107,12 +107,6 @@ module ActionView end def _render_template(template, layout = nil, options = {}, partial = nil) - logger && logger.info do - msg = "Rendering #{template.inspect}" - msg << " (#{options[:status]})" if options[:status] - msg - end - locals = options[:locals] || {} content = ActiveSupport::Notifications.instrument(:render_template, @@ -124,8 +118,7 @@ module ActionView if layout @_layout = layout.identifier - logger.info("Rendering template within #{layout.inspect}") if logger - content = _render_layout(layout, locals) + content = _render_layout(layout, locals) end content -- cgit v1.2.3 From 97db79ab3c0af7b6805dcaee99384d96ccb3567d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 27 Dec 2009 13:32:40 +0100 Subject: Remove ActiveRecord runtime logging from ActionPack and place in ActiveRecord, adding it through config.action_controller.include hook. --- .../metal/active_record_runtime.rb | 27 ---------------------- actionpack/lib/action_controller/metal/logger.rb | 17 +++++++++++--- actionpack/lib/action_controller/rails.rb | 1 + 3 files changed, 15 insertions(+), 30 deletions(-) delete mode 100644 actionpack/lib/action_controller/metal/active_record_runtime.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/metal/active_record_runtime.rb b/actionpack/lib/action_controller/metal/active_record_runtime.rb deleted file mode 100644 index 29f6dcc783..0000000000 --- a/actionpack/lib/action_controller/metal/active_record_runtime.rb +++ /dev/null @@ -1,27 +0,0 @@ -module ActionController - module ActiveRecordRuntime - extend ActiveSupport::Concern - - attr_internal :db_runtime - - def cleanup_view_runtime - if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected? - db_rt_before_render = ActiveRecord::Base.connection.reset_runtime - runtime = super - db_rt_after_render = ActiveRecord::Base.connection.reset_runtime - self.db_runtime = db_rt_before_render + db_rt_after_render - runtime - db_rt_after_render - else - super - end - end - - module ClassMethods - def process_log_action(controller) - super - db_runtime = controller.send :db_runtime - logger.info(" ActiveRecord runtime: %.1fms" % db_runtime.to_f) if db_runtime - end - end - end -end \ No newline at end of file diff --git a/actionpack/lib/action_controller/metal/logger.rb b/actionpack/lib/action_controller/metal/logger.rb index 5d14f6c9c9..e71f77fbb2 100644 --- a/actionpack/lib/action_controller/metal/logger.rb +++ b/actionpack/lib/action_controller/metal/logger.rb @@ -30,12 +30,22 @@ module ActionController end end - def cleanup_view_runtime + # If you want to remove any time taken into account in :view_runtime + # wrongly, you can do it here: + # + # def cleanup_view_runtime + # super - time_taken_in_something_expensive + # end + # + # :api: plugin + def cleanup_view_runtime #:nodoc: yield end module ClassMethods - def log_event(name, before, after, instrumenter_id, payload) + # This is the hook invoked by ActiveSupport::Notifications.subscribe. + # If you need to log any event, overwrite the method and do it here. + def log_event(name, before, after, instrumenter_id, payload) #:nodoc: if name == :process_action duration = [(after - before) * 1000, 0.01].max controller = payload[:controller] @@ -65,10 +75,11 @@ module ActionController protected # A hook which allows logging what happened during controller process action. + # :api: plugin def log_process_action(controller) #:nodoc: view_runtime = controller.send :view_runtime logger.info(" View runtime: %.1fms" % view_runtime.to_f) if view_runtime end end end -end +end \ No newline at end of file diff --git a/actionpack/lib/action_controller/rails.rb b/actionpack/lib/action_controller/rails.rb index e381828ee4..6ebb50887b 100644 --- a/actionpack/lib/action_controller/rails.rb +++ b/actionpack/lib/action_controller/rails.rb @@ -1,6 +1,7 @@ module ActionController class Plugin < Rails::Plugin plugin_name :action_controller + include_modules_in "ActionController::Base" initializer "action_controller.set_configs" do |app| app.config.action_controller.each do |k,v| -- cgit v1.2.3 From 95762cbbb3528bcb6a1a8119795df9647daaaab6 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 27 Dec 2009 14:13:03 -0800 Subject: Added shorthand for match 'products/overview' that expands to match 'products/overview', :to => 'products#overview', :as => 'products_overview' --- actionpack/lib/action_dispatch/routing/mapper.rb | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index e655d6a708..3d604158f4 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -43,15 +43,29 @@ module ActionDispatch def extract_path_and_options(args) options = args.extract_options! - if args.empty? + case + when using_to_shorthand?(args, options) path, to = options.find { |name, value| name.is_a?(String) } options.merge!(:to => to).delete(path) if path + when using_match_shorthand?(args, options) + path = args.first + options = { :to => path.gsub("/", "#"), :as => path.gsub("/", "_") } else path = args.first end [ normalize_path(path), options ] end + + # match "account" => "account#index" + def using_to_shorthand?(args, options) + args.empty? && options.present? + end + + # match "account/overview" + def using_match_shorthand?(args, options) + args.present? && options.except(:via).empty? && args.first.exclude?(":") + end def normalize_path(path) path = nil if path == "" -- cgit v1.2.3 From 438a8c3ec798e5c1b983db8a8421f634021d4420 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 27 Dec 2009 15:23:30 -0800 Subject: Require the enumberable extension from active support because we use #exclude? --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 3d604158f4..f02c681cf6 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/enumberable' + module ActionDispatch module Routing class Mapper -- cgit v1.2.3 From 3a79117c77e5c5ac44a6a561af968ecd23e3024f Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 27 Dec 2009 15:27:18 -0800 Subject: Typo --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index f02c681cf6..4943ac3fa9 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1,4 +1,4 @@ -require 'active_support/core_ext/enumberable' +require 'active_support/core_ext/enumerable' module ActionDispatch module Routing -- cgit v1.2.3 From 7c4fb93ac30b03c512ba163c5444eced18f12171 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 27 Dec 2009 15:38:00 -0800 Subject: Ruby 1.9: string is not enumerable, so #exclude? is not available --- actionpack/lib/action_dispatch/routing/mapper.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 4943ac3fa9..8f33346a4f 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1,5 +1,3 @@ -require 'active_support/core_ext/enumerable' - module ActionDispatch module Routing class Mapper @@ -58,15 +56,15 @@ module ActionDispatch [ normalize_path(path), options ] end - + # match "account" => "account#index" def using_to_shorthand?(args, options) args.empty? && options.present? end - + # match "account/overview" def using_match_shorthand?(args, options) - args.present? && options.except(:via).empty? && args.first.exclude?(":") + args.present? && options.except(:via).empty? && !args.first.include?(':') end def normalize_path(path) -- cgit v1.2.3 From 9a650a6547d2a83004db1bf913e26a8daa1c0b6e Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 28 Dec 2009 16:28:26 -0800 Subject: Silence some trivial warnings: shadowed local vars, indentation mismatches --- actionpack/lib/abstract_controller/layouts.rb | 2 +- .../lib/abstract_controller/localized_cache.rb | 2 +- actionpack/lib/action_controller/metal.rb | 2 +- actionpack/lib/action_controller/metal/cookies.rb | 242 ++++++++++----------- actionpack/lib/action_controller/metal/flash.rb | 119 +++++----- actionpack/lib/action_dispatch/http/headers.rb | 14 +- actionpack/lib/action_dispatch/http/mime_type.rb | 2 +- actionpack/lib/action_view/template/handler.rb | 4 +- actionpack/lib/action_view/template/resolver.rb | 12 +- 9 files changed, 197 insertions(+), 202 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb index 46760bba7c..4073e9b386 100644 --- a/actionpack/lib/abstract_controller/layouts.rb +++ b/actionpack/lib/abstract_controller/layouts.rb @@ -20,7 +20,7 @@ module AbstractController end def clear_template_caches! - @found_layouts.clear if @found_layouts + @found_layouts.clear if defined? @found_layouts super end diff --git a/actionpack/lib/abstract_controller/localized_cache.rb b/actionpack/lib/abstract_controller/localized_cache.rb index ee7b43cb9f..bf648af60a 100644 --- a/actionpack/lib/abstract_controller/localized_cache.rb +++ b/actionpack/lib/abstract_controller/localized_cache.rb @@ -1,6 +1,6 @@ module AbstractController class HashKey - @hash_keys = Hash.new {|h,k| h[k] = Hash.new {|h,k| h[k] = {} } } + @hash_keys = Hash.new {|h,k| h[k] = Hash.new {|sh,sk| sh[sk] = {} } } def self.get(klass, formats, locale) @hash_keys[klass][formats][locale] ||= new(klass, formats, locale) diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index b436de9878..f445ca70ee 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -85,7 +85,7 @@ module ActionController end class ActionEndpoint - @@endpoints = Hash.new {|h,k| h[k] = Hash.new {|h,k| h[k] = {} } } + @@endpoints = Hash.new {|h,k| h[k] = Hash.new {|sh,sk| sh[sk] = {} } } def self.for(controller, action, stack) @@endpoints[controller][action][stack] ||= begin diff --git a/actionpack/lib/action_controller/metal/cookies.rb b/actionpack/lib/action_controller/metal/cookies.rb index 8d5f0d7199..5b51bd21d0 100644 --- a/actionpack/lib/action_controller/metal/cookies.rb +++ b/actionpack/lib/action_controller/metal/cookies.rb @@ -58,140 +58,140 @@ module ActionController #:nodoc: def cookies @cookies ||= CookieJar.build(request, response) end - end + end - class CookieJar < Hash #:nodoc: - def self.build(request, response) - new.tap do |hash| - hash.update(request.cookies) - hash.response = response - end + class CookieJar < Hash #:nodoc: + def self.build(request, response) + new.tap do |hash| + hash.update(request.cookies) + hash.response = response end + end - attr_accessor :response + attr_accessor :response - # Returns the value of the cookie by +name+, or +nil+ if no such cookie exists. - def [](name) - super(name.to_s) - end + # Returns the value of the cookie by +name+, or +nil+ if no such cookie exists. + def [](name) + super(name.to_s) + end - # Sets the cookie named +name+. The second argument may be the very cookie - # value, or a hash of options as documented above. - def []=(key, options) - if options.is_a?(Hash) - options.symbolize_keys! - value = options[:value] - else - value = options - options = { :value => value } - end - - super(key.to_s, value) - - options[:path] ||= "/" - response.set_cookie(key, options) + # Sets the cookie named +name+. The second argument may be the very cookie + # value, or a hash of options as documented above. + def []=(key, options) + if options.is_a?(Hash) + options.symbolize_keys! + value = options[:value] + else + value = options + options = { :value => value } end - # Removes the cookie on the client machine by setting the value to an empty string - # and setting its expiration date into the past. Like []=, you can pass in - # an options hash to delete cookies with extra data such as a :path. - def delete(key, options = {}) + super(key.to_s, value) + + options[:path] ||= "/" + response.set_cookie(key, options) + end + + # Removes the cookie on the client machine by setting the value to an empty string + # and setting its expiration date into the past. Like []=, you can pass in + # an options hash to delete cookies with extra data such as a :path. + def delete(key, options = {}) + options.symbolize_keys! + options[:path] ||= "/" + value = super(key.to_s) + response.delete_cookie(key, options) + value + end + + # Returns a jar that'll automatically set the assigned cookies to have an expiration date 20 years from now. Example: + # + # cookies.permanent[:prefers_open_id] = true + # # => Set-Cookie: prefers_open_id=true; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT + # + # This jar is only meant for writing. You'll read permanent cookies through the regular accessor. + # + # This jar allows chaining with the signed jar as well, so you can set permanent, signed cookies. Examples: + # + # cookies.permanent.signed[:remember_me] = current_user.id + # # => Set-Cookie: discount=BAhU--848956038e692d7046deab32b7131856ab20e14e; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT + def permanent + @permanent ||= PermanentCookieJar.new(self) + end + + # Returns a jar that'll automatically generate a signed representation of cookie value and verify it when reading from + # the cookie again. This is useful for creating cookies with values that the user is not supposed to change. If a signed + # cookie was tampered with by the user (or a 3rd party), an ActiveSupport::MessageVerifier::InvalidSignature exception will + # be raised. + # + # This jar requires that you set a suitable secret for the verification on ActionController::Base.cookie_verifier_secret. + # + # Example: + # + # cookies.signed[:discount] = 45 + # # => Set-Cookie: discount=BAhpMg==--2c1c6906c90a3bc4fd54a51ffb41dffa4bf6b5f7; path=/ + # + # cookies.signed[:discount] # => 45 + def signed + @signed ||= SignedCookieJar.new(self) + end + end + + class PermanentCookieJar < CookieJar #:nodoc: + def initialize(parent_jar) + @parent_jar = parent_jar + end + + def []=(key, options) + if options.is_a?(Hash) options.symbolize_keys! - options[:path] ||= "/" - value = super(key.to_s) - response.delete_cookie(key, options) - value + else + options = { :value => options } end - # Returns a jar that'll automatically set the assigned cookies to have an expiration date 20 years from now. Example: - # - # cookies.permanent[:prefers_open_id] = true - # # => Set-Cookie: prefers_open_id=true; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT - # - # This jar is only meant for writing. You'll read permanent cookies through the regular accessor. - # - # This jar allows chaining with the signed jar as well, so you can set permanent, signed cookies. Examples: - # - # cookies.permanent.signed[:remember_me] = current_user.id - # # => Set-Cookie: discount=BAhU--848956038e692d7046deab32b7131856ab20e14e; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT - def permanent - @permanent ||= PermanentCookieJar.new(self) - end - - # Returns a jar that'll automatically generate a signed representation of cookie value and verify it when reading from - # the cookie again. This is useful for creating cookies with values that the user is not supposed to change. If a signed - # cookie was tampered with by the user (or a 3rd party), an ActiveSupport::MessageVerifier::InvalidSignature exception will - # be raised. - # - # This jar requires that you set a suitable secret for the verification on ActionController::Base.cookie_verifier_secret. - # - # Example: - # - # cookies.signed[:discount] = 45 - # # => Set-Cookie: discount=BAhpMg==--2c1c6906c90a3bc4fd54a51ffb41dffa4bf6b5f7; path=/ - # - # cookies.signed[:discount] # => 45 - def signed - @signed ||= SignedCookieJar.new(self) - end + options[:expires] = 20.years.from_now + @parent_jar[key] = options end - - class PermanentCookieJar < CookieJar #:nodoc: - def initialize(parent_jar) - @parent_jar = parent_jar - end - - def []=(key, options) - if options.is_a?(Hash) - options.symbolize_keys! - else - options = { :value => options } - end - - options[:expires] = 20.years.from_now - @parent_jar[key] = options - end - - def signed - @signed ||= SignedCookieJar.new(self) - end - - def controller - @parent_jar.controller - end - - def method_missing(method, *arguments, &block) - @parent_jar.send(method, *arguments, &block) - end + + def signed + @signed ||= SignedCookieJar.new(self) end - - class SignedCookieJar < CookieJar #:nodoc: - def initialize(parent_jar) - unless ActionController::Base.cookie_verifier_secret - raise "You must set ActionController::Base.cookie_verifier_secret to use signed cookies" - end - - @parent_jar = parent_jar - @verifier = ActiveSupport::MessageVerifier.new(ActionController::Base.cookie_verifier_secret) - end - - def [](name) - @verifier.verify(@parent_jar[name]) - end - - def []=(key, options) - if options.is_a?(Hash) - options.symbolize_keys! - options[:value] = @verifier.generate(options[:value]) - else - options = { :value => @verifier.generate(options) } - end - - @parent_jar[key] = options + + def controller + @parent_jar.controller + end + + def method_missing(method, *arguments, &block) + @parent_jar.send(method, *arguments, &block) + end + end + + class SignedCookieJar < CookieJar #:nodoc: + def initialize(parent_jar) + unless ActionController::Base.cookie_verifier_secret + raise "You must set ActionController::Base.cookie_verifier_secret to use signed cookies" end - - def method_missing(method, *arguments, &block) - @parent_jar.send(method, *arguments, &block) + + @parent_jar = parent_jar + @verifier = ActiveSupport::MessageVerifier.new(ActionController::Base.cookie_verifier_secret) + end + + def [](name) + @verifier.verify(@parent_jar[name]) + end + + def []=(key, options) + if options.is_a?(Hash) + options.symbolize_keys! + options[:value] = @verifier.generate(options[:value]) + else + options = { :value => @verifier.generate(options) } end + + @parent_jar[key] = options + end + + def method_missing(method, *arguments, &block) + @parent_jar.send(method, *arguments, &block) + end end end diff --git a/actionpack/lib/action_controller/metal/flash.rb b/actionpack/lib/action_controller/metal/flash.rb index 581ff6109e..682f90e23b 100644 --- a/actionpack/lib/action_controller/metal/flash.rb +++ b/actionpack/lib/action_controller/metal/flash.rb @@ -123,80 +123,79 @@ module ActionController #:nodoc: session["flash"] = self end - private - # Used internally by the keep and discard methods - # use() # marks the entire flash as used - # use('msg') # marks the "msg" entry as used - # use(nil, false) # marks the entire flash as unused (keeps it around for one more action) - # use('msg', false) # marks the "msg" entry as unused (keeps it around for one more action) - # Returns the single value for the key you asked to be marked (un)used or the FlashHash itself - # if no key is passed. - def use(key = nil, used = true) - 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 flash["notice"] to - # read a notice you put there or flash["notice"] = "hello" - # to put a new one. - def flash #:doc: - unless @_flash - @_flash = session["flash"] || FlashHash.new - @_flash.sweep + private + # Used internally by the keep and discard methods + # use() # marks the entire flash as used + # use('msg') # marks the "msg" entry as used + # use(nil, false) # marks the entire flash as unused (keeps it around for one more action) + # use('msg', false) # marks the "msg" entry as unused (keeps it around for one more action) + # Returns the single value for the key you asked to be marked (un)used or the FlashHash itself + # if no key is passed. + def use(key = nil, used = true) + Array(key || keys).each { |k| used ? @used << k : @used.delete(k) } + return key ? self[key] : self + end end - @_flash - end - - # Convenience accessor for flash[:alert] - def alert - flash[:alert] - end - - # Convenience accessor for flash[:alert]= - def alert=(message) - flash[:alert] = message - end + # Access the contents of the flash. Use flash["notice"] to + # read a notice you put there or flash["notice"] = "hello" + # to put a new one. + def flash #:doc: + unless @_flash + @_flash = session["flash"] || FlashHash.new + @_flash.sweep + end - # Convenience accessor for flash[:notice] - def notice - flash[:notice] - end + @_flash + end - # Convenience accessor for flash[:notice]= - def notice=(message) - flash[:notice] = message - end + # Convenience accessor for flash[:alert] + def alert + flash[:alert] + end + # Convenience accessor for flash[:alert]= + def alert=(message) + flash[:alert] = message + end - protected - def process_action(method_name) - @_flash = nil - super - @_flash.store(session) if @_flash - @_flash = nil + # Convenience accessor for flash[:notice] + def notice + flash[:notice] end - def reset_session - super - @_flash = nil + # Convenience accessor for flash[:notice]= + def notice=(message) + flash[:notice] = message end - def redirect_to(options = {}, response_status_and_flash = {}) #:doc: - if alert = response_status_and_flash.delete(:alert) - flash[:alert] = alert + protected + def process_action(method_name) + @_flash = nil + super + @_flash.store(session) if @_flash + @_flash = nil end - if notice = response_status_and_flash.delete(:notice) - flash[:notice] = notice + def reset_session + super + @_flash = nil end - if other_flashes = response_status_and_flash.delete(:flash) - flash.update(other_flashes) - end + def redirect_to(options = {}, response_status_and_flash = {}) #:doc: + if alert = response_status_and_flash.delete(:alert) + flash[:alert] = alert + end - super(options, response_status_and_flash) - end + if notice = response_status_and_flash.delete(:notice) + flash[:notice] = notice + end + + if other_flashes = response_status_and_flash.delete(:flash) + flash.update(other_flashes) + end + + super(options, response_status_and_flash) + end end end diff --git a/actionpack/lib/action_dispatch/http/headers.rb b/actionpack/lib/action_dispatch/http/headers.rb index 2a41b4dbad..1e43104f0a 100644 --- a/actionpack/lib/action_dispatch/http/headers.rb +++ b/actionpack/lib/action_dispatch/http/headers.rb @@ -6,13 +6,13 @@ module ActionDispatch extend ActiveSupport::Memoizable def initialize(*args) - if args.size == 1 && args[0].is_a?(Hash) - super() - update(args[0]) - else - super - end - end + if args.size == 1 && args[0].is_a?(Hash) + super() + update(args[0]) + else + super + end + end def [](header_name) if include?(header_name) diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index c30897b32a..e681b6340d 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -104,7 +104,7 @@ module Mime SET << Mime.const_get(symbol.to_s.upcase) - ([string] + mime_type_synonyms).each { |string| LOOKUP[string] = SET.last } unless skip_lookup + ([string] + mime_type_synonyms).each { |str| LOOKUP[str] = SET.last } unless skip_lookup ([symbol.to_s] + extension_synonyms).each { |ext| EXTENSION_LOOKUP[ext] = SET.last } end diff --git a/actionpack/lib/action_view/template/handler.rb b/actionpack/lib/action_view/template/handler.rb index 5a46a27893..221d1bd5c5 100644 --- a/actionpack/lib/action_view/template/handler.rb +++ b/actionpack/lib/action_view/template/handler.rb @@ -17,8 +17,8 @@ module ActionView end def compile(template) - raise "Need to implement #{self.class.name}#compile(template)" - end + raise "Need to implement #{self.class.name}#compile(template)" + end end end diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index a2f4ab2ef5..c6a17907ff 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -108,13 +108,9 @@ module ActionView query << '{' << ext.map {|e| e && ".#{e}" }.join(',') << '}' end - Dir[query].map do |path| - next if File.directory?(path) - source = File.read(path) - identifier = Pathname.new(path).expand_path.to_s - - Template.new(source, identifier, *path_to_details(path)) - end.compact + Dir[query].reject { |p| File.directory?(p) }.map do |p| + Template.new(File.read(p), File.expand_path(p), *path_to_details(p)) + end end # # TODO: fix me @@ -162,4 +158,4 @@ module ActionView @paths.first.to_s end end -end \ No newline at end of file +end -- cgit v1.2.3 From d747b6847ba6e3770986e445f7365efae6077df3 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Mon, 28 Dec 2009 17:30:43 -0800 Subject: Require active_support/dependencies/autoload in action_dispatch --- actionpack/lib/action_dispatch.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 0696cb017c..7f61ff5657 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -24,6 +24,7 @@ activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__) $:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path) require 'active_support/ruby/shim' +require 'active_support/dependencies/autoload' require 'rack' -- cgit v1.2.3 From f79caa49fb78bca986a4321830c4cd155c17e13a Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 28 Dec 2009 20:18:14 -0800 Subject: Complain if there's no such middleware --- actionpack/lib/action_dispatch/middleware/stack.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb index 3b27309f58..24be4fee55 100644 --- a/actionpack/lib/action_dispatch/middleware/stack.rb +++ b/actionpack/lib/action_dispatch/middleware/stack.rb @@ -93,8 +93,9 @@ module ActionDispatch alias_method :insert_before, :insert def insert_after(index, *args, &block) - index = self.index(index) unless index.is_a?(Integer) - insert(index + 1, *args, &block) + i = index.is_a?(Integer) ? index : self.index(index) + raise "No such middleware to insert after: #{index.inspect}" unless i + insert(i + 1, *args, &block) end def swap(target, *args, &block) -- cgit v1.2.3 From cf4978313bbf908f85ff23c7a484bc856bed5181 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Tue, 29 Dec 2009 01:04:00 -0800 Subject: Make sure evalled method knows where it came from --- actionpack/lib/action_dispatch/http/mime_type.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index e681b6340d..13c0f2bad0 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -10,8 +10,8 @@ module Mime %w(<< concat shift unshift push pop []= clear compact! collect! delete delete_at delete_if flatten! map! insert reject! reverse! replace slice! sort! uniq!).each do |method| - module_eval <<-CODE - def #{method}(*args) + module_eval <<-CODE, __FILE__, __LINE__ + 1 + def #{method}(*) @symbols = nil super end -- cgit v1.2.3 From 2e87196d14f0cb7b75a6b81cbd8a0810ed684de9 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Tue, 29 Dec 2009 13:21:36 -0800 Subject: Use extlib_inheritable_accessor in request_forgery_protection.rb. For some reason the current class_inheritable_accessor does not play nice with included hooks. class_inheritable_accessor will be revised shortly. --- actionpack/lib/action_controller/metal/request_forgery_protection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index 2826b1e34c..f1fb4d7ce5 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -13,7 +13,7 @@ module ActionController #:nodoc: cattr_accessor :request_forgery_protection_token # Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode. - class_inheritable_accessor :allow_forgery_protection + extlib_inheritable_accessor :allow_forgery_protection self.allow_forgery_protection = true helper_method :form_authenticity_token -- cgit v1.2.3 From bb153f42e45160c5ef3593c393db5d3c6857fb70 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Wed, 30 Dec 2009 12:58:40 -0800 Subject: ActionDispatch should require as little of ActiveSupport as possible --- actionpack/lib/action_dispatch.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 7f61ff5657..49e1634af5 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -21,9 +21,7 @@ # 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/ruby/shim' +require 'active_support' require 'active_support/dependencies/autoload' require 'rack' -- cgit v1.2.3 From 8ad9d14494dbe2a02d95ff6d23373b5662eede52 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 30 Dec 2009 17:34:53 -0800 Subject: Partially revert "ActionDispatch should require as little of ActiveSupport as possible" Removes load path change from commit bb153f42e45160c5ef3593c393db5d3c6857fb70. --- actionpack/lib/action_dispatch.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 49e1634af5..1e87a016f9 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -21,6 +21,8 @@ # 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 'active_support/dependencies/autoload' -- cgit v1.2.3 From 1fbd02e44618f1f56e1d9d0af85c6a4108a66532 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 30 Dec 2009 19:33:32 -0800 Subject: Revert "Add config.action_controller.include behavior to plugins." This reverts commit 7e8b7f46bfc086a36db996420fbee93348c5268e. Conflicts: railties/lib/rails/plugin.rb --- actionpack/lib/action_controller/rails.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/rails.rb b/actionpack/lib/action_controller/rails.rb index 6ebb50887b..df708c315b 100644 --- a/actionpack/lib/action_controller/rails.rb +++ b/actionpack/lib/action_controller/rails.rb @@ -1,7 +1,6 @@ module ActionController class Plugin < Rails::Plugin plugin_name :action_controller - include_modules_in "ActionController::Base" initializer "action_controller.set_configs" do |app| app.config.action_controller.each do |k,v| @@ -91,4 +90,4 @@ module ActionController end end -end \ No newline at end of file +end -- cgit v1.2.3 From a23f4b6aeed6b49f90f5c544c818798840f090b7 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Thu, 31 Dec 2009 11:46:56 -0800 Subject: Add a /rails.rb for each framework for consistency --- actionpack/lib/action_controller/rails.rb | 2 ++ actionpack/lib/action_view/rails.rb | 1 + 2 files changed, 3 insertions(+) create mode 100644 actionpack/lib/action_view/rails.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/rails.rb b/actionpack/lib/action_controller/rails.rb index df708c315b..d4faca2681 100644 --- a/actionpack/lib/action_controller/rails.rb +++ b/actionpack/lib/action_controller/rails.rb @@ -1,3 +1,5 @@ +require "action_controller" + module ActionController class Plugin < Rails::Plugin plugin_name :action_controller diff --git a/actionpack/lib/action_view/rails.rb b/actionpack/lib/action_view/rails.rb new file mode 100644 index 0000000000..cae39382b8 --- /dev/null +++ b/actionpack/lib/action_view/rails.rb @@ -0,0 +1 @@ +require "action_view" \ No newline at end of file -- cgit v1.2.3 From e749424dfa38a0300a621b772eae96f9cc5d2555 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Thu, 31 Dec 2009 12:28:48 -0800 Subject: Rename rails.rb -> rails/all.rb and rails/core.rb -> rails.rb --- actionpack/lib/action_controller/rails.rb | 1 + actionpack/lib/action_view/rails.rb | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/rails.rb b/actionpack/lib/action_controller/rails.rb index d4faca2681..4d3ca43f99 100644 --- a/actionpack/lib/action_controller/rails.rb +++ b/actionpack/lib/action_controller/rails.rb @@ -1,4 +1,5 @@ require "action_controller" +require "rails" module ActionController class Plugin < Rails::Plugin diff --git a/actionpack/lib/action_view/rails.rb b/actionpack/lib/action_view/rails.rb index cae39382b8..a90e0636b9 100644 --- a/actionpack/lib/action_view/rails.rb +++ b/actionpack/lib/action_view/rails.rb @@ -1 +1,2 @@ -require "action_view" \ No newline at end of file +require "action_view" +require "rails" \ No newline at end of file -- cgit v1.2.3 From ae7ada1fde1648a5c81b9e6adf74d515e0bbe0a5 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Thu, 31 Dec 2009 13:11:54 -0800 Subject: Some railties cleanup: * Rename /rails.rb -> /railtie.rb * Rails::Plugin -> Rails::Railtie * Rails::Plugin::Vendored -> Rails::Plugin --- actionpack/lib/action_controller/rails.rb | 96 ----------------------------- actionpack/lib/action_controller/railtie.rb | 96 +++++++++++++++++++++++++++++ actionpack/lib/action_view/rails.rb | 2 - actionpack/lib/action_view/railtie.rb | 2 + 4 files changed, 98 insertions(+), 98 deletions(-) delete mode 100644 actionpack/lib/action_controller/rails.rb create mode 100644 actionpack/lib/action_controller/railtie.rb delete mode 100644 actionpack/lib/action_view/rails.rb create mode 100644 actionpack/lib/action_view/railtie.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/rails.rb b/actionpack/lib/action_controller/rails.rb deleted file mode 100644 index 4d3ca43f99..0000000000 --- a/actionpack/lib/action_controller/rails.rb +++ /dev/null @@ -1,96 +0,0 @@ -require "action_controller" -require "rails" - -module ActionController - class Plugin < Rails::Plugin - plugin_name :action_controller - - initializer "action_controller.set_configs" do |app| - app.config.action_controller.each do |k,v| - ActionController::Base.send "#{k}=", v - end - end - - # TODO: ActionController::Base.logger should delegate to its own config.logger - initializer "action_controller.logger" do - ActionController::Base.logger ||= Rails.logger - end - - # Routing must be initialized after plugins to allow the former to extend the routes - initializer "action_controller.initialize_routing" do |app| - app.route_configuration_files << app.config.routes_configuration_file - app.route_configuration_files << app.config.builtin_routes_configuration_file - app.reload_routes! - end - - # Include middleware to serve up static assets - initializer "action_controller.initialize_static_server" do |app| - if app.config.serve_static_assets - app.config.middleware.use(ActionDispatch::Static, Rails.public_path) - end - end - - initializer "action_controller.initialize_middleware_stack" do |app| - middleware = app.config.middleware - middleware.use(::Rack::Lock, :if => lambda { ActionController::Base.allow_concurrency }) - middleware.use(::Rack::Runtime) - middleware.use(ActionDispatch::ShowExceptions, lambda { ActionController::Base.consider_all_requests_local }) - middleware.use(ActionDispatch::Callbacks, lambda { ActionController::Dispatcher.prepare_each_request }) - middleware.use(lambda { ActionController::Base.session_store }, lambda { ActionController::Base.session_options }) - middleware.use(ActionDispatch::ParamsParser) - middleware.use(::Rack::MethodOverride) - middleware.use(::Rack::Head) - middleware.use(ActionDispatch::StringCoercion) - end - - initializer "action_controller.initialize_framework_caches" do - ActionController::Base.cache_store ||= RAILS_CACHE - end - - # Sets +ActionController::Base#view_paths+ and +ActionMailer::Base#template_root+ - # (but only for those frameworks that are to be loaded). If the framework's - # paths have already been set, it is not changed, otherwise it is - # set to use Configuration#view_path. - initializer "action_controller.initialize_framework_views" do |app| - # TODO: this should be combined with the logic for default config.action_controller.view_paths - view_path = ActionView::PathSet.type_cast(app.config.view_path, app.config.cache_classes) - ActionController::Base.view_paths = view_path if ActionController::Base.view_paths.blank? - end - - initializer "action_controller.initialize_metal" do |app| - Rails::Rack::Metal.requested_metals = app.config.metals - - app.config.middleware.insert_before(:"ActionDispatch::ParamsParser", - Rails::Rack::Metal, :if => Rails::Rack::Metal.metals.any?) - end - - # # Prepare dispatcher callbacks and run 'prepare' callbacks - initializer "action_controller.prepare_dispatcher" do |app| - # TODO: This used to say unless defined?(Dispatcher). Find out why and fix. - require 'rails/dispatcher' - - Dispatcher.define_dispatcher_callbacks(app.config.cache_classes) - - unless app.config.cache_classes - # Setup dev mode route reloading - routes_last_modified = app.routes_changed_at - reload_routes = lambda do - unless app.routes_changed_at == routes_last_modified - routes_last_modified = app.routes_changed_at - app.reload_routes! - end - end - ActionDispatch::Callbacks.before_dispatch { |callbacks| reload_routes.call } - end - end - - initializer "action_controller.notifications" do |app| - require 'active_support/notifications' - - ActiveSupport::Notifications.subscribe do |*args| - ActionController::Base.log_event(*args) if ActionController::Base.logger - end - end - - end -end diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb new file mode 100644 index 0000000000..f861d12905 --- /dev/null +++ b/actionpack/lib/action_controller/railtie.rb @@ -0,0 +1,96 @@ +require "action_controller" +require "rails" + +module ActionController + class Railtie < Rails::Railtie + plugin_name :action_controller + + initializer "action_controller.set_configs" do |app| + app.config.action_controller.each do |k,v| + ActionController::Base.send "#{k}=", v + end + end + + # TODO: ActionController::Base.logger should delegate to its own config.logger + initializer "action_controller.logger" do + ActionController::Base.logger ||= Rails.logger + end + + # Routing must be initialized after plugins to allow the former to extend the routes + initializer "action_controller.initialize_routing" do |app| + app.route_configuration_files << app.config.routes_configuration_file + app.route_configuration_files << app.config.builtin_routes_configuration_file + app.reload_routes! + end + + # Include middleware to serve up static assets + initializer "action_controller.initialize_static_server" do |app| + if app.config.serve_static_assets + app.config.middleware.use(ActionDispatch::Static, Rails.public_path) + end + end + + initializer "action_controller.initialize_middleware_stack" do |app| + middleware = app.config.middleware + middleware.use(::Rack::Lock, :if => lambda { ActionController::Base.allow_concurrency }) + middleware.use(::Rack::Runtime) + middleware.use(ActionDispatch::ShowExceptions, lambda { ActionController::Base.consider_all_requests_local }) + middleware.use(ActionDispatch::Callbacks, lambda { ActionController::Dispatcher.prepare_each_request }) + middleware.use(lambda { ActionController::Base.session_store }, lambda { ActionController::Base.session_options }) + middleware.use(ActionDispatch::ParamsParser) + middleware.use(::Rack::MethodOverride) + middleware.use(::Rack::Head) + middleware.use(ActionDispatch::StringCoercion) + end + + initializer "action_controller.initialize_framework_caches" do + ActionController::Base.cache_store ||= RAILS_CACHE + end + + # Sets +ActionController::Base#view_paths+ and +ActionMailer::Base#template_root+ + # (but only for those frameworks that are to be loaded). If the framework's + # paths have already been set, it is not changed, otherwise it is + # set to use Configuration#view_path. + initializer "action_controller.initialize_framework_views" do |app| + # TODO: this should be combined with the logic for default config.action_controller.view_paths + view_path = ActionView::PathSet.type_cast(app.config.view_path, app.config.cache_classes) + ActionController::Base.view_paths = view_path if ActionController::Base.view_paths.blank? + end + + initializer "action_controller.initialize_metal" do |app| + Rails::Rack::Metal.requested_metals = app.config.metals + + app.config.middleware.insert_before(:"ActionDispatch::ParamsParser", + Rails::Rack::Metal, :if => Rails::Rack::Metal.metals.any?) + end + + # # Prepare dispatcher callbacks and run 'prepare' callbacks + initializer "action_controller.prepare_dispatcher" do |app| + # TODO: This used to say unless defined?(Dispatcher). Find out why and fix. + require 'rails/dispatcher' + + Dispatcher.define_dispatcher_callbacks(app.config.cache_classes) + + unless app.config.cache_classes + # Setup dev mode route reloading + routes_last_modified = app.routes_changed_at + reload_routes = lambda do + unless app.routes_changed_at == routes_last_modified + routes_last_modified = app.routes_changed_at + app.reload_routes! + end + end + ActionDispatch::Callbacks.before_dispatch { |callbacks| reload_routes.call } + end + end + + initializer "action_controller.notifications" do |app| + require 'active_support/notifications' + + ActiveSupport::Notifications.subscribe do |*args| + ActionController::Base.log_event(*args) if ActionController::Base.logger + end + end + + end +end diff --git a/actionpack/lib/action_view/rails.rb b/actionpack/lib/action_view/rails.rb deleted file mode 100644 index a90e0636b9..0000000000 --- a/actionpack/lib/action_view/rails.rb +++ /dev/null @@ -1,2 +0,0 @@ -require "action_view" -require "rails" \ No newline at end of file diff --git a/actionpack/lib/action_view/railtie.rb b/actionpack/lib/action_view/railtie.rb new file mode 100644 index 0000000000..a90e0636b9 --- /dev/null +++ b/actionpack/lib/action_view/railtie.rb @@ -0,0 +1,2 @@ +require "action_view" +require "rails" \ No newline at end of file -- cgit v1.2.3 From 38fa0d14a8c96fc6e02531408be5ce8c36f4fb7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 31 Dec 2009 01:33:54 +0100 Subject: controller_path is required by ActionView, so move it up to AbstractController and refactor AbstractController::Layouts. --- actionpack/lib/abstract_controller/base.rb | 15 ++ actionpack/lib/abstract_controller/layouts.rb | 158 +++++++++++++++++++- actionpack/lib/action_controller.rb | 2 - actionpack/lib/action_controller/base.rb | 2 +- actionpack/lib/action_controller/metal.rb | 15 -- actionpack/lib/action_controller/metal/layouts.rb | 171 ---------------------- 6 files changed, 173 insertions(+), 190 deletions(-) delete mode 100644 actionpack/lib/action_controller/metal/layouts.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index efea81aa71..a6889d5d01 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -72,6 +72,16 @@ module AbstractController # And always exclude explicitly hidden actions hidden_actions end + + # Returns the full controller name, underscored, without the ending Controller. + # For instance, MyApp::MyPostsController would return "my_app/my_posts" for + # controller_name. + # + # ==== Returns + # String + def controller_path + @controller_path ||= name && name.sub(/Controller$/, '').underscore + end end abstract! @@ -96,6 +106,11 @@ module AbstractController process_action(action_name, *args) end + # Delegates to the class' #controller_path + def controller_path + self.class.controller_path + end + private # Returns true if the name can be considered an action. This can # be overridden in subclasses to modify the semantics of what diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb index 4073e9b386..6fbf6bc392 100644 --- a/actionpack/lib/abstract_controller/layouts.rb +++ b/actionpack/lib/abstract_controller/layouts.rb @@ -1,4 +1,160 @@ module AbstractController + # Layouts reverse the common pattern of including shared headers and footers in many templates to isolate changes in + # repeated setups. The inclusion pattern has pages that look like this: + # + # <%= render "shared/header" %> + # Hello World + # <%= render "shared/footer" %> + # + # This approach is a decent way of keeping common structures isolated from the changing content, but it's verbose + # and if you ever want to change the structure of these two includes, you'll have to change all the templates. + # + # With layouts, you can flip it around and have the common structure know where to insert changing content. This means + # that the header and footer are only mentioned in one place, like this: + # + # // The header part of this layout + # <%= yield %> + # // The footer part of this layout + # + # And then you have content pages that look like this: + # + # hello world + # + # At rendering time, the content page is computed and then inserted in the layout, like this: + # + # // The header part of this layout + # hello world + # // The footer part of this layout + # + # == Accessing shared variables + # + # Layouts have access to variables specified in the content pages and vice versa. This allows you to have layouts with + # references that won't materialize before rendering time: + # + #

<%= @page_title %>

+ # <%= yield %> + # + # ...and content pages that fulfill these references _at_ rendering time: + # + # <% @page_title = "Welcome" %> + # Off-world colonies offers you a chance to start a new life + # + # The result after rendering is: + # + #

Welcome

+ # Off-world colonies offers you a chance to start a new life + # + # == Layout assignment + # + # You can either specify a layout declaratively (using the #layout class method) or give + # it the same name as your controller, and place it in app/views/layouts. + # If a subclass does not have a layout specified, it inherits its layout using normal Ruby inheritance. + # + # For instance, if you have PostsController and a template named app/views/layouts/posts.html.erb, + # that template will be used for all actions in PostsController and controllers inheriting + # from PostsController. + # + # If you use a module, for instance Weblog::PostsController, you will need a template named + # app/views/layouts/weblog/posts.html.erb. + # + # Since all your controllers inherit from ApplicationController, they will use + # app/views/layouts/application.html.erb if no other layout is specified + # or provided. + # + # == Inheritance Examples + # + # class BankController < ActionController::Base + # layout "bank_standard" + # + # class InformationController < BankController + # + # class TellerController < BankController + # # teller.html.erb exists + # + # class TillController < TellerController + # + # class VaultController < BankController + # layout :access_level_layout + # + # class EmployeeController < BankController + # layout nil + # + # The InformationController uses "bank_standard" inherited from the BankController, the VaultController overwrites + # and picks the layout dynamically, and the EmployeeController doesn't want to use a layout at all. + # + # The TellerController uses +teller.html.erb+, and TillController inherits that layout and + # uses it as well. + # + # == Types of layouts + # + # Layouts are basically just regular templates, but the name of this template needs not be specified statically. Sometimes + # you want to alternate layouts depending on runtime information, such as whether someone is logged in or not. This can + # be done either by specifying a method reference as a symbol or using an inline method (as a proc). + # + # The method reference is the preferred approach to variable layouts and is used like this: + # + # class WeblogController < ActionController::Base + # layout :writers_and_readers + # + # def index + # # fetching posts + # end + # + # private + # def writers_and_readers + # logged_in? ? "writer_layout" : "reader_layout" + # end + # + # Now when a new request for the index action is processed, the layout will vary depending on whether the person accessing + # is logged in or not. + # + # If you want to use an inline method, such as a proc, do something like this: + # + # class WeblogController < ActionController::Base + # layout proc{ |controller| controller.logged_in? ? "writer_layout" : "reader_layout" } + # + # Of course, the most common way of specifying a layout is still just as a plain template name: + # + # class WeblogController < ActionController::Base + # layout "weblog_standard" + # + # If no directory is specified for the template name, the template will by default be looked for in app/views/layouts/. + # Otherwise, it will be looked up relative to the template root. + # + # == Conditional layouts + # + # If you have a layout that by default is applied to all the actions of a controller, you still have the option of rendering + # a given action or set of actions without a layout, or restricting a layout to only a single action or a set of actions. The + # :only and :except options can be passed to the layout call. For example: + # + # class WeblogController < ActionController::Base + # layout "weblog_standard", :except => :rss + # + # # ... + # + # end + # + # This will assign "weblog_standard" as the WeblogController's layout except for the +rss+ action, which will not wrap a layout + # around the rendered view. + # + # Both the :only and :except condition can accept an arbitrary number of method references, so + # #:except => [ :rss, :text_only ] is valid, as is :except => :rss. + # + # == Using a different layout in the action render call + # + # If most of your actions use the same layout, it makes perfect sense to define a controller-wide layout as described above. + # Sometimes you'll have exceptions where one action wants to use a different layout than the rest of the controller. + # You can do this by passing a :layout option to the render call. For example: + # + # class WeblogController < ActionController::Base + # layout "weblog_standard" + # + # def help + # render :action => "help", :layout => "help" + # end + # end + # + # This will render the help action with the "help" layout instead of the controller-wide "weblog_standard" layout. module Layouts extend ActiveSupport::Concern @@ -89,7 +245,7 @@ module AbstractController # ==== Returns # String:: A template name def _implied_layout_name - name && name.underscore + controller_path end # Takes the specified layout and creates a _layout method to be called diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 26a85d4de8..d3dc90f377 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -13,13 +13,11 @@ module ActionController autoload :Middleware autoload_under "metal" do - autoload :Benchmarking autoload :ConditionalGet autoload :Configuration autoload :Head autoload :Helpers autoload :HideActions - autoload :Layouts autoload :Logger autoload :MimeResponds autoload :RackDelegation diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 67656110c4..7a2e27ce86 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -4,6 +4,7 @@ module ActionController include AbstractController::Callbacks include AbstractController::Logger + include AbstractController::Layouts include ActionController::Helpers include ActionController::HideActions @@ -11,7 +12,6 @@ module ActionController include ActionController::Redirecting include ActionController::Rendering include ActionController::Renderers::All - include ActionController::Layouts include ActionController::ConditionalGet include ActionController::RackDelegation include ActionController::Logger diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index f445ca70ee..1819c0f886 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -28,21 +28,6 @@ module ActionController self.class.controller_name end - # Returns the full controller name, underscored, without the ending Controller. - # For instance, MyApp::MyPostsController would return "my_app/my_posts" for - # controller_name. - # - # ==== Returns - # String - def self.controller_path - @controller_path ||= name && name.sub(/Controller$/, '').underscore - end - - # Delegates to the class' #controller_path - def controller_path - self.class.controller_path - end - # The details below can be overridden to support a specific # Request and Response object. The default ActionController::Base # implementation includes RackDelegation, which makes a request diff --git a/actionpack/lib/action_controller/metal/layouts.rb b/actionpack/lib/action_controller/metal/layouts.rb deleted file mode 100644 index f44498a884..0000000000 --- a/actionpack/lib/action_controller/metal/layouts.rb +++ /dev/null @@ -1,171 +0,0 @@ -module ActionController - # Layouts reverse the common pattern of including shared headers and footers in many templates to isolate changes in - # repeated setups. The inclusion pattern has pages that look like this: - # - # <%= render "shared/header" %> - # Hello World - # <%= render "shared/footer" %> - # - # This approach is a decent way of keeping common structures isolated from the changing content, but it's verbose - # and if you ever want to change the structure of these two includes, you'll have to change all the templates. - # - # With layouts, you can flip it around and have the common structure know where to insert changing content. This means - # that the header and footer are only mentioned in one place, like this: - # - # // The header part of this layout - # <%= yield %> - # // The footer part of this layout - # - # And then you have content pages that look like this: - # - # hello world - # - # At rendering time, the content page is computed and then inserted in the layout, like this: - # - # // The header part of this layout - # hello world - # // The footer part of this layout - # - # == Accessing shared variables - # - # Layouts have access to variables specified in the content pages and vice versa. This allows you to have layouts with - # references that won't materialize before rendering time: - # - #

<%= @page_title %>

- # <%= yield %> - # - # ...and content pages that fulfill these references _at_ rendering time: - # - # <% @page_title = "Welcome" %> - # Off-world colonies offers you a chance to start a new life - # - # The result after rendering is: - # - #

Welcome

- # Off-world colonies offers you a chance to start a new life - # - # == Layout assignment - # - # You can either specify a layout declaratively (using the #layout class method) or give - # it the same name as your controller, and place it in app/views/layouts. - # If a subclass does not have a layout specified, it inherits its layout using normal Ruby inheritance. - # - # For instance, if you have PostsController and a template named app/views/layouts/posts.html.erb, - # that template will be used for all actions in PostsController and controllers inheriting - # from PostsController. - # - # If you use a module, for instance Weblog::PostsController, you will need a template named - # app/views/layouts/weblog/posts.html.erb. - # - # Since all your controllers inherit from ApplicationController, they will use - # app/views/layouts/application.html.erb if no other layout is specified - # or provided. - # - # == Inheritance Examples - # - # class BankController < ActionController::Base - # layout "bank_standard" - # - # class InformationController < BankController - # - # class TellerController < BankController - # # teller.html.erb exists - # - # class TillController < TellerController - # - # class VaultController < BankController - # layout :access_level_layout - # - # class EmployeeController < BankController - # layout nil - # - # The InformationController uses "bank_standard" inherited from the BankController, the VaultController overwrites - # and picks the layout dynamically, and the EmployeeController doesn't want to use a layout at all. - # - # The TellerController uses +teller.html.erb+, and TillController inherits that layout and - # uses it as well. - # - # == Types of layouts - # - # Layouts are basically just regular templates, but the name of this template needs not be specified statically. Sometimes - # you want to alternate layouts depending on runtime information, such as whether someone is logged in or not. This can - # be done either by specifying a method reference as a symbol or using an inline method (as a proc). - # - # The method reference is the preferred approach to variable layouts and is used like this: - # - # class WeblogController < ActionController::Base - # layout :writers_and_readers - # - # def index - # # fetching posts - # end - # - # private - # def writers_and_readers - # logged_in? ? "writer_layout" : "reader_layout" - # end - # - # Now when a new request for the index action is processed, the layout will vary depending on whether the person accessing - # is logged in or not. - # - # If you want to use an inline method, such as a proc, do something like this: - # - # class WeblogController < ActionController::Base - # layout proc{ |controller| controller.logged_in? ? "writer_layout" : "reader_layout" } - # - # Of course, the most common way of specifying a layout is still just as a plain template name: - # - # class WeblogController < ActionController::Base - # layout "weblog_standard" - # - # If no directory is specified for the template name, the template will by default be looked for in app/views/layouts/. - # Otherwise, it will be looked up relative to the template root. - # - # == Conditional layouts - # - # If you have a layout that by default is applied to all the actions of a controller, you still have the option of rendering - # a given action or set of actions without a layout, or restricting a layout to only a single action or a set of actions. The - # :only and :except options can be passed to the layout call. For example: - # - # class WeblogController < ActionController::Base - # layout "weblog_standard", :except => :rss - # - # # ... - # - # end - # - # This will assign "weblog_standard" as the WeblogController's layout except for the +rss+ action, which will not wrap a layout - # around the rendered view. - # - # Both the :only and :except condition can accept an arbitrary number of method references, so - # #:except => [ :rss, :text_only ] is valid, as is :except => :rss. - # - # == Using a different layout in the action render call - # - # If most of your actions use the same layout, it makes perfect sense to define a controller-wide layout as described above. - # Sometimes you'll have exceptions where one action wants to use a different layout than the rest of the controller. - # You can do this by passing a :layout option to the render call. For example: - # - # class WeblogController < ActionController::Base - # layout "weblog_standard" - # - # def help - # render :action => "help", :layout => "help" - # end - # end - # - # This will render the help action with the "help" layout instead of the controller-wide "weblog_standard" layout. - module Layouts - extend ActiveSupport::Concern - - include ActionController::Rendering - include AbstractController::Layouts - - module ClassMethods - # If no layout is provided, look for a layout with this name. - def _implied_layout_name - controller_path - end - end - end -end -- cgit v1.2.3 From 33c98b15bc8bea1366a721eae5fbfecf6c53c65d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 31 Dec 2009 01:35:50 +0100 Subject: ActionController::Logger should include AbstractController::Logger and sort autoloads for easier readability. --- actionpack/lib/action_controller.rb | 14 +++++++------- actionpack/lib/action_controller/base.rb | 1 - actionpack/lib/action_controller/metal/logger.rb | 4 ++++ 3 files changed, 11 insertions(+), 8 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index d3dc90f377..d66fc3fcc9 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -13,29 +13,29 @@ module ActionController autoload :Middleware autoload_under "metal" do + autoload :Compatibility autoload :ConditionalGet autoload :Configuration + autoload :Cookies + autoload :FilterParameterLogging + autoload :Flash autoload :Head autoload :Helpers autoload :HideActions + autoload :HttpAuthentication autoload :Logger autoload :MimeResponds autoload :RackDelegation - autoload :Compatibility autoload :Redirecting autoload :Rendering autoload :Renderers + autoload :RequestForgeryProtection autoload :Rescue autoload :Responder autoload :SessionManagement + autoload :Streaming autoload :UrlFor autoload :Verification - autoload :Flash - autoload :RequestForgeryProtection - autoload :Streaming - autoload :HttpAuthentication - autoload :FilterParameterLogging - autoload :Cookies end autoload :Dispatcher, 'action_controller/dispatch/dispatcher' diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 7a2e27ce86..b23be66910 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -3,7 +3,6 @@ module ActionController abstract! include AbstractController::Callbacks - include AbstractController::Logger include AbstractController::Layouts include ActionController::Helpers diff --git a/actionpack/lib/action_controller/metal/logger.rb b/actionpack/lib/action_controller/metal/logger.rb index e71f77fbb2..4f4370e5f0 100644 --- a/actionpack/lib/action_controller/metal/logger.rb +++ b/actionpack/lib/action_controller/metal/logger.rb @@ -8,6 +8,10 @@ module ActionController module Logger extend ActiveSupport::Concern + included do + include AbstractController::Logger + end + attr_internal :view_runtime def process_action(action) -- cgit v1.2.3 From c03c40b481f433214ff68d1cae93df9e26190b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 31 Dec 2009 01:45:56 +0100 Subject: Expose a _render_partial hook as thhe _render_template one and make use of it. --- actionpack/lib/abstract_controller/rendering.rb | 14 +++++++++----- actionpack/lib/action_controller/metal/rendering.rb | 12 ++++++------ 2 files changed, 15 insertions(+), 11 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index 64a8a5f241..332d86b089 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -1,5 +1,4 @@ require "abstract_controller/base" -require "abstract_controller/logger" module AbstractController class DoubleRenderError < Error @@ -13,8 +12,6 @@ module AbstractController module Rendering extend ActiveSupport::Concern - include AbstractController::Logger - included do extlib_inheritable_accessor :_view_paths self._view_paths ||= ActionView::PathSet.new @@ -67,7 +64,7 @@ module AbstractController def render_to_body(options = {}) # TODO: Refactor so we can just use the normal template logic for this if options.key?(:partial) - view_context.render_partial(options) + _render_partial(options) else _determine_template(options) _render_template(options) @@ -87,11 +84,18 @@ module AbstractController # ==== Options # _template:: The template to render # _layout:: The layout to wrap the template in (optional) - # _partial:: Whether or not the template to be rendered is a partial def _render_template(options) view_context.render_template(options) end + # Renders the given partial. + # + # ==== Options + # partial:: The partial name or the object to be rendered + def _render_partial(options) + view_context.render_partial(options) + end + # The list of view paths for this controller. See ActionView::ViewPathSet for # more details about writing custom view paths. def view_paths diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb index 20eb524e50..74e50bb032 100644 --- a/actionpack/lib/action_controller/metal/rendering.rb +++ b/actionpack/lib/action_controller/metal/rendering.rb @@ -20,12 +20,6 @@ module ActionController def render_to_body(options) _process_options(options) - - if options.key?(:partial) - options[:partial] = action_name if options[:partial] == true - options[:_details] = {:formats => formats} - end - super end @@ -43,6 +37,12 @@ module ActionController super end + def _render_partial(options) + options[:partial] = action_name if options[:partial] == true + options[:_details] = {:formats => formats} + super + end + def format_for_text formats.first end -- cgit v1.2.3 From 50aa876f3276aabfac16aea90ba5f6b45b4cbffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 31 Dec 2009 02:09:06 +0100 Subject: Make rendering in ActionView happen through _render_template, as the rendering which comes from ActionController. --- actionpack/lib/action_view/render/rendering.rb | 44 ++++++++------------------ 1 file changed, 14 insertions(+), 30 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index 0302e44b4e..48316cac53 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -22,15 +22,18 @@ module ActionView return _render_partial(options) end - layout = find(layout, {:formats => formats}) if layout + template = if options[:file] + find(options[:file], {:formats => formats}) + elsif options[:inline] + handler = Template.handler_class_for_extension(options[:type] || "erb") + Template.new(options[:inline], "inline template", handler, {}) + elsif options[:text] + Template::Text.new(options[:text]) + end - if file = options[:file] - template = find(file, {:formats => formats}) + if template + layout = find(layout, {:formats => formats}) if layout _render_template(template, layout, :locals => options[:locals]) - elsif inline = options[:inline] - _render_inline(inline, layout, options) - elsif text = options[:text] - _render_text(text, layout, options[:locals]) end when :update update_page(&block) @@ -76,42 +79,23 @@ module ActionView capture(&block) end - def _render_inline(inline, layout, options) - locals = options[:locals] - - content = ActiveSupport::Notifications.instrument(:render_inline) do - handler = Template.handler_class_for_extension(options[:type] || "erb") - template = Template.new(options[:inline], "inline template", handler, {}) - template.render(self, locals) - end - - _render_text(content, layout, locals) - end - - def _render_text(content, layout, locals) - ActiveSupport::Notifications.instrument(:render_text) - content = _render_layout(layout, locals){ content } if layout - content - end - # This is the API to render a ViewContext's template from a controller. # # Internal Options: # _template:: The Template object to render # _layout:: The layout, if any, to wrap the Template in - # _partial:: true if the template is a partial def render_template(options) _evaluate_assigns_and_ivars - template, layout, partial = options.values_at(:_template, :_layout, :_partial) - _render_template(template, layout, options, partial) + template, layout = options.values_at(:_template, :_layout) + _render_template(template, layout, options) end - def _render_template(template, layout = nil, options = {}, partial = nil) + def _render_template(template, layout = nil, options = {}) locals = options[:locals] || {} content = ActiveSupport::Notifications.instrument(:render_template, :identifier => template.identifier, :layout => (layout ? layout.identifier : nil)) do - partial ? _render_partial_object(template, options) : template.render(self, locals) + template.render(self, locals) end @_content_for[:layout] = content -- cgit v1.2.3 From bef968d37942bfb2b7a59fca0e4451e096197c0a Mon Sep 17 00:00:00 2001 From: Carsten Gehling Date: Tue, 29 Dec 2009 13:06:19 +0100 Subject: I18n label helper [#745 status:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/lib/action_view/helpers/form_helper.rb | 39 +++++++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index d0c66eda60..9baa9f1fff 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -504,8 +504,9 @@ module ActionView end # Returns a label tag tailored for labelling an input field for a specified attribute (identified by +method+) on an object - # assigned to the template (identified by +object+). The text of label will default to the attribute name unless you specify - # it explicitly. Additional options on the label tag can be passed as a hash with +options+. These options will be tagged + # assigned to the template (identified by +object+). The text of label will default to the attribute name unless a translation + # is found in the current I18n locale (through views.labels..) or you specify it explicitly. + # Additional options on the label tag can be passed as a hash with +options+. These options will be tagged # onto the HTML as an HTML element attribute as in the example shown, except for the :value option, which is designed to # target labels for radio_button tags (where the value is used in the ID of the input tag). # @@ -513,6 +514,29 @@ module ActionView # label(:post, :title) # # => # + # You can localize your labels based on model and attribute names. + # For example you can define the following in your locale (e.g. en.yml) + # + # views: + # labels: + # post: + # body: "Write your entire text here" + # + # Which then will result in + # + # label(:post, :body) + # # => + # + # Localization can also be based purely on the translation of the attribute-name like this: + # + # activemodel: + # attribute: + # post: + # cost: "Total cost" + # + # label(:post, :cost) + # # => + # # label(:post, :title, "A short title") # # => # @@ -751,7 +775,16 @@ module ActionView add_default_name_and_id_for_value(tag_value, name_and_id) options.delete("index") options["for"] ||= name_and_id["id"] - content = (text.blank? ? nil : text.to_s) || method_name.humanize + + content = if text.blank? + i18n_label = I18n.t("views.labels.#{object_name}.#{method_name}", :default => "") + i18n_label if i18n_label.present? + else + text.to_s + end + content ||= object.class.human_attribute_name(method_name) if object + content ||= method_name.humanize + label_tag(name_and_id["id"], content, options) end -- cgit v1.2.3 From f50bb48e048b63186684e220b03235936e646ea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 31 Dec 2009 14:31:03 +0100 Subject: Do not enforce human_attribute_name as required API. --- actionpack/lib/action_view/helpers/form_helper.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 9baa9f1fff..81c9c88820 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -777,12 +777,15 @@ module ActionView options["for"] ||= name_and_id["id"] content = if text.blank? - i18n_label = I18n.t("views.labels.#{object_name}.#{method_name}", :default => "") - i18n_label if i18n_label.present? + I18n.t("views.labels.#{object_name}.#{method_name}", :default => "").presence else text.to_s end - content ||= object.class.human_attribute_name(method_name) if object + + content ||= if object && object.class.respond_to?(:human_attribute_name) + object.class.human_attribute_name(method_name) + end + content ||= method_name.humanize label_tag(name_and_id["id"], content, options) -- cgit v1.2.3 From 42aa9b87c2d8ae9e19e387f304d2463b6b8c02c5 Mon Sep 17 00:00:00 2001 From: Mikel Lindsaar Date: Fri, 1 Jan 2010 20:45:28 +1100 Subject: Silence warnings --- actionpack/lib/action_view/base.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index d69e5109fa..4970c768e8 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -274,6 +274,7 @@ module ActionView #:nodoc: end def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil, formats = nil)#:nodoc: + @config = nil @formats = formats @assigns = assigns_for_first_render.each { |key, value| instance_variable_set("@#{key}", value) } @controller = controller -- cgit v1.2.3 From d531cbc80959dfc35ee1dcbac133d52d63beacc9 Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Sun, 3 Jan 2010 00:56:55 -0600 Subject: fixed missing or incorrect session data error message --- actionpack/lib/action_dispatch/middleware/session/cookie_store.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb index f27f22c7e7..04a101dbb2 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb @@ -179,7 +179,7 @@ module ActionDispatch 'cookie containing the session data. Use ' + 'config.action_controller.session = { :key => ' + '"_myapp_session", :secret => "some secret phrase" } in ' + - 'config/environment.rb' + 'config/application.rb' end end -- cgit v1.2.3