activesupport 4.2.11.3 → 5.0.7.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +678 -348
- data/MIT-LICENSE +2 -2
- data/README.rdoc +2 -3
- data/lib/active_support/array_inquirer.rb +44 -0
- data/lib/active_support/backtrace_cleaner.rb +1 -1
- data/lib/active_support/benchmarkable.rb +1 -1
- data/lib/active_support/cache/file_store.rb +36 -22
- data/lib/active_support/cache/mem_cache_store.rb +63 -54
- data/lib/active_support/cache/memory_store.rb +16 -21
- data/lib/active_support/cache/null_store.rb +1 -4
- data/lib/active_support/cache/strategy/local_cache.rb +31 -20
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +4 -4
- data/lib/active_support/cache.rb +71 -87
- data/lib/active_support/callbacks.rb +109 -113
- data/lib/active_support/concern.rb +1 -1
- data/lib/active_support/concurrency/latch.rb +11 -12
- data/lib/active_support/concurrency/share_lock.rb +226 -0
- data/lib/active_support/configurable.rb +1 -0
- data/lib/active_support/core_ext/array/access.rb +27 -1
- data/lib/active_support/core_ext/array/conversions.rb +6 -4
- data/lib/active_support/core_ext/array/grouping.rb +9 -18
- data/lib/active_support/core_ext/array/inquiry.rb +17 -0
- data/lib/active_support/core_ext/array/wrap.rb +5 -4
- data/lib/active_support/core_ext/array.rb +1 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -10
- data/lib/active_support/core_ext/class/attribute.rb +10 -9
- data/lib/active_support/core_ext/class/subclasses.rb +3 -2
- data/lib/active_support/core_ext/class.rb +0 -1
- data/lib/active_support/core_ext/date/blank.rb +12 -0
- data/lib/active_support/core_ext/date/calculations.rb +1 -1
- data/lib/active_support/core_ext/date/conversions.rb +7 -6
- data/lib/active_support/core_ext/date.rb +1 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +100 -27
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +0 -1
- data/lib/active_support/core_ext/date_and_time/zones.rb +3 -4
- data/lib/active_support/core_ext/date_time/blank.rb +12 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +14 -8
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
- data/lib/active_support/core_ext/date_time.rb +1 -1
- data/lib/active_support/core_ext/enumerable.rb +75 -25
- data/lib/active_support/core_ext/file/atomic.rb +30 -25
- data/lib/active_support/core_ext/hash/conversions.rb +22 -2
- data/lib/active_support/core_ext/hash/deep_merge.rb +1 -1
- data/lib/active_support/core_ext/hash/except.rb +9 -8
- data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -1
- data/lib/active_support/core_ext/hash/keys.rb +25 -21
- data/lib/active_support/core_ext/hash/slice.rb +1 -1
- data/lib/active_support/core_ext/hash/transform_values.rb +11 -5
- data/lib/active_support/core_ext/integer/time.rb +2 -2
- data/lib/active_support/core_ext/kernel/concern.rb +2 -0
- data/lib/active_support/core_ext/kernel/debugger.rb +3 -10
- data/lib/active_support/core_ext/kernel/reporting.rb +2 -84
- data/lib/active_support/core_ext/kernel.rb +0 -1
- data/lib/active_support/core_ext/load_error.rb +5 -2
- data/lib/active_support/core_ext/marshal.rb +7 -9
- data/lib/active_support/core_ext/module/aliasing.rb +6 -1
- data/lib/active_support/core_ext/module/anonymous.rb +10 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -5
- data/lib/active_support/core_ext/module/attribute_accessors.rb +15 -15
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
- data/lib/active_support/core_ext/module/concerning.rb +4 -4
- data/lib/active_support/core_ext/module/delegation.rb +11 -20
- data/lib/active_support/core_ext/module/deprecation.rb +2 -2
- data/lib/active_support/core_ext/module/introspection.rb +8 -2
- data/lib/active_support/core_ext/module/method_transplanting.rb +3 -13
- data/lib/active_support/core_ext/module/qualified_const.rb +30 -12
- data/lib/active_support/core_ext/module/remove_method.rb +23 -0
- data/lib/active_support/core_ext/module.rb +1 -0
- data/lib/active_support/core_ext/name_error.rb +15 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +20 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +78 -77
- data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
- data/lib/active_support/core_ext/numeric/time.rb +26 -6
- data/lib/active_support/core_ext/numeric.rb +1 -0
- data/lib/active_support/core_ext/object/blank.rb +15 -3
- data/lib/active_support/core_ext/object/deep_dup.rb +10 -3
- data/lib/active_support/core_ext/object/duplicable.rb +7 -12
- data/lib/active_support/core_ext/object/inclusion.rb +2 -2
- data/lib/active_support/core_ext/object/instance_variables.rb +1 -1
- data/lib/active_support/core_ext/object/json.rb +15 -7
- data/lib/active_support/core_ext/object/to_query.rb +1 -1
- data/lib/active_support/core_ext/object/try.rb +67 -21
- data/lib/active_support/core_ext/object/with_options.rb +1 -1
- data/lib/active_support/core_ext/object.rb +0 -1
- data/lib/active_support/core_ext/range/conversions.rb +18 -6
- data/lib/active_support/core_ext/range/each.rb +16 -18
- data/lib/active_support/core_ext/range/include_range.rb +20 -20
- data/lib/active_support/core_ext/securerandom.rb +23 -0
- data/lib/active_support/core_ext/string/behavior.rb +1 -1
- data/lib/active_support/core_ext/string/conversions.rb +3 -2
- data/lib/active_support/core_ext/string/filters.rb +1 -2
- data/lib/active_support/core_ext/string/inflections.rb +32 -5
- data/lib/active_support/core_ext/string/multibyte.rb +11 -7
- data/lib/active_support/core_ext/string/output_safety.rb +12 -14
- data/lib/active_support/core_ext/string/strip.rb +3 -6
- data/lib/active_support/core_ext/struct.rb +3 -6
- data/lib/active_support/core_ext/time/calculations.rb +18 -9
- data/lib/active_support/core_ext/time/conversions.rb +4 -2
- data/lib/active_support/core_ext/time/marshal.rb +2 -29
- data/lib/active_support/core_ext/time/zones.rb +36 -4
- data/lib/active_support/core_ext/time.rb +0 -1
- data/lib/active_support/core_ext/uri.rb +1 -3
- data/lib/active_support/core_ext.rb +2 -1
- data/lib/active_support/dependencies/interlock.rb +55 -0
- data/lib/active_support/dependencies.rb +88 -95
- data/lib/active_support/deprecation/behaviors.rb +15 -1
- data/lib/active_support/deprecation/instance_delegator.rb +13 -0
- data/lib/active_support/deprecation/method_wrappers.rb +42 -16
- data/lib/active_support/deprecation/proxy_wrappers.rb +47 -24
- data/lib/active_support/deprecation/reporting.rb +23 -5
- data/lib/active_support/deprecation.rb +1 -1
- data/lib/active_support/duration/iso8601_parser.rb +122 -0
- data/lib/active_support/duration/iso8601_serializer.rb +51 -0
- data/lib/active_support/duration.rb +90 -15
- data/lib/active_support/evented_file_update_checker.rb +199 -0
- data/lib/active_support/execution_wrapper.rb +126 -0
- data/lib/active_support/executor.rb +6 -0
- data/lib/active_support/file_update_checker.rb +23 -3
- data/lib/active_support/gem_version.rb +5 -5
- data/lib/active_support/gzip.rb +1 -1
- data/lib/active_support/hash_with_indifferent_access.rb +40 -11
- data/lib/active_support/i18n_railtie.rb +25 -4
- data/lib/active_support/inflector/inflections.rb +36 -5
- data/lib/active_support/inflector/methods.rb +97 -90
- data/lib/active_support/inflector/transliterate.rb +36 -21
- data/lib/active_support/json/decoding.rb +11 -10
- data/lib/active_support/json/encoding.rb +1 -51
- data/lib/active_support/key_generator.rb +7 -9
- data/lib/active_support/lazy_load_hooks.rb +46 -18
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber/test_helper.rb +3 -3
- data/lib/active_support/log_subscriber.rb +1 -1
- data/lib/active_support/logger.rb +3 -4
- data/lib/active_support/logger_silence.rb +2 -1
- data/lib/active_support/logger_thread_safe_level.rb +2 -3
- data/lib/active_support/message_encryptor.rb +7 -7
- data/lib/active_support/message_verifier.rb +70 -8
- data/lib/active_support/multibyte/chars.rb +12 -3
- data/lib/active_support/multibyte/unicode.rb +44 -21
- data/lib/active_support/notifications/fanout.rb +5 -5
- data/lib/active_support/notifications/instrumenter.rb +20 -2
- data/lib/active_support/notifications.rb +2 -2
- data/lib/active_support/number_helper/number_to_currency_converter.rb +7 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +8 -3
- data/lib/active_support/number_helper/number_to_human_converter.rb +6 -4
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -2
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +11 -2
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +30 -25
- data/lib/active_support/number_helper.rb +90 -67
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +15 -1
- data/lib/active_support/per_thread_registry.rb +3 -0
- data/lib/active_support/rails.rb +2 -2
- data/lib/active_support/railtie.rb +6 -1
- data/lib/active_support/reloader.rb +129 -0
- data/lib/active_support/rescuable.rb +101 -47
- data/lib/active_support/string_inquirer.rb +1 -1
- data/lib/active_support/subscriber.rb +5 -10
- data/lib/active_support/tagged_logging.rb +8 -7
- data/lib/active_support/test_case.rb +17 -29
- data/lib/active_support/testing/assertions.rb +15 -13
- data/lib/active_support/testing/deprecation.rb +9 -8
- data/lib/active_support/testing/file_fixtures.rb +34 -0
- data/lib/active_support/testing/isolation.rb +22 -8
- data/lib/active_support/testing/method_call_assertions.rb +41 -0
- data/lib/active_support/testing/stream.rb +42 -0
- data/lib/active_support/testing/time_helpers.rb +3 -1
- data/lib/active_support/time_with_zone.rb +123 -33
- data/lib/active_support/values/time_zone.rb +101 -47
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/xml_mini/jdom.rb +1 -1
- data/lib/active_support/xml_mini/libxml.rb +2 -2
- data/lib/active_support/xml_mini/nokogiri.rb +2 -2
- data/lib/active_support.rb +11 -6
- metadata +36 -17
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
- data/lib/active_support/core_ext/date_time/zones.rb +0 -6
- data/lib/active_support/core_ext/object/itself.rb +0 -15
- data/lib/active_support/core_ext/thread.rb +0 -86
@@ -20,29 +20,57 @@ module ActiveSupport
|
|
20
20
|
# +activerecord/lib/active_record/base.rb+ is:
|
21
21
|
#
|
22
22
|
# ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Base)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
23
|
+
module LazyLoadHooks
|
24
|
+
def self.extended(base) # :nodoc:
|
25
|
+
base.class_eval do
|
26
|
+
@load_hooks = Hash.new { |h, k| h[k] = [] }
|
27
|
+
@loaded = Hash.new { |h, k| h[k] = [] }
|
28
|
+
@run_once = Hash.new { |h, k| h[k] = [] }
|
29
|
+
end
|
29
30
|
end
|
30
31
|
|
31
|
-
|
32
|
-
|
32
|
+
# Declares a block that will be executed when a Rails component is fully
|
33
|
+
# loaded.
|
34
|
+
#
|
35
|
+
# Options:
|
36
|
+
#
|
37
|
+
# * <tt>:yield</tt> - Yields the object that run_load_hooks to +block+.
|
38
|
+
# * <tt>:run_once</tt> - Given +block+ will run only once.
|
39
|
+
def on_load(name, options = {}, &block)
|
40
|
+
@loaded[name].each do |base|
|
41
|
+
execute_hook(name, base, options, block)
|
42
|
+
end
|
33
43
|
|
34
|
-
|
35
|
-
if options[:yield]
|
36
|
-
block.call(base)
|
37
|
-
else
|
38
|
-
base.instance_eval(&block)
|
44
|
+
@load_hooks[name] << [block, options]
|
39
45
|
end
|
40
|
-
end
|
41
46
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
47
|
+
def run_load_hooks(name, base = Object)
|
48
|
+
@loaded[name] << base
|
49
|
+
@load_hooks[name].each do |hook, options|
|
50
|
+
execute_hook(name, base, options, hook)
|
51
|
+
end
|
46
52
|
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def with_execution_control(name, block, once)
|
57
|
+
unless @run_once[name].include?(block)
|
58
|
+
@run_once[name] << block if once
|
59
|
+
|
60
|
+
yield
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def execute_hook(name, base, options, block)
|
65
|
+
with_execution_control(name, block, options[:run_once]) do
|
66
|
+
if options[:yield]
|
67
|
+
block.call(base)
|
68
|
+
else
|
69
|
+
base.instance_eval(&block)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
47
73
|
end
|
74
|
+
|
75
|
+
extend LazyLoadHooks
|
48
76
|
end
|
@@ -10,7 +10,7 @@ module ActiveSupport
|
|
10
10
|
# class SyncLogSubscriberTest < ActiveSupport::TestCase
|
11
11
|
# include ActiveSupport::LogSubscriber::TestHelper
|
12
12
|
#
|
13
|
-
#
|
13
|
+
# setup do
|
14
14
|
# ActiveRecord::LogSubscriber.attach_to(:active_record)
|
15
15
|
# end
|
16
16
|
#
|
@@ -33,7 +33,7 @@ module ActiveSupport
|
|
33
33
|
# you can collect them doing @logger.logged(level), where level is the level
|
34
34
|
# used in logging, like info, debug, warn and so on.
|
35
35
|
module TestHelper
|
36
|
-
def setup
|
36
|
+
def setup # :nodoc:
|
37
37
|
@logger = MockLogger.new
|
38
38
|
@notifier = ActiveSupport::Notifications::Fanout.new
|
39
39
|
|
@@ -44,7 +44,7 @@ module ActiveSupport
|
|
44
44
|
ActiveSupport::Notifications.notifier = @notifier
|
45
45
|
end
|
46
46
|
|
47
|
-
def teardown
|
47
|
+
def teardown # :nodoc:
|
48
48
|
set_logger(nil)
|
49
49
|
ActiveSupport::Notifications.notifier = @old_notifier
|
50
50
|
end
|
@@ -95,7 +95,7 @@ module ActiveSupport
|
|
95
95
|
METHOD
|
96
96
|
end
|
97
97
|
|
98
|
-
# Set color by using a
|
98
|
+
# Set color by using a symbol or one of the defined constants. If a third
|
99
99
|
# option is set to +true+, it also adds bold to the string. This is based
|
100
100
|
# on the Highline implementation and will automatically append CLEAR to the
|
101
101
|
# end of the returned String.
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'active_support/core_ext/module/attribute_accessors'
|
2
1
|
require 'active_support/logger_silence'
|
3
2
|
require 'active_support/logger_thread_safe_level'
|
4
3
|
require 'logger'
|
@@ -58,16 +57,16 @@ module ActiveSupport
|
|
58
57
|
end
|
59
58
|
|
60
59
|
define_method(:silence) do |level = Logger::ERROR, &block|
|
61
|
-
if logger.respond_to?(:silence)
|
60
|
+
if logger.respond_to?(:silence)
|
62
61
|
logger.silence(level) do
|
63
|
-
if
|
62
|
+
if defined?(super)
|
64
63
|
super(level, &block)
|
65
64
|
else
|
66
65
|
block.call(self)
|
67
66
|
end
|
68
67
|
end
|
69
68
|
else
|
70
|
-
if
|
69
|
+
if defined?(super)
|
71
70
|
super(level, &block)
|
72
71
|
else
|
73
72
|
block.call(self)
|
@@ -1,12 +1,11 @@
|
|
1
1
|
require 'active_support/concern'
|
2
|
-
require 'thread_safe'
|
3
2
|
|
4
3
|
module ActiveSupport
|
5
|
-
module LoggerThreadSafeLevel
|
4
|
+
module LoggerThreadSafeLevel # :nodoc:
|
6
5
|
extend ActiveSupport::Concern
|
7
6
|
|
8
7
|
def after_initialize
|
9
|
-
@local_levels =
|
8
|
+
@local_levels = Concurrent::Map.new(initial_capacity: 2)
|
10
9
|
end
|
11
10
|
|
12
11
|
def local_log_id
|
@@ -13,10 +13,10 @@ module ActiveSupport
|
|
13
13
|
# where you don't want users to be able to determine the value of the payload.
|
14
14
|
#
|
15
15
|
# salt = SecureRandom.random_bytes(64)
|
16
|
-
# key = ActiveSupport::KeyGenerator.new('password').generate_key(salt) # => "\x89\xE0\x156\xAC..."
|
17
|
-
# crypt = ActiveSupport::MessageEncryptor.new(key)
|
18
|
-
# encrypted_data = crypt.encrypt_and_sign('my secret data')
|
19
|
-
# crypt.decrypt_and_verify(encrypted_data)
|
16
|
+
# key = ActiveSupport::KeyGenerator.new('password').generate_key(salt, 32) # => "\x89\xE0\x156\xAC..."
|
17
|
+
# crypt = ActiveSupport::MessageEncryptor.new(key) # => #<ActiveSupport::MessageEncryptor ...>
|
18
|
+
# encrypted_data = crypt.encrypt_and_sign('my secret data') # => "NlFBTTMwOUV5UlA1QlNEN2xkY2d6eThYWWh..."
|
19
|
+
# crypt.decrypt_and_verify(encrypted_data) # => "my secret data"
|
20
20
|
class MessageEncryptor
|
21
21
|
DEFAULT_CIPHER = "aes-256-cbc"
|
22
22
|
|
@@ -36,8 +36,8 @@ module ActiveSupport
|
|
36
36
|
# Initialize a new MessageEncryptor. +secret+ must be at least as long as
|
37
37
|
# the cipher key size. For the default 'aes-256-cbc' cipher, this is 256
|
38
38
|
# bits. If you are using a user-entered secret, you can generate a suitable
|
39
|
-
# key
|
40
|
-
#
|
39
|
+
# key by using <tt>ActiveSupport::KeyGenerator</tt> or a similar key
|
40
|
+
# derivation function.
|
41
41
|
#
|
42
42
|
# Options:
|
43
43
|
# * <tt>:cipher</tt> - Cipher to use. Can be any cipher returned by
|
@@ -89,7 +89,7 @@ module ActiveSupport
|
|
89
89
|
|
90
90
|
def _decrypt(encrypted_message)
|
91
91
|
cipher = new_cipher
|
92
|
-
encrypted_data, iv = encrypted_message.split("--").map {|v| ::Base64.strict_decode64(v)}
|
92
|
+
encrypted_data, iv = encrypted_message.split("--".freeze).map {|v| ::Base64.strict_decode64(v)}
|
93
93
|
|
94
94
|
cipher.decrypt
|
95
95
|
cipher.key = @secret
|
@@ -15,7 +15,7 @@ module ActiveSupport
|
|
15
15
|
# In the authentication filter:
|
16
16
|
#
|
17
17
|
# id, time = @verifier.verify(cookies[:remember_me])
|
18
|
-
# if
|
18
|
+
# if Time.now < time
|
19
19
|
# self.current_user = User.find(id)
|
20
20
|
# end
|
21
21
|
#
|
@@ -24,6 +24,12 @@ module ActiveSupport
|
|
24
24
|
# hash upon initialization:
|
25
25
|
#
|
26
26
|
# @verifier = ActiveSupport::MessageVerifier.new('s3Krit', serializer: YAML)
|
27
|
+
#
|
28
|
+
# +MessageVerifier+ creates HMAC signatures using SHA1 hash algorithm by default.
|
29
|
+
# If you want to use a different hash algorithm, you can change it by providing
|
30
|
+
# `:digest` key as an option while initializing the verifier:
|
31
|
+
#
|
32
|
+
# @verifier = ActiveSupport::MessageVerifier.new('s3Krit', digest: 'SHA256')
|
27
33
|
class MessageVerifier
|
28
34
|
class InvalidSignature < StandardError; end
|
29
35
|
|
@@ -34,22 +40,78 @@ module ActiveSupport
|
|
34
40
|
@serializer = options[:serializer] || Marshal
|
35
41
|
end
|
36
42
|
|
37
|
-
|
38
|
-
|
43
|
+
# Checks if a signed message could have been generated by signing an object
|
44
|
+
# with the +MessageVerifier+'s secret.
|
45
|
+
#
|
46
|
+
# verifier = ActiveSupport::MessageVerifier.new 's3Krit'
|
47
|
+
# signed_message = verifier.generate 'a private message'
|
48
|
+
# verifier.valid_message?(signed_message) # => true
|
49
|
+
#
|
50
|
+
# tampered_message = signed_message.chop # editing the message invalidates the signature
|
51
|
+
# verifier.valid_message?(tampered_message) # => false
|
52
|
+
def valid_message?(signed_message)
|
53
|
+
return if signed_message.nil? || !signed_message.valid_encoding? || signed_message.blank?
|
54
|
+
|
55
|
+
data, digest = signed_message.split("--".freeze)
|
56
|
+
data.present? && digest.present? && ActiveSupport::SecurityUtils.secure_compare(digest, generate_digest(data))
|
57
|
+
end
|
39
58
|
|
40
|
-
|
41
|
-
|
59
|
+
# Decodes the signed message using the +MessageVerifier+'s secret.
|
60
|
+
#
|
61
|
+
# verifier = ActiveSupport::MessageVerifier.new 's3Krit'
|
62
|
+
#
|
63
|
+
# signed_message = verifier.generate 'a private message'
|
64
|
+
# verifier.verified(signed_message) # => 'a private message'
|
65
|
+
#
|
66
|
+
# Returns +nil+ if the message was not signed with the same secret.
|
67
|
+
#
|
68
|
+
# other_verifier = ActiveSupport::MessageVerifier.new 'd1ff3r3nt-s3Krit'
|
69
|
+
# other_verifier.verified(signed_message) # => nil
|
70
|
+
#
|
71
|
+
# Returns +nil+ if the message is not Base64-encoded.
|
72
|
+
#
|
73
|
+
# invalid_message = "f--46a0120593880c733a53b6dad75b42ddc1c8996d"
|
74
|
+
# verifier.verified(invalid_message) # => nil
|
75
|
+
#
|
76
|
+
# Raises any error raised while decoding the signed message.
|
77
|
+
#
|
78
|
+
# incompatible_message = "test--dad7b06c94abba8d46a15fafaef56c327665d5ff"
|
79
|
+
# verifier.verified(incompatible_message) # => TypeError: incompatible marshal file format
|
80
|
+
def verified(signed_message)
|
81
|
+
if valid_message?(signed_message)
|
42
82
|
begin
|
83
|
+
data = signed_message.split("--".freeze)[0]
|
43
84
|
@serializer.load(decode(data))
|
44
85
|
rescue ArgumentError => argument_error
|
45
|
-
|
86
|
+
return if argument_error.message =~ %r{invalid base64}
|
46
87
|
raise
|
47
88
|
end
|
48
|
-
else
|
49
|
-
raise InvalidSignature
|
50
89
|
end
|
51
90
|
end
|
52
91
|
|
92
|
+
# Decodes the signed message using the +MessageVerifier+'s secret.
|
93
|
+
#
|
94
|
+
# verifier = ActiveSupport::MessageVerifier.new 's3Krit'
|
95
|
+
# signed_message = verifier.generate 'a private message'
|
96
|
+
#
|
97
|
+
# verifier.verify(signed_message) # => 'a private message'
|
98
|
+
#
|
99
|
+
# Raises +InvalidSignature+ if the message was not signed with the same
|
100
|
+
# secret or was not Base64-encoded.
|
101
|
+
#
|
102
|
+
# other_verifier = ActiveSupport::MessageVerifier.new 'd1ff3r3nt-s3Krit'
|
103
|
+
# other_verifier.verify(signed_message) # => ActiveSupport::MessageVerifier::InvalidSignature
|
104
|
+
def verify(signed_message)
|
105
|
+
verified(signed_message) || raise(InvalidSignature)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Generates a signed message for the provided value.
|
109
|
+
#
|
110
|
+
# The message is signed with the +MessageVerifier+'s secret. Without knowing
|
111
|
+
# the secret, the original value cannot be extracted from the message.
|
112
|
+
#
|
113
|
+
# verifier = ActiveSupport::MessageVerifier.new 's3Krit'
|
114
|
+
# verifier.generate 'a private message' # => "BAhJIhRwcml2YXRlLW1lc3NhZ2UGOgZFVA==--e2d724331ebdee96a10fb99b089508d1c72bd772"
|
53
115
|
def generate(value)
|
54
116
|
data = encode(@serializer.dump(value))
|
55
117
|
"#{data}--#{generate_digest(data)}"
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
require 'active_support/json'
|
3
2
|
require 'active_support/core_ext/string/access'
|
4
3
|
require 'active_support/core_ext/string/behavior'
|
@@ -87,9 +86,19 @@ module ActiveSupport #:nodoc:
|
|
87
86
|
end
|
88
87
|
|
89
88
|
# Works like <tt>String#slice!</tt>, but returns an instance of
|
90
|
-
# Chars, or nil if the string was not modified.
|
89
|
+
# Chars, or nil if the string was not modified. The string will not be
|
90
|
+
# modified if the range given is out of bounds
|
91
|
+
#
|
92
|
+
# string = 'Welcome'
|
93
|
+
# string.mb_chars.slice!(3) # => #<ActiveSupport::Multibyte::Chars:0x000000038109b8 @wrapped_string="c">
|
94
|
+
# string # => 'Welome'
|
95
|
+
# string.mb_chars.slice!(0..3) # => #<ActiveSupport::Multibyte::Chars:0x00000002eb80a0 @wrapped_string="Welo">
|
96
|
+
# string # => 'me'
|
91
97
|
def slice!(*args)
|
92
|
-
|
98
|
+
string_sliced = @wrapped_string.slice!(*args)
|
99
|
+
if string_sliced
|
100
|
+
chars(string_sliced)
|
101
|
+
end
|
93
102
|
end
|
94
103
|
|
95
104
|
# Reverses all characters in the string.
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
module ActiveSupport
|
3
2
|
module Multibyte
|
4
3
|
module Unicode
|
@@ -11,7 +10,7 @@ module ActiveSupport
|
|
11
10
|
NORMALIZATION_FORMS = [:c, :kc, :d, :kd]
|
12
11
|
|
13
12
|
# The Unicode version that is supported by the implementation
|
14
|
-
UNICODE_VERSION = '
|
13
|
+
UNICODE_VERSION = '8.0.0'
|
15
14
|
|
16
15
|
# The default normalization used for operations that require
|
17
16
|
# normalization. It can be set to any of the normalizations
|
@@ -58,7 +57,7 @@ module ActiveSupport
|
|
58
57
|
# Returns a regular expression pattern that matches the passed Unicode
|
59
58
|
# codepoints.
|
60
59
|
def self.codepoints_to_pattern(array_of_codepoints) #:nodoc:
|
61
|
-
array_of_codepoints.collect{ |e| [e].pack 'U*' }.join('|')
|
60
|
+
array_of_codepoints.collect{ |e| [e].pack 'U*'.freeze }.join('|'.freeze)
|
62
61
|
end
|
63
62
|
TRAILERS_PAT = /(#{codepoints_to_pattern(LEADERS_AND_TRAILERS)})+\Z/u
|
64
63
|
LEADERS_PAT = /\A(#{codepoints_to_pattern(LEADERS_AND_TRAILERS)})+/u
|
@@ -88,19 +87,44 @@ module ActiveSupport
|
|
88
87
|
pos += 1
|
89
88
|
previous = codepoints[pos-1]
|
90
89
|
current = codepoints[pos]
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
)
|
103
|
-
|
90
|
+
|
91
|
+
should_break =
|
92
|
+
# GB3. CR X LF
|
93
|
+
if previous == database.boundary[:cr] and current == database.boundary[:lf]
|
94
|
+
false
|
95
|
+
# GB4. (Control|CR|LF) ÷
|
96
|
+
elsif previous and in_char_class?(previous, [:control,:cr,:lf])
|
97
|
+
true
|
98
|
+
# GB5. ÷ (Control|CR|LF)
|
99
|
+
elsif in_char_class?(current, [:control,:cr,:lf])
|
100
|
+
true
|
101
|
+
# GB6. L X (L|V|LV|LVT)
|
102
|
+
elsif database.boundary[:l] === previous and in_char_class?(current, [:l,:v,:lv,:lvt])
|
103
|
+
false
|
104
|
+
# GB7. (LV|V) X (V|T)
|
105
|
+
elsif in_char_class?(previous, [:lv,:v]) and in_char_class?(current, [:v,:t])
|
106
|
+
false
|
107
|
+
# GB8. (LVT|T) X (T)
|
108
|
+
elsif in_char_class?(previous, [:lvt,:t]) and database.boundary[:t] === current
|
109
|
+
false
|
110
|
+
# GB8a. Regional_Indicator X Regional_Indicator
|
111
|
+
elsif database.boundary[:regional_indicator] === previous and database.boundary[:regional_indicator] === current
|
112
|
+
false
|
113
|
+
# GB9. X Extend
|
114
|
+
elsif database.boundary[:extend] === current
|
115
|
+
false
|
116
|
+
# GB9a. X SpacingMark
|
117
|
+
elsif database.boundary[:spacingmark] === current
|
118
|
+
false
|
119
|
+
# GB9b. Prepend X
|
120
|
+
elsif database.boundary[:prepend] === previous
|
121
|
+
false
|
122
|
+
# GB10. Any ÷ Any
|
123
|
+
else
|
124
|
+
true
|
125
|
+
end
|
126
|
+
|
127
|
+
if should_break
|
104
128
|
unpacked << codepoints[marker..pos-1]
|
105
129
|
marker = pos
|
106
130
|
end
|
@@ -211,9 +235,8 @@ module ActiveSupport
|
|
211
235
|
codepoints
|
212
236
|
end
|
213
237
|
|
214
|
-
# Ruby >= 2.1 has String#scrub, which is faster than the workaround used for < 2.1.
|
215
238
|
# Rubinius' String#scrub, however, doesn't support ASCII-incompatible chars.
|
216
|
-
if
|
239
|
+
if !defined?(Rubinius)
|
217
240
|
# Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent
|
218
241
|
# resulting in a valid UTF-8 string.
|
219
242
|
#
|
@@ -258,7 +281,7 @@ module ActiveSupport
|
|
258
281
|
# * <tt>string</tt> - The string to perform normalization on.
|
259
282
|
# * <tt>form</tt> - The form you want to normalize in. Should be one of
|
260
283
|
# the following: <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>.
|
261
|
-
# Default is ActiveSupport::Multibyte.default_normalization_form.
|
284
|
+
# Default is ActiveSupport::Multibyte::Unicode.default_normalization_form.
|
262
285
|
def normalize(string, form=nil)
|
263
286
|
form ||= @default_normalization_form
|
264
287
|
# See http://www.unicode.org/reports/tr15, Table 1
|
@@ -274,7 +297,7 @@ module ActiveSupport
|
|
274
297
|
compose(reorder_characters(decompose(:compatibility, codepoints)))
|
275
298
|
else
|
276
299
|
raise ArgumentError, "#{form} is not a valid normalization variant", caller
|
277
|
-
end.pack('U*')
|
300
|
+
end.pack('U*'.freeze)
|
278
301
|
end
|
279
302
|
|
280
303
|
def downcase(string)
|
@@ -339,7 +362,7 @@ module ActiveSupport
|
|
339
362
|
end
|
340
363
|
|
341
364
|
# Redefine the === method so we can write shorter rules for grapheme cluster breaks
|
342
|
-
@boundary.
|
365
|
+
@boundary.each_key do |k|
|
343
366
|
@boundary[k].instance_eval do
|
344
367
|
def ===(other)
|
345
368
|
detect { |i| i === other } ? true : false
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'mutex_m'
|
2
|
-
require '
|
2
|
+
require 'concurrent/map'
|
3
3
|
|
4
4
|
module ActiveSupport
|
5
5
|
module Notifications
|
@@ -12,7 +12,7 @@ module ActiveSupport
|
|
12
12
|
|
13
13
|
def initialize
|
14
14
|
@subscribers = []
|
15
|
-
@listeners_for =
|
15
|
+
@listeners_for = Concurrent::Map.new
|
16
16
|
super
|
17
17
|
end
|
18
18
|
|
@@ -42,8 +42,8 @@ module ActiveSupport
|
|
42
42
|
listeners_for(name).each { |s| s.start(name, id, payload) }
|
43
43
|
end
|
44
44
|
|
45
|
-
def finish(name, id, payload)
|
46
|
-
|
45
|
+
def finish(name, id, payload, listeners = listeners_for(name))
|
46
|
+
listeners.each { |s| s.finish(name, id, payload) }
|
47
47
|
end
|
48
48
|
|
49
49
|
def publish(name, *args)
|
@@ -51,7 +51,7 @@ module ActiveSupport
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def listeners_for(name)
|
54
|
-
# this is correctly done double-checked locking (
|
54
|
+
# this is correctly done double-checked locking (Concurrent::Map's lookups have volatile semantics)
|
55
55
|
@listeners_for[name] || synchronize do
|
56
56
|
# use synchronisation when accessing @subscribers
|
57
57
|
@listeners_for[name] ||= @subscribers.select { |s| s.subscribed_to?(name) }
|
@@ -15,14 +15,16 @@ module ActiveSupport
|
|
15
15
|
# and publish it. Notice that events get sent even if an error occurs
|
16
16
|
# in the passed-in block.
|
17
17
|
def instrument(name, payload={})
|
18
|
-
|
18
|
+
# some of the listeners might have state
|
19
|
+
listeners_state = start name, payload
|
19
20
|
begin
|
20
21
|
yield payload
|
21
22
|
rescue Exception => e
|
22
23
|
payload[:exception] = [e.class.name, e.message]
|
24
|
+
payload[:exception_object] = e
|
23
25
|
raise e
|
24
26
|
ensure
|
25
|
-
|
27
|
+
finish_with_state listeners_state, name, payload
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
@@ -36,6 +38,10 @@ module ActiveSupport
|
|
36
38
|
@notifier.finish name, @id, payload
|
37
39
|
end
|
38
40
|
|
41
|
+
def finish_with_state(listeners_state, name, payload)
|
42
|
+
@notifier.finish name, @id, payload, listeners_state
|
43
|
+
end
|
44
|
+
|
39
45
|
private
|
40
46
|
|
41
47
|
def unique_id
|
@@ -57,6 +63,18 @@ module ActiveSupport
|
|
57
63
|
@duration = nil
|
58
64
|
end
|
59
65
|
|
66
|
+
# Returns the difference in milliseconds between when the execution of the
|
67
|
+
# event started and when it ended.
|
68
|
+
#
|
69
|
+
# ActiveSupport::Notifications.subscribe('wait') do |*args|
|
70
|
+
# @event = ActiveSupport::Notifications::Event.new(*args)
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# ActiveSupport::Notifications.instrument('wait') do
|
74
|
+
# sleep 1
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# @event.duration # => 1000.138
|
60
78
|
def duration
|
61
79
|
@duration ||= 1000.0 * (self.end - time)
|
62
80
|
end
|
@@ -69,8 +69,8 @@ module ActiveSupport
|
|
69
69
|
# is able to take the arguments as they come and provide an object-oriented
|
70
70
|
# interface to that data.
|
71
71
|
#
|
72
|
-
# It is also possible to pass an object
|
73
|
-
# <tt>subscribe</tt> method instead of a block:
|
72
|
+
# It is also possible to pass an object which responds to <tt>call</tt> method
|
73
|
+
# as the second parameter to the <tt>subscribe</tt> method instead of a block:
|
74
74
|
#
|
75
75
|
# module ActionController
|
76
76
|
# class PageRequest
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/core_ext/numeric/inquiry'
|
2
|
+
|
1
3
|
module ActiveSupport
|
2
4
|
module NumberHelper
|
3
5
|
class NumberToCurrencyConverter < NumberConverter # :nodoc:
|
@@ -7,36 +9,32 @@ module ActiveSupport
|
|
7
9
|
number = self.number.to_s.strip
|
8
10
|
format = options[:format]
|
9
11
|
|
10
|
-
if
|
12
|
+
if number.to_f.negative?
|
11
13
|
format = options[:negative_format]
|
12
14
|
number = absolute_value(number)
|
13
15
|
end
|
14
16
|
|
15
17
|
rounded_number = NumberToRoundedConverter.convert(number, options)
|
16
|
-
format.gsub(
|
18
|
+
format.gsub('%n'.freeze, rounded_number).gsub('%u'.freeze, options[:unit])
|
17
19
|
end
|
18
20
|
|
19
21
|
private
|
20
22
|
|
21
|
-
def is_negative?(number)
|
22
|
-
number.to_f.phase != 0
|
23
|
-
end
|
24
|
-
|
25
23
|
def absolute_value(number)
|
26
|
-
number.respond_to?(
|
24
|
+
number.respond_to?(:abs) ? number.abs : number.sub(/\A-/, '')
|
27
25
|
end
|
28
26
|
|
29
27
|
def options
|
30
28
|
@options ||= begin
|
31
29
|
defaults = default_format_options.merge(i18n_opts)
|
32
|
-
# Override negative format if format options
|
30
|
+
# Override negative format if format options are given
|
33
31
|
defaults[:negative_format] = "-#{opts[:format]}" if opts[:format]
|
34
32
|
defaults.merge!(opts)
|
35
33
|
end
|
36
34
|
end
|
37
35
|
|
38
36
|
def i18n_opts
|
39
|
-
# Set International negative format if not
|
37
|
+
# Set International negative format if it does not exist
|
40
38
|
i18n = i18n_format_options
|
41
39
|
i18n[:negative_format] ||= "-#{i18n[:format]}" if i18n[:format]
|
42
40
|
i18n
|
@@ -3,7 +3,7 @@ module ActiveSupport
|
|
3
3
|
class NumberToDelimitedConverter < NumberConverter #:nodoc:
|
4
4
|
self.validate_float = true
|
5
5
|
|
6
|
-
|
6
|
+
DEFAULT_DELIMITER_REGEX = /(\d)(?=(\d\d\d)+(?!\d))/
|
7
7
|
|
8
8
|
def convert
|
9
9
|
parts.join(options[:separator])
|
@@ -12,12 +12,17 @@ module ActiveSupport
|
|
12
12
|
private
|
13
13
|
|
14
14
|
def parts
|
15
|
-
left, right = number.to_s.split('.')
|
16
|
-
left.gsub!(
|
15
|
+
left, right = number.to_s.split('.'.freeze)
|
16
|
+
left.gsub!(delimiter_pattern) do |digit_to_delimit|
|
17
17
|
"#{digit_to_delimit}#{options[:delimiter]}"
|
18
18
|
end
|
19
19
|
[left, right].compact
|
20
20
|
end
|
21
|
+
|
22
|
+
def delimiter_pattern
|
23
|
+
options.fetch(:delimiter_pattern, DEFAULT_DELIMITER_REGEX)
|
24
|
+
end
|
25
|
+
|
21
26
|
end
|
22
27
|
end
|
23
28
|
end
|
@@ -20,10 +20,12 @@ module ActiveSupport
|
|
20
20
|
exponent = calculate_exponent(units)
|
21
21
|
@number = number / (10 ** exponent)
|
22
22
|
|
23
|
+
until (rounded_number = NumberToRoundedConverter.convert(number, options)) != NumberToRoundedConverter.convert(1000, options)
|
24
|
+
@number = number / 1000.0
|
25
|
+
exponent += 3
|
26
|
+
end
|
23
27
|
unit = determine_unit(units, exponent)
|
24
|
-
|
25
|
-
rounded_number = NumberToRoundedConverter.convert(number, options)
|
26
|
-
format.gsub(/%n/, rounded_number).gsub(/%u/, unit).strip
|
28
|
+
format.gsub('%n'.freeze, rounded_number).gsub('%u'.freeze, unit).strip
|
27
29
|
end
|
28
30
|
|
29
31
|
private
|
@@ -59,7 +61,7 @@ module ActiveSupport
|
|
59
61
|
translate_in_locale("human.decimal_units.units", raise: true)
|
60
62
|
else
|
61
63
|
raise ArgumentError, ":units must be a Hash or String translation scope."
|
62
|
-
end.keys.map { |e_name| INVERTED_DECIMAL_UNITS[e_name] }.sort_by
|
64
|
+
end.keys.map { |e_name| INVERTED_DECIMAL_UNITS[e_name] }.sort_by(&:-@)
|
63
65
|
end
|
64
66
|
end
|
65
67
|
end
|