Added delegation support to Module that allows multiple delegations at once...

Added delegation support to Module that allows multiple delegations at once (unlike Forwardable in the stdlib) [DHH]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3535 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
上级 5cbc062c
*SVN*
* Added delegation support to Module that allows multiple delegations at once (unlike Forwardable in the stdlib) [DHH]. Example:
class Account < ActiveRecord::Base
has_one :subscription
delegate :free?, :paying?, :to => :subscription
delegate :overdue?, :to => "subscription.last_payment"
end
account.free? # => account.subscription.free?
account.overdue? # => account.subscription.last_payment.overdue?
* Fix Reloadable to handle the case where a class that has been 'removed' has not yet been garbage collected. [Nicholas Seckar]
* Don't allow Reloadable to be included into Modules.
......
require File.dirname(__FILE__) + '/module/inclusion'
require File.dirname(__FILE__) + '/module/attribute_accessors'
\ No newline at end of file
require File.dirname(__FILE__) + '/module/attribute_accessors'
require File.dirname(__FILE__) + '/module/delegation'
\ No newline at end of file
class Module
def delegate(*methods)
options = methods.pop
unless options.is_a?(Hash) && to = options[:to]
raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key"
end
methods.each do |method|
module_eval(<<-EOS, "(__DELEGATION__)", 1)
def #{method}(*args, &block)
#{to}.__send__(#{method.inspect}, *args, &block)
end
EOS
end
end
end
\ No newline at end of file
......@@ -26,6 +26,34 @@ class Cd
class De
end
Somewhere = Struct.new(:street, :city)
Someone = Struct.new(:name, :place) do
delegate :street, :city, :to => :place
delegate :state, :to => :@place
delegate :upcase, :to => "place.city"
end
class Name
delegate :upcase, :to => :@full_name
def initialize(first, last)
@full_name = "#{first} #{last}"
end
end
$nowhere = <<-EOF
class Name
delegate :nowhere
end
EOF
$noplace = <<-EOF
class Name
delegate :noplace, :tos => :hollywood
end
EOF
class ModuleTest < Test::Unit::TestCase
def test_included_in_classes
assert One.included_in_classes.include?(Ab)
......@@ -34,4 +62,24 @@ def test_included_in_classes
assert !One.included_in_classes.include?(De)
end
def test_delegation_to_methods
david = Someone.new("David", Somewhere.new("Paulina", "Chicago"))
assert_equal "Paulina", david.street
assert_equal "Chicago", david.city
end
def test_delegation_down_hierarchy
david = Someone.new("David", Somewhere.new("Paulina", "Chicago"))
assert_equal "CHICAGO", david.upcase
end
def test_delegation_to_instance_variable
david = Name.new("David", "Hansson")
assert_equal "DAVID HANSSON", david.upcase
end
def test_missing_delegation_target
assert_raises(ArgumentError) { eval($nowhere) }
assert_raises(ArgumentError) { eval($noplace) }
end
end
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册