Define_method and blocks

I'm trying to programmatically add methods taking a block to a class.
Specifically I'm trying to write a method 'define_inline_element' that
will let me type

  define_inline_element :title

and create a method called 'title' in my class, with appropriate
behavior, taking a block.

My first stab was this:

  def self.define_inline_element(element)
    define_method(element) do |&block|
      inline_element(element.to_s, &block)
    end
  end

but |&block| was syntactically invalid. Then I tried this:

  def self.define_inline_element(element)
    define_method(element) do
      inline_element(element.to_s) { yield }
    end
  end

but when I invoked one of my generated methods with a block, the block
got thrown away and the yield call failed.

So now I've resorted to eval:

  def self.define_inline_element(element)
    module_eval %Q{def #{element}(&block)
                     inline_element("#{element}", &block)
                   end}
  end

which works, but I don't like eval as much as blocks.

Anything I'm missing? I'm using Ruby 1.8.2, if that matters. (Yes, I
know I'm a few versions behind.)

David Carlton
carlton@bactrian.org

You're not really missing anything. This is an unfortunate oversight that's
been fixed in 1.9

meth { |&block| } is valid syntax in 1.9

···

On 7/21/07, David Carlton <carlton@bactrian.org> wrote:

I'm trying to programmatically add methods taking a block to a class.
Specifically I'm trying to write a method 'define_inline_element' that
will let me type

  define_inline_element :title

and create a method called 'title' in my class, with appropriate
behavior, taking a block.

My first stab was this:

  def self.define_inline_element(element)
    define_method(element) do |&block|
      inline_element(element.to_s, &block)
    end
  end

but |&block| was syntactically invalid. Then I tried this:

  def self.define_inline_element(element)
    define_method(element) do
      inline_element(element.to_s) { yield }
    end
  end

but when I invoked one of my generated methods with a block, the block
got thrown away and the yield call failed.

So now I've resorted to eval:

  def self.define_inline_element(element)
    module_eval %Q{def #{element}(&block)
                     inline_element("#{element}", &block)
                   end}
  end

which works, but I don't like eval as much as blocks.

Anything I'm missing? I'm using Ruby 1.8.2, if that matters. (Yes, I
know I'm a few versions behind.)

David Carlton
carlton@bactrian.org