activesupport 5.1.7 → 6.1.7

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 (262) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +434 -490
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -5
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/all.rb +2 -0
  7. data/lib/active_support/array_inquirer.rb +6 -2
  8. data/lib/active_support/backtrace_cleaner.rb +31 -3
  9. data/lib/active_support/benchmarkable.rb +3 -1
  10. data/lib/active_support/builder.rb +2 -0
  11. data/lib/active_support/cache/file_store.rb +37 -36
  12. data/lib/active_support/cache/mem_cache_store.rb +72 -56
  13. data/lib/active_support/cache/memory_store.rb +61 -33
  14. data/lib/active_support/cache/null_store.rb +10 -3
  15. data/lib/active_support/cache/redis_cache_store.rb +493 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +67 -21
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
  18. data/lib/active_support/cache.rb +310 -126
  19. data/lib/active_support/callbacks.rb +106 -100
  20. data/lib/active_support/concern.rb +79 -6
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
  22. data/lib/active_support/concurrency/share_lock.rb +2 -1
  23. data/lib/active_support/configurable.rb +12 -14
  24. data/lib/active_support/configuration_file.rb +51 -0
  25. data/lib/active_support/core_ext/array/access.rb +21 -7
  26. data/lib/active_support/core_ext/array/conversions.rb +7 -5
  27. data/lib/active_support/core_ext/array/extract.rb +21 -0
  28. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  29. data/lib/active_support/core_ext/array/grouping.rb +2 -0
  30. data/lib/active_support/core_ext/array/inquiry.rb +2 -0
  31. data/lib/active_support/core_ext/array/wrap.rb +2 -0
  32. data/lib/active_support/core_ext/array.rb +3 -1
  33. data/lib/active_support/core_ext/benchmark.rb +4 -2
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +2 -0
  35. data/lib/active_support/core_ext/big_decimal.rb +2 -0
  36. data/lib/active_support/core_ext/class/attribute.rb +50 -47
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
  38. data/lib/active_support/core_ext/class/subclasses.rb +18 -40
  39. data/lib/active_support/core_ext/class.rb +2 -0
  40. data/lib/active_support/core_ext/date/acts_like.rb +2 -0
  41. data/lib/active_support/core_ext/date/blank.rb +2 -0
  42. data/lib/active_support/core_ext/date/calculations.rb +8 -5
  43. data/lib/active_support/core_ext/date/conversions.rb +12 -10
  44. data/lib/active_support/core_ext/date/zones.rb +2 -0
  45. data/lib/active_support/core_ext/date.rb +2 -0
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +61 -37
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -1
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +2 -1
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
  50. data/lib/active_support/core_ext/date_time/blank.rb +2 -0
  51. data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
  53. data/lib/active_support/core_ext/date_time/conversions.rb +2 -1
  54. data/lib/active_support/core_ext/date_time.rb +2 -0
  55. data/lib/active_support/core_ext/digest/uuid.rb +4 -1
  56. data/lib/active_support/core_ext/digest.rb +3 -0
  57. data/lib/active_support/core_ext/enumerable.rb +174 -71
  58. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  59. data/lib/active_support/core_ext/file.rb +2 -0
  60. data/lib/active_support/core_ext/hash/conversions.rb +7 -5
  61. data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
  62. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  63. data/lib/active_support/core_ext/hash/except.rb +4 -2
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +2 -0
  65. data/lib/active_support/core_ext/hash/keys.rb +3 -30
  66. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  67. data/lib/active_support/core_ext/hash/slice.rb +8 -29
  68. data/lib/active_support/core_ext/hash.rb +3 -2
  69. data/lib/active_support/core_ext/integer/inflections.rb +2 -0
  70. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  71. data/lib/active_support/core_ext/integer/time.rb +7 -14
  72. data/lib/active_support/core_ext/integer.rb +2 -0
  73. data/lib/active_support/core_ext/kernel/concern.rb +2 -0
  74. data/lib/active_support/core_ext/kernel/reporting.rb +2 -0
  75. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  76. data/lib/active_support/core_ext/kernel.rb +2 -1
  77. data/lib/active_support/core_ext/load_error.rb +3 -8
  78. data/lib/active_support/core_ext/marshal.rb +4 -0
  79. data/lib/active_support/core_ext/module/aliasing.rb +2 -0
  80. data/lib/active_support/core_ext/module/anonymous.rb +2 -0
  81. data/lib/active_support/core_ext/module/attr_internal.rb +4 -2
  82. data/lib/active_support/core_ext/module/attribute_accessors.rb +44 -56
  83. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +18 -18
  84. data/lib/active_support/core_ext/module/concerning.rb +15 -10
  85. data/lib/active_support/core_ext/module/delegation.rb +103 -58
  86. data/lib/active_support/core_ext/module/deprecation.rb +2 -0
  87. data/lib/active_support/core_ext/module/introspection.rb +18 -15
  88. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  89. data/lib/active_support/core_ext/module/remove_method.rb +5 -23
  90. data/lib/active_support/core_ext/module.rb +3 -1
  91. data/lib/active_support/core_ext/name_error.rb +36 -2
  92. data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
  93. data/lib/active_support/core_ext/numeric/conversions.rb +131 -129
  94. data/lib/active_support/core_ext/numeric/time.rb +7 -15
  95. data/lib/active_support/core_ext/numeric.rb +2 -1
  96. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  97. data/lib/active_support/core_ext/object/blank.rb +13 -3
  98. data/lib/active_support/core_ext/object/conversions.rb +2 -0
  99. data/lib/active_support/core_ext/object/deep_dup.rb +3 -1
  100. data/lib/active_support/core_ext/object/duplicable.rb +9 -114
  101. data/lib/active_support/core_ext/object/inclusion.rb +2 -0
  102. data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
  103. data/lib/active_support/core_ext/object/json.rb +22 -2
  104. data/lib/active_support/core_ext/object/to_param.rb +2 -0
  105. data/lib/active_support/core_ext/object/to_query.rb +2 -0
  106. data/lib/active_support/core_ext/object/try.rb +19 -7
  107. data/lib/active_support/core_ext/object/with_options.rb +4 -2
  108. data/lib/active_support/core_ext/object.rb +2 -0
  109. data/lib/active_support/core_ext/range/compare_range.rb +82 -0
  110. data/lib/active_support/core_ext/range/conversions.rb +35 -25
  111. data/lib/active_support/core_ext/range/each.rb +5 -2
  112. data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
  113. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  114. data/lib/active_support/core_ext/range.rb +4 -1
  115. data/lib/active_support/core_ext/regexp.rb +10 -5
  116. data/lib/active_support/core_ext/securerandom.rb +25 -3
  117. data/lib/active_support/core_ext/string/access.rb +7 -16
  118. data/lib/active_support/core_ext/string/behavior.rb +2 -0
  119. data/lib/active_support/core_ext/string/conversions.rb +3 -0
  120. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  121. data/lib/active_support/core_ext/string/filters.rb +44 -1
  122. data/lib/active_support/core_ext/string/indent.rb +2 -0
  123. data/lib/active_support/core_ext/string/inflections.rb +69 -16
  124. data/lib/active_support/core_ext/string/inquiry.rb +3 -0
  125. data/lib/active_support/core_ext/string/multibyte.rb +9 -4
  126. data/lib/active_support/core_ext/string/output_safety.rb +104 -20
  127. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  128. data/lib/active_support/core_ext/string/strip.rb +5 -1
  129. data/lib/active_support/core_ext/string/zones.rb +2 -0
  130. data/lib/active_support/core_ext/string.rb +2 -0
  131. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  132. data/lib/active_support/core_ext/symbol.rb +3 -0
  133. data/lib/active_support/core_ext/time/acts_like.rb +2 -0
  134. data/lib/active_support/core_ext/time/calculations.rb +76 -18
  135. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  136. data/lib/active_support/core_ext/time/conversions.rb +4 -0
  137. data/lib/active_support/core_ext/time/zones.rb +6 -4
  138. data/lib/active_support/core_ext/time.rb +2 -0
  139. data/lib/active_support/core_ext/uri.rb +11 -6
  140. data/lib/active_support/core_ext.rb +3 -1
  141. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  142. data/lib/active_support/current_attributes.rb +210 -0
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +2 -0
  145. data/lib/active_support/dependencies/zeitwerk_integration.rb +120 -0
  146. data/lib/active_support/dependencies.rb +134 -60
  147. data/lib/active_support/deprecation/behaviors.rb +43 -11
  148. data/lib/active_support/deprecation/constant_accessor.rb +4 -2
  149. data/lib/active_support/deprecation/disallowed.rb +56 -0
  150. data/lib/active_support/deprecation/instance_delegator.rb +2 -1
  151. data/lib/active_support/deprecation/method_wrappers.rb +29 -21
  152. data/lib/active_support/deprecation/proxy_wrappers.rb +32 -6
  153. data/lib/active_support/deprecation/reporting.rb +54 -9
  154. data/lib/active_support/deprecation.rb +9 -2
  155. data/lib/active_support/descendants_tracker.rb +61 -9
  156. data/lib/active_support/digest.rb +22 -0
  157. data/lib/active_support/duration/iso8601_parser.rb +6 -6
  158. data/lib/active_support/duration/iso8601_serializer.rb +20 -14
  159. data/lib/active_support/duration.rb +102 -45
  160. data/lib/active_support/encrypted_configuration.rb +45 -0
  161. data/lib/active_support/encrypted_file.rb +117 -0
  162. data/lib/active_support/environment_inquirer.rb +20 -0
  163. data/lib/active_support/evented_file_update_checker.rb +84 -117
  164. data/lib/active_support/execution_wrapper.rb +19 -13
  165. data/lib/active_support/executor.rb +2 -0
  166. data/lib/active_support/file_update_checker.rb +2 -1
  167. data/lib/active_support/fork_tracker.rb +64 -0
  168. data/lib/active_support/gem_version.rb +3 -1
  169. data/lib/active_support/gzip.rb +2 -0
  170. data/lib/active_support/hash_with_indifferent_access.rb +123 -41
  171. data/lib/active_support/i18n.rb +4 -1
  172. data/lib/active_support/i18n_railtie.rb +19 -14
  173. data/lib/active_support/inflections.rb +2 -0
  174. data/lib/active_support/inflector/inflections.rb +19 -8
  175. data/lib/active_support/inflector/methods.rb +87 -77
  176. data/lib/active_support/inflector/transliterate.rb +56 -18
  177. data/lib/active_support/inflector.rb +2 -0
  178. data/lib/active_support/json/decoding.rb +27 -26
  179. data/lib/active_support/json/encoding.rb +13 -3
  180. data/lib/active_support/json.rb +2 -0
  181. data/lib/active_support/key_generator.rb +3 -33
  182. data/lib/active_support/lazy_load_hooks.rb +7 -2
  183. data/lib/active_support/locale/en.rb +33 -0
  184. data/lib/active_support/locale/en.yml +7 -3
  185. data/lib/active_support/log_subscriber/test_helper.rb +2 -0
  186. data/lib/active_support/log_subscriber.rb +42 -11
  187. data/lib/active_support/logger.rb +4 -17
  188. data/lib/active_support/logger_silence.rb +13 -20
  189. data/lib/active_support/logger_thread_safe_level.rb +54 -7
  190. data/lib/active_support/message_encryptor.rb +100 -32
  191. data/lib/active_support/message_verifier.rb +85 -14
  192. data/lib/active_support/messages/metadata.rb +80 -0
  193. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  194. data/lib/active_support/messages/rotator.rb +57 -0
  195. data/lib/active_support/multibyte/chars.rb +12 -68
  196. data/lib/active_support/multibyte/unicode.rb +17 -327
  197. data/lib/active_support/multibyte.rb +2 -0
  198. data/lib/active_support/notifications/fanout.rb +118 -16
  199. data/lib/active_support/notifications/instrumenter.rb +73 -9
  200. data/lib/active_support/notifications.rb +74 -8
  201. data/lib/active_support/number_helper/number_converter.rb +7 -6
  202. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -9
  203. data/lib/active_support/number_helper/number_to_delimited_converter.rb +5 -2
  204. data/lib/active_support/number_helper/number_to_human_converter.rb +6 -3
  205. data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -3
  206. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  207. data/lib/active_support/number_helper/number_to_phone_converter.rb +5 -2
  208. data/lib/active_support/number_helper/number_to_rounded_converter.rb +14 -27
  209. data/lib/active_support/number_helper/rounding_helper.rb +16 -30
  210. data/lib/active_support/number_helper.rb +40 -12
  211. data/lib/active_support/option_merger.rb +24 -3
  212. data/lib/active_support/ordered_hash.rb +3 -1
  213. data/lib/active_support/ordered_options.rb +17 -5
  214. data/lib/active_support/parameter_filter.rb +133 -0
  215. data/lib/active_support/per_thread_registry.rb +4 -1
  216. data/lib/active_support/proxy_object.rb +2 -0
  217. data/lib/active_support/rails.rb +3 -10
  218. data/lib/active_support/railtie.rb +60 -9
  219. data/lib/active_support/reloader.rb +12 -11
  220. data/lib/active_support/rescuable.rb +7 -6
  221. data/lib/active_support/secure_compare_rotator.rb +51 -0
  222. data/lib/active_support/security_utils.rb +26 -15
  223. data/lib/active_support/string_inquirer.rb +6 -3
  224. data/lib/active_support/subscriber.rb +74 -24
  225. data/lib/active_support/tagged_logging.rb +44 -8
  226. data/lib/active_support/test_case.rb +94 -2
  227. data/lib/active_support/testing/assertions.rb +58 -20
  228. data/lib/active_support/testing/autorun.rb +2 -0
  229. data/lib/active_support/testing/constant_lookup.rb +2 -0
  230. data/lib/active_support/testing/declarative.rb +2 -0
  231. data/lib/active_support/testing/deprecation.rb +2 -1
  232. data/lib/active_support/testing/file_fixtures.rb +4 -0
  233. data/lib/active_support/testing/isolation.rb +4 -2
  234. data/lib/active_support/testing/method_call_assertions.rb +30 -1
  235. data/lib/active_support/testing/parallelization/server.rb +78 -0
  236. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  237. data/lib/active_support/testing/parallelization.rb +51 -0
  238. data/lib/active_support/testing/setup_and_teardown.rb +12 -7
  239. data/lib/active_support/testing/stream.rb +3 -2
  240. data/lib/active_support/testing/tagged_logging.rb +2 -0
  241. data/lib/active_support/testing/time_helpers.rb +78 -13
  242. data/lib/active_support/time.rb +2 -0
  243. data/lib/active_support/time_with_zone.rb +113 -41
  244. data/lib/active_support/values/time_zone.rb +54 -25
  245. data/lib/active_support/version.rb +2 -0
  246. data/lib/active_support/xml_mini/jdom.rb +5 -4
  247. data/lib/active_support/xml_mini/libxml.rb +4 -2
  248. data/lib/active_support/xml_mini/libxmlsax.rb +6 -4
  249. data/lib/active_support/xml_mini/nokogiri.rb +4 -2
  250. data/lib/active_support/xml_mini/nokogirisax.rb +5 -3
  251. data/lib/active_support/xml_mini/rexml.rb +12 -3
  252. data/lib/active_support/xml_mini.rb +5 -11
  253. data/lib/active_support.rb +18 -13
  254. metadata +71 -32
  255. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  256. data/lib/active_support/core_ext/hash/compact.rb +0 -27
  257. data/lib/active_support/core_ext/hash/transform_values.rb +0 -30
  258. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  259. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  260. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
  261. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  262. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "time"
4
+
5
+ module ActiveSupport
6
+ module Messages #:nodoc:
7
+ class Metadata #:nodoc:
8
+ def initialize(message, expires_at = nil, purpose = nil)
9
+ @message, @purpose = message, purpose
10
+ @expires_at = expires_at.is_a?(String) ? parse_expires_at(expires_at) : expires_at
11
+ end
12
+
13
+ def as_json(options = {})
14
+ { _rails: { message: @message, exp: @expires_at, pur: @purpose } }
15
+ end
16
+
17
+ class << self
18
+ def wrap(message, expires_at: nil, expires_in: nil, purpose: nil)
19
+ if expires_at || expires_in || purpose
20
+ JSON.encode new(encode(message), pick_expiry(expires_at, expires_in), purpose)
21
+ else
22
+ message
23
+ end
24
+ end
25
+
26
+ def verify(message, purpose)
27
+ extract_metadata(message).verify(purpose)
28
+ end
29
+
30
+ private
31
+ def pick_expiry(expires_at, expires_in)
32
+ if expires_at
33
+ expires_at.utc.iso8601(3)
34
+ elsif expires_in
35
+ Time.now.utc.advance(seconds: expires_in).iso8601(3)
36
+ end
37
+ end
38
+
39
+ def extract_metadata(message)
40
+ data = JSON.decode(message) rescue nil
41
+
42
+ if data.is_a?(Hash) && data.key?("_rails")
43
+ new(decode(data["_rails"]["message"]), data["_rails"]["exp"], data["_rails"]["pur"])
44
+ else
45
+ new(message)
46
+ end
47
+ end
48
+
49
+ def encode(message)
50
+ ::Base64.strict_encode64(message)
51
+ end
52
+
53
+ def decode(message)
54
+ ::Base64.strict_decode64(message)
55
+ end
56
+ end
57
+
58
+ def verify(purpose)
59
+ @message if match?(purpose) && fresh?
60
+ end
61
+
62
+ private
63
+ def match?(purpose)
64
+ @purpose.to_s == purpose.to_s
65
+ end
66
+
67
+ def fresh?
68
+ @expires_at.nil? || Time.now.utc < @expires_at
69
+ end
70
+
71
+ def parse_expires_at(expires_at)
72
+ if ActiveSupport.use_standard_json_time_format
73
+ Time.iso8601(expires_at)
74
+ else
75
+ Time.parse(expires_at)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module Messages
5
+ class RotationConfiguration # :nodoc:
6
+ attr_reader :signed, :encrypted
7
+
8
+ def initialize
9
+ @signed, @encrypted = [], []
10
+ end
11
+
12
+ def rotate(kind, *args, **options)
13
+ args << options unless options.empty?
14
+ case kind
15
+ when :signed
16
+ @signed << args
17
+ when :encrypted
18
+ @encrypted << args
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module Messages
5
+ module Rotator # :nodoc:
6
+ def initialize(*secrets, on_rotation: nil, **options)
7
+ super(*secrets, **options)
8
+
9
+ @options = options
10
+ @rotations = []
11
+ @on_rotation = on_rotation
12
+ end
13
+
14
+ def rotate(*secrets, **options)
15
+ @rotations << build_rotation(*secrets, @options.merge(options))
16
+ end
17
+
18
+ module Encryptor
19
+ include Rotator
20
+
21
+ def decrypt_and_verify(*args, on_rotation: @on_rotation, **options)
22
+ super
23
+ rescue MessageEncryptor::InvalidMessage, MessageVerifier::InvalidSignature
24
+ run_rotations(on_rotation) { |encryptor| encryptor.decrypt_and_verify(*args, **options) } || raise
25
+ end
26
+
27
+ private
28
+ def build_rotation(secret = @secret, sign_secret = @sign_secret, options)
29
+ self.class.new(secret, sign_secret, **options)
30
+ end
31
+ end
32
+
33
+ module Verifier
34
+ include Rotator
35
+
36
+ def verified(*args, on_rotation: @on_rotation, **options)
37
+ super || run_rotations(on_rotation) { |verifier| verifier.verified(*args, **options) }
38
+ end
39
+
40
+ private
41
+ def build_rotation(secret = @secret, options)
42
+ self.class.new(secret, **options)
43
+ end
44
+ end
45
+
46
+ private
47
+ def run_rotations(on_rotation)
48
+ @rotations.find do |rotation|
49
+ if message = yield(rotation) rescue next
50
+ on_rotation&.call
51
+ return message
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/json"
2
4
  require "active_support/core_ext/string/access"
3
5
  require "active_support/core_ext/string/behavior"
6
+ require "active_support/core_ext/symbol/starts_ends_with"
4
7
  require "active_support/core_ext/module/delegation"
5
- require "active_support/core_ext/regexp"
6
8
 
7
9
  module ActiveSupport #:nodoc:
8
10
  module Multibyte #:nodoc:
@@ -16,7 +18,7 @@ module ActiveSupport #:nodoc:
16
18
  # through the +mb_chars+ method. Methods which would normally return a
17
19
  # String object now return a Chars object so methods can be chained.
18
20
  #
19
- # 'The Perfect String '.mb_chars.downcase.strip.normalize
21
+ # 'The Perfect String '.mb_chars.downcase.strip
20
22
  # # => #<ActiveSupport::Multibyte::Chars:0x007fdc434ccc10 @wrapped_string="the perfect string">
21
23
  #
22
24
  # Chars objects are perfectly interchangeable with String objects as long as
@@ -47,7 +49,7 @@ module ActiveSupport #:nodoc:
47
49
  alias to_s wrapped_string
48
50
  alias to_str wrapped_string
49
51
 
50
- delegate :<=>, :=~, :acts_like_string?, to: :wrapped_string
52
+ delegate :<=>, :=~, :match?, :acts_like_string?, to: :wrapped_string
51
53
 
52
54
  # Creates a new Chars instance by wrapping _string_.
53
55
  def initialize(string)
@@ -58,7 +60,7 @@ module ActiveSupport #:nodoc:
58
60
  # Forward all undefined methods to the wrapped string.
59
61
  def method_missing(method, *args, &block)
60
62
  result = @wrapped_string.__send__(method, *args, &block)
61
- if /!$/.match?(method)
63
+ if method.end_with?("!")
62
64
  self if result
63
65
  else
64
66
  result.kind_of?(String) ? chars(result) : result
@@ -72,12 +74,6 @@ module ActiveSupport #:nodoc:
72
74
  @wrapped_string.respond_to?(method, include_private)
73
75
  end
74
76
 
75
- # Returns +true+ when the proxy class can handle the string. Returns
76
- # +false+ otherwise.
77
- def self.consumes?(string)
78
- string.encoding == Encoding::UTF_8
79
- end
80
-
81
77
  # Works just like <tt>String#split</tt>, with the exception that the items
82
78
  # in the resulting list are Chars instances instead of String. This makes
83
79
  # chaining methods easier.
@@ -107,7 +103,7 @@ module ActiveSupport #:nodoc:
107
103
  #
108
104
  # 'Café'.mb_chars.reverse.to_s # => 'éfaC'
109
105
  def reverse
110
- chars(Unicode.unpack_graphemes(@wrapped_string).reverse.flatten.pack("U*"))
106
+ chars(@wrapped_string.scan(/\X/).reverse.join)
111
107
  end
112
108
 
113
109
  # Limits the byte size of the string to a number of bytes without breaking
@@ -116,35 +112,7 @@ module ActiveSupport #:nodoc:
116
112
  #
117
113
  # 'こんにちは'.mb_chars.limit(7).to_s # => "こん"
118
114
  def limit(limit)
119
- slice(0...translate_offset(limit))
120
- end
121
-
122
- # Converts characters in the string to uppercase.
123
- #
124
- # 'Laurent, où sont les tests ?'.mb_chars.upcase.to_s # => "LAURENT, OÙ SONT LES TESTS ?"
125
- def upcase
126
- chars Unicode.upcase(@wrapped_string)
127
- end
128
-
129
- # Converts characters in the string to lowercase.
130
- #
131
- # 'VĚDA A VÝZKUM'.mb_chars.downcase.to_s # => "věda a výzkum"
132
- def downcase
133
- chars Unicode.downcase(@wrapped_string)
134
- end
135
-
136
- # Converts characters in the string to the opposite case.
137
- #
138
- # 'El Cañón'.mb_chars.swapcase.to_s # => "eL cAÑÓN"
139
- def swapcase
140
- chars Unicode.swapcase(@wrapped_string)
141
- end
142
-
143
- # Converts the first character to uppercase and the remainder to lowercase.
144
- #
145
- # 'über'.mb_chars.capitalize.to_s # => "Über"
146
- def capitalize
147
- (slice(0) || chars("")).upcase + (slice(1..-1) || chars("")).downcase
115
+ chars(@wrapped_string.truncate_bytes(limit, omission: nil))
148
116
  end
149
117
 
150
118
  # Capitalizes the first letter of every word, when possible.
@@ -152,21 +120,10 @@ module ActiveSupport #:nodoc:
152
120
  # "ÉL QUE SE ENTERÓ".mb_chars.titleize.to_s # => "Él Que Se Enteró"
153
121
  # "日本語".mb_chars.titleize.to_s # => "日本語"
154
122
  def titleize
155
- chars(downcase.to_s.gsub(/\b('?\S)/u) { Unicode.upcase($1) })
123
+ chars(downcase.to_s.gsub(/\b('?\S)/u) { $1.upcase })
156
124
  end
157
125
  alias_method :titlecase, :titleize
158
126
 
159
- # Returns the KC normalization of the string by default. NFKC is
160
- # considered the best normalization form for passing strings to databases
161
- # and validations.
162
- #
163
- # * <tt>form</tt> - The form you want to normalize in. Should be one of the following:
164
- # <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>. Default is
165
- # ActiveSupport::Multibyte::Unicode.default_normalization_form
166
- def normalize(form = nil)
167
- chars(Unicode.normalize(@wrapped_string, form))
168
- end
169
-
170
127
  # Performs canonical decomposition on all the characters.
171
128
  #
172
129
  # 'é'.length # => 2
@@ -188,7 +145,7 @@ module ActiveSupport #:nodoc:
188
145
  # 'क्षि'.mb_chars.length # => 4
189
146
  # 'क्षि'.mb_chars.grapheme_length # => 3
190
147
  def grapheme_length
191
- Unicode.unpack_graphemes(@wrapped_string).length
148
+ @wrapped_string.scan(/\X/).length
192
149
  end
193
150
 
194
151
  # Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent
@@ -204,27 +161,14 @@ module ActiveSupport #:nodoc:
204
161
  to_s.as_json(options)
205
162
  end
206
163
 
207
- %w(capitalize downcase reverse tidy_bytes upcase).each do |method|
164
+ %w(reverse tidy_bytes).each do |method|
208
165
  define_method("#{method}!") do |*args|
209
- @wrapped_string = send(method, *args).to_s
166
+ @wrapped_string = public_send(method, *args).to_s
210
167
  self
211
168
  end
212
169
  end
213
170
 
214
171
  private
215
-
216
- def translate_offset(byte_offset)
217
- return nil if byte_offset.nil?
218
- return 0 if @wrapped_string == ""
219
-
220
- begin
221
- @wrapped_string.byteslice(0...byte_offset).unpack("U*").length
222
- rescue ArgumentError
223
- byte_offset -= 1
224
- retry
225
- end
226
- end
227
-
228
172
  def chars(string)
229
173
  self.class.new(string)
230
174
  end