Add :allow_nil option to delegate [#1127 state:resolved]

Signed-off-by: Pratik Naik <pratiknaik@gmail.com>
This commit is contained in:
Sergio Gil 2008-12-08 00:53:38 +01:00 committed by Pratik Naik
parent f7bd0beb67
commit e8de7a67a5
3 changed files with 56 additions and 1 deletions

@ -1,5 +1,7 @@
*2.3.0 [Edge]*
* Add :allow_nil option to delegate. #1127 [Sergio Gil]
* Add Benchmark.ms convenience method to benchmark realtime in milliseconds. [Jeremy Kemper]
* Updated included memcache-client to the 1.5.0.5 version which includes fixes from fiveruns and 37signals to deal with failover and timeouts #1535 [Joshua Sierles]

@ -72,6 +72,30 @@ class Module
# invoice.customer_name # => "John Doe"
# invoice.customer_address # => "Vimmersvej 13"
#
# If the object to which you delegate can be nil, you may want to use the
# :allow_nil option. In that case, it returns nil instead of raising a
# NoMethodError exception:
#
# class Foo
# attr_accessor :bar
# def initialize(bar = nil)
# @bar = bar
# end
# delegate :zoo, :to => :bar
# end
#
# Foo.new.zoo # raises NoMethodError exception (you called nil.zoo)
#
# class Foo
# attr_accessor :bar
# def initialize(bar = nil)
# @bar = bar
# end
# delegate :zoo, :to => :bar, :allow_nil => true
# end
#
# Foo.new.zoo # returns nil
#
def delegate(*methods)
options = methods.pop
unless options.is_a?(Hash) && to = options[:to]
@ -84,10 +108,12 @@ def delegate(*methods)
prefix = options[:prefix] && "#{options[:prefix] == true ? to : options[:prefix]}_"
allow_nil = options[:allow_nil] && "#{to} && "
methods.each do |method|
module_eval(<<-EOS, "(__DELEGATION__)", 1)
def #{prefix}#{method}(*args, &block)
#{to}.__send__(#{method.inspect}, *args, &block)
#{allow_nil}#{to}.__send__(#{method.inspect}, *args, &block)
end
EOS
end

@ -41,6 +41,10 @@ class De
delegate :street, :city, :name, :to => :client, :prefix => :customer
end
Project = Struct.new(:description, :person) do
delegate :name, :to => :person, :allow_nil => true
end
class Name
delegate :upcase, :to => :@full_name
@ -117,6 +121,29 @@ def initialize(client)
end
end
def test_delegation_with_allow_nil
rails = Project.new("Rails", Someone.new("David"))
assert_equal rails.name, "David"
end
def test_delegation_with_allow_nil_and_nil_value
rails = Project.new("Rails")
assert_nil rails.name
end
def test_delegation_with_allow_nil_and_nil_value_and_prefix
Project.class_eval do
delegate :name, :to => :person, :allow_nil => true, :prefix => true
end
rails = Project.new("Rails")
assert_nil rails.person_name
end
def test_delegation_without_allow_nil_and_nil_value
david = Someone.new("David")
assert_raises(NoMethodError) { david.street }
end
def test_parent
assert_equal Yz::Zy, Yz::Zy::Cd.parent
assert_equal Yz, Yz::Zy.parent