Easy to create an enumerator
When creating methods that yield
, sometimes we want it to return Enumerator
if no block is specified. The recommended way is mostly return to_enum(:name_of_method, [args]) unless block_given?
. However, it is a pain to be recruited for every method that does it. Ruby was ruby, I decided to create a method make_enum
similar to attr_accessor
which does this for me:
class Module # Put this in a mixin, but for the purposes of this experiment, it in Module
def make_enum *args
args.each do |name|
old_method = instance_method(name)
define_method(name) do |*args, &block|
next to_enum(name, *args) unless block
old_method.bind(self).call(*args, &block)
end
end
end
end
Now I can use it like this:
class Test
def test
yield 1
yield 2
end
make_enum :test
end
t = Test.new
t.test { |n| puts n }
# 1
# 2
t.test.to_a #=> [1, 2]
And it works! But it doesn't work if make_enum
before the method is defined.
How can I get this method to work before the method is defined so that the following will work? Perhaps I need to use method_added
?
class Test
make_enum :test
def test
yield 1
yield 2
end
end
I don't know if it was a bad idea for this before the method, but my reason for thinking it would be good to do this is because it better matches the way we use attr_accessor
and the like.
source to share
While the methods attr_
create instance methods again, yours is make_enum
modifying the existing method, which is quite similar to methods protected
, private
and public
. Note that these visibility methods are used either in the form:
protected
def foo; ... end
or
protected def foo; ... end
or
def foo; ... end
protected :foo
The last two methods are already available with yours make_enum
. In particular, the second form is already possible (which is also noted by Stefan in the commentary). You can do:
make_enum def test; ... end
If you want to make the first shape, you should try to implement it in your definition make_enum
.
source to share