From 1cd93f1cdfbe6f7e71b05b3f8e707f21d70e94ba Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Sat, 11 May 2019 16:32:00 -0700 Subject: [PATCH] Allow DelegateClass() to module_eval given block Methods that return classes often module_eval the given block (e.g. Class.new and Struct.new). This allows DelegateClass to work similarly. This makes it easier to use DelegateClass directly without subclassing, so as not to create an unnecessary subclass. Implements [Feature #15842] --- NEWS | 5 +++++ lib/delegate.rb | 11 ++++++++++- test/test_delegate.rb | 7 +++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 89ed64ce4b..9aa94cd4e9 100644 --- a/NEWS +++ b/NEWS @@ -118,6 +118,11 @@ Date:: new Japanese era as an informal extension, until the new JIS X 0301 is issued. [Feature #15742] +Delegate:: + + * Object#DelegateClass accepts a block and module_evals it in the context + of the returned class, similar to Class.new and Struct.new. + ERB:: * Prohibit marshaling ERB instance. diff --git a/lib/delegate.rb b/lib/delegate.rb index 9f8ef9d5ad..859cc2ed84 100644 --- a/lib/delegate.rb +++ b/lib/delegate.rb @@ -360,6 +360,14 @@ end # end # end # +# or: +# +# MyClass = DelegateClass(ClassToDelegateTo) do # Step 1 +# def initialize +# super(obj_of_ClassToDelegateTo) # Step 2 +# end +# end +# # Here's a sample of use from Tempfile which is really a File object with a # few special rules about storage location and when the File should be # deleted. That makes for an almost textbook perfect example of how to use @@ -383,7 +391,7 @@ end # # ... # end # -def DelegateClass(superclass) +def DelegateClass(superclass, &block) klass = Class.new(Delegator) methods = superclass.instance_methods methods -= ::Delegator.public_api @@ -410,5 +418,6 @@ def DelegateClass(superclass) klass.define_singleton_method :protected_instance_methods do |all=true| super(all) | superclass.protected_instance_methods end + klass.module_eval(&block) if block return klass end diff --git a/test/test_delegate.rb b/test/test_delegate.rb index ffc4d9527e..8ed3342afa 100644 --- a/test/test_delegate.rb +++ b/test/test_delegate.rb @@ -22,6 +22,13 @@ class TestDelegateClass < Test::Unit::TestCase assert_equal(:m, obj.m, "[ruby-dev:33116]") end + def test_delegate_class_block + klass = DelegateClass(Array) do + alias foo first + end + assert_equal(1, klass.new([1]).foo) + end + def test_systemcallerror_eq e = SystemCallError.new(0) assert((SimpleDelegator.new(e) == e) == (e == SimpleDelegator.new(e)), "[ruby-dev:34808]")