Creating a DSL: adding random methods

hi -

I'm trying to create a simple DSL, using method missing.

i want to be able to add different event logic for different
instances, defined in their own files.
trivial example:

# eg in fred.rb
event :say do
  "hi this is fred!"
end

# and joe.rb
event :say do
  "joe doesnt say much"
end

so i have a class to implement/create the DSL methods:

  def event evt, &block
    puts "event: #{evt} , #{event}"
    str = "
      def #{evt}
        #{block}
      end
    "
    puts str
    self.class.class_eval(str)
  end

after loading the individual fred.rb file in
class Brain
  def self.load(filename)
    dsl = new
    dsl.instance_eval(File.read(filename))
  end

then when the event XX do is encountered, i am getting:

ArgumentError: ./parser.rb:37:in ‘event’: wrong number of arguments (0
for 1)

# this is the method call
event :say do
   puts ".code here.."
end

# calling this
def event evt, &block

i was expecting "say" to be passed as the evt (method name) and block
to be the code block after do.
perhaps i need to yield something back to the caller?

appreciate any tips on this!

/dc

Basically, I only wanted to say that your subject line sounded very
promising.

def event evt, &block
puts "event: #{evt} , #{event}"

What does this #{event} refer to?

Regards,
Thomas

Hi --

hi -

I'm trying to create a simple DSL, using method missing.

i want to be able to add different event logic for different
instances, defined in their own files.
trivial example:

# eg in fred.rb
event :say do
"hi this is fred!"
end

# and joe.rb
event :say do
"joe doesnt say much"
end

so i have a class to implement/create the DSL methods:

def event evt, &block
   puts "event: #{evt} , #{event}"

Right there is where you seem to be calling event without an argument
(inside the string interpolation). I suspect that's where you're
getting the "Wrong number of arguments" error.

   str = "
     def #{evt}
       #{block}
     end
   "
   puts str
   self.class.class_eval(str)
end

after loading the individual fred.rb file in
class Brain
def self.load(filename)
   dsl = new
   dsl.instance_eval(File.read(filename))
end

then when the event XX do is encountered, i am getting:

ArgumentError: ./parser.rb:37:in ‘event’: wrong number of arguments (0
for 1)

# this is the method call
event :say do
  puts ".code here.."
end

# calling this
def event evt, &block

i was expecting "say" to be passed as the evt (method name) and block
to be the code block after do.
perhaps i need to yield something back to the caller?

appreciate any tips on this!

You can't use a string representation of a block as code. Instead,
you'd want to do something like this:

def event(evt, &block)
   (class << self; self; end).class_eval do
     define_method(evt, &block)
   end
end

so that you can get the local variable evt and the block into the
method definition. (This isn't a complete example but it might point
you in a useful direction.)

David

···

On Sun, 7 Dec 2008, dc wrote:

--
Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS (Jan 12-15), Fort Lauderdale, FL
See http://www.rubypal.com for details
Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2\)

Based on what I'm seeing here, it looks as though you may want something
like the publisher library.

http://atomicobjectrb.rubyforge.org/publisher/

Not quite sure how to answer your question though. HTH
/Shawn

···

On Sun, Dec 7, 2008 at 8:08 AM, Tom Link <micathom@gmail.com> wrote:

Basically, I only wanted to say that your subject line sounded very
promising.

> def event evt, &block
> puts "event: #{evt} , #{event}"

What does this #{event} refer to?

Regards,
Thomas