[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

loading "plugins"

Hans Fugal

3/25/2005 6:26:00 PM

I am writing a log analyzer (hans.fugal.net/src/clog) that uses a sort
of plugin (I call them agents) which is basically a class that gets
instantiated and then called to do work. I want to include various
agents with the distribution.

Where should the files end up? How should I discover the agents?

The sysadmin will be able to specify a directory (or directories) that
contain his own agents, in addition to the included agents. I can scan
that directory for .rb files and load them. That part works. But I don't
want to make the sysadmin specify where the standard agents are in the
config file - that should be implied. "require 'clog/agents/*'" would
express what I want to do, although that isn't valid. I don't want to
hardcode a path to /usr/local/lib/site_ruby/whatever, either.

Ultimately, the sysadmin should refer to the agents with a simple
one-word name, e.g. Postfix or Bogofilter.

I don't know if my question makes sense, but I'm wondering what you all
would do because there is no obvious best way to do this to me at the
moment.

(and yes, I know IoC or DI would fit here but I don't want to put the
burden of figuring out what the heck those are on the poor sysadmin who
just needs to specify what agent to use)
7 Answers

Patrick Hurley

3/25/2005 6:46:00 PM

0

On Sat, 26 Mar 2005 03:29:50 +0900, Hans Fugal <fugalh@xmission.com> wrote:
> I am writing a log analyzer (hans.fugal.net/src/clog) that uses a sort
> of plugin (I call them agents) which is basically a class that gets
> instantiated and then called to do work. I want to include various
> agents with the distribution.
>
> Where should the files end up? How should I discover the agents?
>
> The sysadmin will be able to specify a directory (or directories) that
> contain his own agents, in addition to the included agents. I can scan
> that directory for .rb files and load them. That part works. But I don't
> want to make the sysadmin specify where the standard agents are in the
> config file - that should be implied. "require 'clog/agents/*'" would
> express what I want to do, although that isn't valid. I don't want to
> hardcode a path to /usr/local/lib/site_ruby/whatever, either.
>
> Ultimately, the sysadmin should refer to the agents with a simple
> one-word name, e.g. Postfix or Bogofilter.
>
> I don't know if my question makes sense, but I'm wondering what you all
> would do because there is no obvious best way to do this to me at the
> moment.
>
> (and yes, I know IoC or DI would fit here but I don't want to put the
> burden of figuring out what the heck those are on the poor sysadmin who
> just needs to specify what agent to use)
>
>

What is wrong with something like:

base = "."
Dir.glob("#{base}/*.rb").each { |plugin|
require plugin
}

where you can obviously set base to anything you want.

Patrick


Shajith

3/25/2005 6:46:00 PM

0

Hi!

On Sat, 26 Mar 2005 03:29:50 +0900, Hans Fugal <fugalh@xmission.com> wrote:
> I am writing a log analyzer (hans.fugal.net/src/clog) that uses a sort
> of plugin (I call them agents) which is basically a class that gets
> instantiated and then called to do work.

I'm not sure if it fits the bill, but take a look at FreeBASE[1]. It
is part of the FreeRIDE[2] project, and also available as an
independent library(though I could not find a working download link
for just that upon basic googling)

HTH!
Shajith

1: http://freeride.rubyforge.org/wiki/wiki.p...
2: http://freeride.rubyforge.org/wi...


Patrick Hurley

3/25/2005 7:04:00 PM

0

Oops I realized you might want to "discover" what classes you loaded
so something like this might be closer:

before_classes = []
ObjectSpace.each_object(Class) { |obj| before_classes << obj }

base= "."
Dir.glob("#{base}/*.rb").each { |plugin| require plugin }

new_classes = []
ObjectSpace.each_object(Class) { |obj|
new_classes << obj unless before_classes.include?(obj)
}


And then you can further check the loaded classes (in new_classes
array) by using the respond_to? method (check to see if it is a Duck
:-)

Patrick


Bill Atkins

3/25/2005 7:14:00 PM

0

That's a little heavy on memory (and time). Alternatively, you could do

class Object
# Object.inherited callback
def Object.inherited new_class
return unless @@classes
@@classes << new_class
end

def self.start_log
@@classes = []
end

def self.end_log
res = @@classes
@@classes = nil
res
end
end

Object.start_log
# require all plugins here
new_classes = Object.end_log

Bill

On Sat, 26 Mar 2005 04:03:48 +0900, Patrick Hurley <phurley@gmail.com> wrote:
> Oops I realized you might want to "discover" what classes you loaded
> so something like this might be closer:
>
> before_classes = []
> ObjectSpace.each_object(Class) { |obj| before_classes << obj }
>
> base= "."
> Dir.glob("#{base}/*.rb").each { |plugin| require plugin }
>
> new_classes = []
> ObjectSpace.each_object(Class) { |obj|
> new_classes << obj unless before_classes.include?(obj)
> }
>
> And then you can further check the loaded classes (in new_classes
> array) by using the respond_to? method (check to see if it is a Duck
> :-)
>
> Patrick
>
>


--
$stdout.sync = true
"Just another Ruby hacker.".each_byte do |b|
('a'..'z').step do|c|print c+"\b";sleep 0.007 end;print b.chr
end; print "\n"


Curt Hibbs

3/25/2005 7:56:00 PM

0

Shajith wrote:
> Hi!
>
> On Sat, 26 Mar 2005 03:29:50 +0900, Hans Fugal <fugalh@xmission.com> wrote:
>
>>I am writing a log analyzer (hans.fugal.net/src/clog) that uses a sort
>>of plugin (I call them agents) which is basically a class that gets
>>instantiated and then called to do work.
>
>
> I'm not sure if it fits the bill, but take a look at FreeBASE[1]. It
> is part of the FreeRIDE[2] project, and also available as an
> independent library(though I could not find a working download link
> for just that upon basic googling)
>
> HTH!
> Shajith
>
> 1: http://freeride.rubyforge.org/wiki/wiki.p...
> 2: http://freeride.rubyforge.org/wi...

FreeBASE is probably overkill for this.

Curt


Hans Fugal

3/25/2005 8:09:00 PM

0

Patrick Hurley wrote:
> Oops I realized you might want to "discover" what classes you loaded
> so something like this might be closer:
>
> before_classes = []
> ObjectSpace.each_object(Class) { |obj| before_classes << obj }
>
> base= "."
> Dir.glob("#{base}/*.rb").each { |plugin| require plugin }
>
> new_classes = []
> ObjectSpace.each_object(Class) { |obj|
> new_classes << obj unless before_classes.include?(obj)
> }
>
>
> And then you can further check the loaded classes (in new_classes
> array) by using the respond_to? method (check to see if it is a Duck
> :-)
>
> Patrick
>
>

Thanks for the ideas, but the question isn't so much about mechanics as
about design. Should the agents reside in /usr/local/lib/site_ruby/...
or should they reside in /usr/local/share/clog and how do I make that
directory configurable at installation time or auto-discover it.

Aredridel

3/26/2005 12:47:00 AM

0

On Sat, 26 Mar 2005 03:29:50 +0900, Hans Fugal <fugalh@xmission.com> wrote:
> I am writing a log analyzer (hans.fugal.net/src/clog) that uses a sort
> of plugin (I call them agents) which is basically a class that gets
> instantiated and then called to do work. I want to include various
> agents with the distribution.
>
> Where should the files end up? How should I discover the agents?
>
> The sysadmin will be able to specify a directory (or directories) that
> contain his own agents, in addition to the included agents. I can scan
> that directory for .rb files and load them. That part works. But I don't
> want to make the sysadmin specify where the standard agents are in the
> config file - that should be implied. "require 'clog/agents/*'" would
> express what I want to do, although that isn't valid. I don't want to
> hardcode a path to /usr/local/lib/site_ruby/whatever, either.
>
> Ultimately, the sysadmin should refer to the agents with a simple
> one-word name, e.g. Postfix or Bogofilter.
>

The unix way would be to have /usr/share/yourapp/plugins/FooClass.rb
be the FooClass plugin, and perhaps optionally also search a user's
home directory, ~/.yourapp/plugins/FooClass.rb

Simple, concise, understandable and scalable.