limitations of passing a block to class_eval

One shortcoming of define_method is that it does not allow you to specify a method body that expects a block. If you need to dynamically create a method that accepts a block, you will need to use the def statement within class_eval. Here's a trivial example:

class Module   def acts_as_thing(name, &block)     self.class_eval {       define_method(name, &block)     }   end end

class Thing   #using define_method does not allow us to specify a method body that expects a block, because the block used in define method becomes the method body itself, not a block passed to a method body.   acts_as_thing :animals do     puts "animal group"   end

  def initialize(name)     @name = name   end end

#To address the limitations of define_method, that is, to dynamically create a method that accepts a block, we need to use the def statement with class_eval. Thing.class_eval {   def spell_out_name     yield @name   end }

thing = Thing.new("dog") thing.animals # => animal group thing.spell_out_name {|name| puts "The name is #{name}."} # => The name is dog.

Here's my question. I am reading a book called The Ruby Programming Language. It says the following:

"If the method you are creating is sufficiently dynamic, you may not be able to pass a block to class_eval and will instead have to specify the method definition as a string to be evaluated."

I'm not sure what they are talking about here. What does it mean by "sufficiently dynamic"? In my example above, I proved that a method defined within the context of class_eval can accept a block.

Why are you using define_method inside of class eval again? That set aside I hope you are not learning Ruby on 1.8.7 because that would defeat the purpose of learning Ruby, since 1.8.7 is pretty much dead and 1.9.3 is where you should start, since hopefully no company will ever ask you to do Ruby on 1.8.7 that said, ruby does in-fact support blocks in define_method see:

class MyClass   define_method(:my_method1) do |&block|     if !block       raise "No block given"     end

    block.call   end end

MyClass.new.my_method1 do   $stdout.puts "Hello World" end