activesupport 4.2.11.1 → 6.0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (263) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +399 -411
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +7 -7
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/all.rb +5 -3
  7. data/lib/active_support/array_inquirer.rb +48 -0
  8. data/lib/active_support/backtrace_cleaner.rb +34 -6
  9. data/lib/active_support/benchmarkable.rb +6 -4
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +58 -53
  12. data/lib/active_support/cache/mem_cache_store.rb +95 -91
  13. data/lib/active_support/cache/memory_store.rb +39 -36
  14. data/lib/active_support/cache/null_store.rb +11 -7
  15. data/lib/active_support/cache/redis_cache_store.rb +493 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +75 -42
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  18. data/lib/active_support/cache.rb +331 -217
  19. data/lib/active_support/callbacks.rb +650 -592
  20. data/lib/active_support/concern.rb +35 -6
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
  22. data/lib/active_support/concurrency/share_lock.rb +226 -0
  23. data/lib/active_support/configurable.rb +13 -14
  24. data/lib/active_support/core_ext/array/access.rb +41 -1
  25. data/lib/active_support/core_ext/array/conversions.rb +24 -20
  26. data/lib/active_support/core_ext/array/extract.rb +21 -0
  27. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  28. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  29. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  30. data/lib/active_support/core_ext/array/prepend_and_append.rb +4 -6
  31. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  32. data/lib/active_support/core_ext/array.rb +9 -6
  33. data/lib/active_support/core_ext/benchmark.rb +3 -1
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  35. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  36. data/lib/active_support/core_ext/class/attribute.rb +45 -31
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  38. data/lib/active_support/core_ext/class/subclasses.rb +20 -6
  39. data/lib/active_support/core_ext/class.rb +4 -3
  40. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  41. data/lib/active_support/core_ext/date/blank.rb +14 -0
  42. data/lib/active_support/core_ext/date/calculations.rb +17 -14
  43. data/lib/active_support/core_ext/date/conversions.rb +25 -23
  44. data/lib/active_support/core_ext/date/zones.rb +4 -2
  45. data/lib/active_support/core_ext/date.rb +6 -4
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +154 -65
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -3
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -13
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  50. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  51. data/lib/active_support/core_ext/date_time/calculations.rb +37 -19
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
  53. data/lib/active_support/core_ext/date_time/conversions.rb +16 -13
  54. data/lib/active_support/core_ext/date_time.rb +7 -5
  55. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  56. data/lib/active_support/core_ext/digest.rb +3 -0
  57. data/lib/active_support/core_ext/enumerable.rb +114 -22
  58. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  59. data/lib/active_support/core_ext/file.rb +3 -1
  60. data/lib/active_support/core_ext/hash/compact.rb +4 -23
  61. data/lib/active_support/core_ext/hash/conversions.rb +62 -41
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  63. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  64. data/lib/active_support/core_ext/hash/except.rb +12 -9
  65. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  66. data/lib/active_support/core_ext/hash/keys.rb +19 -42
  67. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  68. data/lib/active_support/core_ext/hash/slice.rb +5 -27
  69. data/lib/active_support/core_ext/hash/transform_values.rb +4 -22
  70. data/lib/active_support/core_ext/hash.rb +10 -9
  71. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  72. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  73. data/lib/active_support/core_ext/integer/time.rb +11 -18
  74. data/lib/active_support/core_ext/integer.rb +5 -3
  75. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  76. data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  78. data/lib/active_support/core_ext/kernel.rb +5 -5
  79. data/lib/active_support/core_ext/load_error.rb +3 -22
  80. data/lib/active_support/core_ext/marshal.rb +8 -8
  81. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  82. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  83. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +46 -46
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +144 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  87. data/lib/active_support/core_ext/module/delegation.rb +133 -30
  88. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  89. data/lib/active_support/core_ext/module/introspection.rb +44 -19
  90. data/lib/active_support/core_ext/module/reachable.rb +5 -7
  91. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/module.rb +13 -11
  94. data/lib/active_support/core_ext/name_error.rb +22 -2
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +129 -136
  97. data/lib/active_support/core_ext/numeric/inquiry.rb +5 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +35 -23
  99. data/lib/active_support/core_ext/numeric.rb +5 -3
  100. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  101. data/lib/active_support/core_ext/object/blank.rb +27 -3
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  104. data/lib/active_support/core_ext/object/duplicable.rb +13 -93
  105. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +51 -20
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +10 -5
  110. data/lib/active_support/core_ext/object/try.rb +81 -23
  111. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  112. data/lib/active_support/core_ext/object.rb +14 -13
  113. data/lib/active_support/core_ext/range/compare_range.rb +76 -0
  114. data/lib/active_support/core_ext/range/conversions.rb +37 -15
  115. data/lib/active_support/core_ext/range/each.rb +18 -17
  116. data/lib/active_support/core_ext/range/include_range.rb +7 -21
  117. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  118. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  119. data/lib/active_support/core_ext/range.rb +7 -4
  120. data/lib/active_support/core_ext/regexp.rb +2 -0
  121. data/lib/active_support/core_ext/securerandom.rb +45 -0
  122. data/lib/active_support/core_ext/string/access.rb +16 -6
  123. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  124. data/lib/active_support/core_ext/string/conversions.rb +7 -4
  125. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  126. data/lib/active_support/core_ext/string/filters.rb +48 -6
  127. data/lib/active_support/core_ext/string/indent.rb +6 -4
  128. data/lib/active_support/core_ext/string/inflections.rb +66 -24
  129. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  130. data/lib/active_support/core_ext/string/multibyte.rb +16 -7
  131. data/lib/active_support/core_ext/string/output_safety.rb +93 -40
  132. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  133. data/lib/active_support/core_ext/string/strip.rb +6 -5
  134. data/lib/active_support/core_ext/string/zones.rb +4 -2
  135. data/lib/active_support/core_ext/string.rb +15 -13
  136. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  137. data/lib/active_support/core_ext/time/calculations.rb +115 -52
  138. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  139. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  140. data/lib/active_support/core_ext/time/zones.rb +41 -7
  141. data/lib/active_support/core_ext/time.rb +7 -6
  142. data/lib/active_support/core_ext/uri.rb +6 -7
  143. data/lib/active_support/core_ext.rb +3 -1
  144. data/lib/active_support/current_attributes.rb +203 -0
  145. data/lib/active_support/dependencies/autoload.rb +2 -0
  146. data/lib/active_support/dependencies/interlock.rb +57 -0
  147. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  148. data/lib/active_support/dependencies.rb +208 -166
  149. data/lib/active_support/deprecation/behaviors.rb +44 -11
  150. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  151. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  152. data/lib/active_support/deprecation/method_wrappers.rb +61 -21
  153. data/lib/active_support/deprecation/proxy_wrappers.rb +81 -30
  154. data/lib/active_support/deprecation/reporting.rb +32 -12
  155. data/lib/active_support/deprecation.rb +12 -9
  156. data/lib/active_support/descendants_tracker.rb +57 -9
  157. data/lib/active_support/digest.rb +20 -0
  158. data/lib/active_support/duration/iso8601_parser.rb +123 -0
  159. data/lib/active_support/duration/iso8601_serializer.rb +53 -0
  160. data/lib/active_support/duration.rb +315 -40
  161. data/lib/active_support/encrypted_configuration.rb +45 -0
  162. data/lib/active_support/encrypted_file.rb +100 -0
  163. data/lib/active_support/evented_file_update_checker.rb +234 -0
  164. data/lib/active_support/execution_wrapper.rb +129 -0
  165. data/lib/active_support/executor.rb +8 -0
  166. data/lib/active_support/file_update_checker.rb +62 -37
  167. data/lib/active_support/gem_version.rb +6 -4
  168. data/lib/active_support/gzip.rb +7 -5
  169. data/lib/active_support/hash_with_indifferent_access.rb +129 -30
  170. data/lib/active_support/i18n.rb +9 -6
  171. data/lib/active_support/i18n_railtie.rb +50 -14
  172. data/lib/active_support/inflections.rb +13 -11
  173. data/lib/active_support/inflector/inflections.rb +58 -13
  174. data/lib/active_support/inflector/methods.rb +159 -145
  175. data/lib/active_support/inflector/transliterate.rb +84 -34
  176. data/lib/active_support/inflector.rb +7 -5
  177. data/lib/active_support/json/decoding.rb +32 -30
  178. data/lib/active_support/json/encoding.rb +17 -60
  179. data/lib/active_support/json.rb +4 -2
  180. data/lib/active_support/key_generator.rb +11 -43
  181. data/lib/active_support/lazy_load_hooks.rb +53 -20
  182. data/lib/active_support/locale/en.rb +33 -0
  183. data/lib/active_support/locale/en.yml +2 -0
  184. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  185. data/lib/active_support/log_subscriber.rb +44 -19
  186. data/lib/active_support/logger.rb +9 -23
  187. data/lib/active_support/logger_silence.rb +32 -14
  188. data/lib/active_support/logger_thread_safe_level.rb +32 -8
  189. data/lib/active_support/message_encryptor.rb +166 -53
  190. data/lib/active_support/message_verifier.rb +149 -16
  191. data/lib/active_support/messages/metadata.rb +72 -0
  192. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  193. data/lib/active_support/messages/rotator.rb +56 -0
  194. data/lib/active_support/multibyte/chars.rb +56 -63
  195. data/lib/active_support/multibyte/unicode.rb +56 -290
  196. data/lib/active_support/multibyte.rb +4 -2
  197. data/lib/active_support/notifications/fanout.rb +109 -22
  198. data/lib/active_support/notifications/instrumenter.rb +107 -16
  199. data/lib/active_support/notifications.rb +51 -10
  200. data/lib/active_support/number_helper/number_converter.rb +16 -15
  201. data/lib/active_support/number_helper/number_to_currency_converter.rb +14 -15
  202. data/lib/active_support/number_helper/number_to_delimited_converter.rb +11 -4
  203. data/lib/active_support/number_helper/number_to_human_converter.rb +13 -10
  204. data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -9
  205. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  206. data/lib/active_support/number_helper/number_to_phone_converter.rb +15 -5
  207. data/lib/active_support/number_helper/number_to_rounded_converter.rb +25 -57
  208. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  209. data/lib/active_support/number_helper.rb +105 -68
  210. data/lib/active_support/option_merger.rb +24 -4
  211. data/lib/active_support/ordered_hash.rb +7 -5
  212. data/lib/active_support/ordered_options.rb +27 -5
  213. data/lib/active_support/parameter_filter.rb +128 -0
  214. data/lib/active_support/per_thread_registry.rb +9 -4
  215. data/lib/active_support/proxy_object.rb +2 -0
  216. data/lib/active_support/rails.rb +10 -8
  217. data/lib/active_support/railtie.rb +43 -9
  218. data/lib/active_support/reloader.rb +130 -0
  219. data/lib/active_support/rescuable.rb +108 -53
  220. data/lib/active_support/security_utils.rb +15 -11
  221. data/lib/active_support/string_inquirer.rb +11 -4
  222. data/lib/active_support/subscriber.rb +74 -30
  223. data/lib/active_support/tagged_logging.rb +25 -13
  224. data/lib/active_support/test_case.rb +107 -44
  225. data/lib/active_support/testing/assertions.rb +151 -20
  226. data/lib/active_support/testing/autorun.rb +4 -2
  227. data/lib/active_support/testing/constant_lookup.rb +2 -1
  228. data/lib/active_support/testing/declarative.rb +3 -1
  229. data/lib/active_support/testing/deprecation.rb +13 -10
  230. data/lib/active_support/testing/file_fixtures.rb +38 -0
  231. data/lib/active_support/testing/isolation.rb +35 -26
  232. data/lib/active_support/testing/method_call_assertions.rb +70 -0
  233. data/lib/active_support/testing/parallelization.rb +134 -0
  234. data/lib/active_support/testing/setup_and_teardown.rb +13 -8
  235. data/lib/active_support/testing/stream.rb +43 -0
  236. data/lib/active_support/testing/tagged_logging.rb +3 -1
  237. data/lib/active_support/testing/time_helpers.rb +84 -20
  238. data/lib/active_support/time.rb +14 -12
  239. data/lib/active_support/time_with_zone.rb +179 -39
  240. data/lib/active_support/values/time_zone.rb +203 -63
  241. data/lib/active_support/version.rb +3 -1
  242. data/lib/active_support/xml_mini/jdom.rb +116 -115
  243. data/lib/active_support/xml_mini/libxml.rb +16 -13
  244. data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
  245. data/lib/active_support/xml_mini/nokogiri.rb +14 -12
  246. data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
  247. data/lib/active_support/xml_mini/rexml.rb +11 -9
  248. data/lib/active_support/xml_mini.rb +38 -46
  249. data/lib/active_support.rb +13 -11
  250. metadata +84 -26
  251. data/lib/active_support/concurrency/latch.rb +0 -27
  252. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
  253. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  254. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  255. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  256. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  257. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
  258. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  259. data/lib/active_support/core_ext/object/itself.rb +0 -15
  260. data/lib/active_support/core_ext/struct.rb +0 -6
  261. data/lib/active_support/core_ext/thread.rb +0 -86
  262. data/lib/active_support/core_ext/time/marshal.rb +0 -30
  263. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,4 +1,6 @@
1
- require 'securerandom'
1
+ # frozen_string_literal: true
2
+
3
+ require "securerandom"
2
4
 
3
5
  module ActiveSupport
4
6
  module Notifications
@@ -11,18 +13,21 @@ module ActiveSupport
11
13
  @notifier = notifier
12
14
  end
13
15
 
14
- # Instrument the given block by measuring the time taken to execute it
15
- # and publish it. Notice that events get sent even if an error occurs
16
- # in the passed-in block.
17
- def instrument(name, payload={})
18
- start name, payload
16
+ # Given a block, instrument it by measuring the time taken to execute
17
+ # and publish it. Without a block, simply send a message via the
18
+ # notifier. Notice that events get sent even if an error occurs in the
19
+ # passed-in block.
20
+ def instrument(name, payload = {})
21
+ # some of the listeners might have state
22
+ listeners_state = start name, payload
19
23
  begin
20
- yield payload
24
+ yield payload if block_given?
21
25
  rescue Exception => e
22
26
  payload[:exception] = [e.class.name, e.message]
27
+ payload[:exception_object] = e
23
28
  raise e
24
29
  ensure
25
- finish name, payload
30
+ finish_with_state listeners_state, name, payload
26
31
  end
27
32
  end
28
33
 
@@ -36,16 +41,25 @@ module ActiveSupport
36
41
  @notifier.finish name, @id, payload
37
42
  end
38
43
 
39
- private
40
-
41
- def unique_id
42
- SecureRandom.hex(10)
44
+ def finish_with_state(listeners_state, name, payload)
45
+ @notifier.finish name, @id, payload, listeners_state
43
46
  end
47
+
48
+ private
49
+ def unique_id
50
+ SecureRandom.hex(10)
51
+ end
44
52
  end
45
53
 
46
54
  class Event
47
- attr_reader :name, :time, :transaction_id, :payload, :children
48
- attr_accessor :end
55
+ attr_reader :name, :time, :end, :transaction_id, :payload, :children
56
+
57
+ def self.clock_gettime_supported? # :nodoc:
58
+ defined?(Process::CLOCK_THREAD_CPUTIME_ID) &&
59
+ !Gem.win_platform? &&
60
+ !RUBY_PLATFORM.match?(/solaris/i)
61
+ end
62
+ private_class_method :clock_gettime_supported?
49
63
 
50
64
  def initialize(name, start, ending, transaction_id, payload)
51
65
  @name = name
@@ -54,11 +68,63 @@ module ActiveSupport
54
68
  @transaction_id = transaction_id
55
69
  @end = ending
56
70
  @children = []
57
- @duration = nil
71
+ @cpu_time_start = 0
72
+ @cpu_time_finish = 0
73
+ @allocation_count_start = 0
74
+ @allocation_count_finish = 0
75
+ end
76
+
77
+ # Record information at the time this event starts
78
+ def start!
79
+ @time = now
80
+ @cpu_time_start = now_cpu
81
+ @allocation_count_start = now_allocations
82
+ end
83
+
84
+ # Record information at the time this event finishes
85
+ def finish!
86
+ @cpu_time_finish = now_cpu
87
+ @end = now
88
+ @allocation_count_finish = now_allocations
89
+ end
90
+
91
+ def end=(ending)
92
+ ActiveSupport::Deprecation.deprecation_warning(:end=, :finish!)
93
+ @end = ending
58
94
  end
59
95
 
96
+ # Returns the CPU time (in milliseconds) passed since the call to
97
+ # +start!+ and the call to +finish!+
98
+ def cpu_time
99
+ (@cpu_time_finish - @cpu_time_start) * 1000
100
+ end
101
+
102
+ # Returns the idle time time (in milliseconds) passed since the call to
103
+ # +start!+ and the call to +finish!+
104
+ def idle_time
105
+ duration - cpu_time
106
+ end
107
+
108
+ # Returns the number of allocations made since the call to +start!+ and
109
+ # the call to +finish!+
110
+ def allocations
111
+ @allocation_count_finish - @allocation_count_start
112
+ end
113
+
114
+ # Returns the difference in milliseconds between when the execution of the
115
+ # event started and when it ended.
116
+ #
117
+ # ActiveSupport::Notifications.subscribe('wait') do |*args|
118
+ # @event = ActiveSupport::Notifications::Event.new(*args)
119
+ # end
120
+ #
121
+ # ActiveSupport::Notifications.instrument('wait') do
122
+ # sleep 1
123
+ # end
124
+ #
125
+ # @event.duration # => 1000.138
60
126
  def duration
61
- @duration ||= 1000.0 * (self.end - time)
127
+ 1000.0 * (self.end - time)
62
128
  end
63
129
 
64
130
  def <<(event)
@@ -68,6 +134,31 @@ module ActiveSupport
68
134
  def parent_of?(event)
69
135
  @children.include? event
70
136
  end
137
+
138
+ private
139
+ def now
140
+ Concurrent.monotonic_time
141
+ end
142
+
143
+ if clock_gettime_supported?
144
+ def now_cpu
145
+ Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID)
146
+ end
147
+ else
148
+ def now_cpu
149
+ 0
150
+ end
151
+ end
152
+
153
+ if defined?(JRUBY_VERSION)
154
+ def now_allocations
155
+ 0
156
+ end
157
+ else
158
+ def now_allocations
159
+ GC.stat :total_allocated_objects
160
+ end
161
+ end
71
162
  end
72
163
  end
73
164
  end
@@ -1,6 +1,8 @@
1
- require 'active_support/notifications/instrumenter'
2
- require 'active_support/notifications/fanout'
3
- require 'active_support/per_thread_registry'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/notifications/instrumenter"
4
+ require "active_support/notifications/fanout"
5
+ require "active_support/per_thread_registry"
4
6
 
5
7
  module ActiveSupport
6
8
  # = Notifications
@@ -13,7 +15,7 @@ module ActiveSupport
13
15
  # To instrument an event you just need to do:
14
16
  #
15
17
  # ActiveSupport::Notifications.instrument('render', extra: :information) do
16
- # render text: 'Foo'
18
+ # render plain: 'Foo'
17
19
  # end
18
20
  #
19
21
  # That first executes the block and then notifies all subscribers once done.
@@ -32,7 +34,7 @@ module ActiveSupport
32
34
  # name # => String, name of the event (such as 'render' from above)
33
35
  # start # => Time, when the instrumented block started execution
34
36
  # finish # => Time, when the instrumented block ended execution
35
- # id # => String, unique ID for this notification
37
+ # id # => String, unique ID for the instrumenter that fired the event
36
38
  # payload # => Hash, the payload
37
39
  # end
38
40
  #
@@ -48,7 +50,7 @@ module ActiveSupport
48
50
  # The block is saved and will be called whenever someone instruments "render":
49
51
  #
50
52
  # ActiveSupport::Notifications.instrument('render', extra: :information) do
51
- # render text: 'Foo'
53
+ # render plain: 'Foo'
52
54
  # end
53
55
  #
54
56
  # event = events.first
@@ -57,20 +59,25 @@ module ActiveSupport
57
59
  # event.payload # => { extra: :information }
58
60
  #
59
61
  # 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
62
+ # timestamp, end timestamp, a string with a unique identifier for that event's instrumenter
61
63
  # (something like "535801666f04d0298cd6"), and a hash with the payload, in
62
64
  # that order.
63
65
  #
64
66
  # If an exception happens during that particular instrumentation the payload will
65
67
  # have a key <tt>:exception</tt> with an array of two elements as value: a string with
66
68
  # the name of the exception class, and the exception message.
69
+ # The <tt>:exception_object</tt> key of the payload will have the exception
70
+ # itself as the value:
71
+ #
72
+ # event.payload[:exception] # => ["ArgumentError", "Invalid value"]
73
+ # event.payload[:exception_object] # => #<ArgumentError: Invalid value>
67
74
  #
68
- # As the previous example depicts, the class <tt>ActiveSupport::Notifications::Event</tt>
75
+ # As the earlier example depicts, the class <tt>ActiveSupport::Notifications::Event</tt>
69
76
  # is able to take the arguments as they come and provide an object-oriented
70
77
  # interface to that data.
71
78
  #
72
- # It is also possible to pass an object as the second parameter passed to the
73
- # <tt>subscribe</tt> method instead of a block:
79
+ # It is also possible to pass an object which responds to <tt>call</tt> method
80
+ # as the second parameter to the <tt>subscribe</tt> method instead of a block:
74
81
  #
75
82
  # module ActionController
76
83
  # class PageRequest
@@ -146,6 +153,15 @@ module ActiveSupport
146
153
  #
147
154
  # ActiveSupport::Notifications.unsubscribe("render")
148
155
  #
156
+ # Subscribers using a regexp or other pattern-matching object will remain subscribed
157
+ # to all events that match their original pattern, unless those events match a string
158
+ # passed to `unsubscribe`:
159
+ #
160
+ # subscriber = ActiveSupport::Notifications.subscribe(/render/) { }
161
+ # ActiveSupport::Notifications.unsubscribe('render_template.action_view')
162
+ # subscriber.matches?('render_template.action_view') # => false
163
+ # subscriber.matches?('render_partial.action_view') # => true
164
+ #
149
165
  # == Default Queue
150
166
  #
151
167
  # Notifications ships with a queue implementation that consumes and publishes events
@@ -167,6 +183,31 @@ module ActiveSupport
167
183
  end
168
184
  end
169
185
 
186
+ # Subscribe to a given event name with the passed +block+.
187
+ #
188
+ # You can subscribe to events by passing a String to match exact event
189
+ # names, or by passing a Regexp to match all events that match a pattern.
190
+ #
191
+ # ActiveSupport::Notifications.subscribe(/render/) do |*args|
192
+ # @event = ActiveSupport::Notifications::Event.new(*args)
193
+ # end
194
+ #
195
+ # The +block+ will receive five parameters with information about the event:
196
+ #
197
+ # ActiveSupport::Notifications.subscribe('render') do |name, start, finish, id, payload|
198
+ # name # => String, name of the event (such as 'render' from above)
199
+ # start # => Time, when the instrumented block started execution
200
+ # finish # => Time, when the instrumented block ended execution
201
+ # id # => String, unique ID for the instrumenter that fired the event
202
+ # payload # => Hash, the payload
203
+ # end
204
+ #
205
+ # If the block passed to the method only takes one parameter,
206
+ # it will yield an event object to the block:
207
+ #
208
+ # ActiveSupport::Notifications.subscribe(/render/) do |event|
209
+ # @event = event
210
+ # end
170
211
  def subscribe(*args, &block)
171
212
  notifier.subscribe(*args, &block)
172
213
  end
@@ -1,8 +1,10 @@
1
- require 'active_support/core_ext/big_decimal/conversions'
2
- require 'active_support/core_ext/object/blank'
3
- require 'active_support/core_ext/hash/keys'
4
- require 'active_support/i18n'
5
- require 'active_support/core_ext/class/attribute'
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"
6
8
 
7
9
  module ActiveSupport
8
10
  module NumberHelper
@@ -134,22 +136,21 @@ module ActiveSupport
134
136
  end
135
137
 
136
138
  private
137
-
138
139
  def options
139
140
  @options ||= format_options.merge(opts)
140
141
  end
141
142
 
142
- def format_options #:nodoc:
143
+ def format_options
143
144
  default_format_options.merge!(i18n_format_options)
144
145
  end
145
146
 
146
- def default_format_options #:nodoc:
147
+ def default_format_options
147
148
  options = DEFAULTS[:format].dup
148
149
  options.merge!(DEFAULTS[namespace][:format]) if namespace
149
150
  options
150
151
  end
151
152
 
152
- def i18n_format_options #:nodoc:
153
+ def i18n_format_options
153
154
  locale = opts[:locale]
154
155
  options = I18n.translate(:'number.format', locale: locale, default: {}).dup
155
156
 
@@ -160,19 +161,19 @@ module ActiveSupport
160
161
  options
161
162
  end
162
163
 
163
- def translate_number_value_with_default(key, i18n_options = {}) #:nodoc:
164
- I18n.translate(key, { default: default_value(key), scope: :number }.merge!(i18n_options))
164
+ def translate_number_value_with_default(key, **i18n_options)
165
+ I18n.translate(key, **{ default: default_value(key), scope: :number }.merge!(i18n_options))
165
166
  end
166
167
 
167
- def translate_in_locale(key, i18n_options = {})
168
- translate_number_value_with_default(key, { locale: options[:locale] }.merge(i18n_options))
168
+ def translate_in_locale(key, **i18n_options)
169
+ translate_number_value_with_default(key, **{ locale: options[:locale] }.merge(i18n_options))
169
170
  end
170
171
 
171
172
  def default_value(key)
172
- key.split('.').reduce(DEFAULTS) { |defaults, k| defaults[k.to_sym] }
173
+ key.split(".").reduce(DEFAULTS) { |defaults, k| defaults[k.to_sym] }
173
174
  end
174
175
 
175
- def valid_float? #:nodoc:
176
+ def valid_float?
176
177
  Float(number)
177
178
  rescue ArgumentError, TypeError
178
179
  false
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/number_helper/number_converter"
4
+
1
5
  module ActiveSupport
2
6
  module NumberHelper
3
7
  class NumberToCurrencyConverter < NumberConverter # :nodoc:
@@ -5,38 +9,33 @@ module ActiveSupport
5
9
 
6
10
  def convert
7
11
  number = self.number.to_s.strip
12
+ number_f = number.to_f
8
13
  format = options[:format]
9
14
 
10
- if is_negative?(number)
11
- format = options[:negative_format]
12
- number = absolute_value(number)
15
+ if number_f.negative?
16
+ number = number_f.abs
17
+
18
+ unless options[:precision] == 0 && number < 0.5
19
+ format = options[:negative_format]
20
+ end
13
21
  end
14
22
 
15
23
  rounded_number = NumberToRoundedConverter.convert(number, options)
16
- format.gsub(/%n/, rounded_number).gsub(/%u/, options[:unit])
24
+ format.gsub("%n", rounded_number).gsub("%u", options[:unit])
17
25
  end
18
26
 
19
27
  private
20
-
21
- def is_negative?(number)
22
- number.to_f.phase != 0
23
- end
24
-
25
- def absolute_value(number)
26
- number.respond_to?("abs") ? number.abs : number.sub(/\A-/, '')
27
- end
28
-
29
28
  def options
30
29
  @options ||= begin
31
30
  defaults = default_format_options.merge(i18n_opts)
32
- # Override negative format if format options is given
31
+ # Override negative format if format options are given
33
32
  defaults[:negative_format] = "-#{opts[:format]}" if opts[:format]
34
33
  defaults.merge!(opts)
35
34
  end
36
35
  end
37
36
 
38
37
  def i18n_opts
39
- # Set International negative format if not exists
38
+ # Set International negative format if it does not exist
40
39
  i18n = i18n_format_options
41
40
  i18n[:negative_format] ||= "-#{i18n[:format]}" if i18n[:format]
42
41
  i18n
@@ -1,23 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/number_helper/number_converter"
4
+
1
5
  module ActiveSupport
2
6
  module NumberHelper
3
7
  class NumberToDelimitedConverter < NumberConverter #:nodoc:
4
8
  self.validate_float = true
5
9
 
6
- DELIMITED_REGEX = /(\d)(?=(\d\d\d)+(?!\d))/
10
+ DEFAULT_DELIMITER_REGEX = /(\d)(?=(\d\d\d)+(?!\d))/
7
11
 
8
12
  def convert
9
13
  parts.join(options[:separator])
10
14
  end
11
15
 
12
16
  private
13
-
14
17
  def parts
15
- left, right = number.to_s.split('.')
16
- left.gsub!(DELIMITED_REGEX) do |digit_to_delimit|
18
+ left, right = number.to_s.split(".")
19
+ left.gsub!(delimiter_pattern) do |digit_to_delimit|
17
20
  "#{digit_to_delimit}#{options[:delimiter]}"
18
21
  end
19
22
  [left, right].compact
20
23
  end
24
+
25
+ def delimiter_pattern
26
+ options.fetch(:delimiter_pattern, DEFAULT_DELIMITER_REGEX)
27
+ end
21
28
  end
22
29
  end
23
30
  end
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/number_helper/number_converter"
4
+
1
5
  module ActiveSupport
2
6
  module NumberHelper
3
7
  class NumberToHumanConverter < NumberConverter # :nodoc:
@@ -9,6 +13,7 @@ module ActiveSupport
9
13
  self.validate_float = true
10
14
 
11
15
  def convert # :nodoc:
16
+ @number = RoundingHelper.new(options).round(number)
12
17
  @number = Float(number)
13
18
 
14
19
  # for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
@@ -18,27 +23,25 @@ module ActiveSupport
18
23
 
19
24
  units = opts[:units]
20
25
  exponent = calculate_exponent(units)
21
- @number = number / (10 ** exponent)
22
-
23
- unit = determine_unit(units, exponent)
26
+ @number = number / (10**exponent)
24
27
 
25
28
  rounded_number = NumberToRoundedConverter.convert(number, options)
26
- format.gsub(/%n/, rounded_number).gsub(/%u/, unit).strip
29
+ unit = determine_unit(units, exponent)
30
+ format.gsub("%n", rounded_number).gsub("%u", unit).strip
27
31
  end
28
32
 
29
33
  private
30
-
31
34
  def format
32
- options[:format] || translate_in_locale('human.decimal_units.format')
35
+ options[:format] || translate_in_locale("human.decimal_units.format")
33
36
  end
34
37
 
35
38
  def determine_unit(units, exponent)
36
39
  exp = DECIMAL_UNITS[exponent]
37
40
  case units
38
41
  when Hash
39
- units[exp] || ''
42
+ units[exp] || ""
40
43
  when String, Symbol
41
- I18n.translate("#{units}.#{exp}", :locale => options[:locale], :count => number.to_i)
44
+ I18n.translate("#{units}.#{exp}", locale: options[:locale], count: number.to_i)
42
45
  else
43
46
  translate_in_locale("human.decimal_units.units.#{exp}", count: number.to_i)
44
47
  end
@@ -54,12 +57,12 @@ module ActiveSupport
54
57
  when Hash
55
58
  units
56
59
  when String, Symbol
57
- I18n.translate(units.to_s, :locale => options[:locale], :raise => true)
60
+ I18n.translate(units.to_s, locale: options[:locale], raise: true)
58
61
  when nil
59
62
  translate_in_locale("human.decimal_units.units", raise: true)
60
63
  else
61
64
  raise ArgumentError, ":units must be a Hash or String translation scope."
62
- end.keys.map { |e_name| INVERTED_DECIMAL_UNITS[e_name] }.sort_by { |e| -e }
65
+ end.keys.map { |e_name| INVERTED_DECIMAL_UNITS[e_name] }.sort_by(&:-@)
63
66
  end
64
67
  end
65
68
  end
@@ -1,7 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/number_helper/number_converter"
4
+
1
5
  module ActiveSupport
2
6
  module NumberHelper
3
7
  class NumberToHumanSizeConverter < NumberConverter #:nodoc:
4
- STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb]
8
+ STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb, :pb, :eb]
5
9
 
6
10
  self.namespace = :human
7
11
  self.validate_float = true
@@ -17,24 +21,23 @@ module ActiveSupport
17
21
  if smaller_than_base?
18
22
  number_to_format = number.to_i.to_s
19
23
  else
20
- human_size = number / (base ** exponent)
24
+ human_size = number / (base**exponent)
21
25
  number_to_format = NumberToRoundedConverter.convert(human_size, options)
22
26
  end
23
- conversion_format.gsub(/%n/, number_to_format).gsub(/%u/, unit)
27
+ conversion_format.gsub("%n", number_to_format).gsub("%u", unit)
24
28
  end
25
29
 
26
30
  private
27
-
28
31
  def conversion_format
29
- translate_number_value_with_default('human.storage_units.format', :locale => options[:locale], :raise => true)
32
+ translate_number_value_with_default("human.storage_units.format", locale: options[:locale], raise: true)
30
33
  end
31
34
 
32
35
  def unit
33
- translate_number_value_with_default(storage_unit_key, :locale => options[:locale], :count => number.to_i, :raise => true)
36
+ translate_number_value_with_default(storage_unit_key, locale: options[:locale], count: number.to_i, raise: true)
34
37
  end
35
38
 
36
39
  def storage_unit_key
37
- key_end = smaller_than_base? ? 'byte' : STORAGE_UNITS[exponent]
40
+ key_end = smaller_than_base? ? "byte" : STORAGE_UNITS[exponent]
38
41
  "human.storage_units.units.#{key_end}"
39
42
  end
40
43
 
@@ -50,9 +53,8 @@ module ActiveSupport
50
53
  end
51
54
 
52
55
  def base
53
- opts[:prefix] == :si ? 1000 : 1024
56
+ 1024
54
57
  end
55
58
  end
56
59
  end
57
60
  end
58
-
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/number_helper/number_converter"
4
+
1
5
  module ActiveSupport
2
6
  module NumberHelper
3
7
  class NumberToPercentageConverter < NumberConverter # :nodoc:
@@ -5,7 +9,7 @@ module ActiveSupport
5
9
 
6
10
  def convert
7
11
  rounded_number = NumberToRoundedConverter.convert(number, options)
8
- options[:format].gsub(/%n/, rounded_number)
12
+ options[:format].gsub("%n", rounded_number)
9
13
  end
10
14
  end
11
15
  end
@@ -1,14 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/number_helper/number_converter"
4
+
1
5
  module ActiveSupport
2
6
  module NumberHelper
3
7
  class NumberToPhoneConverter < NumberConverter #:nodoc:
4
8
  def convert
5
- str = country_code(opts[:country_code])
9
+ str = country_code(opts[:country_code]).dup
6
10
  str << convert_to_phone_number(number.to_s.strip)
7
11
  str << phone_ext(opts[:extension])
8
12
  end
9
13
 
10
14
  private
11
-
12
15
  def convert_to_phone_number(number)
13
16
  if opts[:area_code]
14
17
  convert_with_area_code(number)
@@ -18,12 +21,16 @@ module ActiveSupport
18
21
  end
19
22
 
20
23
  def convert_with_area_code(number)
21
- number.gsub!(/(\d{1,3})(\d{3})(\d{4}$)/,"(\\1) \\2#{delimiter}\\3")
24
+ default_pattern = /(\d{1,3})(\d{3})(\d{4}$)/
25
+ number.gsub!(regexp_pattern(default_pattern),
26
+ "(\\1) \\2#{delimiter}\\3")
22
27
  number
23
28
  end
24
29
 
25
30
  def convert_without_area_code(number)
26
- number.gsub!(/(\d{0,3})(\d{3})(\d{4})$/,"\\1#{delimiter}\\2#{delimiter}\\3")
31
+ default_pattern = /(\d{0,3})(\d{3})(\d{4})$/
32
+ number.gsub!(regexp_pattern(default_pattern),
33
+ "\\1#{delimiter}\\2#{delimiter}\\3")
27
34
  number.slice!(0, 1) if start_with_delimiter?(number)
28
35
  number
29
36
  end
@@ -43,7 +50,10 @@ module ActiveSupport
43
50
  def phone_ext(ext)
44
51
  ext.blank? ? "" : " x #{ext}"
45
52
  end
53
+
54
+ def regexp_pattern(default_pattern)
55
+ opts.fetch :pattern, default_pattern
56
+ end
46
57
  end
47
58
  end
48
59
  end
49
-