activesupport 4.2.11.1 → 5.2.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

Files changed (256) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +399 -440
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +4 -5
  5. data/lib/active_support/all.rb +5 -3
  6. data/lib/active_support/array_inquirer.rb +48 -0
  7. data/lib/active_support/backtrace_cleaner.rb +7 -5
  8. data/lib/active_support/benchmarkable.rb +6 -4
  9. data/lib/active_support/builder.rb +3 -1
  10. data/lib/active_support/cache/file_store.rb +41 -35
  11. data/lib/active_support/cache/mem_cache_store.rb +97 -88
  12. data/lib/active_support/cache/memory_store.rb +27 -30
  13. data/lib/active_support/cache/null_store.rb +7 -8
  14. data/lib/active_support/cache/redis_cache_store.rb +461 -0
  15. data/lib/active_support/cache/strategy/local_cache.rb +67 -34
  16. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  17. data/lib/active_support/cache.rb +287 -196
  18. data/lib/active_support/callbacks.rb +640 -590
  19. data/lib/active_support/concern.rb +11 -5
  20. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
  21. data/lib/active_support/concurrency/share_lock.rb +227 -0
  22. data/lib/active_support/configurable.rb +8 -5
  23. data/lib/active_support/core_ext/array/access.rb +29 -1
  24. data/lib/active_support/core_ext/array/conversions.rb +22 -18
  25. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  26. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  27. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  28. data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
  29. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  30. data/lib/active_support/core_ext/array.rb +9 -6
  31. data/lib/active_support/core_ext/benchmark.rb +3 -1
  32. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  33. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  34. data/lib/active_support/core_ext/class/attribute.rb +41 -22
  35. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  36. data/lib/active_support/core_ext/class/subclasses.rb +20 -6
  37. data/lib/active_support/core_ext/class.rb +4 -3
  38. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  39. data/lib/active_support/core_ext/date/blank.rb +14 -0
  40. data/lib/active_support/core_ext/date/calculations.rb +11 -9
  41. data/lib/active_support/core_ext/date/conversions.rb +25 -23
  42. data/lib/active_support/core_ext/date/zones.rb +4 -2
  43. data/lib/active_support/core_ext/date.rb +6 -4
  44. data/lib/active_support/core_ext/date_and_time/calculations.rb +170 -58
  45. data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -3
  46. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
  47. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  48. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  49. data/lib/active_support/core_ext/date_time/calculations.rb +36 -18
  50. data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
  51. data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
  52. data/lib/active_support/core_ext/date_time.rb +7 -5
  53. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  54. data/lib/active_support/core_ext/digest.rb +3 -0
  55. data/lib/active_support/core_ext/enumerable.rb +101 -33
  56. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  57. data/lib/active_support/core_ext/file.rb +3 -1
  58. data/lib/active_support/core_ext/hash/compact.rb +14 -9
  59. data/lib/active_support/core_ext/hash/conversions.rb +62 -41
  60. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  61. data/lib/active_support/core_ext/hash/except.rb +11 -8
  62. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  63. data/lib/active_support/core_ext/hash/keys.rb +33 -27
  64. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  65. data/lib/active_support/core_ext/hash/slice.rb +8 -8
  66. data/lib/active_support/core_ext/hash/transform_values.rb +14 -5
  67. data/lib/active_support/core_ext/hash.rb +11 -9
  68. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  69. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  70. data/lib/active_support/core_ext/integer/time.rb +11 -18
  71. data/lib/active_support/core_ext/integer.rb +5 -3
  72. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  73. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  74. data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
  75. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  76. data/lib/active_support/core_ext/kernel.rb +6 -5
  77. data/lib/active_support/core_ext/load_error.rb +3 -22
  78. data/lib/active_support/core_ext/marshal.rb +8 -8
  79. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  80. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  81. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  82. data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
  83. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
  84. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  85. data/lib/active_support/core_ext/module/delegation.rb +99 -29
  86. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  87. data/lib/active_support/core_ext/module/introspection.rb +9 -9
  88. data/lib/active_support/core_ext/module/reachable.rb +5 -2
  89. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  90. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  91. data/lib/active_support/core_ext/module.rb +14 -11
  92. data/lib/active_support/core_ext/name_error.rb +22 -2
  93. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  94. data/lib/active_support/core_ext/numeric/conversions.rb +78 -81
  95. data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
  96. data/lib/active_support/core_ext/numeric/time.rb +35 -23
  97. data/lib/active_support/core_ext/numeric.rb +6 -3
  98. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  99. data/lib/active_support/core_ext/object/blank.rb +27 -2
  100. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  101. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  102. data/lib/active_support/core_ext/object/duplicable.rb +41 -14
  103. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  104. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  105. data/lib/active_support/core_ext/object/json.rb +49 -19
  106. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  107. data/lib/active_support/core_ext/object/to_query.rb +10 -5
  108. data/lib/active_support/core_ext/object/try.rb +69 -21
  109. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  110. data/lib/active_support/core_ext/object.rb +14 -13
  111. data/lib/active_support/core_ext/range/compare_range.rb +61 -0
  112. data/lib/active_support/core_ext/range/conversions.rb +27 -7
  113. data/lib/active_support/core_ext/range/each.rb +19 -17
  114. data/lib/active_support/core_ext/range/include_range.rb +2 -22
  115. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  116. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  117. data/lib/active_support/core_ext/range.rb +7 -4
  118. data/lib/active_support/core_ext/regexp.rb +6 -0
  119. data/lib/active_support/core_ext/securerandom.rb +25 -0
  120. data/lib/active_support/core_ext/string/access.rb +8 -6
  121. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  122. data/lib/active_support/core_ext/string/conversions.rb +7 -4
  123. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  124. data/lib/active_support/core_ext/string/filters.rb +6 -5
  125. data/lib/active_support/core_ext/string/indent.rb +6 -4
  126. data/lib/active_support/core_ext/string/inflections.rb +61 -24
  127. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  128. data/lib/active_support/core_ext/string/multibyte.rb +15 -7
  129. data/lib/active_support/core_ext/string/output_safety.rb +34 -38
  130. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  131. data/lib/active_support/core_ext/string/strip.rb +4 -5
  132. data/lib/active_support/core_ext/string/zones.rb +4 -2
  133. data/lib/active_support/core_ext/string.rb +15 -13
  134. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  135. data/lib/active_support/core_ext/time/calculations.rb +85 -51
  136. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  137. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  138. data/lib/active_support/core_ext/time/zones.rb +41 -7
  139. data/lib/active_support/core_ext/time.rb +7 -6
  140. data/lib/active_support/core_ext/uri.rb +6 -8
  141. data/lib/active_support/core_ext.rb +3 -1
  142. data/lib/active_support/current_attributes.rb +195 -0
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +57 -0
  145. data/lib/active_support/dependencies.rb +152 -161
  146. data/lib/active_support/deprecation/behaviors.rb +44 -11
  147. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  148. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  149. data/lib/active_support/deprecation/method_wrappers.rb +66 -20
  150. data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
  151. data/lib/active_support/deprecation/reporting.rb +32 -12
  152. data/lib/active_support/deprecation.rb +12 -9
  153. data/lib/active_support/descendants_tracker.rb +2 -0
  154. data/lib/active_support/digest.rb +20 -0
  155. data/lib/active_support/duration/iso8601_parser.rb +125 -0
  156. data/lib/active_support/duration/iso8601_serializer.rb +55 -0
  157. data/lib/active_support/duration.rb +307 -35
  158. data/lib/active_support/encrypted_configuration.rb +49 -0
  159. data/lib/active_support/encrypted_file.rb +99 -0
  160. data/lib/active_support/evented_file_update_checker.rb +205 -0
  161. data/lib/active_support/execution_wrapper.rb +128 -0
  162. data/lib/active_support/executor.rb +8 -0
  163. data/lib/active_support/file_update_checker.rb +63 -37
  164. data/lib/active_support/gem_version.rb +6 -4
  165. data/lib/active_support/gzip.rb +7 -5
  166. data/lib/active_support/hash_with_indifferent_access.rb +123 -28
  167. data/lib/active_support/i18n.rb +8 -6
  168. data/lib/active_support/i18n_railtie.rb +37 -13
  169. data/lib/active_support/inflections.rb +13 -11
  170. data/lib/active_support/inflector/inflections.rb +61 -12
  171. data/lib/active_support/inflector/methods.rb +163 -136
  172. data/lib/active_support/inflector/transliterate.rb +48 -27
  173. data/lib/active_support/inflector.rb +7 -5
  174. data/lib/active_support/json/decoding.rb +16 -13
  175. data/lib/active_support/json/encoding.rb +11 -58
  176. data/lib/active_support/json.rb +4 -2
  177. data/lib/active_support/key_generator.rb +25 -25
  178. data/lib/active_support/lazy_load_hooks.rb +50 -20
  179. data/lib/active_support/locale/en.yml +2 -0
  180. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  181. data/lib/active_support/log_subscriber.rb +13 -10
  182. data/lib/active_support/logger.rb +8 -7
  183. data/lib/active_support/logger_silence.rb +6 -4
  184. data/lib/active_support/logger_thread_safe_level.rb +7 -5
  185. data/lib/active_support/message_encryptor.rb +168 -53
  186. data/lib/active_support/message_verifier.rb +150 -17
  187. data/lib/active_support/messages/metadata.rb +71 -0
  188. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  189. data/lib/active_support/messages/rotator.rb +56 -0
  190. data/lib/active_support/multibyte/chars.rb +36 -23
  191. data/lib/active_support/multibyte/unicode.rb +100 -96
  192. data/lib/active_support/multibyte.rb +4 -2
  193. data/lib/active_support/notifications/fanout.rb +11 -9
  194. data/lib/active_support/notifications/instrumenter.rb +27 -7
  195. data/lib/active_support/notifications.rb +11 -7
  196. data/lib/active_support/number_helper/number_converter.rb +13 -11
  197. data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -9
  198. data/lib/active_support/number_helper/number_to_delimited_converter.rb +9 -3
  199. data/lib/active_support/number_helper/number_to_human_converter.rb +11 -9
  200. data/lib/active_support/number_helper/number_to_human_size_converter.rb +9 -8
  201. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  202. data/lib/active_support/number_helper/number_to_phone_converter.rb +13 -4
  203. data/lib/active_support/number_helper/number_to_rounded_converter.rb +23 -56
  204. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  205. data/lib/active_support/number_helper.rb +94 -68
  206. data/lib/active_support/option_merger.rb +3 -1
  207. data/lib/active_support/ordered_hash.rb +6 -4
  208. data/lib/active_support/ordered_options.rb +23 -5
  209. data/lib/active_support/per_thread_registry.rb +9 -4
  210. data/lib/active_support/proxy_object.rb +2 -0
  211. data/lib/active_support/rails.rb +16 -8
  212. data/lib/active_support/railtie.rb +43 -9
  213. data/lib/active_support/reloader.rb +131 -0
  214. data/lib/active_support/rescuable.rb +108 -53
  215. data/lib/active_support/security_utils.rb +15 -11
  216. data/lib/active_support/string_inquirer.rb +11 -3
  217. data/lib/active_support/subscriber.rb +21 -16
  218. data/lib/active_support/tagged_logging.rb +14 -11
  219. data/lib/active_support/test_case.rb +19 -47
  220. data/lib/active_support/testing/assertions.rb +137 -20
  221. data/lib/active_support/testing/autorun.rb +4 -2
  222. data/lib/active_support/testing/constant_lookup.rb +2 -1
  223. data/lib/active_support/testing/declarative.rb +3 -1
  224. data/lib/active_support/testing/deprecation.rb +14 -10
  225. data/lib/active_support/testing/file_fixtures.rb +36 -0
  226. data/lib/active_support/testing/isolation.rb +34 -25
  227. data/lib/active_support/testing/method_call_assertions.rb +43 -0
  228. data/lib/active_support/testing/setup_and_teardown.rb +13 -8
  229. data/lib/active_support/testing/stream.rb +44 -0
  230. data/lib/active_support/testing/tagged_logging.rb +3 -1
  231. data/lib/active_support/testing/time_helpers.rb +81 -15
  232. data/lib/active_support/time.rb +14 -12
  233. data/lib/active_support/time_with_zone.rb +169 -39
  234. data/lib/active_support/values/time_zone.rb +196 -61
  235. data/lib/active_support/values/unicode_tables.dat +0 -0
  236. data/lib/active_support/version.rb +3 -1
  237. data/lib/active_support/xml_mini/jdom.rb +116 -114
  238. data/lib/active_support/xml_mini/libxml.rb +16 -13
  239. data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
  240. data/lib/active_support/xml_mini/nokogiri.rb +14 -12
  241. data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
  242. data/lib/active_support/xml_mini/rexml.rb +11 -9
  243. data/lib/active_support/xml_mini.rb +37 -37
  244. data/lib/active_support.rb +12 -11
  245. metadata +54 -24
  246. data/lib/active_support/concurrency/latch.rb +0 -27
  247. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
  248. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  249. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  250. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  251. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
  252. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  253. data/lib/active_support/core_ext/object/itself.rb +0 -15
  254. data/lib/active_support/core_ext/struct.rb +0 -6
  255. data/lib/active_support/core_ext/thread.rb +0 -86
  256. data/lib/active_support/core_ext/time/marshal.rb +0 -30
@@ -1,5 +1,7 @@
1
- require 'active_support/core_ext/hash/keys'
2
- require 'active_support/core_ext/hash/reverse_merge'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/keys"
4
+ require "active_support/core_ext/hash/reverse_merge"
3
5
 
4
6
  module ActiveSupport
5
7
  # Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are considered
@@ -40,6 +42,12 @@ module ActiveSupport
40
42
  # rgb = { black: '#000000', white: '#FFFFFF' }.with_indifferent_access
41
43
  #
42
44
  # which may be handy.
45
+ #
46
+ # To access this class outside of Rails, require the core extension with:
47
+ #
48
+ # require "active_support/core_ext/hash/indifferent_access"
49
+ #
50
+ # which will, in turn, require this file.
43
51
  class HashWithIndifferentAccess < Hash
44
52
  # Returns +true+ so that <tt>Array#extract_options!</tt> finds members of
45
53
  # this class.
@@ -59,24 +67,12 @@ module ActiveSupport
59
67
  if constructor.respond_to?(:to_hash)
60
68
  super()
61
69
  update(constructor)
62
- else
63
- super(constructor)
64
- end
65
- end
66
70
 
67
- def default(key = nil)
68
- if key.is_a?(Symbol) && include?(key = key.to_s)
69
- self[key]
71
+ hash = constructor.to_hash
72
+ self.default = hash.default if hash.default
73
+ self.default_proc = hash.default_proc if hash.default_proc
70
74
  else
71
- super
72
- end
73
- end
74
-
75
- def self.new_from_hash_copying_default(hash)
76
- hash = hash.to_hash
77
- new(hash).tap do |new_hash|
78
- new_hash.default = hash.default
79
- new_hash.default_proc = hash.default_proc if hash.default_proc
75
+ super(constructor)
80
76
  end
81
77
  end
82
78
 
@@ -92,7 +88,7 @@ module ActiveSupport
92
88
  # hash = ActiveSupport::HashWithIndifferentAccess.new
93
89
  # hash[:key] = 'value'
94
90
  #
95
- # This value can be later fetched using either +:key+ or +'key'+.
91
+ # This value can be later fetched using either +:key+ or <tt>'key'</tt>.
96
92
  def []=(key, value)
97
93
  regular_writer(convert_key(key), convert_value(value, for: :assignment))
98
94
  end
@@ -154,6 +150,32 @@ module ActiveSupport
154
150
  alias_method :has_key?, :key?
155
151
  alias_method :member?, :key?
156
152
 
153
+ # Same as <tt>Hash#[]</tt> where the key passed as argument can be
154
+ # either a string or a symbol:
155
+ #
156
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
157
+ # counters[:foo] = 1
158
+ #
159
+ # counters['foo'] # => 1
160
+ # counters[:foo] # => 1
161
+ # counters[:zoo] # => nil
162
+ def [](key)
163
+ super(convert_key(key))
164
+ end
165
+
166
+ # Same as <tt>Hash#assoc</tt> where the key passed as argument can be
167
+ # either a string or a symbol:
168
+ #
169
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
170
+ # counters[:foo] = 1
171
+ #
172
+ # counters.assoc('foo') # => ["foo", 1]
173
+ # counters.assoc(:foo) # => ["foo", 1]
174
+ # counters.assoc(:zoo) # => nil
175
+ def assoc(key)
176
+ super(convert_key(key))
177
+ end
178
+
157
179
  # Same as <tt>Hash#fetch</tt> where the key passed as argument can be
158
180
  # either a string or a symbol:
159
181
  #
@@ -168,6 +190,36 @@ module ActiveSupport
168
190
  super(convert_key(key), *extras)
169
191
  end
170
192
 
193
+ if Hash.new.respond_to?(:dig)
194
+ # Same as <tt>Hash#dig</tt> where the key passed as argument can be
195
+ # either a string or a symbol:
196
+ #
197
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
198
+ # counters[:foo] = { bar: 1 }
199
+ #
200
+ # counters.dig('foo', 'bar') # => 1
201
+ # counters.dig(:foo, :bar) # => 1
202
+ # counters.dig(:zoo) # => nil
203
+ def dig(*args)
204
+ args[0] = convert_key(args[0]) if args.size > 0
205
+ super(*args)
206
+ end
207
+ end
208
+
209
+ # Same as <tt>Hash#default</tt> where the key passed as argument can be
210
+ # either a string or a symbol:
211
+ #
212
+ # hash = ActiveSupport::HashWithIndifferentAccess.new(1)
213
+ # hash.default # => 1
214
+ #
215
+ # hash = ActiveSupport::HashWithIndifferentAccess.new { |hash, key| key }
216
+ # hash.default # => nil
217
+ # hash.default('foo') # => 'foo'
218
+ # hash.default(:foo) # => 'foo'
219
+ def default(*args)
220
+ super(*args.map { |arg| convert_key(arg) })
221
+ end
222
+
171
223
  # Returns an array of the values at the specified indices:
172
224
  #
173
225
  # hash = ActiveSupport::HashWithIndifferentAccess.new
@@ -178,13 +230,26 @@ module ActiveSupport
178
230
  indices.collect { |key| self[convert_key(key)] }
179
231
  end
180
232
 
233
+ # Returns an array of the values at the specified indices, but also
234
+ # raises an exception when one of the keys can't be found.
235
+ #
236
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
237
+ # hash[:a] = 'x'
238
+ # hash[:b] = 'y'
239
+ # hash.fetch_values('a', 'b') # => ["x", "y"]
240
+ # hash.fetch_values('a', 'c') { |key| 'z' } # => ["x", "z"]
241
+ # hash.fetch_values('a', 'c') # => KeyError: key not found: "c"
242
+ def fetch_values(*indices, &block)
243
+ indices.collect { |key| fetch(key, &block) }
244
+ end if Hash.method_defined?(:fetch_values)
245
+
181
246
  # Returns a shallow copy of the hash.
182
247
  #
183
248
  # hash = ActiveSupport::HashWithIndifferentAccess.new({ a: { b: 'b' } })
184
249
  # dup = hash.dup
185
250
  # dup[:a][:c] = 'c'
186
251
  #
187
- # hash[:a][:c] # => nil
252
+ # hash[:a][:c] # => "c"
188
253
  # dup[:a][:c] # => "c"
189
254
  def dup
190
255
  self.class.new(self).tap do |new_hash|
@@ -196,7 +261,7 @@ module ActiveSupport
196
261
  # modify the receiver but rather returns a new hash with indifferent
197
262
  # access with the result of the merge.
198
263
  def merge(hash, &block)
199
- self.dup.update(hash, &block)
264
+ dup.update(hash, &block)
200
265
  end
201
266
 
202
267
  # Like +merge+ but the other way around: Merges the receiver into the
@@ -206,20 +271,22 @@ module ActiveSupport
206
271
  # hash['a'] = nil
207
272
  # hash.reverse_merge(a: 0, b: 1) # => {"a"=>nil, "b"=>1}
208
273
  def reverse_merge(other_hash)
209
- super(self.class.new_from_hash_copying_default(other_hash))
274
+ super(self.class.new(other_hash))
210
275
  end
276
+ alias_method :with_defaults, :reverse_merge
211
277
 
212
278
  # Same semantics as +reverse_merge+ but modifies the receiver in-place.
213
279
  def reverse_merge!(other_hash)
214
- replace(reverse_merge( other_hash ))
280
+ super(self.class.new(other_hash))
215
281
  end
282
+ alias_method :with_defaults!, :reverse_merge!
216
283
 
217
284
  # Replaces the contents of this hash with other_hash.
218
285
  #
219
286
  # h = { "a" => 100, "b" => 200 }
220
287
  # h.replace({ "c" => 300, "d" => 400 }) # => {"c"=>300, "d"=>400}
221
288
  def replace(other_hash)
222
- super(self.class.new_from_hash_copying_default(other_hash))
289
+ super(self.class.new(other_hash))
223
290
  end
224
291
 
225
292
  # Removes the specified key from the hash.
@@ -234,14 +301,17 @@ module ActiveSupport
234
301
  undef :symbolize_keys!
235
302
  undef :deep_symbolize_keys!
236
303
  def symbolize_keys; to_hash.symbolize_keys! end
304
+ alias_method :to_options, :symbolize_keys
237
305
  def deep_symbolize_keys; to_hash.deep_symbolize_keys! end
238
306
  def to_options!; self end
239
307
 
240
308
  def select(*args, &block)
309
+ return to_enum(:select) unless block_given?
241
310
  dup.tap { |hash| hash.select!(*args, &block) }
242
311
  end
243
312
 
244
313
  def reject(*args, &block)
314
+ return to_enum(:reject) unless block_given?
245
315
  dup.tap { |hash| hash.reject!(*args, &block) }
246
316
  end
247
317
 
@@ -250,6 +320,29 @@ module ActiveSupport
250
320
  dup.tap { |hash| hash.transform_values!(*args, &block) }
251
321
  end
252
322
 
323
+ def transform_keys(*args, &block)
324
+ return to_enum(:transform_keys) unless block_given?
325
+ dup.tap { |hash| hash.transform_keys!(*args, &block) }
326
+ end
327
+
328
+ def transform_keys!
329
+ return enum_for(:transform_keys!) { size } unless block_given?
330
+ keys.each do |key|
331
+ self[yield(key)] = delete(key)
332
+ end
333
+ self
334
+ end
335
+
336
+ def slice(*keys)
337
+ keys.map! { |key| convert_key(key) }
338
+ self.class.new(super)
339
+ end
340
+
341
+ def slice!(*keys)
342
+ keys.map! { |key| convert_key(key) }
343
+ super
344
+ end
345
+
253
346
  def compact
254
347
  dup.tap(&:compact!)
255
348
  end
@@ -265,12 +358,12 @@ module ActiveSupport
265
358
  _new_hash
266
359
  end
267
360
 
268
- protected
269
- def convert_key(key)
361
+ private
362
+ def convert_key(key) # :doc:
270
363
  key.kind_of?(Symbol) ? key.to_s : key
271
364
  end
272
365
 
273
- def convert_value(value, options = {})
366
+ def convert_value(value, options = {}) # :doc:
274
367
  if value.is_a? Hash
275
368
  if options[:for] == :to_hash
276
369
  value.to_hash
@@ -287,7 +380,7 @@ module ActiveSupport
287
380
  end
288
381
  end
289
382
 
290
- def set_defaults(target)
383
+ def set_defaults(target) # :doc:
291
384
  if default_proc
292
385
  target.default_proc = default_proc.dup
293
386
  else
@@ -297,4 +390,6 @@ module ActiveSupport
297
390
  end
298
391
  end
299
392
 
393
+ # :stopdoc:
394
+
300
395
  HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess
@@ -1,13 +1,15 @@
1
- require 'active_support/core_ext/hash/deep_merge'
2
- require 'active_support/core_ext/hash/except'
3
- require 'active_support/core_ext/hash/slice'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/deep_merge"
4
+ require "active_support/core_ext/hash/except"
5
+ require "active_support/core_ext/hash/slice"
4
6
  begin
5
- require 'i18n'
7
+ require "i18n"
6
8
  rescue LoadError => e
7
9
  $stderr.puts "The i18n gem is not available. Please add it to your Gemfile and run bundle install"
8
10
  raise e
9
11
  end
10
- require 'active_support/lazy_load_hooks'
12
+ require "active_support/lazy_load_hooks"
11
13
 
12
14
  ActiveSupport.run_load_hooks(:i18n)
13
- I18n.load_path << "#{File.dirname(__FILE__)}/locale/en.yml"
15
+ I18n.load_path << File.expand_path("locale/en.yml", __dir__)
@@ -1,7 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support"
2
4
  require "active_support/file_update_checker"
3
5
  require "active_support/core_ext/array/wrap"
4
6
 
7
+ # :enddoc:
8
+
5
9
  module I18n
6
10
  class Railtie < Rails::Railtie
7
11
  config.i18n = ActiveSupport::OrderedOptions.new
@@ -21,8 +25,6 @@ module I18n
21
25
  I18n::Railtie.initialize_i18n(app)
22
26
  end
23
27
 
24
- protected
25
-
26
28
  @i18n_inited = false
27
29
 
28
30
  # Setup i18n configuration.
@@ -37,10 +39,12 @@ module I18n
37
39
  enforce_available_locales = I18n.enforce_available_locales if enforce_available_locales.nil?
38
40
  I18n.enforce_available_locales = false
39
41
 
42
+ reloadable_paths = []
40
43
  app.config.i18n.each do |setting, value|
41
44
  case setting
42
45
  when :railties_load_path
43
- app.config.i18n.load_path.unshift(*value)
46
+ reloadable_paths = value
47
+ app.config.i18n.load_path.unshift(*value.flat_map(&:existent))
44
48
  when :load_path
45
49
  I18n.load_path += value
46
50
  else
@@ -53,28 +57,42 @@ module I18n
53
57
  # Restore available locales check so it will take place from now on.
54
58
  I18n.enforce_available_locales = enforce_available_locales
55
59
 
56
- reloader = ActiveSupport::FileUpdateChecker.new(I18n.load_path.dup){ I18n.reload! }
60
+ directories = watched_dirs_with_extensions(reloadable_paths)
61
+ reloader = app.config.file_watcher.new(I18n.load_path.dup, directories) do
62
+ I18n.load_path.keep_if { |p| File.exist?(p) }
63
+ I18n.load_path |= reloadable_paths.flat_map(&:existent)
64
+
65
+ I18n.reload!
66
+ end
67
+
57
68
  app.reloaders << reloader
58
- ActionDispatch::Reloader.to_prepare { reloader.execute_if_updated }
69
+ app.reloader.to_run do
70
+ reloader.execute_if_updated { require_unload_lock! }
71
+ end
59
72
  reloader.execute
60
73
 
61
74
  @i18n_inited = true
62
75
  end
63
76
 
64
77
  def self.include_fallbacks_module
65
- I18n.backend.class.send(:include, I18n::Backend::Fallbacks)
78
+ I18n.backend.class.include(I18n::Backend::Fallbacks)
66
79
  end
67
80
 
68
81
  def self.init_fallbacks(fallbacks)
69
82
  include_fallbacks_module
70
83
 
71
- args = case fallbacks
72
- when ActiveSupport::OrderedOptions
73
- [*(fallbacks[:defaults] || []) << fallbacks[:map]].compact
74
- when Hash, Array
75
- Array.wrap(fallbacks)
76
- else # TrueClass
77
- []
84
+ args = \
85
+ case fallbacks
86
+ when ActiveSupport::OrderedOptions
87
+ [*(fallbacks[:defaults] || []) << fallbacks[:map]].compact
88
+ when Hash, Array
89
+ Array.wrap(fallbacks)
90
+ else # TrueClass
91
+ [I18n.default_locale]
92
+ end
93
+
94
+ if args.empty? || args.first.is_a?(Hash)
95
+ args.unshift I18n.default_locale
78
96
  end
79
97
 
80
98
  I18n.fallbacks = I18n::Locale::Fallbacks.new(*args)
@@ -90,5 +108,11 @@ module I18n
90
108
  raise "Unexpected fallback type #{fallbacks.inspect}"
91
109
  end
92
110
  end
111
+
112
+ def self.watched_dirs_with_extensions(paths)
113
+ paths.each_with_object({}) do |path, result|
114
+ result[path.absolute_current] = path.extensions
115
+ end
116
+ end
93
117
  end
94
118
  end
@@ -1,4 +1,6 @@
1
- require 'active_support/inflector/inflections'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/inflector/inflections"
2
4
 
3
5
  #--
4
6
  # Defines the standard inflection rules. These are the starting point for
@@ -8,8 +10,8 @@ require 'active_support/inflector/inflections'
8
10
  #++
9
11
  module ActiveSupport
10
12
  Inflector.inflections(:en) do |inflect|
11
- inflect.plural(/$/, 's')
12
- inflect.plural(/s$/i, 's')
13
+ inflect.plural(/$/, "s")
14
+ inflect.plural(/s$/i, "s")
13
15
  inflect.plural(/^(ax|test)is$/i, '\1es')
14
16
  inflect.plural(/(octop|vir)us$/i, '\1i')
15
17
  inflect.plural(/(octop|vir)i$/i, '\1i')
@@ -18,7 +20,7 @@ module ActiveSupport
18
20
  inflect.plural(/(buffal|tomat)o$/i, '\1oes')
19
21
  inflect.plural(/([ti])um$/i, '\1a')
20
22
  inflect.plural(/([ti])a$/i, '\1a')
21
- inflect.plural(/sis$/i, 'ses')
23
+ inflect.plural(/sis$/i, "ses")
22
24
  inflect.plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
23
25
  inflect.plural(/(hive)$/i, '\1s')
24
26
  inflect.plural(/([^aeiouy]|qu)y$/i, '\1ies')
@@ -30,7 +32,7 @@ module ActiveSupport
30
32
  inflect.plural(/^(oxen)$/i, '\1')
31
33
  inflect.plural(/(quiz)$/i, '\1zes')
32
34
 
33
- inflect.singular(/s$/i, '')
35
+ inflect.singular(/s$/i, "")
34
36
  inflect.singular(/(ss)$/i, '\1')
35
37
  inflect.singular(/(n)ews$/i, '\1ews')
36
38
  inflect.singular(/([ti])a$/i, '\1um')
@@ -58,12 +60,12 @@ module ActiveSupport
58
60
  inflect.singular(/(quiz)zes$/i, '\1')
59
61
  inflect.singular(/(database)s$/i, '\1')
60
62
 
61
- inflect.irregular('person', 'people')
62
- inflect.irregular('man', 'men')
63
- inflect.irregular('child', 'children')
64
- inflect.irregular('sex', 'sexes')
65
- inflect.irregular('move', 'moves')
66
- inflect.irregular('zombie', 'zombies')
63
+ inflect.irregular("person", "people")
64
+ inflect.irregular("man", "men")
65
+ inflect.irregular("child", "children")
66
+ inflect.irregular("sex", "sexes")
67
+ inflect.irregular("move", "moves")
68
+ inflect.irregular("zombie", "zombies")
67
69
 
68
70
  inflect.uncountable(%w(equipment information rice money species series fish sheep jeans police))
69
71
  end
@@ -1,6 +1,10 @@
1
- require 'thread_safe'
2
- require 'active_support/core_ext/array/prepend_and_append'
3
- require 'active_support/i18n'
1
+ # frozen_string_literal: true
2
+
3
+ require "concurrent/map"
4
+ require "active_support/core_ext/array/prepend_and_append"
5
+ require "active_support/core_ext/regexp"
6
+ require "active_support/i18n"
7
+ require "active_support/deprecation"
4
8
 
5
9
  module ActiveSupport
6
10
  module Inflector
@@ -25,23 +29,60 @@ module ActiveSupport
25
29
  # singularization rules that is runs. This guarantees that your rules run
26
30
  # before any of the rules that may already have been loaded.
27
31
  class Inflections
28
- @__instance__ = ThreadSafe::Cache.new
32
+ @__instance__ = Concurrent::Map.new
33
+
34
+ class Uncountables < Array
35
+ def initialize
36
+ @regex_array = []
37
+ super
38
+ end
39
+
40
+ def delete(entry)
41
+ super entry
42
+ @regex_array.delete(to_regex(entry))
43
+ end
44
+
45
+ def <<(*word)
46
+ add(word)
47
+ end
48
+
49
+ def add(words)
50
+ words = words.flatten.map(&:downcase)
51
+ concat(words)
52
+ @regex_array += words.map { |word| to_regex(word) }
53
+ self
54
+ end
55
+
56
+ def uncountable?(str)
57
+ @regex_array.any? { |regex| regex.match? str }
58
+ end
59
+
60
+ private
61
+ def to_regex(string)
62
+ /\b#{::Regexp.escape(string)}\Z/i
63
+ end
64
+ end
29
65
 
30
66
  def self.instance(locale = :en)
31
67
  @__instance__[locale] ||= new
32
68
  end
33
69
 
34
70
  attr_reader :plurals, :singulars, :uncountables, :humans, :acronyms, :acronym_regex
71
+ deprecate :acronym_regex
72
+
73
+ attr_reader :acronyms_camelize_regex, :acronyms_underscore_regex # :nodoc:
35
74
 
36
75
  def initialize
37
- @plurals, @singulars, @uncountables, @humans, @acronyms, @acronym_regex = [], [], [], [], {}, /(?=a)b/
76
+ @plurals, @singulars, @uncountables, @humans, @acronyms = [], [], Uncountables.new, [], {}
77
+ define_acronym_regex_patterns
38
78
  end
39
79
 
40
80
  # Private, for the test suite.
41
81
  def initialize_dup(orig) # :nodoc:
42
- %w(plurals singulars uncountables humans acronyms acronym_regex).each do |scope|
82
+ %w(plurals singulars uncountables humans acronyms).each do |scope|
43
83
  instance_variable_set("@#{scope}", orig.send(scope).dup)
44
84
  end
85
+ define_acronym_regex_patterns
45
86
  end
46
87
 
47
88
  # Specifies a new acronym. An acronym must be specified as it will appear
@@ -95,7 +136,7 @@ module ActiveSupport
95
136
  # camelize 'mcdonald' # => 'McDonald'
96
137
  def acronym(word)
97
138
  @acronyms[word.downcase] = word
98
- @acronym_regex = /#{@acronyms.values.join("|")}/
139
+ define_acronym_regex_patterns
99
140
  end
100
141
 
101
142
  # Specifies a new pluralization rule and its replacement. The rule can
@@ -160,7 +201,7 @@ module ActiveSupport
160
201
  # uncountable 'money', 'information'
161
202
  # uncountable %w( money information rice )
162
203
  def uncountable(*words)
163
- @uncountables += words.flatten.map(&:downcase)
204
+ @uncountables.add(words)
164
205
  end
165
206
 
166
207
  # Specifies a humanized form of a string by a regular expression rule or
@@ -184,12 +225,20 @@ module ActiveSupport
184
225
  # clear :plurals
185
226
  def clear(scope = :all)
186
227
  case scope
187
- when :all
188
- @plurals, @singulars, @uncountables, @humans = [], [], [], []
189
- else
190
- instance_variable_set "@#{scope}", []
228
+ when :all
229
+ @plurals, @singulars, @uncountables, @humans = [], [], Uncountables.new, []
230
+ else
231
+ instance_variable_set "@#{scope}", []
191
232
  end
192
233
  end
234
+
235
+ private
236
+
237
+ def define_acronym_regex_patterns
238
+ @acronym_regex = @acronyms.empty? ? /(?=a)b/ : /#{@acronyms.values.join("|")}/
239
+ @acronyms_camelize_regex = /^(?:#{@acronym_regex}(?=\b|[A-Z_])|\w)/
240
+ @acronyms_underscore_regex = /(?:(?<=([A-Za-z\d]))|\b)(#{@acronym_regex})(?=\b|[^a-z])/
241
+ end
193
242
  end
194
243
 
195
244
  # Yields a singleton instance of Inflector::Inflections so you can specify