How to Create a Custom Gemfile for Development

How to Create a Custom Gemfile for Development

While working with a client, we noticed that they had two Gemfiles: one with gems specifically for development and local references to a gem, and the other with a reference to a resource on GitHub. They wanted to switch between the local installation of the gem and the external GitHub reference based on whether they were in development or production. This approach worked well for their needs; however, our team was concerned that one downside was the difficulty in maintaining two separate Gemfiles. In this article, we will discuss an approach to creating conditional Gemfiles for development.

This approach contrasts with the one found in either Loading Additional Ruby Gems in Development opens a new window or Customize your Gemfile for Development opens a new window . If you haven’t read either of these articles, the gist of their approach is to copy your Gemfile, rename it to whatever you want (Gemfile.development for example), and have two different Gemfile.lock lock files. The downside to this approach is that you still have two Gemfiles to keep track of. One Gemfile contains the gems for your application, while the other, such as Gemfile.development, contains gems specifically for your development environment.

While this method is effective, it may not suit everyone’s needs. For instance, you might not mind sharing your development-only gems, or you might have gems that need to be referenced differently between development and production. In such cases, we can use an approach similar to the one taken by our next_rails opens a new window tool.

Here at FastRuby.io, we use next_rails as part of our upgrading workflow. next_rails creates a symlink to your Gemfile called Gemfile.next. You can then use that Gemfile.next to bundle install, creating a Gemfile.next.lock. This allows you to have two Gemfile.lock files: Gemfile.next.lock and Gemfile.lock.

How to do it

Creating a symlink is straightforward. Just run the following command:

ln -s Gemfile Gemfile.development

Here, Gemfile.development is the name of whatever you want to call your new Gemfile.

Next, you can write a method that will help you switch between environments:

def development?
  File.basename(__FILE__) == "Gemfile.development"
end

Here’s an example of a Gemfile that uses this method to change a gem’s reference depending on whether the environment is development or not:

def development?
  File.basename(__FILE__) == "Gemfile.development"
end

if development?
  gem 'sample-gem', path: '../sample-gem'
else
  gem 'sample-gem'
end

You may be wondering how to run Gemfile.development for testing. It’s simple: you can append BUNDLE_GEMFILE=Gemfile.development (or whatever the Gemfile is called) to your command—whether it’s rspec, bundle, etc. and Bundler will use the Gemfile that you specify.

Conclusion

Using a symlink to manage different Gemfiles for development and production environments offers a streamlined and maintainable approach compared to having multiple separate Gemfiles. This method leverages the flexibility of Bundler to switch between environments easily, ensuring that you can manage dependencies efficiently without the overhead of maintaining duplicate files. By adopting this technique, you can simplify your workflow and focus more on development rather than the intricacies of dependency management.

Interested in paying off 1% of your tech debt every month? Let’s talk! opens a new window

Get the book