[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

[ANN] GemPlugin 0.1 -- A Mongrel Spinoff

Zed A. Shaw

3/6/2006 6:23:00 AM

Hello folks,

Well I spent the weekend working on the Mongrel
(http://mongrel.rub...) plugin system, and actually ended up cracking
it out into a separate sub-project and releasing it under Ruby or LGPL.

The GemPlugin project is a dynamic plugin system that uses RubyGems to
create, manage, and load plugins. It's used in Mongrel to allow others to
create commands for people to use without having to be a part of the Mongrel
project. Other systems could use it no problem and it doesn't depend on any
Mongrel code.

The stuff is kind of funky, but take a look at:

http://mongrel.rub.../gem_plugin_rdoc/

For more information.

== Quick Usage

Plugin Authors do this:

class Snazzy < GemPlugin::Plugin "/commands"
...
end

Then place this code in a file they will have RubyGems autorequire (I use
lib/init.rb).

Next they need to add the following to whatever Rakefile code you use to
create your gem:

spec.add_dependency('gem_plugin', '>= 0.1')
spec.add_dependency('theapp', '>= 0.1')
spec.autorequire = 'init.rb'


Plugin Users do this:

$ gem install snazzy_plugin


System Implementers then setup their system to do this:

GemPlugin::Manager.instance.load "theapp" => GemPlugin::INCLUDE
plug = GemPlugin::Manager.instance.create("/commands/snazzy")

And everyone is happy. Read the docs for more information.

== Future Directions

There is already a sample plugin available named mongrel_status which people
can check out as an example:

http://rubyforge.org/frs/download.php/9029/mongrel_stat...

Or just:

$ gem install mongrel_status

Enjoy! And feedback is welcome.

Zed A. Shaw
http://www.ze...




8 Answers

Austin Ziegler

3/6/2006 1:21:00 PM

0

On 3/6/06, Zed Shaw <zedshaw@zedshaw.com> wrote:Hey, Zed. this looks pretty interesting. Just a few points that I thinkwill require a pretty quick rework:> == Quick Usage>> Plugin Authors do this:>> class Snazzy < GemPlugin::Plugin "/commands"> ...> end>> Then place this code in a file they will have RubyGems autorequire (I> use lib/init.rb).> Next they need to add the following to whatever Rakefile code you use to> create your gem:>> spec.add_dependency('gem_plugin', '>= 0.1')> spec.add_dependency('theapp', '>= 0.1')> spec.autorequire = 'init.rb'The #autorequire is deprecated at this point and is not recommended inany way. RubyGems still supports it, but I believe that the next versionwill be spouting some warnings at people who use autorequire in buildingtheir gems. Since you're using a secondary call to do the load, you canmandate that lib/init.rb is the file to load and have your loader do therequire yourself.> System Implementers then setup their system to do this:>> GemPlugin::Manager.instance.load "theapp" => GemPlugin::INCLUDE> plug = GemPlugin::Manager.instance.create("/commands/snazzy")This also seems like you're using Singleton. I think you should be ableto do this such that you can drop the call to Manager.instance if youput your load/create etc. as transparent reflections to an instance. I'mnot sure that I did it in the most optimal way in MIME::Types 1.15 thatI released recently, but I had changed MIME::Types from a module to aclass and implemented it such that it was more or less transparent tothe user. You should be able to do it with: class GemPlugin::Manager class << self private :new def method_missing(m, *a, &b) @__me__ ||= self.new @__me__.__send__(m, *a, &b) end end endThen it would simply become: GemPlugin::Manager.load "theapp" => GemPlugin::INCLUDE plug = GemPlugin::Manager.create("/commands/snazzy")-austin--Austin Ziegler * halostatue@gmail.com * Alternate: austin@halostatue.ca

Zed A. Shaw

3/6/2006 7:00:00 PM

0

On Mon, Mar 06, 2006 at 10:20:38PM +0900, Austin Ziegler wrote:
> On 3/6/06, Zed Shaw <zedshaw@zedshaw.com> wrote:
>
> Hey, Zed. this looks pretty interesting. Just a few points that I think
> will require a pretty quick rework:
>
<snip>
> The #autorequire is deprecated at this point and is not recommended in
> any way. RubyGems still supports it, but I believe that the next version
> will be spouting some warnings at people who use autorequire in building
> their gems. Since you're using a secondary call to do the load, you can
> mandate that lib/init.rb is the file to load and have your loader do the
> require yourself.
>
Man that just sucks. I'll have to think about this, but off the top of
my head doing a require of init.rb won't work. I'll have to __FILE__
crap and re-implement the autorequire code.

Maybe I can chat with the rubygems folks and get it put back in. It
really makes these plugins work perfectly with minimal effort.

> > System Implementers then setup their system to do this:
> >
> > GemPlugin::Manager.instance.load "theapp" => GemPlugin::INCLUDE
> > plug = GemPlugin::Manager.instance.create("/commands/snazzy")
>
> This also seems like you're using Singleton. I think you should be able
> to do this such that you can drop the call to Manager.instance if you
> put your load/create etc. as transparent reflections to an instance. I'm
> not sure that I did it in the most optimal way in MIME::Types 1.15 that
> I released recently, but I had changed MIME::Types from a module to a
> class and implemented it such that it was more or less transparent to
> the user. You should be able to do it with:
>
> class GemPlugin::Manager
> class << self
> private :new
>
> def method_missing(m, *a, &b)
> @__me__ ||= self.new
> @__me__.__send__(m, *a, &b)
> end
> end
> end
>

I'll play with this, I agree that the instance stuff is really annoying.
I also don't like the include/exclude stuff and will probably change
that out for something more succinct.

Zed A. Shaw
http://www.ze...



Mark Volkmann

3/6/2006 7:52:00 PM

0

On 3/6/06, Austin Ziegler <halostatue@gmail.com> wrote:

> > spec.autorequire = 'init.rb'
>
> The #autorequire is deprecated at this point and is not recommended in
> any way. RubyGems still supports it, but I believe that the next version
> will be spouting some warnings at people who use autorequire in building
> their gems. Since you're using a secondary call to do the load, you can
> mandate that lib/init.rb is the file to load and have your loader do the
> require yourself.

Maybe I misunderstood this, but I thought "require_gem {gem-name}"
used the autorequire attribute to know which file from the gem to
load. Is that correct? If so, what will happen to require_gem when
autorequire goes away?

--
R. Mark Volkmann
Partner, Object Computing, Inc.


Jim Weirich

3/6/2006 10:57:00 PM

0

Mark Volkmann wrote:
> On 3/6/06, Austin Ziegler <halostatue@gmail.com> wrote:
>
>> > spec.autorequire = 'init.rb'
>>
>> The #autorequire is deprecated at this point and is not recommended in
>> any way. RubyGems still supports it, but I believe that the next version
>> will be spouting some warnings at people who use autorequire in building
>> their gems. Since you're using a secondary call to do the load, you can
>> mandate that lib/init.rb is the file to load and have your loader do the
>> require yourself.
>
> Maybe I misunderstood this, but I thought "require_gem {gem-name}"
> used the autorequire attribute to know which file from the gem to
> load. Is that correct? If so, what will happen to require_gem when
> autorequire goes away?

The preferred way of requiring files is to use a plain require. Unless
something tricky is going on, this will work with both gem and non-gem
installed software (assuming you load rubygems beforehand if you are
using gem installs).

The require_gem is really only needed if you want a particular version
of gem installed, in which case you just *add* the require_gem statement
in a nice, centrally controlled location in your code (because you don't
want to spread version dependencies throughout your code base), and do
the normal requires.

This is probably with an example:

If you want you use the foo file in the foobar gem, just do whereever
needed in your code base:

require 'foo'

(you may need to require rubygems if your system doesn't make that
automatic).

If you want to make sure you use version 3.1.4 of the gem foobar, then
in one central location put:

require_gem 'foobar', '= 3.1.4'

And whereever you need the foo file, write:

require 'foo'

Require_gem is a mix of two concepts, the specifying of the *gem*
version, and the requiring of a specific (autorequire) file. This
conceptual confusion has caused several subtle bugs in the gems software
over time.

The autorequire feature is a holdever from the days when regular
requires didn't work in rubygems. It avoided the need to do a
require_gem *and* a regular require. Since the regular require is all
that is needed today, autorequire is a holdover from the past.

I haven't looked at Zed's issues in detail yet, so I can't comment on
his use in the pluggin system.

--
-- Jim Weirich

--
Posted via http://www.ruby-....


Mark Volkmann

3/7/2006 11:48:00 AM

0

On 3/6/06, Jim Weirich <jim@weirichhouse.org> wrote:
> Mark Volkmann wrote:
> > On 3/6/06, Austin Ziegler <halostatue@gmail.com> wrote:
> >
> >> > spec.autorequire = 'init.rb'
> >>
> >> The #autorequire is deprecated at this point and is not recommended in
> >> any way. RubyGems still supports it, but I believe that the next version
> >> will be spouting some warnings at people who use autorequire in building
> >> their gems. Since you're using a secondary call to do the load, you can
> >> mandate that lib/init.rb is the file to load and have your loader do the
> >> require yourself.
> >
> > Maybe I misunderstood this, but I thought "require_gem {gem-name}"
> > used the autorequire attribute to know which file from the gem to
> > load. Is that correct? If so, what will happen to require_gem when
> > autorequire goes away?
>
> The preferred way of requiring files is to use a plain require. Unless
> something tricky is going on, this will work with both gem and non-gem
> installed software (assuming you load rubygems beforehand if you are
> using gem installs).
>
> The require_gem is really only needed if you want a particular version
> of gem installed, in which case you just *add* the require_gem statement
> in a nice, centrally controlled location in your code (because you don't
> want to spread version dependencies throughout your code base), and do
> the normal requires.
>
> This is probably with an example:
>
> If you want you use the foo file in the foobar gem, just do whereever
> needed in your code base:
>
> require 'foo'

The problem I have with this is that maybe all I know is that I want
to use the foobar gem in my code. How am I supposed to know that the
main file I should require is foo.rb? Maybe the main file of each gem
should always have the same name as the gem.

--
R. Mark Volkmann
Partner, Object Computing, Inc.


Jim Weirich

3/7/2006 11:09:00 PM

0

Mark Volkmann wrote:
> On 3/6/06, Jim Weirich <jim@weirichhouse.org> wrote:
>> >> require yourself.
>>
>>
>> require 'foo'
>
> The problem I have with this is that maybe all I know is that I want
> to use the foobar gem in my code. How am I supposed to know that the
> main file I should require is foo.rb? Maybe the main file of each gem
> should always have the same name as the gem.

I suggest specifying standard practices when creating plugins. Naming
the main include the same as the gem name is one possiblity. Or naming
the main include "GEMNAME/init.rb". Just pick a standard and make it
the standard for defining plugins.

--
-- Jim Weirich


--
Posted via http://www.ruby-....


Mark Volkmann

3/7/2006 11:27:00 PM

0

On 3/7/06, Jim Weirich <jim@weirichhouse.org> wrote:
> Mark Volkmann wrote:
> > On 3/6/06, Jim Weirich <jim@weirichhouse.org> wrote:
> >> >> require yourself.
> >>
> >>
> >> require 'foo'
> >
> > The problem I have with this is that maybe all I know is that I want
> > to use the foobar gem in my code. How am I supposed to know that the
> > main file I should require is foo.rb? Maybe the main file of each gem
> > should always have the same name as the gem.
>
> I suggest specifying standard practices when creating plugins. Naming
> the main include the same as the gem name is one possiblity. Or naming
> the main include "GEMNAME/init.rb". Just pick a standard and make it
> the standard for defining plugins.

I like your first suggestion best ... main include has the same name as the gem.

Obviously though, for the gems already out there, when autorequire
goes away we'll all have to learn what file we should be requiring.

--
R. Mark Volkmann
Partner, Object Computing, Inc.


Austin Ziegler

3/8/2006 12:13:00 AM

0

On 3/7/06, Mark Volkmann <r.mark.volkmann@gmail.com> wrote:> Obviously though, for the gems already out there, when autorequire> goes away we'll all have to learn what file we should be requiring.Sort of. As far as I know, they're deprecating it and warning oncreation in CVS. It won't affect users any time soon, though. Iwouldn't be surprised if a future version released fails to create agem that specifies an autorequire.As I update my software that I release as gems (far less often than Iwant right now :( I am removing the autorequire.It is my understanding as well that #require_gem itself will bedeprecated in favour of something like #activate_gem.-austin--Austin Ziegler * halostatue@gmail.com * Alternate: austin@halostatue.ca