aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/CHANGELOG.md14
-rw-r--r--activesupport/MIT-LICENSE2
-rw-r--r--activesupport/lib/active_support.rb2
-rw-r--r--activesupport/lib/active_support/cache.rb37
-rw-r--r--activesupport/lib/active_support/core_ext/module/concerning.rb3
-rw-r--r--activesupport/lib/active_support/core_ext/module/delegation.rb7
-rw-r--r--activesupport/lib/active_support/core_ext/object/blank.rb11
-rw-r--r--activesupport/lib/active_support/digest.rb10
-rw-r--r--activesupport/lib/active_support/duration.rb4
-rw-r--r--activesupport/lib/active_support/encrypted_configuration.rb5
-rw-r--r--activesupport/lib/active_support/encrypted_file.rb10
-rw-r--r--activesupport/lib/active_support/message_encryptor.rb4
-rw-r--r--activesupport/lib/active_support/railtie.rb12
-rw-r--r--activesupport/lib/active_support/testing/assertions.rb11
-rw-r--r--activesupport/test/abstract_unit.rb4
-rw-r--r--activesupport/test/cache/behaviors/cache_store_behavior.rb12
-rw-r--r--activesupport/test/core_ext/duration_test.rb2
-rw-r--r--activesupport/test/core_ext/hash_ext_test.rb2
-rw-r--r--activesupport/test/core_ext/object/blank_test.rb4
-rw-r--r--activesupport/test/digest_test.rb2
-rw-r--r--activesupport/test/encrypted_configuration_test.rb6
-rw-r--r--activesupport/test/encrypted_file_test.rb13
-rw-r--r--activesupport/test/test_case_test.rb11
23 files changed, 125 insertions, 63 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index abbadd404f..3f77b191f9 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,10 +1,16 @@
-* Introduced `ActiveSupport::Digest` that allows to specify hash function implementation
- and defaults to `Digest::MD5`.
+* `assert_changes` will always assert that the expression changes,
+ regardless of `from:` and `to:` argument combinations.
- Replaced calls to `::Digest::MD5.hexdigest` with calls to `ActiveSupport::Digest.hexdigest`.
+ *Daniel Ma*
+
+* Allow the hash function used to generate non-sensitive digests, such as the
+ ETag header, to be specified with `config.active_support.hash_digest_class`.
+
+ The object provided must respond to `#hexdigest`, e.g. `Digest::SHA1`.
*Dmitri Dolguikh*
-
+
+
## Rails 5.2.0.beta2 (November 28, 2017) ##
* No changes.
diff --git a/activesupport/MIT-LICENSE b/activesupport/MIT-LICENSE
index 6b3cead1a7..8f769c0767 100644
--- a/activesupport/MIT-LICENSE
+++ b/activesupport/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2005-2017 David Heinemeier Hansson
+Copyright (c) 2005-2018 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index 16b9a5bc1d..a4fb697669 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
#--
-# Copyright (c) 2005-2017 David Heinemeier Hansson
+# Copyright (c) 2005-2018 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb
index 395aa5e8f1..8301b8c7cb 100644
--- a/activesupport/lib/active_support/cache.rb
+++ b/activesupport/lib/active_support/cache.rb
@@ -91,16 +91,11 @@ module ActiveSupport
private
def retrieve_cache_key(key)
case
- when key.respond_to?(:cache_key_with_version)
- key.cache_key_with_version
- when key.respond_to?(:cache_key)
- key.cache_key
- when key.is_a?(Hash)
- key.sort_by { |k, _| k.to_s }.collect { |k, v| "#{k}=#{v}" }.to_param
- when key.respond_to?(:to_a)
- key.to_a.collect { |element| retrieve_cache_key(element) }.to_param
- else
- key.to_param
+ when key.respond_to?(:cache_key_with_version) then key.cache_key_with_version
+ when key.respond_to?(:cache_key) then key.cache_key
+ when key.is_a?(Array) then key.map { |element| retrieve_cache_key(element) }.to_param
+ when key.respond_to?(:to_a) then retrieve_cache_key(key.to_a)
+ else key.to_param
end.to_s
end
@@ -569,7 +564,7 @@ module ActiveSupport
# Expands and namespaces the cache key. May be overridden by
# cache stores to do additional normalization.
def normalize_key(key, options = nil)
- namespace_key Cache.expand_cache_key(key), options
+ namespace_key expanded_key(key), options
end
# Prefix the key with a namespace string:
@@ -596,6 +591,26 @@ module ActiveSupport
end
end
+ # Expands key to be a consistent string value. Invokes +cache_key+ if
+ # object responds to +cache_key+. Otherwise, +to_param+ method will be
+ # called. If the key is a Hash, then keys will be sorted alphabetically.
+ def expanded_key(key)
+ return key.cache_key.to_s if key.respond_to?(:cache_key)
+
+ case key
+ when Array
+ if key.size > 1
+ key = key.collect { |element| expanded_key(element) }
+ else
+ key = key.first
+ end
+ when Hash
+ key = key.sort_by { |k, _| k.to_s }.collect { |k, v| "#{k}=#{v}" }
+ end
+
+ key.to_param
+ end
+
def normalize_version(key, options = nil)
(options && options[:version].try(:to_param)) || expanded_version(key)
end
diff --git a/activesupport/lib/active_support/core_ext/module/concerning.rb b/activesupport/lib/active_support/core_ext/module/concerning.rb
index 800bf213cc..7bbbf321ab 100644
--- a/activesupport/lib/active_support/core_ext/module/concerning.rb
+++ b/activesupport/lib/active_support/core_ext/module/concerning.rb
@@ -30,7 +30,6 @@ class Module
# has_many :events
#
# before_create :track_creation
- # after_destroy :track_deletion
#
# private
# def track_creation
@@ -52,7 +51,6 @@ class Module
# included do
# has_many :events
# before_create :track_creation
- # after_destroy :track_deletion
# end
#
# private
@@ -90,7 +88,6 @@ class Module
# included do
# has_many :events
# before_create :track_creation
- # after_destroy :track_deletion
# end
#
# private
diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb
index a77f903db5..4310df3024 100644
--- a/activesupport/lib/active_support/core_ext/module/delegation.rb
+++ b/activesupport/lib/active_support/core_ext/module/delegation.rb
@@ -115,11 +115,8 @@ class Module
# invoice.customer_address # => 'Vimmersvej 13'
#
# If the target is +nil+ and does not respond to the delegated method a
- # +Module::DelegationError+ is raised, as with any other value. Sometimes,
- # however, it makes sense to be robust to that situation and that is the
- # purpose of the <tt>:allow_nil</tt> option: If the target is not +nil+, or it
- # is and responds to the method, everything works as usual. But if it is +nil+
- # and does not respond to the delegated method, +nil+ is returned.
+ # +Module::DelegationError+ is raised. If you wish to instead return +nil+,
+ # use the <tt>:allow_nil</tt> option.
#
# class User < ActiveRecord::Base
# has_one :profile
diff --git a/activesupport/lib/active_support/core_ext/object/blank.rb b/activesupport/lib/active_support/core_ext/object/blank.rb
index e42ad852dd..2ca431ab10 100644
--- a/activesupport/lib/active_support/core_ext/object/blank.rb
+++ b/activesupport/lib/active_support/core_ext/object/blank.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require "active_support/core_ext/regexp"
+require "concurrent/map"
class Object
# An object is blank if it's false, empty, or a whitespace string.
@@ -102,6 +103,9 @@ end
class String
BLANK_RE = /\A[[:space:]]*\z/
+ ENCODED_BLANKS = Concurrent::Map.new do |h, enc|
+ h[enc] = Regexp.new(BLANK_RE.source.encode(enc), BLANK_RE.options | Regexp::FIXEDENCODING)
+ end
# A string is blank if it's empty or contains whitespaces only:
#
@@ -119,7 +123,12 @@ class String
# The regexp that matches blank strings is expensive. For the case of empty
# strings we can speed up this method (~3.5x) with an empty? call. The
# penalty for the rest of strings is marginal.
- empty? || BLANK_RE.match?(self)
+ empty? ||
+ begin
+ BLANK_RE.match?(self)
+ rescue Encoding::CompatibilityError
+ ENCODED_BLANKS[self.encoding].match?(self)
+ end
end
end
diff --git a/activesupport/lib/active_support/digest.rb b/activesupport/lib/active_support/digest.rb
index d77eeb072b..fba10fbdcf 100644
--- a/activesupport/lib/active_support/digest.rb
+++ b/activesupport/lib/active_support/digest.rb
@@ -13,16 +13,8 @@ module ActiveSupport
end
def hexdigest(arg)
- new.hexdigest(arg)
+ hash_digest_class.hexdigest(arg)[0...32]
end
end
-
- def initialize(digest_class: nil)
- @digest_class = digest_class || self.class.hash_digest_class
- end
-
- def hexdigest(arg)
- @digest_class.hexdigest(arg).truncate(32)
- end
end
end
diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb
index 1af3411a8a..fe1058762b 100644
--- a/activesupport/lib/active_support/duration.rb
+++ b/activesupport/lib/active_support/duration.rb
@@ -194,7 +194,6 @@ module ActiveSupport
end
parts[:seconds] = remainder
- parts.reject! { |k, v| v.zero? }
new(value, parts)
end
@@ -211,6 +210,7 @@ module ActiveSupport
def initialize(value, parts) #:nodoc:
@value, @parts = value, parts.to_h
@parts.default = 0
+ @parts.reject! { |k, v| v.zero? }
end
def coerce(other) #:nodoc:
@@ -370,6 +370,8 @@ module ActiveSupport
alias :before :ago
def inspect #:nodoc:
+ return "0 seconds" if parts.empty?
+
parts.
reduce(::Hash.new(0)) { |h, (l, r)| h[l] += r; h }.
sort_by { |unit, _ | PARTS.index(unit) }.
diff --git a/activesupport/lib/active_support/encrypted_configuration.rb b/activesupport/lib/active_support/encrypted_configuration.rb
index c52d3869de..dab953d5d5 100644
--- a/activesupport/lib/active_support/encrypted_configuration.rb
+++ b/activesupport/lib/active_support/encrypted_configuration.rb
@@ -11,8 +11,9 @@ module ActiveSupport
delegate :[], :fetch, to: :config
delegate_missing_to :options
- def initialize(config_path:, key_path:, env_key:)
- super content_path: config_path, key_path: key_path, env_key: env_key
+ def initialize(config_path:, key_path:, env_key:, raise_if_missing_key:)
+ super content_path: config_path, key_path: key_path,
+ env_key: env_key, raise_if_missing_key: raise_if_missing_key
end
# Allow a config to be started without a file present
diff --git a/activesupport/lib/active_support/encrypted_file.rb b/activesupport/lib/active_support/encrypted_file.rb
index 3d1455fb95..671b6b6a69 100644
--- a/activesupport/lib/active_support/encrypted_file.rb
+++ b/activesupport/lib/active_support/encrypted_file.rb
@@ -26,11 +26,11 @@ module ActiveSupport
end
- attr_reader :content_path, :key_path, :env_key
+ attr_reader :content_path, :key_path, :env_key, :raise_if_missing_key
- def initialize(content_path:, key_path:, env_key:)
+ def initialize(content_path:, key_path:, env_key:, raise_if_missing_key:)
@content_path, @key_path = Pathname.new(content_path), Pathname.new(key_path)
- @env_key = env_key
+ @env_key, @raise_if_missing_key = env_key, raise_if_missing_key
end
def key
@@ -38,7 +38,7 @@ module ActiveSupport
end
def read
- if content_path.exist?
+ if !key.nil? && content_path.exist?
decrypt content_path.binread
else
raise MissingContentError, content_path
@@ -93,7 +93,7 @@ module ActiveSupport
end
def handle_missing_key
- raise MissingKeyError, key_path: key_path, env_key: env_key
+ raise MissingKeyError, key_path: key_path, env_key: env_key if raise_if_missing_key
end
end
end
diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb
index 27fd061947..5236c776dd 100644
--- a/activesupport/lib/active_support/message_encryptor.rb
+++ b/activesupport/lib/active_support/message_encryptor.rb
@@ -81,9 +81,9 @@ module ActiveSupport
class MessageEncryptor
prepend Messages::Rotator::Encryptor
- class << self
- attr_accessor :use_authenticated_message_encryption #:nodoc:
+ cattr_accessor :use_authenticated_message_encryption, instance_accessor: false, default: false
+ class << self
def default_cipher #:nodoc:
if use_authenticated_message_encryption
"aes-256-gcm"
diff --git a/activesupport/lib/active_support/railtie.rb b/activesupport/lib/active_support/railtie.rb
index 3488721df9..6b8fa676a9 100644
--- a/activesupport/lib/active_support/railtie.rb
+++ b/activesupport/lib/active_support/railtie.rb
@@ -10,9 +10,11 @@ module ActiveSupport
config.eager_load_namespaces << ActiveSupport
initializer "active_support.set_authenticated_message_encryption" do |app|
- if app.config.active_support.respond_to?(:use_authenticated_message_encryption)
- ActiveSupport::MessageEncryptor.use_authenticated_message_encryption =
- app.config.active_support.use_authenticated_message_encryption
+ config.after_initialize do
+ unless app.config.active_support.use_authenticated_message_encryption.nil?
+ ActiveSupport::MessageEncryptor.use_authenticated_message_encryption =
+ app.config.active_support.use_authenticated_message_encryption
+ end
end
end
@@ -68,9 +70,9 @@ module ActiveSupport
end
initializer "active_support.set_hash_digest_class" do |app|
- if app.config.active_support.respond_to?(:use_hash_digest_class) && app.config.active_support.use_hash_digest_class
+ if app.config.active_support.hash_digest_class
ActiveSupport::Digest.hash_digest_class =
- app.config.active_support.use_hash_digest_class
+ app.config.active_support.hash_digest_class
end
end
end
diff --git a/activesupport/lib/active_support/testing/assertions.rb b/activesupport/lib/active_support/testing/assertions.rb
index b24aa36ede..6f69c48674 100644
--- a/activesupport/lib/active_support/testing/assertions.rb
+++ b/activesupport/lib/active_support/testing/assertions.rb
@@ -156,11 +156,12 @@ module ActiveSupport
after = exp.call
- if to == UNTRACKED
- error = "#{expression.inspect} didn't change"
- error = "#{message}.\n#{error}" if message
- assert before != after, error
- else
+ error = "#{expression.inspect} didn't change"
+ error = "#{error}. It was already #{to}" if before == to
+ error = "#{message}.\n#{error}" if message
+ assert before != after, error
+
+ unless to == UNTRACKED
error = "#{expression.inspect} didn't change to #{to}"
error = "#{message}.\n#{error}" if message
assert to === after, error
diff --git a/activesupport/test/abstract_unit.rb b/activesupport/test/abstract_unit.rb
index 3ac11e0fe0..f214898145 100644
--- a/activesupport/test/abstract_unit.rb
+++ b/activesupport/test/abstract_unit.rb
@@ -38,4 +38,8 @@ class ActiveSupport::TestCase
private def jruby_skip(message = "")
skip message if defined?(JRUBY_VERSION)
end
+
+ def frozen_error_class
+ Object.const_defined?(:FrozenError) ? FrozenError : RuntimeError
+ end
end
diff --git a/activesupport/test/cache/behaviors/cache_store_behavior.rb b/activesupport/test/cache/behaviors/cache_store_behavior.rb
index 73a9b2a71c..bdc689b8b4 100644
--- a/activesupport/test/cache/behaviors/cache_store_behavior.rb
+++ b/activesupport/test/cache/behaviors/cache_store_behavior.rb
@@ -174,6 +174,18 @@ module CacheStoreBehavior
assert_equal "bar", @cache.read("foo")
end
+ def test_unversioned_cache_key
+ obj = Object.new
+ def obj.cache_key
+ "foo"
+ end
+ def obj.cache_key_with_version
+ "foo-v1"
+ end
+ @cache.write(obj, "bar")
+ assert_equal "bar", @cache.read("foo")
+ end
+
def test_array_as_cache_key
@cache.write([:fu, "foo"], "bar")
assert_equal "bar", @cache.read("fu/foo")
diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb
index dbee543644..4a02f27def 100644
--- a/activesupport/test/core_ext/duration_test.rb
+++ b/activesupport/test/core_ext/duration_test.rb
@@ -71,6 +71,8 @@ class DurationTest < ActiveSupport::TestCase
assert_equal "7 days", 7.days.inspect
assert_equal "1 week", 1.week.inspect
assert_equal "2 weeks", 1.fortnight.inspect
+ assert_equal "0 seconds", (10 % 5.seconds).inspect
+ assert_equal "10 minutes", (10.minutes + 0.seconds).inspect
end
def test_inspect_locale
diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb
index 746d7ad416..17952e9fc7 100644
--- a/activesupport/test/core_ext/hash_ext_test.rb
+++ b/activesupport/test/core_ext/hash_ext_test.rb
@@ -446,7 +446,7 @@ class HashExtTest < ActiveSupport::TestCase
original.freeze
assert_nothing_raised { original.except(:a) }
- assert_raise(RuntimeError) { original.except!(:a) }
+ assert_raise(frozen_error_class) { original.except!(:a) }
end
def test_except_does_not_delete_values_in_original
diff --git a/activesupport/test/core_ext/object/blank_test.rb b/activesupport/test/core_ext/object/blank_test.rb
index 749e59ec00..954f415383 100644
--- a/activesupport/test/core_ext/object/blank_test.rb
+++ b/activesupport/test/core_ext/object/blank_test.rb
@@ -16,8 +16,8 @@ class BlankTest < ActiveSupport::TestCase
end
end
- BLANK = [ EmptyTrue.new, nil, false, "", " ", " \n\t \r ", " ", "\u00a0", [], {} ]
- NOT = [ EmptyFalse.new, Object.new, true, 0, 1, "a", [nil], { nil => 0 }, Time.now ]
+ BLANK = [ EmptyTrue.new, nil, false, "", " ", " \n\t \r ", " ", "\u00a0", [], {}, " ".encode("UTF-16LE") ]
+ NOT = [ EmptyFalse.new, Object.new, true, 0, 1, "a", [nil], { nil => 0 }, Time.now, "my value".encode("UTF-16LE") ]
def test_blank
BLANK.each { |v| assert_equal true, v.blank?, "#{v.inspect} should be blank" }
diff --git a/activesupport/test/digest_test.rb b/activesupport/test/digest_test.rb
index 5dec75b9fe..83ff2a8d83 100644
--- a/activesupport/test/digest_test.rb
+++ b/activesupport/test/digest_test.rb
@@ -16,7 +16,7 @@ class DigestTest < ActiveSupport::TestCase
digest = ActiveSupport::Digest.hexdigest("hello friend")
assert_equal 32, digest.length
- assert_equal ::Digest::SHA1.hexdigest("hello friend").truncate(32), digest
+ assert_equal ::Digest::SHA1.hexdigest("hello friend")[0...32], digest
ensure
ActiveSupport::Digest.hash_digest_class = original_hash_digest_class
end
diff --git a/activesupport/test/encrypted_configuration_test.rb b/activesupport/test/encrypted_configuration_test.rb
index 0bc915be82..93ccf457de 100644
--- a/activesupport/test/encrypted_configuration_test.rb
+++ b/activesupport/test/encrypted_configuration_test.rb
@@ -10,8 +10,10 @@ class EncryptedConfigurationTest < ActiveSupport::TestCase
@credentials_key_path = File.join(Dir.tmpdir, "master.key")
File.write(@credentials_key_path, ActiveSupport::EncryptedConfiguration.generate_key)
- @credentials = ActiveSupport::EncryptedConfiguration.new \
- config_path: @credentials_config_path, key_path: @credentials_key_path, env_key: "RAILS_MASTER_KEY"
+ @credentials = ActiveSupport::EncryptedConfiguration.new(
+ config_path: @credentials_config_path, key_path: @credentials_key_path,
+ env_key: "RAILS_MASTER_KEY", raise_if_missing_key: true
+ )
end
teardown do
diff --git a/activesupport/test/encrypted_file_test.rb b/activesupport/test/encrypted_file_test.rb
index 7259726d08..ba3bbef903 100644
--- a/activesupport/test/encrypted_file_test.rb
+++ b/activesupport/test/encrypted_file_test.rb
@@ -12,8 +12,9 @@ class EncryptedFileTest < ActiveSupport::TestCase
@key_path = File.join(Dir.tmpdir, "content.txt.key")
File.write(@key_path, ActiveSupport::EncryptedFile.generate_key)
- @encrypted_file = ActiveSupport::EncryptedFile.new \
- content_path: @content_path, key_path: @key_path, env_key: "CONTENT_KEY"
+ @encrypted_file = ActiveSupport::EncryptedFile.new(
+ content_path: @content_path, key_path: @key_path, env_key: "CONTENT_KEY", raise_if_missing_key: true
+ )
end
teardown do
@@ -47,4 +48,12 @@ class EncryptedFileTest < ActiveSupport::TestCase
assert_equal "#{@content} and went by the lake", @encrypted_file.read
end
+
+ test "raise MissingKeyError when key is missing" do
+ assert_raise(ActiveSupport::EncryptedFile::MissingKeyError) do
+ ActiveSupport::EncryptedFile.new(
+ content_path: @content_path, key_path: "", env_key: "", raise_if_missing_key: true
+ ).read
+ end
+ end
end
diff --git a/activesupport/test/test_case_test.rb b/activesupport/test/test_case_test.rb
index 84e4953fe2..79b75a001a 100644
--- a/activesupport/test/test_case_test.rb
+++ b/activesupport/test/test_case_test.rb
@@ -156,6 +156,16 @@ class AssertDifferenceTest < ActiveSupport::TestCase
end
end
+ def test_assert_changes_with_to_option_but_no_change_has_special_message
+ error = assert_raises Minitest::Assertion do
+ assert_changes "@object.num", to: 0 do
+ # no changes
+ end
+ end
+
+ assert_equal "\"@object.num\" didn't change. It was already 0", error.message
+ end
+
def test_assert_changes_with_wrong_to_option
assert_raises Minitest::Assertion do
assert_changes "@object.num", to: 2 do
@@ -218,6 +228,7 @@ class AssertDifferenceTest < ActiveSupport::TestCase
def test_assert_changes_with_message
error = assert_raises Minitest::Assertion do
assert_changes "@object.num", "@object.num should 1", to: 1 do
+ @object.decrement
end
end