activesupport 4.2.0 → 5.0.0.1
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 +4 -4
- data/CHANGELOG.md +630 -220
- data/MIT-LICENSE +2 -2
- data/README.rdoc +2 -3
- data/lib/active_support/array_inquirer.rb +44 -0
- data/lib/active_support/backtrace_cleaner.rb +1 -1
- data/lib/active_support/benchmarkable.rb +1 -1
- data/lib/active_support/cache/file_store.rb +36 -22
- data/lib/active_support/cache/mem_cache_store.rb +63 -54
- data/lib/active_support/cache/memory_store.rb +16 -21
- data/lib/active_support/cache/null_store.rb +1 -4
- data/lib/active_support/cache/strategy/local_cache.rb +31 -20
- data/lib/active_support/cache.rb +73 -89
- data/lib/active_support/callbacks.rb +195 -155
- data/lib/active_support/concern.rb +2 -2
- data/lib/active_support/concurrency/latch.rb +7 -15
- data/lib/active_support/concurrency/share_lock.rb +186 -0
- data/lib/active_support/configurable.rb +1 -0
- data/lib/active_support/core_ext/array/access.rb +27 -1
- data/lib/active_support/core_ext/array/conversions.rb +6 -4
- data/lib/active_support/core_ext/array/grouping.rb +9 -18
- data/lib/active_support/core_ext/array/inquiry.rb +17 -0
- data/lib/active_support/core_ext/array/wrap.rb +5 -4
- data/lib/active_support/core_ext/array.rb +1 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -10
- data/lib/active_support/core_ext/class/attribute.rb +10 -9
- data/lib/active_support/core_ext/class/subclasses.rb +3 -4
- data/lib/active_support/core_ext/class.rb +0 -1
- data/lib/active_support/core_ext/date/blank.rb +12 -0
- data/lib/active_support/core_ext/date/calculations.rb +1 -1
- data/lib/active_support/core_ext/date/conversions.rb +13 -6
- data/lib/active_support/core_ext/date.rb +1 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +109 -25
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +3 -4
- data/lib/active_support/core_ext/date_time/blank.rb +12 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +36 -10
- data/lib/active_support/core_ext/date_time/compatibility.rb +5 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
- data/lib/active_support/core_ext/date_time.rb +2 -1
- data/lib/active_support/core_ext/enumerable.rb +49 -5
- data/lib/active_support/core_ext/file/atomic.rb +30 -25
- data/lib/active_support/core_ext/hash/conversions.rb +23 -4
- data/lib/active_support/core_ext/hash/deep_merge.rb +1 -1
- data/lib/active_support/core_ext/hash/except.rb +9 -8
- data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -1
- data/lib/active_support/core_ext/hash/keys.rb +23 -19
- data/lib/active_support/core_ext/hash/slice.rb +1 -1
- data/lib/active_support/core_ext/hash/transform_values.rb +11 -5
- data/lib/active_support/core_ext/integer/time.rb +1 -16
- data/lib/active_support/core_ext/kernel/concern.rb +2 -0
- data/lib/active_support/core_ext/kernel/debugger.rb +3 -10
- data/lib/active_support/core_ext/kernel/reporting.rb +2 -83
- data/lib/active_support/core_ext/kernel.rb +0 -1
- data/lib/active_support/core_ext/load_error.rb +4 -2
- data/lib/active_support/core_ext/marshal.rb +12 -11
- data/lib/active_support/core_ext/module/aliasing.rb +6 -1
- data/lib/active_support/core_ext/module/anonymous.rb +10 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -5
- data/lib/active_support/core_ext/module/attribute_accessors.rb +15 -15
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
- data/lib/active_support/core_ext/module/concerning.rb +4 -4
- data/lib/active_support/core_ext/module/delegation.rb +35 -25
- data/lib/active_support/core_ext/module/deprecation.rb +2 -2
- data/lib/active_support/core_ext/module/introspection.rb +4 -0
- data/lib/active_support/core_ext/module/method_transplanting.rb +3 -11
- data/lib/active_support/core_ext/module/qualified_const.rb +30 -12
- data/lib/active_support/core_ext/module/remove_method.rb +23 -0
- data/lib/active_support/core_ext/module.rb +1 -0
- data/lib/active_support/core_ext/name_error.rb +15 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +20 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +74 -64
- data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
- data/lib/active_support/core_ext/numeric/time.rb +24 -19
- data/lib/active_support/core_ext/numeric.rb +1 -0
- data/lib/active_support/core_ext/object/blank.rb +17 -5
- data/lib/active_support/core_ext/object/deep_dup.rb +10 -3
- data/lib/active_support/core_ext/object/duplicable.rb +8 -13
- data/lib/active_support/core_ext/object/inclusion.rb +2 -2
- data/lib/active_support/core_ext/object/instance_variables.rb +1 -1
- data/lib/active_support/core_ext/object/json.rb +15 -7
- data/lib/active_support/core_ext/object/to_query.rb +1 -1
- data/lib/active_support/core_ext/object/try.rb +68 -22
- data/lib/active_support/core_ext/object/with_options.rb +1 -1
- data/lib/active_support/core_ext/object.rb +0 -1
- data/lib/active_support/core_ext/range/conversions.rb +18 -6
- data/lib/active_support/core_ext/range/each.rb +16 -18
- data/lib/active_support/core_ext/range/include_range.rb +20 -20
- data/lib/active_support/core_ext/securerandom.rb +23 -0
- data/lib/active_support/core_ext/string/access.rb +1 -1
- data/lib/active_support/core_ext/string/behavior.rb +1 -1
- data/lib/active_support/core_ext/string/conversions.rb +4 -3
- data/lib/active_support/core_ext/string/filters.rb +5 -5
- data/lib/active_support/core_ext/string/inflections.rb +32 -5
- data/lib/active_support/core_ext/string/multibyte.rb +11 -7
- data/lib/active_support/core_ext/string/output_safety.rb +18 -16
- data/lib/active_support/core_ext/string/strip.rb +3 -6
- data/lib/active_support/core_ext/struct.rb +3 -6
- data/lib/active_support/core_ext/time/calculations.rb +36 -11
- data/lib/active_support/core_ext/time/compatibility.rb +5 -0
- data/lib/active_support/core_ext/time/conversions.rb +4 -2
- data/lib/active_support/core_ext/time/marshal.rb +2 -29
- data/lib/active_support/core_ext/time/zones.rb +36 -4
- data/lib/active_support/core_ext/time.rb +1 -1
- data/lib/active_support/core_ext/uri.rb +1 -3
- data/lib/active_support/core_ext.rb +2 -1
- data/lib/active_support/dependencies/interlock.rb +51 -0
- data/lib/active_support/dependencies.rb +87 -95
- data/lib/active_support/deprecation/behaviors.rb +16 -2
- data/lib/active_support/deprecation/method_wrappers.rb +42 -16
- data/lib/active_support/deprecation/proxy_wrappers.rb +47 -24
- data/lib/active_support/deprecation/reporting.rb +23 -5
- data/lib/active_support/deprecation.rb +1 -1
- data/lib/active_support/duration/iso8601_parser.rb +122 -0
- data/lib/active_support/duration/iso8601_serializer.rb +51 -0
- data/lib/active_support/duration.rb +55 -10
- data/lib/active_support/evented_file_update_checker.rb +194 -0
- data/lib/active_support/execution_wrapper.rb +117 -0
- data/lib/active_support/executor.rb +6 -0
- data/lib/active_support/file_update_checker.rb +23 -3
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/hash_with_indifferent_access.rb +46 -13
- data/lib/active_support/i18n_railtie.rb +25 -4
- data/lib/active_support/inflector/inflections.rb +36 -5
- data/lib/active_support/inflector/methods.rb +97 -90
- data/lib/active_support/inflector/transliterate.rb +36 -21
- data/lib/active_support/json/decoding.rb +11 -10
- data/lib/active_support/json/encoding.rb +4 -49
- data/lib/active_support/key_generator.rb +7 -9
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber/test_helper.rb +3 -3
- data/lib/active_support/log_subscriber.rb +1 -1
- data/lib/active_support/logger.rb +50 -1
- data/lib/active_support/logger_silence.rb +8 -4
- data/lib/active_support/logger_thread_safe_level.rb +31 -0
- data/lib/active_support/message_encryptor.rb +4 -4
- data/lib/active_support/message_verifier.rb +70 -8
- data/lib/active_support/multibyte/chars.rb +13 -4
- data/lib/active_support/multibyte/unicode.rb +44 -21
- data/lib/active_support/notifications/fanout.rb +6 -6
- data/lib/active_support/notifications/instrumenter.rb +20 -2
- data/lib/active_support/notifications.rb +2 -2
- data/lib/active_support/number_helper/number_to_currency_converter.rb +7 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +8 -3
- data/lib/active_support/number_helper/number_to_human_converter.rb +6 -4
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -2
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +11 -2
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +30 -25
- data/lib/active_support/number_helper.rb +90 -67
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +15 -1
- data/lib/active_support/per_thread_registry.rb +8 -3
- data/lib/active_support/rails.rb +2 -2
- data/lib/active_support/railtie.rb +6 -1
- data/lib/active_support/reloader.rb +129 -0
- data/lib/active_support/rescuable.rb +93 -47
- data/lib/active_support/security_utils.rb +7 -0
- data/lib/active_support/string_inquirer.rb +1 -1
- data/lib/active_support/subscriber.rb +5 -10
- data/lib/active_support/tagged_logging.rb +3 -1
- data/lib/active_support/test_case.rb +15 -29
- data/lib/active_support/testing/assertions.rb +15 -13
- data/lib/active_support/testing/autorun.rb +8 -1
- data/lib/active_support/testing/deprecation.rb +9 -8
- data/lib/active_support/testing/file_fixtures.rb +34 -0
- data/lib/active_support/testing/isolation.rb +22 -8
- data/lib/active_support/testing/method_call_assertions.rb +41 -0
- data/lib/active_support/testing/stream.rb +42 -0
- data/lib/active_support/testing/time_helpers.rb +13 -10
- data/lib/active_support/time_with_zone.rb +135 -46
- data/lib/active_support/values/time_zone.rb +95 -47
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/xml_mini/jdom.rb +7 -6
- data/lib/active_support/xml_mini/libxml.rb +2 -2
- data/lib/active_support/xml_mini/nokogiri.rb +2 -2
- data/lib/active_support/xml_mini/rexml.rb +7 -8
- data/lib/active_support/xml_mini.rb +22 -14
- data/lib/active_support.rb +20 -6
- metadata +33 -35
- 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/object/itself.rb +0 -15
- data/lib/active_support/core_ext/thread.rb +0 -86
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'active_support/duration'
|
2
2
|
require 'active_support/core_ext/time/calculations'
|
3
3
|
require 'active_support/core_ext/time/acts_like'
|
4
|
+
require 'active_support/core_ext/date/calculations'
|
5
|
+
require 'active_support/core_ext/date/acts_like'
|
4
6
|
|
5
7
|
class Numeric
|
6
8
|
# Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years.
|
@@ -16,53 +18,56 @@ class Numeric
|
|
16
18
|
#
|
17
19
|
# # equivalent to Time.current.advance(months: 4, years: 5)
|
18
20
|
# (4.months + 5.years).from_now
|
19
|
-
#
|
20
|
-
# While these methods provide precise calculation when used as in the examples above, care
|
21
|
-
# should be taken to note that this is not true if the result of `months', `years', etc is
|
22
|
-
# converted before use:
|
23
|
-
#
|
24
|
-
# # equivalent to 30.days.to_i.from_now
|
25
|
-
# 1.month.to_i.from_now
|
26
|
-
#
|
27
|
-
# # equivalent to 365.25.days.to_f.from_now
|
28
|
-
# 1.year.to_f.from_now
|
29
|
-
#
|
30
|
-
# In such cases, Ruby's core
|
31
|
-
# Date[http://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html] and
|
32
|
-
# Time[http://ruby-doc.org/stdlib/libdoc/time/rdoc/Time.html] should be used for precision
|
33
|
-
# date and time arithmetic.
|
34
21
|
def seconds
|
35
22
|
ActiveSupport::Duration.new(self, [[:seconds, self]])
|
36
23
|
end
|
37
24
|
alias :second :seconds
|
38
25
|
|
26
|
+
# Returns a Duration instance matching the number of minutes provided.
|
27
|
+
#
|
28
|
+
# 2.minutes # => 2 minutes
|
39
29
|
def minutes
|
40
|
-
ActiveSupport::Duration.new(self * 60, [[:
|
30
|
+
ActiveSupport::Duration.new(self * 60, [[:minutes, self]])
|
41
31
|
end
|
42
32
|
alias :minute :minutes
|
43
33
|
|
34
|
+
# Returns a Duration instance matching the number of hours provided.
|
35
|
+
#
|
36
|
+
# 2.hours # => 2 hours
|
44
37
|
def hours
|
45
|
-
ActiveSupport::Duration.new(self * 3600, [[:
|
38
|
+
ActiveSupport::Duration.new(self * 3600, [[:hours, self]])
|
46
39
|
end
|
47
40
|
alias :hour :hours
|
48
41
|
|
42
|
+
# Returns a Duration instance matching the number of days provided.
|
43
|
+
#
|
44
|
+
# 2.days # => 2 days
|
49
45
|
def days
|
50
46
|
ActiveSupport::Duration.new(self * 24.hours, [[:days, self]])
|
51
47
|
end
|
52
48
|
alias :day :days
|
53
49
|
|
50
|
+
# Returns a Duration instance matching the number of weeks provided.
|
51
|
+
#
|
52
|
+
# 2.weeks # => 2 weeks
|
54
53
|
def weeks
|
55
|
-
ActiveSupport::Duration.new(self * 7.days, [[:
|
54
|
+
ActiveSupport::Duration.new(self * 7.days, [[:weeks, self]])
|
56
55
|
end
|
57
56
|
alias :week :weeks
|
58
57
|
|
58
|
+
# Returns a Duration instance matching the number of fortnights provided.
|
59
|
+
#
|
60
|
+
# 2.fortnights # => 4 weeks
|
59
61
|
def fortnights
|
60
|
-
ActiveSupport::Duration.new(self * 2.weeks, [[:
|
62
|
+
ActiveSupport::Duration.new(self * 2.weeks, [[:weeks, self * 2]])
|
61
63
|
end
|
62
64
|
alias :fortnight :fortnights
|
63
65
|
|
66
|
+
# Returns the number of milliseconds equivalent to the seconds provided.
|
64
67
|
# Used with the standard time durations, like 1.hour.in_milliseconds --
|
65
68
|
# so we can feed them to JavaScript functions like getTime().
|
69
|
+
#
|
70
|
+
# 2.in_milliseconds # => 2_000
|
66
71
|
def in_milliseconds
|
67
72
|
self * 1000
|
68
73
|
end
|
@@ -1,12 +1,10 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
class Object
|
4
2
|
# An object is blank if it's false, empty, or a whitespace string.
|
5
|
-
# For example, '', ' ', +nil+, [], and {} are all blank.
|
3
|
+
# For example, +false+, '', ' ', +nil+, [], and {} are all blank.
|
6
4
|
#
|
7
5
|
# This simplifies
|
8
6
|
#
|
9
|
-
# address
|
7
|
+
# !address || address.empty?
|
10
8
|
#
|
11
9
|
# to
|
12
10
|
#
|
@@ -114,7 +112,10 @@ class String
|
|
114
112
|
#
|
115
113
|
# @return [true, false]
|
116
114
|
def blank?
|
117
|
-
|
115
|
+
# The regexp that matches blank strings is expensive. For the case of empty
|
116
|
+
# strings we can speed up this method (~3.5x) with an empty? call. The
|
117
|
+
# penalty for the rest of strings is marginal.
|
118
|
+
empty? || BLANK_RE === self
|
118
119
|
end
|
119
120
|
end
|
120
121
|
|
@@ -129,3 +130,14 @@ class Numeric #:nodoc:
|
|
129
130
|
false
|
130
131
|
end
|
131
132
|
end
|
133
|
+
|
134
|
+
class Time #:nodoc:
|
135
|
+
# No Time is blank:
|
136
|
+
#
|
137
|
+
# Time.now.blank? # => false
|
138
|
+
#
|
139
|
+
# @return [false]
|
140
|
+
def blank?
|
141
|
+
false
|
142
|
+
end
|
143
|
+
end
|
@@ -25,7 +25,7 @@ class Array
|
|
25
25
|
# array[1][2] # => nil
|
26
26
|
# dup[1][2] # => 4
|
27
27
|
def deep_dup
|
28
|
-
map
|
28
|
+
map(&:deep_dup)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -39,8 +39,15 @@ class Hash
|
|
39
39
|
# hash[:a][:c] # => nil
|
40
40
|
# dup[:a][:c] # => "c"
|
41
41
|
def deep_dup
|
42
|
-
|
43
|
-
|
42
|
+
hash = dup
|
43
|
+
each_pair do |key, value|
|
44
|
+
if key.frozen? && ::String === key
|
45
|
+
hash[key] = value.deep_dup
|
46
|
+
else
|
47
|
+
hash.delete(key)
|
48
|
+
hash[key.deep_dup] = value.deep_dup
|
49
|
+
end
|
44
50
|
end
|
51
|
+
hash
|
45
52
|
end
|
46
53
|
end
|
@@ -19,7 +19,7 @@
|
|
19
19
|
class Object
|
20
20
|
# Can you safely dup this object?
|
21
21
|
#
|
22
|
-
# False for +nil+, +false+, +true+, symbol, number
|
22
|
+
# False for +nil+, +false+, +true+, symbol, number, method objects;
|
23
23
|
# true otherwise.
|
24
24
|
def duplicable?
|
25
25
|
true
|
@@ -70,7 +70,7 @@ class Numeric
|
|
70
70
|
# Numbers are not duplicable:
|
71
71
|
#
|
72
72
|
# 3.duplicable? # => false
|
73
|
-
# 3.dup # => TypeError: can't dup
|
73
|
+
# 3.dup # => TypeError: can't dup Integer
|
74
74
|
def duplicable?
|
75
75
|
false
|
76
76
|
end
|
@@ -78,17 +78,12 @@ end
|
|
78
78
|
|
79
79
|
require 'bigdecimal'
|
80
80
|
class BigDecimal
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
def duplicable?
|
88
|
-
true
|
89
|
-
end
|
90
|
-
rescue TypeError
|
91
|
-
# can't dup, so use superclass implementation
|
81
|
+
# BigDecimals are duplicable:
|
82
|
+
#
|
83
|
+
# BigDecimal.new("1.2").duplicable? # => true
|
84
|
+
# BigDecimal.new("1.2").dup # => #<BigDecimal:...,'0.12E1',18(18)>
|
85
|
+
def duplicable?
|
86
|
+
true
|
92
87
|
end
|
93
88
|
end
|
94
89
|
|
@@ -5,7 +5,7 @@ class Object
|
|
5
5
|
# characters = ["Konata", "Kagami", "Tsukasa"]
|
6
6
|
# "Konata".in?(characters) # => true
|
7
7
|
#
|
8
|
-
# This will throw an ArgumentError if the argument doesn't respond
|
8
|
+
# This will throw an +ArgumentError+ if the argument doesn't respond
|
9
9
|
# to +#include?+.
|
10
10
|
def in?(another_object)
|
11
11
|
another_object.include?(self)
|
@@ -18,7 +18,7 @@ class Object
|
|
18
18
|
#
|
19
19
|
# params[:bucket_type].presence_in %w( project calendar )
|
20
20
|
#
|
21
|
-
# This will throw an ArgumentError if the argument doesn't respond to +#include?+.
|
21
|
+
# This will throw an +ArgumentError+ if the argument doesn't respond to +#include?+.
|
22
22
|
#
|
23
23
|
# @return [Object]
|
24
24
|
def presence_in(another_object)
|
@@ -9,7 +9,6 @@ require 'time'
|
|
9
9
|
require 'active_support/core_ext/time/conversions'
|
10
10
|
require 'active_support/core_ext/date_time/conversions'
|
11
11
|
require 'active_support/core_ext/date/conversions'
|
12
|
-
require 'active_support/core_ext/module/aliasing'
|
13
12
|
|
14
13
|
# The JSON gem adds a few modules to Ruby core classes containing :to_json definition, overwriting
|
15
14
|
# their default behavior. That said, we need to define the basic to_json method in all of them,
|
@@ -26,22 +25,25 @@ require 'active_support/core_ext/module/aliasing'
|
|
26
25
|
# bypassed completely. This means that as_json won't be invoked and the JSON gem will simply
|
27
26
|
# ignore any options it does not natively understand. This also means that ::JSON.{generate,dump}
|
28
27
|
# should give exactly the same results with or without active support.
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
|
29
|
+
module ActiveSupport
|
30
|
+
module ToJsonWithActiveSupportEncoder # :nodoc:
|
31
|
+
def to_json(options = nil)
|
32
32
|
if options.is_a?(::JSON::State)
|
33
33
|
# Called from JSON.{generate,dump}, forward it to JSON gem's to_json
|
34
|
-
|
34
|
+
super(options)
|
35
35
|
else
|
36
36
|
# to_json is being invoked directly, use ActiveSupport's encoder
|
37
37
|
ActiveSupport::JSON.encode(self, options)
|
38
38
|
end
|
39
39
|
end
|
40
|
-
|
41
|
-
alias_method_chain :to_json, :active_support_encoder
|
42
40
|
end
|
43
41
|
end
|
44
42
|
|
43
|
+
[Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass, Enumerable].reverse_each do |klass|
|
44
|
+
klass.prepend(ActiveSupport::ToJsonWithActiveSupportEncoder)
|
45
|
+
end
|
46
|
+
|
45
47
|
class Object
|
46
48
|
def as_json(options = nil) #:nodoc:
|
47
49
|
if respond_to?(:to_hash)
|
@@ -195,3 +197,9 @@ class Process::Status #:nodoc:
|
|
195
197
|
{ :exitstatus => exitstatus, :pid => pid }
|
196
198
|
end
|
197
199
|
end
|
200
|
+
|
201
|
+
class Exception
|
202
|
+
def as_json(options = nil)
|
203
|
+
to_s
|
204
|
+
end
|
205
|
+
end
|
@@ -38,7 +38,7 @@ class Array
|
|
38
38
|
# Calls <tt>to_param</tt> on all its elements and joins the result with
|
39
39
|
# slashes. This is used by <tt>url_for</tt> in Action Pack.
|
40
40
|
def to_param
|
41
|
-
collect
|
41
|
+
collect(&:to_param).join '/'
|
42
42
|
end
|
43
43
|
|
44
44
|
# Converts an array into a string suitable for use as a URL query string,
|
@@ -1,4 +1,34 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module Tryable #:nodoc:
|
5
|
+
def try(*a, &b)
|
6
|
+
try!(*a, &b) if a.empty? || respond_to?(a.first)
|
7
|
+
end
|
8
|
+
|
9
|
+
def try!(*a, &b)
|
10
|
+
if a.empty? && block_given?
|
11
|
+
if b.arity == 0
|
12
|
+
instance_eval(&b)
|
13
|
+
else
|
14
|
+
yield self
|
15
|
+
end
|
16
|
+
else
|
17
|
+
public_send(*a, &b)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
1
23
|
class Object
|
24
|
+
include ActiveSupport::Tryable
|
25
|
+
|
26
|
+
##
|
27
|
+
# :method: try
|
28
|
+
#
|
29
|
+
# :call-seq:
|
30
|
+
# try(*a, &b)
|
31
|
+
#
|
2
32
|
# Invokes the public method whose name goes as first argument just like
|
3
33
|
# +public_send+ does, except that if the receiver does not respond to it the
|
4
34
|
# call returns +nil+ rather than raising an exception.
|
@@ -21,11 +51,11 @@ class Object
|
|
21
51
|
#
|
22
52
|
# +try+ will also return +nil+ if the receiver does not respond to the method:
|
23
53
|
#
|
24
|
-
# @person.try(:non_existing_method)
|
54
|
+
# @person.try(:non_existing_method) # => nil
|
25
55
|
#
|
26
56
|
# instead of
|
27
57
|
#
|
28
|
-
# @person.non_existing_method if @person.respond_to?(:non_existing_method)
|
58
|
+
# @person.non_existing_method if @person.respond_to?(:non_existing_method) # => nil
|
29
59
|
#
|
30
60
|
# +try+ returns +nil+ when called on +nil+ regardless of whether it responds
|
31
61
|
# to the method:
|
@@ -56,27 +86,40 @@ class Object
|
|
56
86
|
#
|
57
87
|
# Please also note that +try+ is defined on +Object+. Therefore, it won't work
|
58
88
|
# with instances of classes that do not have +Object+ among their ancestors,
|
59
|
-
# like direct subclasses of +BasicObject+.
|
60
|
-
# +SimpleDelegator+ will delegate +try+ to the target instead of calling it on
|
61
|
-
# the delegator itself.
|
62
|
-
def try(*a, &b)
|
63
|
-
try!(*a, &b) if a.empty? || respond_to?(a.first)
|
64
|
-
end
|
89
|
+
# like direct subclasses of +BasicObject+.
|
65
90
|
|
66
|
-
|
67
|
-
#
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
91
|
+
##
|
92
|
+
# :method: try!
|
93
|
+
#
|
94
|
+
# :call-seq:
|
95
|
+
# try!(*a, &b)
|
96
|
+
#
|
97
|
+
# Same as #try, but raises a +NoMethodError+ exception if the receiver is
|
98
|
+
# not +nil+ and does not implement the tried method.
|
99
|
+
#
|
100
|
+
# "a".try!(:upcase) # => "A"
|
101
|
+
# nil.try!(:upcase) # => nil
|
102
|
+
# 123.try!(:upcase) # => NoMethodError: undefined method `upcase' for 123:Integer
|
103
|
+
end
|
104
|
+
|
105
|
+
class Delegator
|
106
|
+
include ActiveSupport::Tryable
|
107
|
+
|
108
|
+
##
|
109
|
+
# :method: try
|
110
|
+
#
|
111
|
+
# :call-seq:
|
112
|
+
# try(a*, &b)
|
113
|
+
#
|
114
|
+
# See Object#try
|
115
|
+
|
116
|
+
##
|
117
|
+
# :method: try!
|
118
|
+
#
|
119
|
+
# :call-seq:
|
120
|
+
# try!(a*, &b)
|
121
|
+
#
|
122
|
+
# See Object#try!
|
80
123
|
end
|
81
124
|
|
82
125
|
class NilClass
|
@@ -94,6 +137,9 @@ class NilClass
|
|
94
137
|
nil
|
95
138
|
end
|
96
139
|
|
140
|
+
# Calling +try!+ on +nil+ always returns +nil+.
|
141
|
+
#
|
142
|
+
# nil.try!(:name) # => nil
|
97
143
|
def try!(*args)
|
98
144
|
nil
|
99
145
|
end
|
@@ -7,7 +7,7 @@ class Object
|
|
7
7
|
# provided. Each method called on the block variable must take an options
|
8
8
|
# hash as its final argument.
|
9
9
|
#
|
10
|
-
# Without <tt>with_options
|
10
|
+
# Without <tt>with_options</tt>, this code contains duplication:
|
11
11
|
#
|
12
12
|
# class Account < ActiveRecord::Base
|
13
13
|
# has_many :customers, dependent: :destroy
|
@@ -2,7 +2,6 @@ require 'active_support/core_ext/object/acts_like'
|
|
2
2
|
require 'active_support/core_ext/object/blank'
|
3
3
|
require 'active_support/core_ext/object/duplicable'
|
4
4
|
require 'active_support/core_ext/object/deep_dup'
|
5
|
-
require 'active_support/core_ext/object/itself'
|
6
5
|
require 'active_support/core_ext/object/try'
|
7
6
|
require 'active_support/core_ext/object/inclusion'
|
8
7
|
|
@@ -1,19 +1,31 @@
|
|
1
|
-
|
1
|
+
module ActiveSupport::RangeWithFormat
|
2
2
|
RANGE_FORMATS = {
|
3
3
|
:db => Proc.new { |start, stop| "BETWEEN '#{start.to_s(:db)}' AND '#{stop.to_s(:db)}'" }
|
4
4
|
}
|
5
5
|
|
6
|
-
#
|
6
|
+
# Convert range to a formatted string. See RANGE_FORMATS for predefined formats.
|
7
7
|
#
|
8
|
-
# (1..100)
|
9
|
-
|
8
|
+
# range = (1..100) # => 1..100
|
9
|
+
#
|
10
|
+
# range.to_s # => "1..100"
|
11
|
+
# range.to_s(:db) # => "BETWEEN '1' AND '100'"
|
12
|
+
#
|
13
|
+
# == Adding your own range formats to to_s
|
14
|
+
# You can add your own formats to the Range::RANGE_FORMATS hash.
|
15
|
+
# Use the format name as the hash key and a Proc instance.
|
16
|
+
#
|
17
|
+
# # config/initializers/range_formats.rb
|
18
|
+
# Range::RANGE_FORMATS[:short] = ->(start, stop) { "Between #{start.to_s(:db)} and #{stop.to_s(:db)}" }
|
19
|
+
def to_s(format = :default)
|
10
20
|
if formatter = RANGE_FORMATS[format]
|
11
21
|
formatter.call(first, last)
|
12
22
|
else
|
13
|
-
|
23
|
+
super()
|
14
24
|
end
|
15
25
|
end
|
16
26
|
|
17
27
|
alias_method :to_default_s, :to_s
|
18
|
-
alias_method :
|
28
|
+
alias_method :to_formatted_s, :to_s
|
19
29
|
end
|
30
|
+
|
31
|
+
Range.prepend(ActiveSupport::RangeWithFormat)
|
@@ -1,23 +1,21 @@
|
|
1
|
-
|
1
|
+
module ActiveSupport
|
2
|
+
module EachTimeWithZone #:nodoc:
|
3
|
+
def each(&block)
|
4
|
+
ensure_iteration_allowed
|
5
|
+
super
|
6
|
+
end
|
2
7
|
|
3
|
-
|
8
|
+
def step(n = 1, &block)
|
9
|
+
ensure_iteration_allowed
|
10
|
+
super
|
11
|
+
end
|
4
12
|
|
5
|
-
|
6
|
-
ensure_iteration_allowed
|
7
|
-
each_without_time_with_zone(&block)
|
8
|
-
end
|
9
|
-
alias_method_chain :each, :time_with_zone
|
13
|
+
private
|
10
14
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
15
|
-
alias_method_chain :step, :time_with_zone
|
16
|
-
|
17
|
-
private
|
18
|
-
def ensure_iteration_allowed
|
19
|
-
if first.is_a?(Time)
|
20
|
-
raise TypeError, "can't iterate from #{first.class}"
|
21
|
-
end
|
15
|
+
def ensure_iteration_allowed
|
16
|
+
raise TypeError, "can't iterate from #{first.class}" if first.is_a?(Time)
|
17
|
+
end
|
22
18
|
end
|
23
19
|
end
|
20
|
+
|
21
|
+
Range.prepend(ActiveSupport::EachTimeWithZone)
|
@@ -1,23 +1,23 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
1
|
+
module ActiveSupport
|
2
|
+
module IncludeWithRange #:nodoc:
|
3
|
+
# Extends the default Range#include? to support range comparisons.
|
4
|
+
# (1..5).include?(1..5) # => true
|
5
|
+
# (1..5).include?(2..3) # => true
|
6
|
+
# (1..5).include?(2..6) # => false
|
7
|
+
#
|
8
|
+
# The native Range#include? behavior is untouched.
|
9
|
+
# ('a'..'f').include?('c') # => true
|
10
|
+
# (5..9).include?(11) # => false
|
11
|
+
def include?(value)
|
12
|
+
if value.is_a?(::Range)
|
13
|
+
# 1...10 includes 1..9 but it does not include 1..10.
|
14
|
+
operator = exclude_end? && !value.exclude_end? ? :< : :<=
|
15
|
+
super(value.first) && value.last.send(operator, last)
|
16
|
+
else
|
17
|
+
super
|
18
|
+
end
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
22
|
-
alias_method_chain :include?, :range
|
23
21
|
end
|
22
|
+
|
23
|
+
Range.prepend(ActiveSupport::IncludeWithRange)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
module SecureRandom
|
4
|
+
BASE58_ALPHABET = ('0'..'9').to_a + ('A'..'Z').to_a + ('a'..'z').to_a - ['0', 'O', 'I', 'l']
|
5
|
+
# SecureRandom.base58 generates a random base58 string.
|
6
|
+
#
|
7
|
+
# The argument _n_ specifies the length, of the random string to be generated.
|
8
|
+
#
|
9
|
+
# If _n_ is not specified or is nil, 16 is assumed. It may be larger in the future.
|
10
|
+
#
|
11
|
+
# The result may contain alphanumeric characters except 0, O, I and l
|
12
|
+
#
|
13
|
+
# p SecureRandom.base58 # => "4kUgL2pdQMSCQtjE"
|
14
|
+
# p SecureRandom.base58(24) # => "77TMHrHJFvFDwodq8w7Ev2m7"
|
15
|
+
#
|
16
|
+
def self.base58(n = 16)
|
17
|
+
SecureRandom.random_bytes(n).unpack("C*").map do |byte|
|
18
|
+
idx = byte % 64
|
19
|
+
idx = SecureRandom.random_number(58) if idx >= 58
|
20
|
+
BASE58_ALPHABET[idx]
|
21
|
+
end.join
|
22
|
+
end
|
23
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class String
|
2
|
-
# If you pass a single
|
2
|
+
# If you pass a single integer, returns a substring of one character at that
|
3
3
|
# position. The first character of the string is at position 0, the next at
|
4
4
|
# position 1, and so on. If a range is supplied, a substring containing
|
5
5
|
# characters at offsets given by the range is returned. In both cases, if an
|
@@ -14,11 +14,12 @@ class String
|
|
14
14
|
# "06:12".to_time # => 2012-12-13 06:12:00 +0100
|
15
15
|
# "2012-12-13 06:12".to_time # => 2012-12-13 06:12:00 +0100
|
16
16
|
# "2012-12-13T06:12".to_time # => 2012-12-13 06:12:00 +0100
|
17
|
-
# "2012-12-13T06:12".to_time(:utc) # => 2012-12-13
|
17
|
+
# "2012-12-13T06:12".to_time(:utc) # => 2012-12-13 06:12:00 UTC
|
18
18
|
# "12/13/2012".to_time # => ArgumentError: argument out of range
|
19
19
|
def to_time(form = :local)
|
20
20
|
parts = Date._parse(self, false)
|
21
|
-
|
21
|
+
used_keys = %i(year mon mday hour min sec sec_fraction offset)
|
22
|
+
return if (parts.keys & used_keys).empty?
|
22
23
|
|
23
24
|
now = Time.now
|
24
25
|
time = Time.new(
|
@@ -31,7 +32,7 @@ class String
|
|
31
32
|
parts.fetch(:offset, form == :utc ? 0 : nil)
|
32
33
|
)
|
33
34
|
|
34
|
-
form == :utc ? time.utc : time.
|
35
|
+
form == :utc ? time.utc : time.to_time
|
35
36
|
end
|
36
37
|
|
37
38
|
# Converts a string to a Date value.
|
@@ -17,15 +17,15 @@ class String
|
|
17
17
|
# str.squish! # => "foo bar boo"
|
18
18
|
# str # => "foo bar boo"
|
19
19
|
def squish!
|
20
|
-
gsub!(/\A[[:space:]]+/, '')
|
21
|
-
gsub!(/[[:space:]]+\z/, '')
|
22
20
|
gsub!(/[[:space:]]+/, ' ')
|
21
|
+
strip!
|
23
22
|
self
|
24
23
|
end
|
25
24
|
|
26
25
|
# Returns a new string with all occurrences of the patterns removed.
|
27
26
|
# str = "foo bar test"
|
28
27
|
# str.remove(" test") # => "foo bar"
|
28
|
+
# str.remove(" test", /bar/) # => "foo "
|
29
29
|
# str # => "foo bar test"
|
30
30
|
def remove(*patterns)
|
31
31
|
dup.remove!(*patterns)
|
@@ -33,8 +33,8 @@ class String
|
|
33
33
|
|
34
34
|
# Alters the string by removing all occurrences of the patterns.
|
35
35
|
# str = "foo bar test"
|
36
|
-
# str.remove!(" test")
|
37
|
-
# str
|
36
|
+
# str.remove!(" test", /bar/) # => "foo "
|
37
|
+
# str # => "foo "
|
38
38
|
def remove!(*patterns)
|
39
39
|
patterns.each do |pattern|
|
40
40
|
gsub! pattern, ""
|
@@ -93,7 +93,7 @@ class String
|
|
93
93
|
def truncate_words(words_count, options = {})
|
94
94
|
sep = options[:separator] || /\s+/
|
95
95
|
sep = Regexp.escape(sep.to_s) unless Regexp === sep
|
96
|
-
if self =~ /\A((
|
96
|
+
if self =~ /\A((?>.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/m
|
97
97
|
$1 + (options[:omission] || '...')
|
98
98
|
else
|
99
99
|
dup
|