activesupport 5.1.6 → 5.2.0

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 (240) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +325 -576
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -3
  5. data/lib/active_support/all.rb +2 -0
  6. data/lib/active_support/array_inquirer.rb +2 -0
  7. data/lib/active_support/backtrace_cleaner.rb +2 -0
  8. data/lib/active_support/benchmarkable.rb +2 -0
  9. data/lib/active_support/builder.rb +2 -0
  10. data/lib/active_support/cache/file_store.rb +5 -4
  11. data/lib/active_support/cache/mem_cache_store.rb +37 -27
  12. data/lib/active_support/cache/memory_store.rb +2 -0
  13. data/lib/active_support/cache/null_store.rb +2 -0
  14. data/lib/active_support/cache/redis_cache_store.rb +454 -0
  15. data/lib/active_support/cache/strategy/local_cache.rb +33 -2
  16. data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
  17. data/lib/active_support/cache.rb +181 -64
  18. data/lib/active_support/callbacks.rb +28 -39
  19. data/lib/active_support/concern.rb +3 -1
  20. data/lib/active_support/concurrency/share_lock.rb +2 -0
  21. data/lib/active_support/configurable.rb +2 -0
  22. data/lib/active_support/core_ext/array/access.rb +4 -2
  23. data/lib/active_support/core_ext/array/conversions.rb +2 -0
  24. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  25. data/lib/active_support/core_ext/array/grouping.rb +2 -0
  26. data/lib/active_support/core_ext/array/inquiry.rb +2 -0
  27. data/lib/active_support/core_ext/array/prepend_and_append.rb +4 -2
  28. data/lib/active_support/core_ext/array/wrap.rb +2 -0
  29. data/lib/active_support/core_ext/array.rb +2 -0
  30. data/lib/active_support/core_ext/benchmark.rb +2 -0
  31. data/lib/active_support/core_ext/big_decimal/conversions.rb +2 -0
  32. data/lib/active_support/core_ext/big_decimal.rb +2 -0
  33. data/lib/active_support/core_ext/class/attribute.rb +34 -16
  34. data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
  35. data/lib/active_support/core_ext/class/subclasses.rb +1 -2
  36. data/lib/active_support/core_ext/class.rb +2 -0
  37. data/lib/active_support/core_ext/date/acts_like.rb +2 -0
  38. data/lib/active_support/core_ext/date/blank.rb +2 -0
  39. data/lib/active_support/core_ext/date/calculations.rb +2 -0
  40. data/lib/active_support/core_ext/date/conversions.rb +10 -9
  41. data/lib/active_support/core_ext/date/zones.rb +2 -0
  42. data/lib/active_support/core_ext/date.rb +2 -0
  43. data/lib/active_support/core_ext/date_and_time/calculations.rb +50 -16
  44. data/lib/active_support/core_ext/date_and_time/compatibility.rb +3 -1
  45. data/lib/active_support/core_ext/date_and_time/zones.rb +2 -0
  46. data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
  47. data/lib/active_support/core_ext/date_time/blank.rb +2 -0
  48. data/lib/active_support/core_ext/date_time/calculations.rb +2 -0
  49. data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
  50. data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
  51. data/lib/active_support/core_ext/date_time.rb +2 -0
  52. data/lib/active_support/core_ext/digest/uuid.rb +3 -1
  53. data/lib/active_support/core_ext/enumerable.rb +3 -1
  54. data/lib/active_support/core_ext/file/atomic.rb +2 -0
  55. data/lib/active_support/core_ext/file.rb +2 -0
  56. data/lib/active_support/core_ext/hash/compact.rb +2 -0
  57. data/lib/active_support/core_ext/hash/conversions.rb +4 -2
  58. data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
  59. data/lib/active_support/core_ext/hash/except.rb +2 -0
  60. data/lib/active_support/core_ext/hash/indifferent_access.rb +2 -0
  61. data/lib/active_support/core_ext/hash/keys.rb +2 -0
  62. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  63. data/lib/active_support/core_ext/hash/slice.rb +4 -4
  64. data/lib/active_support/core_ext/hash/transform_values.rb +2 -0
  65. data/lib/active_support/core_ext/hash.rb +2 -0
  66. data/lib/active_support/core_ext/integer/inflections.rb +2 -0
  67. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  68. data/lib/active_support/core_ext/integer/time.rb +7 -14
  69. data/lib/active_support/core_ext/integer.rb +2 -0
  70. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  71. data/lib/active_support/core_ext/kernel/concern.rb +2 -0
  72. data/lib/active_support/core_ext/kernel/reporting.rb +2 -0
  73. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  74. data/lib/active_support/core_ext/kernel.rb +2 -0
  75. data/lib/active_support/core_ext/load_error.rb +2 -7
  76. data/lib/active_support/core_ext/marshal.rb +2 -0
  77. data/lib/active_support/core_ext/module/aliasing.rb +2 -0
  78. data/lib/active_support/core_ext/module/anonymous.rb +2 -0
  79. data/lib/active_support/core_ext/module/attr_internal.rb +2 -0
  80. data/lib/active_support/core_ext/module/attribute_accessors.rb +21 -24
  81. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +2 -0
  82. data/lib/active_support/core_ext/module/concerning.rb +7 -8
  83. data/lib/active_support/core_ext/module/delegation.rb +31 -29
  84. data/lib/active_support/core_ext/module/deprecation.rb +2 -0
  85. data/lib/active_support/core_ext/module/introspection.rb +2 -0
  86. data/lib/active_support/core_ext/module/reachable.rb +3 -0
  87. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  88. data/lib/active_support/core_ext/module/remove_method.rb +5 -23
  89. data/lib/active_support/core_ext/module.rb +3 -0
  90. data/lib/active_support/core_ext/name_error.rb +7 -0
  91. data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
  92. data/lib/active_support/core_ext/numeric/conversions.rb +9 -7
  93. data/lib/active_support/core_ext/numeric/inquiry.rb +2 -0
  94. data/lib/active_support/core_ext/numeric/time.rb +7 -15
  95. data/lib/active_support/core_ext/numeric.rb +2 -0
  96. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  97. data/lib/active_support/core_ext/object/blank.rb +12 -1
  98. data/lib/active_support/core_ext/object/conversions.rb +2 -0
  99. data/lib/active_support/core_ext/object/deep_dup.rb +2 -0
  100. data/lib/active_support/core_ext/object/duplicable.rb +10 -8
  101. data/lib/active_support/core_ext/object/inclusion.rb +2 -0
  102. data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
  103. data/lib/active_support/core_ext/object/json.rb +8 -0
  104. data/lib/active_support/core_ext/object/to_param.rb +2 -0
  105. data/lib/active_support/core_ext/object/to_query.rb +2 -0
  106. data/lib/active_support/core_ext/object/try.rb +2 -0
  107. data/lib/active_support/core_ext/object/with_options.rb +3 -1
  108. data/lib/active_support/core_ext/object.rb +2 -0
  109. data/lib/active_support/core_ext/range/conversions.rb +9 -1
  110. data/lib/active_support/core_ext/range/each.rb +5 -1
  111. data/lib/active_support/core_ext/range/include_range.rb +2 -0
  112. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  113. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  114. data/lib/active_support/core_ext/range.rb +3 -0
  115. data/lib/active_support/core_ext/regexp.rb +2 -0
  116. data/lib/active_support/core_ext/securerandom.rb +2 -0
  117. data/lib/active_support/core_ext/string/access.rb +2 -0
  118. data/lib/active_support/core_ext/string/behavior.rb +2 -0
  119. data/lib/active_support/core_ext/string/conversions.rb +2 -0
  120. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  121. data/lib/active_support/core_ext/string/filters.rb +2 -0
  122. data/lib/active_support/core_ext/string/indent.rb +2 -0
  123. data/lib/active_support/core_ext/string/inflections.rb +26 -12
  124. data/lib/active_support/core_ext/string/inquiry.rb +2 -0
  125. data/lib/active_support/core_ext/string/multibyte.rb +4 -0
  126. data/lib/active_support/core_ext/string/output_safety.rb +6 -7
  127. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  128. data/lib/active_support/core_ext/string/strip.rb +2 -0
  129. data/lib/active_support/core_ext/string/zones.rb +2 -0
  130. data/lib/active_support/core_ext/string.rb +2 -0
  131. data/lib/active_support/core_ext/time/acts_like.rb +2 -0
  132. data/lib/active_support/core_ext/time/calculations.rb +23 -15
  133. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  134. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  135. data/lib/active_support/core_ext/time/zones.rb +6 -4
  136. data/lib/active_support/core_ext/time.rb +2 -0
  137. data/lib/active_support/core_ext/uri.rb +4 -1
  138. data/lib/active_support/core_ext.rb +3 -1
  139. data/lib/active_support/current_attributes.rb +195 -0
  140. data/lib/active_support/dependencies/autoload.rb +2 -0
  141. data/lib/active_support/dependencies/interlock.rb +2 -0
  142. data/lib/active_support/dependencies.rb +16 -25
  143. data/lib/active_support/deprecation/behaviors.rb +24 -9
  144. data/lib/active_support/deprecation/constant_accessor.rb +4 -2
  145. data/lib/active_support/deprecation/instance_delegator.rb +2 -0
  146. data/lib/active_support/deprecation/method_wrappers.rb +8 -8
  147. data/lib/active_support/deprecation/proxy_wrappers.rb +5 -2
  148. data/lib/active_support/deprecation/reporting.rb +5 -3
  149. data/lib/active_support/deprecation.rb +4 -2
  150. data/lib/active_support/descendants_tracker.rb +2 -0
  151. data/lib/active_support/digest.rb +20 -0
  152. data/lib/active_support/duration/iso8601_parser.rb +4 -2
  153. data/lib/active_support/duration/iso8601_serializer.rb +4 -2
  154. data/lib/active_support/duration.rb +11 -7
  155. data/lib/active_support/encrypted_configuration.rb +49 -0
  156. data/lib/active_support/encrypted_file.rb +99 -0
  157. data/lib/active_support/evented_file_update_checker.rb +2 -0
  158. data/lib/active_support/execution_wrapper.rb +2 -0
  159. data/lib/active_support/executor.rb +2 -0
  160. data/lib/active_support/file_update_checker.rb +2 -0
  161. data/lib/active_support/gem_version.rb +4 -2
  162. data/lib/active_support/gzip.rb +2 -0
  163. data/lib/active_support/hash_with_indifferent_access.rb +41 -1
  164. data/lib/active_support/i18n.rb +3 -1
  165. data/lib/active_support/i18n_railtie.rb +4 -6
  166. data/lib/active_support/inflections.rb +2 -0
  167. data/lib/active_support/inflector/inflections.rb +20 -4
  168. data/lib/active_support/inflector/methods.rb +41 -24
  169. data/lib/active_support/inflector/transliterate.rb +17 -8
  170. data/lib/active_support/inflector.rb +2 -0
  171. data/lib/active_support/json/decoding.rb +2 -0
  172. data/lib/active_support/json/encoding.rb +2 -0
  173. data/lib/active_support/json.rb +2 -0
  174. data/lib/active_support/key_generator.rb +3 -1
  175. data/lib/active_support/lazy_load_hooks.rb +2 -0
  176. data/lib/active_support/log_subscriber/test_helper.rb +2 -0
  177. data/lib/active_support/log_subscriber.rb +3 -2
  178. data/lib/active_support/logger.rb +2 -0
  179. data/lib/active_support/logger_silence.rb +3 -2
  180. data/lib/active_support/logger_thread_safe_level.rb +2 -0
  181. data/lib/active_support/message_encryptor.rb +95 -22
  182. data/lib/active_support/message_verifier.rb +78 -7
  183. data/lib/active_support/messages/metadata.rb +71 -0
  184. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  185. data/lib/active_support/messages/rotator.rb +56 -0
  186. data/lib/active_support/multibyte/chars.rb +2 -0
  187. data/lib/active_support/multibyte/unicode.rb +4 -2
  188. data/lib/active_support/multibyte.rb +2 -0
  189. data/lib/active_support/notifications/fanout.rb +2 -0
  190. data/lib/active_support/notifications/instrumenter.rb +2 -0
  191. data/lib/active_support/notifications.rb +2 -0
  192. data/lib/active_support/number_helper/number_converter.rb +2 -0
  193. data/lib/active_support/number_helper/number_to_currency_converter.rb +2 -0
  194. data/lib/active_support/number_helper/number_to_delimited_converter.rb +2 -0
  195. data/lib/active_support/number_helper/number_to_human_converter.rb +2 -0
  196. data/lib/active_support/number_helper/number_to_human_size_converter.rb +2 -0
  197. data/lib/active_support/number_helper/number_to_percentage_converter.rb +2 -0
  198. data/lib/active_support/number_helper/number_to_phone_converter.rb +3 -1
  199. data/lib/active_support/number_helper/number_to_rounded_converter.rb +2 -20
  200. data/lib/active_support/number_helper/rounding_helper.rb +6 -4
  201. data/lib/active_support/number_helper.rb +2 -0
  202. data/lib/active_support/option_merger.rb +2 -0
  203. data/lib/active_support/ordered_hash.rb +2 -0
  204. data/lib/active_support/ordered_options.rb +4 -2
  205. data/lib/active_support/per_thread_registry.rb +2 -0
  206. data/lib/active_support/proxy_object.rb +2 -0
  207. data/lib/active_support/rails.rb +2 -0
  208. data/lib/active_support/railtie.rb +37 -8
  209. data/lib/active_support/reloader.rb +7 -5
  210. data/lib/active_support/rescuable.rb +3 -2
  211. data/lib/active_support/security_utils.rb +15 -11
  212. data/lib/active_support/string_inquirer.rb +2 -0
  213. data/lib/active_support/subscriber.rb +2 -0
  214. data/lib/active_support/tagged_logging.rb +2 -0
  215. data/lib/active_support/test_case.rb +2 -1
  216. data/lib/active_support/testing/assertions.rb +31 -14
  217. data/lib/active_support/testing/autorun.rb +2 -0
  218. data/lib/active_support/testing/constant_lookup.rb +2 -0
  219. data/lib/active_support/testing/declarative.rb +2 -0
  220. data/lib/active_support/testing/deprecation.rb +2 -0
  221. data/lib/active_support/testing/file_fixtures.rb +2 -0
  222. data/lib/active_support/testing/isolation.rb +3 -1
  223. data/lib/active_support/testing/method_call_assertions.rb +2 -0
  224. data/lib/active_support/testing/setup_and_teardown.rb +10 -1
  225. data/lib/active_support/testing/stream.rb +2 -0
  226. data/lib/active_support/testing/tagged_logging.rb +2 -0
  227. data/lib/active_support/testing/time_helpers.rb +33 -3
  228. data/lib/active_support/time.rb +2 -0
  229. data/lib/active_support/time_with_zone.rb +38 -0
  230. data/lib/active_support/values/time_zone.rb +19 -8
  231. data/lib/active_support/version.rb +2 -0
  232. data/lib/active_support/xml_mini/jdom.rb +4 -2
  233. data/lib/active_support/xml_mini/libxml.rb +3 -1
  234. data/lib/active_support/xml_mini/libxmlsax.rb +4 -2
  235. data/lib/active_support/xml_mini/nokogiri.rb +3 -1
  236. data/lib/active_support/xml_mini/nokogirisax.rb +3 -1
  237. data/lib/active_support/xml_mini/rexml.rb +3 -1
  238. data/lib/active_support/xml_mini.rb +3 -1
  239. data/lib/active_support.rb +5 -13
  240. metadata +15 -5
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/array/conversions"
2
4
  require "active_support/core_ext/module/delegation"
3
5
  require "active_support/core_ext/object/acts_like"
@@ -131,7 +133,7 @@ module ActiveSupport
131
133
  class << self
132
134
  # Creates a new Duration from string formatted according to ISO 8601 Duration.
133
135
  #
134
- # See {ISO 8601}[http://en.wikipedia.org/wiki/ISO_8601#Durations] for more information.
136
+ # See {ISO 8601}[https://en.wikipedia.org/wiki/ISO_8601#Durations] for more information.
135
137
  # This method allows negative parts to be present in pattern.
136
138
  # If invalid string is provided, it will raise +ActiveSupport::Duration::ISO8601Parser::ParsingError+.
137
139
  def parse(iso8601duration)
@@ -192,7 +194,6 @@ module ActiveSupport
192
194
  end
193
195
 
194
196
  parts[:seconds] = remainder
195
- parts.reject! { |k, v| v.zero? }
196
197
 
197
198
  new(value, parts)
198
199
  end
@@ -209,6 +210,7 @@ module ActiveSupport
209
210
  def initialize(value, parts) #:nodoc:
210
211
  @value, @parts = value, parts.to_h
211
212
  @parts.default = 0
213
+ @parts.reject! { |k, v| v.zero? }
212
214
  end
213
215
 
214
216
  def coerce(other) #:nodoc:
@@ -368,6 +370,8 @@ module ActiveSupport
368
370
  alias :before :ago
369
371
 
370
372
  def inspect #:nodoc:
373
+ return "0 seconds" if parts.empty?
374
+
371
375
  parts.
372
376
  reduce(::Hash.new(0)) { |h, (l, r)| h[l] += r; h }.
373
377
  sort_by { |unit, _ | PARTS.index(unit) }.
@@ -379,10 +383,6 @@ module ActiveSupport
379
383
  to_i
380
384
  end
381
385
 
382
- def respond_to_missing?(method, include_private = false) #:nodoc:
383
- @value.respond_to?(method, include_private)
384
- end
385
-
386
386
  def init_with(coder) #:nodoc:
387
387
  initialize(coder["value"], coder["parts"])
388
388
  end
@@ -417,8 +417,12 @@ module ActiveSupport
417
417
  end
418
418
  end
419
419
 
420
+ def respond_to_missing?(method, _)
421
+ value.respond_to?(method)
422
+ end
423
+
420
424
  def method_missing(method, *args, &block)
421
- value.send(method, *args, &block)
425
+ value.public_send(method, *args, &block)
422
426
  end
423
427
 
424
428
  def raise_type_error(other)
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+ require "active_support/encrypted_file"
5
+ require "active_support/ordered_options"
6
+ require "active_support/core_ext/object/inclusion"
7
+ require "active_support/core_ext/module/delegation"
8
+
9
+ module ActiveSupport
10
+ class EncryptedConfiguration < EncryptedFile
11
+ delegate :[], :fetch, to: :config
12
+ delegate_missing_to :options
13
+
14
+ def initialize(config_path:, key_path:, env_key:, raise_if_missing_key:)
15
+ super content_path: config_path, key_path: key_path,
16
+ env_key: env_key, raise_if_missing_key: raise_if_missing_key
17
+ end
18
+
19
+ # Allow a config to be started without a file present
20
+ def read
21
+ super
22
+ rescue ActiveSupport::EncryptedFile::MissingContentError
23
+ ""
24
+ end
25
+
26
+ def write(contents)
27
+ deserialize(contents)
28
+
29
+ super
30
+ end
31
+
32
+ def config
33
+ @config ||= deserialize(read).deep_symbolize_keys
34
+ end
35
+
36
+ private
37
+ def options
38
+ @options ||= ActiveSupport::InheritableOptions.new(config)
39
+ end
40
+
41
+ def serialize(config)
42
+ config.present? ? YAML.dump(config) : ""
43
+ end
44
+
45
+ def deserialize(config)
46
+ config.present? ? YAML.load(config, content_path) : {}
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+ require "active_support/message_encryptor"
5
+
6
+ module ActiveSupport
7
+ class EncryptedFile
8
+ class MissingContentError < RuntimeError
9
+ def initialize(content_path)
10
+ super "Missing encrypted content file in #{content_path}."
11
+ end
12
+ end
13
+
14
+ class MissingKeyError < RuntimeError
15
+ def initialize(key_path:, env_key:)
16
+ super \
17
+ "Missing encryption key to decrypt file with. " +
18
+ "Ask your team for your master key and write it to #{key_path} or put it in the ENV['#{env_key}']."
19
+ end
20
+ end
21
+
22
+ CIPHER = "aes-128-gcm"
23
+
24
+ def self.generate_key
25
+ SecureRandom.hex(ActiveSupport::MessageEncryptor.key_len(CIPHER))
26
+ end
27
+
28
+
29
+ attr_reader :content_path, :key_path, :env_key, :raise_if_missing_key
30
+
31
+ def initialize(content_path:, key_path:, env_key:, raise_if_missing_key:)
32
+ @content_path, @key_path = Pathname.new(content_path), Pathname.new(key_path)
33
+ @env_key, @raise_if_missing_key = env_key, raise_if_missing_key
34
+ end
35
+
36
+ def key
37
+ read_env_key || read_key_file || handle_missing_key
38
+ end
39
+
40
+ def read
41
+ if !key.nil? && content_path.exist?
42
+ decrypt content_path.binread
43
+ else
44
+ raise MissingContentError, content_path
45
+ end
46
+ end
47
+
48
+ def write(contents)
49
+ IO.binwrite "#{content_path}.tmp", encrypt(contents)
50
+ FileUtils.mv "#{content_path}.tmp", content_path
51
+ end
52
+
53
+ def change(&block)
54
+ writing read, &block
55
+ end
56
+
57
+
58
+ private
59
+ def writing(contents)
60
+ tmp_file = "#{content_path.basename}.#{Process.pid}"
61
+ tmp_path = Pathname.new File.join(Dir.tmpdir, tmp_file)
62
+ tmp_path.binwrite contents
63
+
64
+ yield tmp_path
65
+
66
+ updated_contents = tmp_path.binread
67
+
68
+ write(updated_contents) if updated_contents != contents
69
+ ensure
70
+ FileUtils.rm(tmp_path) if tmp_path.exist?
71
+ end
72
+
73
+
74
+ def encrypt(contents)
75
+ encryptor.encrypt_and_sign contents
76
+ end
77
+
78
+ def decrypt(contents)
79
+ encryptor.decrypt_and_verify contents
80
+ end
81
+
82
+ def encryptor
83
+ @encryptor ||= ActiveSupport::MessageEncryptor.new([ key ].pack("H*"), cipher: CIPHER)
84
+ end
85
+
86
+
87
+ def read_env_key
88
+ ENV[env_key]
89
+ end
90
+
91
+ def read_key_file
92
+ key_path.binread.strip if key_path.exist?
93
+ end
94
+
95
+ def handle_missing_key
96
+ raise MissingKeyError, key_path: key_path, env_key: env_key if raise_if_missing_key
97
+ end
98
+ end
99
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "set"
2
4
  require "pathname"
3
5
  require "concurrent/atomic/atomic_boolean"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/callbacks"
2
4
 
3
5
  module ActiveSupport
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/execution_wrapper"
2
4
 
3
5
  module ActiveSupport
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/time/calculations"
2
4
 
3
5
  module ActiveSupport
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  # Returns the version of the currently loaded Active Support as a <tt>Gem::Version</tt>.
3
5
  def self.gem_version
@@ -6,8 +8,8 @@ module ActiveSupport
6
8
 
7
9
  module VERSION
8
10
  MAJOR = 5
9
- MINOR = 1
10
- TINY = 6
11
+ MINOR = 2
12
+ TINY = 0
11
13
  PRE = nil
12
14
 
13
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "zlib"
2
4
  require "stringio"
3
5
 
@@ -1,3 +1,5 @@
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"
3
5
 
@@ -215,6 +217,19 @@ module ActiveSupport
215
217
  indices.collect { |key| self[convert_key(key)] }
216
218
  end
217
219
 
220
+ # Returns an array of the values at the specified indices, but also
221
+ # raises an exception when one of the keys can't be found.
222
+ #
223
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
224
+ # hash[:a] = 'x'
225
+ # hash[:b] = 'y'
226
+ # hash.fetch_values('a', 'b') # => ["x", "y"]
227
+ # hash.fetch_values('a', 'c') { |key| 'z' } # => ["x", "z"]
228
+ # hash.fetch_values('a', 'c') # => KeyError: key not found: "c"
229
+ def fetch_values(*indices, &block)
230
+ indices.collect { |key| fetch(key, &block) }
231
+ end if Hash.method_defined?(:fetch_values)
232
+
218
233
  # Returns a shallow copy of the hash.
219
234
  #
220
235
  # hash = ActiveSupport::HashWithIndifferentAccess.new({ a: { b: 'b' } })
@@ -245,11 +260,13 @@ module ActiveSupport
245
260
  def reverse_merge(other_hash)
246
261
  super(self.class.new(other_hash))
247
262
  end
263
+ alias_method :with_defaults, :reverse_merge
248
264
 
249
265
  # Same semantics as +reverse_merge+ but modifies the receiver in-place.
250
266
  def reverse_merge!(other_hash)
251
- replace(reverse_merge(other_hash))
267
+ super(self.class.new(other_hash))
252
268
  end
269
+ alias_method :with_defaults!, :reverse_merge!
253
270
 
254
271
  # Replaces the contents of this hash with other_hash.
255
272
  #
@@ -289,6 +306,29 @@ module ActiveSupport
289
306
  dup.tap { |hash| hash.transform_values!(*args, &block) }
290
307
  end
291
308
 
309
+ def transform_keys(*args, &block)
310
+ return to_enum(:transform_keys) unless block_given?
311
+ dup.tap { |hash| hash.transform_keys!(*args, &block) }
312
+ end
313
+
314
+ def transform_keys!
315
+ return enum_for(:transform_keys!) { size } unless block_given?
316
+ keys.each do |key|
317
+ self[yield(key)] = delete(key)
318
+ end
319
+ self
320
+ end
321
+
322
+ def slice(*keys)
323
+ keys.map! { |key| convert_key(key) }
324
+ self.class.new(super)
325
+ end
326
+
327
+ def slice!(*keys)
328
+ keys.map! { |key| convert_key(key) }
329
+ super
330
+ end
331
+
292
332
  def compact
293
333
  dup.tap(&:compact!)
294
334
  end
@@ -1,3 +1,5 @@
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"
@@ -10,4 +12,4 @@ end
10
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,3 +1,5 @@
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"
@@ -42,7 +44,7 @@ module I18n
42
44
  case setting
43
45
  when :railties_load_path
44
46
  reloadable_paths = value
45
- app.config.i18n.load_path.unshift(*value.map(&:existent).flatten)
47
+ app.config.i18n.load_path.unshift(*value.flat_map(&:existent))
46
48
  when :load_path
47
49
  I18n.load_path += value
48
50
  else
@@ -58,7 +60,7 @@ module I18n
58
60
  directories = watched_dirs_with_extensions(reloadable_paths)
59
61
  reloader = app.config.file_watcher.new(I18n.load_path.dup, directories) do
60
62
  I18n.load_path.keep_if { |p| File.exist?(p) }
61
- I18n.load_path |= reloadable_paths.map(&:existent).flatten
63
+ I18n.load_path |= reloadable_paths.flat_map(&:existent)
62
64
 
63
65
  I18n.reload!
64
66
  end
@@ -66,10 +68,6 @@ module I18n
66
68
  app.reloaders << reloader
67
69
  app.reloader.to_run do
68
70
  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
71
  end
74
72
  reloader.execute
75
73
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/inflector/inflections"
2
4
 
3
5
  #--
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "concurrent/map"
2
4
  require "active_support/core_ext/array/prepend_and_append"
3
5
  require "active_support/core_ext/regexp"
4
6
  require "active_support/i18n"
7
+ require "active_support/deprecation"
5
8
 
6
9
  module ActiveSupport
7
10
  module Inflector
@@ -65,16 +68,21 @@ module ActiveSupport
65
68
  end
66
69
 
67
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:
68
74
 
69
75
  def initialize
70
- @plurals, @singulars, @uncountables, @humans, @acronyms, @acronym_regex = [], [], Uncountables.new, [], {}, /(?=a)b/
76
+ @plurals, @singulars, @uncountables, @humans, @acronyms = [], [], Uncountables.new, [], {}
77
+ define_acronym_regex_patterns
71
78
  end
72
79
 
73
80
  # Private, for the test suite.
74
81
  def initialize_dup(orig) # :nodoc:
75
- %w(plurals singulars uncountables humans acronyms acronym_regex).each do |scope|
82
+ %w(plurals singulars uncountables humans acronyms).each do |scope|
76
83
  instance_variable_set("@#{scope}", orig.send(scope).dup)
77
84
  end
85
+ define_acronym_regex_patterns
78
86
  end
79
87
 
80
88
  # Specifies a new acronym. An acronym must be specified as it will appear
@@ -128,7 +136,7 @@ module ActiveSupport
128
136
  # camelize 'mcdonald' # => 'McDonald'
129
137
  def acronym(word)
130
138
  @acronyms[word.downcase] = word
131
- @acronym_regex = /#{@acronyms.values.join("|")}/
139
+ define_acronym_regex_patterns
132
140
  end
133
141
 
134
142
  # Specifies a new pluralization rule and its replacement. The rule can
@@ -219,10 +227,18 @@ module ActiveSupport
219
227
  case scope
220
228
  when :all
221
229
  @plurals, @singulars, @uncountables, @humans = [], [], Uncountables.new, []
222
- else
230
+ else
223
231
  instance_variable_set "@#{scope}", []
224
232
  end
225
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
226
242
  end
227
243
 
228
244
  # Yields a singleton instance of Inflector::Inflections so you can specify
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/inflections"
2
4
  require "active_support/core_ext/regexp"
3
5
 
@@ -28,7 +30,7 @@ module ActiveSupport
28
30
  # pluralize('CamelOctopus') # => "CamelOctopi"
29
31
  # pluralize('ley', :es) # => "leyes"
30
32
  def pluralize(word, locale = :en)
31
- apply_inflections(word, inflections(locale).plurals)
33
+ apply_inflections(word, inflections(locale).plurals, locale)
32
34
  end
33
35
 
34
36
  # The reverse of #pluralize, returns the singular form of a word in a
@@ -45,7 +47,7 @@ module ActiveSupport
45
47
  # singularize('CamelOctopi') # => "CamelOctopus"
46
48
  # singularize('leyes', :es) # => "ley"
47
49
  def singularize(word, locale = :en)
48
- apply_inflections(word, inflections(locale).singulars)
50
+ apply_inflections(word, inflections(locale).singulars, locale)
49
51
  end
50
52
 
51
53
  # Converts strings to UpperCamelCase.
@@ -69,7 +71,7 @@ module ActiveSupport
69
71
  if uppercase_first_letter
70
72
  string = string.sub(/^[a-z\d]*/) { |match| inflections.acronyms[match] || match.capitalize }
71
73
  else
72
- string = string.sub(/^(?:#{inflections.acronym_regex}(?=\b|[A-Z_])|\w)/) { |match| match.downcase }
74
+ string = string.sub(inflections.acronyms_camelize_regex) { |match| match.downcase }
73
75
  end
74
76
  string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{inflections.acronyms[$2] || $2.capitalize}" }
75
77
  string.gsub!("/".freeze, "::".freeze)
@@ -90,7 +92,7 @@ module ActiveSupport
90
92
  def underscore(camel_cased_word)
91
93
  return camel_cased_word unless /[A-Z-]|::/.match?(camel_cased_word)
92
94
  word = camel_cased_word.to_s.gsub("::".freeze, "/".freeze)
93
- word.gsub!(/(?:(?<=([A-Za-z\d]))|\b)(#{inflections.acronym_regex})(?=\b|[^a-z])/) { "#{$1 && '_'.freeze }#{$2.downcase}" }
95
+ word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_'.freeze }#{$2.downcase}" }
94
96
  word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2'.freeze)
95
97
  word.gsub!(/([a-z\d])([A-Z])/, '\1_\2'.freeze)
96
98
  word.tr!("-".freeze, "_".freeze)
@@ -108,33 +110,38 @@ module ActiveSupport
108
110
  # * Replaces underscores with spaces, if any.
109
111
  # * Downcases all words except acronyms.
110
112
  # * Capitalizes the first word.
111
- #
112
113
  # The capitalization of the first word can be turned off by setting the
113
114
  # +:capitalize+ option to false (default is true).
114
115
  #
115
- # humanize('employee_salary') # => "Employee salary"
116
- # humanize('author_id') # => "Author"
117
- # humanize('author_id', capitalize: false) # => "author"
118
- # humanize('_id') # => "Id"
116
+ # The trailing '_id' can be kept and capitalized by setting the
117
+ # optional parameter +keep_id_suffix+ to true (default is false).
118
+ #
119
+ # humanize('employee_salary') # => "Employee salary"
120
+ # humanize('author_id') # => "Author"
121
+ # humanize('author_id', capitalize: false) # => "author"
122
+ # humanize('_id') # => "Id"
123
+ # humanize('author_id', keep_id_suffix: true) # => "Author Id"
119
124
  #
120
125
  # If "SSL" was defined to be an acronym:
121
126
  #
122
127
  # humanize('ssl_error') # => "SSL error"
123
128
  #
124
- def humanize(lower_case_and_underscored_word, options = {})
129
+ def humanize(lower_case_and_underscored_word, capitalize: true, keep_id_suffix: false)
125
130
  result = lower_case_and_underscored_word.to_s.dup
126
131
 
127
132
  inflections.humans.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
128
133
 
129
134
  result.sub!(/\A_+/, "".freeze)
130
- result.sub!(/_id\z/, "".freeze)
135
+ unless keep_id_suffix
136
+ result.sub!(/_id\z/, "".freeze)
137
+ end
131
138
  result.tr!("_".freeze, " ".freeze)
132
139
 
133
140
  result.gsub!(/([a-z\d]*)/i) do |match|
134
- "#{inflections.acronyms[match] || match.downcase}"
141
+ "#{inflections.acronyms[match.downcase] || match.downcase}"
135
142
  end
136
143
 
137
- if options.fetch(:capitalize, true)
144
+ if capitalize
138
145
  result.sub!(/\A\w/) { |match| match.upcase }
139
146
  end
140
147
 
@@ -154,14 +161,21 @@ module ActiveSupport
154
161
  # create a nicer looking title. +titleize+ is meant for creating pretty
155
162
  # output. It is not used in the Rails internals.
156
163
  #
164
+ # The trailing '_id','Id'.. can be kept and capitalized by setting the
165
+ # optional parameter +keep_id_suffix+ to true.
166
+ # By default, this parameter is false.
167
+ #
157
168
  # +titleize+ is also aliased as +titlecase+.
158
169
  #
159
- # titleize('man from the boondocks') # => "Man From The Boondocks"
160
- # titleize('x-men: the last stand') # => "X Men: The Last Stand"
161
- # titleize('TheManWithoutAPast') # => "The Man Without A Past"
162
- # titleize('raiders_of_the_lost_ark') # => "Raiders Of The Lost Ark"
163
- def titleize(word)
164
- humanize(underscore(word)).gsub(/\b(?<!\w['’`])[a-z]/) { |match| match.capitalize }
170
+ # titleize('man from the boondocks') # => "Man From The Boondocks"
171
+ # titleize('x-men: the last stand') # => "X Men: The Last Stand"
172
+ # titleize('TheManWithoutAPast') # => "The Man Without A Past"
173
+ # titleize('raiders_of_the_lost_ark') # => "Raiders Of The Lost Ark"
174
+ # titleize('string_ending_with_id', keep_id_suffix: true) # => "String Ending With Id"
175
+ def titleize(word, keep_id_suffix: false)
176
+ humanize(underscore(word), keep_id_suffix: keep_id_suffix).gsub(/\b(?<!\w['’`])[a-z]/) do |match|
177
+ match.capitalize
178
+ end
165
179
  end
166
180
 
167
181
  # Creates the name of a table like Rails does for models to table names.
@@ -336,7 +350,7 @@ module ActiveSupport
336
350
  when 1; "st"
337
351
  when 2; "nd"
338
352
  when 3; "rd"
339
- else "th"
353
+ else "th"
340
354
  end
341
355
  end
342
356
  end
@@ -375,12 +389,15 @@ module ActiveSupport
375
389
 
376
390
  # Applies inflection rules for +singularize+ and +pluralize+.
377
391
  #
378
- # apply_inflections('post', inflections.plurals) # => "posts"
379
- # apply_inflections('posts', inflections.singulars) # => "post"
380
- def apply_inflections(word, rules)
392
+ # If passed an optional +locale+ parameter, the uncountables will be
393
+ # found for that locale.
394
+ #
395
+ # apply_inflections('post', inflections.plurals, :en) # => "posts"
396
+ # apply_inflections('posts', inflections.singulars, :en) # => "post"
397
+ def apply_inflections(word, rules, locale = :en)
381
398
  result = word.to_s.dup
382
399
 
383
- if word.empty? || inflections.uncountables.uncountable?(result)
400
+ if word.empty? || inflections(locale).uncountables.uncountable?(result)
384
401
  result
385
402
  else
386
403
  rules.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/string/multibyte"
2
4
  require "active_support/i18n"
3
5
 
@@ -59,26 +61,33 @@ module ActiveSupport
59
61
  def transliterate(string, replacement = "?".freeze)
60
62
  raise ArgumentError, "Can only transliterate strings. Received #{string.class.name}" unless string.is_a?(String)
61
63
 
62
- I18n.transliterate(ActiveSupport::Multibyte::Unicode.normalize(
63
- ActiveSupport::Multibyte::Unicode.tidy_bytes(string), :c),
64
- replacement: replacement)
64
+ I18n.transliterate(
65
+ ActiveSupport::Multibyte::Unicode.normalize(
66
+ ActiveSupport::Multibyte::Unicode.tidy_bytes(string), :c),
67
+ replacement: replacement)
65
68
  end
66
69
 
67
70
  # Replaces special characters in a string so that it may be used as part of
68
71
  # a 'pretty' URL.
69
72
  #
70
73
  # parameterize("Donald E. Knuth") # => "donald-e-knuth"
71
- # parameterize("^trés|Jolie-- ") # => "tres-jolie"
74
+ # parameterize("^très|Jolie-- ") # => "tres-jolie"
72
75
  #
73
- # To use a custom separator, override the `separator` argument.
76
+ # To use a custom separator, override the +separator+ argument.
74
77
  #
75
78
  # parameterize("Donald E. Knuth", separator: '_') # => "donald_e_knuth"
76
- # parameterize("^trés|Jolie-- ", separator: '_') # => "tres_jolie"
79
+ # parameterize("^très|Jolie__ ", separator: '_') # => "tres_jolie"
77
80
  #
78
- # To preserve the case of the characters in a string, use the `preserve_case` argument.
81
+ # To preserve the case of the characters in a string, use the +preserve_case+ argument.
79
82
  #
80
83
  # parameterize("Donald E. Knuth", preserve_case: true) # => "Donald-E-Knuth"
81
- # parameterize("^trés|Jolie-- ", preserve_case: true) # => "tres-Jolie"
84
+ # parameterize("^très|Jolie-- ", preserve_case: true) # => "tres-Jolie"
85
+ #
86
+ # It preserves dashes and underscores unless they are used as separators:
87
+ #
88
+ # parameterize("^très|Jolie__ ") # => "tres-jolie__"
89
+ # parameterize("^très|Jolie-- ", separator: "_") # => "tres_jolie--"
90
+ # parameterize("^très_Jolie-- ", separator: ".") # => "tres_jolie--"
82
91
  #
83
92
  def parameterize(string, separator: "-", preserve_case: false)
84
93
  # Replace accented chars with their ASCII equivalents.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # in case active_support/inflector is required without the rest of active_support
2
4
  require "active_support/inflector/inflections"
3
5
  require "active_support/inflector/transliterate"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/module/attribute_accessors"
2
4
  require "active_support/core_ext/module/delegation"
3
5
  require "json"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/object/json"
2
4
  require "active_support/core_ext/module/delegation"
3
5
 
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/json/decoding"
2
4
  require "active_support/json/encoding"