activesupport 4.2.0 → 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 (254) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +366 -232
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +4 -5
  5. data/lib/active_support.rb +17 -7
  6. data/lib/active_support/all.rb +5 -3
  7. data/lib/active_support/array_inquirer.rb +48 -0
  8. data/lib/active_support/backtrace_cleaner.rb +7 -5
  9. data/lib/active_support/benchmarkable.rb +6 -4
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache.rb +271 -177
  12. data/lib/active_support/cache/file_store.rb +41 -35
  13. data/lib/active_support/cache/mem_cache_store.rb +97 -88
  14. data/lib/active_support/cache/memory_store.rb +27 -30
  15. data/lib/active_support/cache/null_store.rb +7 -8
  16. data/lib/active_support/cache/redis_cache_store.rb +454 -0
  17. data/lib/active_support/cache/strategy/local_cache.rb +67 -34
  18. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  19. data/lib/active_support/callbacks.rb +654 -560
  20. data/lib/active_support/concern.rb +5 -3
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
  22. data/lib/active_support/concurrency/share_lock.rb +227 -0
  23. data/lib/active_support/configurable.rb +8 -5
  24. data/lib/active_support/core_ext.rb +3 -1
  25. data/lib/active_support/core_ext/array.rb +9 -6
  26. data/lib/active_support/core_ext/array/access.rb +29 -1
  27. data/lib/active_support/core_ext/array/conversions.rb +22 -18
  28. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  29. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  30. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  31. data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
  32. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  33. data/lib/active_support/core_ext/benchmark.rb +3 -1
  34. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  35. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  36. data/lib/active_support/core_ext/class.rb +4 -3
  37. data/lib/active_support/core_ext/class/attribute.rb +41 -22
  38. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  39. data/lib/active_support/core_ext/class/subclasses.rb +20 -8
  40. data/lib/active_support/core_ext/date.rb +6 -4
  41. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  42. data/lib/active_support/core_ext/date/blank.rb +14 -0
  43. data/lib/active_support/core_ext/date/calculations.rb +11 -9
  44. data/lib/active_support/core_ext/date/conversions.rb +31 -23
  45. data/lib/active_support/core_ext/date/zones.rb +4 -2
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +179 -56
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +16 -0
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
  49. data/lib/active_support/core_ext/date_time.rb +7 -4
  50. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  51. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  52. data/lib/active_support/core_ext/date_time/calculations.rb +58 -20
  53. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  54. data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
  55. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  56. data/lib/active_support/core_ext/enumerable.rb +107 -28
  57. data/lib/active_support/core_ext/file.rb +3 -1
  58. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  59. data/lib/active_support/core_ext/hash.rb +11 -9
  60. data/lib/active_support/core_ext/hash/compact.rb +24 -15
  61. data/lib/active_support/core_ext/hash/conversions.rb +63 -43
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  63. data/lib/active_support/core_ext/hash/except.rb +11 -8
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  65. data/lib/active_support/core_ext/hash/keys.rb +33 -27
  66. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  67. data/lib/active_support/core_ext/hash/slice.rb +8 -8
  68. data/lib/active_support/core_ext/hash/transform_values.rb +16 -7
  69. data/lib/active_support/core_ext/integer.rb +5 -3
  70. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  71. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  72. data/lib/active_support/core_ext/integer/time.rb +11 -33
  73. data/lib/active_support/core_ext/kernel.rb +6 -5
  74. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  75. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  76. data/lib/active_support/core_ext/kernel/reporting.rb +4 -83
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  78. data/lib/active_support/core_ext/load_error.rb +3 -22
  79. data/lib/active_support/core_ext/marshal.rb +13 -10
  80. data/lib/active_support/core_ext/module.rb +14 -11
  81. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  82. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  83. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  87. data/lib/active_support/core_ext/module/delegation.rb +121 -39
  88. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  89. data/lib/active_support/core_ext/module/introspection.rb +9 -9
  90. data/lib/active_support/core_ext/module/reachable.rb +5 -2
  91. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/name_error.rb +22 -2
  94. data/lib/active_support/core_ext/numeric.rb +6 -3
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +79 -74
  97. data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +35 -38
  99. data/lib/active_support/core_ext/object.rb +14 -13
  100. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  101. data/lib/active_support/core_ext/object/blank.rb +29 -4
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  104. data/lib/active_support/core_ext/object/duplicable.rb +98 -45
  105. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +49 -19
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +6 -4
  110. data/lib/active_support/core_ext/object/try.rb +70 -22
  111. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  112. data/lib/active_support/core_ext/range.rb +7 -4
  113. data/lib/active_support/core_ext/range/conversions.rb +27 -7
  114. data/lib/active_support/core_ext/range/each.rb +19 -17
  115. data/lib/active_support/core_ext/range/include_range.rb +21 -19
  116. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  117. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  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.rb +15 -13
  121. data/lib/active_support/core_ext/string/access.rb +9 -7
  122. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  123. data/lib/active_support/core_ext/string/conversions.rb +8 -5
  124. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  125. data/lib/active_support/core_ext/string/filters.rb +10 -8
  126. data/lib/active_support/core_ext/string/indent.rb +6 -4
  127. data/lib/active_support/core_ext/string/inflections.rb +61 -24
  128. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  129. data/lib/active_support/core_ext/string/multibyte.rb +15 -7
  130. data/lib/active_support/core_ext/string/output_safety.rb +35 -35
  131. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  132. data/lib/active_support/core_ext/string/strip.rb +4 -5
  133. data/lib/active_support/core_ext/string/zones.rb +4 -2
  134. data/lib/active_support/core_ext/time.rb +7 -5
  135. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  136. data/lib/active_support/core_ext/time/calculations.rb +101 -51
  137. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  138. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  139. data/lib/active_support/core_ext/time/zones.rb +41 -7
  140. data/lib/active_support/core_ext/uri.rb +5 -4
  141. data/lib/active_support/current_attributes.rb +195 -0
  142. data/lib/active_support/dependencies.rb +143 -160
  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/deprecation.rb +12 -9
  146. data/lib/active_support/deprecation/behaviors.rb +41 -12
  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 +54 -21
  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/descendants_tracker.rb +2 -0
  153. data/lib/active_support/digest.rb +20 -0
  154. data/lib/active_support/duration.rb +326 -30
  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/encrypted_configuration.rb +49 -0
  158. data/lib/active_support/encrypted_file.rb +99 -0
  159. data/lib/active_support/evented_file_update_checker.rb +205 -0
  160. data/lib/active_support/execution_wrapper.rb +128 -0
  161. data/lib/active_support/executor.rb +8 -0
  162. data/lib/active_support/file_update_checker.rb +63 -37
  163. data/lib/active_support/gem_version.rb +4 -2
  164. data/lib/active_support/gzip.rb +7 -5
  165. data/lib/active_support/hash_with_indifferent_access.rb +130 -30
  166. data/lib/active_support/i18n.rb +8 -6
  167. data/lib/active_support/i18n_railtie.rb +34 -14
  168. data/lib/active_support/inflections.rb +13 -11
  169. data/lib/active_support/inflector.rb +7 -5
  170. data/lib/active_support/inflector/inflections.rb +61 -12
  171. data/lib/active_support/inflector/methods.rb +161 -136
  172. data/lib/active_support/inflector/transliterate.rb +48 -27
  173. data/lib/active_support/json.rb +4 -2
  174. data/lib/active_support/json/decoding.rb +16 -13
  175. data/lib/active_support/json/encoding.rb +15 -57
  176. data/lib/active_support/key_generator.rb +25 -25
  177. data/lib/active_support/lazy_load_hooks.rb +50 -20
  178. data/lib/active_support/locale/en.yml +2 -0
  179. data/lib/active_support/log_subscriber.rb +13 -10
  180. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  181. data/lib/active_support/logger.rb +54 -3
  182. data/lib/active_support/logger_silence.rb +12 -7
  183. data/lib/active_support/logger_thread_safe_level.rb +33 -0
  184. data/lib/active_support/message_encryptor.rb +173 -51
  185. data/lib/active_support/message_verifier.rb +150 -17
  186. data/lib/active_support/messages/metadata.rb +71 -0
  187. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  188. data/lib/active_support/messages/rotator.rb +56 -0
  189. data/lib/active_support/multibyte.rb +4 -2
  190. data/lib/active_support/multibyte/chars.rb +37 -24
  191. data/lib/active_support/multibyte/unicode.rb +100 -96
  192. data/lib/active_support/notifications.rb +11 -7
  193. data/lib/active_support/notifications/fanout.rb +10 -8
  194. data/lib/active_support/notifications/instrumenter.rb +27 -7
  195. data/lib/active_support/number_helper.rb +94 -68
  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/option_merger.rb +3 -1
  206. data/lib/active_support/ordered_hash.rb +6 -4
  207. data/lib/active_support/ordered_options.rb +22 -4
  208. data/lib/active_support/per_thread_registry.rb +13 -6
  209. data/lib/active_support/proxy_object.rb +2 -0
  210. data/lib/active_support/rails.rb +16 -8
  211. data/lib/active_support/railtie.rb +43 -9
  212. data/lib/active_support/reloader.rb +131 -0
  213. data/lib/active_support/rescuable.rb +108 -53
  214. data/lib/active_support/security_utils.rb +17 -6
  215. data/lib/active_support/string_inquirer.rb +11 -3
  216. data/lib/active_support/subscriber.rb +15 -14
  217. data/lib/active_support/tagged_logging.rb +14 -11
  218. data/lib/active_support/test_case.rb +18 -46
  219. data/lib/active_support/testing/assertions.rb +137 -20
  220. data/lib/active_support/testing/autorun.rb +4 -2
  221. data/lib/active_support/testing/constant_lookup.rb +2 -1
  222. data/lib/active_support/testing/declarative.rb +3 -1
  223. data/lib/active_support/testing/deprecation.rb +14 -10
  224. data/lib/active_support/testing/file_fixtures.rb +36 -0
  225. data/lib/active_support/testing/isolation.rb +34 -25
  226. data/lib/active_support/testing/method_call_assertions.rb +43 -0
  227. data/lib/active_support/testing/setup_and_teardown.rb +12 -3
  228. data/lib/active_support/testing/stream.rb +44 -0
  229. data/lib/active_support/testing/tagged_logging.rb +3 -1
  230. data/lib/active_support/testing/time_helpers.rb +96 -27
  231. data/lib/active_support/time.rb +14 -12
  232. data/lib/active_support/time_with_zone.rb +195 -53
  233. data/lib/active_support/values/time_zone.rb +200 -61
  234. data/lib/active_support/values/unicode_tables.dat +0 -0
  235. data/lib/active_support/version.rb +3 -1
  236. data/lib/active_support/xml_mini.rb +69 -51
  237. data/lib/active_support/xml_mini/jdom.rb +116 -113
  238. data/lib/active_support/xml_mini/libxml.rb +17 -16
  239. data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
  240. data/lib/active_support/xml_mini/nokogiri.rb +15 -15
  241. data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
  242. data/lib/active_support/xml_mini/rexml.rb +17 -16
  243. metadata +55 -43
  244. data/lib/active_support/concurrency/latch.rb +0 -27
  245. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -14
  246. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  247. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  248. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  249. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -11
  250. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  251. data/lib/active_support/core_ext/object/itself.rb +0 -15
  252. data/lib/active_support/core_ext/struct.rb +0 -6
  253. data/lib/active_support/core_ext/thread.rb +0 -86
  254. data/lib/active_support/core_ext/time/marshal.rb +0 -30
@@ -0,0 +1,128 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/callbacks"
4
+
5
+ module ActiveSupport
6
+ class ExecutionWrapper
7
+ include ActiveSupport::Callbacks
8
+
9
+ Null = Object.new # :nodoc:
10
+ def Null.complete! # :nodoc:
11
+ end
12
+
13
+ define_callbacks :run
14
+ define_callbacks :complete
15
+
16
+ def self.to_run(*args, &block)
17
+ set_callback(:run, *args, &block)
18
+ end
19
+
20
+ def self.to_complete(*args, &block)
21
+ set_callback(:complete, *args, &block)
22
+ end
23
+
24
+ RunHook = Struct.new(:hook) do # :nodoc:
25
+ def before(target)
26
+ hook_state = target.send(:hook_state)
27
+ hook_state[hook] = hook.run
28
+ end
29
+ end
30
+
31
+ CompleteHook = Struct.new(:hook) do # :nodoc:
32
+ def before(target)
33
+ hook_state = target.send(:hook_state)
34
+ if hook_state.key?(hook)
35
+ hook.complete hook_state[hook]
36
+ end
37
+ end
38
+ alias after before
39
+ end
40
+
41
+ # Register an object to be invoked during both the +run+ and
42
+ # +complete+ steps.
43
+ #
44
+ # +hook.complete+ will be passed the value returned from +hook.run+,
45
+ # and will only be invoked if +run+ has previously been called.
46
+ # (Mostly, this means it won't be invoked if an exception occurs in
47
+ # a preceding +to_run+ block; all ordinary +to_complete+ blocks are
48
+ # invoked in that situation.)
49
+ def self.register_hook(hook, outer: false)
50
+ if outer
51
+ to_run RunHook.new(hook), prepend: true
52
+ to_complete :after, CompleteHook.new(hook)
53
+ else
54
+ to_run RunHook.new(hook)
55
+ to_complete CompleteHook.new(hook)
56
+ end
57
+ end
58
+
59
+ # Run this execution.
60
+ #
61
+ # Returns an instance, whose +complete!+ method *must* be invoked
62
+ # after the work has been performed.
63
+ #
64
+ # Where possible, prefer +wrap+.
65
+ def self.run!
66
+ if active?
67
+ Null
68
+ else
69
+ new.tap do |instance|
70
+ success = nil
71
+ begin
72
+ instance.run!
73
+ success = true
74
+ ensure
75
+ instance.complete! unless success
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ # Perform the work in the supplied block as an execution.
82
+ def self.wrap
83
+ return yield if active?
84
+
85
+ instance = run!
86
+ begin
87
+ yield
88
+ ensure
89
+ instance.complete!
90
+ end
91
+ end
92
+
93
+ class << self # :nodoc:
94
+ attr_accessor :active
95
+ end
96
+
97
+ def self.inherited(other) # :nodoc:
98
+ super
99
+ other.active = Concurrent::Hash.new
100
+ end
101
+
102
+ self.active = Concurrent::Hash.new
103
+
104
+ def self.active? # :nodoc:
105
+ @active[Thread.current]
106
+ end
107
+
108
+ def run! # :nodoc:
109
+ self.class.active[Thread.current] = true
110
+ run_callbacks(:run)
111
+ end
112
+
113
+ # Complete this in-flight execution. This method *must* be called
114
+ # exactly once on the result of any call to +run!+.
115
+ #
116
+ # Where possible, prefer +wrap+.
117
+ def complete!
118
+ run_callbacks(:complete)
119
+ ensure
120
+ self.class.active.delete Thread.current
121
+ end
122
+
123
+ private
124
+ def hook_state
125
+ @_hook_state ||= {}
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/execution_wrapper"
4
+
5
+ module ActiveSupport
6
+ class Executor < ExecutionWrapper
7
+ end
8
+ end
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/time/calculations"
4
+
1
5
  module ActiveSupport
2
6
  # FileUpdateChecker specifies the API used by Rails to watch files
3
7
  # and control reloading. The API depends on four methods:
@@ -23,7 +27,7 @@ module ActiveSupport
23
27
  # I18n.reload!
24
28
  # end
25
29
  #
26
- # ActionDispatch::Reloader.to_prepare do
30
+ # ActiveSupport::Reloader.to_prepare do
27
31
  # i18n_reloader.execute_if_updated
28
32
  # end
29
33
  class FileUpdateChecker
@@ -35,7 +39,11 @@ module ActiveSupport
35
39
  # This method must also receive a block that will be called once a path
36
40
  # changes. The array of files and list of directories cannot be changed
37
41
  # after FileUpdateChecker has been initialized.
38
- def initialize(files, dirs={}, &block)
42
+ def initialize(files, dirs = {}, &block)
43
+ unless block
44
+ raise ArgumentError, "A block is required to initialize a FileUpdateChecker"
45
+ end
46
+
39
47
  @files = files.freeze
40
48
  @glob = compile_glob(dirs)
41
49
  @block = block
@@ -81,6 +89,7 @@ module ActiveSupport
81
89
  # Execute the block given if updated.
82
90
  def execute_if_updated
83
91
  if updated?
92
+ yield if block_given?
84
93
  execute
85
94
  true
86
95
  else
@@ -90,48 +99,65 @@ module ActiveSupport
90
99
 
91
100
  private
92
101
 
93
- def watched
94
- @watched || begin
95
- all = @files.select { |f| File.exist?(f) }
96
- all.concat(Dir[@glob]) if @glob
97
- all
102
+ def watched
103
+ @watched || begin
104
+ all = @files.select { |f| File.exist?(f) }
105
+ all.concat(Dir[@glob]) if @glob
106
+ all
107
+ end
98
108
  end
99
- end
100
109
 
101
- def updated_at(paths)
102
- @updated_at || max_mtime(paths) || Time.at(0)
103
- end
110
+ def updated_at(paths)
111
+ @updated_at || max_mtime(paths) || Time.at(0)
112
+ end
104
113
 
105
- # This method returns the maximum mtime of the files in +paths+, or +nil+
106
- # if the array is empty.
107
- #
108
- # Files with a mtime in the future are ignored. Such abnormal situation
109
- # can happen for example if the user changes the clock by hand. It is
110
- # healthy to consider this edge case because with mtimes in the future
111
- # reloading is not triggered.
112
- def max_mtime(paths)
113
- time_now = Time.now
114
- paths.map {|path| File.mtime(path)}.reject {|mtime| time_now < mtime}.max
115
- end
114
+ # This method returns the maximum mtime of the files in +paths+, or +nil+
115
+ # if the array is empty.
116
+ #
117
+ # Files with a mtime in the future are ignored. Such abnormal situation
118
+ # can happen for example if the user changes the clock by hand. It is
119
+ # healthy to consider this edge case because with mtimes in the future
120
+ # reloading is not triggered.
121
+ def max_mtime(paths)
122
+ time_now = Time.now
123
+ max_mtime = nil
124
+
125
+ # Time comparisons are performed with #compare_without_coercion because
126
+ # AS redefines these operators in a way that is much slower and does not
127
+ # bring any benefit in this particular code.
128
+ #
129
+ # Read t1.compare_without_coercion(t2) < 0 as t1 < t2.
130
+ paths.each do |path|
131
+ mtime = File.mtime(path)
116
132
 
117
- def compile_glob(hash)
118
- hash.freeze # Freeze so changes aren't accidentally pushed
119
- return if hash.empty?
133
+ next if time_now.compare_without_coercion(mtime) < 0
120
134
 
121
- globs = hash.map do |key, value|
122
- "#{escape(key)}/**/*#{compile_ext(value)}"
135
+ if max_mtime.nil? || max_mtime.compare_without_coercion(mtime) < 0
136
+ max_mtime = mtime
137
+ end
138
+ end
139
+
140
+ max_mtime
123
141
  end
124
- "{#{globs.join(",")}}"
125
- end
126
142
 
127
- def escape(key)
128
- key.gsub(',','\,')
129
- end
143
+ def compile_glob(hash)
144
+ hash.freeze # Freeze so changes aren't accidentally pushed
145
+ return if hash.empty?
130
146
 
131
- def compile_ext(array)
132
- array = Array(array)
133
- return if array.empty?
134
- ".{#{array.join(",")}}"
135
- end
147
+ globs = hash.map do |key, value|
148
+ "#{escape(key)}/**/*#{compile_ext(value)}"
149
+ end
150
+ "{#{globs.join(",")}}"
151
+ end
152
+
153
+ def escape(key)
154
+ key.gsub(",", '\,')
155
+ end
156
+
157
+ def compile_ext(array)
158
+ array = Array(array)
159
+ return if array.empty?
160
+ ".{#{array.join(",")}}"
161
+ end
136
162
  end
137
163
  end
@@ -1,11 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
- # Returns the version of the currently loaded Active Support as a <tt>Gem::Version</tt>
4
+ # Returns the version of the currently loaded Active Support as a <tt>Gem::Version</tt>.
3
5
  def self.gem_version
4
6
  Gem::Version.new VERSION::STRING
5
7
  end
6
8
 
7
9
  module VERSION
8
- MAJOR = 4
10
+ MAJOR = 5
9
11
  MINOR = 2
10
12
  TINY = 0
11
13
  PRE = nil
@@ -1,5 +1,7 @@
1
- require 'zlib'
2
- require 'stringio'
1
+ # frozen_string_literal: true
2
+
3
+ require "zlib"
4
+ require "stringio"
3
5
 
4
6
  module ActiveSupport
5
7
  # A convenient wrapper for the zlib standard library that allows
@@ -9,7 +11,7 @@ module ActiveSupport
9
11
  # # => "\x1F\x8B\b\x00o\x8D\xCDO\x00\x03K\xCE\xCF-(J-.V\xC8MU\x04\x00R>n\x83\f\x00\x00\x00"
10
12
  #
11
13
  # ActiveSupport::Gzip.decompress(gzip)
12
- # # => "compress me!"
14
+ # # => "compress me!"
13
15
  module Gzip
14
16
  class Stream < StringIO
15
17
  def initialize(*)
@@ -21,11 +23,11 @@ module ActiveSupport
21
23
 
22
24
  # Decompresses a gzipped string.
23
25
  def self.decompress(source)
24
- Zlib::GzipReader.new(StringIO.new(source)).read
26
+ Zlib::GzipReader.wrap(StringIO.new(source), &:read)
25
27
  end
26
28
 
27
29
  # Compresses a string using gzip.
28
- def self.compress(source, level=Zlib::DEFAULT_COMPRESSION, strategy=Zlib::DEFAULT_STRATEGY)
30
+ def self.compress(source, level = Zlib::DEFAULT_COMPRESSION, strategy = Zlib::DEFAULT_STRATEGY)
29
31
  output = Stream.new
30
32
  gz = Zlib::GzipWriter.new(output, level, strategy)
31
33
  gz.write(source)
@@ -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,19 @@ 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
+
157
166
  # Same as <tt>Hash#fetch</tt> where the key passed as argument can be
158
167
  # either a string or a symbol:
159
168
  #
@@ -168,6 +177,36 @@ module ActiveSupport
168
177
  super(convert_key(key), *extras)
169
178
  end
170
179
 
180
+ if Hash.new.respond_to?(:dig)
181
+ # Same as <tt>Hash#dig</tt> where the key passed as argument can be
182
+ # either a string or a symbol:
183
+ #
184
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
185
+ # counters[:foo] = { bar: 1 }
186
+ #
187
+ # counters.dig('foo', 'bar') # => 1
188
+ # counters.dig(:foo, :bar) # => 1
189
+ # counters.dig(:zoo) # => nil
190
+ def dig(*args)
191
+ args[0] = convert_key(args[0]) if args.size > 0
192
+ super(*args)
193
+ end
194
+ end
195
+
196
+ # Same as <tt>Hash#default</tt> where the key passed as argument can be
197
+ # either a string or a symbol:
198
+ #
199
+ # hash = ActiveSupport::HashWithIndifferentAccess.new(1)
200
+ # hash.default # => 1
201
+ #
202
+ # hash = ActiveSupport::HashWithIndifferentAccess.new { |hash, key| key }
203
+ # hash.default # => nil
204
+ # hash.default('foo') # => 'foo'
205
+ # hash.default(:foo) # => 'foo'
206
+ def default(*args)
207
+ super(*args.map { |arg| convert_key(arg) })
208
+ end
209
+
171
210
  # Returns an array of the values at the specified indices:
172
211
  #
173
212
  # hash = ActiveSupport::HashWithIndifferentAccess.new
@@ -178,17 +217,30 @@ module ActiveSupport
178
217
  indices.collect { |key| self[convert_key(key)] }
179
218
  end
180
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
+
181
233
  # Returns a shallow copy of the hash.
182
234
  #
183
235
  # hash = ActiveSupport::HashWithIndifferentAccess.new({ a: { b: 'b' } })
184
236
  # dup = hash.dup
185
237
  # dup[:a][:c] = 'c'
186
238
  #
187
- # hash[:a][:c] # => nil
239
+ # hash[:a][:c] # => "c"
188
240
  # dup[:a][:c] # => "c"
189
241
  def dup
190
242
  self.class.new(self).tap do |new_hash|
191
- new_hash.default = default
243
+ set_defaults(new_hash)
192
244
  end
193
245
  end
194
246
 
@@ -196,7 +248,7 @@ module ActiveSupport
196
248
  # modify the receiver but rather returns a new hash with indifferent
197
249
  # access with the result of the merge.
198
250
  def merge(hash, &block)
199
- self.dup.update(hash, &block)
251
+ dup.update(hash, &block)
200
252
  end
201
253
 
202
254
  # Like +merge+ but the other way around: Merges the receiver into the
@@ -206,20 +258,22 @@ module ActiveSupport
206
258
  # hash['a'] = nil
207
259
  # hash.reverse_merge(a: 0, b: 1) # => {"a"=>nil, "b"=>1}
208
260
  def reverse_merge(other_hash)
209
- super(self.class.new_from_hash_copying_default(other_hash))
261
+ super(self.class.new(other_hash))
210
262
  end
263
+ alias_method :with_defaults, :reverse_merge
211
264
 
212
265
  # Same semantics as +reverse_merge+ but modifies the receiver in-place.
213
266
  def reverse_merge!(other_hash)
214
- replace(reverse_merge( other_hash ))
267
+ super(self.class.new(other_hash))
215
268
  end
269
+ alias_method :with_defaults!, :reverse_merge!
216
270
 
217
271
  # Replaces the contents of this hash with other_hash.
218
272
  #
219
273
  # h = { "a" => 100, "b" => 200 }
220
274
  # h.replace({ "c" => 300, "d" => 400 }) # => {"c"=>300, "d"=>400}
221
275
  def replace(other_hash)
222
- super(self.class.new_from_hash_copying_default(other_hash))
276
+ super(self.class.new(other_hash))
223
277
  end
224
278
 
225
279
  # Removes the specified key from the hash.
@@ -238,28 +292,64 @@ module ActiveSupport
238
292
  def to_options!; self end
239
293
 
240
294
  def select(*args, &block)
295
+ return to_enum(:select) unless block_given?
241
296
  dup.tap { |hash| hash.select!(*args, &block) }
242
297
  end
243
298
 
244
299
  def reject(*args, &block)
300
+ return to_enum(:reject) unless block_given?
245
301
  dup.tap { |hash| hash.reject!(*args, &block) }
246
302
  end
247
303
 
304
+ def transform_values(*args, &block)
305
+ return to_enum(:transform_values) unless block_given?
306
+ dup.tap { |hash| hash.transform_values!(*args, &block) }
307
+ end
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
+
332
+ def compact
333
+ dup.tap(&:compact!)
334
+ end
335
+
248
336
  # Convert to a regular hash with string keys.
249
337
  def to_hash
250
- _new_hash = Hash.new(default)
338
+ _new_hash = Hash.new
339
+ set_defaults(_new_hash)
340
+
251
341
  each do |key, value|
252
342
  _new_hash[key] = convert_value(value, for: :to_hash)
253
343
  end
254
344
  _new_hash
255
345
  end
256
346
 
257
- protected
258
- def convert_key(key)
347
+ private
348
+ def convert_key(key) # :doc:
259
349
  key.kind_of?(Symbol) ? key.to_s : key
260
350
  end
261
351
 
262
- def convert_value(value, options = {})
352
+ def convert_value(value, options = {}) # :doc:
263
353
  if value.is_a? Hash
264
354
  if options[:for] == :to_hash
265
355
  value.to_hash
@@ -267,7 +357,7 @@ module ActiveSupport
267
357
  value.nested_under_indifferent_access
268
358
  end
269
359
  elsif value.is_a?(Array)
270
- unless options[:for] == :assignment
360
+ if options[:for] != :assignment || value.frozen?
271
361
  value = value.dup
272
362
  end
273
363
  value.map! { |e| convert_value(e, options) }
@@ -275,7 +365,17 @@ module ActiveSupport
275
365
  value
276
366
  end
277
367
  end
368
+
369
+ def set_defaults(target) # :doc:
370
+ if default_proc
371
+ target.default_proc = default_proc.dup
372
+ else
373
+ target.default = default
374
+ end
375
+ end
278
376
  end
279
377
  end
280
378
 
379
+ # :stopdoc:
380
+
281
381
  HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess