aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2019-05-11 16:32:00 -0700
committerJeremy Evans <code@jeremyevans.net>2019-05-30 18:34:45 -0700
commit1cd93f1cdfbe6f7e71b05b3f8e707f21d70e94ba (patch)
treea1741805f80749f90f35d21f0f646148b41dd610
parent856593cc4972562d2ab0a59a61f38fe3a4a863ab (diff)
downloadruby-1cd93f1cdfbe6f7e71b05b3f8e707f21d70e94ba.tar.gz
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]
-rw-r--r--NEWS5
-rw-r--r--lib/delegate.rb11
-rw-r--r--test/test_delegate.rb7
3 files changed, 22 insertions, 1 deletions
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]")