Thursday, February 15, 2007

Plugems Dependency Loading: Part 2 - Bundling a plugin as a Gem and getting it all to work

Plugins live in the project root, so Rails need only loop through the plugins, unshift them onto the load path, and require their init files. In a plugem environment, it's a little more complicated (to implement, not to use.)

Each of our applications has a manifest file. This is simply a YAML file that has some basic metadata about the appication (name, version, etc.) as well as a list of all of that application's plugem dependencies. This manifest file has two applications:

  1. Our rake tasks use it to generate a gemspec file for application gemification
  2. The bootstrapper uses it as a list of dependent plugems to load

Without getting into the weeds, this is accomplished in the following way:

  1. A bootstrap set of tasks is loaded right after the environment is booted.
  2. The bootstrap monkeypatches the Rails initializer, alias-chaining our plugem-loading code to plugin load.
  3. Upon startup, the plugem bootstrap code will loop through the dependencies and load and initialize them all. This is all mostly handled via require_gem, as our gemspec generator automatically registers the equivalent 'init.rb' type initialization via gem autorequire.

Next time: We put views, rake tasks, and layouts in these things too!

Wednesday, February 14, 2007


Brian Ketelson of InfoQ was gracious enough to feature Revolution Health in an article today. Thanks Brian.

Here's a link to all of their Ruby-oriented articles:

Locking down a deployed application

A single host might have multiple applications installed each on a different release track. Since all our applications are distributed as a bunch of gems, there is a potential issue with shared components. Even though the whole portal is being tested when some application or component is being pushed through the stack, there is always a possibility of incompatibility of on of the upgraded shared component with another dependent application. In some other environments there would only one solution - to roll back the whole new application. In our environment we have another option - to lock down the affected application. When an application is deployed, one of the deployment steps is to create a gem repository inside the application structure. The application gem repository has the sources gem installed and the rest of gems sym-linked as in this example:

actionmailer-1.2.5 -> /usr/lib/ruby/gems/1.8/gems/actionmailer-1.2.5
actionpack-1.12.5 -> /usr/lib/ruby/gems/1.8/gems/actionpack-1.12.5

Gems put into an internal gem structure are those it was tested with, so they are guarantee to work. All is needed to lock down an application now is to set the GEM_HOME environment variable on a web server instance, serving the application, and to point it to the application internal gem repository. After that the application won't use the latest versions of the gems but those specific it is locked to.