activesupport 6.0.3.4 → 6.1.0

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 (131) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +342 -472
  3. data/MIT-LICENSE +1 -1
  4. data/lib/active_support.rb +13 -1
  5. data/lib/active_support/array_inquirer.rb +4 -2
  6. data/lib/active_support/backtrace_cleaner.rb +3 -3
  7. data/lib/active_support/benchmarkable.rb +1 -1
  8. data/lib/active_support/cache.rb +85 -44
  9. data/lib/active_support/cache/file_store.rb +4 -3
  10. data/lib/active_support/cache/mem_cache_store.rb +21 -14
  11. data/lib/active_support/cache/memory_store.rb +46 -26
  12. data/lib/active_support/cache/redis_cache_store.rb +27 -27
  13. data/lib/active_support/cache/strategy/local_cache.rb +21 -6
  14. data/lib/active_support/callbacks.rb +65 -56
  15. data/lib/active_support/concern.rb +46 -2
  16. data/lib/active_support/configurable.rb +3 -3
  17. data/lib/active_support/configuration_file.rb +46 -0
  18. data/lib/active_support/core_ext/benchmark.rb +2 -2
  19. data/lib/active_support/core_ext/class/attribute.rb +34 -44
  20. data/lib/active_support/core_ext/class/subclasses.rb +17 -38
  21. data/lib/active_support/core_ext/date/conversions.rb +2 -1
  22. data/lib/active_support/core_ext/date_and_time/calculations.rb +13 -0
  23. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  24. data/lib/active_support/core_ext/enumerable.rb +76 -4
  25. data/lib/active_support/core_ext/hash/conversions.rb +2 -2
  26. data/lib/active_support/core_ext/hash/deep_transform_values.rb +1 -1
  27. data/lib/active_support/core_ext/hash/except.rb +1 -1
  28. data/lib/active_support/core_ext/hash/keys.rb +1 -1
  29. data/lib/active_support/core_ext/hash/slice.rb +3 -2
  30. data/lib/active_support/core_ext/load_error.rb +1 -1
  31. data/lib/active_support/core_ext/marshal.rb +2 -0
  32. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  33. data/lib/active_support/core_ext/module/attribute_accessors.rb +23 -29
  34. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +8 -4
  35. data/lib/active_support/core_ext/module/concerning.rb +8 -2
  36. data/lib/active_support/core_ext/module/delegation.rb +38 -28
  37. data/lib/active_support/core_ext/module/introspection.rb +1 -25
  38. data/lib/active_support/core_ext/name_error.rb +29 -2
  39. data/lib/active_support/core_ext/numeric/conversions.rb +22 -18
  40. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  41. data/lib/active_support/core_ext/object/json.rb +6 -2
  42. data/lib/active_support/core_ext/object/try.rb +2 -2
  43. data/lib/active_support/core_ext/range/compare_range.rb +9 -3
  44. data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
  45. data/lib/active_support/core_ext/regexp.rb +8 -1
  46. data/lib/active_support/core_ext/string/access.rb +5 -24
  47. data/lib/active_support/core_ext/string/conversions.rb +1 -0
  48. data/lib/active_support/core_ext/string/inflections.rb +38 -4
  49. data/lib/active_support/core_ext/string/inquiry.rb +1 -0
  50. data/lib/active_support/core_ext/string/multibyte.rb +2 -2
  51. data/lib/active_support/core_ext/string/output_safety.rb +9 -9
  52. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  53. data/lib/active_support/core_ext/symbol.rb +3 -0
  54. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  55. data/lib/active_support/core_ext/time/calculations.rb +19 -1
  56. data/lib/active_support/core_ext/time/conversions.rb +1 -0
  57. data/lib/active_support/core_ext/uri.rb +5 -1
  58. data/lib/active_support/current_attributes.rb +7 -2
  59. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  60. data/lib/active_support/dependencies.rb +43 -19
  61. data/lib/active_support/deprecation.rb +6 -1
  62. data/lib/active_support/deprecation/behaviors.rb +15 -2
  63. data/lib/active_support/deprecation/disallowed.rb +56 -0
  64. data/lib/active_support/deprecation/instance_delegator.rb +0 -1
  65. data/lib/active_support/deprecation/method_wrappers.rb +3 -2
  66. data/lib/active_support/deprecation/proxy_wrappers.rb +3 -3
  67. data/lib/active_support/deprecation/reporting.rb +50 -7
  68. data/lib/active_support/descendants_tracker.rb +6 -2
  69. data/lib/active_support/duration.rb +71 -22
  70. data/lib/active_support/duration/iso8601_serializer.rb +15 -9
  71. data/lib/active_support/encrypted_file.rb +19 -2
  72. data/lib/active_support/environment_inquirer.rb +20 -0
  73. data/lib/active_support/evented_file_update_checker.rb +69 -133
  74. data/lib/active_support/fork_tracker.rb +62 -0
  75. data/lib/active_support/gem_version.rb +3 -3
  76. data/lib/active_support/hash_with_indifferent_access.rb +42 -23
  77. data/lib/active_support/i18n_railtie.rb +14 -19
  78. data/lib/active_support/inflector/inflections.rb +1 -2
  79. data/lib/active_support/inflector/methods.rb +35 -31
  80. data/lib/active_support/inflector/transliterate.rb +4 -4
  81. data/lib/active_support/json/decoding.rb +4 -4
  82. data/lib/active_support/json/encoding.rb +5 -1
  83. data/lib/active_support/key_generator.rb +1 -1
  84. data/lib/active_support/locale/en.yml +7 -3
  85. data/lib/active_support/log_subscriber.rb +8 -0
  86. data/lib/active_support/logger.rb +1 -1
  87. data/lib/active_support/logger_silence.rb +2 -26
  88. data/lib/active_support/logger_thread_safe_level.rb +34 -12
  89. data/lib/active_support/message_encryptor.rb +4 -7
  90. data/lib/active_support/message_verifier.rb +5 -5
  91. data/lib/active_support/messages/metadata.rb +9 -1
  92. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  93. data/lib/active_support/messages/rotator.rb +6 -5
  94. data/lib/active_support/multibyte/chars.rb +4 -42
  95. data/lib/active_support/multibyte/unicode.rb +9 -83
  96. data/lib/active_support/notifications.rb +31 -4
  97. data/lib/active_support/notifications/fanout.rb +23 -8
  98. data/lib/active_support/notifications/instrumenter.rb +6 -15
  99. data/lib/active_support/number_helper.rb +29 -14
  100. data/lib/active_support/number_helper/number_converter.rb +1 -1
  101. data/lib/active_support/number_helper/number_to_currency_converter.rb +3 -7
  102. data/lib/active_support/number_helper/number_to_human_converter.rb +1 -1
  103. data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
  104. data/lib/active_support/number_helper/number_to_rounded_converter.rb +3 -3
  105. data/lib/active_support/number_helper/rounding_helper.rb +12 -28
  106. data/lib/active_support/option_merger.rb +3 -2
  107. data/lib/active_support/ordered_options.rb +8 -2
  108. data/lib/active_support/parameter_filter.rb +15 -10
  109. data/lib/active_support/per_thread_registry.rb +1 -1
  110. data/lib/active_support/rails.rb +1 -4
  111. data/lib/active_support/railtie.rb +23 -1
  112. data/lib/active_support/secure_compare_rotator.rb +51 -0
  113. data/lib/active_support/security_utils.rb +19 -12
  114. data/lib/active_support/string_inquirer.rb +4 -2
  115. data/lib/active_support/subscriber.rb +12 -7
  116. data/lib/active_support/tagged_logging.rb +29 -4
  117. data/lib/active_support/testing/assertions.rb +18 -11
  118. data/lib/active_support/testing/parallelization.rb +12 -95
  119. data/lib/active_support/testing/parallelization/server.rb +78 -0
  120. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  121. data/lib/active_support/testing/time_helpers.rb +40 -3
  122. data/lib/active_support/time_with_zone.rb +66 -42
  123. data/lib/active_support/values/time_zone.rb +20 -10
  124. data/lib/active_support/xml_mini/rexml.rb +8 -1
  125. metadata +36 -38
  126. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
  127. data/lib/active_support/core_ext/hash/compact.rb +0 -5
  128. data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
  129. data/lib/active_support/core_ext/module/reachable.rb +0 -6
  130. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
  131. data/lib/active_support/core_ext/range/include_range.rb +0 -9
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "active_support/core_ext/big_decimal/conversions"
4
4
  require "active_support/number_helper"
5
- require "active_support/core_ext/module/deprecation"
6
5
 
7
6
  module ActiveSupport
8
7
  module NumericWithFormat
@@ -27,10 +26,11 @@ module ActiveSupport
27
26
  # # => "+1.123.555.1234 x 1343"
28
27
  #
29
28
  # Currency:
30
- # 1234567890.50.to_s(:currency) # => "$1,234,567,890.50"
31
- # 1234567890.506.to_s(:currency) # => "$1,234,567,890.51"
32
- # 1234567890.506.to_s(:currency, precision: 3) # => "$1,234,567,890.506"
33
- # 1234567890.506.to_s(:currency, locale: :fr) # => "1 234 567 890,51 €"
29
+ # 1234567890.50.to_s(:currency) # => "$1,234,567,890.50"
30
+ # 1234567890.506.to_s(:currency) # => "$1,234,567,890.51"
31
+ # 1234567890.506.to_s(:currency, precision: 3) # => "$1,234,567,890.506"
32
+ # 1234567890.506.to_s(:currency, round_mode: :down) # => "$1,234,567,890.50"
33
+ # 1234567890.506.to_s(:currency, locale: :fr) # => "1 234 567 890,51 €"
34
34
  # -1234567890.50.to_s(:currency, negative_format: '(%u%n)')
35
35
  # # => "($1,234,567,890.50)"
36
36
  # 1234567890.50.to_s(:currency, unit: '£', separator: ',', delimiter: '')
@@ -43,6 +43,7 @@ module ActiveSupport
43
43
  # 100.to_s(:percentage, precision: 0) # => "100%"
44
44
  # 1000.to_s(:percentage, delimiter: '.', separator: ',') # => "1.000,000%"
45
45
  # 302.24398923423.to_s(:percentage, precision: 5) # => "302.24399%"
46
+ # 302.24398923423.to_s(:percentage, round_mode: :down) # => "302.243%"
46
47
  # 1000.to_s(:percentage, locale: :fr) # => "1 000,000%"
47
48
  # 100.to_s(:percentage, format: '%n %') # => "100.000 %"
48
49
  #
@@ -59,6 +60,7 @@ module ActiveSupport
59
60
  # Rounded:
60
61
  # 111.2345.to_s(:rounded) # => "111.235"
61
62
  # 111.2345.to_s(:rounded, precision: 2) # => "111.23"
63
+ # 111.2345.to_s(:rounded, precision: 2, round_mode: :up) # => "111.24"
62
64
  # 13.to_s(:rounded, precision: 5) # => "13.00000"
63
65
  # 389.32314.to_s(:rounded, precision: 0) # => "389"
64
66
  # 111.2345.to_s(:rounded, significant: true) # => "111"
@@ -72,19 +74,20 @@ module ActiveSupport
72
74
  # # => "1.111,23"
73
75
  #
74
76
  # Human-friendly size in Bytes:
75
- # 123.to_s(:human_size) # => "123 Bytes"
76
- # 1234.to_s(:human_size) # => "1.21 KB"
77
- # 12345.to_s(:human_size) # => "12.1 KB"
78
- # 1234567.to_s(:human_size) # => "1.18 MB"
79
- # 1234567890.to_s(:human_size) # => "1.15 GB"
80
- # 1234567890123.to_s(:human_size) # => "1.12 TB"
81
- # 1234567890123456.to_s(:human_size) # => "1.1 PB"
82
- # 1234567890123456789.to_s(:human_size) # => "1.07 EB"
83
- # 1234567.to_s(:human_size, precision: 2) # => "1.2 MB"
84
- # 483989.to_s(:human_size, precision: 2) # => "470 KB"
85
- # 1234567.to_s(:human_size, precision: 2, separator: ',') # => "1,2 MB"
86
- # 1234567890123.to_s(:human_size, precision: 5) # => "1.1228 TB"
87
- # 524288000.to_s(:human_size, precision: 5) # => "500 MB"
77
+ # 123.to_s(:human_size) # => "123 Bytes"
78
+ # 1234.to_s(:human_size) # => "1.21 KB"
79
+ # 12345.to_s(:human_size) # => "12.1 KB"
80
+ # 1234567.to_s(:human_size) # => "1.18 MB"
81
+ # 1234567890.to_s(:human_size) # => "1.15 GB"
82
+ # 1234567890123.to_s(:human_size) # => "1.12 TB"
83
+ # 1234567890123456.to_s(:human_size) # => "1.1 PB"
84
+ # 1234567890123456789.to_s(:human_size) # => "1.07 EB"
85
+ # 1234567.to_s(:human_size, precision: 2) # => "1.2 MB"
86
+ # 1234567.to_s(:human_size, precision: 2, round_mode: :up) # => "1.3 MB"
87
+ # 483989.to_s(:human_size, precision: 2) # => "470 KB"
88
+ # 1234567.to_s(:human_size, precision: 2, separator: ',') # => "1,2 MB"
89
+ # 1234567890123.to_s(:human_size, precision: 5) # => "1.1228 TB"
90
+ # 524288000.to_s(:human_size, precision: 5) # => "500 MB"
88
91
  #
89
92
  # Human-friendly format:
90
93
  # 123.to_s(:human) # => "123"
@@ -96,6 +99,7 @@ module ActiveSupport
96
99
  # 1234567890123456.to_s(:human) # => "1.23 Quadrillion"
97
100
  # 1234567890123456789.to_s(:human) # => "1230 Quadrillion"
98
101
  # 489939.to_s(:human, precision: 2) # => "490 Thousand"
102
+ # 489939.to_s(:human, precision: 2, round_mode: :down) # => "480 Thousand"
99
103
  # 489939.to_s(:human, precision: 4) # => "489.9 Thousand"
100
104
  # 1234567.to_s(:human, precision: 4,
101
105
  # significant: false) # => "1.2346 Million"
@@ -43,7 +43,7 @@ class Hash
43
43
  def deep_dup
44
44
  hash = dup
45
45
  each_pair do |key, value|
46
- if key.frozen? && ::String === key
46
+ if (::String === key && key.frozen?) || ::Symbol === key
47
47
  hash[key] = value.deep_dup
48
48
  else
49
49
  hash.delete(key)
@@ -45,7 +45,7 @@ module ActiveSupport
45
45
  end
46
46
  end
47
47
 
48
- [Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass, Enumerable].reverse_each do |klass|
48
+ [Enumerable, Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].reverse_each do |klass|
49
49
  klass.prepend(ActiveSupport::ToJsonWithActiveSupportEncoder)
50
50
  end
51
51
 
@@ -169,7 +169,11 @@ class Hash
169
169
  self
170
170
  end
171
171
 
172
- Hash[subset.map { |k, v| [k.to_s, options ? v.as_json(options.dup) : v.as_json] }]
172
+ result = {}
173
+ subset.each do |k, v|
174
+ result[k.to_s] = options ? v.as_json(options.dup) : v.as_json
175
+ end
176
+ result
173
177
  end
174
178
  end
175
179
 
@@ -145,14 +145,14 @@ class NilClass
145
145
  #
146
146
  # With +try+
147
147
  # @person.try(:children).try(:first).try(:name)
148
- def try(method_name = nil, *args)
148
+ def try(_method_name = nil, *)
149
149
  nil
150
150
  end
151
151
 
152
152
  # Calling +try!+ on +nil+ always returns +nil+.
153
153
  #
154
154
  # nil.try!(:name) # => nil
155
- def try!(method_name = nil, *args)
155
+ def try!(_method_name = nil, *)
156
156
  nil
157
157
  end
158
158
  end
@@ -15,11 +15,13 @@ module ActiveSupport
15
15
  # The given range must be fully bounded, with both start and end.
16
16
  def ===(value)
17
17
  if value.is_a?(::Range)
18
+ is_backwards_op = value.exclude_end? ? :>= : :>
19
+ return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
18
20
  # 1...10 includes 1..9 but it does not include 1..10.
19
21
  # 1..10 includes 1...11 but it does not include 1...12.
20
22
  operator = exclude_end? && !value.exclude_end? ? :< : :<=
21
23
  value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
22
- super(value.first) && (self.end.nil? || value_max.send(operator, last))
24
+ super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
23
25
  else
24
26
  super
25
27
  end
@@ -38,11 +40,13 @@ module ActiveSupport
38
40
  # The given range must be fully bounded, with both start and end.
39
41
  def include?(value)
40
42
  if value.is_a?(::Range)
43
+ is_backwards_op = value.exclude_end? ? :>= : :>
44
+ return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
41
45
  # 1...10 includes 1..9 but it does not include 1..10.
42
46
  # 1..10 includes 1...11 but it does not include 1...12.
43
47
  operator = exclude_end? && !value.exclude_end? ? :< : :<=
44
48
  value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
45
- super(value.first) && (self.end.nil? || value_max.send(operator, last))
49
+ super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
46
50
  else
47
51
  super
48
52
  end
@@ -61,11 +65,13 @@ module ActiveSupport
61
65
  # The given range must be fully bounded, with both start and end.
62
66
  def cover?(value)
63
67
  if value.is_a?(::Range)
68
+ is_backwards_op = value.exclude_end? ? :>= : :>
69
+ return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
64
70
  # 1...10 covers 1..9 but it does not cover 1..10.
65
71
  # 1..10 covers 1...11 but it does not cover 1...12.
66
72
  operator = exclude_end? && !value.exclude_end? ? :< : :<=
67
73
  value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
68
- super(value.first) && (self.end.nil? || value_max.send(operator, last))
74
+ super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
69
75
  else
70
76
  super
71
77
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/time_with_zone"
4
+ require "active_support/deprecation"
4
5
 
5
6
  module ActiveSupport
6
7
  module IncludeTimeWithZone #:nodoc:
@@ -9,9 +10,13 @@ module ActiveSupport
9
10
  # (1.hour.ago..1.hour.from_now).include?(Time.current) # => true
10
11
  #
11
12
  def include?(value)
12
- if self.begin.is_a?(TimeWithZone)
13
- cover?(value)
14
- elsif self.end.is_a?(TimeWithZone)
13
+ if self.begin.is_a?(TimeWithZone) || self.end.is_a?(TimeWithZone)
14
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
15
+ Using `Range#include?` to check the inclusion of a value in
16
+ a date time range is deprecated.
17
+ It is recommended to use `Range#cover?` instead of `Range#include?` to
18
+ check the inclusion of a value in a date time range.
19
+ MSG
15
20
  cover?(value)
16
21
  else
17
22
  super
@@ -1,6 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Regexp #:nodoc:
3
+ class Regexp
4
+ # Returns +true+ if the regexp has the multiline flag set.
5
+ #
6
+ # (/./).multiline? # => false
7
+ # (/./m).multiline? # => true
8
+ #
9
+ # Regexp.new(".").multiline? # => false
10
+ # Regexp.new(".", Regexp::MULTILINE).multiline? # => true
4
11
  def multiline?
5
12
  options & MULTILINE == MULTILINE
6
13
  end
@@ -44,7 +44,7 @@ class String
44
44
  # str.from(0).to(-1) # => "hello"
45
45
  # str.from(1).to(-2) # => "ell"
46
46
  def from(position)
47
- self[position..-1]
47
+ self[position, length]
48
48
  end
49
49
 
50
50
  # Returns a substring from the beginning of the string to the given position.
@@ -61,7 +61,8 @@ class String
61
61
  # str.from(0).to(-1) # => "hello"
62
62
  # str.from(1).to(-2) # => "ell"
63
63
  def to(position)
64
- self[0..position]
64
+ position += size if position < 0
65
+ self[0, position + 1] || +""
65
66
  end
66
67
 
67
68
  # Returns the first character. If a limit is supplied, returns a substring
@@ -75,17 +76,7 @@ class String
75
76
  # str.first(0) # => ""
76
77
  # str.first(6) # => "hello"
77
78
  def first(limit = 1)
78
- ActiveSupport::Deprecation.warn(
79
- "Calling String#first with a negative integer limit " \
80
- "will raise an ArgumentError in Rails 6.1."
81
- ) if limit < 0
82
- if limit == 0
83
- ""
84
- elsif limit >= size
85
- dup
86
- else
87
- to(limit - 1)
88
- end
79
+ self[0, limit] || raise(ArgumentError, "negative limit")
89
80
  end
90
81
 
91
82
  # Returns the last character of the string. If a limit is supplied, returns a substring
@@ -99,16 +90,6 @@ class String
99
90
  # str.last(0) # => ""
100
91
  # str.last(6) # => "hello"
101
92
  def last(limit = 1)
102
- ActiveSupport::Deprecation.warn(
103
- "Calling String#last with a negative integer limit " \
104
- "will raise an ArgumentError in Rails 6.1."
105
- ) if limit < 0
106
- if limit == 0
107
- ""
108
- elsif limit >= size
109
- dup
110
- else
111
- from(-limit)
112
- end
93
+ self[[length - limit, 0].max, limit] || raise(ArgumentError, "negative limit")
113
94
  end
114
95
  end
@@ -18,6 +18,7 @@ class String
18
18
  # "2012-12-13T06:12".to_time # => 2012-12-13 06:12:00 +0100
19
19
  # "2012-12-13T06:12".to_time(:utc) # => 2012-12-13 06:12:00 UTC
20
20
  # "12/13/2012".to_time # => ArgumentError: argument out of range
21
+ # "1604326192".to_time # => ArgumentError: argument out of range
21
22
  def to_time(form = :local)
22
23
  parts = Date._parse(self, false)
23
24
  used_keys = %i(year mon mday hour min sec sec_fraction offset)
@@ -30,6 +30,8 @@ class String
30
30
  # 'apple'.pluralize(2) # => "apples"
31
31
  # 'ley'.pluralize(:es) # => "leyes"
32
32
  # 'ley'.pluralize(1, :es) # => "ley"
33
+ #
34
+ # See ActiveSupport::Inflector.pluralize.
33
35
  def pluralize(count = nil, locale = :en)
34
36
  locale = count if count.is_a?(Symbol)
35
37
  if count == 1
@@ -53,28 +55,34 @@ class String
53
55
  # 'the blue mailmen'.singularize # => "the blue mailman"
54
56
  # 'CamelOctopi'.singularize # => "CamelOctopus"
55
57
  # 'leyes'.singularize(:es) # => "ley"
58
+ #
59
+ # See ActiveSupport::Inflector.singularize.
56
60
  def singularize(locale = :en)
57
61
  ActiveSupport::Inflector.singularize(self, locale)
58
62
  end
59
63
 
60
64
  # +constantize+ tries to find a declared constant with the name specified
61
65
  # in the string. It raises a NameError when the name is not in CamelCase
62
- # or is not initialized. See ActiveSupport::Inflector.constantize
66
+ # or is not initialized.
63
67
  #
64
68
  # 'Module'.constantize # => Module
65
69
  # 'Class'.constantize # => Class
66
70
  # 'blargle'.constantize # => NameError: wrong constant name blargle
71
+ #
72
+ # See ActiveSupport::Inflector.constantize.
67
73
  def constantize
68
74
  ActiveSupport::Inflector.constantize(self)
69
75
  end
70
76
 
71
77
  # +safe_constantize+ tries to find a declared constant with the name specified
72
78
  # in the string. It returns +nil+ when the name is not in CamelCase
73
- # or is not initialized. See ActiveSupport::Inflector.safe_constantize
79
+ # or is not initialized.
74
80
  #
75
81
  # 'Module'.safe_constantize # => Module
76
82
  # 'Class'.safe_constantize # => Class
77
83
  # 'blargle'.safe_constantize # => nil
84
+ #
85
+ # See ActiveSupport::Inflector.safe_constantize.
78
86
  def safe_constantize
79
87
  ActiveSupport::Inflector.safe_constantize(self)
80
88
  end
@@ -88,6 +96,10 @@ class String
88
96
  # 'active_record'.camelize(:lower) # => "activeRecord"
89
97
  # 'active_record/errors'.camelize # => "ActiveRecord::Errors"
90
98
  # 'active_record/errors'.camelize(:lower) # => "activeRecord::Errors"
99
+ #
100
+ # +camelize+ is also aliased as +camelcase+.
101
+ #
102
+ # See ActiveSupport::Inflector.camelize.
91
103
  def camelize(first_letter = :upper)
92
104
  case first_letter
93
105
  when :upper
@@ -108,11 +120,13 @@ class String
108
120
  # optional parameter +keep_id_suffix+ to true.
109
121
  # By default, this parameter is false.
110
122
  #
111
- # +titleize+ is also aliased as +titlecase+.
112
- #
113
123
  # 'man from the boondocks'.titleize # => "Man From The Boondocks"
114
124
  # 'x-men: the last stand'.titleize # => "X Men: The Last Stand"
115
125
  # 'string_ending_with_id'.titleize(keep_id_suffix: true) # => "String Ending With Id"
126
+ #
127
+ # +titleize+ is also aliased as +titlecase+.
128
+ #
129
+ # See ActiveSupport::Inflector.titleize.
116
130
  def titleize(keep_id_suffix: false)
117
131
  ActiveSupport::Inflector.titleize(self, keep_id_suffix: keep_id_suffix)
118
132
  end
@@ -124,6 +138,8 @@ class String
124
138
  #
125
139
  # 'ActiveModel'.underscore # => "active_model"
126
140
  # 'ActiveModel::Errors'.underscore # => "active_model/errors"
141
+ #
142
+ # See ActiveSupport::Inflector.underscore.
127
143
  def underscore
128
144
  ActiveSupport::Inflector.underscore(self)
129
145
  end
@@ -131,6 +147,8 @@ class String
131
147
  # Replaces underscores with dashes in the string.
132
148
  #
133
149
  # 'puni_puni'.dasherize # => "puni-puni"
150
+ #
151
+ # See ActiveSupport::Inflector.dasherize.
134
152
  def dasherize
135
153
  ActiveSupport::Inflector.dasherize(self)
136
154
  end
@@ -142,6 +160,8 @@ class String
142
160
  # '::Inflections'.demodulize # => "Inflections"
143
161
  # ''.demodulize # => ''
144
162
  #
163
+ # See ActiveSupport::Inflector.demodulize.
164
+ #
145
165
  # See also +deconstantize+.
146
166
  def demodulize
147
167
  ActiveSupport::Inflector.demodulize(self)
@@ -155,6 +175,8 @@ class String
155
175
  # '::String'.deconstantize # => ""
156
176
  # ''.deconstantize # => ""
157
177
  #
178
+ # See ActiveSupport::Inflector.deconstantize.
179
+ #
158
180
  # See also +demodulize+.
159
181
  def deconstantize
160
182
  ActiveSupport::Inflector.deconstantize(self)
@@ -192,6 +214,8 @@ class String
192
214
  #
193
215
  # <%= link_to(@person.name, person_path) %>
194
216
  # # => <a href="/person/1-Donald-E-Knuth">Donald E. Knuth</a>
217
+ #
218
+ # See ActiveSupport::Inflector.parameterize.
195
219
  def parameterize(separator: "-", preserve_case: false, locale: nil)
196
220
  ActiveSupport::Inflector.parameterize(self, separator: separator, preserve_case: preserve_case, locale: locale)
197
221
  end
@@ -202,6 +226,8 @@ class String
202
226
  # 'RawScaledScorer'.tableize # => "raw_scaled_scorers"
203
227
  # 'ham_and_egg'.tableize # => "ham_and_eggs"
204
228
  # 'fancyCategory'.tableize # => "fancy_categories"
229
+ #
230
+ # See ActiveSupport::Inflector.tableize.
205
231
  def tableize
206
232
  ActiveSupport::Inflector.tableize(self)
207
233
  end
@@ -212,6 +238,8 @@ class String
212
238
  #
213
239
  # 'ham_and_eggs'.classify # => "HamAndEgg"
214
240
  # 'posts'.classify # => "Post"
241
+ #
242
+ # See ActiveSupport::Inflector.classify.
215
243
  def classify
216
244
  ActiveSupport::Inflector.classify(self)
217
245
  end
@@ -233,6 +261,8 @@ class String
233
261
  # 'author_id'.humanize(capitalize: false) # => "author"
234
262
  # '_id'.humanize # => "Id"
235
263
  # 'author_id'.humanize(keep_id_suffix: true) # => "Author Id"
264
+ #
265
+ # See ActiveSupport::Inflector.humanize.
236
266
  def humanize(capitalize: true, keep_id_suffix: false)
237
267
  ActiveSupport::Inflector.humanize(self, capitalize: capitalize, keep_id_suffix: keep_id_suffix)
238
268
  end
@@ -242,6 +272,8 @@ class String
242
272
  # 'what a Lovely Day'.upcase_first # => "What a Lovely Day"
243
273
  # 'w'.upcase_first # => "W"
244
274
  # ''.upcase_first # => ""
275
+ #
276
+ # See ActiveSupport::Inflector.upcase_first.
245
277
  def upcase_first
246
278
  ActiveSupport::Inflector.upcase_first(self)
247
279
  end
@@ -253,6 +285,8 @@ class String
253
285
  # 'Message'.foreign_key # => "message_id"
254
286
  # 'Message'.foreign_key(false) # => "messageid"
255
287
  # 'Admin::Post'.foreign_key # => "post_id"
288
+ #
289
+ # See ActiveSupport::Inflector.foreign_key.
256
290
  def foreign_key(separate_class_name_and_id_with_underscore = true)
257
291
  ActiveSupport::Inflector.foreign_key(self, separate_class_name_and_id_with_underscore)
258
292
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/string_inquirer"
4
+ require "active_support/environment_inquirer"
4
5
 
5
6
  class String
6
7
  # Wraps the current string in the <tt>ActiveSupport::StringInquirer</tt> class,
@@ -47,9 +47,9 @@ class String
47
47
  # iso_str.is_utf8? # => false
48
48
  def is_utf8?
49
49
  case encoding
50
- when Encoding::UTF_8
50
+ when Encoding::UTF_8, Encoding::US_ASCII
51
51
  valid_encoding?
52
- when Encoding::ASCII_8BIT, Encoding::US_ASCII
52
+ when Encoding::ASCII_8BIT
53
53
  dup.force_encoding(Encoding::UTF_8).valid_encoding?
54
54
  else
55
55
  false