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
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
- # If you pass a single Fixnum, returns a substring of one character at that
4
+ # If you pass a single integer, returns a substring of one character at that
3
5
  # position. The first character of the string is at position 0, the next at
4
6
  # position 1, and so on. If a range is supplied, a substring containing
5
7
  # characters at offsets given by the range is returned. In both cases, if an
6
- # offset is negative, it is counted from the end of the string. Returns nil
8
+ # offset is negative, it is counted from the end of the string. Returns +nil+
7
9
  # if the initial offset falls outside the string. Returns an empty string if
8
10
  # the beginning of the range is greater than the end of the string.
9
11
  #
@@ -17,7 +19,7 @@ class String
17
19
  #
18
20
  # If a Regexp is given, the matching portion of the string is returned.
19
21
  # If a String is given, that given string is returned if it occurs in
20
- # the string. In both cases, nil is returned if there is no match.
22
+ # the string. In both cases, +nil+ is returned if there is no match.
21
23
  #
22
24
  # str = "hello"
23
25
  # str.at(/lo/) # => "lo"
@@ -74,9 +76,9 @@ class String
74
76
  # str.first(6) # => "hello"
75
77
  def first(limit = 1)
76
78
  if limit == 0
77
- ''
79
+ ""
78
80
  elsif limit >= size
79
- self.dup
81
+ dup
80
82
  else
81
83
  to(limit - 1)
82
84
  end
@@ -94,9 +96,9 @@ class String
94
96
  # str.last(6) # => "hello"
95
97
  def last(limit = 1)
96
98
  if limit == 0
97
- ''
99
+ ""
98
100
  elsif limit >= size
99
- self.dup
101
+ dup
100
102
  else
101
103
  from(-limit)
102
104
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
- # Enable more predictable duck-typing on String-like classes. See <tt>Object#acts_like?</tt>.
4
+ # Enables more predictable duck-typing on String-like classes. See <tt>Object#acts_like?</tt>.
3
5
  def acts_like_string?
4
6
  true
5
7
  end
@@ -1,5 +1,7 @@
1
- require 'date'
2
- require 'active_support/core_ext/time/calculations'
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+ require "active_support/core_ext/time/calculations"
3
5
 
4
6
  class String
5
7
  # Converts a string to a Time value.
@@ -14,11 +16,12 @@ class String
14
16
  # "06:12".to_time # => 2012-12-13 06:12:00 +0100
15
17
  # "2012-12-13 06:12".to_time # => 2012-12-13 06:12:00 +0100
16
18
  # "2012-12-13T06:12".to_time # => 2012-12-13 06:12:00 +0100
17
- # "2012-12-13T06:12".to_time(:utc) # => 2012-12-13 05:12:00 UTC
19
+ # "2012-12-13T06:12".to_time(:utc) # => 2012-12-13 06:12:00 UTC
18
20
  # "12/13/2012".to_time # => ArgumentError: argument out of range
19
21
  def to_time(form = :local)
20
22
  parts = Date._parse(self, false)
21
- return if parts.empty?
23
+ used_keys = %i(year mon mday hour min sec sec_fraction offset)
24
+ return if (parts.keys & used_keys).empty?
22
25
 
23
26
  now = Time.now
24
27
  time = Time.new(
@@ -31,7 +34,7 @@ class String
31
34
  parts.fetch(:offset, form == :utc ? 0 : nil)
32
35
  )
33
36
 
34
- form == :utc ? time.utc : time.getlocal
37
+ form == :utc ? time.utc : time.to_time
35
38
  end
36
39
 
37
40
  # Converts a string to a Date value.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
4
  # The inverse of <tt>String#include?</tt>. Returns true if the string
3
5
  # does not include the other string.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
4
  # Returns the string, first removing all whitespace on both ends of
3
5
  # the string, and then changing remaining consecutive whitespace
@@ -17,15 +19,15 @@ class String
17
19
  # str.squish! # => "foo bar boo"
18
20
  # str # => "foo bar boo"
19
21
  def squish!
20
- gsub!(/\A[[:space:]]+/, '')
21
- gsub!(/[[:space:]]+\z/, '')
22
- gsub!(/[[:space:]]+/, ' ')
22
+ gsub!(/[[:space:]]+/, " ")
23
+ strip!
23
24
  self
24
25
  end
25
26
 
26
27
  # Returns a new string with all occurrences of the patterns removed.
27
28
  # str = "foo bar test"
28
29
  # str.remove(" test") # => "foo bar"
30
+ # str.remove(" test", /bar/) # => "foo "
29
31
  # str # => "foo bar test"
30
32
  def remove(*patterns)
31
33
  dup.remove!(*patterns)
@@ -33,8 +35,8 @@ class String
33
35
 
34
36
  # Alters the string by removing all occurrences of the patterns.
35
37
  # str = "foo bar test"
36
- # str.remove!(" test") # => "foo bar"
37
- # str # => "foo bar"
38
+ # str.remove!(" test", /bar/) # => "foo "
39
+ # str # => "foo "
38
40
  def remove!(*patterns)
39
41
  patterns.each do |pattern|
40
42
  gsub! pattern, ""
@@ -64,7 +66,7 @@ class String
64
66
  def truncate(truncate_at, options = {})
65
67
  return dup unless length > truncate_at
66
68
 
67
- omission = options[:omission] || '...'
69
+ omission = options[:omission] || "..."
68
70
  length_with_room_for_omission = truncate_at - omission.length
69
71
  stop = \
70
72
  if options[:separator]
@@ -93,8 +95,8 @@ class String
93
95
  def truncate_words(words_count, options = {})
94
96
  sep = options[:separator] || /\s+/
95
97
  sep = Regexp.escape(sep.to_s) unless Regexp === sep
96
- if self =~ /\A((?:.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/m
97
- $1 + (options[:omission] || '...')
98
+ if self =~ /\A((?>.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/m
99
+ $1 + (options[:omission] || "...")
98
100
  else
99
101
  dup
100
102
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
4
  # Same as +indent+, except it indents the receiver in-place.
3
5
  #
4
6
  # Returns the indented string, or +nil+ if there was nothing to indent.
5
- def indent!(amount, indent_string=nil, indent_empty_lines=false)
6
- indent_string = indent_string || self[/^[ \t]/] || ' '
7
+ def indent!(amount, indent_string = nil, indent_empty_lines = false)
8
+ indent_string = indent_string || self[/^[ \t]/] || " "
7
9
  re = indent_empty_lines ? /^/ : /^(?!$)/
8
10
  gsub!(re, indent_string * amount)
9
11
  end
@@ -37,7 +39,7 @@ class String
37
39
  # "foo\n\nbar".indent(2) # => " foo\n\n bar"
38
40
  # "foo\n\nbar".indent(2, nil, true) # => " foo\n \n bar"
39
41
  #
40
- def indent(amount, indent_string=nil, indent_empty_lines=false)
41
- dup.tap {|_| _.indent!(amount, indent_string, indent_empty_lines)}
42
+ def indent(amount, indent_string = nil, indent_empty_lines = false)
43
+ dup.tap { |_| _.indent!(amount, indent_string, indent_empty_lines) }
42
44
  end
43
45
  end
@@ -1,5 +1,7 @@
1
- require 'active_support/inflector/methods'
2
- require 'active_support/inflector/transliterate'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/inflector/methods"
4
+ require "active_support/inflector/transliterate"
3
5
 
4
6
  # String inflections define new methods on the String class to transform names for different purposes.
5
7
  # For instance, you can figure out the name of a table from the name of a class.
@@ -31,7 +33,7 @@ class String
31
33
  def pluralize(count = nil, locale = :en)
32
34
  locale = count if count.is_a?(Symbol)
33
35
  if count == 1
34
- self.dup
36
+ dup
35
37
  else
36
38
  ActiveSupport::Inflector.pluralize(self, locale)
37
39
  end
@@ -67,7 +69,7 @@ class String
67
69
  end
68
70
 
69
71
  # +safe_constantize+ tries to find a declared constant with the name specified
70
- # in the string. It returns nil when the name is not in CamelCase
72
+ # in the string. It returns +nil+ when the name is not in CamelCase
71
73
  # or is not initialized. See ActiveSupport::Inflector.safe_constantize
72
74
  #
73
75
  # 'Module'.safe_constantize # => Module
@@ -92,6 +94,8 @@ class String
92
94
  ActiveSupport::Inflector.camelize(self, true)
93
95
  when :lower
94
96
  ActiveSupport::Inflector.camelize(self, false)
97
+ else
98
+ raise ArgumentError, "Invalid option, use either :upper or :lower."
95
99
  end
96
100
  end
97
101
  alias_method :camelcase, :camelize
@@ -100,12 +104,17 @@ class String
100
104
  # a nicer looking title. +titleize+ is meant for creating pretty output. It is not
101
105
  # used in the Rails internals.
102
106
  #
107
+ # The trailing '_id','Id'.. can be kept and capitalized by setting the
108
+ # optional parameter +keep_id_suffix+ to true.
109
+ # By default, this parameter is false.
110
+ #
103
111
  # +titleize+ is also aliased as +titlecase+.
104
112
  #
105
- # 'man from the boondocks'.titleize # => "Man From The Boondocks"
106
- # 'x-men: the last stand'.titleize # => "X Men: The Last Stand"
107
- def titleize
108
- ActiveSupport::Inflector.titleize(self)
113
+ # 'man from the boondocks'.titleize # => "Man From The Boondocks"
114
+ # 'x-men: the last stand'.titleize # => "X Men: The Last Stand"
115
+ # 'string_ending_with_id'.titleize(keep_id_suffix: true) # => "String Ending With Id"
116
+ def titleize(keep_id_suffix: false)
117
+ ActiveSupport::Inflector.titleize(self, keep_id_suffix: keep_id_suffix)
109
118
  end
110
119
  alias_method :titlecase, :titleize
111
120
 
@@ -128,10 +137,10 @@ class String
128
137
 
129
138
  # Removes the module part from the constant expression in the string.
130
139
  #
131
- # 'ActiveRecord::CoreExtensions::String::Inflections'.demodulize # => "Inflections"
132
- # 'Inflections'.demodulize # => "Inflections"
133
- # '::Inflections'.demodulize # => "Inflections"
134
- # ''.demodulize # => ''
140
+ # 'ActiveSupport::Inflector::Inflections'.demodulize # => "Inflections"
141
+ # 'Inflections'.demodulize # => "Inflections"
142
+ # '::Inflections'.demodulize # => "Inflections"
143
+ # ''.demodulize # => ''
135
144
  #
136
145
  # See also +deconstantize+.
137
146
  def demodulize
@@ -164,31 +173,45 @@ class String
164
173
  #
165
174
  # <%= link_to(@person.name, person_path) %>
166
175
  # # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
167
- def parameterize(sep = '-')
168
- ActiveSupport::Inflector.parameterize(self, sep)
176
+ #
177
+ # To preserve the case of the characters in a string, use the +preserve_case+ argument.
178
+ #
179
+ # class Person
180
+ # def to_param
181
+ # "#{id}-#{name.parameterize(preserve_case: true)}"
182
+ # end
183
+ # end
184
+ #
185
+ # @person = Person.find(1)
186
+ # # => #<Person id: 1, name: "Donald E. Knuth">
187
+ #
188
+ # <%= link_to(@person.name, person_path) %>
189
+ # # => <a href="/person/1-Donald-E-Knuth">Donald E. Knuth</a>
190
+ def parameterize(separator: "-", preserve_case: false)
191
+ ActiveSupport::Inflector.parameterize(self, separator: separator, preserve_case: preserve_case)
169
192
  end
170
193
 
171
194
  # Creates the name of a table like Rails does for models to table names. This method
172
195
  # uses the +pluralize+ method on the last word in the string.
173
196
  #
174
197
  # 'RawScaledScorer'.tableize # => "raw_scaled_scorers"
175
- # 'egg_and_ham'.tableize # => "egg_and_hams"
198
+ # 'ham_and_egg'.tableize # => "ham_and_eggs"
176
199
  # 'fancyCategory'.tableize # => "fancy_categories"
177
200
  def tableize
178
201
  ActiveSupport::Inflector.tableize(self)
179
202
  end
180
203
 
181
- # Create a class name from a plural table name like Rails does for table names to models.
204
+ # Creates a class name from a plural table name like Rails does for table names to models.
182
205
  # Note that this returns a string and not a class. (To convert to an actual class
183
206
  # follow +classify+ with +constantize+.)
184
207
  #
185
- # 'egg_and_hams'.classify # => "EggAndHam"
208
+ # 'ham_and_eggs'.classify # => "HamAndEgg"
186
209
  # 'posts'.classify # => "Post"
187
210
  def classify
188
211
  ActiveSupport::Inflector.classify(self)
189
212
  end
190
213
 
191
- # Capitalizes the first word, turns underscores into spaces, and strips a
214
+ # Capitalizes the first word, turns underscores into spaces, and (by default)strips a
192
215
  # trailing '_id' if present.
193
216
  # Like +titleize+, this is meant for creating pretty output.
194
217
  #
@@ -196,12 +219,26 @@ class String
196
219
  # optional parameter +capitalize+ to false.
197
220
  # By default, this parameter is true.
198
221
  #
199
- # 'employee_salary'.humanize # => "Employee salary"
200
- # 'author_id'.humanize # => "Author"
201
- # 'author_id'.humanize(capitalize: false) # => "author"
202
- # '_id'.humanize # => "Id"
203
- def humanize(options = {})
204
- ActiveSupport::Inflector.humanize(self, options)
222
+ # The trailing '_id' can be kept and capitalized by setting the
223
+ # optional parameter +keep_id_suffix+ to true.
224
+ # By default, this parameter is false.
225
+ #
226
+ # 'employee_salary'.humanize # => "Employee salary"
227
+ # 'author_id'.humanize # => "Author"
228
+ # 'author_id'.humanize(capitalize: false) # => "author"
229
+ # '_id'.humanize # => "Id"
230
+ # 'author_id'.humanize(keep_id_suffix: true) # => "Author Id"
231
+ def humanize(capitalize: true, keep_id_suffix: false)
232
+ ActiveSupport::Inflector.humanize(self, capitalize: capitalize, keep_id_suffix: keep_id_suffix)
233
+ end
234
+
235
+ # Converts just the first character to uppercase.
236
+ #
237
+ # 'what a Lovely Day'.upcase_first # => "What a Lovely Day"
238
+ # 'w'.upcase_first # => "W"
239
+ # ''.upcase_first # => ""
240
+ def upcase_first
241
+ ActiveSupport::Inflector.upcase_first(self)
205
242
  end
206
243
 
207
244
  # Creates a foreign key name from a class name.
@@ -1,4 +1,6 @@
1
- require 'active_support/string_inquirer'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/string_inquirer"
2
4
 
3
5
  class String
4
6
  # Wraps the current string in the <tt>ActiveSupport::StringInquirer</tt> class,
@@ -1,5 +1,6 @@
1
- # encoding: utf-8
2
- require 'active_support/multibyte'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/multibyte"
3
4
 
4
5
  class String
5
6
  # == Multibyte proxy
@@ -10,12 +11,12 @@ class String
10
11
  # encapsulates the original string. A Unicode safe version of all the String methods are defined on this proxy
11
12
  # class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsulated string.
12
13
  #
13
- # name = 'Claus Müller'
14
- # name.reverse # => "rell??M sualC"
15
- # name.length # => 13
14
+ # >> "lj".upcase
15
+ # => "lj"
16
+ # >> "lj".mb_chars.upcase.to_s
17
+ # => "LJ"
16
18
  #
17
- # name.mb_chars.reverse.to_s # => "rellüM sualC"
18
- # name.mb_chars.length # => 12
19
+ # NOTE: An above example is useful for pre Ruby 2.4. Ruby 2.4 supports Unicode case mappings.
19
20
  #
20
21
  # == Method chaining
21
22
  #
@@ -36,6 +37,13 @@ class String
36
37
  ActiveSupport::Multibyte.proxy_class.new(self)
37
38
  end
38
39
 
40
+ # Returns +true+ if string has utf_8 encoding.
41
+ #
42
+ # utf_8_str = "some string".encode "UTF-8"
43
+ # iso_str = "some string".encode "ISO-8859-1"
44
+ #
45
+ # utf_8_str.is_utf8? # => true
46
+ # iso_str.is_utf8? # => false
39
47
  def is_utf8?
40
48
  case encoding
41
49
  when Encoding::UTF_8
@@ -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:
@@ -138,23 +141,26 @@ module ActiveSupport #:nodoc:
138
141
  alias_method :original_concat, :concat
139
142
  private :original_concat
140
143
 
144
+ # Raised when <tt>ActiveSupport::SafeBuffer#safe_concat</tt> is called on unsafe buffers.
141
145
  class SafeConcatError < StandardError
142
146
  def initialize
143
- super 'Could not concatenate to the buffer because it is not html safe.'
147
+ super "Could not concatenate to the buffer because it is not html safe."
144
148
  end
145
149
  end
146
150
 
147
151
  def [](*args)
148
152
  if args.size < 2
149
153
  super
150
- else
151
- if html_safe?
152
- new_safe_buffer = super
154
+ elsif html_safe?
155
+ new_safe_buffer = super
156
+
157
+ if new_safe_buffer
153
158
  new_safe_buffer.instance_variable_set :@html_safe, true
154
- new_safe_buffer
155
- else
156
- to_str[*args]
157
159
  end
160
+
161
+ new_safe_buffer
162
+ else
163
+ to_str[*args]
158
164
  end
159
165
  end
160
166
 
@@ -163,7 +169,7 @@ module ActiveSupport #:nodoc:
163
169
  original_concat(value)
164
170
  end
165
171
 
166
- def initialize(*)
172
+ def initialize(str = "")
167
173
  @html_safe = true
168
174
  super
169
175
  end
@@ -186,11 +192,6 @@ module ActiveSupport #:nodoc:
186
192
  super(html_escape_interpolated_argument(value))
187
193
  end
188
194
 
189
- def prepend!(value)
190
- ActiveSupport::Deprecation.deprecation_warning "ActiveSupport::SafeBuffer#prepend!", :prepend
191
- prepend value
192
- end
193
-
194
195
  def +(other)
195
196
  dup.concat(other)
196
197
  end
@@ -198,7 +199,7 @@ module ActiveSupport #:nodoc:
198
199
  def %(args)
199
200
  case args
200
201
  when Hash
201
- escaped_args = Hash[args.map { |k,arg| [k, html_escape_interpolated_argument(arg)] }]
202
+ escaped_args = Hash[args.map { |k, arg| [k, html_escape_interpolated_argument(arg)] }]
202
203
  else
203
204
  escaped_args = Array(args).map { |arg| html_escape_interpolated_argument(arg) }
204
205
  end
@@ -219,7 +220,7 @@ module ActiveSupport #:nodoc:
219
220
  end
220
221
 
221
222
  def encode_with(coder)
222
- coder.represent_scalar nil, to_str
223
+ coder.represent_object nil, to_str
223
224
  end
224
225
 
225
226
  UNSAFE_STRING_METHODS.each do |unsafe_method|
@@ -239,18 +240,17 @@ module ActiveSupport #:nodoc:
239
240
 
240
241
  private
241
242
 
242
- def html_escape_interpolated_argument(arg)
243
- (!html_safe? || arg.html_safe?) ? arg :
244
- arg.to_s.gsub(ERB::Util::HTML_ESCAPE_REGEXP, ERB::Util::HTML_ESCAPE)
245
- end
243
+ def html_escape_interpolated_argument(arg)
244
+ (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
245
+ end
246
246
  end
247
247
  end
248
248
 
249
249
  class String
250
250
  # Marks a string as trusted safe. It will be inserted into HTML with no
251
- # additional escaping performed. It is your responsibilty to ensure that the
251
+ # additional escaping performed. It is your responsibility to ensure that the
252
252
  # string contains no malicious content. This method is equivalent to the
253
- # `raw` helper in views. It is recommended that you use `sanitize` instead of
253
+ # +raw+ helper in views. It is recommended that you use +sanitize+ instead of
254
254
  # this method. It should never be called on user input.
255
255
  def html_safe
256
256
  ActiveSupport::SafeBuffer.new(self)