activesupport 4.0.13 → 5.2.5
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 +412 -444
- data/MIT-LICENSE +2 -2
- data/README.rdoc +8 -4
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +14 -12
- data/lib/active_support/benchmarkable.rb +6 -14
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +67 -51
- data/lib/active_support/cache/mem_cache_store.rb +95 -97
- data/lib/active_support/cache/memory_store.rb +28 -30
- data/lib/active_support/cache/null_store.rb +7 -8
- data/lib/active_support/cache/redis_cache_store.rb +466 -0
- data/lib/active_support/cache/strategy/local_cache.rb +70 -56
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
- data/lib/active_support/cache.rb +331 -206
- data/lib/active_support/callbacks.rb +697 -426
- data/lib/active_support/concern.rb +32 -10
- 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/array/access.rb +39 -1
- data/lib/active_support/core_ext/array/conversions.rb +24 -35
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +23 -13
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -5
- data/lib/active_support/core_ext/array/wrap.rb +7 -4
- data/lib/active_support/core_ext/array.rb +9 -7
- data/lib/active_support/core_ext/benchmark.rb +3 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +9 -26
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +41 -23
- data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
- data/lib/active_support/core_ext/class/subclasses.rb +20 -8
- data/lib/active_support/core_ext/class.rb +4 -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 +21 -9
- data/lib/active_support/core_ext/date/conversions.rb +32 -22
- data/lib/active_support/core_ext/date/zones.rb +5 -34
- data/lib/active_support/core_ext/date.rb +6 -4
- data/lib/active_support/core_ext/date_and_time/calculations.rb +199 -57
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +41 -0
- 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 +78 -37
- data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +19 -13
- data/lib/active_support/core_ext/date_time.rb +7 -4
- data/lib/active_support/core_ext/digest/uuid.rb +53 -0
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +113 -29
- data/lib/active_support/core_ext/file/atomic.rb +38 -31
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/hash/compact.rb +29 -0
- data/lib/active_support/core_ext/hash/conversions.rb +71 -49
- data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
- data/lib/active_support/core_ext/hash/except.rb +12 -3
- data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
- data/lib/active_support/core_ext/hash/keys.rb +50 -38
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +12 -6
- data/lib/active_support/core_ext/hash/transform_values.rb +32 -0
- data/lib/active_support/core_ext/hash.rb +11 -8
- 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/integer.rb +5 -3
- data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
- data/lib/active_support/core_ext/kernel/concern.rb +14 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +5 -74
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +6 -4
- data/lib/active_support/core_ext/load_error.rb +5 -21
- data/lib/active_support/core_ext/marshal.rb +13 -10
- 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 -8
- data/lib/active_support/core_ext/module/attribute_accessors.rb +170 -21
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
- data/lib/active_support/core_ext/module/concerning.rb +134 -0
- data/lib/active_support/core_ext/module/delegation.rb +135 -45
- data/lib/active_support/core_ext/module/deprecation.rb +3 -3
- data/lib/active_support/core_ext/module/introspection.rb +9 -25
- 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/module.rb +14 -10
- data/lib/active_support/core_ext/name_error.rb +22 -2
- 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 +37 -50
- data/lib/active_support/core_ext/numeric.rb +6 -3
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +70 -19
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +19 -10
- data/lib/active_support/core_ext/object/duplicable.rb +100 -34
- data/lib/active_support/core_ext/object/inclusion.rb +18 -15
- data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
- data/lib/active_support/core_ext/object/json.rb +227 -0
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +21 -8
- data/lib/active_support/core_ext/object/try.rb +94 -24
- data/lib/active_support/core_ext/object/with_options.rb +45 -5
- data/lib/active_support/core_ext/object.rb +14 -12
- data/lib/active_support/core_ext/range/compare_range.rb +61 -0
- 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 +2 -22
- 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/range.rb +7 -4
- 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/access.rb +41 -39
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +17 -13
- data/lib/active_support/core_ext/string/exclude.rb +5 -3
- data/lib/active_support/core_ext/string/filters.rb +55 -6
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +66 -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 +114 -54
- 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 -1
- data/lib/active_support/core_ext/string.rb +15 -13
- data/lib/active_support/core_ext/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +123 -110
- data/lib/active_support/core_ext/time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/time/conversions.rb +23 -14
- data/lib/active_support/core_ext/time/zones.rb +42 -26
- data/lib/active_support/core_ext/time.rb +7 -5
- data/lib/active_support/core_ext/uri.rb +6 -8
- data/lib/active_support/core_ext.rb +3 -2
- data/lib/active_support/current_attributes.rb +195 -0
- data/lib/active_support/dependencies/autoload.rb +3 -1
- data/lib/active_support/dependencies/interlock.rb +57 -0
- data/lib/active_support/dependencies.rb +196 -166
- data/lib/active_support/deprecation/behaviors.rb +48 -15
- 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 +66 -20
- data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
- data/lib/active_support/deprecation/reporting.rb +32 -12
- data/lib/active_support/deprecation.rb +14 -11
- data/lib/active_support/descendants_tracker.rb +2 -0
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration/iso8601_parser.rb +125 -0
- data/lib/active_support/duration/iso8601_serializer.rb +55 -0
- data/lib/active_support/duration.rb +354 -34
- 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 +17 -0
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +158 -35
- data/lib/active_support/i18n.rb +8 -6
- data/lib/active_support/i18n_railtie.rb +38 -20
- data/lib/active_support/inflections.rb +19 -12
- data/lib/active_support/inflector/inflections.rb +79 -30
- data/lib/active_support/inflector/methods.rb +197 -129
- data/lib/active_support/inflector/transliterate.rb +48 -27
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/json/decoding.rb +21 -25
- data/lib/active_support/json/encoding.rb +84 -292
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +26 -28
- data/lib/active_support/lazy_load_hooks.rb +51 -21
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/log_subscriber.rb +13 -10
- 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 +34 -0
- data/lib/active_support/message_encryptor.rb +173 -50
- data/lib/active_support/message_verifier.rb +159 -22
- 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/chars.rb +38 -26
- data/lib/active_support/multibyte/unicode.rb +138 -146
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/notifications/fanout.rb +23 -16
- data/lib/active_support/notifications/instrumenter.rb +29 -8
- data/lib/active_support/notifications.rb +22 -13
- data/lib/active_support/number_helper/number_converter.rb +184 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +29 -0
- data/lib/active_support/number_helper/number_to_human_converter.rb +68 -0
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +59 -0
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +14 -0
- data/lib/active_support/number_helper/number_to_phone_converter.rb +58 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +54 -0
- data/lib/active_support/number_helper/rounding_helper.rb +66 -0
- data/lib/active_support/number_helper.rb +125 -391
- 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 +31 -5
- data/lib/active_support/per_thread_registry.rb +19 -11
- 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 +31 -0
- data/lib/active_support/string_inquirer.rb +11 -3
- data/lib/active_support/subscriber.rb +54 -17
- data/lib/active_support/tagged_logging.rb +14 -11
- data/lib/active_support/test_case.rb +42 -37
- data/lib/active_support/testing/assertions.rb +126 -39
- data/lib/active_support/testing/autorun.rb +5 -3
- data/lib/active_support/testing/constant_lookup.rb +3 -6
- data/lib/active_support/testing/declarative.rb +10 -22
- 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 +55 -86
- data/lib/active_support/testing/method_call_assertions.rb +43 -0
- data/lib/active_support/testing/setup_and_teardown.rb +30 -10
- data/lib/active_support/testing/stream.rb +44 -0
- data/lib/active_support/testing/tagged_logging.rb +5 -3
- data/lib/active_support/testing/time_helpers.rb +200 -0
- data/lib/active_support/time.rb +13 -13
- data/lib/active_support/time_with_zone.rb +223 -73
- data/lib/active_support/values/time_zone.rb +261 -126
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +6 -7
- 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
- data/lib/active_support/xml_mini.rb +69 -51
- data/lib/active_support.rb +29 -3
- metadata +84 -54
- data/lib/active_support/basic_object.rb +0 -11
- data/lib/active_support/buffered_logger.rb +0 -21
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -40
- data/lib/active_support/core_ext/date_time/zones.rb +0 -24
- data/lib/active_support/core_ext/hash/diff.rb +0 -14
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
- data/lib/active_support/core_ext/logger.rb +0 -67
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
- data/lib/active_support/core_ext/object/to_json.rb +0 -27
- data/lib/active_support/core_ext/proc.rb +0 -17
- data/lib/active_support/core_ext/string/encoding.rb +0 -8
- data/lib/active_support/core_ext/struct.rb +0 -6
- data/lib/active_support/core_ext/thread.rb +0 -79
- data/lib/active_support/core_ext/time/marshal.rb +0 -30
- data/lib/active_support/file_watcher.rb +0 -36
- data/lib/active_support/json/variable.rb +0 -18
- data/lib/active_support/testing/pending.rb +0 -14
@@ -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,10 +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
|
20
|
+
# "12/13/2012".to_time # => ArgumentError: argument out of range
|
18
21
|
def to_time(form = :local)
|
19
22
|
parts = Date._parse(self, false)
|
20
|
-
|
23
|
+
used_keys = %i(year mon mday hour min sec sec_fraction offset)
|
24
|
+
return if (parts.keys & used_keys).empty?
|
21
25
|
|
22
26
|
now = Time.now
|
23
27
|
time = Time.new(
|
@@ -30,25 +34,25 @@ class String
|
|
30
34
|
parts.fetch(:offset, form == :utc ? 0 : nil)
|
31
35
|
)
|
32
36
|
|
33
|
-
form == :utc ? time.utc : time.
|
37
|
+
form == :utc ? time.utc : time.to_time
|
34
38
|
end
|
35
39
|
|
36
40
|
# Converts a string to a Date value.
|
37
41
|
#
|
38
|
-
# "1-1-2012".to_date
|
39
|
-
# "01/01/2012".to_date
|
40
|
-
# "2012-12-13".to_date
|
41
|
-
# "12/13/2012".to_date
|
42
|
+
# "1-1-2012".to_date # => Sun, 01 Jan 2012
|
43
|
+
# "01/01/2012".to_date # => Sun, 01 Jan 2012
|
44
|
+
# "2012-12-13".to_date # => Thu, 13 Dec 2012
|
45
|
+
# "12/13/2012".to_date # => ArgumentError: invalid date
|
42
46
|
def to_date
|
43
47
|
::Date.parse(self, false) unless blank?
|
44
48
|
end
|
45
49
|
|
46
50
|
# Converts a string to a DateTime value.
|
47
51
|
#
|
48
|
-
# "1-1-2012".to_datetime
|
49
|
-
# "01/01/2012 23:59:59".to_datetime
|
50
|
-
# "2012-12-13 12:50".to_datetime
|
51
|
-
# "12/13/2012".to_datetime
|
52
|
+
# "1-1-2012".to_datetime # => Sun, 01 Jan 2012 00:00:00 +0000
|
53
|
+
# "01/01/2012 23:59:59".to_datetime # => Sun, 01 Jan 2012 23:59:59 +0000
|
54
|
+
# "2012-12-13 12:50".to_datetime # => Thu, 13 Dec 2012 12:50:00 +0000
|
55
|
+
# "12/13/2012".to_datetime # => ArgumentError: invalid date
|
52
56
|
def to_datetime
|
53
57
|
::DateTime.parse(self, false) unless blank?
|
54
58
|
end
|
@@ -1,10 +1,12 @@
|
|
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.
|
4
6
|
#
|
5
|
-
# "hello".exclude? "lo"
|
6
|
-
# "hello".exclude? "ol"
|
7
|
-
# "hello".exclude? ?h
|
7
|
+
# "hello".exclude? "lo" # => false
|
8
|
+
# "hello".exclude? "ol" # => true
|
9
|
+
# "hello".exclude? ?h # => false
|
8
10
|
def exclude?(string)
|
9
11
|
!include?(string)
|
10
12
|
end
|
@@ -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
|
@@ -13,10 +15,33 @@ class String
|
|
13
15
|
end
|
14
16
|
|
15
17
|
# Performs a destructive squish. See String#squish.
|
18
|
+
# str = " foo bar \n \t boo"
|
19
|
+
# str.squish! # => "foo bar boo"
|
20
|
+
# str # => "foo bar boo"
|
16
21
|
def squish!
|
17
|
-
gsub!(
|
18
|
-
|
19
|
-
|
22
|
+
gsub!(/[[:space:]]+/, " ")
|
23
|
+
strip!
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns a new string with all occurrences of the patterns removed.
|
28
|
+
# str = "foo bar test"
|
29
|
+
# str.remove(" test") # => "foo bar"
|
30
|
+
# str.remove(" test", /bar/) # => "foo "
|
31
|
+
# str # => "foo bar test"
|
32
|
+
def remove(*patterns)
|
33
|
+
dup.remove!(*patterns)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Alters the string by removing all occurrences of the patterns.
|
37
|
+
# str = "foo bar test"
|
38
|
+
# str.remove!(" test", /bar/) # => "foo "
|
39
|
+
# str # => "foo "
|
40
|
+
def remove!(*patterns)
|
41
|
+
patterns.each do |pattern|
|
42
|
+
gsub! pattern, ""
|
43
|
+
end
|
44
|
+
|
20
45
|
self
|
21
46
|
end
|
22
47
|
|
@@ -41,8 +66,8 @@ class String
|
|
41
66
|
def truncate(truncate_at, options = {})
|
42
67
|
return dup unless length > truncate_at
|
43
68
|
|
44
|
-
options[:omission]
|
45
|
-
length_with_room_for_omission = truncate_at -
|
69
|
+
omission = options[:omission] || "..."
|
70
|
+
length_with_room_for_omission = truncate_at - omission.length
|
46
71
|
stop = \
|
47
72
|
if options[:separator]
|
48
73
|
rindex(options[:separator], length_with_room_for_omission) || length_with_room_for_omission
|
@@ -50,6 +75,30 @@ class String
|
|
50
75
|
length_with_room_for_omission
|
51
76
|
end
|
52
77
|
|
53
|
-
"#{self[0
|
78
|
+
"#{self[0, stop]}#{omission}"
|
79
|
+
end
|
80
|
+
|
81
|
+
# Truncates a given +text+ after a given number of words (<tt>words_count</tt>):
|
82
|
+
#
|
83
|
+
# 'Once upon a time in a world far far away'.truncate_words(4)
|
84
|
+
# # => "Once upon a time..."
|
85
|
+
#
|
86
|
+
# Pass a string or regexp <tt>:separator</tt> to specify a different separator of words:
|
87
|
+
#
|
88
|
+
# 'Once<br>upon<br>a<br>time<br>in<br>a<br>world'.truncate_words(5, separator: '<br>')
|
89
|
+
# # => "Once<br>upon<br>a<br>time<br>in..."
|
90
|
+
#
|
91
|
+
# The last characters will be replaced with the <tt>:omission</tt> string (defaults to "..."):
|
92
|
+
#
|
93
|
+
# 'And they found that many people were sleeping better.'.truncate_words(5, omission: '... (continued)')
|
94
|
+
# # => "And they found that many... (continued)"
|
95
|
+
def truncate_words(words_count, options = {})
|
96
|
+
sep = options[:separator] || /\s+/
|
97
|
+
sep = Regexp.escape(sep.to_s) unless Regexp === sep
|
98
|
+
if self =~ /\A((?>.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/m
|
99
|
+
$1 + (options[:omission] || "...")
|
100
|
+
else
|
101
|
+
dup
|
102
|
+
end
|
54
103
|
end
|
55
104
|
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,8 +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
|
140
|
+
# 'ActiveSupport::Inflector::Inflections'.demodulize # => "Inflections"
|
141
|
+
# 'Inflections'.demodulize # => "Inflections"
|
142
|
+
# '::Inflections'.demodulize # => "Inflections"
|
143
|
+
# ''.demodulize # => ''
|
133
144
|
#
|
134
145
|
# See also +deconstantize+.
|
135
146
|
def demodulize
|
@@ -162,41 +173,72 @@ class String
|
|
162
173
|
#
|
163
174
|
# <%= link_to(@person.name, person_path) %>
|
164
175
|
# # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
|
165
|
-
|
166
|
-
|
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)
|
167
192
|
end
|
168
193
|
|
169
194
|
# Creates the name of a table like Rails does for models to table names. This method
|
170
195
|
# uses the +pluralize+ method on the last word in the string.
|
171
196
|
#
|
172
197
|
# 'RawScaledScorer'.tableize # => "raw_scaled_scorers"
|
173
|
-
# '
|
198
|
+
# 'ham_and_egg'.tableize # => "ham_and_eggs"
|
174
199
|
# 'fancyCategory'.tableize # => "fancy_categories"
|
175
200
|
def tableize
|
176
201
|
ActiveSupport::Inflector.tableize(self)
|
177
202
|
end
|
178
203
|
|
179
|
-
#
|
204
|
+
# Creates a class name from a plural table name like Rails does for table names to models.
|
180
205
|
# Note that this returns a string and not a class. (To convert to an actual class
|
181
206
|
# follow +classify+ with +constantize+.)
|
182
207
|
#
|
183
|
-
# '
|
208
|
+
# 'ham_and_eggs'.classify # => "HamAndEgg"
|
184
209
|
# 'posts'.classify # => "Post"
|
185
|
-
#
|
186
|
-
# Singular names are not handled correctly.
|
187
|
-
#
|
188
|
-
# 'business'.classify # => "Busines"
|
189
210
|
def classify
|
190
211
|
ActiveSupport::Inflector.classify(self)
|
191
212
|
end
|
192
213
|
|
193
|
-
# Capitalizes the first word, turns underscores into spaces, and strips
|
214
|
+
# Capitalizes the first word, turns underscores into spaces, and (by default)strips a
|
215
|
+
# trailing '_id' if present.
|
194
216
|
# Like +titleize+, this is meant for creating pretty output.
|
195
217
|
#
|
196
|
-
#
|
197
|
-
#
|
198
|
-
|
199
|
-
|
218
|
+
# The capitalization of the first word can be turned off by setting the
|
219
|
+
# optional parameter +capitalize+ to false.
|
220
|
+
# By default, this parameter is true.
|
221
|
+
#
|
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)
|
200
242
|
end
|
201
243
|
|
202
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,39 +1,46 @@
|
|
1
|
-
|
2
|
-
|
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"
|
3
7
|
|
4
8
|
class ERB
|
5
9
|
module Util
|
6
|
-
HTML_ESCAPE = {
|
7
|
-
JSON_ESCAPE = {
|
8
|
-
HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+));)/
|
9
|
-
JSON_ESCAPE_REGEXP = /[
|
10
|
+
HTML_ESCAPE = { "&" => "&", ">" => ">", "<" => "<", '"' => """, "'" => "'" }
|
11
|
+
JSON_ESCAPE = { "&" => '\u0026', ">" => '\u003e', "<" => '\u003c', "\u2028" => '\u2028', "\u2029" => '\u2029' }
|
12
|
+
HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+)|(#[xX][\dA-Fa-f]+));)/
|
13
|
+
JSON_ESCAPE_REGEXP = /[\u2028\u2029&><]/u
|
10
14
|
|
11
15
|
# A utility method for escaping HTML tag characters.
|
12
16
|
# This method is also aliased as <tt>h</tt>.
|
13
17
|
#
|
14
|
-
# In your ERB templates, use this method to escape any unsafe content. For example:
|
15
|
-
# <%=h @person.name %>
|
16
|
-
#
|
17
18
|
# puts html_escape('is a > 0 & a < 10?')
|
18
19
|
# # => is a > 0 & a < 10?
|
19
20
|
def html_escape(s)
|
20
|
-
s
|
21
|
-
if s.html_safe?
|
22
|
-
s
|
23
|
-
else
|
24
|
-
s.gsub(/[&"'><]/, HTML_ESCAPE).html_safe
|
25
|
-
end
|
21
|
+
unwrapped_html_escape(s).html_safe
|
26
22
|
end
|
27
23
|
|
28
|
-
|
29
|
-
remove_method(:h)
|
24
|
+
silence_redefinition_of_method :h
|
30
25
|
alias h html_escape
|
31
26
|
|
32
27
|
module_function :h
|
33
28
|
|
34
|
-
singleton_class.
|
29
|
+
singleton_class.silence_redefinition_of_method :html_escape
|
35
30
|
module_function :html_escape
|
36
31
|
|
32
|
+
# HTML escapes strings but doesn't wrap them with an ActiveSupport::SafeBuffer.
|
33
|
+
# This method is not for public consumption! Seriously!
|
34
|
+
def unwrapped_html_escape(s) # :nodoc:
|
35
|
+
s = s.to_s
|
36
|
+
if s.html_safe?
|
37
|
+
s
|
38
|
+
else
|
39
|
+
CGI.escapeHTML(ActiveSupport::Multibyte::Unicode.tidy_bytes(s))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
module_function :unwrapped_html_escape
|
43
|
+
|
37
44
|
# A utility method for escaping HTML without affecting existing escaped entities.
|
38
45
|
#
|
39
46
|
# html_escape_once('1 < 2 & 3')
|
@@ -42,23 +49,67 @@ class ERB
|
|
42
49
|
# html_escape_once('<< Accept & Checkout')
|
43
50
|
# # => "<< Accept & Checkout"
|
44
51
|
def html_escape_once(s)
|
45
|
-
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)
|
46
53
|
s.html_safe? ? result.html_safe : result
|
47
54
|
end
|
48
55
|
|
49
56
|
module_function :html_escape_once
|
50
57
|
|
51
|
-
# A utility method for escaping HTML entities in JSON strings
|
52
|
-
#
|
58
|
+
# A utility method for escaping HTML entities in JSON strings. Specifically, the
|
59
|
+
# &, > and < characters are replaced with their equivalent unicode escaped form -
|
60
|
+
# \u0026, \u003e, and \u003c. The Unicode sequences \u2028 and \u2029 are also
|
61
|
+
# escaped as they are treated as newline characters in some JavaScript engines.
|
62
|
+
# These sequences have identical meaning as the original characters inside the
|
63
|
+
# context of a JSON string, so assuming the input is a valid and well-formed
|
64
|
+
# JSON value, the output will have equivalent meaning when parsed:
|
65
|
+
#
|
66
|
+
# json = JSON.generate({ name: "</script><script>alert('PWNED!!!')</script>"})
|
67
|
+
# # => "{\"name\":\"</script><script>alert('PWNED!!!')</script>\"}"
|
68
|
+
#
|
69
|
+
# json_escape(json)
|
70
|
+
# # => "{\"name\":\"\\u003C/script\\u003E\\u003Cscript\\u003Ealert('PWNED!!!')\\u003C/script\\u003E\"}"
|
71
|
+
#
|
72
|
+
# JSON.parse(json) == JSON.parse(json_escape(json))
|
73
|
+
# # => true
|
74
|
+
#
|
75
|
+
# The intended use case for this method is to escape JSON strings before including
|
76
|
+
# them inside a script tag to avoid XSS vulnerability:
|
53
77
|
#
|
54
|
-
#
|
55
|
-
#
|
78
|
+
# <script>
|
79
|
+
# var currentUser = <%= raw json_escape(current_user.to_json) %>;
|
80
|
+
# </script>
|
56
81
|
#
|
57
|
-
#
|
58
|
-
#
|
82
|
+
# It is necessary to +raw+ the result of +json_escape+, so that quotation marks
|
83
|
+
# don't get converted to <tt>"</tt> entities. +json_escape+ doesn't
|
84
|
+
# automatically flag the result as HTML safe, since the raw value is unsafe to
|
85
|
+
# use inside HTML attributes.
|
59
86
|
#
|
60
|
-
#
|
61
|
-
#
|
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
|
+
#
|
92
|
+
# If you need to output JSON elsewhere in your HTML, you can just do something
|
93
|
+
# like this, as any unsafe characters (including quotation marks) will be
|
94
|
+
# automatically escaped for you:
|
95
|
+
#
|
96
|
+
# <div data-user-info="<%= current_user.to_json %>">...</div>
|
97
|
+
#
|
98
|
+
# WARNING: this helper only works with valid JSON. Using this on non-JSON values
|
99
|
+
# will open up serious XSS vulnerabilities. For example, if you replace the
|
100
|
+
# +current_user.to_json+ in the example above with user input instead, the browser
|
101
|
+
# will happily eval() that string as JavaScript.
|
102
|
+
#
|
103
|
+
# The escaping performed in this method is identical to those performed in the
|
104
|
+
# Active Support JSON encoder when +ActiveSupport.escape_html_entities_in_json+ is
|
105
|
+
# set to true. Because this transformation is idempotent, this helper can be
|
106
|
+
# applied even if +ActiveSupport.escape_html_entities_in_json+ is already true.
|
107
|
+
#
|
108
|
+
# Therefore, when you are unsure if +ActiveSupport.escape_html_entities_in_json+
|
109
|
+
# is enabled, or if you are unsure where your JSON string originated from, it
|
110
|
+
# is recommended that you always apply this helper (other libraries, such as the
|
111
|
+
# JSON gem, do not provide this kind of protection by default; also some gems
|
112
|
+
# might override +to_json+ to bypass Active Support's encoder).
|
62
113
|
def json_escape(s)
|
63
114
|
result = s.to_s.gsub(JSON_ESCAPE_REGEXP, JSON_ESCAPE)
|
64
115
|
s.html_safe? ? result.html_safe : result
|
@@ -84,33 +135,32 @@ module ActiveSupport #:nodoc:
|
|
84
135
|
class SafeBuffer < String
|
85
136
|
UNSAFE_STRING_METHODS = %w(
|
86
137
|
capitalize chomp chop delete downcase gsub lstrip next reverse rstrip
|
87
|
-
slice squeeze strip sub succ swapcase tr tr_s upcase
|
138
|
+
slice squeeze strip sub succ swapcase tr tr_s upcase
|
88
139
|
)
|
89
140
|
|
90
141
|
alias_method :original_concat, :concat
|
91
142
|
private :original_concat
|
92
143
|
|
144
|
+
# Raised when <tt>ActiveSupport::SafeBuffer#safe_concat</tt> is called on unsafe buffers.
|
93
145
|
class SafeConcatError < StandardError
|
94
146
|
def initialize
|
95
|
-
super
|
147
|
+
super "Could not concatenate to the buffer because it is not html safe."
|
96
148
|
end
|
97
149
|
end
|
98
150
|
|
99
151
|
def [](*args)
|
100
152
|
if args.size < 2
|
101
153
|
super
|
102
|
-
|
103
|
-
|
104
|
-
new_safe_buffer = super
|
105
|
-
|
106
|
-
if new_safe_buffer
|
107
|
-
new_safe_buffer.instance_eval { @html_safe = true }
|
108
|
-
end
|
154
|
+
elsif html_safe?
|
155
|
+
new_safe_buffer = super
|
109
156
|
|
110
|
-
|
111
|
-
|
112
|
-
to_str[*args]
|
157
|
+
if new_safe_buffer
|
158
|
+
new_safe_buffer.instance_variable_set :@html_safe, true
|
113
159
|
end
|
160
|
+
|
161
|
+
new_safe_buffer
|
162
|
+
else
|
163
|
+
to_str[*args]
|
114
164
|
end
|
115
165
|
end
|
116
166
|
|
@@ -119,7 +169,7 @@ module ActiveSupport #:nodoc:
|
|
119
169
|
original_concat(value)
|
120
170
|
end
|
121
171
|
|
122
|
-
def initialize(
|
172
|
+
def initialize(str = "")
|
123
173
|
@html_safe = true
|
124
174
|
super
|
125
175
|
end
|
@@ -134,28 +184,27 @@ module ActiveSupport #:nodoc:
|
|
134
184
|
end
|
135
185
|
|
136
186
|
def concat(value)
|
137
|
-
|
138
|
-
super(value)
|
139
|
-
else
|
140
|
-
super(ERB::Util.h(value))
|
141
|
-
end
|
187
|
+
super(html_escape_interpolated_argument(value))
|
142
188
|
end
|
143
189
|
alias << concat
|
144
190
|
|
191
|
+
def prepend(value)
|
192
|
+
super(html_escape_interpolated_argument(value))
|
193
|
+
end
|
194
|
+
|
145
195
|
def +(other)
|
146
196
|
dup.concat(other)
|
147
197
|
end
|
148
198
|
|
149
199
|
def %(args)
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
end
|
200
|
+
case args
|
201
|
+
when Hash
|
202
|
+
escaped_args = Hash[args.map { |k, arg| [k, html_escape_interpolated_argument(arg)] }]
|
203
|
+
else
|
204
|
+
escaped_args = Array(args).map { |arg| html_escape_interpolated_argument(arg) }
|
156
205
|
end
|
157
206
|
|
158
|
-
self.class.new(super(
|
207
|
+
self.class.new(super(escaped_args))
|
159
208
|
end
|
160
209
|
|
161
210
|
def html_safe?
|
@@ -171,11 +220,11 @@ module ActiveSupport #:nodoc:
|
|
171
220
|
end
|
172
221
|
|
173
222
|
def encode_with(coder)
|
174
|
-
coder.
|
223
|
+
coder.represent_object nil, to_str
|
175
224
|
end
|
176
225
|
|
177
226
|
UNSAFE_STRING_METHODS.each do |unsafe_method|
|
178
|
-
if
|
227
|
+
if unsafe_method.respond_to?(unsafe_method)
|
179
228
|
class_eval <<-EOT, __FILE__, __LINE__ + 1
|
180
229
|
def #{unsafe_method}(*args, &block) # def capitalize(*args, &block)
|
181
230
|
to_str.#{unsafe_method}(*args, &block) # to_str.capitalize(*args, &block)
|
@@ -188,10 +237,21 @@ module ActiveSupport #:nodoc:
|
|
188
237
|
EOT
|
189
238
|
end
|
190
239
|
end
|
240
|
+
|
241
|
+
private
|
242
|
+
|
243
|
+
def html_escape_interpolated_argument(arg)
|
244
|
+
(!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
|
245
|
+
end
|
191
246
|
end
|
192
247
|
end
|
193
248
|
|
194
249
|
class String
|
250
|
+
# Marks a string as trusted safe. It will be inserted into HTML with no
|
251
|
+
# additional escaping performed. It is your responsibility to ensure that the
|
252
|
+
# string contains no malicious content. This method is equivalent to the
|
253
|
+
# +raw+ helper in views. It is recommended that you use +sanitize+ instead of
|
254
|
+
# this method. It should never be called on user input.
|
195
255
|
def html_safe
|
196
256
|
ActiveSupport::SafeBuffer.new(self)
|
197
257
|
end
|