Hi, 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), test. * 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 optimum. * 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, Susan ----- 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:[EMAIL PROTECTED] www:http://susanpotter.net blog:http://snakesgemscoffee.susanpotter.net linkedin:http://linkedin.com/in/susanpotter _______________________________________________ Rubygems-developers mailing list Rubygems-developers@rubyforge.org http://rubyforge.org/mailman/listinfo/rubygems-developers