The Cloud Foundry Blog

Polishing Cloud Foundry’s Ruby Gem Support

The Cloud Foundry team has released new features to improve management of Ruby gems in apps running on CloudFoundry.com. These features include support for using Git URLs in Gemfiles, handling of the BUNDLE_WITHOUT environment variable, and platform specification to control the gem installation process. With these improvements, it is now easier than ever to get your existing Ruby projects up and running on CloudFoundry.com.

History

In 2003, RubyGems was launched as Ruby’s package manager. Six years later, Rubyists began using Bundler–a means for managing and installing gem dependencies in the context of an application. The combination of these two technologies has given developers the ability to run Ruby applications without having to worry about the specific gem version, gem source, or the platform that is available on the server. In this blog, we will review the changes in the Cloud Foundry 4 that provide better support for gems. We will discuss using Git URLs as a gem source, how you can use BUNDLE_WITHOUT to manage gem groups, and how Cloud Foundry installs only the platform specific gems that make sense.

Using Git URLs as a Gems Source

Most of the time, developers use default “rubygems” source to fetch gems from the official Ruby Gems repository. Alternatively, Bundler supports Git source URLs in order to associate a gem name and version with a certain Git repository. In this latter scenario, Bundler will automatically clone the latest version of a gem and install it. As of today, CloudFoundry.com fully supports using these Git URLs.

How does it work?

In the same way that Bundler installs gems from a Git source URL, resolving Git branches and references, Cloud Foundry locates Git dependencies in the Gemfile.lock, fetches the source code, and checks out the specified revision. Next, Cloud Foundry will find all of the gemspecs, build the gems and inject them into the application exactly where Bundler expects to see them. When the application gets started via “bundle exec,” Bundler picks up all installed dependencies as usual. To optimize the staging process, CloudFoundry.com also caches fetched Git sources. For example, if you reference the

Rails Git URL, CloudFoundry.com clones the repository and caches it in the local filesystem, so the next request for Rails will use the cache. If a requested revision is missing from the cache, there is no need to clone from scratch because only the missing objects will get downloaded from the original repo.

Example

Let’s take a look at the application

padrino shortener-demo. This demo is using the latest version of Padrino (a Sinatra-based web framework). As we can see in application Gemfile, gem padrino is requested to be provided from GitHub:

There may be situations where using the official published gem versions is not enough, such as using the current HEAD of the project, or specific branch, tag or fork. Cloud Foundry supports Git URLs in Gemfile, so it’s easy to point to a Git repo with the exact version of the library you need, and it will be downloaded and packaged as a part of your Cloud Foundry app.

Using BUNDLE_WITHOUT to Manage Gem Groups

Gemfiles support the grouping of gems so that a test server, for example, can get a different group of gems than a production one. The second feature we are announcing is that Cloud Foundry allows developers to take advantage of these groups by using the BUNDLE_WITHOUT environment variable, just as you would locally. Setting BUNDLE_WITHOUT causes Cloud Foundry to skip installation of gems in excluded groups.

Example

BUNDLE_WITHOUT is particularly useful for Rails applications, where there are typically “assets” and “development” gem groups containing gems that are not needed when the app runs in production. Let’s take a look at an example.

Spacely is a Rails 3.2 application that provides image upload via drag and drop. The Gemfile contains several gems in a group called “assets.”

Let’s push the application to CloudFoundry.com without the gems in the “assets” group. We need to run “bundle install” first to generate a Gemfile.lock, which Cloud Foundry requires. Spacely includes a VMC manifest.yml file, so we can easily push the app without the full interaction. Notice that we push the app with the “–no-start” flag, so we can set the BUNDLE_WITHOUT environment variable before starting the application. We will make this step easier in the new version of VMC by enhancing the manifest support.

Cloud Foundry also supports the exclusion of multiple groups. For example, if Spacely included a “test” group, we could have excluded gems in both assets and tests with “vmc env-add spacely BUNDLE_WITHOUT=assets:tests”.

Excluding Gems by Platform

Bundler allows developers to use the “platforms” method in Gemfiles to specify that a gem be used on particular platforms. This is the final piece of polish for gems that we are adding today. Cloud Foundry will skip the installation of gems on irrelevant platforms, as it should. The following Gemfile specifies that the rb-inotify gem should be used in non-Windows environments, while three other gems are for Windows only. When this app is deployed to CloudFoundry.com, only the rb-inotify gem will be installed.

The “platforms” designation can also be used to selectively install gems based on Ruby versions. For example, certain gems can be excluded when switching between Ruby 1.8 and Ruby 1.9.

Support for Windows Gemfiles

When a Gemfile.lock is generated on a Windows machine, it often contains gems with Windows-specific versions. This results in versions of gems such as mysql2, thin, and pg containing “-x86-mingw32.” For example, a Gemfile that contains the following:

gem ‘sinatra’
gem ‘mysql2’
gem ‘json’

When you run “bundle install” with the above Gemfile on a Windows machine, it would result in the following Gemfile.lock:

Notice the “-x86-mingw32” in mysql2’s version number. Previously this would cause a failure on deployment, as Cloud Foundry would attempt to install the Windows-specific gem. However, now Cloud Foundry will install the Ubuntu-friendly version of these gems without requiring any modification to Gemfile.lock. Developers can seamlessly migrate their app between local Windows machines and CloudFoundry.com.

Conclusion

The ability to use Git URLs as a dependency source and specify which gem groups should be installed depending on the platform provides greater flexibility for Ruby developers. The work we have done to enhance gem and bundler support is part of our commitment to providing a Platform as a Service that meets real needs of Rubyists building and deploying applications in the cloud. Follow us on Twitter at

@cloudfoundry and let us know how these new features are working for you! – Jennifer Hickey and Maria ShaldibinaThe Cloud Foundry Team