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/mime_type.rb14
-rw-r--r--actionpack/lib/action_dispatch/journey/formatter.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb164
-rw-r--r--actionpack/lib/action_dispatch/middleware/request_id.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/cookie_store.rb96
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb10
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb2
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb51
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb4
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/routing.rb4
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/selector.rb4
-rw-r--r--actionpack/lib/action_dispatch/testing/test_process.rb2
13 files changed, 192 insertions, 165 deletions
diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb
index 912da741b7..f29ad359ac 100644
--- a/actionpack/lib/action_dispatch/http/mime_type.rb
+++ b/actionpack/lib/action_dispatch/http/mime_type.rb
@@ -223,8 +223,8 @@ module Mime
Mime.instance_eval { remove_const(symbol) }
SET.delete_if { |v| v.eql?(mime) }
- LOOKUP.delete_if { |k,v| v.eql?(mime) }
- EXTENSION_LOOKUP.delete_if { |k,v| v.eql?(mime) }
+ LOOKUP.delete_if { |_,v| v.eql?(mime) }
+ EXTENSION_LOOKUP.delete_if { |_,v| v.eql?(mime) }
end
end
@@ -306,12 +306,20 @@ module Mime
method.to_s.ends_with? '?'
end
end
-
+
class NullType
def nil?
true
end
+ def ref
+ nil
+ end
+
+ def respond_to_missing?(method, include_private = false)
+ method.to_s.ends_with? '?'
+ end
+
private
def method_missing(method, *args)
false if method.to_s.ends_with? '?'
diff --git a/actionpack/lib/action_dispatch/journey/formatter.rb b/actionpack/lib/action_dispatch/journey/formatter.rb
index 82c55660ea..a732e570f2 100644
--- a/actionpack/lib/action_dispatch/journey/formatter.rb
+++ b/actionpack/lib/action_dispatch/journey/formatter.rb
@@ -58,7 +58,7 @@ module ActionDispatch
end
end
- parameterized_parts.keep_if { |_, v| v }
+ parameterized_parts.keep_if { |_, v| v }
parameterized_parts
end
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index f21d1d4ee5..5b914f293d 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -31,7 +31,7 @@ module ActionDispatch
#
# # Sets a signed cookie, which prevents users from tampering with its value.
# # The cookie is signed by your app's <tt>config.secret_key_base</tt> value.
- # # It can be read using the signed method <tt>cookies.signed[:key]</tt>
+ # # It can be read using the signed method <tt>cookies.signed[:name]</tt>
# cookies.signed[:user_id] = current_user.id
#
# # Sets a "permanent" cookie (which expires in 20 years from now).
@@ -53,13 +53,13 @@ module ActionDispatch
#
# Please note that if you specify a :domain when setting a cookie, you must also specify the domain when deleting the cookie:
#
- # cookies[:key] = {
+ # cookies[:name] = {
# value: 'a yummy cookie',
# expires: 1.year.from_now,
# domain: 'domain.com'
# }
#
- # cookies.delete(:key, domain: 'domain.com')
+ # cookies.delete(:name, domain: 'domain.com')
#
# The option symbols for setting cookies are:
#
@@ -70,7 +70,7 @@ module ActionDispatch
# restrict to the domain level. If you use a schema like www.example.com
# and want to share session with user.example.com set <tt>:domain</tt>
# to <tt>:all</tt>. Make sure to specify the <tt>:domain</tt> option with
- # <tt>:all</tt> again when deleting keys.
+ # <tt>:all</tt> again when deleting cookies.
#
# domain: nil # Does not sets cookie domain. (default)
# domain: :all # Allow the cookie for the top most level
@@ -117,6 +117,9 @@ module ActionDispatch
# 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), nil will be returned.
#
+ # If +config.secret_key_base+ and +config.secret_token+ (deprecated) are both set,
+ # legacy cookies signed with the old key generator will be transparently upgraded.
+ #
# This jar requires that you set a suitable secret for the verification on your app's +config.secret_key_base+.
#
# Example:
@@ -126,23 +129,20 @@ module ActionDispatch
#
# cookies.signed[:discount] # => 45
def signed
- @signed ||= begin
- if @options[:upgrade_legacy_signed_cookie_jar]
+ @signed ||=
+ if @options[:upgrade_legacy_signed_cookies]
UpgradeLegacySignedCookieJar.new(self, @key_generator, @options)
else
SignedCookieJar.new(self, @key_generator, @options)
end
- end
- end
-
- # Only needed for supporting the +UpgradeSignatureToEncryptionCookieStore+, users and plugin authors should not use this
- def signed_using_old_secret #:nodoc:
- @signed_using_old_secret ||= SignedCookieJar.new(self, ActiveSupport::DummyKeyGenerator.new(@options[:secret_token]), @options)
end
# Returns a jar that'll automatically encrypt cookie values before sending them to the client and will decrypt them for read.
# If the cookie was tampered with by the user (or a 3rd party), nil will be returned.
#
+ # If +config.secret_key_base+ and +config.secret_token+ (deprecated) are both set,
+ # legacy cookies signed with the old key generator will be transparently upgraded.
+ #
# This jar requires that you set a suitable secret for the verification on your app's +config.secret_key_base+.
#
# Example:
@@ -152,7 +152,38 @@ module ActionDispatch
#
# cookies.encrypted[:discount] # => 45
def encrypted
- @encrypted ||= EncryptedCookieJar.new(self, @key_generator, @options)
+ @encrypted ||=
+ if @options[:upgrade_legacy_signed_cookies]
+ UpgradeLegacyEncryptedCookieJar.new(self, @key_generator, @options)
+ else
+ EncryptedCookieJar.new(self, @key_generator, @options)
+ end
+ end
+
+ # Returns the +signed+ or +encrypted jar, preferring +encrypted+ if +secret_key_base+ is set.
+ # Used by ActionDispatch::Session::CookieStore to avoid the need to introduce new cookie stores.
+ def signed_or_encrypted
+ @signed_or_encrypted ||=
+ if @options[:secret_key_base].present?
+ encrypted
+ else
+ signed
+ end
+ end
+ end
+
+ module VerifyAndUpgradeLegacySignedMessage
+ def initialize(*args)
+ super
+ @legacy_verifier = ActiveSupport::MessageVerifier.new(@options[:secret_token])
+ end
+
+ def verify_and_upgrade_legacy_signed_message(name, signed_message)
+ @legacy_verifier.verify(signed_message).tap do |value|
+ self[name] = value
+ end
+ rescue ActiveSupport::MessageVerifier::InvalidSignature
+ nil
end
end
@@ -179,7 +210,7 @@ module ActionDispatch
encrypted_signed_cookie_salt: env[ENCRYPTED_SIGNED_COOKIE_SALT] || '',
secret_token: env[SECRET_TOKEN],
secret_key_base: env[SECRET_KEY_BASE],
- upgrade_legacy_signed_cookie_jar: env[SECRET_TOKEN].present? && env[SECRET_KEY_BASE].present?
+ upgrade_legacy_signed_cookies: env[SECRET_TOKEN].present? && env[SECRET_KEY_BASE].present?
}
end
@@ -249,7 +280,7 @@ module ActionDispatch
# 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)
+ def []=(name, options)
if options.is_a?(Hash)
options.symbolize_keys!
value = options[:value]
@@ -260,10 +291,10 @@ module ActionDispatch
handle_options(options)
- if @cookies[key.to_s] != value or options[:expires]
- @cookies[key.to_s] = value
- @set_cookies[key.to_s] = options
- @delete_cookies.delete(key.to_s)
+ if @cookies[name.to_s] != value or options[:expires]
+ @cookies[name.to_s] = value
+ @set_cookies[name.to_s] = options
+ @delete_cookies.delete(name.to_s)
end
value
@@ -272,24 +303,24 @@ module ActionDispatch
# Removes the cookie on the client machine by setting the value to an empty string
# and the expiration date in the past. Like <tt>[]=</tt>, you can pass in
# an options hash to delete cookies with extra data such as a <tt>:path</tt>.
- def delete(key, options = {})
- return unless @cookies.has_key? key.to_s
+ def delete(name, options = {})
+ return unless @cookies.has_key? name.to_s
options.symbolize_keys!
handle_options(options)
- value = @cookies.delete(key.to_s)
- @delete_cookies[key.to_s] = options
+ value = @cookies.delete(name.to_s)
+ @delete_cookies[name.to_s] = options
value
end
# Whether the given cookie is to be deleted by this CookieJar.
# Like <tt>[]=</tt>, you can pass in an options hash to test if a
# deletion applies to a specific <tt>:path</tt>, <tt>:domain</tt> etc.
- def deleted?(key, options = {})
+ def deleted?(name, options = {})
options.symbolize_keys!
handle_options(options)
- @delete_cookies[key.to_s] == options
+ @delete_cookies[name.to_s] == options
end
# Removes all cookies on the client machine by calling <tt>delete</tt> for each cookie
@@ -311,7 +342,6 @@ module ActionDispatch
self.always_write_cookie = false
private
-
def write_cookie?(cookie)
@secure || !cookie[:secure] || always_write_cookie
end
@@ -326,11 +356,11 @@ module ActionDispatch
@options = options
end
- def [](key)
+ def [](name)
@parent_jar[name.to_s]
end
- def []=(key, options)
+ def []=(name, options)
if options.is_a?(Hash)
options.symbolize_keys!
else
@@ -338,7 +368,7 @@ module ActionDispatch
end
options[:expires] = 20.years.from_now
- @parent_jar[key] = options
+ @parent_jar[name] = options
end
end
@@ -354,13 +384,11 @@ module ActionDispatch
def [](name)
if signed_message = @parent_jar[name]
- @verifier.verify(signed_message)
+ verify(signed_message)
end
- rescue ActiveSupport::MessageVerifier::InvalidSignature
- nil
end
- def []=(key, options)
+ def []=(name, options)
if options.is_a?(Hash)
options.symbolize_keys!
options[:value] = @verifier.generate(options[:value])
@@ -369,8 +397,15 @@ module ActionDispatch
end
raise CookieOverflow if options[:value].size > MAX_COOKIE_SIZE
- @parent_jar[key] = options
+ @parent_jar[name] = options
end
+
+ private
+ def verify(signed_message)
+ @verifier.verify(signed_message)
+ rescue ActiveSupport::MessageVerifier::InvalidSignature
+ nil
+ end
end
# UpgradeLegacySignedCookieJar is used instead of SignedCookieJar if
@@ -378,39 +413,22 @@ module ActionDispatch
# legacy cookies signed with the old dummy key generator and re-saves
# them using the new key generator to provide a smooth upgrade path.
class UpgradeLegacySignedCookieJar < SignedCookieJar #:nodoc:
- def initialize(*args)
- super
- @legacy_verifier = ActiveSupport::MessageVerifier.new(@options[:secret_token])
- end
+ include VerifyAndUpgradeLegacySignedMessage
def [](name)
if signed_message = @parent_jar[name]
- verify_signed_message(signed_message) || verify_and_upgrade_legacy_signed_message(name, signed_message)
+ verify(signed_message) || verify_and_upgrade_legacy_signed_message(name, signed_message)
end
end
-
- def verify_signed_message(signed_message)
- @verifier.verify(signed_message)
- rescue ActiveSupport::MessageVerifier::InvalidSignature
- nil
- end
-
- def verify_and_upgrade_legacy_signed_message(name, signed_message)
- @legacy_verifier.verify(signed_message).tap do |value|
- self[name] = value
- end
- rescue ActiveSupport::MessageVerifier::InvalidSignature
- nil
- end
end
class EncryptedCookieJar #:nodoc:
include ChainedCookieJars
def initialize(parent_jar, key_generator, options = {})
- if ActiveSupport::DummyKeyGenerator === key_generator
- raise "Encrypted Cookies must be used in conjunction with config.secret_key_base." +
- "Set config.secret_key_base in config/initializers/secret_token.rb"
+ if ActiveSupport::LegacyKeyGenerator === key_generator
+ raise "You didn't set config.secret_key_base, which is required for this cookie jar. " +
+ "Read the upgrade documentation to learn more about this new config option."
end
@parent_jar = parent_jar
@@ -420,16 +438,13 @@ module ActionDispatch
@encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret)
end
- def [](key)
- if encrypted_message = @parent_jar[key]
- @encryptor.decrypt_and_verify(encrypted_message)
+ def [](name)
+ if encrypted_message = @parent_jar[name]
+ decrypt_and_verify(encrypted_message)
end
- rescue ActiveSupport::MessageVerifier::InvalidSignature,
- ActiveSupport::MessageEncryptor::InvalidMessage
- nil
end
- def []=(key, options)
+ def []=(name, options)
if options.is_a?(Hash)
options.symbolize_keys!
else
@@ -438,7 +453,28 @@ module ActionDispatch
options[:value] = @encryptor.encrypt_and_sign(options[:value])
raise CookieOverflow if options[:value].size > MAX_COOKIE_SIZE
- @parent_jar[key] = options
+ @parent_jar[name] = options
+ end
+
+ private
+ def decrypt_and_verify(encrypted_message)
+ @encryptor.decrypt_and_verify(encrypted_message)
+ rescue ActiveSupport::MessageVerifier::InvalidSignature, ActiveSupport::MessageEncryptor::InvalidMessage
+ nil
+ end
+ end
+
+ # UpgradeLegacyEncryptedCookieJar is used by ActionDispatch::Session::CookieStore
+ # instead of EncryptedCookieJar if config.secret_token and config.secret_key_base
+ # are both set. It reads legacy cookies signed with the old dummy key generator and
+ # encrypts and re-saves them using the new key generator to provide a smooth upgrade path.
+ class UpgradeLegacyEncryptedCookieJar < EncryptedCookieJar #:nodoc:
+ include VerifyAndUpgradeLegacySignedMessage
+
+ def [](name)
+ if encrypted_or_signed_message = @parent_jar[name]
+ decrypt_and_verify(encrypted_or_signed_message) || verify_and_upgrade_legacy_signed_message(name, encrypted_or_signed_message)
+ end
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/request_id.rb b/actionpack/lib/action_dispatch/middleware/request_id.rb
index 44290445d4..5d1740d0d4 100644
--- a/actionpack/lib/action_dispatch/middleware/request_id.rb
+++ b/actionpack/lib/action_dispatch/middleware/request_id.rb
@@ -18,7 +18,7 @@ module ActionDispatch
def call(env)
env["action_dispatch.request_id"] = external_request_id(env) || internal_request_id
- @app.call(env).tap { |status, headers, body| headers["X-Request-Id"] = env["action_dispatch.request_id"] }
+ @app.call(env).tap { |_status, headers, _body| headers["X-Request-Id"] = env["action_dispatch.request_id"] }
end
private
diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
index 1e6ed624b0..b9eb8036e9 100644
--- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
@@ -4,36 +4,51 @@ require 'rack/session/cookie'
module ActionDispatch
module Session
- # This cookie-based session store is the Rails default. Sessions typically
- # contain at most a user_id and flash message; both fit within the 4K cookie
- # size limit. Cookie-based sessions are dramatically faster than the
- # alternatives.
+ # This cookie-based session store is the Rails default. It is
+ # dramatically faster than the alternatives.
#
- # If you have more than 4K of session data or don't want your data to be
- # visible to the user, pick another session store.
+ # Sessions typically contain at most a user_id and flash message; both fit
+ # within the 4K cookie size limit. A CookieOverflow exception is raised if
+ # you attempt to store more than 4K of data.
#
- # CookieOverflow is raised if you attempt to store more than 4K of data.
+ # The cookie jar used for storage is automatically configured to be the
+ # best possible option given your application's configuration.
#
- # A message digest is included with the cookie to ensure data integrity:
- # a user cannot alter his +user_id+ without knowing the secret key
- # included in the hash. New apps are generated with a pregenerated secret
- # in config/environment.rb. Set your own for old apps you're upgrading.
+ # If you only have secret_token set, your cookies will be signed, but
+ # not encrypted. This means a user cannot alter his +user_id+ without
+ # knowing your app's secret key, but can easily read his +user_id+. This
+ # was the default for Rails 3 apps.
#
- # Session options:
+ # If you have secret_key_base set, your cookies will be encrypted. This
+ # goes a step further than signed cookies in that encrypted cookies cannot
+ # be altered or read by users. This is the default starting in Rails 4.
#
- # * <tt>:secret</tt>: An application-wide key string. It's important that
- # the secret is not vulnerable to a dictionary attack. Therefore, you
- # should choose a secret consisting of random numbers and letters and
- # more than 30 characters.
+ # If you have both secret_token and secret_key base set, your cookies will
+ # be encrypted, and signed cookies generated by Rails 3 will be
+ # transparently read and encrypted to provide a smooth upgrade path.
#
- # secret: '449fe2e7daee471bffae2fd8dc02313d'
+ # Configure your session store in config/initializers/session_store.rb:
#
- # * <tt>:digest</tt>: The message digest algorithm used to verify session
- # integrity defaults to 'SHA1' but may be any digest provided by OpenSSL,
- # such as 'MD5', 'RIPEMD160', 'SHA256', etc.
+ # Myapp::Application.config.session_store :cookie_store, key: '_your_app_session'
#
- # To generate a secret key for an existing application, run
- # "rake secret" and set the key in config/initializers/secret_token.rb.
+ # Configure your secret key in config/initializers/secret_token.rb:
+ #
+ # Myapp::Application.config.secret_key_base 'secret key'
+ #
+ # To generate a secret key for an existing application, run `rake secret`.
+ #
+ # If you are upgrading an existing Rails 3 app, you should leave your
+ # existing secret_token in place and simply add the new secret_key_base.
+ # Note that you should wait to set secret_key_base until you have 100% of
+ # your userbase on Rails 4 and are reasonably sure you will not need to
+ # rollback to Rails 3. This is because cookies signed based on the new
+ # secret_key_base in Rails 4 are not backwards compatible with Rails 3.
+ # You are free to leave your existing secret_token in place, not set the
+ # new secret_key_base, and ignore the deprecation warnings until you are
+ # reasonably sure that your upgrade is otherwise complete. Additionally,
+ # you should take care to make sure you are not relying on the ability to
+ # decode signed cookies generated by your app in external applications or
+ # Javascript before upgrading.
#
# Note that changing digest or secret invalidates all existing sessions!
class CookieStore < Rack::Session::Abstract::ID
@@ -100,42 +115,7 @@ module ActionDispatch
def cookie_jar(env)
request = ActionDispatch::Request.new(env)
- request.cookie_jar.signed
- end
- end
-
- class EncryptedCookieStore < CookieStore
-
- private
-
- def cookie_jar(env)
- request = ActionDispatch::Request.new(env)
- request.cookie_jar.encrypted
- end
- end
-
- # This cookie store helps you upgrading apps that use +CookieStore+ to the new default +EncryptedCookieStore+
- # To use this CookieStore set
- #
- # Myapp::Application.config.session_store :upgrade_signature_to_encryption_cookie_store, key: '_myapp_session'
- #
- # in your config/initializers/session_store.rb
- #
- # You will also need to add
- #
- # Myapp::Application.config.secret_key_base = 'some secret'
- #
- # in your config/initializers/secret_token.rb, but do not remove +Myapp::Application.config.secret_token = 'some secret'+
- class UpgradeSignatureToEncryptionCookieStore < EncryptedCookieStore
- private
-
- def get_cookie(env)
- signed_using_old_secret_cookie_jar(env)[@key] || cookie_jar(env)[@key]
- end
-
- def signed_using_old_secret_cookie_jar(env)
- request = ActionDispatch::Request.new(env)
- request.cookie_jar.signed_using_old_secret
+ request.cookie_jar.signed_or_encrypted
end
end
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 550f4dbd0d..db219c8fa9 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(object)
- object.to_hash.sort_by { |k, v| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n")
+ object.to_hash.sort_by { |k, _| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n")
end unless self.class.method_defined?(:debug_hash)
%>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb
index 9d947aea40..b181909bff 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb
@@ -1,10 +1,8 @@
<%
- traces = [
- ["Application Trace", @application_trace],
- ["Framework Trace", @framework_trace],
- ["Full Trace", @full_trace]
- ]
- names = traces.collect {|name, trace| name}
+ traces = { "Application Trace" => @application_trace,
+ "Framework Trace" => @framework_trace,
+ "Full Trace" => @full_trace }
+ names = traces.keys
%>
<p><code>Rails.root: <%= defined?(Rails) && Rails.respond_to?(:root) ? Rails.root : "unset" %></code></p>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb
index 63216ef7c5..31f46ee340 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb
@@ -2,7 +2,7 @@
<header>
<h1>
<%= @exception.original_exception.class.to_s %> in
- <%= @request.parameters["controller"].capitalize if @request.parameters["controller"]%>#<%= @request.parameters["action"] %>
+ <%= @request.parameters["controller"].camelize if @request.parameters["controller"] %>#<%= @request.parameters["action"] %>
</h1>
</header>
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index c5f2b33602..80054c8a40 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -10,6 +10,9 @@ module ActionDispatch
module Routing
class Mapper
URL_OPTIONS = [:protocol, :subdomain, :domain, :host, :port]
+ SCOPE_OPTIONS = [:path, :shallow_path, :as, :shallow_prefix, :module,
+ :controller, :path_names, :constraints, :defaults,
+ :shallow, :blocks, :options]
class Constraints #:nodoc:
def self.new(app, constraints, request = Rack::Request)
@@ -58,8 +61,8 @@ module ActionDispatch
@set, @scope, @path, @options = set, scope, path, options
@requirements, @conditions, @defaults = {}, {}, {}
- normalize_path!
normalize_options!
+ normalize_path!
normalize_requirements!
normalize_conditions!
normalize_defaults!
@@ -486,7 +489,7 @@ module ActionDispatch
end
options = app
- app, path = options.find { |k, v| k.respond_to?(:call) }
+ app, path = options.find { |k, _| k.respond_to?(:call) }
options.delete(app) if app
end
@@ -589,8 +592,7 @@ module ActionDispatch
private
def map_method(method, args, &block)
options = args.extract_options!
- options[:via] = method
- options[:path] ||= args.first if args.first.is_a?(String)
+ options[:via] = method
match(*args, options, &block)
self
end
@@ -698,19 +700,21 @@ module ActionDispatch
block, options[:constraints] = options[:constraints], {}
end
- scope_options.each do |option|
- if value = options.delete(option)
+ SCOPE_OPTIONS.each do |option|
+ if option == :blocks
+ value = block
+ elsif option == :options
+ value = options
+ else
+ value = options.delete(option)
+ end
+
+ if value
recover[option] = @scope[option]
@scope[option] = send("merge_#{option}_scope", @scope[option], value)
end
end
- recover[:blocks] = @scope[:blocks]
- @scope[:blocks] = merge_blocks_scope(@scope[:blocks], block)
-
- recover[:options] = @scope[:options]
- @scope[:options] = merge_options_scope(@scope[:options], options)
-
yield
self
ensure
@@ -841,10 +845,6 @@ module ActionDispatch
end
private
- def scope_options #:nodoc:
- @scope_options ||= private_methods.grep(/^merge_(.+)_scope$/) { $1.to_sym }
- end
-
def merge_path_scope(parent, child) #:nodoc:
Mapper.normalize_path("#{parent}/#{child}")
end
@@ -1361,7 +1361,7 @@ module ActionDispatch
def match(path, *rest)
if rest.empty? && Hash === path
options = path
- path, to = options.find { |name, value| name.is_a?(String) }
+ path, to = options.find { |name, _value| name.is_a?(String) }
options[:to] = to
options.delete(path)
paths = [path]
@@ -1370,18 +1370,23 @@ module ActionDispatch
paths = [path] + rest
end
- path_without_format = path.to_s.sub(/\(\.:format\)$/, '')
- if using_match_shorthand?(path_without_format, options)
- options[:to] ||= path_without_format.gsub(%r{^/}, "").sub(%r{/([^/]*)$}, '#\1')
- end
-
options[:anchor] = true unless options.key?(:anchor)
if options[:on] && !VALID_ON_OPTIONS.include?(options[:on])
raise ArgumentError, "Unknown scope #{on.inspect} given to :on"
end
- paths.each { |_path| decomposed_match(_path, options.dup) }
+ paths.each do |_path|
+ route_options = options.dup
+ route_options[:path] ||= _path if _path.is_a?(String)
+
+ path_without_format = _path.to_s.sub(/\(\.:format\)$/, '')
+ if using_match_shorthand?(path_without_format, route_options)
+ route_options[:to] ||= path_without_format.gsub(%r{^/}, "").sub(%r{/([^/]*)$}, '#\1')
+ end
+
+ decomposed_match(_path, route_options)
+ end
self
end
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 7fb4719fa0..d48a83e6c6 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -405,7 +405,7 @@ module ActionDispatch
if name && named_routes[name]
raise ArgumentError, "Invalid route name, already in use: '#{name}' \n" \
- "You may have defined two routes with the same name using the `:as` option, or "
+ "You may have defined two routes with the same name using the `:as` option, or " \
"you may be overriding a route already defined by a resource with the same naming. " \
"For the latter, you can restrict the routes created with `resources` as explained here: \n" \
"http://guides.rubyonrails.org/routing.html#restricting-the-routes-created"
@@ -665,7 +665,7 @@ module ActionDispatch
end
req = @request_class.new(env)
- @router.recognize(req) do |route, matches, params|
+ @router.recognize(req) do |route, _matches, params|
params.merge!(extras)
params.each do |key, value|
if value.is_a?(String)
diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
index 9210bffd1d..496682e8bd 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
@@ -81,7 +81,7 @@ module ActionDispatch
# Load routes.rb if it hasn't been loaded.
generated_path, extra_keys = @routes.generate_extras(options, defaults)
- found_extras = options.reject {|k, v| ! extra_keys.include? k}
+ found_extras = options.reject { |k, _| ! extra_keys.include? k }
msg = message || sprintf("found extras <%s>, not <%s>", found_extras, extras)
assert_equal(extras, found_extras, msg)
@@ -120,7 +120,7 @@ module ActionDispatch
options[:controller] = "/#{controller}"
end
- generate_options = options.dup.delete_if{ |k,v| defaults.key?(k) }
+ generate_options = options.dup.delete_if{ |k, _| defaults.key?(k) }
assert_generates(path.is_a?(Hash) ? path[:path] : path, generate_options, defaults, extras, message)
end
diff --git a/actionpack/lib/action_dispatch/testing/assertions/selector.rb b/actionpack/lib/action_dispatch/testing/assertions/selector.rb
index e481f3b245..3253a3d424 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/selector.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/selector.rb
@@ -377,8 +377,8 @@ module ActionDispatch
node.content.gsub(/<!\[CDATA\[(.*)(\]\]>)?/m) { Rack::Utils.escapeHTML($1) }
end
- selected = elements.map do |_element|
- text = _element.children.select{ |c| not c.tag? }.map{ |c| fix_content[c] }.join
+ selected = elements.map do |elem|
+ text = elem.children.select{ |c| not c.tag? }.map{ |c| fix_content[c] }.join
root = HTML::Document.new(CGI.unescapeHTML("<encoded>#{text}</encoded>")).root
css_select(root, "encoded:root", &block)[0]
end
diff --git a/actionpack/lib/action_dispatch/testing/test_process.rb b/actionpack/lib/action_dispatch/testing/test_process.rb
index e657283cec..630e6a9b78 100644
--- a/actionpack/lib/action_dispatch/testing/test_process.rb
+++ b/actionpack/lib/action_dispatch/testing/test_process.rb
@@ -6,7 +6,7 @@ module ActionDispatch
module TestProcess
def assigns(key = nil)
assigns = {}.with_indifferent_access
- @controller.view_assigns.each {|k, v| assigns.regular_writer(k, v)}
+ @controller.view_assigns.each { |k, v| assigns.regular_writer(k, v) }
key.nil? ? assigns : assigns[key]
end