activesupport 4.2.11.1 → 6.0.3.1

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

Potentially problematic release.


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

Files changed (263) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +399 -411
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +7 -7
  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 +48 -0
  8. data/lib/active_support/backtrace_cleaner.rb +34 -6
  9. data/lib/active_support/benchmarkable.rb +6 -4
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +58 -53
  12. data/lib/active_support/cache/mem_cache_store.rb +95 -91
  13. data/lib/active_support/cache/memory_store.rb +39 -36
  14. data/lib/active_support/cache/null_store.rb +11 -7
  15. data/lib/active_support/cache/redis_cache_store.rb +493 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +75 -42
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  18. data/lib/active_support/cache.rb +331 -217
  19. data/lib/active_support/callbacks.rb +650 -592
  20. data/lib/active_support/concern.rb +35 -6
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
  22. data/lib/active_support/concurrency/share_lock.rb +226 -0
  23. data/lib/active_support/configurable.rb +13 -14
  24. data/lib/active_support/core_ext/array/access.rb +41 -1
  25. data/lib/active_support/core_ext/array/conversions.rb +24 -20
  26. data/lib/active_support/core_ext/array/extract.rb +21 -0
  27. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  28. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  29. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  30. data/lib/active_support/core_ext/array/prepend_and_append.rb +4 -6
  31. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  32. data/lib/active_support/core_ext/array.rb +9 -6
  33. data/lib/active_support/core_ext/benchmark.rb +3 -1
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  35. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  36. data/lib/active_support/core_ext/class/attribute.rb +45 -31
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  38. data/lib/active_support/core_ext/class/subclasses.rb +20 -6
  39. data/lib/active_support/core_ext/class.rb +4 -3
  40. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  41. data/lib/active_support/core_ext/date/blank.rb +14 -0
  42. data/lib/active_support/core_ext/date/calculations.rb +17 -14
  43. data/lib/active_support/core_ext/date/conversions.rb +25 -23
  44. data/lib/active_support/core_ext/date/zones.rb +4 -2
  45. data/lib/active_support/core_ext/date.rb +6 -4
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +154 -65
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -3
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -13
  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 +14 -0
  51. data/lib/active_support/core_ext/date_time/calculations.rb +37 -19
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
  53. data/lib/active_support/core_ext/date_time/conversions.rb +16 -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 +114 -22
  58. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  59. data/lib/active_support/core_ext/file.rb +3 -1
  60. data/lib/active_support/core_ext/hash/compact.rb +4 -23
  61. data/lib/active_support/core_ext/hash/conversions.rb +62 -41
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  63. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  64. data/lib/active_support/core_ext/hash/except.rb +12 -9
  65. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  66. data/lib/active_support/core_ext/hash/keys.rb +19 -42
  67. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  68. data/lib/active_support/core_ext/hash/slice.rb +5 -27
  69. data/lib/active_support/core_ext/hash/transform_values.rb +4 -22
  70. data/lib/active_support/core_ext/hash.rb +10 -9
  71. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  72. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  73. data/lib/active_support/core_ext/integer/time.rb +11 -18
  74. data/lib/active_support/core_ext/integer.rb +5 -3
  75. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  76. data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  78. data/lib/active_support/core_ext/kernel.rb +5 -5
  79. data/lib/active_support/core_ext/load_error.rb +3 -22
  80. data/lib/active_support/core_ext/marshal.rb +8 -8
  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 +46 -46
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +144 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  87. data/lib/active_support/core_ext/module/delegation.rb +133 -30
  88. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  89. data/lib/active_support/core_ext/module/introspection.rb +44 -19
  90. data/lib/active_support/core_ext/module/reachable.rb +5 -7
  91. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/module.rb +13 -11
  94. data/lib/active_support/core_ext/name_error.rb +22 -2
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +129 -136
  97. data/lib/active_support/core_ext/numeric/inquiry.rb +5 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +35 -23
  99. data/lib/active_support/core_ext/numeric.rb +5 -3
  100. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  101. data/lib/active_support/core_ext/object/blank.rb +27 -3
  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 +13 -93
  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 +51 -20
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +10 -5
  110. data/lib/active_support/core_ext/object/try.rb +81 -23
  111. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  112. data/lib/active_support/core_ext/object.rb +14 -13
  113. data/lib/active_support/core_ext/range/compare_range.rb +76 -0
  114. data/lib/active_support/core_ext/range/conversions.rb +37 -15
  115. data/lib/active_support/core_ext/range/each.rb +18 -17
  116. data/lib/active_support/core_ext/range/include_range.rb +7 -21
  117. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  118. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  119. data/lib/active_support/core_ext/range.rb +7 -4
  120. data/lib/active_support/core_ext/regexp.rb +2 -0
  121. data/lib/active_support/core_ext/securerandom.rb +45 -0
  122. data/lib/active_support/core_ext/string/access.rb +16 -6
  123. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  124. data/lib/active_support/core_ext/string/conversions.rb +7 -4
  125. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  126. data/lib/active_support/core_ext/string/filters.rb +48 -6
  127. data/lib/active_support/core_ext/string/indent.rb +6 -4
  128. data/lib/active_support/core_ext/string/inflections.rb +66 -24
  129. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  130. data/lib/active_support/core_ext/string/multibyte.rb +16 -7
  131. data/lib/active_support/core_ext/string/output_safety.rb +93 -40
  132. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  133. data/lib/active_support/core_ext/string/strip.rb +6 -5
  134. data/lib/active_support/core_ext/string/zones.rb +4 -2
  135. data/lib/active_support/core_ext/string.rb +15 -13
  136. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  137. data/lib/active_support/core_ext/time/calculations.rb +115 -52
  138. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  139. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  140. data/lib/active_support/core_ext/time/zones.rb +41 -7
  141. data/lib/active_support/core_ext/time.rb +7 -6
  142. data/lib/active_support/core_ext/uri.rb +6 -7
  143. data/lib/active_support/core_ext.rb +3 -1
  144. data/lib/active_support/current_attributes.rb +203 -0
  145. data/lib/active_support/dependencies/autoload.rb +2 -0
  146. data/lib/active_support/dependencies/interlock.rb +57 -0
  147. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  148. data/lib/active_support/dependencies.rb +208 -166
  149. data/lib/active_support/deprecation/behaviors.rb +44 -11
  150. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  151. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  152. data/lib/active_support/deprecation/method_wrappers.rb +61 -21
  153. data/lib/active_support/deprecation/proxy_wrappers.rb +81 -30
  154. data/lib/active_support/deprecation/reporting.rb +32 -12
  155. data/lib/active_support/deprecation.rb +12 -9
  156. data/lib/active_support/descendants_tracker.rb +57 -9
  157. data/lib/active_support/digest.rb +20 -0
  158. data/lib/active_support/duration/iso8601_parser.rb +123 -0
  159. data/lib/active_support/duration/iso8601_serializer.rb +53 -0
  160. data/lib/active_support/duration.rb +315 -40
  161. data/lib/active_support/encrypted_configuration.rb +45 -0
  162. data/lib/active_support/encrypted_file.rb +100 -0
  163. data/lib/active_support/evented_file_update_checker.rb +234 -0
  164. data/lib/active_support/execution_wrapper.rb +129 -0
  165. data/lib/active_support/executor.rb +8 -0
  166. data/lib/active_support/file_update_checker.rb +62 -37
  167. data/lib/active_support/gem_version.rb +6 -4
  168. data/lib/active_support/gzip.rb +7 -5
  169. data/lib/active_support/hash_with_indifferent_access.rb +129 -30
  170. data/lib/active_support/i18n.rb +9 -6
  171. data/lib/active_support/i18n_railtie.rb +50 -14
  172. data/lib/active_support/inflections.rb +13 -11
  173. data/lib/active_support/inflector/inflections.rb +58 -13
  174. data/lib/active_support/inflector/methods.rb +159 -145
  175. data/lib/active_support/inflector/transliterate.rb +84 -34
  176. data/lib/active_support/inflector.rb +7 -5
  177. data/lib/active_support/json/decoding.rb +32 -30
  178. data/lib/active_support/json/encoding.rb +17 -60
  179. data/lib/active_support/json.rb +4 -2
  180. data/lib/active_support/key_generator.rb +11 -43
  181. data/lib/active_support/lazy_load_hooks.rb +53 -20
  182. data/lib/active_support/locale/en.rb +33 -0
  183. data/lib/active_support/locale/en.yml +2 -0
  184. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  185. data/lib/active_support/log_subscriber.rb +44 -19
  186. data/lib/active_support/logger.rb +9 -23
  187. data/lib/active_support/logger_silence.rb +32 -14
  188. data/lib/active_support/logger_thread_safe_level.rb +32 -8
  189. data/lib/active_support/message_encryptor.rb +166 -53
  190. data/lib/active_support/message_verifier.rb +149 -16
  191. data/lib/active_support/messages/metadata.rb +72 -0
  192. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  193. data/lib/active_support/messages/rotator.rb +56 -0
  194. data/lib/active_support/multibyte/chars.rb +56 -63
  195. data/lib/active_support/multibyte/unicode.rb +56 -290
  196. data/lib/active_support/multibyte.rb +4 -2
  197. data/lib/active_support/notifications/fanout.rb +109 -22
  198. data/lib/active_support/notifications/instrumenter.rb +107 -16
  199. data/lib/active_support/notifications.rb +51 -10
  200. data/lib/active_support/number_helper/number_converter.rb +16 -15
  201. data/lib/active_support/number_helper/number_to_currency_converter.rb +14 -15
  202. data/lib/active_support/number_helper/number_to_delimited_converter.rb +11 -4
  203. data/lib/active_support/number_helper/number_to_human_converter.rb +13 -10
  204. data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -9
  205. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  206. data/lib/active_support/number_helper/number_to_phone_converter.rb +15 -5
  207. data/lib/active_support/number_helper/number_to_rounded_converter.rb +25 -57
  208. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  209. data/lib/active_support/number_helper.rb +105 -68
  210. data/lib/active_support/option_merger.rb +24 -4
  211. data/lib/active_support/ordered_hash.rb +7 -5
  212. data/lib/active_support/ordered_options.rb +27 -5
  213. data/lib/active_support/parameter_filter.rb +128 -0
  214. data/lib/active_support/per_thread_registry.rb +9 -4
  215. data/lib/active_support/proxy_object.rb +2 -0
  216. data/lib/active_support/rails.rb +10 -8
  217. data/lib/active_support/railtie.rb +43 -9
  218. data/lib/active_support/reloader.rb +130 -0
  219. data/lib/active_support/rescuable.rb +108 -53
  220. data/lib/active_support/security_utils.rb +15 -11
  221. data/lib/active_support/string_inquirer.rb +11 -4
  222. data/lib/active_support/subscriber.rb +74 -30
  223. data/lib/active_support/tagged_logging.rb +25 -13
  224. data/lib/active_support/test_case.rb +107 -44
  225. data/lib/active_support/testing/assertions.rb +151 -20
  226. data/lib/active_support/testing/autorun.rb +4 -2
  227. data/lib/active_support/testing/constant_lookup.rb +2 -1
  228. data/lib/active_support/testing/declarative.rb +3 -1
  229. data/lib/active_support/testing/deprecation.rb +13 -10
  230. data/lib/active_support/testing/file_fixtures.rb +38 -0
  231. data/lib/active_support/testing/isolation.rb +35 -26
  232. data/lib/active_support/testing/method_call_assertions.rb +70 -0
  233. data/lib/active_support/testing/parallelization.rb +134 -0
  234. data/lib/active_support/testing/setup_and_teardown.rb +13 -8
  235. data/lib/active_support/testing/stream.rb +43 -0
  236. data/lib/active_support/testing/tagged_logging.rb +3 -1
  237. data/lib/active_support/testing/time_helpers.rb +84 -20
  238. data/lib/active_support/time.rb +14 -12
  239. data/lib/active_support/time_with_zone.rb +179 -39
  240. data/lib/active_support/values/time_zone.rb +203 -63
  241. data/lib/active_support/version.rb +3 -1
  242. data/lib/active_support/xml_mini/jdom.rb +116 -115
  243. data/lib/active_support/xml_mini/libxml.rb +16 -13
  244. data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
  245. data/lib/active_support/xml_mini/nokogiri.rb +14 -12
  246. data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
  247. data/lib/active_support/xml_mini/rexml.rb +11 -9
  248. data/lib/active_support/xml_mini.rb +38 -46
  249. data/lib/active_support.rb +13 -11
  250. metadata +84 -26
  251. data/lib/active_support/concurrency/latch.rb +0 -27
  252. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
  253. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  254. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  255. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  256. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  257. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
  258. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  259. data/lib/active_support/core_ext/object/itself.rb +0 -15
  260. data/lib/active_support/core_ext/struct.rb +0 -6
  261. data/lib/active_support/core_ext/thread.rb +0 -86
  262. data/lib/active_support/core_ext/time/marshal.rb +0 -30
  263. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,34 +1,32 @@
1
- require 'erb'
2
- require 'active_support/core_ext/kernel/singleton_class'
3
- require 'active_support/deprecation'
1
+ # frozen_string_literal: true
2
+
3
+ require "erb"
4
+ require "active_support/core_ext/kernel/singleton_class"
5
+ require "active_support/core_ext/module/redefine_method"
6
+ require "active_support/multibyte/unicode"
4
7
 
5
8
  class ERB
6
9
  module Util
7
- HTML_ESCAPE = { '&' => '&amp;', '>' => '&gt;', '<' => '&lt;', '"' => '&quot;', "'" => '&#39;' }
8
- JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003e', '<' => '\u003c', "\u2028" => '\u2028', "\u2029" => '\u2029' }
9
- HTML_ESCAPE_REGEXP = /[&"'><]/
10
+ HTML_ESCAPE = { "&" => "&amp;", ">" => "&gt;", "<" => "&lt;", '"' => "&quot;", "'" => "&#39;" }
11
+ JSON_ESCAPE = { "&" => '\u0026', ">" => '\u003e', "<" => '\u003c', "\u2028" => '\u2028', "\u2029" => '\u2029' }
10
12
  HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+)|(#[xX][\dA-Fa-f]+));)/
11
13
  JSON_ESCAPE_REGEXP = /[\u2028\u2029&><]/u
12
14
 
13
15
  # A utility method for escaping HTML tag characters.
14
16
  # This method is also aliased as <tt>h</tt>.
15
17
  #
16
- # In your ERB templates, use this method to escape any unsafe content. For example:
17
- # <%=h @person.name %>
18
- #
19
18
  # puts html_escape('is a > 0 & a < 10?')
20
19
  # # => is a &gt; 0 &amp; a &lt; 10?
21
20
  def html_escape(s)
22
21
  unwrapped_html_escape(s).html_safe
23
22
  end
24
23
 
25
- # Aliasing twice issues a warning "discarding old...". Remove first to avoid it.
26
- remove_method(:h)
24
+ silence_redefinition_of_method :h
27
25
  alias h html_escape
28
26
 
29
27
  module_function :h
30
28
 
31
- singleton_class.send(:remove_method, :html_escape)
29
+ singleton_class.silence_redefinition_of_method :html_escape
32
30
  module_function :html_escape
33
31
 
34
32
  # HTML escapes strings but doesn't wrap them with an ActiveSupport::SafeBuffer.
@@ -38,7 +36,7 @@ class ERB
38
36
  if s.html_safe?
39
37
  s
40
38
  else
41
- s.gsub(HTML_ESCAPE_REGEXP, HTML_ESCAPE)
39
+ CGI.escapeHTML(ActiveSupport::Multibyte::Unicode.tidy_bytes(s))
42
40
  end
43
41
  end
44
42
  module_function :unwrapped_html_escape
@@ -51,7 +49,7 @@ class ERB
51
49
  # html_escape_once('&lt;&lt; Accept & Checkout')
52
50
  # # => "&lt;&lt; Accept &amp; Checkout"
53
51
  def html_escape_once(s)
54
- result = s.to_s.gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE)
52
+ result = ActiveSupport::Multibyte::Unicode.tidy_bytes(s.to_s).gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE)
55
53
  s.html_safe? ? result.html_safe : result
56
54
  end
57
55
 
@@ -86,6 +84,11 @@ class ERB
86
84
  # automatically flag the result as HTML safe, since the raw value is unsafe to
87
85
  # use inside HTML attributes.
88
86
  #
87
+ # If your JSON is being used downstream for insertion into the DOM, be aware of
88
+ # whether or not it is being inserted via +html()+. Most jQuery plugins do this.
89
+ # If that is the case, be sure to +html_escape+ or +sanitize+ any user-generated
90
+ # content returned by your JSON.
91
+ #
89
92
  # If you need to output JSON elsewhere in your HTML, you can just do something
90
93
  # like this, as any unsafe characters (including quotation marks) will be
91
94
  # automatically escaped for you:
@@ -131,34 +134,34 @@ end
131
134
  module ActiveSupport #:nodoc:
132
135
  class SafeBuffer < String
133
136
  UNSAFE_STRING_METHODS = %w(
134
- capitalize chomp chop delete downcase gsub lstrip next reverse rstrip
135
- slice squeeze strip sub succ swapcase tr tr_s upcase
137
+ capitalize chomp chop delete delete_prefix delete_suffix
138
+ downcase lstrip next reverse rstrip slice squeeze strip
139
+ succ swapcase tr tr_s unicode_normalize upcase
136
140
  )
137
141
 
142
+ UNSAFE_STRING_METHODS_WITH_BACKREF = %w(gsub sub)
143
+
138
144
  alias_method :original_concat, :concat
139
145
  private :original_concat
140
146
 
147
+ # Raised when <tt>ActiveSupport::SafeBuffer#safe_concat</tt> is called on unsafe buffers.
141
148
  class SafeConcatError < StandardError
142
149
  def initialize
143
- super 'Could not concatenate to the buffer because it is not html safe.'
150
+ super "Could not concatenate to the buffer because it is not html safe."
144
151
  end
145
152
  end
146
153
 
147
154
  def [](*args)
148
- if args.size < 2
149
- super
150
- else
151
- if html_safe?
152
- new_safe_buffer = super
153
-
154
- if new_safe_buffer
155
- new_safe_buffer.instance_variable_set :@html_safe, true
156
- end
155
+ if html_safe?
156
+ new_safe_buffer = super
157
157
 
158
- new_safe_buffer
159
- else
160
- to_str[*args]
158
+ if new_safe_buffer
159
+ new_safe_buffer.instance_variable_set :@html_safe, true
161
160
  end
161
+
162
+ new_safe_buffer
163
+ else
164
+ to_str[*args]
162
165
  end
163
166
  end
164
167
 
@@ -167,7 +170,7 @@ module ActiveSupport #:nodoc:
167
170
  original_concat(value)
168
171
  end
169
172
 
170
- def initialize(*)
173
+ def initialize(str = "")
171
174
  @html_safe = true
172
175
  super
173
176
  end
@@ -186,23 +189,40 @@ module ActiveSupport #:nodoc:
186
189
  end
187
190
  alias << concat
188
191
 
192
+ def insert(index, value)
193
+ super(index, html_escape_interpolated_argument(value))
194
+ end
195
+
189
196
  def prepend(value)
190
197
  super(html_escape_interpolated_argument(value))
191
198
  end
192
199
 
193
- def prepend!(value)
194
- ActiveSupport::Deprecation.deprecation_warning "ActiveSupport::SafeBuffer#prepend!", :prepend
195
- prepend value
200
+ def replace(value)
201
+ super(html_escape_interpolated_argument(value))
202
+ end
203
+
204
+ def []=(*args)
205
+ if args.count == 3
206
+ super(args[0], args[1], html_escape_interpolated_argument(args[2]))
207
+ else
208
+ super(args[0], html_escape_interpolated_argument(args[1]))
209
+ end
196
210
  end
197
211
 
198
212
  def +(other)
199
213
  dup.concat(other)
200
214
  end
201
215
 
216
+ def *(*)
217
+ new_safe_buffer = super
218
+ new_safe_buffer.instance_variable_set(:@html_safe, @html_safe)
219
+ new_safe_buffer
220
+ end
221
+
202
222
  def %(args)
203
223
  case args
204
224
  when Hash
205
- escaped_args = Hash[args.map { |k,arg| [k, html_escape_interpolated_argument(arg)] }]
225
+ escaped_args = Hash[args.map { |k, arg| [k, html_escape_interpolated_argument(arg)] }]
206
226
  else
207
227
  escaped_args = Array(args).map { |arg| html_escape_interpolated_argument(arg) }
208
228
  end
@@ -241,20 +261,53 @@ module ActiveSupport #:nodoc:
241
261
  end
242
262
  end
243
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
+
244
293
  private
294
+ def html_escape_interpolated_argument(arg)
295
+ (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
296
+ end
245
297
 
246
- def html_escape_interpolated_argument(arg)
247
- (!html_safe? || arg.html_safe?) ? arg :
248
- arg.to_s.gsub(ERB::Util::HTML_ESCAPE_REGEXP, ERB::Util::HTML_ESCAPE)
249
- 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
250
303
  end
251
304
  end
252
305
 
253
306
  class String
254
307
  # Marks a string as trusted safe. It will be inserted into HTML with no
255
- # additional escaping performed. It is your responsibilty to ensure that the
308
+ # additional escaping performed. It is your responsibility to ensure that the
256
309
  # string contains no malicious content. This method is equivalent to the
257
- # `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
258
311
  # this method. It should never be called on user input.
259
312
  def html_safe
260
313
  ActiveSupport::SafeBuffer.new(self)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
4
  alias_method :starts_with?, :start_with?
3
5
  alias_method :ends_with?, :end_with?
@@ -1,4 +1,4 @@
1
- require 'active_support/core_ext/object/try'
1
+ # frozen_string_literal: true
2
2
 
3
3
  class String
4
4
  # Strips indentation in heredocs.
@@ -17,10 +17,11 @@ class String
17
17
  #
18
18
  # the user would see the usage message aligned against the left margin.
19
19
  #
20
- # Technically, it looks for the least indented line in the whole string, and removes
21
- # that amount of leading whitespace.
20
+ # Technically, it looks for the least indented non-empty line
21
+ # in the whole string, and removes that amount of leading whitespace.
22
22
  def strip_heredoc
23
- indent = scan(/^[ \t]*(?=\S)/).min.try(:size) || 0
24
- gsub(/^[ \t]{#{indent}}/, '')
23
+ gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "").tap do |stripped|
24
+ stripped.freeze if frozen?
25
+ end
25
26
  end
26
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"
@@ -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,11 @@
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"
7
9
 
8
10
  class Time
9
11
  include DateAndTime::Calculations
@@ -16,9 +18,9 @@ class Time
16
18
  super || (self == Time && other.is_a?(ActiveSupport::TimeWithZone))
17
19
  end
18
20
 
19
- # Return the number of days in the given month.
21
+ # Returns the number of days in the given month.
20
22
  # If no year is specified, it will use the current year.
21
- def days_in_month(month, year = now.year)
23
+ def days_in_month(month, year = current.year)
22
24
  if month == 2 && ::Date.gregorian_leap?(year)
23
25
  29
24
26
  else
@@ -26,6 +28,12 @@ class Time
26
28
  end
27
29
  end
28
30
 
31
+ # Returns the number of days in the given year.
32
+ # If no year is specified, it will use the current year.
33
+ def days_in_year(year = current.year)
34
+ days_in_month(2, year) + 337
35
+ end
36
+
29
37
  # Returns <tt>Time.zone.now</tt> when <tt>Time.zone</tt> or <tt>config.time_zone</tt> are set, otherwise just returns <tt>Time.now</tt>.
30
38
  def current
31
39
  ::Time.zone ? ::Time.zone.now : ::Time.now
@@ -47,11 +55,38 @@ class Time
47
55
  end
48
56
  alias_method :at_without_coercion, :at
49
57
  alias_method :at, :at_with_coercion
58
+
59
+ # Creates a +Time+ instance from an RFC 3339 string.
60
+ #
61
+ # Time.rfc3339('1999-12-31T14:00:00-10:00') # => 2000-01-01 00:00:00 -1000
62
+ #
63
+ # If the time or offset components are missing then an +ArgumentError+ will be raised.
64
+ #
65
+ # Time.rfc3339('1999-12-31') # => ArgumentError: invalid date
66
+ def rfc3339(str)
67
+ parts = Date._rfc3339(str)
68
+
69
+ raise ArgumentError, "invalid date" if parts.empty?
70
+
71
+ Time.new(
72
+ parts.fetch(:year),
73
+ parts.fetch(:mon),
74
+ parts.fetch(:mday),
75
+ parts.fetch(:hour),
76
+ parts.fetch(:min),
77
+ parts.fetch(:sec) + parts.fetch(:sec_fraction, 0),
78
+ parts.fetch(:offset)
79
+ )
80
+ end
50
81
  end
51
82
 
52
- # Seconds since midnight: Time.now.seconds_since_midnight
83
+ # Returns the number of seconds since 00:00:00.
84
+ #
85
+ # Time.new(2012, 8, 29, 0, 0, 0).seconds_since_midnight # => 0.0
86
+ # Time.new(2012, 8, 29, 12, 34, 56).seconds_since_midnight # => 45296.0
87
+ # Time.new(2012, 8, 29, 23, 59, 59).seconds_since_midnight # => 86399.0
53
88
  def seconds_since_midnight
54
- to_i - change(:hour => 0).to_i + (usec / 1.0e+6)
89
+ to_i - change(hour: 0).to_i + (usec / 1.0e+6)
55
90
  end
56
91
 
57
92
  # Returns the number of seconds until 23:59:59.
@@ -74,36 +109,42 @@ class Time
74
109
  # to the +options+ parameter. The time options (<tt>:hour</tt>, <tt>:min</tt>,
75
110
  # <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly, so if only
76
111
  # the hour is passed, then minute, sec, usec and nsec is set to 0. If the hour
77
- # and minute is passed, then sec, usec and nsec is set to 0. The +options+
78
- # parameter takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>,
79
- # <tt>:day</tt>, <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>
80
- # <tt>:nsec</tt>. Path either <tt>:usec</tt> or <tt>:nsec</tt>, not both.
112
+ # and minute is passed, then sec, usec and nsec is set to 0. The +options+ parameter
113
+ # takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>,
114
+ # <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>,
115
+ # <tt>:offset</tt>. Pass either <tt>:usec</tt> or <tt>:nsec</tt>, not both.
81
116
  #
82
117
  # Time.new(2012, 8, 29, 22, 35, 0).change(day: 1) # => Time.new(2012, 8, 1, 22, 35, 0)
83
118
  # Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => Time.new(1981, 8, 1, 22, 35, 0)
84
119
  # Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => Time.new(1981, 8, 29, 0, 0, 0)
85
120
  def change(options)
86
- new_year = options.fetch(:year, year)
87
- new_month = options.fetch(:month, month)
88
- new_day = options.fetch(:day, day)
89
- new_hour = options.fetch(:hour, hour)
90
- new_min = options.fetch(:min, options[:hour] ? 0 : min)
91
- new_sec = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec)
121
+ new_year = options.fetch(:year, year)
122
+ new_month = options.fetch(:month, month)
123
+ new_day = options.fetch(:day, day)
124
+ new_hour = options.fetch(:hour, hour)
125
+ new_min = options.fetch(:min, options[:hour] ? 0 : min)
126
+ new_sec = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec)
127
+ new_offset = options.fetch(:offset, nil)
92
128
 
93
129
  if new_nsec = options[:nsec]
94
130
  raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
95
131
  new_usec = Rational(new_nsec, 1000)
96
132
  else
97
- new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
133
+ new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
98
134
  end
99
135
 
100
- if utc?
101
- ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
136
+ raise ArgumentError, "argument out of range" if new_usec >= 1000000
137
+
138
+ new_sec += Rational(new_usec, 1000000)
139
+
140
+ if new_offset
141
+ ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, new_offset)
142
+ elsif utc?
143
+ ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec)
102
144
  elsif zone
103
- ::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
145
+ ::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec)
104
146
  else
105
- raise ArgumentError, 'argument out of range' if new_usec >= 1000000
106
- ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec + (new_usec.to_r / 1000000), utc_offset)
147
+ ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, utc_offset)
107
148
  end
108
149
  end
109
150
 
@@ -129,9 +170,8 @@ class Time
129
170
  options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
130
171
  end
131
172
 
132
- d = to_date.advance(options)
133
- d = d.gregorian if d.julian?
134
- time_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
173
+ d = to_date.gregorian.advance(options)
174
+ time_advanced_by_date = change(year: d.year, month: d.month, day: d.day)
135
175
  seconds_to_advance = \
136
176
  options.fetch(:seconds, 0) +
137
177
  options.fetch(:minutes, 0) * 60 +
@@ -159,8 +199,7 @@ class Time
159
199
 
160
200
  # Returns a new Time representing the start of the day (0:00)
161
201
  def beginning_of_day
162
- #(self - seconds_since_midnight).change(usec: 0)
163
- change(:hour => 0)
202
+ change(hour: 0)
164
203
  end
165
204
  alias :midnight :beginning_of_day
166
205
  alias :at_midnight :beginning_of_day
@@ -168,7 +207,7 @@ class Time
168
207
 
169
208
  # Returns a new Time representing the middle of the day (12:00)
170
209
  def middle_of_day
171
- change(:hour => 12)
210
+ change(hour: 12)
172
211
  end
173
212
  alias :midday :middle_of_day
174
213
  alias :noon :middle_of_day
@@ -176,53 +215,48 @@ class Time
176
215
  alias :at_noon :middle_of_day
177
216
  alias :at_middle_of_day :middle_of_day
178
217
 
179
- # Returns a new Time representing the end of the day, 23:59:59.999999 (.999999999 in ruby1.9)
218
+ # Returns a new Time representing the end of the day, 23:59:59.999999
180
219
  def end_of_day
181
220
  change(
182
- :hour => 23,
183
- :min => 59,
184
- :sec => 59,
185
- :usec => Rational(999999999, 1000)
221
+ hour: 23,
222
+ min: 59,
223
+ sec: 59,
224
+ usec: Rational(999999999, 1000)
186
225
  )
187
226
  end
188
227
  alias :at_end_of_day :end_of_day
189
228
 
190
229
  # Returns a new Time representing the start of the hour (x:00)
191
230
  def beginning_of_hour
192
- change(:min => 0)
231
+ change(min: 0)
193
232
  end
194
233
  alias :at_beginning_of_hour :beginning_of_hour
195
234
 
196
- # Returns a new Time representing the end of the hour, x:59:59.999999 (.999999999 in ruby1.9)
235
+ # Returns a new Time representing the end of the hour, x:59:59.999999
197
236
  def end_of_hour
198
237
  change(
199
- :min => 59,
200
- :sec => 59,
201
- :usec => Rational(999999999, 1000)
238
+ min: 59,
239
+ sec: 59,
240
+ usec: Rational(999999999, 1000)
202
241
  )
203
242
  end
204
243
  alias :at_end_of_hour :end_of_hour
205
244
 
206
245
  # Returns a new Time representing the start of the minute (x:xx:00)
207
246
  def beginning_of_minute
208
- change(:sec => 0)
247
+ change(sec: 0)
209
248
  end
210
249
  alias :at_beginning_of_minute :beginning_of_minute
211
250
 
212
- # Returns a new Time representing the end of the minute, x:xx:59.999999 (.999999999 in ruby1.9)
251
+ # Returns a new Time representing the end of the minute, x:xx:59.999999
213
252
  def end_of_minute
214
253
  change(
215
- :sec => 59,
216
- :usec => Rational(999999999, 1000)
254
+ sec: 59,
255
+ usec: Rational(999999999, 1000)
217
256
  )
218
257
  end
219
258
  alias :at_end_of_minute :end_of_minute
220
259
 
221
- # Returns a Range representing the whole day of the current time.
222
- def all_day
223
- beginning_of_day..end_of_day
224
- end
225
-
226
260
  def plus_with_duration(other) #:nodoc:
227
261
  if ActiveSupport::Duration === other
228
262
  other.since(self)
@@ -256,7 +290,7 @@ class Time
256
290
  # Layers additional behavior on Time#<=> so that DateTime and ActiveSupport::TimeWithZone instances
257
291
  # can be chronologically compared with a Time
258
292
  def compare_with_coercion(other)
259
- # we're avoiding Time#to_datetime cause it's expensive
293
+ # we're avoiding Time#to_datetime and Time#to_time because they're expensive
260
294
  if other.class == Time
261
295
  compare_without_coercion(other)
262
296
  elsif other.is_a?(Time)
@@ -278,4 +312,33 @@ class Time
278
312
  alias_method :eql_without_coercion, :eql?
279
313
  alias_method :eql?, :eql_with_coercion
280
314
 
315
+ # Returns a new time the specified number of days ago.
316
+ def prev_day(days = 1)
317
+ advance(days: -days)
318
+ end
319
+
320
+ # Returns a new time the specified number of days in the future.
321
+ def next_day(days = 1)
322
+ advance(days: days)
323
+ end
324
+
325
+ # Returns a new time the specified number of months ago.
326
+ def prev_month(months = 1)
327
+ advance(months: -months)
328
+ end
329
+
330
+ # Returns a new time the specified number of months in the future.
331
+ def next_month(months = 1)
332
+ advance(months: months)
333
+ end
334
+
335
+ # Returns a new time the specified number of years ago.
336
+ def prev_year(years = 1)
337
+ advance(years: -years)
338
+ end
339
+
340
+ # Returns a new time the specified number of years in the future.
341
+ def next_year(years = 1)
342
+ advance(years: years)
343
+ end
281
344
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/date_and_time/compatibility"
2
- require "active_support/core_ext/module/remove_method"
4
+ require "active_support/core_ext/module/redefine_method"
3
5
 
4
6
  class Time
5
7
  include DateAndTime::Compatibility
6
8
 
7
- remove_possible_method :to_time
9
+ silence_redefinition_of_method :to_time
8
10
 
9
11
  # Either return +self+ or the time in the local system timezone depending
10
12
  # on the setting of +ActiveSupport.to_time_preserves_timezone+.