This is a multi-part message in MIME format.
--------------040404030007060607000403
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

gabriele renzi wrote:


> I need to write a sw in ruby that would allow people
> adding plug-in/modules
> to handle some event driven functions.
> I can think of two ways of doing this:


> -create a Plugin class, with  methods that won't do
> nothing 

This is not necessary in Ruby

> (actually, I suppose this could be a mix-in)
No, you don't even need a mix-in for that.


> I suppose this should work, but it seems that the last
> step is too long and complex, and
> anyway this approach would end calling  a lot of null
> methods in any Plugin.

This is true : suboptimal.
> After all this raving I come to the question:
> is there some Rubish Right Way (TM) to write  SW with
> plug-in support?

I think I have an extremely simple but useful callback-mechanism,
I send it in an attachment.

Usage :

You define a callback stack (instance of of CallbackStack)
for each of your event.

Your plugins can register a callback by calling the register
method with some block (The block will be executed if the
corresponding event occurs.)

Your application calls the call method of its callback stack
if the specified event occures.

That's all.

--------------040404030007060607000403
Content-Type: text/plain;
 name="callbacks.rb"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="callbacks.rb"

#!/usr/bin/env ruby

class CallbackStack
  def initialize
    @table = {}
    @id    = 0
  end
  
  # You should give your callback a unique name (id) 
  # if you want to delete or overwrite it!
  # The stack returns a unique id if you don't specify any (nil).
  def add(proc=nil,id=nil)
    if id 
      if proc
        @table[id] = proc
        id
      else
        @table.delete(id)
      end
    else
      if !proc
        @table.clear
        nil
      else
        @id+=1 while @table[@id]
        @table[@id] = proc
        @id
      end
    end
  end
  
  def call(*x)
    for id,proc in @table
      proc.call(*x) 
    end
  end
  
  def register(&block)
    add(block)
  end
  
  # call it now + register
  def always(&block)
    block.call(self)
    add(block)
  end
end


--------------040404030007060607000403--