activesupport 5.2.4.4 → 6.1.1

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.

Files changed (187) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +353 -435
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -3
  5. data/lib/active_support.rb +14 -1
  6. data/lib/active_support/actionable_error.rb +48 -0
  7. data/lib/active_support/array_inquirer.rb +4 -2
  8. data/lib/active_support/backtrace_cleaner.rb +29 -3
  9. data/lib/active_support/benchmarkable.rb +1 -1
  10. data/lib/active_support/cache.rb +142 -78
  11. data/lib/active_support/cache/file_store.rb +33 -33
  12. data/lib/active_support/cache/mem_cache_store.rb +32 -20
  13. data/lib/active_support/cache/memory_store.rb +59 -33
  14. data/lib/active_support/cache/null_store.rb +8 -3
  15. data/lib/active_support/cache/redis_cache_store.rb +70 -43
  16. data/lib/active_support/cache/strategy/local_cache.rb +41 -26
  17. data/lib/active_support/callbacks.rb +81 -64
  18. data/lib/active_support/concern.rb +70 -3
  19. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
  20. data/lib/active_support/concurrency/share_lock.rb +0 -1
  21. data/lib/active_support/configurable.rb +10 -14
  22. data/lib/active_support/configuration_file.rb +46 -0
  23. data/lib/active_support/core_ext.rb +1 -1
  24. data/lib/active_support/core_ext/array.rb +1 -1
  25. data/lib/active_support/core_ext/array/access.rb +18 -6
  26. data/lib/active_support/core_ext/array/conversions.rb +5 -5
  27. data/lib/active_support/core_ext/array/extract.rb +21 -0
  28. data/lib/active_support/core_ext/benchmark.rb +2 -2
  29. data/lib/active_support/core_ext/class/attribute.rb +32 -47
  30. data/lib/active_support/core_ext/class/subclasses.rb +17 -38
  31. data/lib/active_support/core_ext/date/calculations.rb +6 -5
  32. data/lib/active_support/core_ext/date/conversions.rb +2 -1
  33. data/lib/active_support/core_ext/date_and_time/calculations.rb +37 -47
  34. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  35. data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
  36. data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
  37. data/lib/active_support/core_ext/date_time/conversions.rb +0 -1
  38. data/lib/active_support/core_ext/enumerable.rb +171 -75
  39. data/lib/active_support/core_ext/hash.rb +1 -2
  40. data/lib/active_support/core_ext/hash/conversions.rb +3 -3
  41. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  42. data/lib/active_support/core_ext/hash/except.rb +2 -2
  43. data/lib/active_support/core_ext/hash/keys.rb +1 -30
  44. data/lib/active_support/core_ext/hash/slice.rb +6 -27
  45. data/lib/active_support/core_ext/integer/multiple.rb +1 -1
  46. data/lib/active_support/core_ext/kernel.rb +0 -1
  47. data/lib/active_support/core_ext/load_error.rb +1 -1
  48. data/lib/active_support/core_ext/marshal.rb +2 -0
  49. data/lib/active_support/core_ext/module.rb +0 -1
  50. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  51. data/lib/active_support/core_ext/module/attribute_accessors.rb +30 -39
  52. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +17 -19
  53. data/lib/active_support/core_ext/module/concerning.rb +8 -2
  54. data/lib/active_support/core_ext/module/delegation.rb +76 -33
  55. data/lib/active_support/core_ext/module/introspection.rb +16 -15
  56. data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
  57. data/lib/active_support/core_ext/name_error.rb +29 -2
  58. data/lib/active_support/core_ext/numeric.rb +0 -1
  59. data/lib/active_support/core_ext/numeric/conversions.rb +129 -129
  60. data/lib/active_support/core_ext/object/blank.rb +1 -2
  61. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  62. data/lib/active_support/core_ext/object/duplicable.rb +7 -114
  63. data/lib/active_support/core_ext/object/json.rb +14 -2
  64. data/lib/active_support/core_ext/object/try.rb +17 -7
  65. data/lib/active_support/core_ext/object/with_options.rb +1 -1
  66. data/lib/active_support/core_ext/range/compare_range.rb +34 -13
  67. data/lib/active_support/core_ext/range/conversions.rb +31 -29
  68. data/lib/active_support/core_ext/range/each.rb +0 -1
  69. data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
  70. data/lib/active_support/core_ext/regexp.rb +8 -5
  71. data/lib/active_support/core_ext/securerandom.rb +23 -3
  72. data/lib/active_support/core_ext/string/access.rb +5 -16
  73. data/lib/active_support/core_ext/string/conversions.rb +1 -0
  74. data/lib/active_support/core_ext/string/filters.rb +42 -1
  75. data/lib/active_support/core_ext/string/inflections.rb +45 -6
  76. data/lib/active_support/core_ext/string/inquiry.rb +1 -0
  77. data/lib/active_support/core_ext/string/multibyte.rb +6 -5
  78. data/lib/active_support/core_ext/string/output_safety.rb +70 -13
  79. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  80. data/lib/active_support/core_ext/string/strip.rb +3 -1
  81. data/lib/active_support/core_ext/symbol.rb +3 -0
  82. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  83. data/lib/active_support/core_ext/time/calculations.rb +50 -3
  84. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  85. data/lib/active_support/core_ext/uri.rb +6 -1
  86. data/lib/active_support/current_attributes.rb +15 -2
  87. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  88. data/lib/active_support/dependencies.rb +109 -34
  89. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  90. data/lib/active_support/deprecation.rb +6 -1
  91. data/lib/active_support/deprecation/behaviors.rb +16 -3
  92. data/lib/active_support/deprecation/disallowed.rb +56 -0
  93. data/lib/active_support/deprecation/instance_delegator.rb +0 -1
  94. data/lib/active_support/deprecation/method_wrappers.rb +18 -23
  95. data/lib/active_support/deprecation/proxy_wrappers.rb +29 -6
  96. data/lib/active_support/deprecation/reporting.rb +50 -7
  97. data/lib/active_support/descendants_tracker.rb +59 -9
  98. data/lib/active_support/duration.rb +90 -38
  99. data/lib/active_support/duration/iso8601_parser.rb +2 -4
  100. data/lib/active_support/duration/iso8601_serializer.rb +18 -14
  101. data/lib/active_support/encrypted_configuration.rb +0 -4
  102. data/lib/active_support/encrypted_file.rb +22 -4
  103. data/lib/active_support/environment_inquirer.rb +20 -0
  104. data/lib/active_support/evented_file_update_checker.rb +82 -117
  105. data/lib/active_support/execution_wrapper.rb +1 -0
  106. data/lib/active_support/file_update_checker.rb +0 -1
  107. data/lib/active_support/fork_tracker.rb +62 -0
  108. data/lib/active_support/gem_version.rb +4 -4
  109. data/lib/active_support/hash_with_indifferent_access.rb +64 -41
  110. data/lib/active_support/i18n.rb +1 -0
  111. data/lib/active_support/i18n_railtie.rb +15 -8
  112. data/lib/active_support/inflector/inflections.rb +2 -7
  113. data/lib/active_support/inflector/methods.rb +49 -58
  114. data/lib/active_support/inflector/transliterate.rb +47 -18
  115. data/lib/active_support/json/decoding.rb +25 -26
  116. data/lib/active_support/json/encoding.rb +11 -3
  117. data/lib/active_support/key_generator.rb +1 -33
  118. data/lib/active_support/lazy_load_hooks.rb +5 -2
  119. data/lib/active_support/locale/en.rb +33 -0
  120. data/lib/active_support/locale/en.yml +7 -3
  121. data/lib/active_support/log_subscriber.rb +39 -9
  122. data/lib/active_support/logger.rb +2 -17
  123. data/lib/active_support/logger_silence.rb +11 -19
  124. data/lib/active_support/logger_thread_safe_level.rb +50 -6
  125. data/lib/active_support/message_encryptor.rb +8 -13
  126. data/lib/active_support/message_verifier.rb +10 -10
  127. data/lib/active_support/messages/metadata.rb +11 -2
  128. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  129. data/lib/active_support/messages/rotator.rb +10 -9
  130. data/lib/active_support/multibyte/chars.rb +10 -68
  131. data/lib/active_support/multibyte/unicode.rb +15 -327
  132. data/lib/active_support/notifications.rb +72 -8
  133. data/lib/active_support/notifications/fanout.rb +116 -16
  134. data/lib/active_support/notifications/instrumenter.rb +71 -9
  135. data/lib/active_support/number_helper.rb +38 -12
  136. data/lib/active_support/number_helper/number_converter.rb +5 -6
  137. data/lib/active_support/number_helper/number_to_currency_converter.rb +4 -9
  138. data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -2
  139. data/lib/active_support/number_helper/number_to_human_converter.rb +4 -3
  140. data/lib/active_support/number_helper/number_to_human_size_converter.rb +4 -3
  141. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  142. data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
  143. data/lib/active_support/number_helper/number_to_rounded_converter.rb +8 -7
  144. data/lib/active_support/number_helper/rounding_helper.rb +12 -28
  145. data/lib/active_support/option_merger.rb +22 -3
  146. data/lib/active_support/ordered_hash.rb +1 -1
  147. data/lib/active_support/ordered_options.rb +13 -3
  148. data/lib/active_support/parameter_filter.rb +133 -0
  149. data/lib/active_support/per_thread_registry.rb +1 -1
  150. data/lib/active_support/rails.rb +1 -10
  151. data/lib/active_support/railtie.rb +23 -1
  152. data/lib/active_support/reloader.rb +4 -5
  153. data/lib/active_support/rescuable.rb +4 -4
  154. data/lib/active_support/secure_compare_rotator.rb +51 -0
  155. data/lib/active_support/security_utils.rb +19 -12
  156. data/lib/active_support/string_inquirer.rb +4 -3
  157. data/lib/active_support/subscriber.rb +72 -28
  158. data/lib/active_support/tagged_logging.rb +42 -8
  159. data/lib/active_support/test_case.rb +91 -0
  160. data/lib/active_support/testing/assertions.rb +30 -9
  161. data/lib/active_support/testing/deprecation.rb +0 -1
  162. data/lib/active_support/testing/file_fixtures.rb +2 -0
  163. data/lib/active_support/testing/isolation.rb +2 -2
  164. data/lib/active_support/testing/method_call_assertions.rb +28 -1
  165. data/lib/active_support/testing/parallelization.rb +51 -0
  166. data/lib/active_support/testing/parallelization/server.rb +78 -0
  167. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  168. data/lib/active_support/testing/stream.rb +1 -2
  169. data/lib/active_support/testing/time_helpers.rb +47 -12
  170. data/lib/active_support/time_with_zone.rb +81 -47
  171. data/lib/active_support/values/time_zone.rb +32 -17
  172. data/lib/active_support/xml_mini.rb +2 -10
  173. data/lib/active_support/xml_mini/jdom.rb +2 -3
  174. data/lib/active_support/xml_mini/libxml.rb +2 -2
  175. data/lib/active_support/xml_mini/libxmlsax.rb +4 -4
  176. data/lib/active_support/xml_mini/nokogiri.rb +2 -2
  177. data/lib/active_support/xml_mini/nokogirisax.rb +3 -3
  178. data/lib/active_support/xml_mini/rexml.rb +10 -3
  179. metadata +58 -32
  180. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -9
  181. data/lib/active_support/core_ext/hash/compact.rb +0 -29
  182. data/lib/active_support/core_ext/hash/transform_values.rb +0 -32
  183. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
  184. data/lib/active_support/core_ext/module/reachable.rb +0 -11
  185. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -28
  186. data/lib/active_support/core_ext/range/include_range.rb +0 -3
  187. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -104,10 +104,16 @@ class Module
104
104
  # * grok the behavior of our class in one glance,
105
105
  # * clean up monolithic junk-drawer classes by separating their concerns, and
106
106
  # * stop leaning on protected/private for crude "this is internal stuff" modularity.
107
+ #
108
+ # === Prepending concerning
109
+ #
110
+ # <tt>concerning</tt> supports a <tt>prepend: true</tt> argument which will <tt>prepend</tt> the
111
+ # concern instead of using <tt>include</tt> for it.
107
112
  module Concerning
108
113
  # Define a new concern and mix it in.
109
- def concerning(topic, &block)
110
- include concern(topic, &block)
114
+ def concerning(topic, prepend: false, &block)
115
+ method = prepend ? :prepend : :include
116
+ __send__(method, concern(topic, &block))
111
117
  end
112
118
 
113
119
  # A low-cruft shortcut to define a concern.
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "set"
4
- require "active_support/core_ext/regexp"
5
4
 
6
5
  class Module
7
6
  # Error generated by +delegate+ when a method is called on +nil+ and +allow_nil+
@@ -20,10 +19,11 @@ class Module
20
19
  # public methods as your own.
21
20
  #
22
21
  # ==== Options
23
- # * <tt>:to</tt> - Specifies the target object
22
+ # * <tt>:to</tt> - Specifies the target object name as a symbol or string
24
23
  # * <tt>:prefix</tt> - Prefixes the new method with the target name or a custom prefix
25
- # * <tt>:allow_nil</tt> - if set to true, prevents a +Module::DelegationError+
24
+ # * <tt>:allow_nil</tt> - If set to true, prevents a +Module::DelegationError+
26
25
  # from being raised
26
+ # * <tt>:private</tt> - If set to true, changes method visibility to private
27
27
  #
28
28
  # The macro receives one or more method names (specified as symbols or
29
29
  # strings) and the name of the target object via the <tt>:to</tt> option
@@ -114,6 +114,23 @@ class Module
114
114
  # invoice.customer_name # => 'John Doe'
115
115
  # invoice.customer_address # => 'Vimmersvej 13'
116
116
  #
117
+ # The delegated methods are public by default.
118
+ # Pass <tt>private: true</tt> to change that.
119
+ #
120
+ # class User < ActiveRecord::Base
121
+ # has_one :profile
122
+ # delegate :first_name, to: :profile
123
+ # delegate :date_of_birth, to: :profile, private: true
124
+ #
125
+ # def age
126
+ # Date.today.year - date_of_birth.year
127
+ # end
128
+ # end
129
+ #
130
+ # User.new.first_name # => "Tomas"
131
+ # User.new.date_of_birth # => NoMethodError: private method `date_of_birth' called for #<User:0x00000008221340>
132
+ # User.new.age # => 2
133
+ #
117
134
  # If the target is +nil+ and does not respond to the delegated method a
118
135
  # +Module::DelegationError+ is raised. If you wish to instead return +nil+,
119
136
  # use the <tt>:allow_nil</tt> option.
@@ -151,9 +168,9 @@ class Module
151
168
  # Foo.new("Bar").name # raises NoMethodError: undefined method `name'
152
169
  #
153
170
  # The target method must be public, otherwise it will raise +NoMethodError+.
154
- def delegate(*methods, to: nil, prefix: nil, allow_nil: nil)
171
+ def delegate(*methods, to: nil, prefix: nil, allow_nil: nil, private: nil)
155
172
  unless to
156
- raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter)."
173
+ raise ArgumentError, "Delegation needs a target. Supply a keyword argument 'to' (e.g. delegate :hello, to: :greeter)."
157
174
  end
158
175
 
159
176
  if prefix == true && /^[^a-z_]/.match?(to)
@@ -173,10 +190,22 @@ class Module
173
190
  to = to.to_s
174
191
  to = "self.#{to}" if DELEGATION_RESERVED_METHOD_NAMES.include?(to)
175
192
 
193
+ method_def = []
194
+ method_names = []
195
+
176
196
  methods.map do |method|
197
+ method_name = prefix ? "#{method_prefix}#{method}" : method
198
+ method_names << method_name.to_sym
199
+
177
200
  # Attribute writer methods only accept one argument. Makes sure []=
178
201
  # methods still accept two arguments.
179
- definition = /[^\]]=$/.match?(method) ? "arg" : "*args, &block"
202
+ definition = if /[^\]]=$/.match?(method)
203
+ "arg"
204
+ elsif RUBY_VERSION >= "2.7"
205
+ "..."
206
+ else
207
+ "*args, &block"
208
+ end
180
209
 
181
210
  # The following generated method calls the target exactly once, storing
182
211
  # the returned value in a dummy variable.
@@ -186,33 +215,35 @@ class Module
186
215
  # whereas conceptually, from the user point of view, the delegator should
187
216
  # be doing one call.
188
217
  if allow_nil
189
- method_def = [
190
- "def #{method_prefix}#{method}(#{definition})",
191
- "_ = #{to}",
192
- "if !_.nil? || nil.respond_to?(:#{method})",
193
- " _.#{method}(#{definition})",
194
- "end",
195
- "end"
196
- ].join ";"
218
+ method = method.to_s
219
+
220
+ method_def <<
221
+ "def #{method_name}(#{definition})" <<
222
+ " _ = #{to}" <<
223
+ " if !_.nil? || nil.respond_to?(:#{method})" <<
224
+ " _.#{method}(#{definition})" <<
225
+ " end" <<
226
+ "end"
197
227
  else
198
- exception = %(raise DelegationError, "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}")
228
+ method = method.to_s
229
+ method_name = method_name.to_s
199
230
 
200
- method_def = [
201
- "def #{method_prefix}#{method}(#{definition})",
202
- " _ = #{to}",
203
- " _.#{method}(#{definition})",
204
- "rescue NoMethodError => e",
205
- " if _.nil? && e.name == :#{method}",
206
- " #{exception}",
207
- " else",
208
- " raise",
209
- " end",
231
+ method_def <<
232
+ "def #{method_name}(#{definition})" <<
233
+ " _ = #{to}" <<
234
+ " _.#{method}(#{definition})" <<
235
+ "rescue NoMethodError => e" <<
236
+ " if _.nil? && e.name == :#{method}" <<
237
+ %( raise DelegationError, "#{self}##{method_name} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}") <<
238
+ " else" <<
239
+ " raise" <<
240
+ " end" <<
210
241
  "end"
211
- ].join ";"
212
242
  end
213
-
214
- module_eval(method_def, file, line)
215
243
  end
244
+ module_eval(method_def.join(";"), file, line)
245
+ private(*method_names) if private
246
+ method_names
216
247
  end
217
248
 
218
249
  # When building decorators, a common pattern may emerge:
@@ -223,7 +254,7 @@ class Module
223
254
  # end
224
255
  #
225
256
  # def person
226
- # @event.detail.person || @event.creator
257
+ # detail.person || creator
227
258
  # end
228
259
  #
229
260
  # private
@@ -246,7 +277,7 @@ class Module
246
277
  # end
247
278
  #
248
279
  # def person
249
- # @event.detail.person || @event.creator
280
+ # detail.person || creator
250
281
  # end
251
282
  # end
252
283
  #
@@ -254,8 +285,14 @@ class Module
254
285
  # variables, methods, constants, etc.
255
286
  #
256
287
  # The delegated method must be public on the target, otherwise it will
257
- # raise +NoMethodError+.
258
- def delegate_missing_to(target)
288
+ # raise +DelegationError+. If you wish to instead return +nil+,
289
+ # use the <tt>:allow_nil</tt> option.
290
+ #
291
+ # The <tt>marshal_dump</tt> and <tt>_dump</tt> methods are exempt from
292
+ # delegation due to possible interference when calling
293
+ # <tt>Marshal.dump(object)</tt>, should the delegation target method
294
+ # of <tt>object</tt> add or remove instance variables.
295
+ def delegate_missing_to(target, allow_nil: nil)
259
296
  target = target.to_s
260
297
  target = "self.#{target}" if DELEGATION_RESERVED_METHOD_NAMES.include?(target)
261
298
 
@@ -264,6 +301,7 @@ class Module
264
301
  # It may look like an oversight, but we deliberately do not pass
265
302
  # +include_private+, because they do not get delegated.
266
303
 
304
+ return false if name == :marshal_dump || name == :_dump
267
305
  #{target}.respond_to?(name) || super
268
306
  end
269
307
 
@@ -275,13 +313,18 @@ class Module
275
313
  super
276
314
  rescue NoMethodError
277
315
  if #{target}.nil?
278
- raise DelegationError, "\#{method} delegated to #{target}, but #{target} is nil"
316
+ if #{allow_nil == true}
317
+ nil
318
+ else
319
+ raise DelegationError, "\#{method} delegated to #{target}, but #{target} is nil"
320
+ end
279
321
  else
280
322
  raise
281
323
  end
282
324
  end
283
325
  end
284
326
  end
327
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
285
328
  RUBY
286
329
  end
287
330
  end
@@ -1,16 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/string/filters"
3
4
  require "active_support/inflector"
4
5
 
5
6
  class Module
6
7
  # Returns the name of the module containing this one.
7
8
  #
8
- # M::N.parent_name # => "M"
9
- def parent_name
9
+ # M::N.module_parent_name # => "M"
10
+ def module_parent_name
10
11
  if defined?(@parent_name)
11
12
  @parent_name
12
13
  else
13
- parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil
14
+ parent_name = name =~ /::[^:]+\z/ ? -$` : nil
14
15
  @parent_name = parent_name unless frozen?
15
16
  parent_name
16
17
  end
@@ -24,15 +25,15 @@ class Module
24
25
  # end
25
26
  # X = M::N
26
27
  #
27
- # M::N.parent # => M
28
- # X.parent # => M
28
+ # M::N.module_parent # => M
29
+ # X.module_parent # => M
29
30
  #
30
31
  # The parent of top-level and anonymous modules is Object.
31
32
  #
32
- # M.parent # => Object
33
- # Module.new.parent # => Object
34
- def parent
35
- parent_name ? ActiveSupport::Inflector.constantize(parent_name) : Object
33
+ # M.module_parent # => Object
34
+ # Module.new.module_parent # => Object
35
+ def module_parent
36
+ module_parent_name ? ActiveSupport::Inflector.constantize(module_parent_name) : Object
36
37
  end
37
38
 
38
39
  # Returns all the parents of this module according to its name, ordered from
@@ -44,13 +45,13 @@ class Module
44
45
  # end
45
46
  # X = M::N
46
47
  #
47
- # M.parents # => [Object]
48
- # M::N.parents # => [M, Object]
49
- # X.parents # => [M, Object]
50
- def parents
48
+ # M.module_parents # => [Object]
49
+ # M::N.module_parents # => [M, Object]
50
+ # X.module_parents # => [M, Object]
51
+ def module_parents
51
52
  parents = []
52
- if parent_name
53
- parts = parent_name.split("::")
53
+ if module_parent_name
54
+ parts = module_parent_name.split("::")
54
55
  until parts.empty?
55
56
  parents << ActiveSupport::Inflector.constantize(parts * "::")
56
57
  parts.pop
@@ -1,23 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Module
4
- if RUBY_VERSION >= "2.3"
5
- # Marks the named method as intended to be redefined, if it exists.
6
- # Suppresses the Ruby method redefinition warning. Prefer
7
- # #redefine_method where possible.
8
- def silence_redefinition_of_method(method)
9
- if method_defined?(method) || private_method_defined?(method)
10
- # This suppresses the "method redefined" warning; the self-alias
11
- # looks odd, but means we don't need to generate a unique name
12
- alias_method method, method
13
- end
14
- end
15
- else
16
- def silence_redefinition_of_method(method)
17
- if method_defined?(method) || private_method_defined?(method)
18
- alias_method :__rails_redefine, method
19
- remove_method :__rails_redefine
20
- end
4
+ # Marks the named method as intended to be redefined, if it exists.
5
+ # Suppresses the Ruby method redefinition warning. Prefer
6
+ # #redefine_method where possible.
7
+ def silence_redefinition_of_method(method)
8
+ if method_defined?(method) || private_method_defined?(method)
9
+ # This suppresses the "method redefined" warning; the self-alias
10
+ # looks odd, but means we don't need to generate a unique name
11
+ alias_method method, method
21
12
  end
22
13
  end
23
14
 
@@ -14,9 +14,22 @@ class NameError
14
14
  # It extends NameError#message with spell corrections which are SLOW.
15
15
  # We should use original_message message instead.
16
16
  message = respond_to?(:original_message) ? original_message : self.message
17
+ return unless message.start_with?("uninitialized constant ")
17
18
 
18
- if /undefined local variable or method/ !~ message
19
- $1 if /((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/ =~ message
19
+ receiver = begin
20
+ self.receiver
21
+ rescue ArgumentError
22
+ nil
23
+ end
24
+
25
+ if receiver == Object
26
+ name.to_s
27
+ elsif receiver
28
+ "#{real_mod_name(receiver)}::#{self.name}"
29
+ else
30
+ if match = message.match(/((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/)
31
+ match[1]
32
+ end
20
33
  end
21
34
  end
22
35
 
@@ -35,4 +48,18 @@ class NameError
35
48
  missing_name == name.to_s
36
49
  end
37
50
  end
51
+
52
+ private
53
+ UNBOUND_METHOD_MODULE_NAME = Module.instance_method(:name)
54
+ private_constant :UNBOUND_METHOD_MODULE_NAME
55
+
56
+ if UnboundMethod.method_defined?(:bind_call)
57
+ def real_mod_name(mod)
58
+ UNBOUND_METHOD_MODULE_NAME.bind_call(mod)
59
+ end
60
+ else
61
+ def real_mod_name(mod)
62
+ UNBOUND_METHOD_MODULE_NAME.bind(mod).call
63
+ end
64
+ end
38
65
  end
@@ -2,5 +2,4 @@
2
2
 
3
3
  require "active_support/core_ext/numeric/bytes"
4
4
  require "active_support/core_ext/numeric/time"
5
- require "active_support/core_ext/numeric/inquiry"
6
5
  require "active_support/core_ext/numeric/conversions"
@@ -2,139 +2,139 @@
2
2
 
3
3
  require "active_support/core_ext/big_decimal/conversions"
4
4
  require "active_support/number_helper"
5
- require "active_support/core_ext/module/deprecation"
6
5
 
7
- module ActiveSupport::NumericWithFormat
8
- # Provides options for converting numbers into formatted strings.
9
- # Options are provided for phone numbers, currency, percentage,
10
- # precision, positional notation, file size and pretty printing.
11
- #
12
- # ==== Options
13
- #
14
- # For details on which formats use which options, see ActiveSupport::NumberHelper
15
- #
16
- # ==== Examples
17
- #
18
- # Phone Numbers:
19
- # 5551234.to_s(:phone) # => "555-1234"
20
- # 1235551234.to_s(:phone) # => "123-555-1234"
21
- # 1235551234.to_s(:phone, area_code: true) # => "(123) 555-1234"
22
- # 1235551234.to_s(:phone, delimiter: ' ') # => "123 555 1234"
23
- # 1235551234.to_s(:phone, area_code: true, extension: 555) # => "(123) 555-1234 x 555"
24
- # 1235551234.to_s(:phone, country_code: 1) # => "+1-123-555-1234"
25
- # 1235551234.to_s(:phone, country_code: 1, extension: 1343, delimiter: '.')
26
- # # => "+1.123.555.1234 x 1343"
27
- #
28
- # Currency:
29
- # 1234567890.50.to_s(:currency) # => "$1,234,567,890.50"
30
- # 1234567890.506.to_s(:currency) # => "$1,234,567,890.51"
31
- # 1234567890.506.to_s(:currency, precision: 3) # => "$1,234,567,890.506"
32
- # 1234567890.506.to_s(:currency, locale: :fr) # => "1 234 567 890,51 €"
33
- # -1234567890.50.to_s(:currency, negative_format: '(%u%n)')
34
- # # => "($1,234,567,890.50)"
35
- # 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '')
36
- # # => "&pound;1234567890,50"
37
- # 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
38
- # # => "1234567890,50 &pound;"
39
- #
40
- # Percentage:
41
- # 100.to_s(:percentage) # => "100.000%"
42
- # 100.to_s(:percentage, precision: 0) # => "100%"
43
- # 1000.to_s(:percentage, delimiter: '.', separator: ',') # => "1.000,000%"
44
- # 302.24398923423.to_s(:percentage, precision: 5) # => "302.24399%"
45
- # 1000.to_s(:percentage, locale: :fr) # => "1 000,000%"
46
- # 100.to_s(:percentage, format: '%n %') # => "100.000 %"
47
- #
48
- # Delimited:
49
- # 12345678.to_s(:delimited) # => "12,345,678"
50
- # 12345678.05.to_s(:delimited) # => "12,345,678.05"
51
- # 12345678.to_s(:delimited, delimiter: '.') # => "12.345.678"
52
- # 12345678.to_s(:delimited, delimiter: ',') # => "12,345,678"
53
- # 12345678.05.to_s(:delimited, separator: ' ') # => "12,345,678 05"
54
- # 12345678.05.to_s(:delimited, locale: :fr) # => "12 345 678,05"
55
- # 98765432.98.to_s(:delimited, delimiter: ' ', separator: ',')
56
- # # => "98 765 432,98"
57
- #
58
- # Rounded:
59
- # 111.2345.to_s(:rounded) # => "111.235"
60
- # 111.2345.to_s(:rounded, precision: 2) # => "111.23"
61
- # 13.to_s(:rounded, precision: 5) # => "13.00000"
62
- # 389.32314.to_s(:rounded, precision: 0) # => "389"
63
- # 111.2345.to_s(:rounded, significant: true) # => "111"
64
- # 111.2345.to_s(:rounded, precision: 1, significant: true) # => "100"
65
- # 13.to_s(:rounded, precision: 5, significant: true) # => "13.000"
66
- # 111.234.to_s(:rounded, locale: :fr) # => "111,234"
67
- # 13.to_s(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true)
68
- # # => "13"
69
- # 389.32314.to_s(:rounded, precision: 4, significant: true) # => "389.3"
70
- # 1111.2345.to_s(:rounded, precision: 2, separator: ',', delimiter: '.')
71
- # # => "1.111,23"
72
- #
73
- # Human-friendly size in Bytes:
74
- # 123.to_s(:human_size) # => "123 Bytes"
75
- # 1234.to_s(:human_size) # => "1.21 KB"
76
- # 12345.to_s(:human_size) # => "12.1 KB"
77
- # 1234567.to_s(:human_size) # => "1.18 MB"
78
- # 1234567890.to_s(:human_size) # => "1.15 GB"
79
- # 1234567890123.to_s(:human_size) # => "1.12 TB"
80
- # 1234567890123456.to_s(:human_size) # => "1.1 PB"
81
- # 1234567890123456789.to_s(:human_size) # => "1.07 EB"
82
- # 1234567.to_s(:human_size, precision: 2) # => "1.2 MB"
83
- # 483989.to_s(:human_size, precision: 2) # => "470 KB"
84
- # 1234567.to_s(:human_size, precision: 2, separator: ',') # => "1,2 MB"
85
- # 1234567890123.to_s(:human_size, precision: 5) # => "1.1228 TB"
86
- # 524288000.to_s(:human_size, precision: 5) # => "500 MB"
87
- #
88
- # Human-friendly format:
89
- # 123.to_s(:human) # => "123"
90
- # 1234.to_s(:human) # => "1.23 Thousand"
91
- # 12345.to_s(:human) # => "12.3 Thousand"
92
- # 1234567.to_s(:human) # => "1.23 Million"
93
- # 1234567890.to_s(:human) # => "1.23 Billion"
94
- # 1234567890123.to_s(:human) # => "1.23 Trillion"
95
- # 1234567890123456.to_s(:human) # => "1.23 Quadrillion"
96
- # 1234567890123456789.to_s(:human) # => "1230 Quadrillion"
97
- # 489939.to_s(:human, precision: 2) # => "490 Thousand"
98
- # 489939.to_s(:human, precision: 4) # => "489.9 Thousand"
99
- # 1234567.to_s(:human, precision: 4,
100
- # significant: false) # => "1.2346 Million"
101
- # 1234567.to_s(:human, precision: 1,
102
- # separator: ',',
103
- # significant: false) # => "1,2 Million"
104
- def to_s(format = nil, options = nil)
105
- case format
106
- when nil
107
- super()
108
- when Integer, String
109
- super(format)
110
- when :phone
111
- ActiveSupport::NumberHelper.number_to_phone(self, options || {})
112
- when :currency
113
- ActiveSupport::NumberHelper.number_to_currency(self, options || {})
114
- when :percentage
115
- ActiveSupport::NumberHelper.number_to_percentage(self, options || {})
116
- when :delimited
117
- ActiveSupport::NumberHelper.number_to_delimited(self, options || {})
118
- when :rounded
119
- ActiveSupport::NumberHelper.number_to_rounded(self, options || {})
120
- when :human
121
- ActiveSupport::NumberHelper.number_to_human(self, options || {})
122
- when :human_size
123
- ActiveSupport::NumberHelper.number_to_human_size(self, options || {})
124
- when Symbol
125
- super()
126
- else
127
- super(format)
6
+ module ActiveSupport
7
+ module NumericWithFormat
8
+ # Provides options for converting numbers into formatted strings.
9
+ # Options are provided for phone numbers, currency, percentage,
10
+ # precision, positional notation, file size and pretty printing.
11
+ #
12
+ # ==== Options
13
+ #
14
+ # For details on which formats use which options, see ActiveSupport::NumberHelper
15
+ #
16
+ # ==== Examples
17
+ #
18
+ # Phone Numbers:
19
+ # 5551234.to_s(:phone) # => "555-1234"
20
+ # 1235551234.to_s(:phone) # => "123-555-1234"
21
+ # 1235551234.to_s(:phone, area_code: true) # => "(123) 555-1234"
22
+ # 1235551234.to_s(:phone, delimiter: ' ') # => "123 555 1234"
23
+ # 1235551234.to_s(:phone, area_code: true, extension: 555) # => "(123) 555-1234 x 555"
24
+ # 1235551234.to_s(:phone, country_code: 1) # => "+1-123-555-1234"
25
+ # 1235551234.to_s(:phone, country_code: 1, extension: 1343, delimiter: '.')
26
+ # # => "+1.123.555.1234 x 1343"
27
+ #
28
+ # Currency:
29
+ # 1234567890.50.to_s(:currency) # => "$1,234,567,890.50"
30
+ # 1234567890.506.to_s(:currency) # => "$1,234,567,890.51"
31
+ # 1234567890.506.to_s(:currency, precision: 3) # => "$1,234,567,890.506"
32
+ # 1234567890.506.to_s(:currency, round_mode: :down) # => "$1,234,567,890.50"
33
+ # 1234567890.506.to_s(:currency, locale: :fr) # => "1 234 567 890,51 €"
34
+ # -1234567890.50.to_s(:currency, negative_format: '(%u%n)')
35
+ # # => "($1,234,567,890.50)"
36
+ # 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '')
37
+ # # => "&pound;1234567890,50"
38
+ # 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
39
+ # # => "1234567890,50 &pound;"
40
+ #
41
+ # Percentage:
42
+ # 100.to_s(:percentage) # => "100.000%"
43
+ # 100.to_s(:percentage, precision: 0) # => "100%"
44
+ # 1000.to_s(:percentage, delimiter: '.', separator: ',') # => "1.000,000%"
45
+ # 302.24398923423.to_s(:percentage, precision: 5) # => "302.24399%"
46
+ # 302.24398923423.to_s(:percentage, round_mode: :down) # => "302.243%"
47
+ # 1000.to_s(:percentage, locale: :fr) # => "1 000,000%"
48
+ # 100.to_s(:percentage, format: '%n %') # => "100.000 %"
49
+ #
50
+ # Delimited:
51
+ # 12345678.to_s(:delimited) # => "12,345,678"
52
+ # 12345678.05.to_s(:delimited) # => "12,345,678.05"
53
+ # 12345678.to_s(:delimited, delimiter: '.') # => "12.345.678"
54
+ # 12345678.to_s(:delimited, delimiter: ',') # => "12,345,678"
55
+ # 12345678.05.to_s(:delimited, separator: ' ') # => "12,345,678 05"
56
+ # 12345678.05.to_s(:delimited, locale: :fr) # => "12 345 678,05"
57
+ # 98765432.98.to_s(:delimited, delimiter: ' ', separator: ',')
58
+ # # => "98 765 432,98"
59
+ #
60
+ # Rounded:
61
+ # 111.2345.to_s(:rounded) # => "111.235"
62
+ # 111.2345.to_s(:rounded, precision: 2) # => "111.23"
63
+ # 111.2345.to_s(:rounded, precision: 2, round_mode: :up) # => "111.24"
64
+ # 13.to_s(:rounded, precision: 5) # => "13.00000"
65
+ # 389.32314.to_s(:rounded, precision: 0) # => "389"
66
+ # 111.2345.to_s(:rounded, significant: true) # => "111"
67
+ # 111.2345.to_s(:rounded, precision: 1, significant: true) # => "100"
68
+ # 13.to_s(:rounded, precision: 5, significant: true) # => "13.000"
69
+ # 111.234.to_s(:rounded, locale: :fr) # => "111,234"
70
+ # 13.to_s(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true)
71
+ # # => "13"
72
+ # 389.32314.to_s(:rounded, precision: 4, significant: true) # => "389.3"
73
+ # 1111.2345.to_s(:rounded, precision: 2, separator: ',', delimiter: '.')
74
+ # # => "1.111,23"
75
+ #
76
+ # Human-friendly size in Bytes:
77
+ # 123.to_s(:human_size) # => "123 Bytes"
78
+ # 1234.to_s(:human_size) # => "1.21 KB"
79
+ # 12345.to_s(:human_size) # => "12.1 KB"
80
+ # 1234567.to_s(:human_size) # => "1.18 MB"
81
+ # 1234567890.to_s(:human_size) # => "1.15 GB"
82
+ # 1234567890123.to_s(:human_size) # => "1.12 TB"
83
+ # 1234567890123456.to_s(:human_size) # => "1.1 PB"
84
+ # 1234567890123456789.to_s(:human_size) # => "1.07 EB"
85
+ # 1234567.to_s(:human_size, precision: 2) # => "1.2 MB"
86
+ # 1234567.to_s(:human_size, precision: 2, round_mode: :up) # => "1.3 MB"
87
+ # 483989.to_s(:human_size, precision: 2) # => "470 KB"
88
+ # 1234567.to_s(:human_size, precision: 2, separator: ',') # => "1,2 MB"
89
+ # 1234567890123.to_s(:human_size, precision: 5) # => "1.1228 TB"
90
+ # 524288000.to_s(:human_size, precision: 5) # => "500 MB"
91
+ #
92
+ # Human-friendly format:
93
+ # 123.to_s(:human) # => "123"
94
+ # 1234.to_s(:human) # => "1.23 Thousand"
95
+ # 12345.to_s(:human) # => "12.3 Thousand"
96
+ # 1234567.to_s(:human) # => "1.23 Million"
97
+ # 1234567890.to_s(:human) # => "1.23 Billion"
98
+ # 1234567890123.to_s(:human) # => "1.23 Trillion"
99
+ # 1234567890123456.to_s(:human) # => "1.23 Quadrillion"
100
+ # 1234567890123456789.to_s(:human) # => "1230 Quadrillion"
101
+ # 489939.to_s(:human, precision: 2) # => "490 Thousand"
102
+ # 489939.to_s(:human, precision: 2, round_mode: :down) # => "480 Thousand"
103
+ # 489939.to_s(:human, precision: 4) # => "489.9 Thousand"
104
+ # 1234567.to_s(:human, precision: 4,
105
+ # significant: false) # => "1.2346 Million"
106
+ # 1234567.to_s(:human, precision: 1,
107
+ # separator: ',',
108
+ # significant: false) # => "1,2 Million"
109
+ def to_s(format = nil, options = nil)
110
+ case format
111
+ when nil
112
+ super()
113
+ when Integer, String
114
+ super(format)
115
+ when :phone
116
+ ActiveSupport::NumberHelper.number_to_phone(self, options || {})
117
+ when :currency
118
+ ActiveSupport::NumberHelper.number_to_currency(self, options || {})
119
+ when :percentage
120
+ ActiveSupport::NumberHelper.number_to_percentage(self, options || {})
121
+ when :delimited
122
+ ActiveSupport::NumberHelper.number_to_delimited(self, options || {})
123
+ when :rounded
124
+ ActiveSupport::NumberHelper.number_to_rounded(self, options || {})
125
+ when :human
126
+ ActiveSupport::NumberHelper.number_to_human(self, options || {})
127
+ when :human_size
128
+ ActiveSupport::NumberHelper.number_to_human_size(self, options || {})
129
+ when Symbol
130
+ super()
131
+ else
132
+ super(format)
133
+ end
128
134
  end
129
135
  end
130
136
  end
131
137
 
132
- # Ruby 2.4+ unifies Fixnum & Bignum into Integer.
133
- if 0.class == Integer
134
- Integer.prepend ActiveSupport::NumericWithFormat
135
- else
136
- Fixnum.prepend ActiveSupport::NumericWithFormat
137
- Bignum.prepend ActiveSupport::NumericWithFormat
138
- end
138
+ Integer.prepend ActiveSupport::NumericWithFormat
139
139
  Float.prepend ActiveSupport::NumericWithFormat
140
140
  BigDecimal.prepend ActiveSupport::NumericWithFormat