activesupport 5.0.0 → 6.1.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 (268) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +343 -590
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -4
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/all.rb +5 -3
  7. data/lib/active_support/array_inquirer.rb +11 -5
  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 +3 -1
  11. data/lib/active_support/cache/file_store.rb +45 -53
  12. data/lib/active_support/cache/mem_cache_store.rb +81 -79
  13. data/lib/active_support/cache/memory_store.rb +69 -41
  14. data/lib/active_support/cache/null_store.rb +11 -4
  15. data/lib/active_support/cache/redis_cache_store.rb +493 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +74 -37
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  18. data/lib/active_support/cache.rb +332 -161
  19. data/lib/active_support/callbacks.rb +657 -586
  20. data/lib/active_support/concern.rb +79 -6
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
  22. data/lib/active_support/concurrency/share_lock.rb +59 -19
  23. data/lib/active_support/configurable.rb +15 -17
  24. data/lib/active_support/configuration_file.rb +46 -0
  25. data/lib/active_support/core_ext/array/access.rb +21 -7
  26. data/lib/active_support/core_ext/array/conversions.rb +20 -18
  27. data/lib/active_support/core_ext/array/extract.rb +21 -0
  28. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  29. data/lib/active_support/core_ext/array/grouping.rb +3 -1
  30. data/lib/active_support/core_ext/array/inquiry.rb +3 -1
  31. data/lib/active_support/core_ext/array/wrap.rb +2 -0
  32. data/lib/active_support/core_ext/array.rb +9 -7
  33. data/lib/active_support/core_ext/benchmark.rb +5 -3
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +6 -6
  35. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  36. data/lib/active_support/core_ext/class/attribute.rb +52 -49
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  38. data/lib/active_support/core_ext/class/subclasses.rb +18 -26
  39. data/lib/active_support/core_ext/class.rb +4 -2
  40. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  41. data/lib/active_support/core_ext/date/blank.rb +3 -1
  42. data/lib/active_support/core_ext/date/calculations.rb +16 -13
  43. data/lib/active_support/core_ext/date/conversions.rb +23 -21
  44. data/lib/active_support/core_ext/date/zones.rb +4 -2
  45. data/lib/active_support/core_ext/date.rb +7 -5
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +82 -53
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -5
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +9 -9
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  50. data/lib/active_support/core_ext/date_time/blank.rb +3 -1
  51. data/lib/active_support/core_ext/date_time/calculations.rb +23 -11
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +15 -2
  53. data/lib/active_support/core_ext/date_time/conversions.rb +14 -13
  54. data/lib/active_support/core_ext/date_time.rb +7 -5
  55. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  56. data/lib/active_support/core_ext/digest.rb +3 -0
  57. data/lib/active_support/core_ext/enumerable.rb +165 -29
  58. data/lib/active_support/core_ext/file/atomic.rb +7 -5
  59. data/lib/active_support/core_ext/file.rb +3 -1
  60. data/lib/active_support/core_ext/hash/conversions.rb +40 -39
  61. data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
  62. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  63. data/lib/active_support/core_ext/hash/except.rb +4 -2
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -2
  65. data/lib/active_support/core_ext/hash/keys.rb +9 -36
  66. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  67. data/lib/active_support/core_ext/hash/slice.rb +8 -29
  68. data/lib/active_support/core_ext/hash.rb +10 -9
  69. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  70. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  71. data/lib/active_support/core_ext/integer/time.rb +11 -18
  72. data/lib/active_support/core_ext/integer.rb +5 -3
  73. data/lib/active_support/core_ext/kernel/concern.rb +3 -1
  74. data/lib/active_support/core_ext/kernel/reporting.rb +3 -1
  75. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  76. data/lib/active_support/core_ext/kernel.rb +5 -4
  77. data/lib/active_support/core_ext/load_error.rb +2 -23
  78. data/lib/active_support/core_ext/marshal.rb +6 -2
  79. data/lib/active_support/core_ext/module/aliasing.rb +5 -48
  80. data/lib/active_support/core_ext/module/anonymous.rb +2 -0
  81. data/lib/active_support/core_ext/module/attr_internal.rb +7 -5
  82. data/lib/active_support/core_ext/module/attribute_accessors.rb +53 -59
  83. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +31 -24
  84. data/lib/active_support/core_ext/module/concerning.rb +16 -11
  85. data/lib/active_support/core_ext/module/delegation.rb +159 -44
  86. data/lib/active_support/core_ext/module/deprecation.rb +2 -0
  87. data/lib/active_support/core_ext/module/introspection.rb +23 -26
  88. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  89. data/lib/active_support/core_ext/module/remove_method.rb +5 -23
  90. data/lib/active_support/core_ext/module.rb +13 -12
  91. data/lib/active_support/core_ext/name_error.rb +36 -2
  92. data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
  93. data/lib/active_support/core_ext/numeric/conversions.rb +129 -134
  94. data/lib/active_support/core_ext/numeric/time.rb +18 -26
  95. data/lib/active_support/core_ext/numeric.rb +5 -4
  96. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  97. data/lib/active_support/core_ext/object/blank.rb +14 -2
  98. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  99. data/lib/active_support/core_ext/object/deep_dup.rb +4 -2
  100. data/lib/active_support/core_ext/object/duplicable.rb +13 -62
  101. data/lib/active_support/core_ext/object/inclusion.rb +3 -1
  102. data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
  103. data/lib/active_support/core_ext/object/json.rb +42 -15
  104. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  105. data/lib/active_support/core_ext/object/to_query.rb +10 -5
  106. data/lib/active_support/core_ext/object/try.rb +20 -8
  107. data/lib/active_support/core_ext/object/with_options.rb +15 -2
  108. data/lib/active_support/core_ext/object.rb +14 -12
  109. data/lib/active_support/core_ext/range/compare_range.rb +82 -0
  110. data/lib/active_support/core_ext/range/conversions.rb +35 -25
  111. data/lib/active_support/core_ext/range/each.rb +5 -2
  112. data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
  113. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  114. data/lib/active_support/core_ext/range.rb +7 -4
  115. data/lib/active_support/core_ext/regexp.rb +10 -1
  116. data/lib/active_support/core_ext/securerandom.rb +28 -6
  117. data/lib/active_support/core_ext/string/access.rb +9 -18
  118. data/lib/active_support/core_ext/string/behavior.rb +2 -0
  119. data/lib/active_support/core_ext/string/conversions.rb +5 -2
  120. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  121. data/lib/active_support/core_ext/string/filters.rb +47 -4
  122. data/lib/active_support/core_ext/string/indent.rb +6 -4
  123. data/lib/active_support/core_ext/string/inflections.rb +78 -29
  124. data/lib/active_support/core_ext/string/inquiry.rb +4 -1
  125. data/lib/active_support/core_ext/string/multibyte.rb +10 -5
  126. data/lib/active_support/core_ext/string/output_safety.rb +86 -31
  127. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  128. data/lib/active_support/core_ext/string/strip.rb +5 -1
  129. data/lib/active_support/core_ext/string/zones.rb +4 -2
  130. data/lib/active_support/core_ext/string.rb +15 -13
  131. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  132. data/lib/active_support/core_ext/symbol.rb +3 -0
  133. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  134. data/lib/active_support/core_ext/time/calculations.rb +117 -45
  135. data/lib/active_support/core_ext/time/compatibility.rb +13 -2
  136. data/lib/active_support/core_ext/time/conversions.rb +18 -12
  137. data/lib/active_support/core_ext/time/zones.rb +9 -7
  138. data/lib/active_support/core_ext/time.rb +7 -5
  139. data/lib/active_support/core_ext/uri.rb +12 -7
  140. data/lib/active_support/core_ext.rb +3 -2
  141. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  142. data/lib/active_support/current_attributes.rb +208 -0
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +7 -1
  145. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  146. data/lib/active_support/dependencies.rb +172 -98
  147. data/lib/active_support/deprecation/behaviors.rb +45 -13
  148. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  149. data/lib/active_support/deprecation/disallowed.rb +56 -0
  150. data/lib/active_support/deprecation/instance_delegator.rb +16 -2
  151. data/lib/active_support/deprecation/method_wrappers.rb +32 -17
  152. data/lib/active_support/deprecation/proxy_wrappers.rb +35 -7
  153. data/lib/active_support/deprecation/reporting.rb +61 -16
  154. data/lib/active_support/deprecation.rb +17 -9
  155. data/lib/active_support/descendants_tracker.rb +61 -9
  156. data/lib/active_support/digest.rb +20 -0
  157. data/lib/active_support/duration/iso8601_parser.rb +67 -66
  158. data/lib/active_support/duration/iso8601_serializer.rb +25 -17
  159. data/lib/active_support/duration.rb +349 -46
  160. data/lib/active_support/encrypted_configuration.rb +45 -0
  161. data/lib/active_support/encrypted_file.rb +117 -0
  162. data/lib/active_support/environment_inquirer.rb +20 -0
  163. data/lib/active_support/evented_file_update_checker.rb +88 -112
  164. data/lib/active_support/execution_wrapper.rb +25 -13
  165. data/lib/active_support/executor.rb +3 -1
  166. data/lib/active_support/file_update_checker.rb +56 -51
  167. data/lib/active_support/fork_tracker.rb +62 -0
  168. data/lib/active_support/gem_version.rb +4 -2
  169. data/lib/active_support/gzip.rb +7 -5
  170. data/lib/active_support/hash_with_indifferent_access.rb +153 -49
  171. data/lib/active_support/i18n.rb +9 -6
  172. data/lib/active_support/i18n_railtie.rb +30 -20
  173. data/lib/active_support/inflections.rb +13 -11
  174. data/lib/active_support/inflector/inflections.rb +28 -15
  175. data/lib/active_support/inflector/methods.rb +120 -109
  176. data/lib/active_support/inflector/transliterate.rb +60 -25
  177. data/lib/active_support/inflector.rb +7 -5
  178. data/lib/active_support/json/decoding.rb +30 -29
  179. data/lib/active_support/json/encoding.rb +22 -11
  180. data/lib/active_support/json.rb +4 -2
  181. data/lib/active_support/key_generator.rb +6 -36
  182. data/lib/active_support/lazy_load_hooks.rb +53 -20
  183. data/lib/active_support/locale/en.rb +33 -0
  184. data/lib/active_support/locale/en.yml +7 -3
  185. data/lib/active_support/log_subscriber/test_helper.rb +11 -9
  186. data/lib/active_support/log_subscriber.rb +51 -18
  187. data/lib/active_support/logger.rb +9 -22
  188. data/lib/active_support/logger_silence.rb +14 -21
  189. data/lib/active_support/logger_thread_safe_level.rb +55 -8
  190. data/lib/active_support/message_encryptor.rb +170 -53
  191. data/lib/active_support/message_verifier.rb +91 -20
  192. data/lib/active_support/messages/metadata.rb +80 -0
  193. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  194. data/lib/active_support/messages/rotator.rb +57 -0
  195. data/lib/active_support/multibyte/chars.rb +24 -78
  196. data/lib/active_support/multibyte/unicode.rb +21 -352
  197. data/lib/active_support/multibyte.rb +4 -2
  198. data/lib/active_support/notifications/fanout.rb +121 -19
  199. data/lib/active_support/notifications/instrumenter.rb +78 -14
  200. data/lib/active_support/notifications.rb +80 -12
  201. data/lib/active_support/number_helper/number_converter.rb +17 -16
  202. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -9
  203. data/lib/active_support/number_helper/number_to_delimited_converter.rb +5 -3
  204. data/lib/active_support/number_helper/number_to_human_converter.rb +13 -12
  205. data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -13
  206. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  207. data/lib/active_support/number_helper/number_to_phone_converter.rb +5 -4
  208. data/lib/active_support/number_helper/number_to_rounded_converter.rb +18 -55
  209. data/lib/active_support/number_helper/rounding_helper.rb +50 -0
  210. data/lib/active_support/number_helper.rb +45 -16
  211. data/lib/active_support/option_merger.rb +25 -4
  212. data/lib/active_support/ordered_hash.rb +6 -4
  213. data/lib/active_support/ordered_options.rb +23 -9
  214. data/lib/active_support/parameter_filter.rb +133 -0
  215. data/lib/active_support/per_thread_registry.rb +7 -5
  216. data/lib/active_support/proxy_object.rb +2 -0
  217. data/lib/active_support/rails.rb +8 -9
  218. data/lib/active_support/railtie.rb +62 -11
  219. data/lib/active_support/reloader.rb +12 -11
  220. data/lib/active_support/rescuable.rb +20 -11
  221. data/lib/active_support/secure_compare_rotator.rb +51 -0
  222. data/lib/active_support/security_utils.rb +26 -15
  223. data/lib/active_support/string_inquirer.rb +12 -3
  224. data/lib/active_support/subscriber.rb +77 -23
  225. data/lib/active_support/tagged_logging.rb +52 -17
  226. data/lib/active_support/test_case.rb +106 -29
  227. data/lib/active_support/testing/assertions.rb +144 -8
  228. data/lib/active_support/testing/autorun.rb +5 -10
  229. data/lib/active_support/testing/constant_lookup.rb +2 -1
  230. data/lib/active_support/testing/declarative.rb +3 -1
  231. data/lib/active_support/testing/deprecation.rb +4 -2
  232. data/lib/active_support/testing/file_fixtures.rb +4 -0
  233. data/lib/active_support/testing/isolation.rb +19 -24
  234. data/lib/active_support/testing/method_call_assertions.rb +31 -2
  235. data/lib/active_support/testing/parallelization/server.rb +78 -0
  236. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  237. data/lib/active_support/testing/parallelization.rb +51 -0
  238. data/lib/active_support/testing/setup_and_teardown.rb +13 -8
  239. data/lib/active_support/testing/stream.rb +30 -29
  240. data/lib/active_support/testing/tagged_logging.rb +3 -1
  241. data/lib/active_support/testing/time_helpers.rb +125 -24
  242. data/lib/active_support/time.rb +14 -12
  243. data/lib/active_support/time_with_zone.rb +142 -55
  244. data/lib/active_support/values/time_zone.rb +160 -53
  245. data/lib/active_support/version.rb +3 -1
  246. data/lib/active_support/xml_mini/jdom.rb +115 -114
  247. data/lib/active_support/xml_mini/libxml.rb +15 -14
  248. data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
  249. data/lib/active_support/xml_mini/nokogiri.rb +13 -13
  250. data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
  251. data/lib/active_support/xml_mini/rexml.rb +18 -9
  252. data/lib/active_support/xml_mini.rb +44 -42
  253. data/lib/active_support.rb +19 -10
  254. metadata +79 -37
  255. data/lib/active_support/concurrency/latch.rb +0 -19
  256. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  257. data/lib/active_support/core_ext/hash/compact.rb +0 -20
  258. data/lib/active_support/core_ext/hash/transform_values.rb +0 -29
  259. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  260. data/lib/active_support/core_ext/kernel/debugger.rb +0 -3
  261. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -3
  262. data/lib/active_support/core_ext/module/qualified_const.rb +0 -70
  263. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  264. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
  265. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  266. data/lib/active_support/core_ext/struct.rb +0 -3
  267. data/lib/active_support/core_ext/time/marshal.rb +0 -3
  268. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,32 +1,31 @@
1
- require 'erb'
2
- require 'active_support/core_ext/kernel/singleton_class'
1
+ # frozen_string_literal: true
2
+
3
+ require "erb"
4
+ require "active_support/core_ext/module/redefine_method"
5
+ require "active_support/multibyte/unicode"
3
6
 
4
7
  class ERB
5
8
  module Util
6
- HTML_ESCAPE = { '&' => '&amp;', '>' => '&gt;', '<' => '&lt;', '"' => '&quot;', "'" => '&#39;' }
7
- JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003e', '<' => '\u003c', "\u2028" => '\u2028', "\u2029" => '\u2029' }
9
+ HTML_ESCAPE = { "&" => "&amp;", ">" => "&gt;", "<" => "&lt;", '"' => "&quot;", "'" => "&#39;" }
10
+ JSON_ESCAPE = { "&" => '\u0026', ">" => '\u003e', "<" => '\u003c', "\u2028" => '\u2028', "\u2029" => '\u2029' }
8
11
  HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+)|(#[xX][\dA-Fa-f]+));)/
9
12
  JSON_ESCAPE_REGEXP = /[\u2028\u2029&><]/u
10
13
 
11
14
  # A utility method for escaping HTML tag characters.
12
15
  # This method is also aliased as <tt>h</tt>.
13
16
  #
14
- # In your ERB templates, use this method to escape any unsafe content. For example:
15
- # <%= h @person.name %>
16
- #
17
17
  # puts html_escape('is a > 0 & a < 10?')
18
18
  # # => is a &gt; 0 &amp; a &lt; 10?
19
19
  def html_escape(s)
20
20
  unwrapped_html_escape(s).html_safe
21
21
  end
22
22
 
23
- # Aliasing twice issues a warning "discarding old...". Remove first to avoid it.
24
- remove_method(:h)
23
+ silence_redefinition_of_method :h
25
24
  alias h html_escape
26
25
 
27
26
  module_function :h
28
27
 
29
- singleton_class.send(:remove_method, :html_escape)
28
+ singleton_class.silence_redefinition_of_method :html_escape
30
29
  module_function :html_escape
31
30
 
32
31
  # HTML escapes strings but doesn't wrap them with an ActiveSupport::SafeBuffer.
@@ -134,35 +133,34 @@ end
134
133
  module ActiveSupport #:nodoc:
135
134
  class SafeBuffer < String
136
135
  UNSAFE_STRING_METHODS = %w(
137
- capitalize chomp chop delete downcase gsub lstrip next reverse rstrip
138
- slice squeeze strip sub succ swapcase tr tr_s upcase
136
+ capitalize chomp chop delete delete_prefix delete_suffix
137
+ downcase lstrip next reverse rstrip scrub slice squeeze strip
138
+ succ swapcase tr tr_s unicode_normalize upcase
139
139
  )
140
140
 
141
+ UNSAFE_STRING_METHODS_WITH_BACKREF = %w(gsub sub)
142
+
141
143
  alias_method :original_concat, :concat
142
144
  private :original_concat
143
145
 
144
146
  # Raised when <tt>ActiveSupport::SafeBuffer#safe_concat</tt> is called on unsafe buffers.
145
147
  class SafeConcatError < StandardError
146
148
  def initialize
147
- super 'Could not concatenate to the buffer because it is not html safe.'
149
+ super "Could not concatenate to the buffer because it is not html safe."
148
150
  end
149
151
  end
150
152
 
151
153
  def [](*args)
152
- if args.size < 2
153
- super
154
- else
155
- if html_safe?
156
- new_safe_buffer = super
154
+ if html_safe?
155
+ new_string = super
157
156
 
158
- if new_safe_buffer
159
- new_safe_buffer.instance_variable_set :@html_safe, true
160
- end
157
+ return unless new_string
161
158
 
162
- new_safe_buffer
163
- else
164
- to_str[*args]
165
- end
159
+ new_safe_buffer = new_string.is_a?(SafeBuffer) ? new_string : SafeBuffer.new(new_string)
160
+ new_safe_buffer.instance_variable_set :@html_safe, true
161
+ new_safe_buffer
162
+ else
163
+ to_str[*args]
166
164
  end
167
165
  end
168
166
 
@@ -171,7 +169,7 @@ module ActiveSupport #:nodoc:
171
169
  original_concat(value)
172
170
  end
173
171
 
174
- def initialize(str = '')
172
+ def initialize(str = "")
175
173
  @html_safe = true
176
174
  super
177
175
  end
@@ -190,18 +188,41 @@ module ActiveSupport #:nodoc:
190
188
  end
191
189
  alias << concat
192
190
 
191
+ def insert(index, value)
192
+ super(index, html_escape_interpolated_argument(value))
193
+ end
194
+
193
195
  def prepend(value)
194
196
  super(html_escape_interpolated_argument(value))
195
197
  end
196
198
 
199
+ def replace(value)
200
+ super(html_escape_interpolated_argument(value))
201
+ end
202
+
203
+ def []=(*args)
204
+ if args.length == 3
205
+ super(args[0], args[1], html_escape_interpolated_argument(args[2]))
206
+ else
207
+ super(args[0], html_escape_interpolated_argument(args[1]))
208
+ end
209
+ end
210
+
197
211
  def +(other)
198
212
  dup.concat(other)
199
213
  end
200
214
 
215
+ def *(*)
216
+ new_string = super
217
+ new_safe_buffer = new_string.is_a?(SafeBuffer) ? new_string : SafeBuffer.new(new_string)
218
+ new_safe_buffer.instance_variable_set(:@html_safe, @html_safe)
219
+ new_safe_buffer
220
+ end
221
+
201
222
  def %(args)
202
223
  case args
203
224
  when Hash
204
- escaped_args = Hash[args.map { |k,arg| [k, html_escape_interpolated_argument(arg)] }]
225
+ escaped_args = args.transform_values { |arg| html_escape_interpolated_argument(arg) }
205
226
  else
206
227
  escaped_args = Array(args).map { |arg| html_escape_interpolated_argument(arg) }
207
228
  end
@@ -240,11 +261,45 @@ module ActiveSupport #:nodoc:
240
261
  end
241
262
  end
242
263
 
264
+ UNSAFE_STRING_METHODS_WITH_BACKREF.each do |unsafe_method|
265
+ if unsafe_method.respond_to?(unsafe_method)
266
+ class_eval <<-EOT, __FILE__, __LINE__ + 1
267
+ def #{unsafe_method}(*args, &block) # def gsub(*args, &block)
268
+ if block # if block
269
+ to_str.#{unsafe_method}(*args) { |*params| # to_str.gsub(*args) { |*params|
270
+ set_block_back_references(block, $~) # set_block_back_references(block, $~)
271
+ block.call(*params) # block.call(*params)
272
+ } # }
273
+ else # else
274
+ to_str.#{unsafe_method}(*args) # to_str.gsub(*args)
275
+ end # end
276
+ end # end
277
+
278
+ def #{unsafe_method}!(*args, &block) # def gsub!(*args, &block)
279
+ @html_safe = false # @html_safe = false
280
+ if block # if block
281
+ super(*args) { |*params| # super(*args) { |*params|
282
+ set_block_back_references(block, $~) # set_block_back_references(block, $~)
283
+ block.call(*params) # block.call(*params)
284
+ } # }
285
+ else # else
286
+ super # super
287
+ end # end
288
+ end # end
289
+ EOT
290
+ end
291
+ end
292
+
243
293
  private
294
+ def html_escape_interpolated_argument(arg)
295
+ (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
296
+ end
244
297
 
245
- def html_escape_interpolated_argument(arg)
246
- (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
247
- end
298
+ def set_block_back_references(block, match_data)
299
+ block.binding.eval("proc { |m| $~ = m }").call(match_data)
300
+ rescue ArgumentError
301
+ # Can't create binding from C level Proc
302
+ end
248
303
  end
249
304
  end
250
305
 
@@ -252,7 +307,7 @@ class String
252
307
  # Marks a string as trusted safe. It will be inserted into HTML with no
253
308
  # additional escaping performed. It is your responsibility to ensure that the
254
309
  # string contains no malicious content. This method is equivalent to the
255
- # `raw` helper in views. It is recommended that you use `sanitize` instead of
310
+ # +raw+ helper in views. It is recommended that you use +sanitize+ instead of
256
311
  # this method. It should never be called on user input.
257
312
  def html_safe
258
313
  ActiveSupport::SafeBuffer.new(self)
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
- alias_method :starts_with?, :start_with?
3
- alias_method :ends_with?, :end_with?
4
+ alias :starts_with? :start_with?
5
+ alias :ends_with? :end_with?
4
6
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
4
  # Strips indentation in heredocs.
3
5
  #
@@ -18,6 +20,8 @@ class String
18
20
  # Technically, it looks for the least indented non-empty line
19
21
  # in the whole string, and removes that amount of leading whitespace.
20
22
  def strip_heredoc
21
- gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, ''.freeze)
23
+ gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "").tap do |stripped|
24
+ stripped.freeze if frozen?
25
+ end
22
26
  end
23
27
  end
@@ -1,5 +1,7 @@
1
- require 'active_support/core_ext/string/conversions'
2
- require 'active_support/core_ext/time/zones'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/string/conversions"
4
+ require "active_support/core_ext/time/zones"
3
5
 
4
6
  class String
5
7
  # Converts String to a TimeWithZone in the current zone if Time.zone or Time.zone_default
@@ -1,13 +1,15 @@
1
- require 'active_support/core_ext/string/conversions'
2
- require 'active_support/core_ext/string/filters'
3
- require 'active_support/core_ext/string/multibyte'
4
- require 'active_support/core_ext/string/starts_ends_with'
5
- require 'active_support/core_ext/string/inflections'
6
- require 'active_support/core_ext/string/access'
7
- require 'active_support/core_ext/string/behavior'
8
- require 'active_support/core_ext/string/output_safety'
9
- require 'active_support/core_ext/string/exclude'
10
- require 'active_support/core_ext/string/strip'
11
- require 'active_support/core_ext/string/inquiry'
12
- require 'active_support/core_ext/string/indent'
13
- require 'active_support/core_ext/string/zones'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/string/conversions"
4
+ require "active_support/core_ext/string/filters"
5
+ require "active_support/core_ext/string/multibyte"
6
+ require "active_support/core_ext/string/starts_ends_with"
7
+ require "active_support/core_ext/string/inflections"
8
+ require "active_support/core_ext/string/access"
9
+ require "active_support/core_ext/string/behavior"
10
+ require "active_support/core_ext/string/output_safety"
11
+ require "active_support/core_ext/string/exclude"
12
+ require "active_support/core_ext/string/strip"
13
+ require "active_support/core_ext/string/inquiry"
14
+ require "active_support/core_ext/string/indent"
15
+ require "active_support/core_ext/string/zones"
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Symbol
4
+ def start_with?(*prefixes)
5
+ to_s.start_with?(*prefixes)
6
+ end unless method_defined?(:start_with?)
7
+
8
+ def end_with?(*suffixes)
9
+ to_s.end_with?(*suffixes)
10
+ end unless method_defined?(:end_with?)
11
+
12
+ alias :starts_with? :start_with?
13
+ alias :ends_with? :end_with?
14
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/symbol/starts_ends_with"
@@ -1,4 +1,6 @@
1
- require 'active_support/core_ext/object/acts_like'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/object/acts_like"
2
4
 
3
5
  class Time
4
6
  # Duck-types as a Time-like class. See Object#acts_like?.
@@ -1,9 +1,12 @@
1
- require 'active_support/duration'
2
- require 'active_support/core_ext/time/conversions'
3
- require 'active_support/time_with_zone'
4
- require 'active_support/core_ext/time/zones'
5
- require 'active_support/core_ext/date_and_time/calculations'
6
- require 'active_support/core_ext/date/calculations'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/duration"
4
+ require "active_support/core_ext/time/conversions"
5
+ require "active_support/time_with_zone"
6
+ require "active_support/core_ext/time/zones"
7
+ require "active_support/core_ext/date_and_time/calculations"
8
+ require "active_support/core_ext/date/calculations"
9
+ require "active_support/core_ext/module/remove_method"
7
10
 
8
11
  class Time
9
12
  include DateAndTime::Calculations
@@ -45,7 +48,9 @@ class Time
45
48
  # Time.at can be called with a time or numerical value
46
49
  time_or_number = args.first
47
50
 
48
- if time_or_number.is_a?(ActiveSupport::TimeWithZone) || time_or_number.is_a?(DateTime)
51
+ if time_or_number.is_a?(ActiveSupport::TimeWithZone)
52
+ at_without_coercion(time_or_number.to_r).getlocal
53
+ elsif time_or_number.is_a?(DateTime)
49
54
  at_without_coercion(time_or_number.to_f).getlocal
50
55
  else
51
56
  at_without_coercion(time_or_number)
@@ -53,6 +58,29 @@ class Time
53
58
  end
54
59
  alias_method :at_without_coercion, :at
55
60
  alias_method :at, :at_with_coercion
61
+
62
+ # Creates a +Time+ instance from an RFC 3339 string.
63
+ #
64
+ # Time.rfc3339('1999-12-31T14:00:00-10:00') # => 2000-01-01 00:00:00 -1000
65
+ #
66
+ # If the time or offset components are missing then an +ArgumentError+ will be raised.
67
+ #
68
+ # Time.rfc3339('1999-12-31') # => ArgumentError: invalid date
69
+ def rfc3339(str)
70
+ parts = Date._rfc3339(str)
71
+
72
+ raise ArgumentError, "invalid date" if parts.empty?
73
+
74
+ Time.new(
75
+ parts.fetch(:year),
76
+ parts.fetch(:mon),
77
+ parts.fetch(:mday),
78
+ parts.fetch(:hour),
79
+ parts.fetch(:min),
80
+ parts.fetch(:sec) + parts.fetch(:sec_fraction, 0),
81
+ parts.fetch(:offset)
82
+ )
83
+ end
56
84
  end
57
85
 
58
86
  # Returns the number of seconds since 00:00:00.
@@ -61,7 +89,7 @@ class Time
61
89
  # Time.new(2012, 8, 29, 12, 34, 56).seconds_since_midnight # => 45296.0
62
90
  # Time.new(2012, 8, 29, 23, 59, 59).seconds_since_midnight # => 86399.0
63
91
  def seconds_since_midnight
64
- to_i - change(:hour => 0).to_i + (usec / 1.0e+6)
92
+ to_i - change(hour: 0).to_i + (usec / 1.0e+6)
65
93
  end
66
94
 
67
95
  # Returns the number of seconds until 23:59:59.
@@ -80,40 +108,61 @@ class Time
80
108
  subsec
81
109
  end
82
110
 
111
+ unless Time.method_defined?(:floor)
112
+ def floor(precision = 0)
113
+ change(nsec: 0) + subsec.floor(precision)
114
+ end
115
+ end
116
+
117
+ # Restricted Ruby version due to a bug in `Time#ceil`
118
+ # See https://bugs.ruby-lang.org/issues/17025 for more details
119
+ if RUBY_VERSION <= "2.8"
120
+ remove_possible_method :ceil
121
+ def ceil(precision = 0)
122
+ change(nsec: 0) + subsec.ceil(precision)
123
+ end
124
+ end
125
+
83
126
  # Returns a new Time where one or more of the elements have been changed according
84
127
  # to the +options+ parameter. The time options (<tt>:hour</tt>, <tt>:min</tt>,
85
128
  # <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly, so if only
86
129
  # the hour is passed, then minute, sec, usec and nsec is set to 0. If the hour
87
- # and minute is passed, then sec, usec and nsec is set to 0. The +options+
88
- # parameter takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>,
89
- # <tt>:day</tt>, <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>
90
- # <tt>:nsec</tt>. Pass either <tt>:usec</tt> or <tt>:nsec</tt>, not both.
130
+ # and minute is passed, then sec, usec and nsec is set to 0. The +options+ parameter
131
+ # takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>,
132
+ # <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>,
133
+ # <tt>:offset</tt>. Pass either <tt>:usec</tt> or <tt>:nsec</tt>, not both.
91
134
  #
92
135
  # Time.new(2012, 8, 29, 22, 35, 0).change(day: 1) # => Time.new(2012, 8, 1, 22, 35, 0)
93
136
  # Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => Time.new(1981, 8, 1, 22, 35, 0)
94
137
  # Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => Time.new(1981, 8, 29, 0, 0, 0)
95
138
  def change(options)
96
- new_year = options.fetch(:year, year)
97
- new_month = options.fetch(:month, month)
98
- new_day = options.fetch(:day, day)
99
- new_hour = options.fetch(:hour, hour)
100
- new_min = options.fetch(:min, options[:hour] ? 0 : min)
101
- new_sec = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec)
139
+ new_year = options.fetch(:year, year)
140
+ new_month = options.fetch(:month, month)
141
+ new_day = options.fetch(:day, day)
142
+ new_hour = options.fetch(:hour, hour)
143
+ new_min = options.fetch(:min, options[:hour] ? 0 : min)
144
+ new_sec = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec)
145
+ new_offset = options.fetch(:offset, nil)
102
146
 
103
147
  if new_nsec = options[:nsec]
104
148
  raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
105
149
  new_usec = Rational(new_nsec, 1000)
106
150
  else
107
- new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
151
+ new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
108
152
  end
109
153
 
110
- if utc?
111
- ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
154
+ raise ArgumentError, "argument out of range" if new_usec >= 1000000
155
+
156
+ new_sec += Rational(new_usec, 1000000)
157
+
158
+ if new_offset
159
+ ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, new_offset)
160
+ elsif utc?
161
+ ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec)
112
162
  elsif zone
113
- ::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
163
+ ::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec)
114
164
  else
115
- raise ArgumentError, 'argument out of range' if new_usec >= 1000000
116
- ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec + (new_usec.to_r / 1000000), utc_offset)
165
+ ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, utc_offset)
117
166
  end
118
167
  end
119
168
 
@@ -139,9 +188,8 @@ class Time
139
188
  options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
140
189
  end
141
190
 
142
- d = to_date.advance(options)
143
- d = d.gregorian if d.julian?
144
- time_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
191
+ d = to_date.gregorian.advance(options)
192
+ time_advanced_by_date = change(year: d.year, month: d.month, day: d.day)
145
193
  seconds_to_advance = \
146
194
  options.fetch(:seconds, 0) +
147
195
  options.fetch(:minutes, 0) * 60 +
@@ -169,7 +217,7 @@ class Time
169
217
 
170
218
  # Returns a new Time representing the start of the day (0:00)
171
219
  def beginning_of_day
172
- change(:hour => 0)
220
+ change(hour: 0)
173
221
  end
174
222
  alias :midnight :beginning_of_day
175
223
  alias :at_midnight :beginning_of_day
@@ -177,7 +225,7 @@ class Time
177
225
 
178
226
  # Returns a new Time representing the middle of the day (12:00)
179
227
  def middle_of_day
180
- change(:hour => 12)
228
+ change(hour: 12)
181
229
  end
182
230
  alias :midday :middle_of_day
183
231
  alias :noon :middle_of_day
@@ -188,50 +236,45 @@ class Time
188
236
  # Returns a new Time representing the end of the day, 23:59:59.999999
189
237
  def end_of_day
190
238
  change(
191
- :hour => 23,
192
- :min => 59,
193
- :sec => 59,
194
- :usec => Rational(999999999, 1000)
239
+ hour: 23,
240
+ min: 59,
241
+ sec: 59,
242
+ usec: Rational(999999999, 1000)
195
243
  )
196
244
  end
197
245
  alias :at_end_of_day :end_of_day
198
246
 
199
247
  # Returns a new Time representing the start of the hour (x:00)
200
248
  def beginning_of_hour
201
- change(:min => 0)
249
+ change(min: 0)
202
250
  end
203
251
  alias :at_beginning_of_hour :beginning_of_hour
204
252
 
205
253
  # Returns a new Time representing the end of the hour, x:59:59.999999
206
254
  def end_of_hour
207
255
  change(
208
- :min => 59,
209
- :sec => 59,
210
- :usec => Rational(999999999, 1000)
256
+ min: 59,
257
+ sec: 59,
258
+ usec: Rational(999999999, 1000)
211
259
  )
212
260
  end
213
261
  alias :at_end_of_hour :end_of_hour
214
262
 
215
263
  # Returns a new Time representing the start of the minute (x:xx:00)
216
264
  def beginning_of_minute
217
- change(:sec => 0)
265
+ change(sec: 0)
218
266
  end
219
267
  alias :at_beginning_of_minute :beginning_of_minute
220
268
 
221
269
  # Returns a new Time representing the end of the minute, x:xx:59.999999
222
270
  def end_of_minute
223
271
  change(
224
- :sec => 59,
225
- :usec => Rational(999999999, 1000)
272
+ sec: 59,
273
+ usec: Rational(999999999, 1000)
226
274
  )
227
275
  end
228
276
  alias :at_end_of_minute :end_of_minute
229
277
 
230
- # Returns a Range representing the whole day of the current time.
231
- def all_day
232
- beginning_of_day..end_of_day
233
- end
234
-
235
278
  def plus_with_duration(other) #:nodoc:
236
279
  if ActiveSupport::Duration === other
237
280
  other.since(self)
@@ -287,4 +330,33 @@ class Time
287
330
  alias_method :eql_without_coercion, :eql?
288
331
  alias_method :eql?, :eql_with_coercion
289
332
 
333
+ # Returns a new time the specified number of days ago.
334
+ def prev_day(days = 1)
335
+ advance(days: -days)
336
+ end
337
+
338
+ # Returns a new time the specified number of days in the future.
339
+ def next_day(days = 1)
340
+ advance(days: days)
341
+ end
342
+
343
+ # Returns a new time the specified number of months ago.
344
+ def prev_month(months = 1)
345
+ advance(months: -months)
346
+ end
347
+
348
+ # Returns a new time the specified number of months in the future.
349
+ def next_month(months = 1)
350
+ advance(months: months)
351
+ end
352
+
353
+ # Returns a new time the specified number of years ago.
354
+ def prev_year(years = 1)
355
+ advance(years: -years)
356
+ end
357
+
358
+ # Returns a new time the specified number of years in the future.
359
+ def next_year(years = 1)
360
+ advance(years: years)
361
+ end
290
362
  end
@@ -1,5 +1,16 @@
1
- require 'active_support/core_ext/date_and_time/compatibility'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/date_and_time/compatibility"
4
+ require "active_support/core_ext/module/redefine_method"
2
5
 
3
6
  class Time
4
- prepend DateAndTime::Compatibility
7
+ include DateAndTime::Compatibility
8
+
9
+ silence_redefinition_of_method :to_time
10
+
11
+ # Either return +self+ or the time in the local system timezone depending
12
+ # on the setting of +ActiveSupport.to_time_preserves_timezone+.
13
+ def to_time
14
+ preserve_timezone ? self : getlocal
15
+ end
5
16
  end
@@ -1,24 +1,27 @@
1
- require 'active_support/inflector/methods'
2
- require 'active_support/values/time_zone'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/inflector/methods"
4
+ require "active_support/values/time_zone"
3
5
 
4
6
  class Time
5
7
  DATE_FORMATS = {
6
- :db => '%Y-%m-%d %H:%M:%S',
7
- :number => '%Y%m%d%H%M%S',
8
- :nsec => '%Y%m%d%H%M%S%9N',
9
- :usec => '%Y%m%d%H%M%S%6N',
10
- :time => '%H:%M',
11
- :short => '%d %b %H:%M',
12
- :long => '%B %d, %Y %H:%M',
13
- :long_ordinal => lambda { |time|
8
+ db: "%Y-%m-%d %H:%M:%S",
9
+ inspect: "%Y-%m-%d %H:%M:%S.%9N %z",
10
+ number: "%Y%m%d%H%M%S",
11
+ nsec: "%Y%m%d%H%M%S%9N",
12
+ usec: "%Y%m%d%H%M%S%6N",
13
+ time: "%H:%M",
14
+ short: "%d %b %H:%M",
15
+ long: "%B %d, %Y %H:%M",
16
+ long_ordinal: lambda { |time|
14
17
  day_format = ActiveSupport::Inflector.ordinalize(time.day)
15
18
  time.strftime("%B #{day_format}, %Y %H:%M")
16
19
  },
17
- :rfc822 => lambda { |time|
20
+ rfc822: lambda { |time|
18
21
  offset_format = time.formatted_offset(false)
19
22
  time.strftime("%a, %d %b %Y %H:%M:%S #{offset_format}")
20
23
  },
21
- :iso8601 => lambda { |time| time.iso8601 }
24
+ iso8601: lambda { |time| time.iso8601 }
22
25
  }
23
26
 
24
27
  # Converts to a formatted string. See DATE_FORMATS for built-in formats.
@@ -64,4 +67,7 @@ class Time
64
67
  def formatted_offset(colon = true, alternate_utc_string = nil)
65
68
  utc? && alternate_utc_string || ActiveSupport::TimeZone.seconds_to_utc_offset(utc_offset, colon)
66
69
  end
70
+
71
+ # Aliased to +xmlschema+ for compatibility with +DateTime+
72
+ alias_method :rfc3339, :xmlschema
67
73
  end
@@ -1,6 +1,8 @@
1
- require 'active_support/time_with_zone'
2
- require 'active_support/core_ext/time/acts_like'
3
- require 'active_support/core_ext/date_and_time/zones'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/time_with_zone"
4
+ require "active_support/core_ext/time/acts_like"
5
+ require "active_support/core_ext/date_and_time/zones"
4
6
 
5
7
  class Time
6
8
  include DateAndTime::Zones
@@ -53,10 +55,10 @@ class Time
53
55
  # end
54
56
  # end
55
57
  #
56
- # NOTE: This won't affect any <tt>ActiveSupport::TimeWithZone</tt>
57
- # objects that have already been created, e.g. any model timestamp
58
- # attributes that have been read before the block will remain in
59
- # the application's default timezone.
58
+ # NOTE: This won't affect any <tt>ActiveSupport::TimeWithZone</tt>
59
+ # objects that have already been created, e.g. any model timestamp
60
+ # attributes that have been read before the block will remain in
61
+ # the application's default timezone.
60
62
  def use_zone(time_zone)
61
63
  new_zone = find_zone!(time_zone)
62
64
  begin