diff options
author | David Heinemeier Hansson <david@loudthinking.com> | 2006-02-04 19:14:53 +0000 |
---|---|---|
committer | David Heinemeier Hansson <david@loudthinking.com> | 2006-02-04 19:14:53 +0000 |
commit | 2ee6229bd8cf3a87ede0cd8b573e3faf5a15dbfa (patch) | |
tree | 6448472533f1bc97162e3d498281a306030a932a /activesupport | |
parent | 5cbc062c8ad82271de11ae245d2bdaeffc0c4da7 (diff) | |
download | rails-2ee6229bd8cf3a87ede0cd8b573e3faf5a15dbfa.tar.gz rails-2ee6229bd8cf3a87ede0cd8b573e3faf5a15dbfa.tar.bz2 rails-2ee6229bd8cf3a87ede0cd8b573e3faf5a15dbfa.zip |
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
Diffstat (limited to 'activesupport')
-rw-r--r-- | activesupport/CHANGELOG | 11 | ||||
-rw-r--r-- | activesupport/lib/active_support/core_ext/module.rb | 3 | ||||
-rw-r--r-- | activesupport/lib/active_support/core_ext/module/delegation.rb | 16 | ||||
-rw-r--r-- | activesupport/test/core_ext/module_test.rb | 48 |
4 files changed, 77 insertions, 1 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 4b6c3096d3..36972ab8dd 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,16 @@ *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. diff --git a/activesupport/lib/active_support/core_ext/module.rb b/activesupport/lib/active_support/core_ext/module.rb index 0f46631e65..bd6d62468a 100644 --- a/activesupport/lib/active_support/core_ext/module.rb +++ b/activesupport/lib/active_support/core_ext/module.rb @@ -1,2 +1,3 @@ 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 diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb new file mode 100644 index 0000000000..95173007ca --- /dev/null +++ b/activesupport/lib/active_support/core_ext/module/delegation.rb @@ -0,0 +1,16 @@ +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 diff --git a/activesupport/test/core_ext/module_test.rb b/activesupport/test/core_ext/module_test.rb index d6ea595ae2..464196a0ec 100644 --- a/activesupport/test/core_ext/module_test.rb +++ b/activesupport/test/core_ext/module_test.rb @@ -26,6 +26,34 @@ end 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 @@ class ModuleTest < Test::Unit::TestCase 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 |