activesupport 4.0.12 → 7.0.2.4
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 +5 -5
- data/CHANGELOG.md +249 -501
- data/MIT-LICENSE +2 -2
- data/README.rdoc +10 -5
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +41 -13
- data/lib/active_support/benchmarkable.rb +7 -15
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +96 -74
- data/lib/active_support/cache/mem_cache_store.rb +211 -103
- data/lib/active_support/cache/memory_store.rb +90 -58
- data/lib/active_support/cache/null_store.rb +19 -7
- data/lib/active_support/cache/redis_cache_store.rb +468 -0
- data/lib/active_support/cache/strategy/local_cache.rb +86 -83
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
- data/lib/active_support/cache.rb +580 -241
- data/lib/active_support/callbacks.rb +812 -425
- data/lib/active_support/code_generator.rb +65 -0
- data/lib/active_support/concern.rb +103 -14
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +33 -0
- data/lib/active_support/concurrency/share_lock.rb +226 -0
- data/lib/active_support/configurable.rb +21 -19
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +47 -1
- data/lib/active_support/core_ext/array/conversions.rb +35 -44
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +26 -16
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/wrap.rb +7 -4
- data/lib/active_support/core_ext/array.rb +10 -7
- data/lib/active_support/core_ext/benchmark.rb +5 -3
- data/lib/active_support/core_ext/big_decimal/conversions.rb +9 -26
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +52 -49
- data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
- data/lib/active_support/core_ext/class/subclasses.rb +25 -26
- data/lib/active_support/core_ext/class.rb +4 -4
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +14 -0
- data/lib/active_support/core_ext/date/calculations.rb +31 -18
- data/lib/active_support/core_ext/date/conversions.rb +43 -32
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/date/zones.rb +5 -34
- data/lib/active_support/core_ext/date.rb +7 -4
- data/lib/active_support/core_ext/date_and_time/calculations.rb +198 -66
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +31 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
- data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +14 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +79 -38
- data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +31 -26
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/date_time.rb +8 -4
- data/lib/active_support/core_ext/digest/uuid.rb +79 -0
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +249 -17
- data/lib/active_support/core_ext/file/atomic.rb +41 -32
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +71 -49
- data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +14 -5
- data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
- data/lib/active_support/core_ext/hash/keys.rb +39 -56
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -23
- data/lib/active_support/core_ext/hash.rb +10 -8
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +11 -33
- data/lib/active_support/core_ext/integer.rb +5 -3
- data/lib/active_support/core_ext/kernel/concern.rb +14 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +9 -78
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +5 -4
- data/lib/active_support/core_ext/load_error.rb +5 -21
- data/lib/active_support/core_ext/module/aliasing.rb +6 -44
- data/lib/active_support/core_ext/module/anonymous.rb +12 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +8 -8
- data/lib/active_support/core_ext/module/attribute_accessors.rb +186 -44
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +157 -0
- data/lib/active_support/core_ext/module/concerning.rb +140 -0
- data/lib/active_support/core_ext/module/delegation.rb +172 -45
- data/lib/active_support/core_ext/module/deprecation.rb +3 -3
- data/lib/active_support/core_ext/module/introspection.rb +23 -38
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +8 -3
- data/lib/active_support/core_ext/module.rb +13 -10
- data/lib/active_support/core_ext/name_error.rb +45 -4
- data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +135 -127
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
- data/lib/active_support/core_ext/numeric/time.rb +37 -50
- data/lib/active_support/core_ext/numeric.rb +6 -3
- data/lib/active_support/core_ext/object/acts_like.rb +41 -6
- data/lib/active_support/core_ext/object/blank.rb +70 -20
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +19 -10
- data/lib/active_support/core_ext/object/duplicable.rb +17 -47
- data/lib/active_support/core_ext/object/inclusion.rb +18 -15
- data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
- data/lib/active_support/core_ext/object/json.rb +244 -0
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +21 -8
- data/lib/active_support/core_ext/object/try.rb +106 -26
- data/lib/active_support/core_ext/object/with_options.rb +64 -5
- data/lib/active_support/core_ext/object.rb +14 -12
- data/lib/active_support/core_ext/pathname/existence.rb +21 -0
- data/lib/active_support/core_ext/pathname.rb +3 -0
- data/lib/active_support/core_ext/range/compare_range.rb +57 -0
- data/lib/active_support/core_ext/range/conversions.rb +37 -15
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/range/each.rb +18 -17
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +7 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/range.rb +7 -4
- data/lib/active_support/core_ext/regexp.rb +10 -1
- data/lib/active_support/core_ext/securerandom.rb +45 -0
- data/lib/active_support/core_ext/string/access.rb +42 -51
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +18 -13
- data/lib/active_support/core_ext/string/exclude.rb +5 -3
- data/lib/active_support/core_ext/string/filters.rb +97 -7
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +106 -25
- data/lib/active_support/core_ext/string/inquiry.rb +4 -1
- data/lib/active_support/core_ext/string/multibyte.rb +18 -9
- data/lib/active_support/core_ext/string/output_safety.rb +227 -54
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- data/lib/active_support/core_ext/string/strip.rb +6 -5
- data/lib/active_support/core_ext/string/zones.rb +4 -1
- data/lib/active_support/core_ext/string.rb +15 -13
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +178 -116
- data/lib/active_support/core_ext/time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/time/conversions.rb +37 -25
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/time/zones.rb +44 -42
- data/lib/active_support/core_ext/time.rb +8 -5
- data/lib/active_support/core_ext/uri.rb +4 -25
- data/lib/active_support/core_ext.rb +4 -2
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +226 -0
- data/lib/active_support/dependencies/autoload.rb +3 -1
- data/lib/active_support/dependencies/interlock.rb +49 -0
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +71 -696
- data/lib/active_support/deprecation/behaviors.rb +65 -16
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +16 -2
- data/lib/active_support/deprecation/method_wrappers.rb +62 -21
- data/lib/active_support/deprecation/proxy_wrappers.rb +82 -31
- data/lib/active_support/deprecation/reporting.rb +81 -18
- data/lib/active_support/deprecation.rb +19 -11
- data/lib/active_support/descendants_tracker.rb +192 -34
- data/lib/active_support/digest.rb +22 -0
- data/lib/active_support/duration/iso8601_parser.rb +123 -0
- data/lib/active_support/duration/iso8601_serializer.rb +67 -0
- data/lib/active_support/duration.rb +437 -39
- data/lib/active_support/encrypted_configuration.rb +56 -0
- data/lib/active_support/encrypted_file.rb +117 -0
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/error_reporter.rb +117 -0
- data/lib/active_support/evented_file_update_checker.rb +170 -0
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +53 -0
- data/lib/active_support/execution_wrapper.rb +151 -0
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +62 -37
- data/lib/active_support/fork_tracker.rb +71 -0
- data/lib/active_support/gem_version.rb +17 -0
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +207 -54
- data/lib/active_support/html_safe_translation.rb +43 -0
- data/lib/active_support/i18n.rb +10 -6
- data/lib/active_support/i18n_railtie.rb +48 -19
- data/lib/active_support/inflections.rb +19 -12
- data/lib/active_support/inflector/inflections.rb +97 -37
- data/lib/active_support/inflector/methods.rb +192 -157
- data/lib/active_support/inflector/transliterate.rb +83 -33
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/isolated_execution_state.rb +64 -0
- data/lib/active_support/json/decoding.rb +37 -42
- data/lib/active_support/json/encoding.rb +93 -293
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +30 -47
- data/lib/active_support/lazy_load_hooks.rb +54 -21
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +10 -4
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/log_subscriber.rb +61 -18
- data/lib/active_support/logger.rb +40 -4
- data/lib/active_support/logger_silence.rb +17 -20
- data/lib/active_support/logger_thread_safe_level.rb +69 -0
- data/lib/active_support/message_encryptor.rb +178 -55
- data/lib/active_support/message_verifier.rb +195 -26
- data/lib/active_support/messages/metadata.rb +80 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotator.rb +57 -0
- data/lib/active_support/multibyte/chars.rb +45 -92
- data/lib/active_support/multibyte/unicode.rb +44 -377
- data/lib/active_support/multibyte.rb +5 -3
- data/lib/active_support/notifications/fanout.rb +177 -44
- data/lib/active_support/notifications/instrumenter.rb +117 -17
- data/lib/active_support/notifications.rb +106 -39
- data/lib/active_support/number_helper/number_converter.rb +181 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +30 -0
- data/lib/active_support/number_helper/number_to_human_converter.rb +69 -0
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +60 -0
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +16 -0
- data/lib/active_support/number_helper/number_to_phone_converter.rb +59 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +59 -0
- data/lib/active_support/number_helper/rounding_helper.rb +46 -0
- data/lib/active_support/number_helper.rb +152 -394
- data/lib/active_support/option_merger.rb +18 -5
- data/lib/active_support/ordered_hash.rb +8 -6
- data/lib/active_support/ordered_options.rb +43 -7
- data/lib/active_support/parameter_filter.rb +138 -0
- data/lib/active_support/per_thread_registry.rb +24 -11
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +10 -11
- data/lib/active_support/railtie.rb +118 -12
- data/lib/active_support/reloader.rb +130 -0
- data/lib/active_support/rescuable.rb +112 -57
- data/lib/active_support/ruby_features.rb +7 -0
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +38 -0
- data/lib/active_support/string_inquirer.rb +11 -4
- data/lib/active_support/subscriber.rb +109 -39
- data/lib/active_support/tagged_logging.rb +54 -17
- data/lib/active_support/test_case.rb +121 -37
- data/lib/active_support/testing/assertions.rb +177 -39
- data/lib/active_support/testing/autorun.rb +5 -3
- data/lib/active_support/testing/constant_lookup.rb +3 -6
- data/lib/active_support/testing/declarative.rb +10 -22
- data/lib/active_support/testing/deprecation.rb +65 -11
- data/lib/active_support/testing/file_fixtures.rb +38 -0
- data/lib/active_support/testing/isolation.rb +56 -87
- data/lib/active_support/testing/method_call_assertions.rb +70 -0
- data/lib/active_support/testing/parallelization/server.rb +82 -0
- data/lib/active_support/testing/parallelization/worker.rb +103 -0
- data/lib/active_support/testing/parallelization.rb +55 -0
- data/lib/active_support/testing/parallelize_executor.rb +76 -0
- data/lib/active_support/testing/setup_and_teardown.rb +30 -10
- data/lib/active_support/testing/stream.rb +41 -0
- data/lib/active_support/testing/tagged_logging.rb +6 -4
- data/lib/active_support/testing/time_helpers.rb +246 -0
- data/lib/active_support/time.rb +13 -13
- data/lib/active_support/time_with_zone.rb +315 -90
- data/lib/active_support/values/time_zone.rb +306 -135
- data/lib/active_support/version.rb +6 -7
- data/lib/active_support/xml_mini/jdom.rb +117 -115
- data/lib/active_support/xml_mini/libxml.rb +22 -21
- data/lib/active_support/xml_mini/libxmlsax.rb +17 -19
- data/lib/active_support/xml_mini/nokogiri.rb +19 -19
- data/lib/active_support/xml_mini/nokogirisax.rb +16 -17
- data/lib/active_support/xml_mini/rexml.rb +25 -17
- data/lib/active_support/xml_mini.rb +67 -56
- data/lib/active_support.rb +58 -3
- metadata +125 -66
- data/lib/active_support/basic_object.rb +0 -11
- data/lib/active_support/buffered_logger.rb +0 -21
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -40
- data/lib/active_support/core_ext/date_time/zones.rb +0 -24
- data/lib/active_support/core_ext/hash/diff.rb +0 -14
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
- data/lib/active_support/core_ext/logger.rb +0 -67
- data/lib/active_support/core_ext/marshal.rb +0 -21
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
- data/lib/active_support/core_ext/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/object/to_json.rb +0 -27
- data/lib/active_support/core_ext/proc.rb +0 -17
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- data/lib/active_support/core_ext/string/encoding.rb +0 -8
- data/lib/active_support/core_ext/struct.rb +0 -6
- data/lib/active_support/core_ext/thread.rb +0 -79
- data/lib/active_support/core_ext/time/marshal.rb +0 -30
- data/lib/active_support/file_watcher.rb +0 -36
- data/lib/active_support/json/variable.rb +0 -18
- data/lib/active_support/testing/pending.rb +0 -14
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,6 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/notifications/instrumenter"
|
4
|
+
require "active_support/notifications/fanout"
|
4
5
|
|
5
6
|
module ActiveSupport
|
6
7
|
# = Notifications
|
@@ -13,10 +14,10 @@ module ActiveSupport
|
|
13
14
|
# To instrument an event you just need to do:
|
14
15
|
#
|
15
16
|
# ActiveSupport::Notifications.instrument('render', extra: :information) do
|
16
|
-
# render
|
17
|
+
# render plain: 'Foo'
|
17
18
|
# end
|
18
19
|
#
|
19
|
-
# That executes the block
|
20
|
+
# That first executes the block and then notifies all subscribers once done.
|
20
21
|
#
|
21
22
|
# In the example above +render+ is the name of the event, and the rest is called
|
22
23
|
# the _payload_. The payload is a mechanism that allows instrumenters to pass
|
@@ -32,10 +33,23 @@ module ActiveSupport
|
|
32
33
|
# name # => String, name of the event (such as 'render' from above)
|
33
34
|
# start # => Time, when the instrumented block started execution
|
34
35
|
# finish # => Time, when the instrumented block ended execution
|
35
|
-
# id # => String, unique ID for
|
36
|
+
# id # => String, unique ID for the instrumenter that fired the event
|
36
37
|
# payload # => Hash, the payload
|
37
38
|
# end
|
38
39
|
#
|
40
|
+
# Here, the +start+ and +finish+ values represent wall-clock time. If you are
|
41
|
+
# concerned about accuracy, you can register a monotonic subscriber.
|
42
|
+
#
|
43
|
+
# ActiveSupport::Notifications.monotonic_subscribe('render') do |name, start, finish, id, payload|
|
44
|
+
# name # => String, name of the event (such as 'render' from above)
|
45
|
+
# start # => Monotonic time, when the instrumented block started execution
|
46
|
+
# finish # => Monotonic time, when the instrumented block ended execution
|
47
|
+
# id # => String, unique ID for the instrumenter that fired the event
|
48
|
+
# payload # => Hash, the payload
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# The +start+ and +finish+ values above represent monotonic time.
|
52
|
+
#
|
39
53
|
# For instance, let's store all "render" events in an array:
|
40
54
|
#
|
41
55
|
# events = []
|
@@ -48,7 +62,7 @@ module ActiveSupport
|
|
48
62
|
# The block is saved and will be called whenever someone instruments "render":
|
49
63
|
#
|
50
64
|
# ActiveSupport::Notifications.instrument('render', extra: :information) do
|
51
|
-
# render
|
65
|
+
# render plain: 'Foo'
|
52
66
|
# end
|
53
67
|
#
|
54
68
|
# event = events.first
|
@@ -57,20 +71,25 @@ module ActiveSupport
|
|
57
71
|
# event.payload # => { extra: :information }
|
58
72
|
#
|
59
73
|
# The block in the <tt>subscribe</tt> call gets the name of the event, start
|
60
|
-
# timestamp, end timestamp, a string with a unique identifier for that event
|
74
|
+
# timestamp, end timestamp, a string with a unique identifier for that event's instrumenter
|
61
75
|
# (something like "535801666f04d0298cd6"), and a hash with the payload, in
|
62
76
|
# that order.
|
63
77
|
#
|
64
78
|
# If an exception happens during that particular instrumentation the payload will
|
65
79
|
# have a key <tt>:exception</tt> with an array of two elements as value: a string with
|
66
80
|
# the name of the exception class, and the exception message.
|
81
|
+
# The <tt>:exception_object</tt> key of the payload will have the exception
|
82
|
+
# itself as the value:
|
67
83
|
#
|
68
|
-
#
|
84
|
+
# event.payload[:exception] # => ["ArgumentError", "Invalid value"]
|
85
|
+
# event.payload[:exception_object] # => #<ArgumentError: Invalid value>
|
86
|
+
#
|
87
|
+
# As the earlier example depicts, the class <tt>ActiveSupport::Notifications::Event</tt>
|
69
88
|
# is able to take the arguments as they come and provide an object-oriented
|
70
89
|
# interface to that data.
|
71
90
|
#
|
72
|
-
# It is also possible to pass an object
|
73
|
-
# <tt>subscribe</tt> method instead of a block:
|
91
|
+
# It is also possible to pass an object which responds to <tt>call</tt> method
|
92
|
+
# as the second parameter to the <tt>subscribe</tt> method instead of a block:
|
74
93
|
#
|
75
94
|
# module ActionController
|
76
95
|
# class PageRequest
|
@@ -128,6 +147,16 @@ module ActiveSupport
|
|
128
147
|
# during the execution of the block. The callback is unsubscribed automatically
|
129
148
|
# after that.
|
130
149
|
#
|
150
|
+
# To record +started+ and +finished+ values with monotonic time,
|
151
|
+
# specify the optional <tt>:monotonic</tt> option to the
|
152
|
+
# <tt>subscribed</tt> method. The <tt>:monotonic</tt> option is set
|
153
|
+
# to +false+ by default.
|
154
|
+
#
|
155
|
+
# callback = lambda {|name, started, finished, unique_id, payload| ... }
|
156
|
+
# ActiveSupport::Notifications.subscribed(callback, "sql.active_record", monotonic: true) do
|
157
|
+
# ...
|
158
|
+
# end
|
159
|
+
#
|
131
160
|
# === Manual Unsubscription
|
132
161
|
#
|
133
162
|
# The +subscribe+ method returns a subscriber object:
|
@@ -141,10 +170,24 @@ module ActiveSupport
|
|
141
170
|
#
|
142
171
|
# ActiveSupport::Notifications.unsubscribe(subscriber)
|
143
172
|
#
|
173
|
+
# You can also unsubscribe by passing the name of the subscriber object. Note
|
174
|
+
# that this will unsubscribe all subscriptions with the given name:
|
175
|
+
#
|
176
|
+
# ActiveSupport::Notifications.unsubscribe("render")
|
177
|
+
#
|
178
|
+
# Subscribers using a regexp or other pattern-matching object will remain subscribed
|
179
|
+
# to all events that match their original pattern, unless those events match a string
|
180
|
+
# passed to +unsubscribe+:
|
181
|
+
#
|
182
|
+
# subscriber = ActiveSupport::Notifications.subscribe(/render/) { }
|
183
|
+
# ActiveSupport::Notifications.unsubscribe('render_template.action_view')
|
184
|
+
# subscriber.matches?('render_template.action_view') # => false
|
185
|
+
# subscriber.matches?('render_partial.action_view') # => true
|
186
|
+
#
|
144
187
|
# == Default Queue
|
145
188
|
#
|
146
|
-
# Notifications ships with a queue implementation that consumes and
|
147
|
-
# to log subscribers
|
189
|
+
# Notifications ships with a queue implementation that consumes and publishes events
|
190
|
+
# to all log subscribers. You can use any queue implementation you want.
|
148
191
|
#
|
149
192
|
module Notifications
|
150
193
|
class << self
|
@@ -154,6 +197,10 @@ module ActiveSupport
|
|
154
197
|
notifier.publish(name, *args)
|
155
198
|
end
|
156
199
|
|
200
|
+
def publish_event(event) # :nodoc:
|
201
|
+
notifier.publish_event(event)
|
202
|
+
end
|
203
|
+
|
157
204
|
def instrument(name, payload = {})
|
158
205
|
if notifier.listening?(name)
|
159
206
|
instrumenter.instrument(name, payload) { yield payload if block_given? }
|
@@ -162,44 +209,64 @@ module ActiveSupport
|
|
162
209
|
end
|
163
210
|
end
|
164
211
|
|
165
|
-
|
166
|
-
|
212
|
+
# Subscribe to a given event name with the passed +block+.
|
213
|
+
#
|
214
|
+
# You can subscribe to events by passing a String to match exact event
|
215
|
+
# names, or by passing a Regexp to match all events that match a pattern.
|
216
|
+
#
|
217
|
+
# ActiveSupport::Notifications.subscribe(/render/) do |*args|
|
218
|
+
# @event = ActiveSupport::Notifications::Event.new(*args)
|
219
|
+
# end
|
220
|
+
#
|
221
|
+
# The +block+ will receive five parameters with information about the event:
|
222
|
+
#
|
223
|
+
# ActiveSupport::Notifications.subscribe('render') do |name, start, finish, id, payload|
|
224
|
+
# name # => String, name of the event (such as 'render' from above)
|
225
|
+
# start # => Time, when the instrumented block started execution
|
226
|
+
# finish # => Time, when the instrumented block ended execution
|
227
|
+
# id # => String, unique ID for the instrumenter that fired the event
|
228
|
+
# payload # => Hash, the payload
|
229
|
+
# end
|
230
|
+
#
|
231
|
+
# If the block passed to the method only takes one parameter,
|
232
|
+
# it will yield an event object to the block:
|
233
|
+
#
|
234
|
+
# ActiveSupport::Notifications.subscribe(/render/) do |event|
|
235
|
+
# @event = event
|
236
|
+
# end
|
237
|
+
#
|
238
|
+
# Raises an error if invalid event name type is passed:
|
239
|
+
#
|
240
|
+
# ActiveSupport::Notifications.subscribe(:render) {|*args| ...}
|
241
|
+
# #=> ArgumentError (pattern must be specified as a String, Regexp or empty)
|
242
|
+
#
|
243
|
+
def subscribe(pattern = nil, callback = nil, &block)
|
244
|
+
notifier.subscribe(pattern, callback, monotonic: false, &block)
|
245
|
+
end
|
246
|
+
|
247
|
+
def monotonic_subscribe(pattern = nil, callback = nil, &block)
|
248
|
+
notifier.subscribe(pattern, callback, monotonic: true, &block)
|
167
249
|
end
|
168
250
|
|
169
|
-
def subscribed(callback,
|
170
|
-
subscriber = subscribe(
|
251
|
+
def subscribed(callback, pattern = nil, monotonic: false, &block)
|
252
|
+
subscriber = notifier.subscribe(pattern, callback, monotonic: monotonic)
|
171
253
|
yield
|
172
254
|
ensure
|
173
255
|
unsubscribe(subscriber)
|
174
256
|
end
|
175
257
|
|
176
|
-
def unsubscribe(
|
177
|
-
notifier.unsubscribe(
|
258
|
+
def unsubscribe(subscriber_or_name)
|
259
|
+
notifier.unsubscribe(subscriber_or_name)
|
178
260
|
end
|
179
261
|
|
180
262
|
def instrumenter
|
181
|
-
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
# This class is a registry which holds all of the +Instrumenter+ objects
|
186
|
-
# in a particular thread local. To access the +Instrumenter+ object for a
|
187
|
-
# particular +notifier+, you can call the following method:
|
188
|
-
#
|
189
|
-
# InstrumentationRegistry.instrumenter_for(notifier)
|
190
|
-
#
|
191
|
-
# The instrumenters for multiple notifiers are held in a single instance of
|
192
|
-
# this class.
|
193
|
-
class InstrumentationRegistry # :nodoc:
|
194
|
-
extend ActiveSupport::PerThreadRegistry
|
195
|
-
|
196
|
-
def initialize
|
197
|
-
@registry = {}
|
263
|
+
registry[notifier] ||= Instrumenter.new(notifier)
|
198
264
|
end
|
199
265
|
|
200
|
-
|
201
|
-
|
202
|
-
|
266
|
+
private
|
267
|
+
def registry
|
268
|
+
ActiveSupport::IsolatedExecutionState[:active_support_notifications_registry] ||= {}
|
269
|
+
end
|
203
270
|
end
|
204
271
|
|
205
272
|
self.notifier = Fanout.new
|
@@ -0,0 +1,181 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/big_decimal/conversions"
|
4
|
+
require "active_support/core_ext/object/blank"
|
5
|
+
require "active_support/core_ext/hash/keys"
|
6
|
+
require "active_support/i18n"
|
7
|
+
require "active_support/core_ext/class/attribute"
|
8
|
+
|
9
|
+
module ActiveSupport
|
10
|
+
module NumberHelper
|
11
|
+
class NumberConverter # :nodoc:
|
12
|
+
# Default and i18n option namespace per class
|
13
|
+
class_attribute :namespace
|
14
|
+
|
15
|
+
# Does the object need a number that is a valid float?
|
16
|
+
class_attribute :validate_float
|
17
|
+
|
18
|
+
attr_reader :number, :opts
|
19
|
+
|
20
|
+
DEFAULTS = {
|
21
|
+
# Used in number_to_delimited
|
22
|
+
# These are also the defaults for 'currency', 'percentage', 'precision', and 'human'
|
23
|
+
format: {
|
24
|
+
# Sets the separator between the units, for more precision (e.g. 1.0 / 2.0 == 0.5)
|
25
|
+
separator: ".",
|
26
|
+
# Delimits thousands (e.g. 1,000,000 is a million) (always in groups of three)
|
27
|
+
delimiter: ",",
|
28
|
+
# Number of decimals, behind the separator (the number 1 with a precision of 2 gives: 1.00)
|
29
|
+
precision: 3,
|
30
|
+
# If set to true, precision will mean the number of significant digits instead
|
31
|
+
# of the number of decimal digits (1234 with precision 2 becomes 1200, 1.23543 becomes 1.2)
|
32
|
+
significant: false,
|
33
|
+
# If set, the zeros after the decimal separator will always be stripped (e.g.: 1.200 will be 1.2)
|
34
|
+
strip_insignificant_zeros: false
|
35
|
+
},
|
36
|
+
|
37
|
+
# Used in number_to_currency
|
38
|
+
currency: {
|
39
|
+
format: {
|
40
|
+
format: "%u%n",
|
41
|
+
negative_format: "-%u%n",
|
42
|
+
unit: "$",
|
43
|
+
# These five are to override number.format and are optional
|
44
|
+
separator: ".",
|
45
|
+
delimiter: ",",
|
46
|
+
precision: 2,
|
47
|
+
significant: false,
|
48
|
+
strip_insignificant_zeros: false
|
49
|
+
}
|
50
|
+
},
|
51
|
+
|
52
|
+
# Used in number_to_percentage
|
53
|
+
percentage: {
|
54
|
+
format: {
|
55
|
+
delimiter: "",
|
56
|
+
format: "%n%"
|
57
|
+
}
|
58
|
+
},
|
59
|
+
|
60
|
+
# Used in number_to_rounded
|
61
|
+
precision: {
|
62
|
+
format: {
|
63
|
+
delimiter: ""
|
64
|
+
}
|
65
|
+
},
|
66
|
+
|
67
|
+
# Used in number_to_human_size and number_to_human
|
68
|
+
human: {
|
69
|
+
format: {
|
70
|
+
# These five are to override number.format and are optional
|
71
|
+
delimiter: "",
|
72
|
+
precision: 3,
|
73
|
+
significant: true,
|
74
|
+
strip_insignificant_zeros: true
|
75
|
+
},
|
76
|
+
# Used in number_to_human_size
|
77
|
+
storage_units: {
|
78
|
+
# Storage units output formatting.
|
79
|
+
# %u is the storage unit, %n is the number (default: 2 MB)
|
80
|
+
format: "%n %u",
|
81
|
+
units: {
|
82
|
+
byte: "Bytes",
|
83
|
+
kb: "KB",
|
84
|
+
mb: "MB",
|
85
|
+
gb: "GB",
|
86
|
+
tb: "TB"
|
87
|
+
}
|
88
|
+
},
|
89
|
+
# Used in number_to_human
|
90
|
+
decimal_units: {
|
91
|
+
format: "%n %u",
|
92
|
+
# Decimal units output formatting
|
93
|
+
# By default we will only quantify some of the exponents
|
94
|
+
# but the commented ones might be defined or overridden
|
95
|
+
# by the user.
|
96
|
+
units: {
|
97
|
+
# femto: Quadrillionth
|
98
|
+
# pico: Trillionth
|
99
|
+
# nano: Billionth
|
100
|
+
# micro: Millionth
|
101
|
+
# mili: Thousandth
|
102
|
+
# centi: Hundredth
|
103
|
+
# deci: Tenth
|
104
|
+
unit: "",
|
105
|
+
# ten:
|
106
|
+
# one: Ten
|
107
|
+
# other: Tens
|
108
|
+
# hundred: Hundred
|
109
|
+
thousand: "Thousand",
|
110
|
+
million: "Million",
|
111
|
+
billion: "Billion",
|
112
|
+
trillion: "Trillion",
|
113
|
+
quadrillion: "Quadrillion"
|
114
|
+
}
|
115
|
+
}
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
119
|
+
def self.convert(number, options)
|
120
|
+
new(number, options).execute
|
121
|
+
end
|
122
|
+
|
123
|
+
def initialize(number, options)
|
124
|
+
@number = number
|
125
|
+
@opts = options.symbolize_keys
|
126
|
+
end
|
127
|
+
|
128
|
+
def execute
|
129
|
+
if !number
|
130
|
+
nil
|
131
|
+
elsif validate_float? && !valid_float?
|
132
|
+
number
|
133
|
+
else
|
134
|
+
convert
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
private
|
139
|
+
def options
|
140
|
+
@options ||= format_options.merge(opts)
|
141
|
+
end
|
142
|
+
|
143
|
+
def format_options
|
144
|
+
default_format_options.merge!(i18n_format_options)
|
145
|
+
end
|
146
|
+
|
147
|
+
def default_format_options
|
148
|
+
options = DEFAULTS[:format].dup
|
149
|
+
options.merge!(DEFAULTS[namespace][:format]) if namespace
|
150
|
+
options
|
151
|
+
end
|
152
|
+
|
153
|
+
def i18n_format_options
|
154
|
+
locale = opts[:locale]
|
155
|
+
options = I18n.translate(:'number.format', locale: locale, default: {}).dup
|
156
|
+
|
157
|
+
if namespace
|
158
|
+
options.merge!(I18n.translate(:"number.#{namespace}.format", locale: locale, default: {}))
|
159
|
+
end
|
160
|
+
|
161
|
+
options
|
162
|
+
end
|
163
|
+
|
164
|
+
def translate_number_value_with_default(key, **i18n_options)
|
165
|
+
I18n.translate(key, **{ default: default_value(key), scope: :number }.merge!(i18n_options))
|
166
|
+
end
|
167
|
+
|
168
|
+
def translate_in_locale(key, **i18n_options)
|
169
|
+
translate_number_value_with_default(key, **{ locale: options[:locale] }.merge(i18n_options))
|
170
|
+
end
|
171
|
+
|
172
|
+
def default_value(key)
|
173
|
+
key.split(".").reduce(DEFAULTS) { |defaults, k| defaults[k.to_sym] }
|
174
|
+
end
|
175
|
+
|
176
|
+
def valid_float?
|
177
|
+
Float(number, exception: false)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/number_helper/number_converter"
|
4
|
+
|
5
|
+
module ActiveSupport
|
6
|
+
module NumberHelper
|
7
|
+
class NumberToCurrencyConverter < NumberConverter # :nodoc:
|
8
|
+
self.namespace = :currency
|
9
|
+
|
10
|
+
def convert
|
11
|
+
format = options[:format]
|
12
|
+
|
13
|
+
number_f = valid_float?
|
14
|
+
if number_f
|
15
|
+
if number_f.negative?
|
16
|
+
number_f = number_f.abs
|
17
|
+
format = options[:negative_format] if (number_f * 10**options[:precision]) >= 0.5
|
18
|
+
end
|
19
|
+
number_s = NumberToRoundedConverter.convert(number_f, options)
|
20
|
+
else
|
21
|
+
number_s = number.to_s.strip
|
22
|
+
format = options[:negative_format] if number_s.sub!(/^-/, "")
|
23
|
+
end
|
24
|
+
|
25
|
+
format.gsub("%n", number_s).gsub("%u", options[:unit])
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def options
|
30
|
+
@options ||= begin
|
31
|
+
defaults = default_format_options.merge(i18n_opts)
|
32
|
+
# Override negative format if format options are given
|
33
|
+
defaults[:negative_format] = "-#{opts[:format]}" if opts[:format]
|
34
|
+
defaults.merge!(opts)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def i18n_opts
|
39
|
+
# Set International negative format if it does not exist
|
40
|
+
i18n = i18n_format_options
|
41
|
+
i18n[:negative_format] ||= "-#{i18n[:format]}" if i18n[:format]
|
42
|
+
i18n
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/number_helper/number_converter"
|
4
|
+
|
5
|
+
module ActiveSupport
|
6
|
+
module NumberHelper
|
7
|
+
class NumberToDelimitedConverter < NumberConverter # :nodoc:
|
8
|
+
self.validate_float = true
|
9
|
+
|
10
|
+
DEFAULT_DELIMITER_REGEX = /(\d)(?=(\d\d\d)+(?!\d))/
|
11
|
+
|
12
|
+
def convert
|
13
|
+
parts.join(options[:separator])
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def parts
|
18
|
+
left, right = number.to_s.split(".")
|
19
|
+
left.gsub!(delimiter_pattern) do |digit_to_delimit|
|
20
|
+
"#{digit_to_delimit}#{options[:delimiter]}"
|
21
|
+
end
|
22
|
+
[left, right].compact
|
23
|
+
end
|
24
|
+
|
25
|
+
def delimiter_pattern
|
26
|
+
options.fetch(:delimiter_pattern, DEFAULT_DELIMITER_REGEX)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/number_helper/number_converter"
|
4
|
+
|
5
|
+
module ActiveSupport
|
6
|
+
module NumberHelper
|
7
|
+
class NumberToHumanConverter < NumberConverter # :nodoc:
|
8
|
+
DECIMAL_UNITS = { 0 => :unit, 1 => :ten, 2 => :hundred, 3 => :thousand, 6 => :million, 9 => :billion, 12 => :trillion, 15 => :quadrillion,
|
9
|
+
-1 => :deci, -2 => :centi, -3 => :mili, -6 => :micro, -9 => :nano, -12 => :pico, -15 => :femto }
|
10
|
+
INVERTED_DECIMAL_UNITS = DECIMAL_UNITS.invert
|
11
|
+
|
12
|
+
self.namespace = :human
|
13
|
+
self.validate_float = true
|
14
|
+
|
15
|
+
def convert # :nodoc:
|
16
|
+
@number = RoundingHelper.new(options).round(number)
|
17
|
+
@number = Float(number)
|
18
|
+
|
19
|
+
# For backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files.
|
20
|
+
unless options.key?(:strip_insignificant_zeros)
|
21
|
+
options[:strip_insignificant_zeros] = true
|
22
|
+
end
|
23
|
+
|
24
|
+
units = opts[:units]
|
25
|
+
exponent = calculate_exponent(units)
|
26
|
+
@number = number / (10**exponent)
|
27
|
+
|
28
|
+
rounded_number = NumberToRoundedConverter.convert(number, options)
|
29
|
+
unit = determine_unit(units, exponent)
|
30
|
+
format.gsub("%n", rounded_number).gsub("%u", unit).strip
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def format
|
35
|
+
options[:format] || translate_in_locale("human.decimal_units.format")
|
36
|
+
end
|
37
|
+
|
38
|
+
def determine_unit(units, exponent)
|
39
|
+
exp = DECIMAL_UNITS[exponent]
|
40
|
+
case units
|
41
|
+
when Hash
|
42
|
+
units[exp] || ""
|
43
|
+
when String, Symbol
|
44
|
+
I18n.translate("#{units}.#{exp}", locale: options[:locale], count: number.to_i)
|
45
|
+
else
|
46
|
+
translate_in_locale("human.decimal_units.units.#{exp}", count: number.to_i)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def calculate_exponent(units)
|
51
|
+
exponent = number != 0 ? Math.log10(number.abs).floor : 0
|
52
|
+
unit_exponents(units).find { |e| exponent >= e } || 0
|
53
|
+
end
|
54
|
+
|
55
|
+
def unit_exponents(units)
|
56
|
+
case units
|
57
|
+
when Hash
|
58
|
+
units
|
59
|
+
when String, Symbol
|
60
|
+
I18n.translate(units.to_s, locale: options[:locale], raise: true)
|
61
|
+
when nil
|
62
|
+
translate_in_locale("human.decimal_units.units", raise: true)
|
63
|
+
else
|
64
|
+
raise ArgumentError, ":units must be a Hash or String translation scope."
|
65
|
+
end.keys.map { |e_name| INVERTED_DECIMAL_UNITS[e_name] }.sort_by(&:-@)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/number_helper/number_converter"
|
4
|
+
|
5
|
+
module ActiveSupport
|
6
|
+
module NumberHelper
|
7
|
+
class NumberToHumanSizeConverter < NumberConverter # :nodoc:
|
8
|
+
STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb, :pb, :eb]
|
9
|
+
|
10
|
+
self.namespace = :human
|
11
|
+
self.validate_float = true
|
12
|
+
|
13
|
+
def convert
|
14
|
+
@number = Float(number)
|
15
|
+
|
16
|
+
# For backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files.
|
17
|
+
unless options.key?(:strip_insignificant_zeros)
|
18
|
+
options[:strip_insignificant_zeros] = true
|
19
|
+
end
|
20
|
+
|
21
|
+
if smaller_than_base?
|
22
|
+
number_to_format = number.to_i.to_s
|
23
|
+
else
|
24
|
+
human_size = number / (base**exponent)
|
25
|
+
number_to_format = NumberToRoundedConverter.convert(human_size, options)
|
26
|
+
end
|
27
|
+
conversion_format.gsub("%n", number_to_format).gsub("%u", unit)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def conversion_format
|
32
|
+
translate_number_value_with_default("human.storage_units.format", locale: options[:locale], raise: true)
|
33
|
+
end
|
34
|
+
|
35
|
+
def unit
|
36
|
+
translate_number_value_with_default(storage_unit_key, locale: options[:locale], count: number.to_i, raise: true)
|
37
|
+
end
|
38
|
+
|
39
|
+
def storage_unit_key
|
40
|
+
key_end = smaller_than_base? ? "byte" : STORAGE_UNITS[exponent]
|
41
|
+
"human.storage_units.units.#{key_end}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def exponent
|
45
|
+
max = STORAGE_UNITS.size - 1
|
46
|
+
exp = (Math.log(number) / Math.log(base)).to_i
|
47
|
+
exp = max if exp > max # avoid overflow for the highest unit
|
48
|
+
exp
|
49
|
+
end
|
50
|
+
|
51
|
+
def smaller_than_base?
|
52
|
+
number.to_i < base
|
53
|
+
end
|
54
|
+
|
55
|
+
def base
|
56
|
+
1024
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/number_helper/number_converter"
|
4
|
+
|
5
|
+
module ActiveSupport
|
6
|
+
module NumberHelper
|
7
|
+
class NumberToPercentageConverter < NumberConverter # :nodoc:
|
8
|
+
self.namespace = :percentage
|
9
|
+
|
10
|
+
def convert
|
11
|
+
rounded_number = NumberToRoundedConverter.convert(number, options)
|
12
|
+
options[:format].gsub("%n", rounded_number)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|