activesupport 4.2.11.1 → 5.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 (256) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +399 -440
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +4 -5
  5. data/lib/active_support/all.rb +5 -3
  6. data/lib/active_support/array_inquirer.rb +48 -0
  7. data/lib/active_support/backtrace_cleaner.rb +7 -5
  8. data/lib/active_support/benchmarkable.rb +6 -4
  9. data/lib/active_support/builder.rb +3 -1
  10. data/lib/active_support/cache/file_store.rb +41 -35
  11. data/lib/active_support/cache/mem_cache_store.rb +97 -88
  12. data/lib/active_support/cache/memory_store.rb +27 -30
  13. data/lib/active_support/cache/null_store.rb +7 -8
  14. data/lib/active_support/cache/redis_cache_store.rb +461 -0
  15. data/lib/active_support/cache/strategy/local_cache.rb +67 -34
  16. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  17. data/lib/active_support/cache.rb +287 -196
  18. data/lib/active_support/callbacks.rb +640 -590
  19. data/lib/active_support/concern.rb +11 -5
  20. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
  21. data/lib/active_support/concurrency/share_lock.rb +227 -0
  22. data/lib/active_support/configurable.rb +8 -5
  23. data/lib/active_support/core_ext/array/access.rb +29 -1
  24. data/lib/active_support/core_ext/array/conversions.rb +22 -18
  25. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  26. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  27. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  28. data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
  29. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  30. data/lib/active_support/core_ext/array.rb +9 -6
  31. data/lib/active_support/core_ext/benchmark.rb +3 -1
  32. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  33. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  34. data/lib/active_support/core_ext/class/attribute.rb +41 -22
  35. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  36. data/lib/active_support/core_ext/class/subclasses.rb +20 -6
  37. data/lib/active_support/core_ext/class.rb +4 -3
  38. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  39. data/lib/active_support/core_ext/date/blank.rb +14 -0
  40. data/lib/active_support/core_ext/date/calculations.rb +11 -9
  41. data/lib/active_support/core_ext/date/conversions.rb +25 -23
  42. data/lib/active_support/core_ext/date/zones.rb +4 -2
  43. data/lib/active_support/core_ext/date.rb +6 -4
  44. data/lib/active_support/core_ext/date_and_time/calculations.rb +170 -58
  45. data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -3
  46. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
  47. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  48. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  49. data/lib/active_support/core_ext/date_time/calculations.rb +36 -18
  50. data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
  51. data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
  52. data/lib/active_support/core_ext/date_time.rb +7 -5
  53. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  54. data/lib/active_support/core_ext/digest.rb +3 -0
  55. data/lib/active_support/core_ext/enumerable.rb +101 -33
  56. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  57. data/lib/active_support/core_ext/file.rb +3 -1
  58. data/lib/active_support/core_ext/hash/compact.rb +14 -9
  59. data/lib/active_support/core_ext/hash/conversions.rb +62 -41
  60. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  61. data/lib/active_support/core_ext/hash/except.rb +11 -8
  62. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  63. data/lib/active_support/core_ext/hash/keys.rb +33 -27
  64. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  65. data/lib/active_support/core_ext/hash/slice.rb +8 -8
  66. data/lib/active_support/core_ext/hash/transform_values.rb +14 -5
  67. data/lib/active_support/core_ext/hash.rb +11 -9
  68. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  69. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  70. data/lib/active_support/core_ext/integer/time.rb +11 -18
  71. data/lib/active_support/core_ext/integer.rb +5 -3
  72. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  73. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  74. data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
  75. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  76. data/lib/active_support/core_ext/kernel.rb +6 -5
  77. data/lib/active_support/core_ext/load_error.rb +3 -22
  78. data/lib/active_support/core_ext/marshal.rb +8 -8
  79. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  80. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  81. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  82. data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
  83. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
  84. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  85. data/lib/active_support/core_ext/module/delegation.rb +99 -29
  86. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  87. data/lib/active_support/core_ext/module/introspection.rb +9 -9
  88. data/lib/active_support/core_ext/module/reachable.rb +5 -2
  89. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  90. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  91. data/lib/active_support/core_ext/module.rb +14 -11
  92. data/lib/active_support/core_ext/name_error.rb +22 -2
  93. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  94. data/lib/active_support/core_ext/numeric/conversions.rb +78 -81
  95. data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
  96. data/lib/active_support/core_ext/numeric/time.rb +35 -23
  97. data/lib/active_support/core_ext/numeric.rb +6 -3
  98. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  99. data/lib/active_support/core_ext/object/blank.rb +27 -2
  100. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  101. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  102. data/lib/active_support/core_ext/object/duplicable.rb +41 -14
  103. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  104. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  105. data/lib/active_support/core_ext/object/json.rb +49 -19
  106. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  107. data/lib/active_support/core_ext/object/to_query.rb +10 -5
  108. data/lib/active_support/core_ext/object/try.rb +69 -21
  109. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  110. data/lib/active_support/core_ext/object.rb +14 -13
  111. data/lib/active_support/core_ext/range/compare_range.rb +61 -0
  112. data/lib/active_support/core_ext/range/conversions.rb +27 -7
  113. data/lib/active_support/core_ext/range/each.rb +19 -17
  114. data/lib/active_support/core_ext/range/include_range.rb +2 -22
  115. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  116. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  117. data/lib/active_support/core_ext/range.rb +7 -4
  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/access.rb +8 -6
  121. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  122. data/lib/active_support/core_ext/string/conversions.rb +7 -4
  123. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  124. data/lib/active_support/core_ext/string/filters.rb +6 -5
  125. data/lib/active_support/core_ext/string/indent.rb +6 -4
  126. data/lib/active_support/core_ext/string/inflections.rb +61 -24
  127. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  128. data/lib/active_support/core_ext/string/multibyte.rb +15 -7
  129. data/lib/active_support/core_ext/string/output_safety.rb +34 -38
  130. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  131. data/lib/active_support/core_ext/string/strip.rb +4 -5
  132. data/lib/active_support/core_ext/string/zones.rb +4 -2
  133. data/lib/active_support/core_ext/string.rb +15 -13
  134. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  135. data/lib/active_support/core_ext/time/calculations.rb +85 -51
  136. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  137. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  138. data/lib/active_support/core_ext/time/zones.rb +41 -7
  139. data/lib/active_support/core_ext/time.rb +7 -6
  140. data/lib/active_support/core_ext/uri.rb +6 -8
  141. data/lib/active_support/core_ext.rb +3 -1
  142. data/lib/active_support/current_attributes.rb +195 -0
  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/dependencies.rb +152 -161
  146. data/lib/active_support/deprecation/behaviors.rb +44 -11
  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 +66 -20
  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/deprecation.rb +12 -9
  153. data/lib/active_support/descendants_tracker.rb +2 -0
  154. data/lib/active_support/digest.rb +20 -0
  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/duration.rb +307 -35
  158. data/lib/active_support/encrypted_configuration.rb +49 -0
  159. data/lib/active_support/encrypted_file.rb +99 -0
  160. data/lib/active_support/evented_file_update_checker.rb +205 -0
  161. data/lib/active_support/execution_wrapper.rb +128 -0
  162. data/lib/active_support/executor.rb +8 -0
  163. data/lib/active_support/file_update_checker.rb +63 -37
  164. data/lib/active_support/gem_version.rb +6 -4
  165. data/lib/active_support/gzip.rb +7 -5
  166. data/lib/active_support/hash_with_indifferent_access.rb +123 -28
  167. data/lib/active_support/i18n.rb +8 -6
  168. data/lib/active_support/i18n_railtie.rb +37 -13
  169. data/lib/active_support/inflections.rb +13 -11
  170. data/lib/active_support/inflector/inflections.rb +61 -12
  171. data/lib/active_support/inflector/methods.rb +163 -136
  172. data/lib/active_support/inflector/transliterate.rb +48 -27
  173. data/lib/active_support/inflector.rb +7 -5
  174. data/lib/active_support/json/decoding.rb +16 -13
  175. data/lib/active_support/json/encoding.rb +11 -58
  176. data/lib/active_support/json.rb +4 -2
  177. data/lib/active_support/key_generator.rb +25 -25
  178. data/lib/active_support/lazy_load_hooks.rb +50 -20
  179. data/lib/active_support/locale/en.yml +2 -0
  180. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  181. data/lib/active_support/log_subscriber.rb +13 -10
  182. data/lib/active_support/logger.rb +8 -7
  183. data/lib/active_support/logger_silence.rb +6 -4
  184. data/lib/active_support/logger_thread_safe_level.rb +7 -5
  185. data/lib/active_support/message_encryptor.rb +168 -53
  186. data/lib/active_support/message_verifier.rb +150 -17
  187. data/lib/active_support/messages/metadata.rb +71 -0
  188. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  189. data/lib/active_support/messages/rotator.rb +56 -0
  190. data/lib/active_support/multibyte/chars.rb +36 -23
  191. data/lib/active_support/multibyte/unicode.rb +100 -96
  192. data/lib/active_support/multibyte.rb +4 -2
  193. data/lib/active_support/notifications/fanout.rb +11 -9
  194. data/lib/active_support/notifications/instrumenter.rb +27 -7
  195. data/lib/active_support/notifications.rb +11 -7
  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/number_helper.rb +94 -68
  206. data/lib/active_support/option_merger.rb +3 -1
  207. data/lib/active_support/ordered_hash.rb +6 -4
  208. data/lib/active_support/ordered_options.rb +23 -5
  209. data/lib/active_support/per_thread_registry.rb +9 -4
  210. data/lib/active_support/proxy_object.rb +2 -0
  211. data/lib/active_support/rails.rb +16 -8
  212. data/lib/active_support/railtie.rb +43 -9
  213. data/lib/active_support/reloader.rb +131 -0
  214. data/lib/active_support/rescuable.rb +108 -53
  215. data/lib/active_support/security_utils.rb +15 -11
  216. data/lib/active_support/string_inquirer.rb +11 -3
  217. data/lib/active_support/subscriber.rb +21 -16
  218. data/lib/active_support/tagged_logging.rb +14 -11
  219. data/lib/active_support/test_case.rb +19 -47
  220. data/lib/active_support/testing/assertions.rb +137 -20
  221. data/lib/active_support/testing/autorun.rb +4 -2
  222. data/lib/active_support/testing/constant_lookup.rb +2 -1
  223. data/lib/active_support/testing/declarative.rb +3 -1
  224. data/lib/active_support/testing/deprecation.rb +14 -10
  225. data/lib/active_support/testing/file_fixtures.rb +36 -0
  226. data/lib/active_support/testing/isolation.rb +34 -25
  227. data/lib/active_support/testing/method_call_assertions.rb +43 -0
  228. data/lib/active_support/testing/setup_and_teardown.rb +13 -8
  229. data/lib/active_support/testing/stream.rb +44 -0
  230. data/lib/active_support/testing/tagged_logging.rb +3 -1
  231. data/lib/active_support/testing/time_helpers.rb +81 -15
  232. data/lib/active_support/time.rb +14 -12
  233. data/lib/active_support/time_with_zone.rb +169 -39
  234. data/lib/active_support/values/time_zone.rb +196 -61
  235. data/lib/active_support/values/unicode_tables.dat +0 -0
  236. data/lib/active_support/version.rb +3 -1
  237. data/lib/active_support/xml_mini/jdom.rb +116 -114
  238. data/lib/active_support/xml_mini/libxml.rb +16 -13
  239. data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
  240. data/lib/active_support/xml_mini/nokogiri.rb +14 -12
  241. data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
  242. data/lib/active_support/xml_mini/rexml.rb +11 -9
  243. data/lib/active_support/xml_mini.rb +37 -37
  244. data/lib/active_support.rb +12 -11
  245. metadata +54 -24
  246. data/lib/active_support/concurrency/latch.rb +0 -27
  247. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
  248. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  249. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  250. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  251. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
  252. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  253. data/lib/active_support/core_ext/object/itself.rb +0 -15
  254. data/lib/active_support/core_ext/struct.rb +0 -6
  255. data/lib/active_support/core_ext/thread.rb +0 -86
  256. data/lib/active_support/core_ext/time/marshal.rb +0 -30
@@ -1,8 +1,10 @@
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'
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
+ require "active_support/core_ext/regexp"
6
8
 
7
9
  module ActiveSupport #:nodoc:
8
10
  module Multibyte #:nodoc:
@@ -16,7 +18,8 @@ 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 # => "the perfect string"
21
+ # 'The Perfect String '.mb_chars.downcase.strip.normalize
22
+ # # => #<ActiveSupport::Multibyte::Chars:0x007fdc434ccc10 @wrapped_string="the perfect string">
20
23
  #
21
24
  # Chars objects are perfectly interchangeable with String objects as long as
22
25
  # no explicit class checks are made. If certain methods do explicitly check
@@ -46,7 +49,7 @@ module ActiveSupport #:nodoc:
46
49
  alias to_s wrapped_string
47
50
  alias to_str wrapped_string
48
51
 
49
- delegate :<=>, :=~, :acts_like_string?, :to => :wrapped_string
52
+ delegate :<=>, :=~, :acts_like_string?, to: :wrapped_string
50
53
 
51
54
  # Creates a new Chars instance by wrapping _string_.
52
55
  def initialize(string)
@@ -57,7 +60,7 @@ module ActiveSupport #:nodoc:
57
60
  # Forward all undefined methods to the wrapped string.
58
61
  def method_missing(method, *args, &block)
59
62
  result = @wrapped_string.__send__(method, *args, &block)
60
- if method.to_s =~ /!$/
63
+ if /!$/.match?(method)
61
64
  self if result
62
65
  else
63
66
  result.kind_of?(String) ? chars(result) : result
@@ -87,16 +90,26 @@ module ActiveSupport #:nodoc:
87
90
  end
88
91
 
89
92
  # Works like <tt>String#slice!</tt>, but returns an instance of
90
- # Chars, or nil if the string was not modified.
93
+ # Chars, or +nil+ if the string was not modified. The string will not be
94
+ # modified if the range given is out of bounds
95
+ #
96
+ # string = 'Welcome'
97
+ # string.mb_chars.slice!(3) # => #<ActiveSupport::Multibyte::Chars:0x000000038109b8 @wrapped_string="c">
98
+ # string # => 'Welome'
99
+ # string.mb_chars.slice!(0..3) # => #<ActiveSupport::Multibyte::Chars:0x00000002eb80a0 @wrapped_string="Welo">
100
+ # string # => 'me'
91
101
  def slice!(*args)
92
- chars(@wrapped_string.slice!(*args))
102
+ string_sliced = @wrapped_string.slice!(*args)
103
+ if string_sliced
104
+ chars(string_sliced)
105
+ end
93
106
  end
94
107
 
95
108
  # Reverses all characters in the string.
96
109
  #
97
110
  # 'Café'.mb_chars.reverse.to_s # => 'éfaC'
98
111
  def reverse
99
- chars(Unicode.unpack_graphemes(@wrapped_string).reverse.flatten.pack('U*'))
112
+ chars(Unicode.unpack_graphemes(@wrapped_string).reverse.flatten.pack("U*"))
100
113
  end
101
114
 
102
115
  # Limits the byte size of the string to a number of bytes without breaking
@@ -124,7 +137,7 @@ module ActiveSupport #:nodoc:
124
137
 
125
138
  # Converts characters in the string to the opposite case.
126
139
  #
127
- # 'El Cañón".mb_chars.swapcase.to_s # => "eL cAÑÓN"
140
+ # 'El Cañón'.mb_chars.swapcase.to_s # => "eL cAÑÓN"
128
141
  def swapcase
129
142
  chars Unicode.swapcase(@wrapped_string)
130
143
  end
@@ -133,15 +146,15 @@ module ActiveSupport #:nodoc:
133
146
  #
134
147
  # 'über'.mb_chars.capitalize.to_s # => "Über"
135
148
  def capitalize
136
- (slice(0) || chars('')).upcase + (slice(1..-1) || chars('')).downcase
149
+ (slice(0) || chars("")).upcase + (slice(1..-1) || chars("")).downcase
137
150
  end
138
151
 
139
152
  # Capitalizes the first letter of every word, when possible.
140
153
  #
141
- # "ÉL QUE SE ENTERÓ".mb_chars.titleize # => "Él Que Se Enteró"
142
- # "日本語".mb_chars.titleize # => "日本語"
154
+ # "ÉL QUE SE ENTERÓ".mb_chars.titleize.to_s # => "Él Que Se Enteró"
155
+ # "日本語".mb_chars.titleize.to_s # => "日本語"
143
156
  def titleize
144
- chars(downcase.to_s.gsub(/\b('?\S)/u) { Unicode.upcase($1)})
157
+ chars(downcase.to_s.gsub(/\b('?\S)/u) { Unicode.upcase($1) })
145
158
  end
146
159
  alias_method :titlecase, :titleize
147
160
 
@@ -161,7 +174,7 @@ module ActiveSupport #:nodoc:
161
174
  # 'é'.length # => 2
162
175
  # 'é'.mb_chars.decompose.to_s.length # => 3
163
176
  def decompose
164
- chars(Unicode.decompose(:canonical, @wrapped_string.codepoints.to_a).pack('U*'))
177
+ chars(Unicode.decompose(:canonical, @wrapped_string.codepoints.to_a).pack("U*"))
165
178
  end
166
179
 
167
180
  # Performs composition on all the characters.
@@ -169,7 +182,7 @@ module ActiveSupport #:nodoc:
169
182
  # 'é'.length # => 3
170
183
  # 'é'.mb_chars.compose.to_s.length # => 2
171
184
  def compose
172
- chars(Unicode.compose(@wrapped_string.codepoints.to_a).pack('U*'))
185
+ chars(Unicode.compose(@wrapped_string.codepoints.to_a).pack("U*"))
173
186
  end
174
187
 
175
188
  # Returns the number of grapheme clusters in the string.
@@ -200,21 +213,21 @@ module ActiveSupport #:nodoc:
200
213
  end
201
214
  end
202
215
 
203
- protected
216
+ private
204
217
 
205
- def translate_offset(byte_offset) #:nodoc:
218
+ def translate_offset(byte_offset)
206
219
  return nil if byte_offset.nil?
207
- return 0 if @wrapped_string == ''
220
+ return 0 if @wrapped_string == ""
208
221
 
209
222
  begin
210
- @wrapped_string.byteslice(0...byte_offset).unpack('U*').length
223
+ @wrapped_string.byteslice(0...byte_offset).unpack("U*").length
211
224
  rescue ArgumentError
212
225
  byte_offset -= 1
213
226
  retry
214
227
  end
215
228
  end
216
229
 
217
- def chars(string) #:nodoc:
230
+ def chars(string)
218
231
  self.class.new(string)
219
232
  end
220
233
  end
@@ -1,8 +1,8 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  module ActiveSupport
3
4
  module Multibyte
4
5
  module Unicode
5
-
6
6
  extend self
7
7
 
8
8
  # A list of all available normalization forms.
@@ -11,7 +11,7 @@ module ActiveSupport
11
11
  NORMALIZATION_FORMS = [:c, :kc, :d, :kd]
12
12
 
13
13
  # The Unicode version that is supported by the implementation
14
- UNICODE_VERSION = '7.0.0'
14
+ UNICODE_VERSION = "9.0.0"
15
15
 
16
16
  # The default normalization used for operations that require
17
17
  # normalization. It can be set to any of the normalizations
@@ -32,36 +32,6 @@ module ActiveSupport
32
32
  HANGUL_NCOUNT = HANGUL_VCOUNT * HANGUL_TCOUNT
33
33
  HANGUL_SCOUNT = 11172
34
34
  HANGUL_SLAST = HANGUL_SBASE + HANGUL_SCOUNT
35
- HANGUL_JAMO_FIRST = 0x1100
36
- HANGUL_JAMO_LAST = 0x11FF
37
-
38
- # All the unicode whitespace
39
- WHITESPACE = [
40
- (0x0009..0x000D).to_a, # White_Space # Cc [5] <control-0009>..<control-000D>
41
- 0x0020, # White_Space # Zs SPACE
42
- 0x0085, # White_Space # Cc <control-0085>
43
- 0x00A0, # White_Space # Zs NO-BREAK SPACE
44
- 0x1680, # White_Space # Zs OGHAM SPACE MARK
45
- (0x2000..0x200A).to_a, # White_Space # Zs [11] EN QUAD..HAIR SPACE
46
- 0x2028, # White_Space # Zl LINE SEPARATOR
47
- 0x2029, # White_Space # Zp PARAGRAPH SEPARATOR
48
- 0x202F, # White_Space # Zs NARROW NO-BREAK SPACE
49
- 0x205F, # White_Space # Zs MEDIUM MATHEMATICAL SPACE
50
- 0x3000, # White_Space # Zs IDEOGRAPHIC SPACE
51
- ].flatten.freeze
52
-
53
- # BOM (byte order mark) can also be seen as whitespace, it's a
54
- # non-rendering character used to distinguish between little and big
55
- # endian. This is not an issue in utf-8, so it must be ignored.
56
- LEADERS_AND_TRAILERS = WHITESPACE + [65279] # ZERO-WIDTH NO-BREAK SPACE aka BOM
57
-
58
- # Returns a regular expression pattern that matches the passed Unicode
59
- # codepoints.
60
- def self.codepoints_to_pattern(array_of_codepoints) #:nodoc:
61
- array_of_codepoints.collect{ |e| [e].pack 'U*' }.join('|')
62
- end
63
- TRAILERS_PAT = /(#{codepoints_to_pattern(LEADERS_AND_TRAILERS)})+\Z/u
64
- LEADERS_PAT = /\A(#{codepoints_to_pattern(LEADERS_AND_TRAILERS)})+/u
65
35
 
66
36
  # Detect whether the codepoint is in a certain character class. Returns
67
37
  # +true+ when it's in the specified character class and +false+ otherwise.
@@ -84,24 +54,59 @@ module ActiveSupport
84
54
  pos = 0
85
55
  marker = 0
86
56
  eoc = codepoints.length
87
- while(pos < eoc)
57
+ while (pos < eoc)
88
58
  pos += 1
89
- previous = codepoints[pos-1]
59
+ previous = codepoints[pos - 1]
90
60
  current = codepoints[pos]
91
- if (
92
- # CR X LF
93
- ( previous == database.boundary[:cr] and current == database.boundary[:lf] ) or
94
- # L X (L|V|LV|LVT)
95
- ( database.boundary[:l] === previous and in_char_class?(current, [:l,:v,:lv,:lvt]) ) or
96
- # (LV|V) X (V|T)
97
- ( in_char_class?(previous, [:lv,:v]) and in_char_class?(current, [:v,:t]) ) or
98
- # (LVT|T) X (T)
99
- ( in_char_class?(previous, [:lvt,:t]) and database.boundary[:t] === current ) or
100
- # X Extend
101
- (database.boundary[:extend] === current)
102
- )
103
- else
104
- unpacked << codepoints[marker..pos-1]
61
+
62
+ # See http://unicode.org/reports/tr29/#Grapheme_Cluster_Boundary_Rules
63
+ should_break =
64
+ if pos == eoc
65
+ true
66
+ # GB3. CR X LF
67
+ elsif previous == database.boundary[:cr] && current == database.boundary[:lf]
68
+ false
69
+ # GB4. (Control|CR|LF) ÷
70
+ elsif previous && in_char_class?(previous, [:control, :cr, :lf])
71
+ true
72
+ # GB5. ÷ (Control|CR|LF)
73
+ elsif in_char_class?(current, [:control, :cr, :lf])
74
+ true
75
+ # GB6. L X (L|V|LV|LVT)
76
+ elsif database.boundary[:l] === previous && in_char_class?(current, [:l, :v, :lv, :lvt])
77
+ false
78
+ # GB7. (LV|V) X (V|T)
79
+ elsif in_char_class?(previous, [:lv, :v]) && in_char_class?(current, [:v, :t])
80
+ false
81
+ # GB8. (LVT|T) X (T)
82
+ elsif in_char_class?(previous, [:lvt, :t]) && database.boundary[:t] === current
83
+ false
84
+ # GB9. X (Extend | ZWJ)
85
+ elsif in_char_class?(current, [:extend, :zwj])
86
+ false
87
+ # GB9a. X SpacingMark
88
+ elsif database.boundary[:spacingmark] === current
89
+ false
90
+ # GB9b. Prepend X
91
+ elsif database.boundary[:prepend] === previous
92
+ false
93
+ # GB10. (E_Base | EBG) Extend* X E_Modifier
94
+ elsif (marker...pos).any? { |i| in_char_class?(codepoints[i], [:e_base, :e_base_gaz]) && codepoints[i + 1...pos].all? { |c| database.boundary[:extend] === c } } && database.boundary[:e_modifier] === current
95
+ false
96
+ # GB11. ZWJ X (Glue_After_Zwj | EBG)
97
+ elsif database.boundary[:zwj] === previous && in_char_class?(current, [:glue_after_zwj, :e_base_gaz])
98
+ false
99
+ # GB12. ^ (RI RI)* RI X RI
100
+ # GB13. [^RI] (RI RI)* RI X RI
101
+ elsif codepoints[marker..pos].all? { |c| database.boundary[:regional_indicator] === c } && codepoints[marker..pos].count { |c| database.boundary[:regional_indicator] === c }.even?
102
+ false
103
+ # GB999. Any ÷ Any
104
+ else
105
+ true
106
+ end
107
+
108
+ if should_break
109
+ unpacked << codepoints[marker..pos - 1]
105
110
  marker = pos
106
111
  end
107
112
  end
@@ -112,17 +117,17 @@ module ActiveSupport
112
117
  #
113
118
  # Unicode.pack_graphemes(Unicode.unpack_graphemes('क्षि')) # => 'क्षि'
114
119
  def pack_graphemes(unpacked)
115
- unpacked.flatten.pack('U*')
120
+ unpacked.flatten.pack("U*")
116
121
  end
117
122
 
118
123
  # Re-order codepoints so the string becomes canonical.
119
124
  def reorder_characters(codepoints)
120
- length = codepoints.length- 1
125
+ length = codepoints.length - 1
121
126
  pos = 0
122
127
  while pos < length do
123
- cp1, cp2 = database.codepoints[codepoints[pos]], database.codepoints[codepoints[pos+1]]
128
+ cp1, cp2 = database.codepoints[codepoints[pos]], database.codepoints[codepoints[pos + 1]]
124
129
  if (cp1.combining_class > cp2.combining_class) && (cp2.combining_class > 0)
125
- codepoints[pos..pos+1] = cp2.code, cp1.code
130
+ codepoints[pos..pos + 1] = cp2.code, cp1.code
126
131
  pos += (pos > 0 ? -1 : 1)
127
132
  else
128
133
  pos += 1
@@ -135,7 +140,7 @@ module ActiveSupport
135
140
  def decompose(type, codepoints)
136
141
  codepoints.inject([]) do |decomposed, cp|
137
142
  # if it's a hangul syllable starter character
138
- if HANGUL_SBASE <= cp and cp < HANGUL_SLAST
143
+ if HANGUL_SBASE <= cp && cp < HANGUL_SLAST
139
144
  sindex = cp - HANGUL_SBASE
140
145
  ncp = [] # new codepoints
141
146
  ncp << HANGUL_LBASE + sindex / HANGUL_NCOUNT
@@ -144,7 +149,7 @@ module ActiveSupport
144
149
  ncp << (HANGUL_TBASE + tindex) unless tindex == 0
145
150
  decomposed.concat ncp
146
151
  # if the codepoint is decomposable in with the current decomposition type
147
- elsif (ncp = database.codepoints[cp].decomp_mapping) and (!database.codepoints[cp].decomp_type || type == :compatibility)
152
+ elsif (ncp = database.codepoints[cp].decomp_mapping) && (!database.codepoints[cp].decomp_type || type == :compatibility)
148
153
  decomposed.concat decompose(type, ncp.dup)
149
154
  else
150
155
  decomposed << cp
@@ -163,11 +168,11 @@ module ActiveSupport
163
168
  pos += 1
164
169
  lindex = starter_char - HANGUL_LBASE
165
170
  # -- Hangul
166
- if 0 <= lindex and lindex < HANGUL_LCOUNT
167
- vindex = codepoints[starter_pos+1] - HANGUL_VBASE rescue vindex = -1
168
- if 0 <= vindex and vindex < HANGUL_VCOUNT
169
- tindex = codepoints[starter_pos+2] - HANGUL_TBASE rescue tindex = -1
170
- if 0 <= tindex and tindex < HANGUL_TCOUNT
171
+ if 0 <= lindex && lindex < HANGUL_LCOUNT
172
+ vindex = codepoints[starter_pos + 1] - HANGUL_VBASE rescue vindex = -1
173
+ if 0 <= vindex && vindex < HANGUL_VCOUNT
174
+ tindex = codepoints[starter_pos + 2] - HANGUL_TBASE rescue tindex = -1
175
+ if 0 <= tindex && tindex < HANGUL_TCOUNT
171
176
  j = starter_pos + 2
172
177
  eoa -= 2
173
178
  else
@@ -211,9 +216,8 @@ module ActiveSupport
211
216
  codepoints
212
217
  end
213
218
 
214
- # Ruby >= 2.1 has String#scrub, which is faster than the workaround used for < 2.1.
215
219
  # Rubinius' String#scrub, however, doesn't support ASCII-incompatible chars.
216
- if '<3'.respond_to?(:scrub) && !defined?(Rubinius)
220
+ if !defined?(Rubinius)
217
221
  # Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent
218
222
  # resulting in a valid UTF-8 string.
219
223
  #
@@ -236,7 +240,7 @@ module ActiveSupport
236
240
  reader = Encoding::Converter.new(Encoding::UTF_8, Encoding::UTF_16LE)
237
241
 
238
242
  source = string.dup
239
- out = ''.force_encoding(Encoding::UTF_16LE)
243
+ out = "".force_encoding(Encoding::UTF_16LE)
240
244
 
241
245
  loop do
242
246
  reader.primitive_convert(source, out)
@@ -258,23 +262,23 @@ module ActiveSupport
258
262
  # * <tt>string</tt> - The string to perform normalization on.
259
263
  # * <tt>form</tt> - The form you want to normalize in. Should be one of
260
264
  # the following: <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>.
261
- # Default is ActiveSupport::Multibyte.default_normalization_form.
262
- def normalize(string, form=nil)
265
+ # Default is ActiveSupport::Multibyte::Unicode.default_normalization_form.
266
+ def normalize(string, form = nil)
263
267
  form ||= @default_normalization_form
264
268
  # See http://www.unicode.org/reports/tr15, Table 1
265
269
  codepoints = string.codepoints.to_a
266
270
  case form
267
- when :d
268
- reorder_characters(decompose(:canonical, codepoints))
269
- when :c
270
- compose(reorder_characters(decompose(:canonical, codepoints)))
271
- when :kd
272
- reorder_characters(decompose(:compatibility, codepoints))
273
- when :kc
274
- compose(reorder_characters(decompose(:compatibility, codepoints)))
275
- else
276
- raise ArgumentError, "#{form} is not a valid normalization variant", caller
277
- end.pack('U*')
271
+ when :d
272
+ reorder_characters(decompose(:canonical, codepoints))
273
+ when :c
274
+ compose(reorder_characters(decompose(:canonical, codepoints)))
275
+ when :kd
276
+ reorder_characters(decompose(:compatibility, codepoints))
277
+ when :kc
278
+ compose(reorder_characters(decompose(:compatibility, codepoints)))
279
+ else
280
+ raise ArgumentError, "#{form} is not a valid normalization variant", caller
281
+ end.pack("U*".freeze)
278
282
  end
279
283
 
280
284
  def downcase(string)
@@ -333,13 +337,13 @@ module ActiveSupport
333
337
  # UnicodeDatabase.
334
338
  def load
335
339
  begin
336
- @codepoints, @composition_exclusion, @composition_map, @boundary, @cp1252 = File.open(self.class.filename, 'rb') { |f| Marshal.load f.read }
340
+ @codepoints, @composition_exclusion, @composition_map, @boundary, @cp1252 = File.open(self.class.filename, "rb") { |f| Marshal.load f.read }
337
341
  rescue => e
338
342
  raise IOError.new("Couldn't load the Unicode tables for UTF8Handler (#{e.message}), ActiveSupport::Multibyte is unusable")
339
343
  end
340
344
 
341
345
  # Redefine the === method so we can write shorter rules for grapheme cluster breaks
342
- @boundary.each do |k,_|
346
+ @boundary.each_key do |k|
343
347
  @boundary[k].instance_eval do
344
348
  def ===(other)
345
349
  detect { |i| i === other } ? true : false
@@ -355,7 +359,7 @@ module ActiveSupport
355
359
 
356
360
  # Returns the directory in which the data files are stored.
357
361
  def self.dirname
358
- File.dirname(__FILE__) + '/../values/'
362
+ File.expand_path("../values", __dir__)
359
363
  end
360
364
 
361
365
  # Returns the filename for the data file for this version.
@@ -366,25 +370,25 @@ module ActiveSupport
366
370
 
367
371
  private
368
372
 
369
- def apply_mapping(string, mapping) #:nodoc:
370
- database.codepoints
371
- string.each_codepoint.map do |codepoint|
372
- cp = database.codepoints[codepoint]
373
- if cp and (ncp = cp.send(mapping)) and ncp > 0
374
- ncp
375
- else
376
- codepoint
377
- end
378
- end.pack('U*')
379
- end
373
+ def apply_mapping(string, mapping)
374
+ database.codepoints
375
+ string.each_codepoint.map do |codepoint|
376
+ cp = database.codepoints[codepoint]
377
+ if cp && (ncp = cp.send(mapping)) && ncp > 0
378
+ ncp
379
+ else
380
+ codepoint
381
+ end
382
+ end.pack("U*")
383
+ end
380
384
 
381
- def recode_windows1252_chars(string)
382
- string.encode(Encoding::UTF_8, Encoding::Windows_1252, invalid: :replace, undef: :replace)
383
- end
385
+ def recode_windows1252_chars(string)
386
+ string.encode(Encoding::UTF_8, Encoding::Windows_1252, invalid: :replace, undef: :replace)
387
+ end
384
388
 
385
- def database
386
- @database ||= UnicodeDatabase.new
387
- end
389
+ def database
390
+ @database ||= UnicodeDatabase.new
391
+ end
388
392
  end
389
393
  end
390
394
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport #:nodoc:
2
4
  module Multibyte
3
- autoload :Chars, 'active_support/multibyte/chars'
4
- autoload :Unicode, 'active_support/multibyte/unicode'
5
+ autoload :Chars, "active_support/multibyte/chars"
6
+ autoload :Unicode, "active_support/multibyte/unicode"
5
7
 
6
8
  # The proxy class returned when calling mb_chars. You can use this accessor
7
9
  # to configure your own proxy class so you can support other encodings. See
@@ -1,5 +1,7 @@
1
- require 'mutex_m'
2
- require 'thread_safe'
1
+ # frozen_string_literal: true
2
+
3
+ require "mutex_m"
4
+ require "concurrent/map"
3
5
 
4
6
  module ActiveSupport
5
7
  module Notifications
@@ -12,12 +14,12 @@ module ActiveSupport
12
14
 
13
15
  def initialize
14
16
  @subscribers = []
15
- @listeners_for = ThreadSafe::Cache.new
17
+ @listeners_for = Concurrent::Map.new
16
18
  super
17
19
  end
18
20
 
19
- def subscribe(pattern = nil, block = Proc.new)
20
- subscriber = Subscribers.new pattern, block
21
+ def subscribe(pattern = nil, callable = nil, &block)
22
+ subscriber = Subscribers.new(pattern, callable || block)
21
23
  synchronize do
22
24
  @subscribers << subscriber
23
25
  @listeners_for.clear
@@ -42,8 +44,8 @@ module ActiveSupport
42
44
  listeners_for(name).each { |s| s.start(name, id, payload) }
43
45
  end
44
46
 
45
- def finish(name, id, payload)
46
- listeners_for(name).each { |s| s.finish(name, id, payload) }
47
+ def finish(name, id, payload, listeners = listeners_for(name))
48
+ listeners.each { |s| s.finish(name, id, payload) }
47
49
  end
48
50
 
49
51
  def publish(name, *args)
@@ -51,7 +53,7 @@ module ActiveSupport
51
53
  end
52
54
 
53
55
  def listeners_for(name)
54
- # this is correctly done double-checked locking (ThreadSafe::Cache's lookups have volatile semantics)
56
+ # this is correctly done double-checked locking (Concurrent::Map's lookups have volatile semantics)
55
57
  @listeners_for[name] || synchronize do
56
58
  # use synchronisation when accessing @subscribers
57
59
  @listeners_for[name] ||= @subscribers.select { |s| s.subscribed_to?(name) }
@@ -68,7 +70,7 @@ module ActiveSupport
68
70
 
69
71
  module Subscribers # :nodoc:
70
72
  def self.new(pattern, listener)
71
- if listener.respond_to?(:start) and listener.respond_to?(:finish)
73
+ if listener.respond_to?(:start) && listener.respond_to?(:finish)
72
74
  subscriber = Evented.new pattern, listener
73
75
  else
74
76
  subscriber = Timed.new pattern, listener
@@ -1,4 +1,6 @@
1
- require 'securerandom'
1
+ # frozen_string_literal: true
2
+
3
+ require "securerandom"
2
4
 
3
5
  module ActiveSupport
4
6
  module Notifications
@@ -14,15 +16,17 @@ module ActiveSupport
14
16
  # Instrument the given block by measuring the time taken to execute it
15
17
  # and publish it. Notice that events get sent even if an error occurs
16
18
  # in the passed-in block.
17
- def instrument(name, payload={})
18
- start name, payload
19
+ def instrument(name, payload = {})
20
+ # some of the listeners might have state
21
+ listeners_state = start name, payload
19
22
  begin
20
23
  yield payload
21
24
  rescue Exception => e
22
25
  payload[:exception] = [e.class.name, e.message]
26
+ payload[:exception_object] = e
23
27
  raise e
24
28
  ensure
25
- finish name, payload
29
+ finish_with_state listeners_state, name, payload
26
30
  end
27
31
  end
28
32
 
@@ -36,11 +40,15 @@ module ActiveSupport
36
40
  @notifier.finish name, @id, payload
37
41
  end
38
42
 
43
+ def finish_with_state(listeners_state, name, payload)
44
+ @notifier.finish name, @id, payload, listeners_state
45
+ end
46
+
39
47
  private
40
48
 
41
- def unique_id
42
- SecureRandom.hex(10)
43
- end
49
+ def unique_id
50
+ SecureRandom.hex(10)
51
+ end
44
52
  end
45
53
 
46
54
  class Event
@@ -57,6 +65,18 @@ module ActiveSupport
57
65
  @duration = nil
58
66
  end
59
67
 
68
+ # Returns the difference in milliseconds between when the execution of the
69
+ # event started and when it ended.
70
+ #
71
+ # ActiveSupport::Notifications.subscribe('wait') do |*args|
72
+ # @event = ActiveSupport::Notifications::Event.new(*args)
73
+ # end
74
+ #
75
+ # ActiveSupport::Notifications.instrument('wait') do
76
+ # sleep 1
77
+ # end
78
+ #
79
+ # @event.duration # => 1000.138
60
80
  def duration
61
81
  @duration ||= 1000.0 * (self.end - time)
62
82
  end
@@ -1,6 +1,8 @@
1
- require 'active_support/notifications/instrumenter'
2
- require 'active_support/notifications/fanout'
3
- require 'active_support/per_thread_registry'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/notifications/instrumenter"
4
+ require "active_support/notifications/fanout"
5
+ require "active_support/per_thread_registry"
4
6
 
5
7
  module ActiveSupport
6
8
  # = Notifications
@@ -13,7 +15,7 @@ module ActiveSupport
13
15
  # To instrument an event you just need to do:
14
16
  #
15
17
  # ActiveSupport::Notifications.instrument('render', extra: :information) do
16
- # render text: 'Foo'
18
+ # render plain: 'Foo'
17
19
  # end
18
20
  #
19
21
  # That first executes the block and then notifies all subscribers once done.
@@ -48,7 +50,7 @@ module ActiveSupport
48
50
  # The block is saved and will be called whenever someone instruments "render":
49
51
  #
50
52
  # ActiveSupport::Notifications.instrument('render', extra: :information) do
51
- # render text: 'Foo'
53
+ # render plain: 'Foo'
52
54
  # end
53
55
  #
54
56
  # event = events.first
@@ -64,13 +66,15 @@ module ActiveSupport
64
66
  # If an exception happens during that particular instrumentation the payload will
65
67
  # have a key <tt>:exception</tt> with an array of two elements as value: a string with
66
68
  # the name of the exception class, and the exception message.
69
+ # The <tt>:exception_object</tt> key of the payload will have the exception
70
+ # itself as the value.
67
71
  #
68
72
  # As the previous example depicts, the class <tt>ActiveSupport::Notifications::Event</tt>
69
73
  # is able to take the arguments as they come and provide an object-oriented
70
74
  # interface to that data.
71
75
  #
72
- # It is also possible to pass an object as the second parameter passed to the
73
- # <tt>subscribe</tt> method instead of a block:
76
+ # It is also possible to pass an object which responds to <tt>call</tt> method
77
+ # as the second parameter to the <tt>subscribe</tt> method instead of a block:
74
78
  #
75
79
  # module ActionController
76
80
  # class PageRequest