activesupport 3.0.20 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +24 -28
- data/README.rdoc +2 -2
- data/lib/active_support/backtrace_cleaner.rb +17 -12
- data/lib/active_support/buffered_logger.rb +7 -9
- data/lib/active_support/cache/file_store.rb +4 -3
- data/lib/active_support/cache/mem_cache_store.rb +10 -2
- data/lib/active_support/cache/strategy/local_cache.rb +28 -23
- data/lib/active_support/cache.rb +11 -14
- data/lib/active_support/callbacks.rb +195 -175
- data/lib/active_support/concern.rb +105 -35
- data/lib/active_support/configurable.rb +50 -8
- data/lib/active_support/core_ext/array/access.rb +2 -2
- data/lib/active_support/core_ext/array/conversions.rb +2 -2
- data/lib/active_support/core_ext/array/random_access.rb +10 -7
- data/lib/active_support/core_ext/array/uniq_by.rb +2 -3
- data/lib/active_support/core_ext/array/wrap.rb +1 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +0 -2
- data/lib/active_support/core_ext/class/attribute.rb +15 -1
- data/lib/active_support/core_ext/class/inheritable_attributes.rb +10 -86
- data/lib/active_support/core_ext/class/subclasses.rb +20 -34
- data/lib/active_support/core_ext/date/calculations.rb +17 -5
- data/lib/active_support/core_ext/date/conversions.rb +9 -2
- data/lib/active_support/core_ext/date_time/calculations.rb +26 -9
- data/lib/active_support/core_ext/date_time/conversions.rb +9 -9
- data/lib/active_support/core_ext/date_time/zones.rb +1 -1
- data/lib/active_support/core_ext/enumerable.rb +3 -6
- data/lib/active_support/core_ext/float/rounding.rb +1 -1
- data/lib/active_support/core_ext/hash/conversions.rb +22 -34
- data/lib/active_support/core_ext/hash/deep_dup.rb +11 -0
- data/lib/active_support/core_ext/hash/indifferent_access.rb +12 -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/hash/slice.rb +3 -1
- data/lib/active_support/core_ext/hash.rb +1 -0
- data/lib/active_support/core_ext/integer/inflections.rb +7 -4
- data/lib/active_support/core_ext/kernel/reporting.rb +31 -0
- data/lib/active_support/core_ext/kernel/requires.rb +2 -0
- data/lib/active_support/core_ext/logger.rb +11 -38
- data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +12 -12
- data/lib/active_support/core_ext/module/attr_internal.rb +13 -6
- data/lib/active_support/core_ext/module/delegation.rb +1 -5
- data/lib/active_support/core_ext/module/remove_method.rb +7 -2
- data/lib/active_support/core_ext/numeric/time.rb +2 -0
- data/lib/active_support/core_ext/object/blank.rb +45 -12
- data/lib/active_support/core_ext/object/duplicable.rb +50 -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 +29 -10
- data/lib/active_support/core_ext/object/with_options.rb +25 -8
- data/lib/active_support/core_ext/object.rb +1 -1
- data/lib/active_support/core_ext/range/cover.rb +3 -0
- data/lib/active_support/core_ext/range.rb +1 -0
- data/lib/active_support/core_ext/string/behavior.rb +1 -2
- data/lib/active_support/core_ext/string/conversions.rb +1 -0
- data/lib/active_support/core_ext/string/exclude.rb +1 -1
- 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 +2 -2
- data/lib/active_support/core_ext/string/output_safety.rb +45 -62
- data/lib/active_support/core_ext/string.rb +1 -0
- data/lib/active_support/core_ext/time/calculations.rb +19 -16
- data/lib/active_support/core_ext/time/conversions.rb +2 -24
- 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 +74 -28
- 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/deprecation.rb +2 -2
- data/lib/active_support/descendants_tracker.rb +9 -7
- data/lib/active_support/duration.rb +5 -0
- data/lib/active_support/file_update_checker.rb +1 -1
- data/lib/active_support/file_watcher.rb +36 -0
- data/lib/active_support/hash_with_indifferent_access.rb +20 -8
- data/lib/active_support/i18n.rb +0 -1
- data/lib/active_support/i18n_railtie.rb +2 -2
- data/lib/active_support/inflections.rb +1 -0
- data/lib/active_support/inflector/inflections.rb +1 -1
- data/lib/active_support/inflector/methods.rb +5 -3
- data/lib/active_support/json/decoding.rb +37 -23
- data/lib/active_support/json/encoding.rb +12 -4
- data/lib/active_support/lazy_load_hooks.rb +7 -7
- data/lib/active_support/log_subscriber/test_helper.rb +5 -3
- data/lib/active_support/log_subscriber.rb +6 -6
- 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 +5 -5
- data/lib/active_support/multibyte/unicode.rb +2 -1
- data/lib/active_support/notifications/fanout.rb +3 -3
- data/lib/active_support/notifications/instrumenter.rb +1 -1
- data/lib/active_support/notifications.rb +9 -10
- data/lib/active_support/ordered_hash.rb +23 -2
- data/lib/active_support/ordered_options.rb +37 -3
- data/lib/active_support/railtie.rb +1 -1
- data/lib/active_support/rescuable.rb +1 -0
- data/lib/active_support/secure_random.rb +3 -196
- data/lib/active_support/test_case.rb +2 -10
- data/lib/active_support/testing/assertions.rb +20 -7
- data/lib/active_support/testing/mochaing.rb +7 -0
- data/lib/active_support/testing/pending.rb +27 -23
- data/lib/active_support/testing/performance/jruby.rb +115 -0
- data/lib/active_support/testing/performance/rubinius.rb +113 -0
- data/lib/active_support/testing/performance/ruby/mri.rb +57 -0
- data/lib/active_support/testing/performance/ruby/yarv.rb +57 -0
- data/lib/active_support/testing/performance/ruby.rb +152 -0
- data/lib/active_support/testing/performance.rb +214 -322
- 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/values/time_zone.rb +26 -8
- data/lib/active_support/version.rb +2 -2
- data/lib/active_support/whiny_nil.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +1 -1
- 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
- data/lib/active_support/xml_mini.rb +8 -3
- data/lib/active_support.rb +4 -2
- metadata +70 -32
- checksums.yaml +0 -7
- data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +0 -19
- data/lib/active_support/core_ext/cgi.rb +0 -1
- 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
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
class Object
|
|
2
2
|
# An object is blank if it's false, empty, or a whitespace string.
|
|
3
|
-
# For example, "", " ", +nil+, [], and {} are blank.
|
|
3
|
+
# For example, "", " ", +nil+, [], and {} are all blank.
|
|
4
4
|
#
|
|
5
5
|
# This simplifies:
|
|
6
6
|
#
|
|
7
|
-
# if
|
|
7
|
+
# if address.nil? || address.empty?
|
|
8
8
|
#
|
|
9
9
|
# ...to:
|
|
10
10
|
#
|
|
11
|
-
# if
|
|
11
|
+
# if address.blank?
|
|
12
12
|
def blank?
|
|
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
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#--
|
|
1
2
|
# Most objects are cloneable, but not all. For example you can't dup +nil+:
|
|
2
3
|
#
|
|
3
4
|
# nil.dup # => TypeError: can't dup NilClass
|
|
@@ -14,51 +15,91 @@
|
|
|
14
15
|
#
|
|
15
16
|
# That's why we hardcode the following cases and check duplicable? instead of
|
|
16
17
|
# using that rescue idiom.
|
|
18
|
+
#++
|
|
17
19
|
class Object
|
|
18
|
-
# Can you safely
|
|
19
|
-
#
|
|
20
|
+
# Can you safely dup this object?
|
|
21
|
+
#
|
|
22
|
+
# False for +nil+, +false+, +true+, symbols, numbers, class and module objects;
|
|
23
|
+
# true otherwise.
|
|
20
24
|
def duplicable?
|
|
21
25
|
true
|
|
22
26
|
end
|
|
23
27
|
end
|
|
24
28
|
|
|
25
|
-
class NilClass
|
|
29
|
+
class NilClass
|
|
30
|
+
# +nil+ is not duplicable:
|
|
31
|
+
#
|
|
32
|
+
# nil.duplicable? # => false
|
|
33
|
+
# nil.dup # => TypeError: can't dup NilClass
|
|
34
|
+
#
|
|
26
35
|
def duplicable?
|
|
27
36
|
false
|
|
28
37
|
end
|
|
29
38
|
end
|
|
30
39
|
|
|
31
|
-
class FalseClass
|
|
40
|
+
class FalseClass
|
|
41
|
+
# +false+ is not duplicable:
|
|
42
|
+
#
|
|
43
|
+
# false.duplicable? # => false
|
|
44
|
+
# false.dup # => TypeError: can't dup FalseClass
|
|
45
|
+
#
|
|
32
46
|
def duplicable?
|
|
33
47
|
false
|
|
34
48
|
end
|
|
35
49
|
end
|
|
36
50
|
|
|
37
|
-
class TrueClass
|
|
51
|
+
class TrueClass
|
|
52
|
+
# +true+ is not duplicable:
|
|
53
|
+
#
|
|
54
|
+
# true.duplicable? # => false
|
|
55
|
+
# true.dup # => TypeError: can't dup TrueClass
|
|
56
|
+
#
|
|
38
57
|
def duplicable?
|
|
39
58
|
false
|
|
40
59
|
end
|
|
41
60
|
end
|
|
42
61
|
|
|
43
|
-
class Symbol
|
|
62
|
+
class Symbol
|
|
63
|
+
# Symbols are not duplicable:
|
|
64
|
+
#
|
|
65
|
+
# :my_symbol.duplicable? # => false
|
|
66
|
+
# :my_symbol.dup # => TypeError: can't dup Symbol
|
|
67
|
+
#
|
|
44
68
|
def duplicable?
|
|
45
69
|
false
|
|
46
70
|
end
|
|
47
71
|
end
|
|
48
72
|
|
|
49
|
-
class Numeric
|
|
73
|
+
class Numeric
|
|
74
|
+
# Numbers are not duplicable:
|
|
75
|
+
#
|
|
76
|
+
# 3.duplicable? # => false
|
|
77
|
+
# 3.dup # => TypeError: can't dup Fixnum
|
|
78
|
+
#
|
|
50
79
|
def duplicable?
|
|
51
80
|
false
|
|
52
81
|
end
|
|
53
82
|
end
|
|
54
83
|
|
|
55
|
-
class Class
|
|
84
|
+
class Class
|
|
85
|
+
# Classes are not duplicable:
|
|
86
|
+
#
|
|
87
|
+
# c = Class.new # => #<Class:0x10328fd80>
|
|
88
|
+
# c.dup # => #<Class:0x10328fd80>
|
|
89
|
+
#
|
|
90
|
+
# Note +dup+ returned the same class object.
|
|
56
91
|
def duplicable?
|
|
57
92
|
false
|
|
58
93
|
end
|
|
59
94
|
end
|
|
60
95
|
|
|
61
|
-
class Module
|
|
96
|
+
class Module
|
|
97
|
+
# Modules are not duplicable:
|
|
98
|
+
#
|
|
99
|
+
# m = Module.new # => #<Module:0x10328b6e0>
|
|
100
|
+
# m.dup # => #<Module:0x10328b6e0>
|
|
101
|
+
#
|
|
102
|
+
# Note +dup+ returned the same module object.
|
|
62
103
|
def duplicable?
|
|
63
104
|
false
|
|
64
105
|
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,50 @@ 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
|
+
elsif !a.empty? && !respond_to?(a.first)
|
|
32
|
+
nil
|
|
33
|
+
else
|
|
34
|
+
__send__(*a, &b)
|
|
35
|
+
end
|
|
27
36
|
end
|
|
28
|
-
remove_method :try
|
|
29
|
-
alias_method :try, :__send__
|
|
30
37
|
end
|
|
31
38
|
|
|
32
|
-
class NilClass
|
|
39
|
+
class NilClass
|
|
40
|
+
# Calling +try+ on +nil+ always returns +nil+.
|
|
41
|
+
# It becomes specially helpful when navigating through associations that may return +nil+.
|
|
42
|
+
#
|
|
43
|
+
# === Examples
|
|
44
|
+
#
|
|
45
|
+
# nil.try(:name) # => nil
|
|
46
|
+
#
|
|
47
|
+
# Without +try+
|
|
48
|
+
# @person && !@person.children.blank? && @person.children.first.name
|
|
49
|
+
#
|
|
50
|
+
# With +try+
|
|
51
|
+
# @person.try(:children).try(:first).try(:name)
|
|
33
52
|
def try(*args)
|
|
34
53
|
nil
|
|
35
54
|
end
|
|
@@ -7,19 +7,36 @@ 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
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
10
|
+
# Without <tt>with_options></tt>, this code contains duplication:
|
|
11
|
+
#
|
|
12
|
+
# class Account < ActiveRecord::Base
|
|
13
|
+
# has_many :customers, :dependent => :destroy
|
|
14
|
+
# has_many :products, :dependent => :destroy
|
|
15
|
+
# has_many :invoices, :dependent => :destroy
|
|
16
|
+
# has_many :expenses, :dependent => :destroy
|
|
14
17
|
# end
|
|
15
18
|
#
|
|
16
|
-
#
|
|
19
|
+
# Using <tt>with_options</tt>, we can remove the duplication:
|
|
17
20
|
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
+
# class Account < ActiveRecord::Base
|
|
22
|
+
# with_options :dependent => :destroy do |assoc|
|
|
23
|
+
# assoc.has_many :customers
|
|
24
|
+
# assoc.has_many :products
|
|
25
|
+
# assoc.has_many :invoices
|
|
26
|
+
# assoc.has_many :expenses
|
|
27
|
+
# end
|
|
21
28
|
# end
|
|
22
29
|
#
|
|
30
|
+
# It can also be used with an explicit receiver:
|
|
31
|
+
#
|
|
32
|
+
# I18n.with_options :locale => user.locale, :scope => "newsletter" do |i18n|
|
|
33
|
+
# subject i18n.t :subject
|
|
34
|
+
# body i18n.t :body, :user_name => user.name
|
|
35
|
+
# end
|
|
36
|
+
#
|
|
37
|
+
# <tt>with_options</tt> can also be nested since the call is forwarded to its receiver.
|
|
38
|
+
# Each nesting level will merge inherited defaults in addition to their own.
|
|
39
|
+
#
|
|
23
40
|
def with_options(options)
|
|
24
41
|
yield ActiveSupport::OptionMerger.new(self, options)
|
|
25
42
|
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'
|
|
@@ -25,13 +25,13 @@ class String
|
|
|
25
25
|
# "Once upon a time in a world far far away".truncate(27)
|
|
26
26
|
# # => "Once upon a time in a wo..."
|
|
27
27
|
#
|
|
28
|
-
#
|
|
29
|
-
# for a total length not exceeding <tt>:length</tt>:
|
|
28
|
+
# Pass a <tt>:separator</tt> to truncate +text+ at a natural break:
|
|
30
29
|
#
|
|
31
30
|
# "Once upon a time in a world far far away".truncate(27, :separator => ' ')
|
|
32
31
|
# # => "Once upon a time in a..."
|
|
33
32
|
#
|
|
34
|
-
#
|
|
33
|
+
# The last characters will be replaced with the <tt>:omission</tt> string (defaults to "...")
|
|
34
|
+
# for a total length not exceeding <tt>:length</tt>:
|
|
35
35
|
#
|
|
36
36
|
# "And they found that many people were sleeping better.".truncate(25, :omission => "... (continued)")
|
|
37
37
|
# # => "And they f... (continued)"
|
|
@@ -3,7 +3,7 @@ require 'active_support/inflector/inflections'
|
|
|
3
3
|
require 'active_support/inflector/transliterate'
|
|
4
4
|
|
|
5
5
|
# String inflections define new methods on the String class to transform names for different purposes.
|
|
6
|
-
# For instance, you can figure out the name of a
|
|
6
|
+
# For instance, you can figure out the name of a table from the name of a class.
|
|
7
7
|
#
|
|
8
8
|
# "ScaleScore".tableize # => "scale_scores"
|
|
9
9
|
#
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'active_support/string_inquirer'
|
|
2
|
+
|
|
3
|
+
class String
|
|
4
|
+
# Wraps the current string in the <tt>ActiveSupport::StringInquirer</tt> class,
|
|
5
|
+
# which gives you a prettier way to test for equality. Example:
|
|
6
|
+
#
|
|
7
|
+
# env = "production".inquiry
|
|
8
|
+
# env.production? # => true
|
|
9
|
+
# env.development? # => false
|
|
10
|
+
def inquiry
|
|
11
|
+
ActiveSupport::StringInquirer.new(self)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -9,7 +9,7 @@ class String
|
|
|
9
9
|
#
|
|
10
10
|
# In Ruby 1.8 and older it creates and returns an instance of the ActiveSupport::Multibyte::Chars class which
|
|
11
11
|
# encapsulates the original string. A Unicode safe version of all the String methods are defined on this proxy
|
|
12
|
-
# class. If the proxy class doesn't respond to a certain method, it's forwarded to the
|
|
12
|
+
# class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsulated string.
|
|
13
13
|
#
|
|
14
14
|
# name = 'Claus Müller'
|
|
15
15
|
# name.reverse # => "rell??M sualC"
|
|
@@ -35,7 +35,7 @@ class String
|
|
|
35
35
|
# object. Interoperability problems can be resolved easily with a +to_s+ call.
|
|
36
36
|
#
|
|
37
37
|
# For more information about the methods defined on the Chars proxy see ActiveSupport::Multibyte::Chars. For
|
|
38
|
-
# information about how to change the default Multibyte
|
|
38
|
+
# information about how to change the default Multibyte behavior see ActiveSupport::Multibyte.
|
|
39
39
|
def mb_chars
|
|
40
40
|
if ActiveSupport::Multibyte.proxy_class.consumes?(self)
|
|
41
41
|
ActiveSupport::Multibyte.proxy_class.new(self)
|