activesupport 4.2.0 → 5.2.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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +366 -232
- data/MIT-LICENSE +2 -2
- data/README.rdoc +4 -5
- data/lib/active_support.rb +17 -7
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +7 -5
- data/lib/active_support/benchmarkable.rb +6 -4
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache.rb +271 -177
- data/lib/active_support/cache/file_store.rb +41 -35
- data/lib/active_support/cache/mem_cache_store.rb +97 -88
- data/lib/active_support/cache/memory_store.rb +27 -30
- data/lib/active_support/cache/null_store.rb +7 -8
- data/lib/active_support/cache/redis_cache_store.rb +454 -0
- data/lib/active_support/cache/strategy/local_cache.rb +67 -34
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
- data/lib/active_support/callbacks.rb +654 -560
- data/lib/active_support/concern.rb +5 -3
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
- data/lib/active_support/concurrency/share_lock.rb +227 -0
- data/lib/active_support/configurable.rb +8 -5
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/core_ext/array.rb +9 -6
- data/lib/active_support/core_ext/array/access.rb +29 -1
- data/lib/active_support/core_ext/array/conversions.rb +22 -18
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +11 -18
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
- data/lib/active_support/core_ext/array/wrap.rb +7 -4
- data/lib/active_support/core_ext/benchmark.rb +3 -1
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
- data/lib/active_support/core_ext/class.rb +4 -3
- data/lib/active_support/core_ext/class/attribute.rb +41 -22
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
- data/lib/active_support/core_ext/class/subclasses.rb +20 -8
- data/lib/active_support/core_ext/date.rb +6 -4
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +14 -0
- data/lib/active_support/core_ext/date/calculations.rb +11 -9
- data/lib/active_support/core_ext/date/conversions.rb +31 -23
- data/lib/active_support/core_ext/date/zones.rb +4 -2
- data/lib/active_support/core_ext/date_and_time/calculations.rb +179 -56
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
- data/lib/active_support/core_ext/date_time.rb +7 -4
- data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +14 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +58 -20
- data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
- data/lib/active_support/core_ext/digest/uuid.rb +7 -5
- data/lib/active_support/core_ext/enumerable.rb +107 -28
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/file/atomic.rb +38 -31
- data/lib/active_support/core_ext/hash.rb +11 -9
- data/lib/active_support/core_ext/hash/compact.rb +24 -15
- data/lib/active_support/core_ext/hash/conversions.rb +63 -43
- data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
- data/lib/active_support/core_ext/hash/except.rb +11 -8
- data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
- data/lib/active_support/core_ext/hash/keys.rb +33 -27
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -8
- data/lib/active_support/core_ext/hash/transform_values.rb +16 -7
- data/lib/active_support/core_ext/integer.rb +5 -3
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +2 -0
- data/lib/active_support/core_ext/integer/time.rb +11 -33
- data/lib/active_support/core_ext/kernel.rb +6 -5
- data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
- data/lib/active_support/core_ext/kernel/concern.rb +5 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -83
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/load_error.rb +3 -22
- data/lib/active_support/core_ext/marshal.rb +13 -10
- data/lib/active_support/core_ext/module.rb +14 -11
- data/lib/active_support/core_ext/module/aliasing.rb +6 -44
- data/lib/active_support/core_ext/module/anonymous.rb +12 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
- data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
- data/lib/active_support/core_ext/module/concerning.rb +11 -12
- data/lib/active_support/core_ext/module/delegation.rb +121 -39
- data/lib/active_support/core_ext/module/deprecation.rb +4 -2
- data/lib/active_support/core_ext/module/introspection.rb +9 -9
- data/lib/active_support/core_ext/module/reachable.rb +5 -2
- data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
- data/lib/active_support/core_ext/module/remove_method.rb +8 -3
- data/lib/active_support/core_ext/name_error.rb +22 -2
- data/lib/active_support/core_ext/numeric.rb +6 -3
- data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +79 -74
- data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
- data/lib/active_support/core_ext/numeric/time.rb +35 -38
- data/lib/active_support/core_ext/object.rb +14 -13
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +29 -4
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
- data/lib/active_support/core_ext/object/duplicable.rb +98 -45
- data/lib/active_support/core_ext/object/inclusion.rb +5 -3
- data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
- data/lib/active_support/core_ext/object/json.rb +49 -19
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +6 -4
- data/lib/active_support/core_ext/object/try.rb +70 -22
- data/lib/active_support/core_ext/object/with_options.rb +16 -3
- data/lib/active_support/core_ext/range.rb +7 -4
- data/lib/active_support/core_ext/range/conversions.rb +27 -7
- data/lib/active_support/core_ext/range/each.rb +19 -17
- data/lib/active_support/core_ext/range/include_range.rb +21 -19
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/regexp.rb +6 -0
- data/lib/active_support/core_ext/securerandom.rb +25 -0
- data/lib/active_support/core_ext/string.rb +15 -13
- data/lib/active_support/core_ext/string/access.rb +9 -7
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +8 -5
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +10 -8
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +61 -24
- data/lib/active_support/core_ext/string/inquiry.rb +3 -1
- data/lib/active_support/core_ext/string/multibyte.rb +15 -7
- data/lib/active_support/core_ext/string/output_safety.rb +35 -35
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
- data/lib/active_support/core_ext/string/strip.rb +4 -5
- data/lib/active_support/core_ext/string/zones.rb +4 -2
- data/lib/active_support/core_ext/time.rb +7 -5
- data/lib/active_support/core_ext/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +101 -51
- data/lib/active_support/core_ext/time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/time/conversions.rb +20 -13
- data/lib/active_support/core_ext/time/zones.rb +41 -7
- data/lib/active_support/core_ext/uri.rb +5 -4
- data/lib/active_support/current_attributes.rb +195 -0
- data/lib/active_support/dependencies.rb +143 -160
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +57 -0
- data/lib/active_support/deprecation.rb +12 -9
- data/lib/active_support/deprecation/behaviors.rb +41 -12
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/instance_delegator.rb +17 -2
- data/lib/active_support/deprecation/method_wrappers.rb +54 -21
- data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
- data/lib/active_support/deprecation/reporting.rb +32 -12
- data/lib/active_support/descendants_tracker.rb +2 -0
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration.rb +326 -30
- data/lib/active_support/duration/iso8601_parser.rb +125 -0
- data/lib/active_support/duration/iso8601_serializer.rb +55 -0
- data/lib/active_support/encrypted_configuration.rb +49 -0
- data/lib/active_support/encrypted_file.rb +99 -0
- data/lib/active_support/evented_file_update_checker.rb +205 -0
- data/lib/active_support/execution_wrapper.rb +128 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +63 -37
- data/lib/active_support/gem_version.rb +4 -2
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +130 -30
- data/lib/active_support/i18n.rb +8 -6
- data/lib/active_support/i18n_railtie.rb +34 -14
- data/lib/active_support/inflections.rb +13 -11
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/inflector/inflections.rb +61 -12
- data/lib/active_support/inflector/methods.rb +161 -136
- data/lib/active_support/inflector/transliterate.rb +48 -27
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/json/decoding.rb +16 -13
- data/lib/active_support/json/encoding.rb +15 -57
- data/lib/active_support/key_generator.rb +25 -25
- data/lib/active_support/lazy_load_hooks.rb +50 -20
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber.rb +13 -10
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/logger.rb +54 -3
- data/lib/active_support/logger_silence.rb +12 -7
- data/lib/active_support/logger_thread_safe_level.rb +33 -0
- data/lib/active_support/message_encryptor.rb +173 -51
- data/lib/active_support/message_verifier.rb +150 -17
- data/lib/active_support/messages/metadata.rb +71 -0
- data/lib/active_support/messages/rotation_configuration.rb +22 -0
- data/lib/active_support/messages/rotator.rb +56 -0
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/multibyte/chars.rb +37 -24
- data/lib/active_support/multibyte/unicode.rb +100 -96
- data/lib/active_support/notifications.rb +11 -7
- data/lib/active_support/notifications/fanout.rb +10 -8
- data/lib/active_support/notifications/instrumenter.rb +27 -7
- data/lib/active_support/number_helper.rb +94 -68
- data/lib/active_support/number_helper/number_converter.rb +13 -11
- data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +9 -3
- data/lib/active_support/number_helper/number_to_human_converter.rb +11 -9
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +9 -8
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +13 -4
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +23 -56
- data/lib/active_support/number_helper/rounding_helper.rb +66 -0
- data/lib/active_support/option_merger.rb +3 -1
- data/lib/active_support/ordered_hash.rb +6 -4
- data/lib/active_support/ordered_options.rb +22 -4
- data/lib/active_support/per_thread_registry.rb +13 -6
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +16 -8
- data/lib/active_support/railtie.rb +43 -9
- data/lib/active_support/reloader.rb +131 -0
- data/lib/active_support/rescuable.rb +108 -53
- data/lib/active_support/security_utils.rb +17 -6
- data/lib/active_support/string_inquirer.rb +11 -3
- data/lib/active_support/subscriber.rb +15 -14
- data/lib/active_support/tagged_logging.rb +14 -11
- data/lib/active_support/test_case.rb +18 -46
- data/lib/active_support/testing/assertions.rb +137 -20
- data/lib/active_support/testing/autorun.rb +4 -2
- data/lib/active_support/testing/constant_lookup.rb +2 -1
- data/lib/active_support/testing/declarative.rb +3 -1
- data/lib/active_support/testing/deprecation.rb +14 -10
- data/lib/active_support/testing/file_fixtures.rb +36 -0
- data/lib/active_support/testing/isolation.rb +34 -25
- data/lib/active_support/testing/method_call_assertions.rb +43 -0
- data/lib/active_support/testing/setup_and_teardown.rb +12 -3
- data/lib/active_support/testing/stream.rb +44 -0
- data/lib/active_support/testing/tagged_logging.rb +3 -1
- data/lib/active_support/testing/time_helpers.rb +96 -27
- data/lib/active_support/time.rb +14 -12
- data/lib/active_support/time_with_zone.rb +195 -53
- data/lib/active_support/values/time_zone.rb +200 -61
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +3 -1
- data/lib/active_support/xml_mini.rb +69 -51
- data/lib/active_support/xml_mini/jdom.rb +116 -113
- data/lib/active_support/xml_mini/libxml.rb +17 -16
- data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
- data/lib/active_support/xml_mini/nokogiri.rb +15 -15
- data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
- data/lib/active_support/xml_mini/rexml.rb +17 -16
- metadata +55 -43
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -14
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
- data/lib/active_support/core_ext/date_time/zones.rb +0 -6
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
- data/lib/active_support/core_ext/module/method_transplanting.rb +0 -11
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
- data/lib/active_support/core_ext/object/itself.rb +0 -15
- data/lib/active_support/core_ext/struct.rb +0 -6
- data/lib/active_support/core_ext/thread.rb +0 -86
- data/lib/active_support/core_ext/time/marshal.rb +0 -30
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class String
|
2
|
-
# If you pass a single
|
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
|
-
|
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
|
-
|
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
|
-
#
|
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
|
-
|
2
|
-
|
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
|
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
|
-
|
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(
|
@@ -31,7 +34,7 @@ class String
|
|
31
34
|
parts.fetch(:offset, form == :utc ? 0 : nil)
|
32
35
|
)
|
33
36
|
|
34
|
-
form == :utc ? time.utc : time.
|
37
|
+
form == :utc ? time.utc : time.to_time
|
35
38
|
end
|
36
39
|
|
37
40
|
# Converts a string to a Date value.
|
@@ -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,15 +19,15 @@ class String
|
|
17
19
|
# str.squish! # => "foo bar boo"
|
18
20
|
# str # => "foo bar boo"
|
19
21
|
def squish!
|
20
|
-
gsub!(
|
21
|
-
|
22
|
-
gsub!(/[[:space:]]+/, ' ')
|
22
|
+
gsub!(/[[:space:]]+/, " ")
|
23
|
+
strip!
|
23
24
|
self
|
24
25
|
end
|
25
26
|
|
26
27
|
# Returns a new string with all occurrences of the patterns removed.
|
27
28
|
# str = "foo bar test"
|
28
29
|
# str.remove(" test") # => "foo bar"
|
30
|
+
# str.remove(" test", /bar/) # => "foo "
|
29
31
|
# str # => "foo bar test"
|
30
32
|
def remove(*patterns)
|
31
33
|
dup.remove!(*patterns)
|
@@ -33,8 +35,8 @@ class String
|
|
33
35
|
|
34
36
|
# Alters the string by removing all occurrences of the patterns.
|
35
37
|
# str = "foo bar test"
|
36
|
-
# str.remove!(" test")
|
37
|
-
# str
|
38
|
+
# str.remove!(" test", /bar/) # => "foo "
|
39
|
+
# str # => "foo "
|
38
40
|
def remove!(*patterns)
|
39
41
|
patterns.each do |pattern|
|
40
42
|
gsub! pattern, ""
|
@@ -64,7 +66,7 @@ class String
|
|
64
66
|
def truncate(truncate_at, options = {})
|
65
67
|
return dup unless length > truncate_at
|
66
68
|
|
67
|
-
omission = options[:omission] ||
|
69
|
+
omission = options[:omission] || "..."
|
68
70
|
length_with_room_for_omission = truncate_at - omission.length
|
69
71
|
stop = \
|
70
72
|
if options[:separator]
|
@@ -93,8 +95,8 @@ class String
|
|
93
95
|
def truncate_words(words_count, options = {})
|
94
96
|
sep = options[:separator] || /\s+/
|
95
97
|
sep = Regexp.escape(sep.to_s) unless Regexp === sep
|
96
|
-
if self =~ /\A((
|
97
|
-
$1 + (options[:omission] ||
|
98
|
+
if self =~ /\A((?>.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/m
|
99
|
+
$1 + (options[:omission] || "...")
|
98
100
|
else
|
99
101
|
dup
|
100
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
|
-
|
2
|
-
|
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
|
-
|
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
|
106
|
-
# 'x-men: the last stand'.titleize
|
107
|
-
|
108
|
-
|
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
|
-
# '
|
132
|
-
# 'Inflections'.demodulize
|
133
|
-
# '::Inflections'.demodulize
|
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
|
-
|
168
|
-
|
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
|
-
# '
|
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
|
-
#
|
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
|
-
# '
|
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
|
-
#
|
200
|
-
#
|
201
|
-
#
|
202
|
-
#
|
203
|
-
|
204
|
-
|
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,5 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
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
|
-
#
|
14
|
-
#
|
15
|
-
#
|
14
|
+
# >> "lj".upcase
|
15
|
+
# => "lj"
|
16
|
+
# >> "lj".mb_chars.upcase.to_s
|
17
|
+
# => "LJ"
|
16
18
|
#
|
17
|
-
#
|
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
|
@@ -1,34 +1,32 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "erb"
|
4
|
+
require "active_support/core_ext/kernel/singleton_class"
|
5
|
+
require "active_support/core_ext/module/redefine_method"
|
6
|
+
require "active_support/multibyte/unicode"
|
4
7
|
|
5
8
|
class ERB
|
6
9
|
module Util
|
7
|
-
HTML_ESCAPE = {
|
8
|
-
JSON_ESCAPE = {
|
9
|
-
HTML_ESCAPE_REGEXP = /[&"'><]/
|
10
|
+
HTML_ESCAPE = { "&" => "&", ">" => ">", "<" => "<", '"' => """, "'" => "'" }
|
11
|
+
JSON_ESCAPE = { "&" => '\u0026', ">" => '\u003e', "<" => '\u003c', "\u2028" => '\u2028', "\u2029" => '\u2029' }
|
10
12
|
HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+)|(#[xX][\dA-Fa-f]+));)/
|
11
13
|
JSON_ESCAPE_REGEXP = /[\u2028\u2029&><]/u
|
12
14
|
|
13
15
|
# A utility method for escaping HTML tag characters.
|
14
16
|
# This method is also aliased as <tt>h</tt>.
|
15
17
|
#
|
16
|
-
# In your ERB templates, use this method to escape any unsafe content. For example:
|
17
|
-
# <%=h @person.name %>
|
18
|
-
#
|
19
18
|
# puts html_escape('is a > 0 & a < 10?')
|
20
19
|
# # => is a > 0 & a < 10?
|
21
20
|
def html_escape(s)
|
22
21
|
unwrapped_html_escape(s).html_safe
|
23
22
|
end
|
24
23
|
|
25
|
-
|
26
|
-
remove_method(:h)
|
24
|
+
silence_redefinition_of_method :h
|
27
25
|
alias h html_escape
|
28
26
|
|
29
27
|
module_function :h
|
30
28
|
|
31
|
-
singleton_class.
|
29
|
+
singleton_class.silence_redefinition_of_method :html_escape
|
32
30
|
module_function :html_escape
|
33
31
|
|
34
32
|
# HTML escapes strings but doesn't wrap them with an ActiveSupport::SafeBuffer.
|
@@ -38,7 +36,7 @@ class ERB
|
|
38
36
|
if s.html_safe?
|
39
37
|
s
|
40
38
|
else
|
41
|
-
|
39
|
+
CGI.escapeHTML(ActiveSupport::Multibyte::Unicode.tidy_bytes(s))
|
42
40
|
end
|
43
41
|
end
|
44
42
|
module_function :unwrapped_html_escape
|
@@ -51,7 +49,7 @@ class ERB
|
|
51
49
|
# html_escape_once('<< Accept & Checkout')
|
52
50
|
# # => "<< Accept & Checkout"
|
53
51
|
def html_escape_once(s)
|
54
|
-
result = s.to_s.gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE)
|
52
|
+
result = ActiveSupport::Multibyte::Unicode.tidy_bytes(s.to_s).gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE)
|
55
53
|
s.html_safe? ? result.html_safe : result
|
56
54
|
end
|
57
55
|
|
@@ -86,6 +84,11 @@ class ERB
|
|
86
84
|
# automatically flag the result as HTML safe, since the raw value is unsafe to
|
87
85
|
# use inside HTML attributes.
|
88
86
|
#
|
87
|
+
# If your JSON is being used downstream for insertion into the DOM, be aware of
|
88
|
+
# whether or not it is being inserted via +html()+. Most jQuery plugins do this.
|
89
|
+
# If that is the case, be sure to +html_escape+ or +sanitize+ any user-generated
|
90
|
+
# content returned by your JSON.
|
91
|
+
#
|
89
92
|
# If you need to output JSON elsewhere in your HTML, you can just do something
|
90
93
|
# like this, as any unsafe characters (including quotation marks) will be
|
91
94
|
# automatically escaped for you:
|
@@ -138,23 +141,26 @@ module ActiveSupport #:nodoc:
|
|
138
141
|
alias_method :original_concat, :concat
|
139
142
|
private :original_concat
|
140
143
|
|
144
|
+
# Raised when <tt>ActiveSupport::SafeBuffer#safe_concat</tt> is called on unsafe buffers.
|
141
145
|
class SafeConcatError < StandardError
|
142
146
|
def initialize
|
143
|
-
super
|
147
|
+
super "Could not concatenate to the buffer because it is not html safe."
|
144
148
|
end
|
145
149
|
end
|
146
150
|
|
147
151
|
def [](*args)
|
148
152
|
if args.size < 2
|
149
153
|
super
|
150
|
-
|
151
|
-
|
152
|
-
|
154
|
+
elsif html_safe?
|
155
|
+
new_safe_buffer = super
|
156
|
+
|
157
|
+
if new_safe_buffer
|
153
158
|
new_safe_buffer.instance_variable_set :@html_safe, true
|
154
|
-
new_safe_buffer
|
155
|
-
else
|
156
|
-
to_str[*args]
|
157
159
|
end
|
160
|
+
|
161
|
+
new_safe_buffer
|
162
|
+
else
|
163
|
+
to_str[*args]
|
158
164
|
end
|
159
165
|
end
|
160
166
|
|
@@ -163,7 +169,7 @@ module ActiveSupport #:nodoc:
|
|
163
169
|
original_concat(value)
|
164
170
|
end
|
165
171
|
|
166
|
-
def initialize(
|
172
|
+
def initialize(str = "")
|
167
173
|
@html_safe = true
|
168
174
|
super
|
169
175
|
end
|
@@ -186,11 +192,6 @@ module ActiveSupport #:nodoc:
|
|
186
192
|
super(html_escape_interpolated_argument(value))
|
187
193
|
end
|
188
194
|
|
189
|
-
def prepend!(value)
|
190
|
-
ActiveSupport::Deprecation.deprecation_warning "ActiveSupport::SafeBuffer#prepend!", :prepend
|
191
|
-
prepend value
|
192
|
-
end
|
193
|
-
|
194
195
|
def +(other)
|
195
196
|
dup.concat(other)
|
196
197
|
end
|
@@ -198,7 +199,7 @@ module ActiveSupport #:nodoc:
|
|
198
199
|
def %(args)
|
199
200
|
case args
|
200
201
|
when Hash
|
201
|
-
escaped_args = Hash[args.map { |k,arg| [k, html_escape_interpolated_argument(arg)] }]
|
202
|
+
escaped_args = Hash[args.map { |k, arg| [k, html_escape_interpolated_argument(arg)] }]
|
202
203
|
else
|
203
204
|
escaped_args = Array(args).map { |arg| html_escape_interpolated_argument(arg) }
|
204
205
|
end
|
@@ -219,7 +220,7 @@ module ActiveSupport #:nodoc:
|
|
219
220
|
end
|
220
221
|
|
221
222
|
def encode_with(coder)
|
222
|
-
coder.
|
223
|
+
coder.represent_object nil, to_str
|
223
224
|
end
|
224
225
|
|
225
226
|
UNSAFE_STRING_METHODS.each do |unsafe_method|
|
@@ -239,18 +240,17 @@ module ActiveSupport #:nodoc:
|
|
239
240
|
|
240
241
|
private
|
241
242
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
end
|
243
|
+
def html_escape_interpolated_argument(arg)
|
244
|
+
(!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
|
245
|
+
end
|
246
246
|
end
|
247
247
|
end
|
248
248
|
|
249
249
|
class String
|
250
250
|
# Marks a string as trusted safe. It will be inserted into HTML with no
|
251
|
-
# additional escaping performed. It is your
|
251
|
+
# additional escaping performed. It is your responsibility to ensure that the
|
252
252
|
# string contains no malicious content. This method is equivalent to the
|
253
|
-
#
|
253
|
+
# +raw+ helper in views. It is recommended that you use +sanitize+ instead of
|
254
254
|
# this method. It should never be called on user input.
|
255
255
|
def html_safe
|
256
256
|
ActiveSupport::SafeBuffer.new(self)
|