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
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "securerandom"
4
+
5
+ module SecureRandom
6
+ BASE58_ALPHABET = ("0".."9").to_a + ("A".."Z").to_a + ("a".."z").to_a - ["0", "O", "I", "l"]
7
+ BASE36_ALPHABET = ("0".."9").to_a + ("a".."z").to_a
8
+
9
+ # SecureRandom.base58 generates a random base58 string.
10
+ #
11
+ # The argument _n_ specifies the length of the random string to be generated.
12
+ #
13
+ # If _n_ is not specified or is +nil+, 16 is assumed. It may be larger in the future.
14
+ #
15
+ # The result may contain alphanumeric characters except 0, O, I and l.
16
+ #
17
+ # p SecureRandom.base58 # => "4kUgL2pdQMSCQtjE"
18
+ # p SecureRandom.base58(24) # => "77TMHrHJFvFDwodq8w7Ev2m7"
19
+ def self.base58(n = 16)
20
+ SecureRandom.random_bytes(n).unpack("C*").map do |byte|
21
+ idx = byte % 64
22
+ idx = SecureRandom.random_number(58) if idx >= 58
23
+ BASE58_ALPHABET[idx]
24
+ end.join
25
+ end
26
+
27
+ # SecureRandom.base36 generates a random base36 string in lowercase.
28
+ #
29
+ # The argument _n_ specifies the length of the random string to be generated.
30
+ #
31
+ # If _n_ is not specified or is +nil+, 16 is assumed. It may be larger in the future.
32
+ # This method can be used over +base58+ if a deterministic case key is necessary.
33
+ #
34
+ # The result will contain alphanumeric characters in lowercase.
35
+ #
36
+ # p SecureRandom.base36 # => "4kugl2pdqmscqtje"
37
+ # p SecureRandom.base36(24) # => "77tmhrhjfvfdwodq8w7ev2m7"
38
+ def self.base36(n = 16)
39
+ SecureRandom.random_bytes(n).unpack("C*").map do |byte|
40
+ idx = byte % 64
41
+ idx = SecureRandom.random_number(36) if idx >= 36
42
+ BASE36_ALPHABET[idx]
43
+ end.join
44
+ end
45
+ end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
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"
@@ -73,10 +75,14 @@ class String
73
75
  # str.first(0) # => ""
74
76
  # str.first(6) # => "hello"
75
77
  def first(limit = 1)
78
+ ActiveSupport::Deprecation.warn(
79
+ "Calling String#first with a negative integer limit " \
80
+ "will raise an ArgumentError in Rails 6.1."
81
+ ) if limit < 0
76
82
  if limit == 0
77
- ''
83
+ ""
78
84
  elsif limit >= size
79
- self.dup
85
+ dup
80
86
  else
81
87
  to(limit - 1)
82
88
  end
@@ -93,10 +99,14 @@ class String
93
99
  # str.last(0) # => ""
94
100
  # str.last(6) # => "hello"
95
101
  def last(limit = 1)
102
+ ActiveSupport::Deprecation.warn(
103
+ "Calling String#last with a negative integer limit " \
104
+ "will raise an ArgumentError in Rails 6.1."
105
+ ) if limit < 0
96
106
  if limit == 0
97
- ''
107
+ ""
98
108
  elsif limit >= size
99
- self.dup
109
+ dup
100
110
  else
101
111
  from(-limit)
102
112
  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(
@@ -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,9 +19,8 @@ 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
 
@@ -65,7 +66,7 @@ class String
65
66
  def truncate(truncate_at, options = {})
66
67
  return dup unless length > truncate_at
67
68
 
68
- omission = options[:omission] || '...'
69
+ omission = options[:omission] || "..."
69
70
  length_with_room_for_omission = truncate_at - omission.length
70
71
  stop = \
71
72
  if options[:separator]
@@ -74,7 +75,48 @@ class String
74
75
  length_with_room_for_omission
75
76
  end
76
77
 
77
- "#{self[0, stop]}#{omission}"
78
+ +"#{self[0, stop]}#{omission}"
79
+ end
80
+
81
+ # Truncates +text+ to at most <tt>bytesize</tt> bytes in length without
82
+ # breaking string encoding by splitting multibyte characters or breaking
83
+ # grapheme clusters ("perceptual characters") by truncating at combining
84
+ # characters.
85
+ #
86
+ # >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".size
87
+ # => 20
88
+ # >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".bytesize
89
+ # => 80
90
+ # >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".truncate_bytes(20)
91
+ # => "🔪🔪🔪🔪…"
92
+ #
93
+ # The truncated text ends with the <tt>:omission</tt> string, defaulting
94
+ # to "…", for a total length not exceeding <tt>bytesize</tt>.
95
+ def truncate_bytes(truncate_at, omission: "…")
96
+ omission ||= ""
97
+
98
+ case
99
+ when bytesize <= truncate_at
100
+ dup
101
+ when omission.bytesize > truncate_at
102
+ raise ArgumentError, "Omission #{omission.inspect} is #{omission.bytesize}, larger than the truncation length of #{truncate_at} bytes"
103
+ when omission.bytesize == truncate_at
104
+ omission.dup
105
+ else
106
+ self.class.new.tap do |cut|
107
+ cut_at = truncate_at - omission.bytesize
108
+
109
+ scan(/\X/) do |grapheme|
110
+ if cut.bytesize + grapheme.bytesize <= cut_at
111
+ cut << grapheme
112
+ else
113
+ break
114
+ end
115
+ end
116
+
117
+ cut << omission
118
+ end
119
+ end
78
120
  end
79
121
 
80
122
  # Truncates a given +text+ after a given number of words (<tt>words_count</tt>):
@@ -95,7 +137,7 @@ class String
95
137
  sep = options[:separator] || /\s+/
96
138
  sep = Regexp.escape(sep.to_s) unless Regexp === sep
97
139
  if self =~ /\A((?>.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/m
98
- $1 + (options[:omission] || '...')
140
+ $1 + (options[:omission] || "...")
99
141
  else
100
142
  dup
101
143
  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
@@ -153,6 +162,11 @@ class String
153
162
 
154
163
  # Replaces special characters in a string so that it may be used as part of a 'pretty' URL.
155
164
  #
165
+ # If the optional parameter +locale+ is specified,
166
+ # the word will be parameterized as a word of that language.
167
+ # By default, this parameter is set to <tt>nil</tt> and it will use
168
+ # the configured <tt>I18n.locale</tt>.
169
+ #
156
170
  # class Person
157
171
  # def to_param
158
172
  # "#{id}-#{name.parameterize}"
@@ -164,31 +178,45 @@ class String
164
178
  #
165
179
  # <%= link_to(@person.name, person_path) %>
166
180
  # # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
167
- def parameterize(sep = '-')
168
- ActiveSupport::Inflector.parameterize(self, sep)
181
+ #
182
+ # To preserve the case of the characters in a string, use the +preserve_case+ argument.
183
+ #
184
+ # class Person
185
+ # def to_param
186
+ # "#{id}-#{name.parameterize(preserve_case: true)}"
187
+ # end
188
+ # end
189
+ #
190
+ # @person = Person.find(1)
191
+ # # => #<Person id: 1, name: "Donald E. Knuth">
192
+ #
193
+ # <%= link_to(@person.name, person_path) %>
194
+ # # => <a href="/person/1-Donald-E-Knuth">Donald E. Knuth</a>
195
+ def parameterize(separator: "-", preserve_case: false, locale: nil)
196
+ ActiveSupport::Inflector.parameterize(self, separator: separator, preserve_case: preserve_case, locale: locale)
169
197
  end
170
198
 
171
199
  # Creates the name of a table like Rails does for models to table names. This method
172
200
  # uses the +pluralize+ method on the last word in the string.
173
201
  #
174
202
  # 'RawScaledScorer'.tableize # => "raw_scaled_scorers"
175
- # 'egg_and_ham'.tableize # => "egg_and_hams"
203
+ # 'ham_and_egg'.tableize # => "ham_and_eggs"
176
204
  # 'fancyCategory'.tableize # => "fancy_categories"
177
205
  def tableize
178
206
  ActiveSupport::Inflector.tableize(self)
179
207
  end
180
208
 
181
- # Create a class name from a plural table name like Rails does for table names to models.
209
+ # Creates a class name from a plural table name like Rails does for table names to models.
182
210
  # Note that this returns a string and not a class. (To convert to an actual class
183
211
  # follow +classify+ with +constantize+.)
184
212
  #
185
- # 'egg_and_hams'.classify # => "EggAndHam"
213
+ # 'ham_and_eggs'.classify # => "HamAndEgg"
186
214
  # 'posts'.classify # => "Post"
187
215
  def classify
188
216
  ActiveSupport::Inflector.classify(self)
189
217
  end
190
218
 
191
- # Capitalizes the first word, turns underscores into spaces, and strips a
219
+ # Capitalizes the first word, turns underscores into spaces, and (by default)strips a
192
220
  # trailing '_id' if present.
193
221
  # Like +titleize+, this is meant for creating pretty output.
194
222
  #
@@ -196,12 +224,26 @@ class String
196
224
  # optional parameter +capitalize+ to false.
197
225
  # By default, this parameter is true.
198
226
  #
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)
227
+ # The trailing '_id' can be kept and capitalized by setting the
228
+ # optional parameter +keep_id_suffix+ to true.
229
+ # By default, this parameter is false.
230
+ #
231
+ # 'employee_salary'.humanize # => "Employee salary"
232
+ # 'author_id'.humanize # => "Author"
233
+ # 'author_id'.humanize(capitalize: false) # => "author"
234
+ # '_id'.humanize # => "Id"
235
+ # 'author_id'.humanize(keep_id_suffix: true) # => "Author Id"
236
+ def humanize(capitalize: true, keep_id_suffix: false)
237
+ ActiveSupport::Inflector.humanize(self, capitalize: capitalize, keep_id_suffix: keep_id_suffix)
238
+ end
239
+
240
+ # Converts just the first character to uppercase.
241
+ #
242
+ # 'what a Lovely Day'.upcase_first # => "What a Lovely Day"
243
+ # 'w'.upcase_first # => "W"
244
+ # ''.upcase_first # => ""
245
+ def upcase_first
246
+ ActiveSupport::Inflector.upcase_first(self)
205
247
  end
206
248
 
207
249
  # 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,13 @@ 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".mb_chars.upcase.to_s
15
+ # => "LJ"
16
+ #
17
+ # NOTE: Ruby 2.4 and later support native Unicode case mappings:
16
18
  #
17
- # name.mb_chars.reverse.to_s # => "rellüM sualC"
18
- # name.mb_chars.length # => 12
19
+ # >> "lj".upcase
20
+ # => "LJ"
19
21
  #
20
22
  # == Method chaining
21
23
  #
@@ -36,6 +38,13 @@ class String
36
38
  ActiveSupport::Multibyte.proxy_class.new(self)
37
39
  end
38
40
 
41
+ # Returns +true+ if string has utf_8 encoding.
42
+ #
43
+ # utf_8_str = "some string".encode "UTF-8"
44
+ # iso_str = "some string".encode "ISO-8859-1"
45
+ #
46
+ # utf_8_str.is_utf8? # => true
47
+ # iso_str.is_utf8? # => false
39
48
  def is_utf8?
40
49
  case encoding
41
50
  when Encoding::UTF_8