activesupport 4.0.12 → 7.0.2.4

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 (295) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +249 -501
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +10 -5
  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 +41 -13
  9. data/lib/active_support/benchmarkable.rb +7 -15
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +96 -74
  12. data/lib/active_support/cache/mem_cache_store.rb +211 -103
  13. data/lib/active_support/cache/memory_store.rb +90 -58
  14. data/lib/active_support/cache/null_store.rb +19 -7
  15. data/lib/active_support/cache/redis_cache_store.rb +468 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +86 -83
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
  18. data/lib/active_support/cache.rb +580 -241
  19. data/lib/active_support/callbacks.rb +812 -425
  20. data/lib/active_support/code_generator.rb +65 -0
  21. data/lib/active_support/concern.rb +103 -14
  22. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +33 -0
  23. data/lib/active_support/concurrency/share_lock.rb +226 -0
  24. data/lib/active_support/configurable.rb +21 -19
  25. data/lib/active_support/configuration_file.rb +51 -0
  26. data/lib/active_support/core_ext/array/access.rb +47 -1
  27. data/lib/active_support/core_ext/array/conversions.rb +35 -44
  28. data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
  29. data/lib/active_support/core_ext/array/extract.rb +21 -0
  30. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  31. data/lib/active_support/core_ext/array/grouping.rb +26 -16
  32. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  33. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  34. data/lib/active_support/core_ext/array.rb +10 -7
  35. data/lib/active_support/core_ext/benchmark.rb +5 -3
  36. data/lib/active_support/core_ext/big_decimal/conversions.rb +9 -26
  37. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  38. data/lib/active_support/core_ext/class/attribute.rb +52 -49
  39. data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
  40. data/lib/active_support/core_ext/class/subclasses.rb +25 -26
  41. data/lib/active_support/core_ext/class.rb +4 -4
  42. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  43. data/lib/active_support/core_ext/date/blank.rb +14 -0
  44. data/lib/active_support/core_ext/date/calculations.rb +31 -18
  45. data/lib/active_support/core_ext/date/conversions.rb +43 -32
  46. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  47. data/lib/active_support/core_ext/date/zones.rb +5 -34
  48. data/lib/active_support/core_ext/date.rb +7 -4
  49. data/lib/active_support/core_ext/date_and_time/calculations.rb +198 -66
  50. data/lib/active_support/core_ext/date_and_time/compatibility.rb +31 -0
  51. data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
  52. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  53. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  54. data/lib/active_support/core_ext/date_time/calculations.rb +79 -38
  55. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  56. data/lib/active_support/core_ext/date_time/conversions.rb +31 -26
  57. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  58. data/lib/active_support/core_ext/date_time.rb +8 -4
  59. data/lib/active_support/core_ext/digest/uuid.rb +79 -0
  60. data/lib/active_support/core_ext/digest.rb +3 -0
  61. data/lib/active_support/core_ext/enumerable.rb +249 -17
  62. data/lib/active_support/core_ext/file/atomic.rb +41 -32
  63. data/lib/active_support/core_ext/file.rb +3 -1
  64. data/lib/active_support/core_ext/hash/conversions.rb +71 -49
  65. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  66. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  67. data/lib/active_support/core_ext/hash/except.rb +14 -5
  68. data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
  69. data/lib/active_support/core_ext/hash/keys.rb +39 -56
  70. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  71. data/lib/active_support/core_ext/hash/slice.rb +8 -23
  72. data/lib/active_support/core_ext/hash.rb +10 -8
  73. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  74. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  75. data/lib/active_support/core_ext/integer/time.rb +11 -33
  76. data/lib/active_support/core_ext/integer.rb +5 -3
  77. data/lib/active_support/core_ext/kernel/concern.rb +14 -0
  78. data/lib/active_support/core_ext/kernel/reporting.rb +9 -78
  79. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  80. data/lib/active_support/core_ext/kernel.rb +5 -4
  81. data/lib/active_support/core_ext/load_error.rb +5 -21
  82. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  83. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  84. data/lib/active_support/core_ext/module/attr_internal.rb +8 -8
  85. data/lib/active_support/core_ext/module/attribute_accessors.rb +186 -44
  86. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +157 -0
  87. data/lib/active_support/core_ext/module/concerning.rb +140 -0
  88. data/lib/active_support/core_ext/module/delegation.rb +172 -45
  89. data/lib/active_support/core_ext/module/deprecation.rb +3 -3
  90. data/lib/active_support/core_ext/module/introspection.rb +23 -38
  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 -10
  94. data/lib/active_support/core_ext/name_error.rb +45 -4
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +135 -127
  97. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +37 -50
  99. data/lib/active_support/core_ext/numeric.rb +6 -3
  100. data/lib/active_support/core_ext/object/acts_like.rb +41 -6
  101. data/lib/active_support/core_ext/object/blank.rb +70 -20
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +19 -10
  104. data/lib/active_support/core_ext/object/duplicable.rb +17 -47
  105. data/lib/active_support/core_ext/object/inclusion.rb +18 -15
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +244 -0
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +21 -8
  110. data/lib/active_support/core_ext/object/try.rb +106 -26
  111. data/lib/active_support/core_ext/object/with_options.rb +64 -5
  112. data/lib/active_support/core_ext/object.rb +14 -12
  113. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  114. data/lib/active_support/core_ext/pathname.rb +3 -0
  115. data/lib/active_support/core_ext/range/compare_range.rb +57 -0
  116. data/lib/active_support/core_ext/range/conversions.rb +37 -15
  117. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  118. data/lib/active_support/core_ext/range/each.rb +18 -17
  119. data/lib/active_support/core_ext/range/include_time_with_zone.rb +7 -0
  120. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  121. data/lib/active_support/core_ext/range.rb +7 -4
  122. data/lib/active_support/core_ext/regexp.rb +10 -1
  123. data/lib/active_support/core_ext/securerandom.rb +45 -0
  124. data/lib/active_support/core_ext/string/access.rb +42 -51
  125. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  126. data/lib/active_support/core_ext/string/conversions.rb +18 -13
  127. data/lib/active_support/core_ext/string/exclude.rb +5 -3
  128. data/lib/active_support/core_ext/string/filters.rb +97 -7
  129. data/lib/active_support/core_ext/string/indent.rb +6 -4
  130. data/lib/active_support/core_ext/string/inflections.rb +106 -25
  131. data/lib/active_support/core_ext/string/inquiry.rb +4 -1
  132. data/lib/active_support/core_ext/string/multibyte.rb +18 -9
  133. data/lib/active_support/core_ext/string/output_safety.rb +227 -54
  134. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  135. data/lib/active_support/core_ext/string/strip.rb +6 -5
  136. data/lib/active_support/core_ext/string/zones.rb +4 -1
  137. data/lib/active_support/core_ext/string.rb +15 -13
  138. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  139. data/lib/active_support/core_ext/symbol.rb +3 -0
  140. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  141. data/lib/active_support/core_ext/time/calculations.rb +178 -116
  142. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  143. data/lib/active_support/core_ext/time/conversions.rb +37 -25
  144. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  145. data/lib/active_support/core_ext/time/zones.rb +44 -42
  146. data/lib/active_support/core_ext/time.rb +8 -5
  147. data/lib/active_support/core_ext/uri.rb +4 -25
  148. data/lib/active_support/core_ext.rb +4 -2
  149. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  150. data/lib/active_support/current_attributes.rb +226 -0
  151. data/lib/active_support/dependencies/autoload.rb +3 -1
  152. data/lib/active_support/dependencies/interlock.rb +49 -0
  153. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  154. data/lib/active_support/dependencies.rb +71 -696
  155. data/lib/active_support/deprecation/behaviors.rb +65 -16
  156. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  157. data/lib/active_support/deprecation/disallowed.rb +56 -0
  158. data/lib/active_support/deprecation/instance_delegator.rb +16 -2
  159. data/lib/active_support/deprecation/method_wrappers.rb +62 -21
  160. data/lib/active_support/deprecation/proxy_wrappers.rb +82 -31
  161. data/lib/active_support/deprecation/reporting.rb +81 -18
  162. data/lib/active_support/deprecation.rb +19 -11
  163. data/lib/active_support/descendants_tracker.rb +192 -34
  164. data/lib/active_support/digest.rb +22 -0
  165. data/lib/active_support/duration/iso8601_parser.rb +123 -0
  166. data/lib/active_support/duration/iso8601_serializer.rb +67 -0
  167. data/lib/active_support/duration.rb +437 -39
  168. data/lib/active_support/encrypted_configuration.rb +56 -0
  169. data/lib/active_support/encrypted_file.rb +117 -0
  170. data/lib/active_support/environment_inquirer.rb +20 -0
  171. data/lib/active_support/error_reporter.rb +117 -0
  172. data/lib/active_support/evented_file_update_checker.rb +170 -0
  173. data/lib/active_support/execution_context/test_helper.rb +13 -0
  174. data/lib/active_support/execution_context.rb +53 -0
  175. data/lib/active_support/execution_wrapper.rb +151 -0
  176. data/lib/active_support/executor/test_helper.rb +7 -0
  177. data/lib/active_support/executor.rb +8 -0
  178. data/lib/active_support/file_update_checker.rb +62 -37
  179. data/lib/active_support/fork_tracker.rb +71 -0
  180. data/lib/active_support/gem_version.rb +17 -0
  181. data/lib/active_support/gzip.rb +7 -5
  182. data/lib/active_support/hash_with_indifferent_access.rb +207 -54
  183. data/lib/active_support/html_safe_translation.rb +43 -0
  184. data/lib/active_support/i18n.rb +10 -6
  185. data/lib/active_support/i18n_railtie.rb +48 -19
  186. data/lib/active_support/inflections.rb +19 -12
  187. data/lib/active_support/inflector/inflections.rb +97 -37
  188. data/lib/active_support/inflector/methods.rb +192 -157
  189. data/lib/active_support/inflector/transliterate.rb +83 -33
  190. data/lib/active_support/inflector.rb +7 -5
  191. data/lib/active_support/isolated_execution_state.rb +64 -0
  192. data/lib/active_support/json/decoding.rb +37 -42
  193. data/lib/active_support/json/encoding.rb +93 -293
  194. data/lib/active_support/json.rb +4 -2
  195. data/lib/active_support/key_generator.rb +30 -47
  196. data/lib/active_support/lazy_load_hooks.rb +54 -21
  197. data/lib/active_support/locale/en.rb +33 -0
  198. data/lib/active_support/locale/en.yml +10 -4
  199. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  200. data/lib/active_support/log_subscriber.rb +61 -18
  201. data/lib/active_support/logger.rb +40 -4
  202. data/lib/active_support/logger_silence.rb +17 -20
  203. data/lib/active_support/logger_thread_safe_level.rb +69 -0
  204. data/lib/active_support/message_encryptor.rb +178 -55
  205. data/lib/active_support/message_verifier.rb +195 -26
  206. data/lib/active_support/messages/metadata.rb +80 -0
  207. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  208. data/lib/active_support/messages/rotator.rb +57 -0
  209. data/lib/active_support/multibyte/chars.rb +45 -92
  210. data/lib/active_support/multibyte/unicode.rb +44 -377
  211. data/lib/active_support/multibyte.rb +5 -3
  212. data/lib/active_support/notifications/fanout.rb +177 -44
  213. data/lib/active_support/notifications/instrumenter.rb +117 -17
  214. data/lib/active_support/notifications.rb +106 -39
  215. data/lib/active_support/number_helper/number_converter.rb +181 -0
  216. data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
  217. data/lib/active_support/number_helper/number_to_delimited_converter.rb +30 -0
  218. data/lib/active_support/number_helper/number_to_human_converter.rb +69 -0
  219. data/lib/active_support/number_helper/number_to_human_size_converter.rb +60 -0
  220. data/lib/active_support/number_helper/number_to_percentage_converter.rb +16 -0
  221. data/lib/active_support/number_helper/number_to_phone_converter.rb +59 -0
  222. data/lib/active_support/number_helper/number_to_rounded_converter.rb +59 -0
  223. data/lib/active_support/number_helper/rounding_helper.rb +46 -0
  224. data/lib/active_support/number_helper.rb +152 -394
  225. data/lib/active_support/option_merger.rb +18 -5
  226. data/lib/active_support/ordered_hash.rb +8 -6
  227. data/lib/active_support/ordered_options.rb +43 -7
  228. data/lib/active_support/parameter_filter.rb +138 -0
  229. data/lib/active_support/per_thread_registry.rb +24 -11
  230. data/lib/active_support/proxy_object.rb +2 -0
  231. data/lib/active_support/rails.rb +10 -11
  232. data/lib/active_support/railtie.rb +118 -12
  233. data/lib/active_support/reloader.rb +130 -0
  234. data/lib/active_support/rescuable.rb +112 -57
  235. data/lib/active_support/ruby_features.rb +7 -0
  236. data/lib/active_support/secure_compare_rotator.rb +51 -0
  237. data/lib/active_support/security_utils.rb +38 -0
  238. data/lib/active_support/string_inquirer.rb +11 -4
  239. data/lib/active_support/subscriber.rb +109 -39
  240. data/lib/active_support/tagged_logging.rb +54 -17
  241. data/lib/active_support/test_case.rb +121 -37
  242. data/lib/active_support/testing/assertions.rb +177 -39
  243. data/lib/active_support/testing/autorun.rb +5 -3
  244. data/lib/active_support/testing/constant_lookup.rb +3 -6
  245. data/lib/active_support/testing/declarative.rb +10 -22
  246. data/lib/active_support/testing/deprecation.rb +65 -11
  247. data/lib/active_support/testing/file_fixtures.rb +38 -0
  248. data/lib/active_support/testing/isolation.rb +56 -87
  249. data/lib/active_support/testing/method_call_assertions.rb +70 -0
  250. data/lib/active_support/testing/parallelization/server.rb +82 -0
  251. data/lib/active_support/testing/parallelization/worker.rb +103 -0
  252. data/lib/active_support/testing/parallelization.rb +55 -0
  253. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  254. data/lib/active_support/testing/setup_and_teardown.rb +30 -10
  255. data/lib/active_support/testing/stream.rb +41 -0
  256. data/lib/active_support/testing/tagged_logging.rb +6 -4
  257. data/lib/active_support/testing/time_helpers.rb +246 -0
  258. data/lib/active_support/time.rb +13 -13
  259. data/lib/active_support/time_with_zone.rb +315 -90
  260. data/lib/active_support/values/time_zone.rb +306 -135
  261. data/lib/active_support/version.rb +6 -7
  262. data/lib/active_support/xml_mini/jdom.rb +117 -115
  263. data/lib/active_support/xml_mini/libxml.rb +22 -21
  264. data/lib/active_support/xml_mini/libxmlsax.rb +17 -19
  265. data/lib/active_support/xml_mini/nokogiri.rb +19 -19
  266. data/lib/active_support/xml_mini/nokogirisax.rb +16 -17
  267. data/lib/active_support/xml_mini/rexml.rb +25 -17
  268. data/lib/active_support/xml_mini.rb +67 -56
  269. data/lib/active_support.rb +58 -3
  270. metadata +125 -66
  271. data/lib/active_support/basic_object.rb +0 -11
  272. data/lib/active_support/buffered_logger.rb +0 -21
  273. data/lib/active_support/concurrency/latch.rb +0 -27
  274. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  275. data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
  276. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -40
  277. data/lib/active_support/core_ext/date_time/zones.rb +0 -24
  278. data/lib/active_support/core_ext/hash/diff.rb +0 -14
  279. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  280. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  281. data/lib/active_support/core_ext/logger.rb +0 -67
  282. data/lib/active_support/core_ext/marshal.rb +0 -21
  283. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  284. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  285. data/lib/active_support/core_ext/object/to_json.rb +0 -27
  286. data/lib/active_support/core_ext/proc.rb +0 -17
  287. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  288. data/lib/active_support/core_ext/string/encoding.rb +0 -8
  289. data/lib/active_support/core_ext/struct.rb +0 -6
  290. data/lib/active_support/core_ext/thread.rb +0 -79
  291. data/lib/active_support/core_ext/time/marshal.rb +0 -30
  292. data/lib/active_support/file_watcher.rb +0 -36
  293. data/lib/active_support/json/variable.rb +0 -18
  294. data/lib/active_support/testing/pending.rb +0 -14
  295. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -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,11 +1,12 @@
1
- # encoding: utf-8
2
- require 'active_support/json'
3
- require 'active_support/core_ext/string/access'
4
- require 'active_support/core_ext/string/behavior'
5
- require 'active_support/core_ext/module/delegation'
6
-
7
- module ActiveSupport #:nodoc:
8
- module Multibyte #:nodoc:
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/json"
4
+ require "active_support/core_ext/string/access"
5
+ require "active_support/core_ext/string/behavior"
6
+ require "active_support/core_ext/module/delegation"
7
+
8
+ module ActiveSupport # :nodoc:
9
+ module Multibyte # :nodoc:
9
10
  # Chars enables you to work transparently with UTF-8 encoding in the Ruby
10
11
  # String class without having extensive knowledge about the encoding. A
11
12
  # Chars object accepts a string upon initialization and proxies String
@@ -16,7 +17,8 @@ module ActiveSupport #:nodoc:
16
17
  # through the +mb_chars+ method. Methods which would normally return a
17
18
  # String object now return a Chars object so methods can be chained.
18
19
  #
19
- # 'The Perfect String '.mb_chars.downcase.strip.normalize # => "the perfect string"
20
+ # 'The Perfect String '.mb_chars.downcase.strip
21
+ # # => #<ActiveSupport::Multibyte::Chars:0x007fdc434ccc10 @wrapped_string="the perfect string">
20
22
  #
21
23
  # Chars objects are perfectly interchangeable with String objects as long as
22
24
  # no explicit class checks are made. If certain methods do explicitly check
@@ -46,7 +48,7 @@ module ActiveSupport #:nodoc:
46
48
  alias to_s wrapped_string
47
49
  alias to_str wrapped_string
48
50
 
49
- delegate :<=>, :=~, :acts_like_string?, :to => :wrapped_string
51
+ delegate :<=>, :=~, :match?, :acts_like_string?, to: :wrapped_string
50
52
 
51
53
  # Creates a new Chars instance by wrapping _string_.
52
54
  def initialize(string)
@@ -56,11 +58,10 @@ module ActiveSupport #:nodoc:
56
58
 
57
59
  # Forward all undefined methods to the wrapped string.
58
60
  def method_missing(method, *args, &block)
59
- if method.to_s =~ /!$/
60
- result = @wrapped_string.__send__(method, *args, &block)
61
+ result = @wrapped_string.__send__(method, *args, &block)
62
+ if method.end_with?("!")
61
63
  self if result
62
64
  else
63
- result = @wrapped_string.__send__(method, *args, &block)
64
65
  result.kind_of?(String) ? chars(result) : result
65
66
  end
66
67
  end
@@ -72,12 +73,6 @@ module ActiveSupport #:nodoc:
72
73
  @wrapped_string.respond_to?(method, include_private)
73
74
  end
74
75
 
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
76
  # Works just like <tt>String#split</tt>, with the exception that the items
82
77
  # in the resulting list are Chars instances instead of String. This makes
83
78
  # chaining methods easier.
@@ -87,17 +82,27 @@ module ActiveSupport #:nodoc:
87
82
  @wrapped_string.split(*args).map { |i| self.class.new(i) }
88
83
  end
89
84
 
90
- # Works like like <tt>String#slice!</tt>, but returns an instance of
91
- # Chars, or nil if the string was not modified.
85
+ # Works like <tt>String#slice!</tt>, but returns an instance of
86
+ # Chars, or +nil+ if the string was not modified. The string will not be
87
+ # modified if the range given is out of bounds
88
+ #
89
+ # string = 'Welcome'
90
+ # string.mb_chars.slice!(3) # => #<ActiveSupport::Multibyte::Chars:0x000000038109b8 @wrapped_string="c">
91
+ # string # => 'Welome'
92
+ # string.mb_chars.slice!(0..3) # => #<ActiveSupport::Multibyte::Chars:0x00000002eb80a0 @wrapped_string="Welo">
93
+ # string # => 'me'
92
94
  def slice!(*args)
93
- chars(@wrapped_string.slice!(*args))
95
+ string_sliced = @wrapped_string.slice!(*args)
96
+ if string_sliced
97
+ chars(string_sliced)
98
+ end
94
99
  end
95
100
 
96
101
  # Reverses all characters in the string.
97
102
  #
98
103
  # 'Café'.mb_chars.reverse.to_s # => 'éfaC'
99
104
  def reverse
100
- chars(Unicode.unpack_graphemes(@wrapped_string).reverse.flatten.pack('U*'))
105
+ chars(@wrapped_string.grapheme_clusters.reverse.join)
101
106
  end
102
107
 
103
108
  # Limits the byte size of the string to a number of bytes without breaking
@@ -106,79 +111,40 @@ module ActiveSupport #:nodoc:
106
111
  #
107
112
  # 'こんにちは'.mb_chars.limit(7).to_s # => "こん"
108
113
  def limit(limit)
109
- slice(0...translate_offset(limit))
110
- end
111
-
112
- # Converts characters in the string to uppercase.
113
- #
114
- # 'Laurent, où sont les tests ?'.mb_chars.upcase.to_s # => "LAURENT, OÙ SONT LES TESTS ?"
115
- def upcase
116
- chars Unicode.upcase(@wrapped_string)
117
- end
118
-
119
- # Converts characters in the string to lowercase.
120
- #
121
- # 'VĚDA A VÝZKUM'.mb_chars.downcase.to_s # => "věda a výzkum"
122
- def downcase
123
- chars Unicode.downcase(@wrapped_string)
124
- end
125
-
126
- # Converts characters in the string to the opposite case.
127
- #
128
- # 'El Cañón".mb_chars.swapcase.to_s # => "eL cAÑÓN"
129
- def swapcase
130
- chars Unicode.swapcase(@wrapped_string)
131
- end
132
-
133
- # Converts the first character to uppercase and the remainder to lowercase.
134
- #
135
- # 'über'.mb_chars.capitalize.to_s # => "Über"
136
- def capitalize
137
- (slice(0) || chars('')).upcase + (slice(1..-1) || chars('')).downcase
114
+ chars(@wrapped_string.truncate_bytes(limit, omission: nil))
138
115
  end
139
116
 
140
117
  # Capitalizes the first letter of every word, when possible.
141
118
  #
142
- # "ÉL QUE SE ENTERÓ".mb_chars.titleize # => "Él Que Se Enteró"
143
- # "日本語".mb_chars.titleize # => "日本語"
119
+ # "ÉL QUE SE ENTERÓ".mb_chars.titleize.to_s # => "Él Que Se Enteró"
120
+ # "日本語".mb_chars.titleize.to_s # => "日本語"
144
121
  def titleize
145
- chars(downcase.to_s.gsub(/\b('?\S)/u) { Unicode.upcase($1)})
122
+ chars(downcase.to_s.gsub(/\b('?\S)/u) { $1.upcase })
146
123
  end
147
124
  alias_method :titlecase, :titleize
148
125
 
149
- # Returns the KC normalization of the string by default. NFKC is
150
- # considered the best normalization form for passing strings to databases
151
- # and validations.
152
- #
153
- # * <tt>form</tt> - The form you want to normalize in. Should be one of the following:
154
- # <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>. Default is
155
- # ActiveSupport::Multibyte::Unicode.default_normalization_form
156
- def normalize(form = nil)
157
- chars(Unicode.normalize(@wrapped_string, form))
158
- end
159
-
160
126
  # Performs canonical decomposition on all the characters.
161
127
  #
162
- # 'é'.length # => 2
163
- # 'é'.mb_chars.decompose.to_s.length # => 3
128
+ # 'é'.length # => 1
129
+ # 'é'.mb_chars.decompose.to_s.length # => 2
164
130
  def decompose
165
- chars(Unicode.decompose(:canonical, @wrapped_string.codepoints.to_a).pack('U*'))
131
+ chars(Unicode.decompose(:canonical, @wrapped_string.codepoints.to_a).pack("U*"))
166
132
  end
167
133
 
168
134
  # Performs composition on all the characters.
169
135
  #
170
- # 'é'.length # => 3
171
- # 'é'.mb_chars.compose.to_s.length # => 2
136
+ # 'é'.length # => 1
137
+ # 'é'.mb_chars.compose.to_s.length # => 1
172
138
  def compose
173
- chars(Unicode.compose(@wrapped_string.codepoints.to_a).pack('U*'))
139
+ chars(Unicode.compose(@wrapped_string.codepoints.to_a).pack("U*"))
174
140
  end
175
141
 
176
142
  # Returns the number of grapheme clusters in the string.
177
143
  #
178
144
  # 'क्षि'.mb_chars.length # => 4
179
- # 'क्षि'.mb_chars.grapheme_length # => 3
145
+ # 'क्षि'.mb_chars.grapheme_length # => 2
180
146
  def grapheme_length
181
- Unicode.unpack_graphemes(@wrapped_string).length
147
+ @wrapped_string.grapheme_clusters.length
182
148
  end
183
149
 
184
150
  # Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent
@@ -190,32 +156,19 @@ module ActiveSupport #:nodoc:
190
156
  chars(Unicode.tidy_bytes(@wrapped_string, force))
191
157
  end
192
158
 
193
- def as_json(options = nil) #:nodoc:
159
+ def as_json(options = nil) # :nodoc:
194
160
  to_s.as_json(options)
195
161
  end
196
162
 
197
- %w(capitalize downcase reverse tidy_bytes upcase).each do |method|
163
+ %w(reverse tidy_bytes).each do |method|
198
164
  define_method("#{method}!") do |*args|
199
- @wrapped_string = send(method, *args).to_s
165
+ @wrapped_string = public_send(method, *args).to_s
200
166
  self
201
167
  end
202
168
  end
203
169
 
204
- protected
205
-
206
- def translate_offset(byte_offset) #:nodoc:
207
- return nil if byte_offset.nil?
208
- return 0 if @wrapped_string == ''
209
-
210
- begin
211
- @wrapped_string.byteslice(0...byte_offset).unpack('U*').length
212
- rescue ArgumentError
213
- byte_offset -= 1
214
- retry
215
- end
216
- end
217
-
218
- def chars(string) #:nodoc:
170
+ private
171
+ def chars(string)
219
172
  self.class.new(string)
220
173
  end
221
174
  end