activesupport 4.0.13 → 4.2.11.3
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 +406 -418
- data/MIT-LICENSE +1 -1
- data/README.rdoc +7 -2
- data/lib/active_support/backtrace_cleaner.rb +8 -8
- data/lib/active_support/benchmarkable.rb +0 -10
- data/lib/active_support/cache/file_store.rb +32 -22
- data/lib/active_support/cache/mem_cache_store.rb +5 -7
- data/lib/active_support/cache/memory_store.rb +1 -0
- data/lib/active_support/cache/strategy/local_cache.rb +11 -30
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +44 -0
- data/lib/active_support/cache.rb +75 -41
- data/lib/active_support/callbacks.rb +482 -261
- data/lib/active_support/concern.rb +23 -7
- data/lib/active_support/configurable.rb +1 -1
- data/lib/active_support/core_ext/array/access.rb +11 -1
- data/lib/active_support/core_ext/array/conversions.rb +2 -17
- data/lib/active_support/core_ext/array/grouping.rb +29 -12
- data/lib/active_support/core_ext/array/prepend_and_append.rb +2 -2
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +0 -15
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +16 -0
- data/lib/active_support/core_ext/class/attribute.rb +1 -2
- data/lib/active_support/core_ext/class/attribute_accessors.rb +4 -170
- data/lib/active_support/core_ext/class/delegating_attributes.rb +13 -8
- data/lib/active_support/core_ext/class/subclasses.rb +0 -2
- data/lib/active_support/core_ext/class.rb +0 -1
- data/lib/active_support/core_ext/date/calculations.rb +10 -0
- data/lib/active_support/core_ext/date/conversions.rb +9 -1
- data/lib/active_support/core_ext/date/zones.rb +2 -33
- data/lib/active_support/core_ext/date_and_time/calculations.rb +41 -11
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +41 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +45 -22
- data/lib/active_support/core_ext/date_time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +4 -2
- data/lib/active_support/core_ext/date_time/zones.rb +3 -21
- data/lib/active_support/core_ext/date_time.rb +1 -0
- data/lib/active_support/core_ext/digest/uuid.rb +51 -0
- data/lib/active_support/core_ext/enumerable.rb +17 -1
- data/lib/active_support/core_ext/file/atomic.rb +1 -1
- data/lib/active_support/core_ext/hash/compact.rb +24 -0
- data/lib/active_support/core_ext/hash/conversions.rb +9 -8
- data/lib/active_support/core_ext/hash/except.rb +8 -2
- data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -0
- data/lib/active_support/core_ext/hash/keys.rb +25 -19
- data/lib/active_support/core_ext/hash/slice.rb +8 -2
- data/lib/active_support/core_ext/hash/transform_values.rb +23 -0
- data/lib/active_support/core_ext/hash.rb +2 -1
- data/lib/active_support/core_ext/integer/time.rb +0 -15
- data/lib/active_support/core_ext/kernel/concern.rb +10 -0
- data/lib/active_support/core_ext/kernel/debugger.rb +1 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +13 -2
- data/lib/active_support/core_ext/kernel.rb +3 -2
- data/lib/active_support/core_ext/load_error.rb +4 -1
- data/lib/active_support/core_ext/marshal.rb +8 -5
- data/lib/active_support/core_ext/module/aliasing.rb +2 -2
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +160 -14
- data/lib/active_support/core_ext/module/concerning.rb +135 -0
- data/lib/active_support/core_ext/module/delegation.rb +53 -25
- data/lib/active_support/core_ext/module/deprecation.rb +0 -2
- data/lib/active_support/core_ext/module/introspection.rb +0 -16
- data/lib/active_support/core_ext/module/method_transplanting.rb +13 -0
- data/lib/active_support/core_ext/module.rb +1 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +11 -3
- data/lib/active_support/core_ext/numeric/time.rb +4 -29
- data/lib/active_support/core_ext/object/blank.rb +44 -18
- data/lib/active_support/core_ext/object/deep_dup.rb +6 -6
- data/lib/active_support/core_ext/object/duplicable.rb +72 -33
- data/lib/active_support/core_ext/object/inclusion.rb +16 -15
- data/lib/active_support/core_ext/object/itself.rb +15 -0
- data/lib/active_support/core_ext/object/json.rb +197 -0
- data/lib/active_support/core_ext/object/to_query.rb +14 -6
- data/lib/active_support/core_ext/object/try.rb +36 -14
- data/lib/active_support/core_ext/object/with_options.rb +30 -3
- data/lib/active_support/core_ext/object.rb +2 -1
- data/lib/active_support/core_ext/string/access.rb +35 -35
- data/lib/active_support/core_ext/string/conversions.rb +10 -9
- data/lib/active_support/core_ext/string/exclude.rb +3 -3
- data/lib/active_support/core_ext/string/filters.rb +51 -3
- data/lib/active_support/core_ext/string/inflections.rb +15 -10
- data/lib/active_support/core_ext/string/output_safety.rb +97 -33
- data/lib/active_support/core_ext/string/zones.rb +1 -0
- data/lib/active_support/core_ext/thread.rb +12 -5
- data/lib/active_support/core_ext/time/calculations.rb +47 -68
- data/lib/active_support/core_ext/time/compatibility.rb +14 -0
- data/lib/active_support/core_ext/time/conversions.rb +4 -2
- data/lib/active_support/core_ext/time/zones.rb +2 -20
- data/lib/active_support/core_ext/time.rb +1 -0
- data/lib/active_support/core_ext.rb +0 -1
- data/lib/active_support/dependencies/autoload.rb +1 -1
- data/lib/active_support/dependencies.rb +64 -25
- data/lib/active_support/deprecation/behaviors.rb +4 -4
- data/lib/active_support/deprecation.rb +4 -4
- data/lib/active_support/duration.rb +55 -11
- data/lib/active_support/file_update_checker.rb +1 -1
- data/lib/active_support/gem_version.rb +15 -0
- data/lib/active_support/hash_with_indifferent_access.rb +39 -11
- data/lib/active_support/i18n.rb +4 -4
- data/lib/active_support/i18n_railtie.rb +1 -7
- data/lib/active_support/inflections.rb +6 -1
- data/lib/active_support/inflector/inflections.rb +19 -19
- data/lib/active_support/inflector/methods.rb +66 -25
- data/lib/active_support/json/decoding.rb +15 -22
- data/lib/active_support/json/encoding.rb +125 -286
- data/lib/active_support/key_generator.rb +8 -10
- data/lib/active_support/lazy_load_hooks.rb +1 -1
- data/lib/active_support/log_subscriber/test_helper.rb +1 -1
- data/lib/active_support/logger.rb +51 -1
- data/lib/active_support/logger_silence.rb +7 -4
- data/lib/active_support/logger_thread_safe_level.rb +32 -0
- data/lib/active_support/message_encryptor.rb +14 -6
- data/lib/active_support/message_verifier.rb +16 -12
- data/lib/active_support/multibyte/chars.rb +2 -3
- data/lib/active_support/multibyte/unicode.rb +46 -58
- data/lib/active_support/notifications/fanout.rb +12 -7
- data/lib/active_support/notifications/instrumenter.rb +2 -1
- data/lib/active_support/notifications.rb +11 -6
- data/lib/active_support/number_helper/number_converter.rb +182 -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 +23 -0
- data/lib/active_support/number_helper/number_to_human_converter.rb +66 -0
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +58 -0
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
- data/lib/active_support/number_helper/number_to_phone_converter.rb +49 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +87 -0
- data/lib/active_support/number_helper.rb +32 -324
- data/lib/active_support/ordered_options.rb +8 -0
- data/lib/active_support/per_thread_registry.rb +13 -10
- data/lib/active_support/security_utils.rb +27 -0
- data/lib/active_support/subscriber.rb +35 -3
- data/lib/active_support/test_case.rb +52 -19
- data/lib/active_support/testing/assertions.rb +1 -31
- data/lib/active_support/testing/autorun.rb +2 -2
- data/lib/active_support/testing/constant_lookup.rb +1 -5
- data/lib/active_support/testing/declarative.rb +7 -21
- data/lib/active_support/testing/isolation.rb +29 -69
- data/lib/active_support/testing/setup_and_teardown.rb +17 -2
- data/lib/active_support/testing/tagged_logging.rb +2 -2
- data/lib/active_support/testing/time_helpers.rb +134 -0
- data/lib/active_support/time.rb +0 -2
- data/lib/active_support/time_with_zone.rb +60 -40
- data/lib/active_support/values/time_zone.rb +101 -101
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +4 -7
- data/lib/active_support/xml_mini/jdom.rb +6 -5
- data/lib/active_support/xml_mini/libxml.rb +1 -3
- data/lib/active_support/xml_mini/libxmlsax.rb +1 -4
- data/lib/active_support/xml_mini/nokogiri.rb +1 -3
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -3
- data/lib/active_support/xml_mini/rexml.rb +7 -8
- data/lib/active_support/xml_mini.rb +33 -15
- data/lib/active_support.rb +27 -2
- metadata +43 -43
- data/lib/active_support/basic_object.rb +0 -11
- data/lib/active_support/buffered_logger.rb +0 -21
- data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
- data/lib/active_support/core_ext/hash/diff.rb +0 -14
- data/lib/active_support/core_ext/logger.rb +0 -67
- 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/file_watcher.rb +0 -36
- data/lib/active_support/json/variable.rb +0 -18
- data/lib/active_support/testing/pending.rb +0 -14
@@ -1,7 +1,7 @@
|
|
1
1
|
#--
|
2
|
-
# Most objects are cloneable, but not all. For example you can't dup
|
2
|
+
# Most objects are cloneable, but not all. For example you can't dup methods:
|
3
3
|
#
|
4
|
-
#
|
4
|
+
# method(:puts).dup # => TypeError: allocator undefined for Method
|
5
5
|
#
|
6
6
|
# Classes may signal their instances are not duplicable removing +dup+/+clone+
|
7
7
|
# or raising exceptions from them. So, to dup an arbitrary object you normally
|
@@ -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, and
|
22
|
+
# False for +nil+, +false+, +true+, symbol, number and BigDecimal(in 1.9.x) objects;
|
23
23
|
# true otherwise.
|
24
24
|
def duplicable?
|
25
25
|
true
|
@@ -27,57 +27,86 @@ class Object
|
|
27
27
|
end
|
28
28
|
|
29
29
|
class NilClass
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
begin
|
31
|
+
nil.dup
|
32
|
+
rescue TypeError
|
33
|
+
|
34
|
+
# +nil+ is not duplicable:
|
35
|
+
#
|
36
|
+
# nil.duplicable? # => false
|
37
|
+
# nil.dup # => TypeError: can't dup NilClass
|
38
|
+
def duplicable?
|
39
|
+
false
|
40
|
+
end
|
36
41
|
end
|
37
42
|
end
|
38
43
|
|
39
44
|
class FalseClass
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
45
|
+
begin
|
46
|
+
false.dup
|
47
|
+
rescue TypeError
|
48
|
+
|
49
|
+
# +false+ is not duplicable:
|
50
|
+
#
|
51
|
+
# false.duplicable? # => false
|
52
|
+
# false.dup # => TypeError: can't dup FalseClass
|
53
|
+
def duplicable?
|
54
|
+
false
|
55
|
+
end
|
46
56
|
end
|
47
57
|
end
|
48
58
|
|
49
59
|
class TrueClass
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
60
|
+
begin
|
61
|
+
true.dup
|
62
|
+
rescue TypeError
|
63
|
+
|
64
|
+
# +true+ is not duplicable:
|
65
|
+
#
|
66
|
+
# true.duplicable? # => false
|
67
|
+
# true.dup # => TypeError: can't dup TrueClass
|
68
|
+
def duplicable?
|
69
|
+
false
|
70
|
+
end
|
56
71
|
end
|
57
72
|
end
|
58
73
|
|
59
74
|
class Symbol
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
75
|
+
begin
|
76
|
+
:symbol.dup # Ruby 2.4.x.
|
77
|
+
'symbol_from_string'.to_sym.dup # Some symbols can't `dup` in Ruby 2.4.0.
|
78
|
+
rescue TypeError
|
79
|
+
|
80
|
+
# Symbols are not duplicable:
|
81
|
+
#
|
82
|
+
# :my_symbol.duplicable? # => false
|
83
|
+
# :my_symbol.dup # => TypeError: can't dup Symbol
|
84
|
+
def duplicable?
|
85
|
+
false
|
86
|
+
end
|
66
87
|
end
|
67
88
|
end
|
68
89
|
|
69
90
|
class Numeric
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
91
|
+
begin
|
92
|
+
1.dup
|
93
|
+
rescue TypeError
|
94
|
+
|
95
|
+
# Numbers are not duplicable:
|
96
|
+
#
|
97
|
+
# 3.duplicable? # => false
|
98
|
+
# 3.dup # => TypeError: can't dup Integer
|
99
|
+
def duplicable?
|
100
|
+
false
|
101
|
+
end
|
76
102
|
end
|
77
103
|
end
|
78
104
|
|
79
105
|
require 'bigdecimal'
|
80
106
|
class BigDecimal
|
107
|
+
# Needed to support Ruby 1.9.x, as it doesn't allow dup on BigDecimal, instead
|
108
|
+
# raises TypeError exception. Checking here on the runtime whether BigDecimal
|
109
|
+
# will allow dup or not.
|
81
110
|
begin
|
82
111
|
BigDecimal.new('4.56').dup
|
83
112
|
|
@@ -88,3 +117,13 @@ class BigDecimal
|
|
88
117
|
# can't dup, so use superclass implementation
|
89
118
|
end
|
90
119
|
end
|
120
|
+
|
121
|
+
class Method
|
122
|
+
# Methods are not duplicable:
|
123
|
+
#
|
124
|
+
# method(:puts).duplicable? # => false
|
125
|
+
# method(:puts).dup # => TypeError: allocator undefined for Method
|
126
|
+
def duplicable?
|
127
|
+
false
|
128
|
+
end
|
129
|
+
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'active_support/deprecation'
|
2
|
-
|
3
1
|
class Object
|
4
2
|
# Returns true if this object is included in the argument. Argument must be
|
5
3
|
# any object which responds to +#include?+. Usage:
|
@@ -9,18 +7,21 @@ class Object
|
|
9
7
|
#
|
10
8
|
# This will throw an ArgumentError if the argument doesn't respond
|
11
9
|
# to +#include?+.
|
12
|
-
def in?(
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
10
|
+
def in?(another_object)
|
11
|
+
another_object.include?(self)
|
12
|
+
rescue NoMethodError
|
13
|
+
raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the receiver if it's included in the argument otherwise returns +nil+.
|
17
|
+
# Argument must be any object which responds to +#include?+. Usage:
|
18
|
+
#
|
19
|
+
# params[:bucket_type].presence_in %w( project calendar )
|
20
|
+
#
|
21
|
+
# This will throw an ArgumentError if the argument doesn't respond to +#include?+.
|
22
|
+
#
|
23
|
+
# @return [Object]
|
24
|
+
def presence_in(another_object)
|
25
|
+
self.in?(another_object) ? self : nil
|
25
26
|
end
|
26
27
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Object
|
2
|
+
# TODO: Remove this file when we drop support for Ruby < 2.2
|
3
|
+
unless respond_to?(:itself)
|
4
|
+
# Returns the object itself.
|
5
|
+
#
|
6
|
+
# Useful for chaining methods, such as Active Record scopes:
|
7
|
+
#
|
8
|
+
# Event.public_send(state.presence_in([ :trashed, :drafted ]) || :itself).order(:created_at)
|
9
|
+
#
|
10
|
+
# @return Object
|
11
|
+
def itself
|
12
|
+
self
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
# Hack to load json gem first so we can overwrite its to_json.
|
2
|
+
require 'json'
|
3
|
+
require 'bigdecimal'
|
4
|
+
require 'active_support/core_ext/big_decimal/conversions' # for #to_s
|
5
|
+
require 'active_support/core_ext/hash/except'
|
6
|
+
require 'active_support/core_ext/hash/slice'
|
7
|
+
require 'active_support/core_ext/object/instance_variables'
|
8
|
+
require 'time'
|
9
|
+
require 'active_support/core_ext/time/conversions'
|
10
|
+
require 'active_support/core_ext/date_time/conversions'
|
11
|
+
require 'active_support/core_ext/date/conversions'
|
12
|
+
require 'active_support/core_ext/module/aliasing'
|
13
|
+
|
14
|
+
# The JSON gem adds a few modules to Ruby core classes containing :to_json definition, overwriting
|
15
|
+
# their default behavior. That said, we need to define the basic to_json method in all of them,
|
16
|
+
# otherwise they will always use to_json gem implementation, which is backwards incompatible in
|
17
|
+
# several cases (for instance, the JSON implementation for Hash does not work) with inheritance
|
18
|
+
# and consequently classes as ActiveSupport::OrderedHash cannot be serialized to json.
|
19
|
+
#
|
20
|
+
# On the other hand, we should avoid conflict with ::JSON.{generate,dump}(obj). Unfortunately, the
|
21
|
+
# JSON gem's encoder relies on its own to_json implementation to encode objects. Since it always
|
22
|
+
# passes a ::JSON::State object as the only argument to to_json, we can detect that and forward the
|
23
|
+
# calls to the original to_json method.
|
24
|
+
#
|
25
|
+
# It should be noted that when using ::JSON.{generate,dump} directly, ActiveSupport's encoder is
|
26
|
+
# bypassed completely. This means that as_json won't be invoked and the JSON gem will simply
|
27
|
+
# ignore any options it does not natively understand. This also means that ::JSON.{generate,dump}
|
28
|
+
# should give exactly the same results with or without active support.
|
29
|
+
[Enumerable, Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].each do |klass|
|
30
|
+
klass.class_eval do
|
31
|
+
def to_json_with_active_support_encoder(options = nil) # :nodoc:
|
32
|
+
if options.is_a?(::JSON::State)
|
33
|
+
# Called from JSON.{generate,dump}, forward it to JSON gem's to_json
|
34
|
+
self.to_json_without_active_support_encoder(options)
|
35
|
+
else
|
36
|
+
# to_json is being invoked directly, use ActiveSupport's encoder
|
37
|
+
ActiveSupport::JSON.encode(self, options)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
alias_method_chain :to_json, :active_support_encoder
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Object
|
46
|
+
def as_json(options = nil) #:nodoc:
|
47
|
+
if respond_to?(:to_hash)
|
48
|
+
to_hash.as_json(options)
|
49
|
+
else
|
50
|
+
instance_values.as_json(options)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class Struct #:nodoc:
|
56
|
+
def as_json(options = nil)
|
57
|
+
Hash[members.zip(values)].as_json(options)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class TrueClass
|
62
|
+
def as_json(options = nil) #:nodoc:
|
63
|
+
self
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class FalseClass
|
68
|
+
def as_json(options = nil) #:nodoc:
|
69
|
+
self
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class NilClass
|
74
|
+
def as_json(options = nil) #:nodoc:
|
75
|
+
self
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class String
|
80
|
+
def as_json(options = nil) #:nodoc:
|
81
|
+
self
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class Symbol
|
86
|
+
def as_json(options = nil) #:nodoc:
|
87
|
+
to_s
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class Numeric
|
92
|
+
def as_json(options = nil) #:nodoc:
|
93
|
+
self
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class Float
|
98
|
+
# Encoding Infinity or NaN to JSON should return "null". The default returns
|
99
|
+
# "Infinity" or "NaN" which are not valid JSON.
|
100
|
+
def as_json(options = nil) #:nodoc:
|
101
|
+
finite? ? self : nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class BigDecimal
|
106
|
+
# A BigDecimal would be naturally represented as a JSON number. Most libraries,
|
107
|
+
# however, parse non-integer JSON numbers directly as floats. Clients using
|
108
|
+
# those libraries would get in general a wrong number and no way to recover
|
109
|
+
# other than manually inspecting the string with the JSON code itself.
|
110
|
+
#
|
111
|
+
# That's why a JSON string is returned. The JSON literal is not numeric, but
|
112
|
+
# if the other end knows by contract that the data is supposed to be a
|
113
|
+
# BigDecimal, it still has the chance to post-process the string and get the
|
114
|
+
# real value.
|
115
|
+
def as_json(options = nil) #:nodoc:
|
116
|
+
finite? ? to_s : nil
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class Regexp
|
121
|
+
def as_json(options = nil) #:nodoc:
|
122
|
+
to_s
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
module Enumerable
|
127
|
+
def as_json(options = nil) #:nodoc:
|
128
|
+
to_a.as_json(options)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
class Range
|
133
|
+
def as_json(options = nil) #:nodoc:
|
134
|
+
to_s
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
class Array
|
139
|
+
def as_json(options = nil) #:nodoc:
|
140
|
+
map { |v| options ? v.as_json(options.dup) : v.as_json }
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class Hash
|
145
|
+
def as_json(options = nil) #:nodoc:
|
146
|
+
# create a subset of the hash by applying :only or :except
|
147
|
+
subset = if options
|
148
|
+
if attrs = options[:only]
|
149
|
+
slice(*Array(attrs))
|
150
|
+
elsif attrs = options[:except]
|
151
|
+
except(*Array(attrs))
|
152
|
+
else
|
153
|
+
self
|
154
|
+
end
|
155
|
+
else
|
156
|
+
self
|
157
|
+
end
|
158
|
+
|
159
|
+
Hash[subset.map { |k, v| [k.to_s, options ? v.as_json(options.dup) : v.as_json] }]
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
class Time
|
164
|
+
def as_json(options = nil) #:nodoc:
|
165
|
+
if ActiveSupport::JSON::Encoding.use_standard_json_time_format
|
166
|
+
xmlschema(ActiveSupport::JSON::Encoding.time_precision)
|
167
|
+
else
|
168
|
+
%(#{strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
class Date
|
174
|
+
def as_json(options = nil) #:nodoc:
|
175
|
+
if ActiveSupport::JSON::Encoding.use_standard_json_time_format
|
176
|
+
strftime("%Y-%m-%d")
|
177
|
+
else
|
178
|
+
strftime("%Y/%m/%d")
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
class DateTime
|
184
|
+
def as_json(options = nil) #:nodoc:
|
185
|
+
if ActiveSupport::JSON::Encoding.use_standard_json_time_format
|
186
|
+
xmlschema(ActiveSupport::JSON::Encoding.time_precision)
|
187
|
+
else
|
188
|
+
strftime('%Y/%m/%d %H:%M:%S %z')
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
class Process::Status #:nodoc:
|
194
|
+
def as_json(options = nil)
|
195
|
+
{ :exitstatus => exitstatus, :pid => pid }
|
196
|
+
end
|
197
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
1
3
|
class Object
|
2
4
|
# Alias of <tt>to_s</tt>.
|
3
5
|
def to_param
|
@@ -7,7 +9,6 @@ class Object
|
|
7
9
|
# Converts an object into a string suitable for use as a URL query string,
|
8
10
|
# using the given <tt>key</tt> as the param name.
|
9
11
|
def to_query(key)
|
10
|
-
require 'cgi' unless defined?(CGI) && defined?(CGI::escape)
|
11
12
|
"#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}"
|
12
13
|
end
|
13
14
|
end
|
@@ -46,7 +47,12 @@ class Array
|
|
46
47
|
# ['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
|
47
48
|
def to_query(key)
|
48
49
|
prefix = "#{key}[]"
|
49
|
-
|
50
|
+
|
51
|
+
if empty?
|
52
|
+
nil.to_query(prefix)
|
53
|
+
else
|
54
|
+
collect { |value| value.to_query(prefix) }.join '&'
|
55
|
+
end
|
50
56
|
end
|
51
57
|
end
|
52
58
|
|
@@ -57,10 +63,10 @@ class Hash
|
|
57
63
|
# {name: 'David', nationality: 'Danish'}.to_query
|
58
64
|
# # => "name=David&nationality=Danish"
|
59
65
|
#
|
60
|
-
# An optional namespace can be passed to enclose
|
66
|
+
# An optional namespace can be passed to enclose key names:
|
61
67
|
#
|
62
68
|
# {name: 'David', nationality: 'Danish'}.to_query('user')
|
63
|
-
# # => "user
|
69
|
+
# # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"
|
64
70
|
#
|
65
71
|
# The string pairs "key=value" that conform the query string
|
66
72
|
# are sorted lexicographically in ascending order.
|
@@ -68,8 +74,10 @@ class Hash
|
|
68
74
|
# This method is also aliased as +to_param+.
|
69
75
|
def to_query(namespace = nil)
|
70
76
|
collect do |key, value|
|
71
|
-
value.
|
72
|
-
|
77
|
+
unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
|
78
|
+
value.to_query(namespace ? "#{namespace}[#{key}]" : key)
|
79
|
+
end
|
80
|
+
end.compact.sort! * '&'
|
73
81
|
end
|
74
82
|
|
75
83
|
alias_method :to_param, :to_query
|
@@ -9,7 +9,23 @@ class Object
|
|
9
9
|
#
|
10
10
|
# instead of
|
11
11
|
#
|
12
|
-
# @person
|
12
|
+
# @person.name if @person
|
13
|
+
#
|
14
|
+
# +try+ calls can be chained:
|
15
|
+
#
|
16
|
+
# @person.try(:spouse).try(:name)
|
17
|
+
#
|
18
|
+
# instead of
|
19
|
+
#
|
20
|
+
# @person.spouse.name if @person && @person.spouse
|
21
|
+
#
|
22
|
+
# +try+ will also return +nil+ if the receiver does not respond to the method:
|
23
|
+
#
|
24
|
+
# @person.try(:non_existing_method) #=> nil
|
25
|
+
#
|
26
|
+
# instead of
|
27
|
+
#
|
28
|
+
# @person.non_existing_method if @person.respond_to?(:non_existing_method) #=> nil
|
13
29
|
#
|
14
30
|
# +try+ returns +nil+ when called on +nil+ regardless of whether it responds
|
15
31
|
# to the method:
|
@@ -24,7 +40,7 @@ class Object
|
|
24
40
|
#
|
25
41
|
# The number of arguments in the signature must match. If the object responds
|
26
42
|
# to the method the call is attempted and +ArgumentError+ is still raised
|
27
|
-
#
|
43
|
+
# in case of argument mismatch.
|
28
44
|
#
|
29
45
|
# If +try+ is called without arguments it yields the receiver to a given
|
30
46
|
# block unless it is +nil+:
|
@@ -33,24 +49,30 @@ class Object
|
|
33
49
|
# ...
|
34
50
|
# end
|
35
51
|
#
|
36
|
-
#
|
52
|
+
# You can also call try with a block without accepting an argument, and the block
|
53
|
+
# will be instance_eval'ed instead:
|
54
|
+
#
|
55
|
+
# @person.try { upcase.truncate(50) }
|
56
|
+
#
|
57
|
+
# Please also note that +try+ is defined on +Object+. Therefore, it won't work
|
37
58
|
# with instances of classes that do not have +Object+ among their ancestors,
|
38
59
|
# like direct subclasses of +BasicObject+. For example, using +try+ with
|
39
60
|
# +SimpleDelegator+ will delegate +try+ to the target instead of calling it on
|
40
|
-
# delegator itself.
|
61
|
+
# the delegator itself.
|
41
62
|
def try(*a, &b)
|
42
|
-
if a.empty?
|
43
|
-
yield self
|
44
|
-
else
|
45
|
-
public_send(*a, &b) if respond_to?(a.first)
|
46
|
-
end
|
63
|
+
try!(*a, &b) if a.empty? || respond_to?(a.first)
|
47
64
|
end
|
48
65
|
|
49
|
-
# Same as #try, but will raise a NoMethodError exception if the
|
50
|
-
# does not
|
66
|
+
# Same as #try, but will raise a NoMethodError exception if the receiver is not +nil+ and
|
67
|
+
# does not implement the tried method.
|
68
|
+
|
51
69
|
def try!(*a, &b)
|
52
70
|
if a.empty? && block_given?
|
53
|
-
|
71
|
+
if b.arity == 0
|
72
|
+
instance_eval(&b)
|
73
|
+
else
|
74
|
+
yield self
|
75
|
+
end
|
54
76
|
else
|
55
77
|
public_send(*a, &b)
|
56
78
|
end
|
@@ -59,12 +81,12 @@ end
|
|
59
81
|
|
60
82
|
class NilClass
|
61
83
|
# Calling +try+ on +nil+ always returns +nil+.
|
62
|
-
# It becomes
|
84
|
+
# It becomes especially helpful when navigating through associations that may return +nil+.
|
63
85
|
#
|
64
86
|
# nil.try(:name) # => nil
|
65
87
|
#
|
66
88
|
# Without +try+
|
67
|
-
# @person &&
|
89
|
+
# @person && @person.children.any? && @person.children.first.name
|
68
90
|
#
|
69
91
|
# With +try+
|
70
92
|
# @person.try(:children).try(:first).try(:name)
|
@@ -34,9 +34,36 @@ class Object
|
|
34
34
|
# body i18n.t :body, user_name: user.name
|
35
35
|
# end
|
36
36
|
#
|
37
|
+
# When you don't pass an explicit receiver, it executes the whole block
|
38
|
+
# in merging options context:
|
39
|
+
#
|
40
|
+
# class Account < ActiveRecord::Base
|
41
|
+
# with_options dependent: :destroy do
|
42
|
+
# has_many :customers
|
43
|
+
# has_many :products
|
44
|
+
# has_many :invoices
|
45
|
+
# has_many :expenses
|
46
|
+
# end
|
47
|
+
# end
|
48
|
+
#
|
37
49
|
# <tt>with_options</tt> can also be nested since the call is forwarded to its receiver.
|
38
|
-
#
|
39
|
-
|
40
|
-
|
50
|
+
#
|
51
|
+
# NOTE: Each nesting level will merge inherited defaults in addition to their own.
|
52
|
+
#
|
53
|
+
# class Post < ActiveRecord::Base
|
54
|
+
# with_options if: :persisted?, length: { minimum: 50 } do
|
55
|
+
# validates :content, if: -> { content.present? }
|
56
|
+
# end
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# The code is equivalent to:
|
60
|
+
#
|
61
|
+
# validates :content, length: { minimum: 50 }, if: -> { content.present? }
|
62
|
+
#
|
63
|
+
# Hence the inherited default for `if` key is ignored.
|
64
|
+
#
|
65
|
+
def with_options(options, &block)
|
66
|
+
option_merger = ActiveSupport::OptionMerger.new(self, options)
|
67
|
+
block.arity.zero? ? option_merger.instance_eval(&block) : block.call(option_merger)
|
41
68
|
end
|
42
69
|
end
|
@@ -2,13 +2,14 @@ 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'
|
5
6
|
require 'active_support/core_ext/object/try'
|
6
7
|
require 'active_support/core_ext/object/inclusion'
|
7
8
|
|
8
9
|
require 'active_support/core_ext/object/conversions'
|
9
10
|
require 'active_support/core_ext/object/instance_variables'
|
10
11
|
|
11
|
-
require 'active_support/core_ext/object/
|
12
|
+
require 'active_support/core_ext/object/json'
|
12
13
|
require 'active_support/core_ext/object/to_param'
|
13
14
|
require 'active_support/core_ext/object/to_query'
|
14
15
|
require 'active_support/core_ext/object/with_options'
|