The release of Bundler 2.2.0 changes how gems are generated. The experience was surprising enough to want to take a moment to discuss the new behavior, point out areas of improvement, and leave you with alternatives for improving your workflow.
Without further ado, let’s dive in!
After upgrading to Bundler 2.2.0, I thought it would be interesting to see what’s new with gem generation by choosing to generate a demo gem:
As you can see from the above screenshot, I was immediately confronted with multiple prompts. This is new behavior. Thankfully, after going through this process once, I was no longer confronted with further prompts:
I much prefer the latter experience because encouraging swift gem generation with safe defaults — even if opinionated — is a better experience than being forced to think about all options up front.
For those not familiar with Bundler, it might not be entirely obvious where the above configuration is stored. The following will discuss the default and XDG configuration options available to you.
By default, Bundler uses a global configuration which can be inspected via
BUNDLE_JOBS: "3" BUNDLE_IGNORE_MESSAGES__HTTPARTY: "true" BUNDLE_SUPPRESS_INSTALL_USING_MESSAGES: "true" BUNDLE_GEM__TEST: "rspec" BUNDLE_GEM__MIT: "true" BUNDLE_GEM__COC: "true" BUNDLE_GEM__CI: "circle" BUNDLE_GEM__RUBOCOP: "true"
The first three lines were configured previously by me while all lines prefixed with
were added by Bundler during earlier generation of the
demo gem. Unfortunately, none of the gem
configuration is explained in the Bundler
Configuration or Bundler Gem documentation.
XDG is nice UNIX standard for organizing program configurations, caches, data, etc. Since I am the maintainer of XDG for Ruby, it’s hard for me to enjoy non-XDG configurations as found with Bundler’s default configuration. That said, it is possible to contort Bundler to behave in an, almost, XDG-like manner using the following global variables:
export BUNDLE_USER_CACHE="$HOME/.cache/bundler" export BUNDLE_USER_CONFIG="$HOME/.config/bundler/configuration.yml" export BUNDLE_USER_HOME="$HOME/.local/share/bundler" export BUNDLE_USER_PLUGIN="$HOME/.local/share/bundler/plugin"
The above configuration is what I use via my Dotfiles
You might want to use these settings for your environment too, especially if you
automate the setup of your machine.
While fine for quick exploration, over time Bundler looses it’s ability to scale once you are developing and maintaining multiple projects and/or gems. For that, I’d like to suggest the following alternatives for consideration.
Rubysmith was designed to fill a gap where you need to generate a Ruby project with professional and configurable defaults while also needing something more sophisticated than a Bundler Inline script. The default experience focuses on letting you get started quickly:
bundle install rubysmith rubysmith --build demo
You can customize project generation further by using command line options or even adding a global and/or local YAML configuration. The power is yours!
Rubysmith can also be a great tool as an interview rubric if you want to see if an engineer can design, implement, and provide a working Ruby project of high quality for review and discussion.
See the Rubysmith documentation for further details.
Gemsmith was designed to replace Bundler’s default gem generation with professional tooling based on years of experience of developing and maintaining projects published on RubyGems. Getting started is roughly equivalent to Rubysmith:
bundle install gemsmith gemsmith --generate demo
As with Rubysmith, Gemsmith provides support for command line options as well as global and/or local configuration customization. For further details, check out the Gemsmith project documentation.
I hope the above was a useful exploration of using Bundler, Rubysmith, and Gemsmith to generate new Ruby projects. All have their uses but I do hope you’ll consider reaching for Rubysmith and/or Gemsmith when building your next Ruby project. 🎉