activesupport 6.0.4.4 → 7.0.4.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 (212) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +257 -532
  3. data/MIT-LICENSE +1 -1
  4. data/lib/active_support/actionable_error.rb +1 -1
  5. data/lib/active_support/array_inquirer.rb +2 -2
  6. data/lib/active_support/backtrace_cleaner.rb +5 -5
  7. data/lib/active_support/benchmarkable.rb +3 -3
  8. data/lib/active_support/cache/file_store.rb +16 -10
  9. data/lib/active_support/cache/mem_cache_store.rb +163 -42
  10. data/lib/active_support/cache/memory_store.rb +57 -29
  11. data/lib/active_support/cache/null_store.rb +10 -2
  12. data/lib/active_support/cache/redis_cache_store.rb +79 -98
  13. data/lib/active_support/cache/strategy/local_cache.rb +49 -57
  14. data/lib/active_support/cache.rb +378 -179
  15. data/lib/active_support/callbacks.rb +230 -122
  16. data/lib/active_support/code_generator.rb +65 -0
  17. data/lib/active_support/concern.rb +49 -5
  18. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +2 -4
  19. data/lib/active_support/concurrency/share_lock.rb +2 -2
  20. data/lib/active_support/configurable.rb +9 -6
  21. data/lib/active_support/configuration_file.rb +51 -0
  22. data/lib/active_support/core_ext/array/access.rb +1 -5
  23. data/lib/active_support/core_ext/array/conversions.rb +13 -12
  24. data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
  25. data/lib/active_support/core_ext/array/grouping.rb +6 -6
  26. data/lib/active_support/core_ext/array/inquiry.rb +2 -2
  27. data/lib/active_support/core_ext/array.rb +1 -0
  28. data/lib/active_support/core_ext/benchmark.rb +2 -2
  29. data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
  30. data/lib/active_support/core_ext/class/attribute.rb +34 -44
  31. data/lib/active_support/core_ext/class/subclasses.rb +9 -22
  32. data/lib/active_support/core_ext/date/blank.rb +1 -1
  33. data/lib/active_support/core_ext/date/calculations.rb +9 -9
  34. data/lib/active_support/core_ext/date/conversions.rb +16 -15
  35. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  36. data/lib/active_support/core_ext/date.rb +1 -0
  37. data/lib/active_support/core_ext/date_and_time/calculations.rb +17 -4
  38. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  39. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  40. data/lib/active_support/core_ext/date_time/conversions.rb +13 -13
  41. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  42. data/lib/active_support/core_ext/date_time.rb +1 -0
  43. data/lib/active_support/core_ext/digest/uuid.rb +39 -13
  44. data/lib/active_support/core_ext/enumerable.rb +164 -23
  45. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  46. data/lib/active_support/core_ext/hash/conversions.rb +2 -3
  47. data/lib/active_support/core_ext/hash/deep_transform_values.rb +1 -1
  48. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  49. data/lib/active_support/core_ext/hash/keys.rb +2 -2
  50. data/lib/active_support/core_ext/hash/slice.rb +3 -2
  51. data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
  52. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  53. data/lib/active_support/core_ext/load_error.rb +1 -1
  54. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  55. data/lib/active_support/core_ext/module/attribute_accessors.rb +25 -29
  56. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +26 -13
  57. data/lib/active_support/core_ext/module/concerning.rb +8 -2
  58. data/lib/active_support/core_ext/module/delegation.rb +40 -36
  59. data/lib/active_support/core_ext/module/introspection.rb +1 -25
  60. data/lib/active_support/core_ext/name_error.rb +23 -2
  61. data/lib/active_support/core_ext/numeric/conversions.rb +80 -73
  62. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  63. data/lib/active_support/core_ext/numeric.rb +1 -0
  64. data/lib/active_support/core_ext/object/acts_like.rb +29 -5
  65. data/lib/active_support/core_ext/object/blank.rb +2 -2
  66. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  67. data/lib/active_support/core_ext/object/duplicable.rb +11 -0
  68. data/lib/active_support/core_ext/object/json.rb +42 -26
  69. data/lib/active_support/core_ext/object/to_query.rb +2 -2
  70. data/lib/active_support/core_ext/object/try.rb +20 -20
  71. data/lib/active_support/core_ext/object/with_options.rb +20 -1
  72. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  73. data/lib/active_support/core_ext/pathname.rb +3 -0
  74. data/lib/active_support/core_ext/range/compare_range.rb +6 -25
  75. data/lib/active_support/core_ext/range/conversions.rb +8 -8
  76. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  77. data/lib/active_support/core_ext/range/each.rb +1 -1
  78. data/lib/active_support/core_ext/range/include_time_with_zone.rb +4 -20
  79. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  80. data/lib/active_support/core_ext/range.rb +1 -1
  81. data/lib/active_support/core_ext/regexp.rb +8 -1
  82. data/lib/active_support/core_ext/securerandom.rb +1 -1
  83. data/lib/active_support/core_ext/string/access.rb +5 -24
  84. data/lib/active_support/core_ext/string/conversions.rb +3 -2
  85. data/lib/active_support/core_ext/string/filters.rb +1 -1
  86. data/lib/active_support/core_ext/string/inflections.rb +39 -5
  87. data/lib/active_support/core_ext/string/inquiry.rb +2 -1
  88. data/lib/active_support/core_ext/string/multibyte.rb +2 -2
  89. data/lib/active_support/core_ext/string/output_safety.rb +92 -41
  90. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  91. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  92. data/lib/active_support/core_ext/symbol.rb +3 -0
  93. data/lib/active_support/core_ext/time/calculations.rb +25 -7
  94. data/lib/active_support/core_ext/time/conversions.rb +15 -12
  95. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  96. data/lib/active_support/core_ext/time/zones.rb +7 -22
  97. data/lib/active_support/core_ext/time.rb +1 -0
  98. data/lib/active_support/core_ext/uri.rb +3 -23
  99. data/lib/active_support/core_ext.rb +2 -1
  100. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  101. data/lib/active_support/current_attributes.rb +39 -16
  102. data/lib/active_support/dependencies/interlock.rb +10 -18
  103. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  104. data/lib/active_support/dependencies.rb +58 -769
  105. data/lib/active_support/deprecation/behaviors.rb +23 -7
  106. data/lib/active_support/deprecation/disallowed.rb +56 -0
  107. data/lib/active_support/deprecation/instance_delegator.rb +0 -1
  108. data/lib/active_support/deprecation/method_wrappers.rb +6 -5
  109. data/lib/active_support/deprecation/proxy_wrappers.rb +4 -4
  110. data/lib/active_support/deprecation/reporting.rb +50 -7
  111. data/lib/active_support/deprecation.rb +7 -2
  112. data/lib/active_support/descendants_tracker.rb +174 -64
  113. data/lib/active_support/digest.rb +5 -3
  114. data/lib/active_support/duration/iso8601_parser.rb +3 -3
  115. data/lib/active_support/duration/iso8601_serializer.rb +24 -10
  116. data/lib/active_support/duration.rb +134 -55
  117. data/lib/active_support/encrypted_configuration.rb +13 -2
  118. data/lib/active_support/encrypted_file.rb +32 -3
  119. data/lib/active_support/environment_inquirer.rb +20 -0
  120. data/lib/active_support/error_reporter.rb +117 -0
  121. data/lib/active_support/evented_file_update_checker.rb +72 -138
  122. data/lib/active_support/execution_context/test_helper.rb +13 -0
  123. data/lib/active_support/execution_context.rb +53 -0
  124. data/lib/active_support/execution_wrapper.rb +43 -21
  125. data/lib/active_support/executor/test_helper.rb +7 -0
  126. data/lib/active_support/fork_tracker.rb +71 -0
  127. data/lib/active_support/gem_version.rb +3 -3
  128. data/lib/active_support/hash_with_indifferent_access.rb +51 -25
  129. data/lib/active_support/html_safe_translation.rb +43 -0
  130. data/lib/active_support/i18n.rb +1 -0
  131. data/lib/active_support/i18n_railtie.rb +14 -19
  132. data/lib/active_support/inflector/inflections.rb +24 -9
  133. data/lib/active_support/inflector/methods.rb +29 -49
  134. data/lib/active_support/inflector/transliterate.rb +5 -5
  135. data/lib/active_support/isolated_execution_state.rb +72 -0
  136. data/lib/active_support/json/decoding.rb +4 -4
  137. data/lib/active_support/json/encoding.rb +8 -4
  138. data/lib/active_support/key_generator.rb +23 -6
  139. data/lib/active_support/lazy_load_hooks.rb +28 -4
  140. data/lib/active_support/locale/en.yml +8 -4
  141. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  142. data/lib/active_support/log_subscriber.rb +23 -5
  143. data/lib/active_support/logger.rb +1 -1
  144. data/lib/active_support/logger_silence.rb +2 -26
  145. data/lib/active_support/logger_thread_safe_level.rb +34 -21
  146. data/lib/active_support/message_encryptor.rb +16 -13
  147. data/lib/active_support/message_verifier.rb +50 -18
  148. data/lib/active_support/messages/metadata.rb +2 -2
  149. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  150. data/lib/active_support/messages/rotator.rb +6 -5
  151. data/lib/active_support/multibyte/chars.rb +13 -52
  152. data/lib/active_support/multibyte/unicode.rb +1 -87
  153. data/lib/active_support/multibyte.rb +1 -1
  154. data/lib/active_support/notifications/fanout.rb +110 -69
  155. data/lib/active_support/notifications/instrumenter.rb +37 -29
  156. data/lib/active_support/notifications.rb +55 -28
  157. data/lib/active_support/number_helper/number_converter.rb +2 -4
  158. data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
  159. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
  160. data/lib/active_support/number_helper/number_to_human_converter.rb +1 -1
  161. data/lib/active_support/number_helper/number_to_human_size_converter.rb +2 -2
  162. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -1
  163. data/lib/active_support/number_helper/number_to_rounded_converter.rb +9 -5
  164. data/lib/active_support/number_helper/rounding_helper.rb +12 -32
  165. data/lib/active_support/number_helper.rb +29 -16
  166. data/lib/active_support/option_merger.rb +11 -18
  167. data/lib/active_support/ordered_hash.rb +1 -1
  168. data/lib/active_support/ordered_options.rb +9 -3
  169. data/lib/active_support/parameter_filter.rb +21 -11
  170. data/lib/active_support/per_thread_registry.rb +6 -1
  171. data/lib/active_support/rails.rb +1 -4
  172. data/lib/active_support/railtie.rb +77 -5
  173. data/lib/active_support/reloader.rb +1 -1
  174. data/lib/active_support/rescuable.rb +16 -16
  175. data/lib/active_support/ruby_features.rb +7 -0
  176. data/lib/active_support/secure_compare_rotator.rb +51 -0
  177. data/lib/active_support/security_utils.rb +19 -12
  178. data/lib/active_support/string_inquirer.rb +2 -2
  179. data/lib/active_support/subscriber.rb +19 -25
  180. data/lib/active_support/tagged_logging.rb +31 -6
  181. data/lib/active_support/test_case.rb +13 -21
  182. data/lib/active_support/testing/assertions.rb +50 -13
  183. data/lib/active_support/testing/deprecation.rb +52 -1
  184. data/lib/active_support/testing/isolation.rb +2 -2
  185. data/lib/active_support/testing/method_call_assertions.rb +5 -5
  186. data/lib/active_support/testing/parallelization/server.rb +82 -0
  187. data/lib/active_support/testing/parallelization/worker.rb +103 -0
  188. data/lib/active_support/testing/parallelization.rb +16 -95
  189. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  190. data/lib/active_support/testing/stream.rb +3 -5
  191. data/lib/active_support/testing/tagged_logging.rb +1 -1
  192. data/lib/active_support/testing/time_helpers.rb +53 -5
  193. data/lib/active_support/time_with_zone.rb +126 -62
  194. data/lib/active_support/values/time_zone.rb +54 -23
  195. data/lib/active_support/version.rb +1 -1
  196. data/lib/active_support/xml_mini/jdom.rb +1 -1
  197. data/lib/active_support/xml_mini/libxml.rb +5 -5
  198. data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
  199. data/lib/active_support/xml_mini/nokogiri.rb +4 -4
  200. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  201. data/lib/active_support/xml_mini/rexml.rb +9 -2
  202. data/lib/active_support/xml_mini.rb +5 -4
  203. data/lib/active_support.rb +29 -1
  204. metadata +46 -45
  205. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
  206. data/lib/active_support/core_ext/hash/compact.rb +0 -5
  207. data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
  208. data/lib/active_support/core_ext/marshal.rb +0 -24
  209. data/lib/active_support/core_ext/module/reachable.rb +0 -6
  210. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
  211. data/lib/active_support/core_ext/range/include_range.rb +0 -9
  212. data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
@@ -19,7 +19,7 @@ module ActiveSupport
19
19
  # By using <tt>ActiveSupport::Concern</tt> the above module could instead be
20
20
  # written as:
21
21
  #
22
- # require 'active_support/concern'
22
+ # require "active_support/concern"
23
23
  #
24
24
  # module M
25
25
  # extend ActiveSupport::Concern
@@ -76,7 +76,7 @@ module ActiveSupport
76
76
  # is the +Bar+ module, not the +Host+ class. With <tt>ActiveSupport::Concern</tt>,
77
77
  # module dependencies are properly resolved:
78
78
  #
79
- # require 'active_support/concern'
79
+ # require "active_support/concern"
80
80
  #
81
81
  # module Foo
82
82
  # extend ActiveSupport::Concern
@@ -99,18 +99,32 @@ module ActiveSupport
99
99
  # class Host
100
100
  # include Bar # It works, now Bar takes care of its dependencies
101
101
  # end
102
+ #
103
+ # === Prepending concerns
104
+ #
105
+ # Just like <tt>include</tt>, concerns also support <tt>prepend</tt> with a corresponding
106
+ # <tt>prepended do</tt> callback. <tt>module ClassMethods</tt> or <tt>class_methods do</tt> are
107
+ # prepended as well.
108
+ #
109
+ # <tt>prepend</tt> is also used for any dependencies.
102
110
  module Concern
103
- class MultipleIncludedBlocks < StandardError #:nodoc:
111
+ class MultipleIncludedBlocks < StandardError # :nodoc:
104
112
  def initialize
105
113
  super "Cannot define multiple 'included' blocks for a Concern"
106
114
  end
107
115
  end
108
116
 
109
- def self.extended(base) #:nodoc:
117
+ class MultiplePrependBlocks < StandardError # :nodoc:
118
+ def initialize
119
+ super "Cannot define multiple 'prepended' blocks for a Concern"
120
+ end
121
+ end
122
+
123
+ def self.extended(base) # :nodoc:
110
124
  base.instance_variable_set(:@_dependencies, [])
111
125
  end
112
126
 
113
- def append_features(base) #:nodoc:
127
+ def append_features(base) # :nodoc:
114
128
  if base.instance_variable_defined?(:@_dependencies)
115
129
  base.instance_variable_get(:@_dependencies) << self
116
130
  false
@@ -123,6 +137,19 @@ module ActiveSupport
123
137
  end
124
138
  end
125
139
 
140
+ def prepend_features(base) # :nodoc:
141
+ if base.instance_variable_defined?(:@_dependencies)
142
+ base.instance_variable_get(:@_dependencies).unshift self
143
+ false
144
+ else
145
+ return false if base < self
146
+ @_dependencies.each { |dep| base.prepend(dep) }
147
+ super
148
+ base.singleton_class.prepend const_get(:ClassMethods) if const_defined?(:ClassMethods)
149
+ base.class_eval(&@_prepended_block) if instance_variable_defined?(:@_prepended_block)
150
+ end
151
+ end
152
+
126
153
  # Evaluate given block in context of base class,
127
154
  # so that you can write class macros here.
128
155
  # When you define more than one +included+ block, it raises an exception.
@@ -140,6 +167,23 @@ module ActiveSupport
140
167
  end
141
168
  end
142
169
 
170
+ # Evaluate given block in context of base class,
171
+ # so that you can write class macros here.
172
+ # When you define more than one +prepended+ block, it raises an exception.
173
+ def prepended(base = nil, &block)
174
+ if base.nil?
175
+ if instance_variable_defined?(:@_prepended_block)
176
+ if @_prepended_block.source_location != block.source_location
177
+ raise MultiplePrependBlocks
178
+ end
179
+ else
180
+ @_prepended_block = block
181
+ end
182
+ else
183
+ super
184
+ end
185
+ end
186
+
143
187
  # Define class methods from given block.
144
188
  # You can define private class methods as well.
145
189
  #
@@ -17,14 +17,12 @@ module ActiveSupport
17
17
  ActiveSupport::Dependencies.interlock.permit_concurrent_loads { super }
18
18
  end
19
19
 
20
- def synchronize
20
+ def synchronize(&block)
21
21
  Thread.handle_interrupt(EXCEPTION_NEVER) do
22
22
  mon_enter
23
23
 
24
24
  begin
25
- Thread.handle_interrupt(EXCEPTION_IMMEDIATE) do
26
- yield
27
- end
25
+ Thread.handle_interrupt(EXCEPTION_IMMEDIATE, &block)
28
26
  ensure
29
27
  mon_exit
30
28
  end
@@ -215,9 +215,9 @@ module ActiveSupport
215
215
  @waiting.any? { |t, (p, _)| compatible.include?(p) && @waiting.all? { |t2, (_, c2)| t == t2 || c2.include?(p) } }
216
216
  end
217
217
 
218
- def wait_for(method)
218
+ def wait_for(method, &block)
219
219
  @sleeping[Thread.current] = method
220
- @cv.wait_while { yield }
220
+ @cv.wait_while(&block)
221
221
  ensure
222
222
  @sleeping.delete Thread.current
223
223
  end
@@ -5,7 +5,7 @@ require "active_support/ordered_options"
5
5
 
6
6
  module ActiveSupport
7
7
  # Configurable provides a <tt>config</tt> method to store and retrieve
8
- # configuration options as an <tt>OrderedHash</tt>.
8
+ # configuration options as an OrderedOptions.
9
9
  module Configurable
10
10
  extend ActiveSupport::Concern
11
11
 
@@ -94,17 +94,19 @@ module ActiveSupport
94
94
  # User.new.allowed_access = true # => NoMethodError
95
95
  # User.new.allowed_access # => NoMethodError
96
96
  #
97
- # Also you can pass a block to set up the attribute with a default value.
97
+ # Also you can pass <tt>default</tt> or a block to set up the attribute with a default value.
98
98
  #
99
99
  # class User
100
100
  # include ActiveSupport::Configurable
101
+ # config_accessor :allowed_access, default: false
101
102
  # config_accessor :hair_colors do
102
103
  # [:brown, :black, :blonde, :red]
103
104
  # end
104
105
  # end
105
106
  #
107
+ # User.allowed_access # => false
106
108
  # User.hair_colors # => [:brown, :black, :blonde, :red]
107
- def config_accessor(*names, instance_reader: true, instance_writer: true, instance_accessor: true) # :doc:
109
+ def config_accessor(*names, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil) # :doc:
108
110
  names.each do |name|
109
111
  raise NameError.new("invalid config attribute name") unless /\A[_A-Za-z]\w*\z/.match?(name)
110
112
 
@@ -118,15 +120,16 @@ module ActiveSupport
118
120
  class_eval reader, __FILE__, reader_line if instance_reader
119
121
  class_eval writer, __FILE__, writer_line if instance_writer
120
122
  end
121
- send("#{name}=", yield) if block_given?
123
+
124
+ send("#{name}=", block_given? ? yield : default)
122
125
  end
123
126
  end
124
127
  private :config_accessor
125
128
  end
126
129
 
127
- # Reads and writes attributes from a configuration <tt>OrderedHash</tt>.
130
+ # Reads and writes attributes from a configuration OrderedOptions.
128
131
  #
129
- # require 'active_support/configurable'
132
+ # require "active_support/configurable"
130
133
  #
131
134
  # class User
132
135
  # include ActiveSupport::Configurable
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ # Reads a YAML configuration file, evaluating any ERB, then
5
+ # parsing the resulting YAML.
6
+ #
7
+ # Warns in case of YAML confusing characters, like invisible
8
+ # non-breaking spaces.
9
+ class ConfigurationFile # :nodoc:
10
+ class FormatError < StandardError; end
11
+
12
+ def initialize(content_path)
13
+ @content_path = content_path.to_s
14
+ @content = read content_path
15
+ end
16
+
17
+ def self.parse(content_path, **options)
18
+ new(content_path).parse(**options)
19
+ end
20
+
21
+ def parse(context: nil, **options)
22
+ source = render(context)
23
+ if YAML.respond_to?(:unsafe_load)
24
+ YAML.unsafe_load(source, **options) || {}
25
+ else
26
+ YAML.load(source, **options) || {}
27
+ end
28
+ rescue Psych::SyntaxError => error
29
+ raise "YAML syntax error occurred while parsing #{@content_path}. " \
30
+ "Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
31
+ "Error: #{error.message}"
32
+ end
33
+
34
+ private
35
+ def read(content_path)
36
+ require "yaml"
37
+ require "erb"
38
+
39
+ File.read(content_path).tap do |content|
40
+ if content.include?("\u00A0")
41
+ warn "#{content_path} contains invisible non-breaking spaces, you may want to remove those"
42
+ end
43
+ end
44
+ end
45
+
46
+ def render(context)
47
+ erb = ERB.new(@content).tap { |e| e.filename = @content_path }
48
+ context ? erb.result(context) : erb.result
49
+ end
50
+ end
51
+ end
@@ -47,11 +47,7 @@ class Array
47
47
  def excluding(*elements)
48
48
  self - elements.flatten(1)
49
49
  end
50
-
51
- # Alias for #excluding.
52
- def without(*elements)
53
- excluding(*elements)
54
- end
50
+ alias :without :excluding
55
51
 
56
52
  # Equal to <tt>self[1]</tt>.
57
53
  #
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/xml_mini"
4
3
  require "active_support/core_ext/hash/keys"
5
4
  require "active_support/core_ext/string/inflections"
6
5
  require "active_support/core_ext/object/to_param"
@@ -16,12 +15,12 @@ class Array
16
15
  #
17
16
  # ==== Options
18
17
  #
19
- # * <tt>:words_connector</tt> - The sign or word used to join the elements
20
- # in arrays with two or more elements (default: ", ").
21
- # * <tt>:two_words_connector</tt> - The sign or word used to join the elements
22
- # in arrays with two elements (default: " and ").
18
+ # * <tt>:words_connector</tt> - The sign or word used to join all but the last
19
+ # element in arrays with three or more elements (default: ", ").
23
20
  # * <tt>:last_word_connector</tt> - The sign or word used to join the last element
24
21
  # in arrays with three or more elements (default: ", and ").
22
+ # * <tt>:two_words_connector</tt> - The sign or word used to join the elements
23
+ # in arrays with two elements (default: " and ").
25
24
  # * <tt>:locale</tt> - If +i18n+ is available, you can set a locale and use
26
25
  # the connector options defined on the 'support.array' namespace in the
27
26
  # corresponding dictionary file.
@@ -66,7 +65,7 @@ class Array
66
65
  two_words_connector: " and ",
67
66
  last_word_connector: ", and "
68
67
  }
69
- if defined?(I18n)
68
+ if options[:locale] != false && defined?(I18n)
70
69
  i18n_connectors = I18n.translate(:'support.array', locale: options[:locale], default: {})
71
70
  default_connectors.merge!(i18n_connectors)
72
71
  end
@@ -87,10 +86,12 @@ class Array
87
86
  # Extends <tt>Array#to_s</tt> to convert a collection of elements into a
88
87
  # comma separated id list if <tt>:db</tt> argument is given as the format.
89
88
  #
90
- # Blog.all.to_formatted_s(:db) # => "1,2,3"
91
- # Blog.none.to_formatted_s(:db) # => "null"
92
- # [1,2].to_formatted_s # => "[1, 2]"
93
- def to_formatted_s(format = :default)
89
+ # This method is aliased to <tt>to_formatted_s</tt>.
90
+ #
91
+ # Blog.all.to_fs(:db) # => "1,2,3"
92
+ # Blog.none.to_fs(:db) # => "null"
93
+ # [1,2].to_fs # => "[1, 2]"
94
+ def to_fs(format = :default)
94
95
  case format
95
96
  when :db
96
97
  if empty?
@@ -102,8 +103,8 @@ class Array
102
103
  to_default_s
103
104
  end
104
105
  end
106
+ alias_method :to_formatted_s, :to_fs
105
107
  alias_method :to_default_s, :to_s
106
- alias_method :to_s, :to_formatted_s
107
108
 
108
109
  # Returns a string that represents the array in XML by invoking +to_xml+
109
110
  # on each element. Active Record collections delegate their representation
@@ -187,7 +188,7 @@ class Array
187
188
  options[:indent] ||= 2
188
189
  options[:builder] ||= Builder::XmlMarkup.new(indent: options[:indent])
189
190
  options[:root] ||= \
190
- if first.class != Hash && all? { |e| e.is_a?(first.class) }
191
+ if first.class != Hash && all?(first.class)
191
192
  underscored = ActiveSupport::Inflector.underscore(first.class.name)
192
193
  ActiveSupport::Inflector.pluralize(underscored).tr("/", "_")
193
194
  else
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Array
4
+ NOT_SET = Object.new # :nodoc:
5
+ def to_s(format = NOT_SET) # :nodoc:
6
+ case format
7
+ when :db
8
+ ActiveSupport::Deprecation.warn(
9
+ "Array#to_s(#{format.inspect}) is deprecated. Please use Array#to_fs(#{format.inspect}) instead."
10
+ )
11
+ if empty?
12
+ "null"
13
+ else
14
+ collect(&:id).join(",")
15
+ end
16
+ when NOT_SET
17
+ to_default_s
18
+ else
19
+ ActiveSupport::Deprecation.warn(
20
+ "Array#to_s(#{format.inspect}) is deprecated. Please use Array#to_fs(#{format.inspect}) instead."
21
+ )
22
+ to_default_s
23
+ end
24
+ end
25
+ end
@@ -19,7 +19,7 @@ class Array
19
19
  # ["1", "2"]
20
20
  # ["3", "4"]
21
21
  # ["5"]
22
- def in_groups_of(number, fill_with = nil)
22
+ def in_groups_of(number, fill_with = nil, &block)
23
23
  if number.to_i <= 0
24
24
  raise ArgumentError,
25
25
  "Group size must be a positive integer, was #{number.inspect}"
@@ -36,7 +36,7 @@ class Array
36
36
  end
37
37
 
38
38
  if block_given?
39
- collection.each_slice(number) { |slice| yield(slice) }
39
+ collection.each_slice(number, &block)
40
40
  else
41
41
  collection.each_slice(number).to_a
42
42
  end
@@ -59,7 +59,7 @@ class Array
59
59
  # ["1", "2", "3"]
60
60
  # ["4", "5"]
61
61
  # ["6", "7"]
62
- def in_groups(number, fill_with = nil)
62
+ def in_groups(number, fill_with = nil, &block)
63
63
  # size.div number gives minor group size;
64
64
  # size % number gives how many objects need extra accommodation;
65
65
  # each group hold either division or division + 1 items.
@@ -79,7 +79,7 @@ class Array
79
79
  end
80
80
 
81
81
  if block_given?
82
- groups.each { |g| yield(g) }
82
+ groups.each(&block)
83
83
  else
84
84
  groups
85
85
  end
@@ -90,11 +90,11 @@ class Array
90
90
  #
91
91
  # [1, 2, 3, 4, 5].split(3) # => [[1, 2], [4, 5]]
92
92
  # (1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]
93
- def split(value = nil)
93
+ def split(value = nil, &block)
94
94
  arr = dup
95
95
  result = []
96
96
  if block_given?
97
- while (idx = arr.index { |i| yield i })
97
+ while (idx = arr.index(&block))
98
98
  result << arr.shift(idx)
99
99
  arr.shift
100
100
  end
@@ -3,8 +3,8 @@
3
3
  require "active_support/array_inquirer"
4
4
 
5
5
  class Array
6
- # Wraps the array in an +ArrayInquirer+ object, which gives a friendlier way
7
- # to check its string-like contents.
6
+ # Wraps the array in an ActiveSupport::ArrayInquirer object, which gives a
7
+ # friendlier way to check its string-like contents.
8
8
  #
9
9
  # pets = [:cat, :dog].inquiry
10
10
  #
@@ -3,6 +3,7 @@
3
3
  require "active_support/core_ext/array/wrap"
4
4
  require "active_support/core_ext/array/access"
5
5
  require "active_support/core_ext/array/conversions"
6
+ require "active_support/core_ext/array/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"]
6
7
  require "active_support/core_ext/array/extract"
7
8
  require "active_support/core_ext/array/extract_options"
8
9
  require "active_support/core_ext/array/grouping"
@@ -10,7 +10,7 @@ class << Benchmark
10
10
  #
11
11
  # Benchmark.ms { User.all }
12
12
  # # => 0.074
13
- def ms
14
- 1000 * realtime { yield }
13
+ def ms(&block)
14
+ 1000 * realtime(&block)
15
15
  end
16
16
  end
@@ -4,7 +4,7 @@ require "bigdecimal"
4
4
  require "bigdecimal/util"
5
5
 
6
6
  module ActiveSupport
7
- module BigDecimalWithDefaultFormat #:nodoc:
7
+ module BigDecimalWithDefaultFormat # :nodoc:
8
8
  def to_s(format = "F")
9
9
  super(format)
10
10
  end
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/kernel/singleton_class"
4
3
  require "active_support/core_ext/module/redefine_method"
5
- require "active_support/core_ext/array/extract_options"
6
4
 
7
5
  class Class
8
6
  # Declare a class-level attribute whose value is inheritable by subclasses.
@@ -84,58 +82,50 @@ class Class
84
82
  # To set a default value for the attribute, pass <tt>default:</tt>, like so:
85
83
  #
86
84
  # class_attribute :settings, default: {}
87
- def class_attribute(
88
- *attrs,
89
- instance_accessor: true,
90
- instance_reader: instance_accessor,
91
- instance_writer: instance_accessor,
92
- instance_predicate: true,
93
- default: nil
94
- )
95
- attrs.each do |name|
96
- singleton_class.silence_redefinition_of_method(name)
97
- define_singleton_method(name) { default }
98
-
99
- singleton_class.silence_redefinition_of_method("#{name}?")
100
- define_singleton_method("#{name}?") { !!public_send(name) } if instance_predicate
85
+ def class_attribute(*attrs, instance_accessor: true,
86
+ instance_reader: instance_accessor, instance_writer: instance_accessor, instance_predicate: true, default: nil)
101
87
 
102
- ivar = "@#{name}".to_sym
88
+ class_methods, methods = [], []
89
+ attrs.each do |name|
90
+ unless name.is_a?(Symbol) || name.is_a?(String)
91
+ raise TypeError, "#{name.inspect} is not a symbol nor a string"
92
+ end
103
93
 
104
- singleton_class.silence_redefinition_of_method("#{name}=")
105
- define_singleton_method("#{name}=") do |val|
106
- redefine_singleton_method(name) { val }
94
+ class_methods << <<~RUBY # In case the method exists and is not public
95
+ silence_redefinition_of_method def #{name}
96
+ end
97
+ RUBY
107
98
 
108
- if singleton_class?
109
- class_eval do
110
- redefine_method(name) do
111
- if instance_variable_defined? ivar
112
- instance_variable_get ivar
113
- else
114
- singleton_class.send name
115
- end
116
- end
117
- end
99
+ methods << <<~RUBY if instance_reader
100
+ silence_redefinition_of_method def #{name}
101
+ defined?(@#{name}) ? @#{name} : self.class.#{name}
118
102
  end
119
- val
120
- end
103
+ RUBY
121
104
 
122
- if instance_reader
123
- redefine_method(name) do
124
- if instance_variable_defined?(ivar)
125
- instance_variable_get ivar
126
- else
127
- self.class.public_send name
128
- end
105
+ class_methods << <<~RUBY
106
+ silence_redefinition_of_method def #{name}=(value)
107
+ redefine_method(:#{name}) { value } if singleton_class?
108
+ redefine_singleton_method(:#{name}) { value }
109
+ value
129
110
  end
111
+ RUBY
130
112
 
131
- redefine_method("#{name}?") { !!public_send(name) } if instance_predicate
132
- end
113
+ methods << <<~RUBY if instance_writer
114
+ silence_redefinition_of_method(:#{name}=)
115
+ attr_writer :#{name}
116
+ RUBY
133
117
 
134
- if instance_writer
135
- redefine_method("#{name}=") do |val|
136
- instance_variable_set ivar, val
118
+ if instance_predicate
119
+ class_methods << "silence_redefinition_of_method def #{name}?; !!self.#{name}; end"
120
+ if instance_reader
121
+ methods << "silence_redefinition_of_method def #{name}?; !!self.#{name}; end"
137
122
  end
138
123
  end
139
124
  end
125
+
126
+ location = caller_locations(1, 1).first
127
+ class_eval(["class << self", *class_methods, "end", *methods].join(";").tr("\n", ";"), location.path, location.lineno)
128
+
129
+ attrs.each { |name| public_send("#{name}=", default) }
140
130
  end
141
131
  end
@@ -1,10 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Class
4
- begin
5
- # Test if this Ruby supports each_object against singleton_class
6
- ObjectSpace.each_object(Numeric.singleton_class) { }
3
+ require "active_support/ruby_features"
7
4
 
5
+ class Class
6
+ if ActiveSupport::RubyFeatures::CLASS_SUBCLASSES
8
7
  # Returns an array with all classes that are < than its receiver.
9
8
  #
10
9
  # class C; end
@@ -19,21 +18,13 @@ class Class
19
18
  # class D < C; end
20
19
  # C.descendants # => [B, A, D]
21
20
  def descendants
22
- descendants = []
23
- ObjectSpace.each_object(singleton_class) do |k|
24
- next if k.singleton_class?
25
- descendants.unshift k unless k == self
26
- end
27
- descendants
21
+ subclasses.concat(subclasses.flat_map(&:descendants))
28
22
  end
29
- rescue StandardError # JRuby 9.0.4.0 and earlier
23
+ else
30
24
  def descendants
31
- descendants = []
32
- ObjectSpace.each_object(Class) do |k|
33
- descendants.unshift k if k < self
25
+ ObjectSpace.each_object(singleton_class).reject do |k|
26
+ k.singleton_class? || k == self
34
27
  end
35
- descendants.uniq!
36
- descendants
37
28
  end
38
29
  end
39
30
 
@@ -45,10 +36,6 @@ class Class
45
36
  #
46
37
  # Foo.subclasses # => [Bar]
47
38
  def subclasses
48
- subclasses, chain = [], descendants
49
- chain.each do |k|
50
- subclasses << k unless chain.any? { |c| c > k }
51
- end
52
- subclasses
53
- end
39
+ descendants.select { |descendant| descendant.superclass == self }
40
+ end unless ActiveSupport::RubyFeatures::CLASS_SUBCLASSES
54
41
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "date"
4
4
 
5
- class Date #:nodoc:
5
+ class Date # :nodoc:
6
6
  # No Date is blank:
7
7
  #
8
8
  # Date.today.blank? # => false
@@ -13,22 +13,22 @@ class Date
13
13
  class << self
14
14
  attr_accessor :beginning_of_week_default
15
15
 
16
- # Returns the week start (e.g. :monday) for the current request, if this has been set (via Date.beginning_of_week=).
16
+ # Returns the week start (e.g. +:monday+) for the current request, if this has been set (via Date.beginning_of_week=).
17
17
  # If <tt>Date.beginning_of_week</tt> has not been set for the current request, returns the week start specified in <tt>config.beginning_of_week</tt>.
18
- # If no config.beginning_of_week was specified, returns :monday.
18
+ # If no +config.beginning_of_week+ was specified, returns +:monday+.
19
19
  def beginning_of_week
20
- Thread.current[:beginning_of_week] || beginning_of_week_default || :monday
20
+ ::ActiveSupport::IsolatedExecutionState[:beginning_of_week] || beginning_of_week_default || :monday
21
21
  end
22
22
 
23
- # Sets <tt>Date.beginning_of_week</tt> to a week start (e.g. :monday) for current request/thread.
23
+ # Sets <tt>Date.beginning_of_week</tt> to a week start (e.g. +:monday+) for current request/thread.
24
24
  #
25
25
  # This method accepts any of the following day symbols:
26
- # :monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday
26
+ # +:monday+, +:tuesday+, +:wednesday+, +:thursday+, +:friday+, +:saturday+, +:sunday+
27
27
  def beginning_of_week=(week_start)
28
- Thread.current[:beginning_of_week] = find_beginning_of_week!(week_start)
28
+ ::ActiveSupport::IsolatedExecutionState[:beginning_of_week] = find_beginning_of_week!(week_start)
29
29
  end
30
30
 
31
- # Returns week start day symbol (e.g. :monday), or raises an +ArgumentError+ for invalid day symbol.
31
+ # Returns week start day symbol (e.g. +:monday+), or raises an +ArgumentError+ for invalid day symbol.
32
32
  def find_beginning_of_week!(week_start)
33
33
  raise ArgumentError, "Invalid beginning of week: #{week_start}" unless ::Date::DAYS_INTO_WEEK.key?(week_start)
34
34
  week_start
@@ -87,7 +87,7 @@ class Date
87
87
  end
88
88
  alias :at_end_of_day :end_of_day
89
89
 
90
- def plus_with_duration(other) #:nodoc:
90
+ def plus_with_duration(other) # :nodoc:
91
91
  if ActiveSupport::Duration === other
92
92
  other.since(self)
93
93
  else
@@ -97,7 +97,7 @@ class Date
97
97
  alias_method :plus_without_duration, :+
98
98
  alias_method :+, :plus_with_duration
99
99
 
100
- def minus_with_duration(other) #:nodoc:
100
+ def minus_with_duration(other) # :nodoc:
101
101
  if ActiveSupport::Duration === other
102
102
  plus_with_duration(-other)
103
103
  else