activesupport 3.0.20 → 3.1.0.beta1
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.
- data/CHANGELOG +14 -66
- data/README.rdoc +1 -1
- data/lib/active_support/backtrace_cleaner.rb +1 -1
- data/lib/active_support/buffered_logger.rb +4 -11
- data/lib/active_support/cache.rb +12 -15
- data/lib/active_support/cache/file_store.rb +3 -2
- data/lib/active_support/cache/mem_cache_store.rb +11 -3
- data/lib/active_support/cache/strategy/local_cache.rb +28 -23
- data/lib/active_support/callbacks.rb +195 -175
- data/lib/active_support/concern.rb +105 -35
- data/lib/active_support/configurable.rb +41 -2
- data/lib/active_support/core_ext/array/access.rb +2 -2
- data/lib/active_support/core_ext/array/random_access.rb +10 -7
- data/lib/active_support/core_ext/big_decimal/conversions.rb +0 -2
- data/lib/active_support/core_ext/class/attribute.rb +27 -17
- data/lib/active_support/core_ext/class/inheritable_attributes.rb +12 -86
- data/lib/active_support/core_ext/class/subclasses.rb +20 -34
- data/lib/active_support/core_ext/date/calculations.rb +14 -2
- data/lib/active_support/core_ext/date/conversions.rb +6 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +26 -9
- data/lib/active_support/core_ext/date_time/conversions.rb +1 -1
- data/lib/active_support/core_ext/date_time/zones.rb +1 -1
- data/lib/active_support/core_ext/enumerable.rb +2 -5
- data/lib/active_support/core_ext/float/rounding.rb +1 -1
- data/lib/active_support/core_ext/hash.rb +1 -0
- data/lib/active_support/core_ext/hash/conversions.rb +23 -36
- data/lib/active_support/core_ext/hash/deep_dup.rb +11 -0
- data/lib/active_support/core_ext/hash/keys.rb +6 -4
- data/lib/active_support/core_ext/hash/reverse_merge.rb +9 -14
- data/lib/active_support/core_ext/kernel/reporting.rb +19 -0
- data/lib/active_support/core_ext/logger.rb +11 -38
- data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +11 -12
- data/lib/active_support/core_ext/module/attr_internal.rb +13 -6
- data/lib/active_support/core_ext/module/deprecation.rb +2 -0
- data/lib/active_support/core_ext/object.rb +1 -1
- data/lib/active_support/core_ext/object/blank.rb +42 -9
- data/lib/active_support/core_ext/object/duplicable.rb +48 -9
- data/lib/active_support/core_ext/object/inclusion.rb +15 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +1 -35
- data/lib/active_support/core_ext/object/to_param.rb +13 -8
- data/lib/active_support/core_ext/object/to_query.rb +2 -2
- data/lib/active_support/core_ext/object/try.rb +27 -10
- data/lib/active_support/core_ext/object/with_options.rb +19 -5
- data/lib/active_support/core_ext/range.rb +1 -0
- data/lib/active_support/core_ext/range/cover.rb +3 -0
- data/lib/active_support/core_ext/string.rb +1 -0
- data/lib/active_support/core_ext/string/filters.rb +3 -3
- data/lib/active_support/core_ext/string/inflections.rb +1 -1
- data/lib/active_support/core_ext/string/inquiry.rb +13 -0
- data/lib/active_support/core_ext/string/multibyte.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +33 -89
- data/lib/active_support/core_ext/time/calculations.rb +14 -13
- data/lib/active_support/core_ext/time/conversions.rb +2 -24
- data/lib/active_support/core_ext/time/marshal.rb +0 -1
- data/lib/active_support/core_ext/time/zones.rb +32 -21
- data/lib/active_support/core_ext/uri.rb +8 -0
- data/lib/active_support/dependencies.rb +93 -37
- data/lib/active_support/deprecation.rb +2 -2
- data/lib/active_support/deprecation/behaviors.rb +7 -0
- data/lib/active_support/deprecation/proxy_wrappers.rb +1 -1
- data/lib/active_support/deprecation/reporting.rb +4 -0
- data/lib/active_support/duration.rb +4 -0
- data/lib/active_support/file_update_checker.rb +1 -1
- data/lib/active_support/file_watcher.rb +36 -0
- data/lib/active_support/gzip.rb +0 -1
- data/lib/active_support/hash_with_indifferent_access.rb +6 -4
- data/lib/active_support/i18n.rb +0 -1
- data/lib/active_support/i18n_railtie.rb +2 -2
- data/lib/active_support/inflector/inflections.rb +1 -1
- data/lib/active_support/json/decoding.rb +37 -23
- data/lib/active_support/json/encoding.rb +8 -3
- data/lib/active_support/lazy_load_hooks.rb +7 -7
- data/lib/active_support/log_subscriber.rb +3 -3
- data/lib/active_support/log_subscriber/test_helper.rb +4 -3
- data/lib/active_support/message_encryptor.rb +1 -1
- data/lib/active_support/message_verifier.rb +1 -1
- data/lib/active_support/multibyte/chars.rb +4 -3
- data/lib/active_support/multibyte/unicode.rb +1 -1
- data/lib/active_support/notifications.rb +9 -8
- data/lib/active_support/notifications/fanout.rb +3 -3
- data/lib/active_support/ordered_hash.rb +19 -2
- data/lib/active_support/ordered_options.rb +33 -3
- data/lib/active_support/railtie.rb +1 -1
- data/lib/active_support/rescuable.rb +1 -0
- data/lib/active_support/secure_random.rb +11 -5
- data/lib/active_support/test_case.rb +2 -10
- data/lib/active_support/testing/assertions.rb +17 -6
- data/lib/active_support/testing/mochaing.rb +7 -0
- data/lib/active_support/testing/pending.rb +27 -23
- data/lib/active_support/testing/setup_and_teardown.rb +8 -11
- data/lib/active_support/time_with_zone.rb +6 -3
- data/lib/active_support/version.rb +3 -3
- data/lib/active_support/whiny_nil.rb +1 -1
- data/lib/active_support/xml_mini.rb +4 -2
- data/lib/active_support/xml_mini/jdom.rb +9 -16
- data/lib/active_support/xml_mini/libxml.rb +1 -0
- data/lib/active_support/xml_mini/libxmlsax.rb +2 -1
- data/lib/active_support/xml_mini/nokogiri.rb +1 -0
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -0
- data/lib/active_support/xml_mini/rexml.rb +1 -0
- metadata +50 -32
- checksums.yaml +0 -7
- data/lib/active_support/core_ext/cgi.rb +0 -1
- data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +0 -19
- data/lib/active_support/core_ext/object/returning.rb +0 -43
- data/lib/active_support/json/backends/jsongem.rb +0 -47
- data/lib/active_support/json/backends/okjson.rb +0 -644
- data/lib/active_support/json/backends/yajl.rb +0 -44
- data/lib/active_support/json/backends/yaml.rb +0 -19
- data/lib/active_support/testing/default.rb +0 -9
@@ -7,25 +7,24 @@ class Module
|
|
7
7
|
# attr_accessor_with_default :age, 25
|
8
8
|
# end
|
9
9
|
#
|
10
|
-
#
|
11
|
-
# => 25
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# => 26
|
10
|
+
# person = Person.new
|
11
|
+
# person.age # => 25
|
12
|
+
#
|
13
|
+
# person.age = 26
|
14
|
+
# person.age # => 26
|
15
15
|
#
|
16
16
|
# To give attribute <tt>:element_name</tt> a dynamic default value, evaluated
|
17
17
|
# in scope of self:
|
18
18
|
#
|
19
19
|
# attr_accessor_with_default(:element_name) { name.underscore }
|
20
20
|
#
|
21
|
-
def attr_accessor_with_default(sym, default =
|
22
|
-
|
23
|
-
define_method(sym, block_given? ? block : Proc.new { default })
|
21
|
+
def attr_accessor_with_default(sym, default = Proc.new)
|
22
|
+
define_method(sym, block_given? ? default : Proc.new { default })
|
24
23
|
module_eval(<<-EVAL, __FILE__, __LINE__ + 1)
|
25
|
-
def #{sym}=(value)
|
26
|
-
class << self;
|
27
|
-
@#{sym} = value
|
28
|
-
end
|
24
|
+
def #{sym}=(value) # def age=(value)
|
25
|
+
class << self; attr_accessor :#{sym} end # class << self; attr_accessor :age end
|
26
|
+
@#{sym} = value # @age = value
|
27
|
+
end # end
|
29
28
|
EVAL
|
30
29
|
end
|
31
30
|
end
|
@@ -1,16 +1,12 @@
|
|
1
1
|
class Module
|
2
2
|
# Declares an attribute reader backed by an internally-named instance variable.
|
3
3
|
def attr_internal_reader(*attrs)
|
4
|
-
attrs.each
|
5
|
-
module_eval "def #{attr}() #{attr_internal_ivar_name(attr)} end", __FILE__, __LINE__
|
6
|
-
end
|
4
|
+
attrs.each {|attr_name| attr_internal_define(attr_name, :reader)}
|
7
5
|
end
|
8
6
|
|
9
7
|
# Declares an attribute writer backed by an internally-named instance variable.
|
10
8
|
def attr_internal_writer(*attrs)
|
11
|
-
attrs.each
|
12
|
-
module_eval "def #{attr}=(v) #{attr_internal_ivar_name(attr)} = v end", __FILE__, __LINE__
|
13
|
-
end
|
9
|
+
attrs.each {|attr_name| attr_internal_define(attr_name, :writer)}
|
14
10
|
end
|
15
11
|
|
16
12
|
# Declares an attribute reader and writer backed by an internally-named instance
|
@@ -29,4 +25,15 @@ class Module
|
|
29
25
|
def attr_internal_ivar_name(attr)
|
30
26
|
Module.attr_internal_naming_format % attr
|
31
27
|
end
|
28
|
+
|
29
|
+
def attr_internal_define(attr_name, type)
|
30
|
+
internal_name = attr_internal_ivar_name(attr_name).sub(/\A@/, '')
|
31
|
+
class_eval do # class_eval is necessary on 1.9 or else the methods a made private
|
32
|
+
# use native attr_* methods as they are faster on some Ruby implementations
|
33
|
+
send("attr_#{type}", internal_name)
|
34
|
+
end
|
35
|
+
attr_name, internal_name = "#{attr_name}=", "#{internal_name}=" if type == :writer
|
36
|
+
alias_method attr_name, internal_name
|
37
|
+
remove_method internal_name
|
38
|
+
end
|
32
39
|
end
|
@@ -2,7 +2,7 @@ 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/try'
|
5
|
-
require 'active_support/core_ext/object/
|
5
|
+
require 'active_support/core_ext/object/inclusion'
|
6
6
|
|
7
7
|
require 'active_support/core_ext/object/conversions'
|
8
8
|
require 'active_support/core_ext/object/instance_variables'
|
@@ -13,13 +13,13 @@ class Object
|
|
13
13
|
respond_to?(:empty?) ? empty? : !self
|
14
14
|
end
|
15
15
|
|
16
|
-
# An object is present if it's not blank
|
16
|
+
# An object is present if it's not <tt>blank?</tt>.
|
17
17
|
def present?
|
18
18
|
!blank?
|
19
19
|
end
|
20
20
|
|
21
|
-
# Returns object if it's
|
22
|
-
# object.presence is equivalent to object.present? ? object : nil
|
21
|
+
# Returns object if it's <tt>present?</tt> otherwise returns +nil+.
|
22
|
+
# <tt>object.presence</tt> is equivalent to <tt>object.present? ? object : nil</tt>.
|
23
23
|
#
|
24
24
|
# This is handy for any representation of objects where blank is the same
|
25
25
|
# as not present at all. For example, this simplifies a common check for
|
@@ -37,39 +37,72 @@ class Object
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
class NilClass
|
40
|
+
class NilClass
|
41
|
+
# +nil+ is blank:
|
42
|
+
#
|
43
|
+
# nil.blank? # => true
|
44
|
+
#
|
41
45
|
def blank?
|
42
46
|
true
|
43
47
|
end
|
44
48
|
end
|
45
49
|
|
46
|
-
class FalseClass
|
50
|
+
class FalseClass
|
51
|
+
# +false+ is blank:
|
52
|
+
#
|
53
|
+
# false.blank? # => true
|
54
|
+
#
|
47
55
|
def blank?
|
48
56
|
true
|
49
57
|
end
|
50
58
|
end
|
51
59
|
|
52
|
-
class TrueClass
|
60
|
+
class TrueClass
|
61
|
+
# +true+ is not blank:
|
62
|
+
#
|
63
|
+
# true.blank? # => false
|
64
|
+
#
|
53
65
|
def blank?
|
54
66
|
false
|
55
67
|
end
|
56
68
|
end
|
57
69
|
|
58
|
-
class Array
|
70
|
+
class Array
|
71
|
+
# An array is blank if it's empty:
|
72
|
+
#
|
73
|
+
# [].blank? # => true
|
74
|
+
# [1,2,3].blank? # => false
|
75
|
+
#
|
59
76
|
alias_method :blank?, :empty?
|
60
77
|
end
|
61
78
|
|
62
|
-
class Hash
|
79
|
+
class Hash
|
80
|
+
# A hash is blank if it's empty:
|
81
|
+
#
|
82
|
+
# {}.blank? # => true
|
83
|
+
# {:key => 'value'}.blank? # => false
|
84
|
+
#
|
63
85
|
alias_method :blank?, :empty?
|
64
86
|
end
|
65
87
|
|
66
|
-
class String
|
88
|
+
class String
|
89
|
+
# A string is blank if it's empty or contains whitespaces only:
|
90
|
+
#
|
91
|
+
# "".blank? # => true
|
92
|
+
# " ".blank? # => true
|
93
|
+
# " something here ".blank? # => false
|
94
|
+
#
|
67
95
|
def blank?
|
68
96
|
self !~ /\S/
|
69
97
|
end
|
70
98
|
end
|
71
99
|
|
72
100
|
class Numeric #:nodoc:
|
101
|
+
# No number is blank:
|
102
|
+
#
|
103
|
+
# 1.blank? # => false
|
104
|
+
# 0.blank? # => false
|
105
|
+
#
|
73
106
|
def blank?
|
74
107
|
false
|
75
108
|
end
|
@@ -15,50 +15,89 @@
|
|
15
15
|
# That's why we hardcode the following cases and check duplicable? instead of
|
16
16
|
# using that rescue idiom.
|
17
17
|
class Object
|
18
|
-
# Can you safely
|
19
|
-
#
|
18
|
+
# Can you safely dup this object?
|
19
|
+
#
|
20
|
+
# False for +nil+, +false+, +true+, symbols, numbers, class and module objects;
|
21
|
+
# true otherwise.
|
20
22
|
def duplicable?
|
21
23
|
true
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
25
|
-
class NilClass
|
27
|
+
class NilClass
|
28
|
+
# +nil+ is not duplicable:
|
29
|
+
#
|
30
|
+
# nil.duplicable? # => false
|
31
|
+
# nil.dup # => TypeError: can't dup NilClass
|
32
|
+
#
|
26
33
|
def duplicable?
|
27
34
|
false
|
28
35
|
end
|
29
36
|
end
|
30
37
|
|
31
|
-
class FalseClass
|
38
|
+
class FalseClass
|
39
|
+
# +false+ is not duplicable:
|
40
|
+
#
|
41
|
+
# false.duplicable? # => false
|
42
|
+
# false.dup # => TypeError: can't dup FalseClass
|
43
|
+
#
|
32
44
|
def duplicable?
|
33
45
|
false
|
34
46
|
end
|
35
47
|
end
|
36
48
|
|
37
|
-
class TrueClass
|
49
|
+
class TrueClass
|
50
|
+
# +true+ is not duplicable:
|
51
|
+
#
|
52
|
+
# true.duplicable? # => false
|
53
|
+
# true.dup # => TypeError: can't dup TrueClass
|
54
|
+
#
|
38
55
|
def duplicable?
|
39
56
|
false
|
40
57
|
end
|
41
58
|
end
|
42
59
|
|
43
|
-
class Symbol
|
60
|
+
class Symbol
|
61
|
+
# Symbols are not duplicable:
|
62
|
+
#
|
63
|
+
# :my_symbol.duplicable? # => false
|
64
|
+
# :my_symbol.dup # => TypeError: can't dup Symbol
|
65
|
+
#
|
44
66
|
def duplicable?
|
45
67
|
false
|
46
68
|
end
|
47
69
|
end
|
48
70
|
|
49
|
-
class Numeric
|
71
|
+
class Numeric
|
72
|
+
# Numbers are not duplicable:
|
73
|
+
#
|
74
|
+
# 3.duplicable? # => false
|
75
|
+
# 3.dup # => TypeError: can't dup Fixnum
|
76
|
+
#
|
50
77
|
def duplicable?
|
51
78
|
false
|
52
79
|
end
|
53
80
|
end
|
54
81
|
|
55
|
-
class Class
|
82
|
+
class Class
|
83
|
+
# Classes are not duplicable:
|
84
|
+
#
|
85
|
+
# c = Class.new # => #<Class:0x10328fd80>
|
86
|
+
# c.dup # => #<Class:0x10328fd80>
|
87
|
+
#
|
88
|
+
# Note +dup+ returned the same class object.
|
56
89
|
def duplicable?
|
57
90
|
false
|
58
91
|
end
|
59
92
|
end
|
60
93
|
|
61
|
-
class Module
|
94
|
+
class Module
|
95
|
+
# Modules are not duplicable:
|
96
|
+
#
|
97
|
+
# m = Module.new # => #<Module:0x10328b6e0>
|
98
|
+
# m.dup # => #<Module:0x10328b6e0>
|
99
|
+
#
|
100
|
+
# Note +dup+ returned the same module object.
|
62
101
|
def duplicable?
|
63
102
|
false
|
64
103
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Object
|
2
|
+
# Returns true if this object is included in the argument. Argument must be
|
3
|
+
# any object which responds to +#include?+. Usage:
|
4
|
+
#
|
5
|
+
# characters = ["Konata", "Kagami", "Tsukasa"]
|
6
|
+
# "Konata".in?(characters) # => true
|
7
|
+
#
|
8
|
+
# This will throw an ArgumentError if the argument doesn't respond
|
9
|
+
# to +#include?+.
|
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
|
+
end
|
@@ -10,10 +10,7 @@ class Object
|
|
10
10
|
#
|
11
11
|
# C.new(0, 1).instance_values # => {"x" => 0, "y" => 1}
|
12
12
|
def instance_values #:nodoc:
|
13
|
-
instance_variables.
|
14
|
-
values[name.to_s[1..-1]] = instance_variable_get(name)
|
15
|
-
values
|
16
|
-
end
|
13
|
+
Hash[instance_variables.map { |name| [name.to_s[1..-1], instance_variable_get(name)] }]
|
17
14
|
end
|
18
15
|
|
19
16
|
# Returns an array of instance variable names including "@". They are strings
|
@@ -33,35 +30,4 @@ class Object
|
|
33
30
|
else
|
34
31
|
alias_method :instance_variable_names, :instance_variables
|
35
32
|
end
|
36
|
-
|
37
|
-
# Copies the instance variables of +object+ into +self+.
|
38
|
-
#
|
39
|
-
# Instance variable names in the +exclude+ array are ignored. If +object+
|
40
|
-
# responds to <tt>protected_instance_variables</tt> the ones returned are
|
41
|
-
# also ignored. For example, Rails controllers implement that method.
|
42
|
-
#
|
43
|
-
# In both cases strings and symbols are understood, and they have to include
|
44
|
-
# the at sign.
|
45
|
-
#
|
46
|
-
# class C
|
47
|
-
# def initialize(x, y, z)
|
48
|
-
# @x, @y, @z = x, y, z
|
49
|
-
# end
|
50
|
-
#
|
51
|
-
# def protected_instance_variables
|
52
|
-
# %w(@z)
|
53
|
-
# end
|
54
|
-
# end
|
55
|
-
#
|
56
|
-
# a = C.new(0, 1, 2)
|
57
|
-
# b = C.new(3, 4, 5)
|
58
|
-
#
|
59
|
-
# a.copy_instance_variables_from(b, [:@y])
|
60
|
-
# # a is now: @x = 3, @y = 1, @z = 2
|
61
|
-
def copy_instance_variables_from(object, exclude = []) #:nodoc:
|
62
|
-
exclude += object.protected_instance_variables if object.respond_to? :protected_instance_variables
|
63
|
-
|
64
|
-
vars = object.instance_variables.map(&:to_s) - exclude.map(&:to_s)
|
65
|
-
vars.each { |name| instance_variable_set(name, object.instance_variable_get(name)) }
|
66
|
-
end
|
67
33
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
1
|
class Object
|
4
2
|
# Alias of <tt>to_s</tt>.
|
5
3
|
def to_param
|
@@ -34,14 +32,21 @@ class Array
|
|
34
32
|
end
|
35
33
|
|
36
34
|
class Hash
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
35
|
+
# Returns a string representation of the receiver suitable for use as a URL
|
36
|
+
# query string:
|
37
|
+
#
|
38
|
+
# {:name => 'David', :nationality => 'Danish'}.to_param
|
39
|
+
# # => "name=David&nationality=Danish"
|
40
|
+
#
|
41
|
+
# An optional namespace can be passed to enclose the param names:
|
42
|
+
#
|
43
|
+
# {:name => 'David', :nationality => 'Danish'}.to_param('user')
|
44
|
+
# # => "user[name]=David&user[nationality]=Danish"
|
40
45
|
#
|
41
|
-
#
|
42
|
-
#
|
46
|
+
# The string pairs "key=value" that conform the query string
|
47
|
+
# are sorted lexicographically in ascending order.
|
43
48
|
#
|
44
|
-
#
|
49
|
+
# This method is also aliased as +to_query+.
|
45
50
|
def to_param(namespace = nil)
|
46
51
|
collect do |key, value|
|
47
52
|
value.to_query(namespace ? "#{namespace}[#{key}]" : key)
|
@@ -7,7 +7,7 @@ class Object
|
|
7
7
|
# Note: This method is defined as a default implementation for all Objects for Hash#to_query to work.
|
8
8
|
def to_query(key)
|
9
9
|
require 'cgi' unless defined?(CGI) && defined?(CGI::escape)
|
10
|
-
"#{CGI.escape(key.to_s)
|
10
|
+
"#{CGI.escape(key.to_s)}=#{CGI.escape(to_param.to_s)}"
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
@@ -15,7 +15,7 @@ class Array
|
|
15
15
|
# Converts an array into a string suitable for use as a URL query string,
|
16
16
|
# using the given +key+ as the param name.
|
17
17
|
#
|
18
|
-
# ['Rails', 'coding'].to_query('hobbies') # => "hobbies
|
18
|
+
# ['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
|
19
19
|
def to_query(key)
|
20
20
|
prefix = "#{key}[]"
|
21
21
|
collect { |value| value.to_query(prefix) }.join '&'
|
@@ -5,31 +5,48 @@ class Object
|
|
5
5
|
# *Unlike* that method however, a +NoMethodError+ exception will *not* be raised
|
6
6
|
# and +nil+ will be returned instead, if the receiving object is a +nil+ object or NilClass.
|
7
7
|
#
|
8
|
+
# If try is called without a method to call, it will yield any given block with the object.
|
9
|
+
#
|
8
10
|
# ==== Examples
|
9
11
|
#
|
10
|
-
# Without try
|
12
|
+
# Without +try+
|
11
13
|
# @person && @person.name
|
12
14
|
# or
|
13
15
|
# @person ? @person.name : nil
|
14
16
|
#
|
15
|
-
# With try
|
17
|
+
# With +try+
|
16
18
|
# @person.try(:name)
|
17
19
|
#
|
18
20
|
# +try+ also accepts arguments and/or a block, for the method it is trying
|
19
21
|
# Person.try(:find, 1)
|
20
22
|
# @people.try(:collect) {|p| p.name}
|
23
|
+
#
|
24
|
+
# Without a method argument try will yield to the block unless the receiver is nil.
|
25
|
+
# @person.try { |p| "#{p.first_name} #{p.last_name}" }
|
21
26
|
#--
|
22
|
-
#
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
+
# +try+ behaves like +Object#send+, unless called on +NilClass+.
|
28
|
+
def try(*a, &b)
|
29
|
+
if a.empty? && block_given?
|
30
|
+
yield self
|
31
|
+
else
|
32
|
+
__send__(*a, &b)
|
33
|
+
end
|
27
34
|
end
|
28
|
-
remove_method :try
|
29
|
-
alias_method :try, :__send__
|
30
35
|
end
|
31
36
|
|
32
|
-
class NilClass
|
37
|
+
class NilClass
|
38
|
+
# Calling +try+ on +nil+ always returns +nil+.
|
39
|
+
# It becomes specially helpful when navigating through associations that may return +nil+.
|
40
|
+
#
|
41
|
+
# === Examples
|
42
|
+
#
|
43
|
+
# nil.try(:name) # => nil
|
44
|
+
#
|
45
|
+
# Without +try+
|
46
|
+
# @person && !@person.children.blank? && @person.children.first.name
|
47
|
+
#
|
48
|
+
# With +try+
|
49
|
+
# @person.try(:children).try(:first).try(:name)
|
33
50
|
def try(*args)
|
34
51
|
nil
|
35
52
|
end
|