diff options
author | Xavier Noria <fxn@hashref.com> | 2010-06-07 15:44:57 +0200 |
---|---|---|
committer | Xavier Noria <fxn@hashref.com> | 2010-06-07 15:44:57 +0200 |
commit | 9e065c6bc175621ad30a416c8c4345f95ce3c264 (patch) | |
tree | 505df4243727a00d1f030205f2e64afe0d098e5e /actionpack | |
parent | 0dbc732995a526354fb1e3c732af5dacdb863dda (diff) | |
parent | 1a8f784a236058101c6e8b6387aefc96e86a1e54 (diff) | |
download | rails-9e065c6bc175621ad30a416c8c4345f95ce3c264.tar.gz rails-9e065c6bc175621ad30a416c8c4345f95ce3c264.tar.bz2 rails-9e065c6bc175621ad30a416c8c4345f95ce3c264.zip |
Merge remote branch 'rails/master'
Diffstat (limited to 'actionpack')
-rw-r--r-- | actionpack/actionpack.gemspec | 2 | ||||
-rw-r--r-- | actionpack/lib/action_controller/test_case.rb | 12 | ||||
-rwxr-xr-x | actionpack/lib/action_dispatch/http/request.rb | 26 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/middleware/flash.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/middleware/session/abstract_store.rb | 8 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/middleware/show_exceptions.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/middleware/stack.rb | 18 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/routing/mapper.rb | 15 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/routing/route_set.rb | 27 | ||||
-rw-r--r-- | actionpack/lib/action_view/base.rb | 3 | ||||
-rw-r--r-- | actionpack/lib/action_view/lookup_context.rb | 74 | ||||
-rw-r--r-- | actionpack/lib/action_view/render/layouts.rb | 15 | ||||
-rw-r--r-- | actionpack/lib/action_view/template/handlers.rb | 2 | ||||
-rw-r--r-- | actionpack/test/dispatch/routing_test.rb | 12 | ||||
-rw-r--r-- | actionpack/test/template/lookup_context_test.rb | 16 |
16 files changed, 139 insertions, 97 deletions
diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index 0f45cb5a4a..02ff908c1c 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -22,7 +22,7 @@ Gem::Specification.new do |s| s.add_dependency('activesupport', version) s.add_dependency('activemodel', version) s.add_dependency('builder', '~> 2.1.2') - s.add_dependency('i18n', '~> 0.4.0') + s.add_dependency('i18n', '~> 0.4.1') s.add_dependency('rack', '~> 1.1.0') s.add_dependency('rack-test', '~> 0.5.4') s.add_dependency('rack-mount', '~> 0.6.3') diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 34499fa784..21281b606e 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -139,14 +139,16 @@ module ActionController end end - params = self.request_parameters.dup + # Clear the combined params hash in case it was already referenced. + @env.delete("action_dispatch.request.parameters") + 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 @@ -155,6 +157,8 @@ module ActionController @formats = nil @env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ } @env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ } + @method = @request_method = nil + @fullpath = @ip = @remote_ip = nil @env['action_dispatch.request.query_parameters'] = {} end end @@ -167,9 +171,7 @@ module ActionController @block = nil @length = 0 @body = [] - @charset = nil - @content_type = nil - + @charset = @content_type = nil @request = @template = nil end end diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 8560a6fc9c..98f4f5ae18 100755 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -52,9 +52,11 @@ module ActionDispatch # the application should use), this \method returns the overridden # value, not the original. def request_method - method = env["REQUEST_METHOD"] - HTTP_METHOD_LOOKUP[method] || raise(ActionController::UnknownHttpMethod, "#{method}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}") - method + @request_method ||= begin + method = env["REQUEST_METHOD"] + HTTP_METHOD_LOOKUP[method] || raise(ActionController::UnknownHttpMethod, "#{method}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}") + method + end end # Returns a symbol form of the #request_method @@ -66,9 +68,11 @@ module ActionDispatch # even if it was overridden by middleware. See #request_method for # more information. def method - method = env["rack.methodoverride.original_method"] || env['REQUEST_METHOD'] - HTTP_METHOD_LOOKUP[method] || raise(ActionController::UnknownHttpMethod, "#{method}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}") - method + @method ||= begin + method = env["rack.methodoverride.original_method"] || env['REQUEST_METHOD'] + HTTP_METHOD_LOOKUP[method] || raise(ActionController::UnknownHttpMethod, "#{method}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}") + method + end end # Returns a symbol form of the #method @@ -113,6 +117,10 @@ module ActionDispatch Http::Headers.new(@env) end + def fullpath + @fullpath ||= super + end + def forgery_whitelisted? get? || xhr? || content_mime_type.nil? || !content_mime_type.verify_request? end @@ -134,6 +142,10 @@ module ActionDispatch end alias :xhr? :xml_http_request? + def ip + @ip ||= super + end + # Which IP addresses are "trusted proxies" that can be stripped from # the right-hand-side of X-Forwarded-For TRUSTED_PROXIES = /^127\.0\.0\.1$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\./i @@ -145,7 +157,7 @@ module ActionDispatch # delimited list in the case of multiple chained proxies; the last # address which is not trusted is the originating IP. def remote_ip - (@env["action_dispatch.remote_ip"] || ip).to_s + @remote_ip ||= (@env["action_dispatch.remote_ip"] || ip).to_s end # Returns the lowercase name of the HTTP server software. diff --git a/actionpack/lib/action_dispatch/middleware/flash.rb b/actionpack/lib/action_dispatch/middleware/flash.rb index adde183cdb..18771fe782 100644 --- a/actionpack/lib/action_dispatch/middleware/flash.rb +++ b/actionpack/lib/action_dispatch/middleware/flash.rb @@ -176,7 +176,7 @@ module ActionDispatch @app.call(env) ensure - if (session = env['rack.session']) && (flash = session['flash']) && flash.empty? + if (session = env['rack.session']) && session.key?('flash') && session['flash'].empty? session.delete('flash') end end diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index 15493cd2eb..3e8d64b0c6 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -51,11 +51,11 @@ module ActionDispatch super end - private - def loaded? - @loaded - end + def loaded? + @loaded + end + private def load! stale_session_check! do id, session = @by.send(:load_session, @env) diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index 2dd2ec9fe9..f9e81a02d3 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -72,7 +72,7 @@ module ActionDispatch rescue_action_in_public(exception) end rescue Exception => failsafe_error - $stderr.puts "Error during failsafe response: #{failsafe_error}" + $stderr.puts "Error during failsafe response: #{failsafe_error}\n #{failsafe_error.backtrace * "\n "}" FAILSAFE_RESPONSE end diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb index e3180dba77..4240e7a5d5 100644 --- a/actionpack/lib/action_dispatch/middleware/stack.rb +++ b/actionpack/lib/action_dispatch/middleware/stack.rb @@ -5,13 +5,13 @@ module ActionDispatch class Middleware attr_reader :args, :block - def initialize(klass, *args, &block) - @klass, @args, @block = klass, args, block + def initialize(klass_or_name, *args, &block) + @ref = ActiveSupport::Dependencies::Reference.new(klass_or_name) + @args, @block = args, block end def klass - return @klass if @klass.respond_to?(:new) - @klass = ActiveSupport::Inflector.constantize(@klass.to_s) + @ref.get end def ==(middleware) @@ -21,11 +21,7 @@ module ActionDispatch when Class klass == middleware else - if lazy_compare?(@klass) && lazy_compare?(middleware) - normalize(@klass) == normalize(middleware) - else - klass.name == normalize(middleware.to_s) - end + normalize(@ref.name) == normalize(middleware) end end @@ -39,10 +35,6 @@ module ActionDispatch private - def lazy_compare?(object) - object.is_a?(String) || object.is_a?(Symbol) - end - def normalize(object) object.to_s.strip.sub(/^::/, '') end diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb index 09ff052fd0..e963b04524 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb @@ -13,7 +13,7 @@ request_dump = clean_params.empty? ? 'None' : clean_params.inspect.gsub(',', ",\n") def debug_hash(hash) - hash.sort_by { |k, v| k.to_s }.map { |k, v| "#{k}: #{v.inspect}" }.join("\n") + hash.sort_by { |k, v| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n") end %> diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 8a8d21c434..ae4417b56c 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -622,12 +622,19 @@ module ActionDispatch end def member - unless @scope[:scope_level] == :resources - raise ArgumentError, "can't use member outside resources scope" + unless [:resources, :resource].include?(@scope[:scope_level]) + raise ArgumentError, "You can't use member action outside resources and resource scope." end - with_scope_level(:member) do - scope(':id', :name_prefix => parent_resource.member_name, :as => "") do + case @scope[:scope_level] + when :resources + with_scope_level(:member) do + scope(':id', :name_prefix => parent_resource.member_name, :as => "") do + yield + end + end + when :resource + with_scope_level(:member) do yield end end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 0d071dd7fe..750912b251 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -12,6 +12,7 @@ module ActionDispatch def initialize(options={}) @defaults = options[:defaults] @glob_param = options.delete(:glob) + @controllers = {} end def call(env) @@ -29,19 +30,18 @@ module ActionDispatch 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 def controller(params, raise_error=true) - if params && params.has_key?(:controller) - controller = "#{params[:controller].camelize}Controller" - ActiveSupport::Inflector.constantize(controller) + if params && params.key?(:controller) + controller_param = params[:controller] + unless controller = @controllers[controller_param] + controller_name = "#{controller_param.camelize}Controller" + controller = @controllers[controller_param] = + ActiveSupport::Dependencies.ref(controller_name) + end + + controller.get end rescue NameError => e raise ActionController::RoutingError, e.message, e.backtrace if raise_error @@ -466,6 +466,13 @@ module ActionDispatch req = Rack::Request.new(env) @set.recognize(req) do |route, matches, params| + params.each do |key, value| + if value.is_a?(String) + value = value.dup.force_encoding(Encoding::BINARY) if value.encoding_aware? + params[key] = URI.unescape(value) + end + end + dispatcher = route.app if dispatcher.is_a?(Dispatcher) && dispatcher.controller(params, false) dispatcher.prepare_params!(params) diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index f4af763afe..7dd9dea358 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -184,7 +184,7 @@ module ActionView #:nodoc: attr_internal :captures, :request, :controller, :template, :config delegate :find_template, :template_exists?, :formats, :formats=, :locale, :locale=, - :view_paths, :view_paths=, :with_fallbacks, :update_details, :to => :lookup_context + :view_paths, :view_paths=, :with_fallbacks, :update_details, :with_layout_format, :to => :lookup_context delegate :request_forgery_protection_token, :template, :params, :session, :cookies, :response, :headers, :flash, :action_name, :controller_name, :to => :controller @@ -201,6 +201,7 @@ module ActionView #:nodoc: end def self.process_view_paths(value) + return value.dup if value.is_a?(PathSet) ActionView::PathSet.new(Array.wrap(value)) end diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb index 7021342b4a..3aaa5e401c 100644 --- a/actionpack/lib/action_view/lookup_context.rb +++ b/actionpack/lib/action_view/lookup_context.rb @@ -13,8 +13,13 @@ module ActionView mattr_accessor :registered_details self.registered_details = [] + mattr_accessor :registered_detail_setters + self.registered_detail_setters = [] + def self.register_detail(name, options = {}, &block) self.registered_details << name + self.registered_detail_setters << [name, "#{name}="] + Accessors.send :define_method, :"_#{name}_defaults", &block Accessors.module_eval <<-METHOD, __FILE__, __LINE__ + 1 def #{name} @@ -23,12 +28,7 @@ module ActionView def #{name}=(value) value = Array.wrap(value.presence || _#{name}_defaults) - - if value != @details[:#{name}] - @details_key = nil - @details = @details.dup if @details.frozen? - @details[:#{name}] = value.freeze - end + _set_detail(:#{name}, value) if value != @details[:#{name}] end METHOD end @@ -59,8 +59,11 @@ module ActionView def initialize(view_paths, details = {}) @details, @details_key = { :handlers => default_handlers }, nil @frozen_formats, @skip_default_locale = false, false + self.view_paths = view_paths - self.update_details(details, true) + self.registered_detail_setters.each do |key, setter| + send(setter, details[key]) + end end module ViewPaths @@ -116,11 +119,11 @@ module ActionView end def default_handlers #:nodoc: - @default_handlers ||= Template::Handlers.extensions + @@default_handlers ||= Template::Handlers.extensions end def handlers_regexp #:nodoc: - @handlers_regexp ||= /\.(?:#{default_handlers.join('|')})$/ + @@handlers_regexp ||= /\.(?:#{default_handlers.join('|')})$/ end end @@ -141,10 +144,13 @@ module ActionView end # Overload formats= to reject [:"*/*"] values. - def formats=(value) - value = nil if value == [:"*/*"] - value << :html if value == [:js] - super(value) + def formats=(values) + if values && values.size == 1 + value = values.first + values = nil if value == :"*/*" + values << :html if value == :js + end + super(values) end # Do not use the default locale on template lookup. @@ -170,24 +176,48 @@ module ActionView super(@skip_default_locale ? I18n.locale : _locale_defaults) end + # A method which only uses the first format in the formats array for layout lookup. + # This method plays straight with instance variables for performance reasons. + def with_layout_format + if formats.size == 1 + yield + else + old_formats = formats + _set_detail(:formats, formats[0,1]) + + begin + yield + ensure + _set_detail(:formats, formats) + end + end + end + # Update the details keys by merging the given hash into the current # details hash. If a block is given, the details are modified just during # the execution of the block and reverted to the previous value after. - def update_details(new_details, force=false) + def update_details(new_details) old_details = @details.dup - registered_details.each do |key| - send(:"#{key}=", new_details[key]) if force || new_details.key?(key) + registered_detail_setters.each do |key, setter| + send(setter, new_details[key]) if new_details.key?(key) end - if block_given? - begin - yield - ensure - @details = old_details - end + begin + yield + ensure + @details_key = nil + @details = old_details end end + + protected + + def _set_detail(key, value) + @details_key = nil + @details = @details.dup if @details.frozen? + @details[key] = value.freeze + end end include Accessors diff --git a/actionpack/lib/action_view/render/layouts.rb b/actionpack/lib/action_view/render/layouts.rb index 31b09d9f0a..a9dfc0cced 100644 --- a/actionpack/lib/action_view/render/layouts.rb +++ b/actionpack/lib/action_view/render/layouts.rb @@ -57,15 +57,11 @@ module ActionView # This is the method which actually finds the layout using details in the lookup # context object. If no layout is found, it checkes if at least a layout with # the given name exists across all details before raising the error. - # - # If self.formats contains several formats, just the first one is considered in - # the layout lookup. def find_layout(layout) begin - if formats.size == 1 - _find_layout(layout) - else - update_details(:formats => self.formats.first){ _find_layout(layout) } + with_layout_format do + layout =~ /^\// ? + with_fallbacks { find_template(layout) } : find_template(layout) end rescue ActionView::MissingTemplate => e update_details(:formats => nil) do @@ -74,11 +70,6 @@ module ActionView end end - def _find_layout(layout) #:nodoc: - layout =~ /^\// ? - with_fallbacks { find_template(layout) } : find_template(layout) - end - # Contains the logic that actually renders the layout. def _render_layout(layout, locals, &block) #:nodoc: layout.render(self, locals){ |*name| _layout_for(*name, &block) } diff --git a/actionpack/lib/action_view/template/handlers.rb b/actionpack/lib/action_view/template/handlers.rb index 35488c0391..6228d7ac39 100644 --- a/actionpack/lib/action_view/template/handlers.rb +++ b/actionpack/lib/action_view/template/handlers.rb @@ -19,7 +19,7 @@ module ActionView #:nodoc: @@default_template_handlers = nil def self.extensions - @@template_handlers.keys + @@template_extensions ||= @@template_handlers.keys end # Register a class that knows how to handle template files with the given diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 180889ddf2..ffa4f50b00 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -28,6 +28,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest post :reset resource :info + + member do + get :crush + end end match 'account/logout' => redirect("/logout"), :as => :logout_redirect @@ -352,6 +356,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end + def test_member_on_resource + with_test_routes do + get '/session/crush' + assert_equal 'sessions#crush', @response.body + assert_equal '/session/crush', crush_session_path + end + end + def test_redirect_modulo with_test_routes do get '/account/modulo/name' diff --git a/actionpack/test/template/lookup_context_test.rb b/actionpack/test/template/lookup_context_test.rb index df1aa2edb2..cc71cb42d0 100644 --- a/actionpack/test/template/lookup_context_test.rb +++ b/actionpack/test/template/lookup_context_test.rb @@ -26,18 +26,6 @@ class LookupContextTest < ActiveSupport::TestCase assert_equal :en, @lookup_context.locale end - test "allows me to update details" do - @lookup_context.update_details(:formats => [:html], :locale => :pt) - assert_equal [:html], @lookup_context.formats - assert_equal :pt, @lookup_context.locale - end - - test "allows me to update an specific detail" do - @lookup_context.update_details(:locale => :pt) - assert_equal :pt, I18n.locale - assert_equal :pt, @lookup_context.locale - end - test "allows me to freeze and retrieve frozen formats" do @lookup_context.formats.freeze assert @lookup_context.formats.frozen? @@ -54,7 +42,7 @@ class LookupContextTest < ActiveSupport::TestCase end test "provides getters and setters for formats" do - @lookup_context.formats = :html + @lookup_context.formats = [:html] assert_equal [:html], @lookup_context.formats end @@ -138,7 +126,7 @@ class LookupContextTest < ActiveSupport::TestCase keys << @lookup_context.details_key assert_equal 2, keys.uniq.size - @lookup_context.formats = :html + @lookup_context.formats = [:html] keys << @lookup_context.details_key assert_equal 3, keys.uniq.size |