#8087 Vendor Everything

Just trying to raise some awareness and discussion on a patch I
recently posted.

The idea of freezing gems in your rails app has been around for a long
time. However there is no suggested convention to follow. Chris
Wanstrath has suggested the directory "vendor/gems" to be use in his
post "Vendor Everything" (http://errtheblog.com/post/2120).

Once you set your path to this directory, everything works great.
There is no code difference between loading gems from your local
machine with rubygems or from the "vendor/gems" directory.

If everyone is down with this convention, we should add a few things
in rails to encourage it.

1. Make the "vendor/gems" directory when you run the rails command.
2. Add "vendor/gems" to the load path
3. Load tasks from "vendor/gems" (I don't really use this but Nic
Williams finds it useful)
4. Add some rake tasks to help you freeze gems.

Are there any other techniques out there that work well for you? Or
does this sound like a delicious patch?

Link to the patch: http://dev.rubyonrails.org/ticket/8087

I loved Chris' post, I love this patch. +1. Here's to never
deploying breaking production you forgot to install a gem or having
to ssh to a bunch of machines to 'sudo gem install' (decidedly not
DRY) ever again!


What about the native code issue? Are you going to create a
sub-directory per platform?

Also, the idea of specifying dependencies (ala Maven) in yaml sounds
pretty cool. Were you thinking about doing something like that?


Josh Peek wrote:

Gems already have a mechanism for specifying dependencies.

Several weeks ago when I checked in the changes to the plugin loading code
Chad and I worked on functionality similar to the proposed patch. We took it
a step further with a slightly different approach whereby gem files placed
in a certain location would automaticaly be unpacked and loaded like regular
plugins on startup. The code is complete (as we intended it), tested and
documented, but despite Chad's repeated insistance, I haven't checked it in
yet...I've attached a diff for those who are interested.


vendor_gems.diff (29.8 KB)

I meant the app's dependencies... which gems an app needs to have installed. Seems like there would need to be some outside help (new code and a config file) to do that.


Marcel Molina Jr. wrote:

The code we're working on will work for both plugins (as gems) and
arbitrary gems.




Chad Fowler wrote:

Awesome! When will something like this make it into core?

Our main reservation vis-a-vis the vendor everything approach is that
it makes for painful distribution when you have multiple teams and
multiple applications that share the same 'operating
environment' (i.e. colocated with a shared GEM_HOME).

If you have a major security hole in shared dependency Foo that you've
backported to all of the major releases, you would need to hunt
through every app and replace the gem in question with the right gem
from based on release. Instead, we just build a gem for each backport,
install them on the gem server, and the 'shared environment' need only
update its repository and restart the apps. No need for a code deploy
on the applications themselves, which would cause the need to create a
maintenance branch on what might have been a short-lived release for
the sole purpose of updating a dependency micro.

From a development perspective, repositories have worked out great for

us as well. When I fix a major bug in a shared dependency, my
coworkers get the latest and greatest when they 'svn up; plugem
up' (which leverages gem update) in the morning--no wack SVN externals
(we started this journey in svn:external hell) or emails to links with
the latest gem.

Platform-specific gems are also a dilemma in the vendor everything
approach (rmagick, hpricot, etc.)--compiling things at application
start seems somewhat unusual. We have both OSX developers and Windows
developers, so it's nice to just add hpricot to the manifest and let
the repository expose the different platform variations (as opposed to
bundling them all in vendor and adding even more logic to the plugin

Gem repositories just do such a good job at acting as a repository for
gems :slight_smile:

I know this isn't the world that everyone is in (or wants to be in for
that matter), but I don't think it makes it much more difficult on the
KISS crowd (while it opens up a lot of doors for us fools that like to
overcomplicate things.)

The catch is the need for the application manifest file to declare the
dependencies, but thats brings a lot of secondary value to the table
as well. You can use it to generate spec files to gemify apps (as we
do), guarantee the presence of required third-party gems at startup
time, etc. It's not so bad.

More background on why we'd like to lobby for this approach in the
body and comments of :



rails-trunk AT revolution.com


Val just released the packaging/update component... that + runtime
should be all folks need to try plugems for themselves.


I patched edge with vendor_everything.diff but am getting this error:

uninitialized constant Gem::UnpackCommand
/usr/local/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:2028:in `const_missing'

Did something happen to Gem::UnpackCommand?


What about the native code issue? Are you going to create a
sub-directory per platform?

It's easy to compile C extensions per-platform. i.e.:


This works in *nix-land, with a special case needed for Windows (as always).