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,23 +1,25 @@
1
- require 'active_support/core_ext/module/aliasing'
1
+ # frozen_string_literal: true
2
2
 
3
- class Range #:nodoc:
3
+ require "active_support/time_with_zone"
4
4
 
5
- def each_with_time_with_zone(&block)
6
- ensure_iteration_allowed
7
- each_without_time_with_zone(&block)
8
- end
9
- alias_method_chain :each, :time_with_zone
10
-
11
- def step_with_time_with_zone(n = 1, &block)
12
- ensure_iteration_allowed
13
- step_without_time_with_zone(n, &block)
14
- end
15
- alias_method_chain :step, :time_with_zone
5
+ module ActiveSupport
6
+ module EachTimeWithZone #:nodoc:
7
+ def each(&block)
8
+ ensure_iteration_allowed
9
+ super
10
+ end
16
11
 
17
- private
18
- def ensure_iteration_allowed
19
- if first.is_a?(Time)
20
- raise TypeError, "can't iterate from #{first.class}"
12
+ def step(n = 1, &block)
13
+ ensure_iteration_allowed
14
+ super
21
15
  end
16
+
17
+ private
18
+
19
+ def ensure_iteration_allowed
20
+ raise TypeError, "can't iterate from #{first.class}" if first.is_a?(TimeWithZone)
21
+ end
22
22
  end
23
23
  end
24
+
25
+ Range.prepend(ActiveSupport::EachTimeWithZone)
@@ -1,23 +1,3 @@
1
- require 'active_support/core_ext/module/aliasing'
1
+ # frozen_string_literal: true
2
2
 
3
- class Range
4
- # Extends the default Range#include? to support range comparisons.
5
- # (1..5).include?(1..5) # => true
6
- # (1..5).include?(2..3) # => true
7
- # (1..5).include?(2..6) # => false
8
- #
9
- # The native Range#include? behavior is untouched.
10
- # ('a'..'f').include?('c') # => true
11
- # (5..9).include?(11) # => false
12
- def include_with_range?(value)
13
- if value.is_a?(::Range)
14
- # 1...10 includes 1..9 but it does not include 1..10.
15
- operator = exclude_end? && !value.exclude_end? ? :< : :<=
16
- include_without_range?(value.first) && value.last.send(operator, last)
17
- else
18
- include_without_range?(value)
19
- end
20
- end
21
-
22
- alias_method_chain :include?, :range
23
- end
3
+ require "active_support/core_ext/range/compare_range"
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/time_with_zone"
4
+
5
+ module ActiveSupport
6
+ module IncludeTimeWithZone #:nodoc:
7
+ # Extends the default Range#include? to support ActiveSupport::TimeWithZone.
8
+ #
9
+ # (1.hour.ago..1.hour.from_now).include?(Time.current) # => true
10
+ #
11
+ def include?(value)
12
+ if first.is_a?(TimeWithZone)
13
+ cover?(value)
14
+ elsif last.is_a?(TimeWithZone)
15
+ cover?(value)
16
+ else
17
+ super
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ Range.prepend(ActiveSupport::IncludeTimeWithZone)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Range
2
4
  # Compare two ranges and see if they overlap each other
3
5
  # (1..5).overlaps?(4..6) # => true
@@ -1,4 +1,7 @@
1
- require 'active_support/core_ext/range/conversions'
2
- require 'active_support/core_ext/range/include_range'
3
- require 'active_support/core_ext/range/overlaps'
4
- require 'active_support/core_ext/range/each'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/range/conversions"
4
+ require "active_support/core_ext/range/compare_range"
5
+ require "active_support/core_ext/range/include_time_with_zone"
6
+ require "active_support/core_ext/range/overlaps"
7
+ require "active_support/core_ext/range/each"
@@ -1,5 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Regexp #:nodoc:
2
4
  def multiline?
3
5
  options & MULTILINE == MULTILINE
4
6
  end
7
+
8
+ def match?(string, pos = 0)
9
+ !!match(string, pos)
10
+ end unless //.respond_to?(:match?)
5
11
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "securerandom"
4
+
5
+ module SecureRandom
6
+ BASE58_ALPHABET = ("0".."9").to_a + ("A".."Z").to_a + ("a".."z").to_a - ["0", "O", "I", "l"]
7
+ # SecureRandom.base58 generates a random base58 string.
8
+ #
9
+ # The argument _n_ specifies the length, of the random string to be generated.
10
+ #
11
+ # If _n_ is not specified or is +nil+, 16 is assumed. It may be larger in the future.
12
+ #
13
+ # The result may contain alphanumeric characters except 0, O, I and l
14
+ #
15
+ # p SecureRandom.base58 # => "4kUgL2pdQMSCQtjE"
16
+ # p SecureRandom.base58(24) # => "77TMHrHJFvFDwodq8w7Ev2m7"
17
+ #
18
+ def self.base58(n = 16)
19
+ SecureRandom.random_bytes(n).unpack("C*").map do |byte|
20
+ idx = byte % 64
21
+ idx = SecureRandom.random_number(58) if idx >= 58
22
+ BASE58_ALPHABET[idx]
23
+ end.join
24
+ end
25
+ end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
4
  # If you pass a single integer, returns a substring of one character at that
3
5
  # position. The first character of the string is at position 0, the next at
4
6
  # position 1, and so on. If a range is supplied, a substring containing
5
7
  # characters at offsets given by the range is returned. In both cases, if an
6
- # offset is negative, it is counted from the end of the string. Returns nil
8
+ # offset is negative, it is counted from the end of the string. Returns +nil+
7
9
  # if the initial offset falls outside the string. Returns an empty string if
8
10
  # the beginning of the range is greater than the end of the string.
9
11
  #
@@ -17,7 +19,7 @@ class String
17
19
  #
18
20
  # If a Regexp is given, the matching portion of the string is returned.
19
21
  # If a String is given, that given string is returned if it occurs in
20
- # the string. In both cases, nil is returned if there is no match.
22
+ # the string. In both cases, +nil+ is returned if there is no match.
21
23
  #
22
24
  # str = "hello"
23
25
  # str.at(/lo/) # => "lo"
@@ -74,9 +76,9 @@ class String
74
76
  # str.first(6) # => "hello"
75
77
  def first(limit = 1)
76
78
  if limit == 0
77
- ''
79
+ ""
78
80
  elsif limit >= size
79
- self.dup
81
+ dup
80
82
  else
81
83
  to(limit - 1)
82
84
  end
@@ -94,9 +96,9 @@ class String
94
96
  # str.last(6) # => "hello"
95
97
  def last(limit = 1)
96
98
  if limit == 0
97
- ''
99
+ ""
98
100
  elsif limit >= size
99
- self.dup
101
+ dup
100
102
  else
101
103
  from(-limit)
102
104
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
- # Enable more predictable duck-typing on String-like classes. See <tt>Object#acts_like?</tt>.
4
+ # Enables more predictable duck-typing on String-like classes. See <tt>Object#acts_like?</tt>.
3
5
  def acts_like_string?
4
6
  true
5
7
  end
@@ -1,5 +1,7 @@
1
- require 'date'
2
- require 'active_support/core_ext/time/calculations'
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+ require "active_support/core_ext/time/calculations"
3
5
 
4
6
  class String
5
7
  # Converts a string to a Time value.
@@ -14,11 +16,12 @@ class String
14
16
  # "06:12".to_time # => 2012-12-13 06:12:00 +0100
15
17
  # "2012-12-13 06:12".to_time # => 2012-12-13 06:12:00 +0100
16
18
  # "2012-12-13T06:12".to_time # => 2012-12-13 06:12:00 +0100
17
- # "2012-12-13T06:12".to_time(:utc) # => 2012-12-13 05:12:00 UTC
19
+ # "2012-12-13T06:12".to_time(:utc) # => 2012-12-13 06:12:00 UTC
18
20
  # "12/13/2012".to_time # => ArgumentError: argument out of range
19
21
  def to_time(form = :local)
20
22
  parts = Date._parse(self, false)
21
- return if parts.empty?
23
+ used_keys = %i(year mon mday hour min sec sec_fraction offset)
24
+ return if (parts.keys & used_keys).empty?
22
25
 
23
26
  now = Time.now
24
27
  time = Time.new(
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
4
  # The inverse of <tt>String#include?</tt>. Returns true if the string
3
5
  # does not include the other string.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
4
  # Returns the string, first removing all whitespace on both ends of
3
5
  # the string, and then changing remaining consecutive whitespace
@@ -17,9 +19,8 @@ class String
17
19
  # str.squish! # => "foo bar boo"
18
20
  # str # => "foo bar boo"
19
21
  def squish!
20
- gsub!(/\A[[:space:]]+/, '')
21
- gsub!(/[[:space:]]+\z/, '')
22
- gsub!(/[[:space:]]+/, ' ')
22
+ gsub!(/[[:space:]]+/, " ")
23
+ strip!
23
24
  self
24
25
  end
25
26
 
@@ -65,7 +66,7 @@ class String
65
66
  def truncate(truncate_at, options = {})
66
67
  return dup unless length > truncate_at
67
68
 
68
- omission = options[:omission] || '...'
69
+ omission = options[:omission] || "..."
69
70
  length_with_room_for_omission = truncate_at - omission.length
70
71
  stop = \
71
72
  if options[:separator]
@@ -95,7 +96,7 @@ class String
95
96
  sep = options[:separator] || /\s+/
96
97
  sep = Regexp.escape(sep.to_s) unless Regexp === sep
97
98
  if self =~ /\A((?>.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/m
98
- $1 + (options[:omission] || '...')
99
+ $1 + (options[:omission] || "...")
99
100
  else
100
101
  dup
101
102
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
4
  # Same as +indent+, except it indents the receiver in-place.
3
5
  #
4
6
  # Returns the indented string, or +nil+ if there was nothing to indent.
5
- def indent!(amount, indent_string=nil, indent_empty_lines=false)
6
- indent_string = indent_string || self[/^[ \t]/] || ' '
7
+ def indent!(amount, indent_string = nil, indent_empty_lines = false)
8
+ indent_string = indent_string || self[/^[ \t]/] || " "
7
9
  re = indent_empty_lines ? /^/ : /^(?!$)/
8
10
  gsub!(re, indent_string * amount)
9
11
  end
@@ -37,7 +39,7 @@ class String
37
39
  # "foo\n\nbar".indent(2) # => " foo\n\n bar"
38
40
  # "foo\n\nbar".indent(2, nil, true) # => " foo\n \n bar"
39
41
  #
40
- def indent(amount, indent_string=nil, indent_empty_lines=false)
41
- dup.tap {|_| _.indent!(amount, indent_string, indent_empty_lines)}
42
+ def indent(amount, indent_string = nil, indent_empty_lines = false)
43
+ dup.tap { |_| _.indent!(amount, indent_string, indent_empty_lines) }
42
44
  end
43
45
  end
@@ -1,5 +1,7 @@
1
- require 'active_support/inflector/methods'
2
- require 'active_support/inflector/transliterate'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/inflector/methods"
4
+ require "active_support/inflector/transliterate"
3
5
 
4
6
  # String inflections define new methods on the String class to transform names for different purposes.
5
7
  # For instance, you can figure out the name of a table from the name of a class.
@@ -31,7 +33,7 @@ class String
31
33
  def pluralize(count = nil, locale = :en)
32
34
  locale = count if count.is_a?(Symbol)
33
35
  if count == 1
34
- self.dup
36
+ dup
35
37
  else
36
38
  ActiveSupport::Inflector.pluralize(self, locale)
37
39
  end
@@ -67,7 +69,7 @@ class String
67
69
  end
68
70
 
69
71
  # +safe_constantize+ tries to find a declared constant with the name specified
70
- # in the string. It returns nil when the name is not in CamelCase
72
+ # in the string. It returns +nil+ when the name is not in CamelCase
71
73
  # or is not initialized. See ActiveSupport::Inflector.safe_constantize
72
74
  #
73
75
  # 'Module'.safe_constantize # => Module
@@ -92,6 +94,8 @@ class String
92
94
  ActiveSupport::Inflector.camelize(self, true)
93
95
  when :lower
94
96
  ActiveSupport::Inflector.camelize(self, false)
97
+ else
98
+ raise ArgumentError, "Invalid option, use either :upper or :lower."
95
99
  end
96
100
  end
97
101
  alias_method :camelcase, :camelize
@@ -100,12 +104,17 @@ class String
100
104
  # a nicer looking title. +titleize+ is meant for creating pretty output. It is not
101
105
  # used in the Rails internals.
102
106
  #
107
+ # The trailing '_id','Id'.. can be kept and capitalized by setting the
108
+ # optional parameter +keep_id_suffix+ to true.
109
+ # By default, this parameter is false.
110
+ #
103
111
  # +titleize+ is also aliased as +titlecase+.
104
112
  #
105
- # 'man from the boondocks'.titleize # => "Man From The Boondocks"
106
- # 'x-men: the last stand'.titleize # => "X Men: The Last Stand"
107
- def titleize
108
- ActiveSupport::Inflector.titleize(self)
113
+ # 'man from the boondocks'.titleize # => "Man From The Boondocks"
114
+ # 'x-men: the last stand'.titleize # => "X Men: The Last Stand"
115
+ # 'string_ending_with_id'.titleize(keep_id_suffix: true) # => "String Ending With Id"
116
+ def titleize(keep_id_suffix: false)
117
+ ActiveSupport::Inflector.titleize(self, keep_id_suffix: keep_id_suffix)
109
118
  end
110
119
  alias_method :titlecase, :titleize
111
120
 
@@ -128,10 +137,10 @@ class String
128
137
 
129
138
  # Removes the module part from the constant expression in the string.
130
139
  #
131
- # 'ActiveRecord::CoreExtensions::String::Inflections'.demodulize # => "Inflections"
132
- # 'Inflections'.demodulize # => "Inflections"
133
- # '::Inflections'.demodulize # => "Inflections"
134
- # ''.demodulize # => ''
140
+ # 'ActiveSupport::Inflector::Inflections'.demodulize # => "Inflections"
141
+ # 'Inflections'.demodulize # => "Inflections"
142
+ # '::Inflections'.demodulize # => "Inflections"
143
+ # ''.demodulize # => ''
135
144
  #
136
145
  # See also +deconstantize+.
137
146
  def demodulize
@@ -164,31 +173,45 @@ class String
164
173
  #
165
174
  # <%= link_to(@person.name, person_path) %>
166
175
  # # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
167
- def parameterize(sep = '-')
168
- ActiveSupport::Inflector.parameterize(self, sep)
176
+ #
177
+ # To preserve the case of the characters in a string, use the +preserve_case+ argument.
178
+ #
179
+ # class Person
180
+ # def to_param
181
+ # "#{id}-#{name.parameterize(preserve_case: true)}"
182
+ # end
183
+ # end
184
+ #
185
+ # @person = Person.find(1)
186
+ # # => #<Person id: 1, name: "Donald E. Knuth">
187
+ #
188
+ # <%= link_to(@person.name, person_path) %>
189
+ # # => <a href="/person/1-Donald-E-Knuth">Donald E. Knuth</a>
190
+ def parameterize(separator: "-", preserve_case: false)
191
+ ActiveSupport::Inflector.parameterize(self, separator: separator, preserve_case: preserve_case)
169
192
  end
170
193
 
171
194
  # Creates the name of a table like Rails does for models to table names. This method
172
195
  # uses the +pluralize+ method on the last word in the string.
173
196
  #
174
197
  # 'RawScaledScorer'.tableize # => "raw_scaled_scorers"
175
- # 'egg_and_ham'.tableize # => "egg_and_hams"
198
+ # 'ham_and_egg'.tableize # => "ham_and_eggs"
176
199
  # 'fancyCategory'.tableize # => "fancy_categories"
177
200
  def tableize
178
201
  ActiveSupport::Inflector.tableize(self)
179
202
  end
180
203
 
181
- # Create a class name from a plural table name like Rails does for table names to models.
204
+ # Creates a class name from a plural table name like Rails does for table names to models.
182
205
  # Note that this returns a string and not a class. (To convert to an actual class
183
206
  # follow +classify+ with +constantize+.)
184
207
  #
185
- # 'egg_and_hams'.classify # => "EggAndHam"
208
+ # 'ham_and_eggs'.classify # => "HamAndEgg"
186
209
  # 'posts'.classify # => "Post"
187
210
  def classify
188
211
  ActiveSupport::Inflector.classify(self)
189
212
  end
190
213
 
191
- # Capitalizes the first word, turns underscores into spaces, and strips a
214
+ # Capitalizes the first word, turns underscores into spaces, and (by default)strips a
192
215
  # trailing '_id' if present.
193
216
  # Like +titleize+, this is meant for creating pretty output.
194
217
  #
@@ -196,12 +219,26 @@ class String
196
219
  # optional parameter +capitalize+ to false.
197
220
  # By default, this parameter is true.
198
221
  #
199
- # 'employee_salary'.humanize # => "Employee salary"
200
- # 'author_id'.humanize # => "Author"
201
- # 'author_id'.humanize(capitalize: false) # => "author"
202
- # '_id'.humanize # => "Id"
203
- def humanize(options = {})
204
- ActiveSupport::Inflector.humanize(self, options)
222
+ # The trailing '_id' can be kept and capitalized by setting the
223
+ # optional parameter +keep_id_suffix+ to true.
224
+ # By default, this parameter is false.
225
+ #
226
+ # 'employee_salary'.humanize # => "Employee salary"
227
+ # 'author_id'.humanize # => "Author"
228
+ # 'author_id'.humanize(capitalize: false) # => "author"
229
+ # '_id'.humanize # => "Id"
230
+ # 'author_id'.humanize(keep_id_suffix: true) # => "Author Id"
231
+ def humanize(capitalize: true, keep_id_suffix: false)
232
+ ActiveSupport::Inflector.humanize(self, capitalize: capitalize, keep_id_suffix: keep_id_suffix)
233
+ end
234
+
235
+ # Converts just the first character to uppercase.
236
+ #
237
+ # 'what a Lovely Day'.upcase_first # => "What a Lovely Day"
238
+ # 'w'.upcase_first # => "W"
239
+ # ''.upcase_first # => ""
240
+ def upcase_first
241
+ ActiveSupport::Inflector.upcase_first(self)
205
242
  end
206
243
 
207
244
  # Creates a foreign key name from a class name.
@@ -1,4 +1,6 @@
1
- require 'active_support/string_inquirer'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/string_inquirer"
2
4
 
3
5
  class String
4
6
  # Wraps the current string in the <tt>ActiveSupport::StringInquirer</tt> class,
@@ -1,5 +1,6 @@
1
- # encoding: utf-8
2
- require 'active_support/multibyte'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/multibyte"
3
4
 
4
5
  class String
5
6
  # == Multibyte proxy
@@ -10,12 +11,12 @@ class String
10
11
  # encapsulates the original string. A Unicode safe version of all the String methods are defined on this proxy
11
12
  # class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsulated string.
12
13
  #
13
- # name = 'Claus Müller'
14
- # name.reverse # => "rell??M sualC"
15
- # name.length # => 13
14
+ # >> "lj".upcase
15
+ # => "lj"
16
+ # >> "lj".mb_chars.upcase.to_s
17
+ # => "LJ"
16
18
  #
17
- # name.mb_chars.reverse.to_s # => "rellüM sualC"
18
- # name.mb_chars.length # => 12
19
+ # NOTE: An above example is useful for pre Ruby 2.4. Ruby 2.4 supports Unicode case mappings.
19
20
  #
20
21
  # == Method chaining
21
22
  #
@@ -36,6 +37,13 @@ class String
36
37
  ActiveSupport::Multibyte.proxy_class.new(self)
37
38
  end
38
39
 
40
+ # Returns +true+ if string has utf_8 encoding.
41
+ #
42
+ # utf_8_str = "some string".encode "UTF-8"
43
+ # iso_str = "some string".encode "ISO-8859-1"
44
+ #
45
+ # utf_8_str.is_utf8? # => true
46
+ # iso_str.is_utf8? # => false
39
47
  def is_utf8?
40
48
  case encoding
41
49
  when Encoding::UTF_8