aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch')
-rw-r--r--actionpack/lib/action_dispatch/http/cache.rb22
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb21
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/upload.rb25
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb5
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/abstract_store.rb283
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/cookie_store.rb64
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb53
-rw-r--r--actionpack/lib/action_dispatch/middleware/static.rb6
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb74
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb3
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/response.rb8
-rw-r--r--actionpack/lib/action_dispatch/testing/performance_test.rb3
13 files changed, 142 insertions, 427 deletions
diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb
index 047fab006e..4061222d11 100644
--- a/actionpack/lib/action_dispatch/http/cache.rb
+++ b/actionpack/lib/action_dispatch/http/cache.rb
@@ -50,8 +50,7 @@ module ActionDispatch
if cache_control = self["Cache-Control"]
cache_control.split(/,\s*/).each do |segment|
first, last = segment.split("=")
- last ||= true
- @cache_control[first.to_sym] = last
+ @cache_control[first.to_sym] = last || true
end
end
end
@@ -88,28 +87,9 @@ module ActionDispatch
def handle_conditional_get!
if etag? || last_modified? || !@cache_control.empty?
set_conditional_cache_control!
- elsif nonempty_ok_response?
- self.etag = body
-
- if request && request.etag_matches?(etag)
- self.status = 304
- self.body = []
- end
-
- set_conditional_cache_control!
- else
- headers["Cache-Control"] = "no-cache"
end
end
- def nonempty_ok_response?
- @status == 200 && string_body?
- end
-
- def string_body?
- !@blank && @body.respond_to?(:all?) && @body.all? { |part| part.is_a?(String) }
- end
-
DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate"
def set_conditional_cache_control!
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 7a28228817..bbcdefb190 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -54,11 +54,7 @@ module ActionDispatch
# the application should use), this \method returns the overridden
# value, not the original.
def request_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
+ @request_method ||= check_method(env["REQUEST_METHOD"])
end
# Returns a symbol form of the #request_method
@@ -70,11 +66,7 @@ module ActionDispatch
# even if it was overridden by middleware. See #request_method for
# more information.
def 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
+ @method ||= check_method(env["rack.methodoverride.original_method"] || env['REQUEST_METHOD'])
end
# Returns a symbol form of the #method
@@ -207,7 +199,7 @@ module ActionDispatch
# TODO This should be broken apart into AD::Request::Session and probably
# be included by the session middleware.
def reset_session
- session.destroy if session
+ session.destroy if session && session.respond_to?(:destroy)
self.session = {}
@env['action_dispatch.request.flash_hash'] = nil
end
@@ -246,5 +238,12 @@ module ActionDispatch
def local?
LOCALHOST.any? { |local_ip| local_ip === remote_addr && local_ip === remote_ip }
end
+
+ private
+
+ def check_method(name)
+ HTTP_METHOD_LOOKUP[name] || raise(ActionController::UnknownHttpMethod, "#{name}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}")
+ name
+ end
end
end
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index 151c90167b..72871e328a 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -132,7 +132,7 @@ module ActionDispatch # :nodoc:
# information.
attr_accessor :charset, :content_type
- CONTENT_TYPE = "Content-Type"
+ CONTENT_TYPE = "Content-Type"
cattr_accessor(:default_charset) { "utf-8" }
diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb
index 49465d820e..84e58d7d6a 100644
--- a/actionpack/lib/action_dispatch/http/upload.rb
+++ b/actionpack/lib/action_dispatch/http/upload.rb
@@ -2,27 +2,28 @@ require 'active_support/core_ext/object/blank'
module ActionDispatch
module Http
- class UploadedFile < Tempfile
+ class UploadedFile
attr_accessor :original_filename, :content_type, :tempfile, :headers
def initialize(hash)
@original_filename = hash[:filename]
@content_type = hash[:type]
@headers = hash[:head]
+ @tempfile = hash[:tempfile]
+ raise(ArgumentError, ':tempfile is required') unless @tempfile
+ end
- # To the untrained eye, this may appear as insanity. Given the alternatives,
- # such as busting the method cache on every request or breaking backwards
- # compatibility with is_a?(Tempfile), this solution is the best available
- # option.
- #
- # TODO: Deprecate is_a?(Tempfile) and define a real API for this parameter
- tempfile = hash[:tempfile]
- tempfile.instance_variables.each do |ivar|
- instance_variable_set(ivar, tempfile.instance_variable_get(ivar))
- end
+ def read(*args)
+ @tempfile.read(*args)
end
- alias local_path path
+ def rewind
+ @tempfile.rewind
+ end
+
+ def size
+ @tempfile.size
+ end
end
module Upload
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index 3e5cd6a2f9..cfee95eb4b 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -18,11 +18,6 @@ module ActionDispatch
@protocol ||= ssl? ? 'https://' : 'http://'
end
- # Is this an SSL request?
- def ssl?
- @ssl ||= @env['HTTPS'] == 'on' || @env['HTTP_X_FORWARDED_PROTO'] == 'https'
- end
-
# Returns the \host for this request, such as "example.com".
def raw_host_with_port
if forwarded = env["HTTP_X_FORWARDED_HOST"]
diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
index ea49b30630..64d3a87fd0 100644
--- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
@@ -1,5 +1,6 @@
require 'rack/utils'
require 'rack/request'
+require 'rack/session/abstract/id'
require 'action_dispatch/middleware/cookies'
require 'active_support/core_ext/object/blank'
@@ -8,252 +9,76 @@ module ActionDispatch
class SessionRestoreError < StandardError #:nodoc:
end
- class AbstractStore
- ENV_SESSION_KEY = 'rack.session'.freeze
- ENV_SESSION_OPTIONS_KEY = 'rack.session.options'.freeze
-
- # thin wrapper around Hash that allows us to lazily
- # load session id into session_options
- class OptionsHash < Hash
- def initialize(by, env, default_options)
- @by = by
- @env = env
- @session_id_loaded = false
- merge!(default_options)
- end
-
- def [](key)
- if key == :id
- load_session_id! unless key?(:id) || has_session_id?
- end
- super
- end
-
- private
-
- def has_session_id?
- @session_id_loaded
- end
-
- def load_session_id!
- self[:id] = @by.send(:extract_session_id, @env)
- @session_id_loaded = true
- end
- end
-
- class SessionHash < Hash
- def initialize(by, env)
- super()
- @by = by
- @env = env
- @loaded = false
- end
-
- def [](key)
- load_for_read!
- super(key.to_s)
- end
-
- def has_key?(key)
- load_for_read!
- super(key.to_s)
- end
-
- def []=(key, value)
- load_for_write!
- super(key.to_s, value)
- end
-
- def clear
- load_for_write!
- super
- end
-
- def to_hash
- load_for_read!
- h = {}.replace(self)
- h.delete_if { |k,v| v.nil? }
- h
- end
-
- def update(hash)
- load_for_write!
- super(hash.stringify_keys)
- end
-
- def delete(key)
- load_for_write!
- super(key.to_s)
- end
-
- def inspect
- load_for_read!
- super
- end
-
- def exists?
- return @exists if instance_variable_defined?(:@exists)
- @exists = @by.send(:exists?, @env)
- end
-
- def loaded?
- @loaded
- end
-
- def destroy
- clear
- @by.send(:destroy, @env) if defined?(@by) && @by
- @env[ENV_SESSION_OPTIONS_KEY][:id] = nil if defined?(@env) && @env && @env[ENV_SESSION_OPTIONS_KEY]
- @loaded = false
- end
-
- private
-
- def load_for_read!
- load! if !loaded? && exists?
- end
-
- def load_for_write!
- load! unless loaded?
- end
-
- def load!
- id, session = @by.send(:load_session, @env)
- @env[ENV_SESSION_OPTIONS_KEY][:id] = id
- replace(session.stringify_keys)
- @loaded = true
- end
-
+ module DestroyableSession
+ def destroy
+ clear
+ options = @env[Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY] if @env
+ options ||= {}
+ @by.send(:destroy_session, @env, options[:id], options) if @by
+ options[:id] = nil
+ @loaded = false
end
+ end
- DEFAULT_OPTIONS = {
- :key => '_session_id',
- :path => '/',
- :domain => nil,
- :expire_after => nil,
- :secure => false,
- :httponly => true,
- :cookie_only => true
- }
+ ::Rack::Session::Abstract::SessionHash.send :include, DestroyableSession
+ module Compatibility
def initialize(app, options = {})
- @app = app
- @default_options = DEFAULT_OPTIONS.merge(options)
- @key = @default_options.delete(:key).freeze
- @cookie_only = @default_options.delete(:cookie_only)
- ensure_session_key!
+ options[:key] ||= '_session_id'
+ super
end
- def call(env)
- prepare!(env)
- response = @app.call(env)
-
- session_data = env[ENV_SESSION_KEY]
- options = env[ENV_SESSION_OPTIONS_KEY]
-
- if !session_data.is_a?(AbstractStore::SessionHash) || session_data.loaded? || options[:expire_after]
- request = ActionDispatch::Request.new(env)
-
- return response if (options[:secure] && !request.ssl?)
-
- session_data.send(:load!) if session_data.is_a?(AbstractStore::SessionHash) && !session_data.loaded?
-
- sid = options[:id] || generate_sid
- session_data = session_data.to_hash
-
- value = set_session(env, sid, session_data)
- return response unless value
-
- cookie = { :value => value }
- unless options[:expire_after].nil?
- cookie[:expires] = Time.now + options.delete(:expire_after)
- end
-
- set_cookie(request, cookie.merge!(options))
- end
-
- response
+ def generate_sid
+ ActiveSupport::SecureRandom.hex(16)
end
- private
-
- def prepare!(env)
- env[ENV_SESSION_KEY] = SessionHash.new(self, env)
- env[ENV_SESSION_OPTIONS_KEY] = OptionsHash.new(self, env, @default_options)
- end
-
- def generate_sid
- ActiveSupport::SecureRandom.hex(16)
- end
+ protected
- def set_cookie(request, options)
- if request.cookie_jar[@key] != options[:value] || !options[:expires].nil?
- request.cookie_jar[@key] = options
- end
- end
-
- def load_session(env)
- stale_session_check! do
- sid = current_session_id(env)
- sid, session = get_session(env, sid)
- [sid, session]
- end
- end
-
- def extract_session_id(env)
- stale_session_check! do
- request = ActionDispatch::Request.new(env)
- sid = request.cookies[@key]
- sid ||= request.params[@key] unless @cookie_only
- sid
- end
- end
+ def initialize_sid
+ @default_options.delete(:sidbits)
+ @default_options.delete(:secure_random)
+ end
+ end
- def current_session_id(env)
- env[ENV_SESSION_OPTIONS_KEY][:id]
- end
+ module StaleSessionCheck
+ def load_session(env)
+ stale_session_check! { super }
+ end
- def ensure_session_key!
- if @key.blank?
- raise ArgumentError, 'A key is required to write a ' +
- 'cookie containing the session data. Use ' +
- 'config.session_store SESSION_STORE, { :key => ' +
- '"_myapp_session" } in config/application.rb'
- end
- end
+ def extract_session_id(env)
+ stale_session_check! { super }
+ end
- def stale_session_check!
- yield
- rescue ArgumentError => argument_error
- if argument_error.message =~ %r{undefined class/module ([\w:]*\w)}
- begin
- # Note that the regexp does not allow $1 to end with a ':'
- $1.constantize
- rescue LoadError, NameError => const_error
- raise ActionDispatch::Session::SessionRestoreError, "Session contains objects whose class definition isn't available.\nRemember to require the classes for all objects kept in the session.\n(Original exception: #{const_error.message} [#{const_error.class}])\n"
- end
- retry
- else
- raise
+ def stale_session_check!
+ yield
+ rescue ArgumentError => argument_error
+ if argument_error.message =~ %r{undefined class/module ([\w:]*\w)}
+ begin
+ # Note that the regexp does not allow $1 to end with a ':'
+ $1.constantize
+ rescue LoadError, NameError => const_error
+ raise ActionDispatch::Session::SessionRestoreError, "Session contains objects whose class definition isn't available.\nRemember to require the classes for all objects kept in the session.\n(Original exception: #{const_error.message} [#{const_error.class}])\n"
end
+ retry
+ else
+ raise
end
+ end
+ end
- def exists?(env)
- current_session_id(env).present?
- end
-
- def get_session(env, sid)
- raise '#get_session needs to be implemented.'
- end
+ class AbstractStore < Rack::Session::Abstract::ID
+ include Compatibility
+ include StaleSessionCheck
- def set_session(env, sid, session_data)
- raise '#set_session needs to be implemented and should return ' <<
- 'the value to be stored in the cookie (usually the sid)'
- end
+ def destroy_session(env, sid, options)
+ ActiveSupport::Deprecation.warn "Implementing #destroy in session stores is deprecated. " <<
+ "Please implement destroy_session(env, session_id, options) instead."
+ destroy(env)
+ end
- def destroy(env)
- raise '#destroy needs to be implemented.'
- end
+ def destroy(env)
+ raise '#destroy needs to be implemented.'
+ end
end
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
index ca1494425f..9c9ccc62f5 100644
--- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
@@ -1,5 +1,7 @@
require 'active_support/core_ext/hash/keys'
require 'active_support/core_ext/object/blank'
+require 'action_dispatch/middleware/session/abstract_store'
+require 'rack/session/cookie'
module ActionDispatch
module Session
@@ -38,58 +40,32 @@ module ActionDispatch
# "rake secret" and set the key in config/initializers/secret_token.rb.
#
# Note that changing digest or secret invalidates all existing sessions!
- class CookieStore < AbstractStore
-
- def initialize(app, options = {})
- super(app, options.merge!(:cookie_only => true))
- freeze
- end
+ class CookieStore < Rack::Session::Cookie
+ include Compatibility
+ include StaleSessionCheck
private
- def load_session(env)
- data = unpacked_cookie_data(env)
- data = persistent_session_id!(data)
- [data["session_id"], data]
- end
-
- def extract_session_id(env)
- if data = unpacked_cookie_data(env)
- data["session_id"]
- else
- nil
- end
- end
-
- def unpacked_cookie_data(env)
- env["action_dispatch.request.unsigned_session_cookie"] ||= begin
- stale_session_check! do
- request = ActionDispatch::Request.new(env)
- if data = request.cookie_jar.signed[@key]
- data.stringify_keys!
- end
- data || {}
+ def unpacked_cookie_data(env)
+ env["action_dispatch.request.unsigned_session_cookie"] ||= begin
+ stale_session_check! do
+ request = ActionDispatch::Request.new(env)
+ if data = request.cookie_jar.signed[@key]
+ data.stringify_keys!
end
+ data || {}
end
end
+ end
- def set_cookie(request, options)
- request.cookie_jar.signed[@key] = options
- end
-
- def set_session(env, sid, session_data)
- persistent_session_id!(session_data, sid)
- end
-
- def destroy(env)
- # session data is stored on client; nothing to do here
- end
+ def set_session(env, sid, session_data, options)
+ persistent_session_id!(session_data, sid)
+ end
- def persistent_session_id!(data, sid=nil)
- data ||= {}
- data["session_id"] ||= sid || generate_sid
- data
- end
+ def set_cookie(env, session_id, cookie)
+ request = ActionDispatch::Request.new(env)
+ request.cookie_jar.signed[@key] = cookie
+ end
end
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb b/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb
index 28e3dbd732..4dd9a946c2 100644
--- a/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb
@@ -1,56 +1,17 @@
+require 'action_dispatch/middleware/session/abstract_store'
+require 'rack/session/memcache'
+
module ActionDispatch
module Session
- class MemCacheStore < AbstractStore
+ class MemCacheStore < Rack::Session::Memcache
+ include Compatibility
+ include StaleSessionCheck
+
def initialize(app, options = {})
require 'memcache'
-
- # Support old :expires option
options[:expire_after] ||= options[:expires]
-
- super
-
- @default_options = {
- :namespace => 'rack:session',
- :memcache_server => 'localhost:11211'
- }.merge(@default_options)
-
- @pool = options[:cache] || MemCache.new(@default_options[:memcache_server], @default_options)
- unless @pool.servers.any? { |s| s.alive? }
- raise "#{self} unable to find server during initialization."
- end
- @mutex = Mutex.new
-
super
end
-
- private
- def get_session(env, sid)
- sid ||= generate_sid
- begin
- session = @pool.get(sid) || {}
- rescue MemCache::MemCacheError, Errno::ECONNREFUSED
- session = {}
- end
- [sid, session]
- end
-
- def set_session(env, sid, session_data)
- options = env['rack.session.options']
- expiry = options[:expire_after] || 0
- @pool.set(sid, session_data, expiry)
- sid
- rescue MemCache::MemCacheError, Errno::ECONNREFUSED
- false
- end
-
- def destroy(env)
- if sid = current_session_id(env)
- @pool.delete(sid)
- end
- rescue MemCache::MemCacheError, Errno::ECONNREFUSED
- false
- end
-
end
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb
index cf13938331..913b899e20 100644
--- a/actionpack/lib/action_dispatch/middleware/static.rb
+++ b/actionpack/lib/action_dispatch/middleware/static.rb
@@ -6,13 +6,13 @@ module ActionDispatch
@at, @root = at.chomp('/'), root.chomp('/')
@compiled_at = (Regexp.compile(/^#{Regexp.escape(at)}/) unless @at.blank?)
@compiled_root = Regexp.compile(/^#{Regexp.escape(root)}/)
- @file_server = ::Rack::File.new(root)
+ @file_server = ::Rack::File.new(@root)
end
def match?(path)
path = path.dup
- if @compiled_at.blank? || path.sub!(@compiled_at, '')
- full_path = File.join(@root, ::Rack::Utils.unescape(path))
+ if !@compiled_at || path.sub!(@compiled_at, '')
+ full_path = path.empty? ? @root : File.join(@root, ::Rack::Utils.unescape(path))
paths = "#{full_path}#{ext}"
matches = Dir[paths]
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 0cb02c5b80..3c7dcea003 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -171,13 +171,13 @@ module ActionDispatch
end
def blocks
+ block = @scope[:blocks] || []
+
if @options[:constraints].present? && !@options[:constraints].is_a?(Hash)
- block = @options[:constraints]
- else
- block = nil
+ block << @options[:constraints]
end
- ((@scope[:blocks] || []) + [ block ]).compact
+ block
end
def constraints
@@ -345,11 +345,11 @@ module ActionDispatch
# Redirect any path to another path:
#
# match "/stories" => redirect("/posts")
- def redirect(*args, &block)
+ def redirect(*args)
options = args.last.is_a?(Hash) ? args.pop : {}
- path = args.shift || block
- path_proc = path.is_a?(Proc) ? path : proc { |params| params.empty? ? path : (path % params) }
+ path = args.shift || Proc.new
+ path_proc = path.is_a?(Proc) ? path : proc { |params| (params.empty? || !path.match(/%\{\w*\}/)) ? path : (path % params) }
status = options[:status] || 301
lambda do |env|
@@ -735,15 +735,15 @@ module ActionDispatch
resource_scope(SingletonResource.new(resources.pop, options)) do
yield if block_given?
- collection_scope do
+ collection do
post :create
end if parent_resource.actions.include?(:create)
- new_scope do
+ new do
get :new
end if parent_resource.actions.include?(:new)
- member_scope do
+ member do
get :edit if parent_resource.actions.include?(:edit)
get :show if parent_resource.actions.include?(:show)
put :update if parent_resource.actions.include?(:update)
@@ -780,16 +780,16 @@ module ActionDispatch
resource_scope(Resource.new(resources.pop, options)) do
yield if block_given?
- collection_scope do
+ collection do
get :index if parent_resource.actions.include?(:index)
post :create if parent_resource.actions.include?(:create)
end
- new_scope do
+ new do
get :new
end if parent_resource.actions.include?(:new)
- member_scope do
+ member do
get :edit if parent_resource.actions.include?(:edit)
get :show if parent_resource.actions.include?(:show)
put :update if parent_resource.actions.include?(:update)
@@ -813,12 +813,14 @@ module ActionDispatch
# create the <tt>search_photos_url</tt> and <tt>search_photos_path</tt>
# route helpers.
def collection
- unless @scope[:scope_level] == :resources
- raise ArgumentError, "can't use collection outside resources scope"
+ unless resource_scope?
+ raise ArgumentError, "can't use collection outside resource(s) scope"
end
- collection_scope do
- yield
+ with_scope_level(:collection) do
+ scope(parent_resource.collection_scope) do
+ yield
+ end
end
end
@@ -838,8 +840,10 @@ module ActionDispatch
raise ArgumentError, "can't use member outside resource(s) scope"
end
- member_scope do
- yield
+ with_scope_level(:member) do
+ scope(parent_resource.member_scope) do
+ yield
+ end
end
end
@@ -848,8 +852,10 @@ module ActionDispatch
raise ArgumentError, "can't use new outside resource(s) scope"
end
- new_scope do
- yield
+ with_scope_level(:new) do
+ scope(parent_resource.new_scope(action_path(:new))) do
+ yield
+ end
end
end
@@ -1034,30 +1040,6 @@ module ActionDispatch
end
end
- def new_scope
- with_scope_level(:new) do
- scope(parent_resource.new_scope(action_path(:new))) do
- yield
- end
- end
- end
-
- def collection_scope
- with_scope_level(:collection) do
- scope(parent_resource.collection_scope) do
- yield
- end
- end
- end
-
- def member_scope
- with_scope_level(:member) do
- scope(parent_resource.member_scope) do
- yield
- end
- end
- end
-
def nested_options
{}.tap do |options|
options[:as] = parent_resource.member_name
@@ -1130,7 +1112,7 @@ module ActionDispatch
end
candidate = name.select(&:present?).join("_").presence
- candidate unless as.nil? && @set.routes.map(&:name).include?(candidate)
+ candidate unless as.nil? && @set.routes.find { |r| r.name == candidate }
end
end
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 5d18dfe369..32f41934f1 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -1,6 +1,7 @@
require 'rack/mount'
require 'forwardable'
require 'active_support/core_ext/object/to_query'
+require 'active_support/core_ext/hash/slice'
module ActionDispatch
module Routing
@@ -511,7 +512,7 @@ module ActionDispatch
end
script_name = options.delete(:script_name)
- path = (script_name.blank? ? _generate_prefix(options) : script_name).to_s
+ path = (script_name.blank? ? _generate_prefix(options) : script_name.chomp('/')).to_s
path_options = options.except(*RESERVED_OPTIONS)
path_options = yield(path_options) if block_given?
diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb
index 10b122557a..1558c3ae05 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/response.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb
@@ -81,14 +81,10 @@ module ActionDispatch
def normalize_argument_to_redirection(fragment)
case fragment
- when %r{^\w[\w\d+.-]*:.*}
+ when %r{^\w[A-Za-z\d+.-]*:.*}
fragment
when String
- if fragment =~ %r{^\w[\w\d+.-]*:.*}
- fragment
- else
- @request.protocol + @request.host_with_port + fragment
- end
+ @request.protocol + @request.host_with_port + fragment
when :back
raise RedirectBackError unless refer = @request.headers["Referer"]
refer
diff --git a/actionpack/lib/action_dispatch/testing/performance_test.rb b/actionpack/lib/action_dispatch/testing/performance_test.rb
index 33a5c68b9d..d6c98b4db7 100644
--- a/actionpack/lib/action_dispatch/testing/performance_test.rb
+++ b/actionpack/lib/action_dispatch/testing/performance_test.rb
@@ -11,9 +11,8 @@ begin
# 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
rescue NameError
$stderr.puts "Specify ruby-prof as application's dependency in Gemfile to run benchmarks."
-end \ No newline at end of file
+end