activesupport 5.1.7 → 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 (279) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +259 -585
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -5
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/all.rb +2 -0
  7. data/lib/active_support/array_inquirer.rb +4 -2
  8. data/lib/active_support/backtrace_cleaner.rb +33 -5
  9. data/lib/active_support/benchmarkable.rb +5 -3
  10. data/lib/active_support/builder.rb +2 -0
  11. data/lib/active_support/cache/file_store.rb +50 -43
  12. data/lib/active_support/cache/mem_cache_store.rb +194 -67
  13. data/lib/active_support/cache/memory_store.rb +70 -34
  14. data/lib/active_support/cache/null_store.rb +18 -3
  15. data/lib/active_support/cache/redis_cache_store.rb +474 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +73 -50
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
  18. data/lib/active_support/cache.rb +556 -220
  19. data/lib/active_support/callbacks.rb +264 -159
  20. data/lib/active_support/code_generator.rb +65 -0
  21. data/lib/active_support/concern.rb +81 -8
  22. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +16 -0
  23. data/lib/active_support/concurrency/share_lock.rb +4 -3
  24. data/lib/active_support/configurable.rb +17 -16
  25. data/lib/active_support/configuration_file.rb +51 -0
  26. data/lib/active_support/core_ext/array/access.rb +18 -8
  27. data/lib/active_support/core_ext/array/conversions.rb +20 -17
  28. data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
  29. data/lib/active_support/core_ext/array/extract.rb +21 -0
  30. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  31. data/lib/active_support/core_ext/array/grouping.rb +8 -6
  32. data/lib/active_support/core_ext/array/inquiry.rb +4 -2
  33. data/lib/active_support/core_ext/array/wrap.rb +2 -0
  34. data/lib/active_support/core_ext/array.rb +4 -1
  35. data/lib/active_support/core_ext/benchmark.rb +4 -2
  36. data/lib/active_support/core_ext/big_decimal/conversions.rb +3 -1
  37. data/lib/active_support/core_ext/big_decimal.rb +2 -0
  38. data/lib/active_support/core_ext/class/attribute.rb +50 -47
  39. data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
  40. data/lib/active_support/core_ext/class/subclasses.rb +10 -24
  41. data/lib/active_support/core_ext/class.rb +2 -0
  42. data/lib/active_support/core_ext/date/acts_like.rb +2 -0
  43. data/lib/active_support/core_ext/date/blank.rb +3 -1
  44. data/lib/active_support/core_ext/date/calculations.rb +17 -14
  45. data/lib/active_support/core_ext/date/conversions.rb +24 -22
  46. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  47. data/lib/active_support/core_ext/date/zones.rb +2 -0
  48. data/lib/active_support/core_ext/date.rb +3 -0
  49. data/lib/active_support/core_ext/date_and_time/calculations.rb +65 -41
  50. data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -1
  51. data/lib/active_support/core_ext/date_and_time/zones.rb +2 -1
  52. data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
  53. data/lib/active_support/core_ext/date_time/blank.rb +3 -1
  54. data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
  55. data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
  56. data/lib/active_support/core_ext/date_time/conversions.rb +15 -14
  57. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  58. data/lib/active_support/core_ext/date_time.rb +3 -0
  59. data/lib/active_support/core_ext/digest/uuid.rb +42 -14
  60. data/lib/active_support/core_ext/digest.rb +3 -0
  61. data/lib/active_support/core_ext/enumerable.rb +244 -72
  62. data/lib/active_support/core_ext/file/atomic.rb +6 -2
  63. data/lib/active_support/core_ext/file.rb +2 -0
  64. data/lib/active_support/core_ext/hash/conversions.rb +7 -6
  65. data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
  66. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  67. data/lib/active_support/core_ext/hash/except.rb +4 -2
  68. data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
  69. data/lib/active_support/core_ext/hash/keys.rb +4 -31
  70. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  71. data/lib/active_support/core_ext/hash/slice.rb +8 -29
  72. data/lib/active_support/core_ext/hash.rb +3 -2
  73. data/lib/active_support/core_ext/integer/inflections.rb +2 -0
  74. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  75. data/lib/active_support/core_ext/integer/time.rb +7 -14
  76. data/lib/active_support/core_ext/integer.rb +2 -0
  77. data/lib/active_support/core_ext/kernel/concern.rb +2 -0
  78. data/lib/active_support/core_ext/kernel/reporting.rb +6 -4
  79. data/lib/active_support/core_ext/kernel/singleton_class.rb +3 -1
  80. data/lib/active_support/core_ext/kernel.rb +2 -1
  81. data/lib/active_support/core_ext/load_error.rb +3 -8
  82. data/lib/active_support/core_ext/module/aliasing.rb +2 -0
  83. data/lib/active_support/core_ext/module/anonymous.rb +2 -0
  84. data/lib/active_support/core_ext/module/attr_internal.rb +4 -2
  85. data/lib/active_support/core_ext/module/attribute_accessors.rb +46 -56
  86. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +36 -27
  87. data/lib/active_support/core_ext/module/concerning.rb +15 -10
  88. data/lib/active_support/core_ext/module/delegation.rb +97 -58
  89. data/lib/active_support/core_ext/module/deprecation.rb +2 -0
  90. data/lib/active_support/core_ext/module/introspection.rb +18 -15
  91. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +5 -23
  93. data/lib/active_support/core_ext/module.rb +3 -1
  94. data/lib/active_support/core_ext/name_error.rb +30 -2
  95. data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +134 -129
  97. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +7 -15
  99. data/lib/active_support/core_ext/numeric.rb +3 -1
  100. data/lib/active_support/core_ext/object/acts_like.rb +41 -6
  101. data/lib/active_support/core_ext/object/blank.rb +15 -5
  102. data/lib/active_support/core_ext/object/conversions.rb +2 -0
  103. data/lib/active_support/core_ext/object/deep_dup.rb +3 -1
  104. data/lib/active_support/core_ext/object/duplicable.rb +16 -110
  105. data/lib/active_support/core_ext/object/inclusion.rb +2 -0
  106. data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
  107. data/lib/active_support/core_ext/object/json.rb +51 -26
  108. data/lib/active_support/core_ext/object/to_param.rb +2 -0
  109. data/lib/active_support/core_ext/object/to_query.rb +4 -2
  110. data/lib/active_support/core_ext/object/try.rb +26 -14
  111. data/lib/active_support/core_ext/object/with_options.rb +24 -3
  112. data/lib/active_support/core_ext/object.rb +2 -0
  113. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  114. data/lib/active_support/core_ext/pathname.rb +3 -0
  115. data/lib/active_support/core_ext/range/compare_range.rb +57 -0
  116. data/lib/active_support/core_ext/range/conversions.rb +35 -25
  117. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  118. data/lib/active_support/core_ext/range/each.rb +6 -3
  119. data/lib/active_support/core_ext/range/include_time_with_zone.rb +7 -0
  120. data/lib/active_support/core_ext/range/overlaps.rb +3 -1
  121. data/lib/active_support/core_ext/range.rb +4 -1
  122. data/lib/active_support/core_ext/regexp.rb +10 -5
  123. data/lib/active_support/core_ext/securerandom.rb +25 -3
  124. data/lib/active_support/core_ext/string/access.rb +7 -16
  125. data/lib/active_support/core_ext/string/behavior.rb +2 -0
  126. data/lib/active_support/core_ext/string/conversions.rb +5 -2
  127. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  128. data/lib/active_support/core_ext/string/filters.rb +44 -1
  129. data/lib/active_support/core_ext/string/indent.rb +2 -0
  130. data/lib/active_support/core_ext/string/inflections.rb +69 -16
  131. data/lib/active_support/core_ext/string/inquiry.rb +4 -1
  132. data/lib/active_support/core_ext/string/multibyte.rb +9 -4
  133. data/lib/active_support/core_ext/string/output_safety.rb +135 -27
  134. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  135. data/lib/active_support/core_ext/string/strip.rb +5 -1
  136. data/lib/active_support/core_ext/string/zones.rb +2 -0
  137. data/lib/active_support/core_ext/string.rb +2 -0
  138. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  139. data/lib/active_support/core_ext/symbol.rb +3 -0
  140. data/lib/active_support/core_ext/time/acts_like.rb +2 -0
  141. data/lib/active_support/core_ext/time/calculations.rb +81 -24
  142. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  143. data/lib/active_support/core_ext/time/conversions.rb +17 -12
  144. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  145. data/lib/active_support/core_ext/time/zones.rb +12 -25
  146. data/lib/active_support/core_ext/time.rb +3 -0
  147. data/lib/active_support/core_ext/uri.rb +4 -23
  148. data/lib/active_support/core_ext.rb +4 -1
  149. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  150. data/lib/active_support/current_attributes.rb +226 -0
  151. data/lib/active_support/dependencies/autoload.rb +2 -0
  152. data/lib/active_support/dependencies/interlock.rb +12 -18
  153. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  154. data/lib/active_support/dependencies.rb +59 -715
  155. data/lib/active_support/deprecation/behaviors.rb +48 -13
  156. data/lib/active_support/deprecation/constant_accessor.rb +4 -2
  157. data/lib/active_support/deprecation/disallowed.rb +56 -0
  158. data/lib/active_support/deprecation/instance_delegator.rb +2 -1
  159. data/lib/active_support/deprecation/method_wrappers.rb +29 -21
  160. data/lib/active_support/deprecation/proxy_wrappers.rb +34 -8
  161. data/lib/active_support/deprecation/reporting.rb +54 -9
  162. data/lib/active_support/deprecation.rb +10 -3
  163. data/lib/active_support/descendants_tracker.rb +192 -34
  164. data/lib/active_support/digest.rb +22 -0
  165. data/lib/active_support/duration/iso8601_parser.rb +9 -9
  166. data/lib/active_support/duration/iso8601_serializer.rb +29 -15
  167. data/lib/active_support/duration.rb +158 -72
  168. data/lib/active_support/encrypted_configuration.rb +56 -0
  169. data/lib/active_support/encrypted_file.rb +129 -0
  170. data/lib/active_support/environment_inquirer.rb +20 -0
  171. data/lib/active_support/error_reporter.rb +117 -0
  172. data/lib/active_support/evented_file_update_checker.rb +87 -122
  173. data/lib/active_support/execution_context/test_helper.rb +13 -0
  174. data/lib/active_support/execution_context.rb +53 -0
  175. data/lib/active_support/execution_wrapper.rb +46 -21
  176. data/lib/active_support/executor/test_helper.rb +7 -0
  177. data/lib/active_support/executor.rb +2 -0
  178. data/lib/active_support/file_update_checker.rb +2 -1
  179. data/lib/active_support/fork_tracker.rb +71 -0
  180. data/lib/active_support/gem_version.rb +7 -5
  181. data/lib/active_support/gzip.rb +2 -0
  182. data/lib/active_support/hash_with_indifferent_access.rb +126 -42
  183. data/lib/active_support/html_safe_translation.rb +43 -0
  184. data/lib/active_support/i18n.rb +5 -1
  185. data/lib/active_support/i18n_railtie.rb +19 -14
  186. data/lib/active_support/inflections.rb +2 -0
  187. data/lib/active_support/inflector/inflections.rb +41 -14
  188. data/lib/active_support/inflector/methods.rb +73 -87
  189. data/lib/active_support/inflector/transliterate.rb +56 -18
  190. data/lib/active_support/inflector.rb +2 -0
  191. data/lib/active_support/isolated_execution_state.rb +72 -0
  192. data/lib/active_support/json/decoding.rb +27 -26
  193. data/lib/active_support/json/encoding.rb +16 -6
  194. data/lib/active_support/json.rb +2 -0
  195. data/lib/active_support/key_generator.rb +25 -38
  196. data/lib/active_support/lazy_load_hooks.rb +35 -6
  197. data/lib/active_support/locale/en.rb +33 -0
  198. data/lib/active_support/locale/en.yml +8 -4
  199. data/lib/active_support/log_subscriber/test_helper.rb +4 -2
  200. data/lib/active_support/log_subscriber.rb +54 -13
  201. data/lib/active_support/logger.rb +4 -17
  202. data/lib/active_support/logger_silence.rb +13 -20
  203. data/lib/active_support/logger_thread_safe_level.rb +48 -10
  204. data/lib/active_support/message_encryptor.rb +111 -37
  205. data/lib/active_support/message_verifier.rb +124 -21
  206. data/lib/active_support/messages/metadata.rb +80 -0
  207. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  208. data/lib/active_support/messages/rotator.rb +57 -0
  209. data/lib/active_support/multibyte/chars.rb +19 -76
  210. data/lib/active_support/multibyte/unicode.rb +9 -331
  211. data/lib/active_support/multibyte.rb +3 -1
  212. data/lib/active_support/notifications/fanout.rb +165 -37
  213. data/lib/active_support/notifications/instrumenter.rb +92 -11
  214. data/lib/active_support/notifications.rb +96 -30
  215. data/lib/active_support/number_helper/number_converter.rb +8 -9
  216. data/lib/active_support/number_helper/number_to_currency_converter.rb +14 -12
  217. data/lib/active_support/number_helper/number_to_delimited_converter.rb +6 -3
  218. data/lib/active_support/number_helper/number_to_human_converter.rb +6 -3
  219. data/lib/active_support/number_helper/number_to_human_size_converter.rb +7 -4
  220. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  221. data/lib/active_support/number_helper/number_to_phone_converter.rb +6 -3
  222. data/lib/active_support/number_helper/number_to_rounded_converter.rb +14 -27
  223. data/lib/active_support/number_helper/rounding_helper.rb +16 -34
  224. data/lib/active_support/number_helper.rb +38 -12
  225. data/lib/active_support/option_merger.rb +19 -6
  226. data/lib/active_support/ordered_hash.rb +4 -2
  227. data/lib/active_support/ordered_options.rb +18 -6
  228. data/lib/active_support/parameter_filter.rb +138 -0
  229. data/lib/active_support/per_thread_registry.rb +8 -1
  230. data/lib/active_support/proxy_object.rb +2 -0
  231. data/lib/active_support/rails.rb +3 -10
  232. data/lib/active_support/railtie.rb +112 -11
  233. data/lib/active_support/reloader.rb +12 -11
  234. data/lib/active_support/rescuable.rb +19 -18
  235. data/lib/active_support/ruby_features.rb +7 -0
  236. data/lib/active_support/secure_compare_rotator.rb +51 -0
  237. data/lib/active_support/security_utils.rb +26 -15
  238. data/lib/active_support/string_inquirer.rb +4 -3
  239. data/lib/active_support/subscriber.rb +81 -42
  240. data/lib/active_support/tagged_logging.rb +45 -9
  241. data/lib/active_support/test_case.rb +86 -2
  242. data/lib/active_support/testing/assertions.rb +89 -21
  243. data/lib/active_support/testing/autorun.rb +2 -0
  244. data/lib/active_support/testing/constant_lookup.rb +2 -0
  245. data/lib/active_support/testing/declarative.rb +2 -0
  246. data/lib/active_support/testing/deprecation.rb +54 -2
  247. data/lib/active_support/testing/file_fixtures.rb +4 -0
  248. data/lib/active_support/testing/isolation.rb +6 -4
  249. data/lib/active_support/testing/method_call_assertions.rb +34 -5
  250. data/lib/active_support/testing/parallelization/server.rb +82 -0
  251. data/lib/active_support/testing/parallelization/worker.rb +103 -0
  252. data/lib/active_support/testing/parallelization.rb +55 -0
  253. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  254. data/lib/active_support/testing/setup_and_teardown.rb +12 -7
  255. data/lib/active_support/testing/stream.rb +6 -7
  256. data/lib/active_support/testing/tagged_logging.rb +3 -1
  257. data/lib/active_support/testing/time_helpers.rb +91 -15
  258. data/lib/active_support/time.rb +2 -0
  259. data/lib/active_support/time_with_zone.rb +168 -56
  260. data/lib/active_support/values/time_zone.rb +85 -37
  261. data/lib/active_support/version.rb +3 -1
  262. data/lib/active_support/xml_mini/jdom.rb +6 -5
  263. data/lib/active_support/xml_mini/libxml.rb +9 -7
  264. data/lib/active_support/xml_mini/libxmlsax.rb +7 -5
  265. data/lib/active_support/xml_mini/nokogiri.rb +8 -6
  266. data/lib/active_support/xml_mini/nokogirisax.rb +6 -4
  267. data/lib/active_support/xml_mini/rexml.rb +13 -4
  268. data/lib/active_support/xml_mini.rb +10 -15
  269. data/lib/active_support.rb +30 -9
  270. metadata +76 -35
  271. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  272. data/lib/active_support/core_ext/hash/compact.rb +0 -27
  273. data/lib/active_support/core_ext/hash/transform_values.rb +0 -30
  274. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  275. data/lib/active_support/core_ext/marshal.rb +0 -22
  276. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  277. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
  278. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  279. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "zlib"
2
4
  require "stringio"
3
5
 
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/hash/keys"
2
4
  require "active_support/core_ext/hash/reverse_merge"
5
+ require "active_support/core_ext/hash/except"
6
+ require "active_support/core_ext/hash/slice"
3
7
 
4
8
  module ActiveSupport
5
9
  # Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are considered
@@ -61,14 +65,16 @@ module ActiveSupport
61
65
  self
62
66
  end
63
67
 
64
- def initialize(constructor = {})
68
+ def initialize(constructor = nil)
65
69
  if constructor.respond_to?(:to_hash)
66
70
  super()
67
71
  update(constructor)
68
72
 
69
- hash = constructor.to_hash
73
+ hash = constructor.is_a?(Hash) ? constructor : constructor.to_hash
70
74
  self.default = hash.default if hash.default
71
75
  self.default_proc = hash.default_proc if hash.default_proc
76
+ elsif constructor.nil?
77
+ super()
72
78
  else
73
79
  super(constructor)
74
80
  end
@@ -88,12 +94,12 @@ module ActiveSupport
88
94
  #
89
95
  # This value can be later fetched using either +:key+ or <tt>'key'</tt>.
90
96
  def []=(key, value)
91
- regular_writer(convert_key(key), convert_value(value, for: :assignment))
97
+ regular_writer(convert_key(key), convert_value(value, conversion: :assignment))
92
98
  end
93
99
 
94
100
  alias_method :store, :[]=
95
101
 
96
- # Updates the receiver in-place, merging in the hash passed as argument:
102
+ # Updates the receiver in-place, merging in the hashes passed as arguments:
97
103
  #
98
104
  # hash_1 = ActiveSupport::HashWithIndifferentAccess.new
99
105
  # hash_1[:key] = 'value'
@@ -103,11 +109,14 @@ module ActiveSupport
103
109
  #
104
110
  # hash_1.update(hash_2) # => {"key"=>"New Value!"}
105
111
  #
106
- # The argument can be either an
112
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
113
+ # hash.update({ "a" => 1 }, { "b" => 2 }) # => { "a" => 1, "b" => 2 }
114
+ #
115
+ # The arguments can be either an
107
116
  # <tt>ActiveSupport::HashWithIndifferentAccess</tt> or a regular +Hash+.
108
117
  # In either case the merge respects the semantics of indifferent access.
109
118
  #
110
- # If the argument is a regular hash with keys +:key+ and +"key"+ only one
119
+ # If the argument is a regular hash with keys +:key+ and <tt>"key"</tt> only one
111
120
  # of the values end up in the receiver, but which one is unspecified.
112
121
  #
113
122
  # When given a block, the value for duplicated keys will be determined
@@ -118,18 +127,15 @@ module ActiveSupport
118
127
  # hash_1[:key] = 10
119
128
  # hash_2['key'] = 12
120
129
  # hash_1.update(hash_2) { |key, old, new| old + new } # => {"key"=>22}
121
- def update(other_hash)
122
- if other_hash.is_a? HashWithIndifferentAccess
123
- super(other_hash)
130
+ def update(*other_hashes, &block)
131
+ if other_hashes.size == 1
132
+ update_with_single_argument(other_hashes.first, block)
124
133
  else
125
- other_hash.to_hash.each_pair do |key, value|
126
- if block_given? && key?(key)
127
- value = yield(convert_key(key), self[key], value)
128
- end
129
- regular_writer(convert_key(key), convert_value(value))
134
+ other_hashes.each do |other_hash|
135
+ update_with_single_argument(other_hash, block)
130
136
  end
131
- self
132
137
  end
138
+ self
133
139
  end
134
140
 
135
141
  alias_method :merge!, :update
@@ -161,6 +167,19 @@ module ActiveSupport
161
167
  super(convert_key(key))
162
168
  end
163
169
 
170
+ # Same as <tt>Hash#assoc</tt> where the key passed as argument can be
171
+ # either a string or a symbol:
172
+ #
173
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
174
+ # counters[:foo] = 1
175
+ #
176
+ # counters.assoc('foo') # => ["foo", 1]
177
+ # counters.assoc(:foo) # => ["foo", 1]
178
+ # counters.assoc(:zoo) # => nil
179
+ def assoc(key)
180
+ super(convert_key(key))
181
+ end
182
+
164
183
  # Same as <tt>Hash#fetch</tt> where the key passed as argument can be
165
184
  # either a string or a symbol:
166
185
  #
@@ -175,20 +194,18 @@ module ActiveSupport
175
194
  super(convert_key(key), *extras)
176
195
  end
177
196
 
178
- if Hash.new.respond_to?(:dig)
179
- # Same as <tt>Hash#dig</tt> where the key passed as argument can be
180
- # either a string or a symbol:
181
- #
182
- # counters = ActiveSupport::HashWithIndifferentAccess.new
183
- # counters[:foo] = { bar: 1 }
184
- #
185
- # counters.dig('foo', 'bar') # => 1
186
- # counters.dig(:foo, :bar) # => 1
187
- # counters.dig(:zoo) # => nil
188
- def dig(*args)
189
- args[0] = convert_key(args[0]) if args.size > 0
190
- super(*args)
191
- end
197
+ # Same as <tt>Hash#dig</tt> where the key passed as argument can be
198
+ # either a string or a symbol:
199
+ #
200
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
201
+ # counters[:foo] = { bar: 1 }
202
+ #
203
+ # counters.dig('foo', 'bar') # => 1
204
+ # counters.dig(:foo, :bar) # => 1
205
+ # counters.dig(:zoo) # => nil
206
+ def dig(*args)
207
+ args[0] = convert_key(args[0]) if args.size > 0
208
+ super(*args)
192
209
  end
193
210
 
194
211
  # Same as <tt>Hash#default</tt> where the key passed as argument can be
@@ -211,8 +228,21 @@ module ActiveSupport
211
228
  # hash[:a] = 'x'
212
229
  # hash[:b] = 'y'
213
230
  # hash.values_at('a', 'b') # => ["x", "y"]
214
- def values_at(*indices)
215
- indices.collect { |key| self[convert_key(key)] }
231
+ def values_at(*keys)
232
+ super(*keys.map { |key| convert_key(key) })
233
+ end
234
+
235
+ # Returns an array of the values at the specified indices, but also
236
+ # raises an exception when one of the keys can't be found.
237
+ #
238
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
239
+ # hash[:a] = 'x'
240
+ # hash[:b] = 'y'
241
+ # hash.fetch_values('a', 'b') # => ["x", "y"]
242
+ # hash.fetch_values('a', 'c') { |key| 'z' } # => ["x", "z"]
243
+ # hash.fetch_values('a', 'c') # => KeyError: key not found: "c"
244
+ def fetch_values(*indices, &block)
245
+ super(*indices.map { |key| convert_key(key) }, &block)
216
246
  end
217
247
 
218
248
  # Returns a shallow copy of the hash.
@@ -232,8 +262,8 @@ module ActiveSupport
232
262
  # This method has the same semantics of +update+, except it does not
233
263
  # modify the receiver but rather returns a new hash with indifferent
234
264
  # access with the result of the merge.
235
- def merge(hash, &block)
236
- dup.update(hash, &block)
265
+ def merge(*hashes, &block)
266
+ dup.update(*hashes, &block)
237
267
  end
238
268
 
239
269
  # Like +merge+ but the other way around: Merges the receiver into the
@@ -245,11 +275,13 @@ module ActiveSupport
245
275
  def reverse_merge(other_hash)
246
276
  super(self.class.new(other_hash))
247
277
  end
278
+ alias_method :with_defaults, :reverse_merge
248
279
 
249
280
  # Same semantics as +reverse_merge+ but modifies the receiver in-place.
250
281
  def reverse_merge!(other_hash)
251
- replace(reverse_merge(other_hash))
282
+ super(self.class.new(other_hash))
252
283
  end
284
+ alias_method :with_defaults!, :reverse_merge!
253
285
 
254
286
  # Replaces the contents of this hash with other_hash.
255
287
  #
@@ -264,6 +296,15 @@ module ActiveSupport
264
296
  super(convert_key(key))
265
297
  end
266
298
 
299
+ # Returns a hash with indifferent access that includes everything except given keys.
300
+ # hash = { a: "x", b: "y", c: 10 }.with_indifferent_access
301
+ # hash.except(:a, "b") # => {c: 10}.with_indifferent_access
302
+ # hash # => { a: "x", b: "y", c: 10 }.with_indifferent_access
303
+ def except(*keys)
304
+ slice(*self.keys - keys.map { |key| convert_key(key) })
305
+ end
306
+ alias_method :without, :except
307
+
267
308
  def stringify_keys!; self end
268
309
  def deep_stringify_keys!; self end
269
310
  def stringify_keys; dup end
@@ -271,6 +312,7 @@ module ActiveSupport
271
312
  undef :symbolize_keys!
272
313
  undef :deep_symbolize_keys!
273
314
  def symbolize_keys; to_hash.symbolize_keys! end
315
+ alias_method :to_options, :symbolize_keys
274
316
  def deep_symbolize_keys; to_hash.deep_symbolize_keys! end
275
317
  def to_options!; self end
276
318
 
@@ -289,6 +331,29 @@ module ActiveSupport
289
331
  dup.tap { |hash| hash.transform_values!(*args, &block) }
290
332
  end
291
333
 
334
+ def transform_keys(*args, &block)
335
+ return to_enum(:transform_keys) unless block_given?
336
+ dup.tap { |hash| hash.transform_keys!(*args, &block) }
337
+ end
338
+
339
+ def transform_keys!
340
+ return enum_for(:transform_keys!) { size } unless block_given?
341
+ keys.each do |key|
342
+ self[yield(key)] = delete(key)
343
+ end
344
+ self
345
+ end
346
+
347
+ def slice(*keys)
348
+ keys.map! { |key| convert_key(key) }
349
+ self.class.new(super)
350
+ end
351
+
352
+ def slice!(*keys)
353
+ keys.map! { |key| convert_key(key) }
354
+ super
355
+ end
356
+
292
357
  def compact
293
358
  dup.tap(&:compact!)
294
359
  end
@@ -299,40 +364,59 @@ module ActiveSupport
299
364
  set_defaults(_new_hash)
300
365
 
301
366
  each do |key, value|
302
- _new_hash[key] = convert_value(value, for: :to_hash)
367
+ _new_hash[key] = convert_value(value, conversion: :to_hash)
303
368
  end
304
369
  _new_hash
305
370
  end
306
371
 
307
372
  private
308
- def convert_key(key) # :doc:
309
- key.kind_of?(Symbol) ? key.to_s : key
373
+ if Symbol.method_defined?(:name)
374
+ def convert_key(key)
375
+ key.kind_of?(Symbol) ? key.name : key
376
+ end
377
+ else
378
+ def convert_key(key)
379
+ key.kind_of?(Symbol) ? key.to_s : key
380
+ end
310
381
  end
311
382
 
312
- def convert_value(value, options = {}) # :doc:
383
+ def convert_value(value, conversion: nil)
313
384
  if value.is_a? Hash
314
- if options[:for] == :to_hash
385
+ if conversion == :to_hash
315
386
  value.to_hash
316
387
  else
317
388
  value.nested_under_indifferent_access
318
389
  end
319
390
  elsif value.is_a?(Array)
320
- if options[:for] != :assignment || value.frozen?
391
+ if conversion != :assignment || value.frozen?
321
392
  value = value.dup
322
393
  end
323
- value.map! { |e| convert_value(e, options) }
394
+ value.map! { |e| convert_value(e, conversion: conversion) }
324
395
  else
325
396
  value
326
397
  end
327
398
  end
328
399
 
329
- def set_defaults(target) # :doc:
400
+ def set_defaults(target)
330
401
  if default_proc
331
402
  target.default_proc = default_proc.dup
332
403
  else
333
404
  target.default = default
334
405
  end
335
406
  end
407
+
408
+ def update_with_single_argument(other_hash, block)
409
+ if other_hash.is_a? HashWithIndifferentAccess
410
+ regular_update(other_hash, &block)
411
+ else
412
+ other_hash.to_hash.each_pair do |key, value|
413
+ if block && key?(key)
414
+ value = block.call(convert_key(key), self[key], value)
415
+ end
416
+ regular_writer(convert_key(key), convert_value(value))
417
+ end
418
+ end
419
+ end
336
420
  end
337
421
  end
338
422
 
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module HtmlSafeTranslation # :nodoc:
5
+ extend self
6
+
7
+ def translate(key, **options)
8
+ if html_safe_translation_key?(key)
9
+ html_safe_options = html_escape_translation_options(options)
10
+ translation = I18n.translate(key, **html_safe_options)
11
+ html_safe_translation(translation)
12
+ else
13
+ I18n.translate(key, **options)
14
+ end
15
+ end
16
+
17
+ private
18
+ def html_safe_translation_key?(key)
19
+ /(?:_|\b)html\z/.match?(key)
20
+ end
21
+
22
+ def html_escape_translation_options(options)
23
+ options.each do |name, value|
24
+ unless i18n_option?(name) || (name == :count && value.is_a?(Numeric))
25
+ options[name] = ERB::Util.html_escape(value.to_s)
26
+ end
27
+ end
28
+ end
29
+
30
+ def i18n_option?(name)
31
+ (@i18n_option_names ||= I18n::RESERVED_KEYS.to_set).include?(name)
32
+ end
33
+
34
+
35
+ def html_safe_translation(translation)
36
+ if translation.respond_to?(:map)
37
+ translation.map { |element| element.respond_to?(:html_safe) ? element.html_safe : element }
38
+ else
39
+ translation.respond_to?(:html_safe) ? translation.html_safe : translation
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/hash/deep_merge"
2
4
  require "active_support/core_ext/hash/except"
3
5
  require "active_support/core_ext/hash/slice"
4
6
  begin
5
7
  require "i18n"
8
+ require "i18n/backend/fallbacks"
6
9
  rescue LoadError => e
7
10
  $stderr.puts "The i18n gem is not available. Please add it to your Gemfile and run bundle install"
8
11
  raise e
@@ -10,4 +13,5 @@ end
10
13
  require "active_support/lazy_load_hooks"
11
14
 
12
15
  ActiveSupport.run_load_hooks(:i18n)
13
- I18n.load_path << "#{File.dirname(__FILE__)}/locale/en.yml"
16
+ I18n.load_path << File.expand_path("locale/en.yml", __dir__)
17
+ I18n.load_path << File.expand_path("locale/en.rb", __dir__)
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support"
2
- require "active_support/file_update_checker"
3
4
  require "active_support/core_ext/array/wrap"
4
5
 
5
6
  # :enddoc:
@@ -11,6 +12,8 @@ module I18n
11
12
  config.i18n.load_path = []
12
13
  config.i18n.fallbacks = ActiveSupport::OrderedOptions.new
13
14
 
15
+ config.eager_load_namespaces << I18n
16
+
14
17
  # Set the i18n configuration after initialization since a lot of
15
18
  # configuration is still usually done in application initializers.
16
19
  config.after_initialize do |app|
@@ -42,11 +45,13 @@ module I18n
42
45
  case setting
43
46
  when :railties_load_path
44
47
  reloadable_paths = value
45
- app.config.i18n.load_path.unshift(*value.map(&:existent).flatten)
48
+ app.config.i18n.load_path.unshift(*value.flat_map(&:existent))
46
49
  when :load_path
47
50
  I18n.load_path += value
51
+ when :raise_on_missing_translations
52
+ forward_raise_on_missing_translations_config(app)
48
53
  else
49
- I18n.send("#{setting}=", value)
54
+ I18n.public_send("#{setting}=", value)
50
55
  end
51
56
  end
52
57
 
@@ -58,24 +63,28 @@ module I18n
58
63
  directories = watched_dirs_with_extensions(reloadable_paths)
59
64
  reloader = app.config.file_watcher.new(I18n.load_path.dup, directories) do
60
65
  I18n.load_path.keep_if { |p| File.exist?(p) }
61
- I18n.load_path |= reloadable_paths.map(&:existent).flatten
62
-
63
- I18n.reload!
66
+ I18n.load_path |= reloadable_paths.flat_map(&:existent)
64
67
  end
65
68
 
66
69
  app.reloaders << reloader
67
70
  app.reloader.to_run do
68
71
  reloader.execute_if_updated { require_unload_lock! }
69
- # TODO: remove the following line as soon as the return value of
70
- # callbacks is ignored, that is, returning `false` does not
71
- # display a deprecation warning or halts the callback chain.
72
- true
73
72
  end
74
73
  reloader.execute
75
74
 
76
75
  @i18n_inited = true
77
76
  end
78
77
 
78
+ def self.forward_raise_on_missing_translations_config(app)
79
+ ActiveSupport.on_load(:action_view) do
80
+ ActionView::Helpers::TranslationHelper.raise_on_missing_translations = app.config.i18n.raise_on_missing_translations
81
+ end
82
+
83
+ ActiveSupport.on_load(:action_controller) do
84
+ AbstractController::Translation.raise_on_missing_translations = app.config.i18n.raise_on_missing_translations
85
+ end
86
+ end
87
+
79
88
  def self.include_fallbacks_module
80
89
  I18n.backend.class.include(I18n::Backend::Fallbacks)
81
90
  end
@@ -93,10 +102,6 @@ module I18n
93
102
  [I18n.default_locale]
94
103
  end
95
104
 
96
- if args.empty? || args.first.is_a?(Hash)
97
- args.unshift I18n.default_locale
98
- end
99
-
100
105
  I18n.fallbacks = I18n::Locale::Fallbacks.new(*args)
101
106
  end
102
107
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/inflector/inflections"
2
4
 
3
5
  #--
@@ -1,6 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "concurrent/map"
2
- require "active_support/core_ext/array/prepend_and_append"
3
- require "active_support/core_ext/regexp"
4
4
  require "active_support/i18n"
5
5
 
6
6
  module ActiveSupport
@@ -16,13 +16,13 @@ module ActiveSupport
16
16
  # inflect.plural /^(ox)$/i, '\1\2en'
17
17
  # inflect.singular /^(ox)en/i, '\1'
18
18
  #
19
- # inflect.irregular 'octopus', 'octopi'
19
+ # inflect.irregular 'cactus', 'cacti'
20
20
  #
21
21
  # inflect.uncountable 'equipment'
22
22
  # end
23
23
  #
24
24
  # New rules are added at the top. So in the example above, the irregular
25
- # rule for octopus will now be the first of the pluralization and
25
+ # rule for cactus will now be the first of the pluralization and
26
26
  # singularization rules that is runs. This guarantees that your rules run
27
27
  # before any of the rules that may already have been loaded.
28
28
  class Inflections
@@ -64,17 +64,28 @@ module ActiveSupport
64
64
  @__instance__[locale] ||= new
65
65
  end
66
66
 
67
- attr_reader :plurals, :singulars, :uncountables, :humans, :acronyms, :acronym_regex
67
+ def self.instance_or_fallback(locale)
68
+ I18n.fallbacks[locale].each do |k|
69
+ return @__instance__[k] if @__instance__.key?(k)
70
+ end
71
+ instance(locale)
72
+ end
73
+
74
+ attr_reader :plurals, :singulars, :uncountables, :humans, :acronyms
75
+
76
+ attr_reader :acronyms_camelize_regex, :acronyms_underscore_regex # :nodoc:
68
77
 
69
78
  def initialize
70
- @plurals, @singulars, @uncountables, @humans, @acronyms, @acronym_regex = [], [], Uncountables.new, [], {}, /(?=a)b/
79
+ @plurals, @singulars, @uncountables, @humans, @acronyms = [], [], Uncountables.new, [], {}
80
+ define_acronym_regex_patterns
71
81
  end
72
82
 
73
83
  # Private, for the test suite.
74
84
  def initialize_dup(orig) # :nodoc:
75
- %w(plurals singulars uncountables humans acronyms acronym_regex).each do |scope|
76
- instance_variable_set("@#{scope}", orig.send(scope).dup)
85
+ %w(plurals singulars uncountables humans acronyms).each do |scope|
86
+ instance_variable_set("@#{scope}", orig.public_send(scope).dup)
77
87
  end
88
+ define_acronym_regex_patterns
78
89
  end
79
90
 
80
91
  # Specifies a new acronym. An acronym must be specified as it will appear
@@ -128,7 +139,7 @@ module ActiveSupport
128
139
  # camelize 'mcdonald' # => 'McDonald'
129
140
  def acronym(word)
130
141
  @acronyms[word.downcase] = word
131
- @acronym_regex = /#{@acronyms.values.join("|")}/
142
+ define_acronym_regex_patterns
132
143
  end
133
144
 
134
145
  # Specifies a new pluralization rule and its replacement. The rule can
@@ -156,7 +167,7 @@ module ActiveSupport
156
167
  # regular expressions. You simply pass the irregular in singular and
157
168
  # plural form.
158
169
  #
159
- # irregular 'octopus', 'octopi'
170
+ # irregular 'cactus', 'cacti'
160
171
  # irregular 'person', 'people'
161
172
  def irregular(singular, plural)
162
173
  @uncountables.delete(singular)
@@ -211,18 +222,34 @@ module ActiveSupport
211
222
  # Clears the loaded inflections within a given scope (default is
212
223
  # <tt>:all</tt>). Give the scope as a symbol of the inflection type, the
213
224
  # options are: <tt>:plurals</tt>, <tt>:singulars</tt>, <tt>:uncountables</tt>,
214
- # <tt>:humans</tt>.
225
+ # <tt>:humans</tt>, <tt>:acronyms</tt>.
215
226
  #
216
227
  # clear :all
217
228
  # clear :plurals
218
229
  def clear(scope = :all)
219
230
  case scope
220
231
  when :all
221
- @plurals, @singulars, @uncountables, @humans = [], [], Uncountables.new, []
222
- else
232
+ clear(:acronyms)
233
+ clear(:plurals)
234
+ clear(:singulars)
235
+ clear(:uncountables)
236
+ clear(:humans)
237
+ when :acronyms
238
+ @acronyms = {}
239
+ define_acronym_regex_patterns
240
+ when :uncountables
241
+ @uncountables = Uncountables.new
242
+ when :plurals, :singulars, :humans
223
243
  instance_variable_set "@#{scope}", []
224
244
  end
225
245
  end
246
+
247
+ private
248
+ def define_acronym_regex_patterns
249
+ @acronym_regex = @acronyms.empty? ? /(?=a)b/ : /#{@acronyms.values.join("|")}/
250
+ @acronyms_camelize_regex = /^(?:#{@acronym_regex}(?=\b|[A-Z_])|\w)/
251
+ @acronyms_underscore_regex = /(?:(?<=([A-Za-z\d]))|\b)(#{@acronym_regex})(?=\b|[^a-z])/
252
+ end
226
253
  end
227
254
 
228
255
  # Yields a singleton instance of Inflector::Inflections so you can specify
@@ -237,7 +264,7 @@ module ActiveSupport
237
264
  if block_given?
238
265
  yield Inflections.instance(locale)
239
266
  else
240
- Inflections.instance(locale)
267
+ Inflections.instance_or_fallback(locale)
241
268
  end
242
269
  end
243
270
  end