[Rubygems-developers] RubyGems Dependency Type

Susan Potter me at susanpotter.net
Wed Jan 30 13:32:52 EST 2008


Back in November on this list there was a discussion skirting around a
feature I have been forced to work-around for my enterprise client.
My work-around is a separate Gem and only allows my solution to work
on our internal systems because it is installed everywhere RubyGems
is.  It uses Ruby's ability to extend/reopen RubyGem classes to append
properties/methods to it, specifically the Gem::Specification and
Gem::Dependency classes as well as the CLI functionality.

The thread I refer to was titled: What is right and wrong with
dependencies definitions?

The thread discussion was initiated by someone named Luis (I think),
but below I quote Eric Hodel and Chad Woolley to provide people a
refresher or background to the uninitiated (see below the ---- line).

While I think Chad Woolley's GemInstaller is useful in some
situations, the problem I am trying to solve is to describe the kind
of dependency a gem is for a project.  For example, it is not right to
say that rspec will only ever be a test dependency, since it would be
needed by any rspec extensions at runtime, not just at test time.  I
am also not personally bowled over with the idea of starting a server
to establish whether I need to install further dependencies.  The
reason for this is the separation of work roles that generally exist
in the server-side environment (system administrator,
deployer/developer, etc.).

I would rather these concerns were taken care of at gem install time.
I see GemInstaller's purpose more useful for one-off scripts or UI
based applications rather than server-side applications.  Server-side
software is primarily my domain, so please keep that in mind.

The following is the scheme I used at my client (but with a few
client-specific things thrown in that I will not discuss here as they
aren't relevant for solving *this* particular problem):
* each dependency when defined has a "type".  I have used the types
(with some modifications) that Maven allows developers to define.
Yes, yes, I know the Ruby world is infinitely better than the Java
world, but Maven (which happens to be in the Java world) has actually
found a plausible solution in my view.  Maven's dependency types are:
compile (default), provided (for JEE contained apps), test.  I have
personally used the following types for Ruby to make more sense for
our world: runtime (default), compile (for Ruby/C extension purposes),
* on "gem install" (unless otherwise told) the runtime dependencies
are installed only.  I added a flag to the gem CLI (again through
extension).  Of course, this again only works in our internal, fully
controlled system.

Here is my proposal open to feedback since my background is primarily
in the server-side enterprise space (I am directly answering Eric
Hodel's questions from below):
* should developer dependencies by installed by default?
>> No
* what does the command-line option look like?
>> gem install -Dall or gem install -Dtest or gem install -Dcompile
>> test installs runtime AND test dependencies.  compile installs
runtime AND compile dependencies.  all installs all three: runtime,
compile and test.
* what happens on uninstall?
>> ???  The client implementation I have currently only uninstalls the
given gem(s), but this needs further thinking as I realize this is not
* what should `gem check` do if all dependencies aren't installed?
>> in my proposed implementation I have found it useful to only check
runtime by default, but if -D is specified it will check those as per
the CLI option noted above.

To be honest, I think the thing that matters most is that RubyGems
provides a way to describe this metadata and then we can worry about
tools and facilities to wrap around this later.  If people do not want
to set the extra dependency type, that is fine, we default it to
runtime and Gem developers aren't any worse off than they are now.

If you want to do extra things based on RAILS_ENV or MERB_ENV or
another environmental setting you can do so with something like
GemInstaller or another RubyGems "extension".  In fact, I think simply
adding the metadata property of Gem::Dependency#type (ok, we use #kind
because of #type history) to RubyGems gives greater flexibility rather
than only providing one facility (e.g. GemInstaller, that you
essentially have to be married to).  We can even defer how people
handle installing using these dependency types to third party Gems
instead of involving RubyGems in that business.

I am willing and able (with about 3-5 hours a week to commit to open
source contributions across the board) to do most of the grunt work
and submit a patch for RubyGems project to do the capturing of the
metadata and change the gem CLI behavior depending on accepted
proposal.  Unfortunately I cannot just open source the client work I
have already done since it is considered proprietary.

Thanks for listening,
Previous thread on this mailing list...
Thread: What is right and wrong with dependencies definitions?
Month: November 2007

From: drbrain at segment7.net (Eric Hodel)
Date: Fri, 9 Nov 2007 14:47:51 -0800

Things that need to be discussed are:
* should developer dependencies by installed by default?
* what does the command-line option look like?
* what happens on uninstall?
* what should `gem check` do if all dependencies aren't installed?

Before attempting a patch, I think at least these questions should be
answered.  There are probably more, since getting it to work well
requires changes and hooks in lots of places.

Its really easy to say "gems should have developer dependencies".
Its a lot of work to make it a reality.

From: thewoolleyman at gmail.com (Chad Woolley)
Date: Fri, 9 Nov 2007 17:08:30 -0700

Regardless, there are valid points on both sides.  If building this
support into RubyGems really is too hard (and I believe you), then we
need alternate approaches.

Ok, pimp-mode on: I think that my GemInstaller tool
(http://geminstaller.rubyforge.org) is perfect for this - it centrally
manaages all your dependencies via an erb-parsed file (or files).
This allows you to explicitly manage your dependencies, and have them
behave differently based on whatever criteria you want - RAILS_ENV,
hostname, environment variables, whatever.  If you have a startup
check in your app that installs and loads the appropriate gems in
development or test mode (rake or test_helper), then you can only
include actual runtime dependencies in your gem, but ensure that
anyone who wants to build/test your app still has the gems they need.

From: drbrain at segment7.net (Eric Hodel)
Date: Fri, 9 Nov 2007 17:33:08 -0800

> I agree that this will probably be really hard to implement in
> rubygems, and I'll believe you that it's not worth it.  However,
> there's still valid reasons for both sides of the argument.

I'm not saying its not worth doing, but it's much, much easier said
than done.

mailto:me at susanpotter.net

More information about the Rubygems-developers mailing list