Search code examples
ruby-on-railsbundler

Should I use `bundle exec` or Rails' binstubs?


Say I have a Rails app with gems installed with bundler. Should I use bundle exec rails or bin/rails? Should I use bundle exec rake or bin/rake? Is there any difference? Is any of those better then the other one?


Solution

  • tl;dr no particular difference, but if I were to choose, I'd use bin/rails

    There's little to no difference. Let us see.

    DISABLE_SPRING=1 bin/rails --version:

    bin/rails: require_relative '../config/boot'
    config/boot: require 'bundler/setup'
    bundler/setup: Bundler.setup
    Bundler.setup: definition.validate_runtime!
    Bundler.definition: Definition.build
    Bundler::Definition.build: Dsl.evaluate
    Bundler::Dsl.evaluate: builder.eval_gemfile
    Bundler::Dsl#eval_gemfile: instance_eval

    After require 'bundler/setup', trying to gem 'rails', 'x.y.z' results in:

    *** Gem::LoadError Exception: can't activate rails (= x.y.z), already activated rails-5.1.3. Make sure all dependencies are added to Gemfile.

    With bundle exec rails --version, we end up running bin/rails anyway:

    ~/.gem/ruby/x.y.z/bin/rails: load Gem.activate_bin_path('railties', 'rails', version)
    exe/rails: require 'rails/cli'
    rails/cli: Rails::AppLoader.exec_app
    Rails::AppLoader.exec_app: `exec RUBY, 'bin/rails', *ARGV

    Also, do note the message one can found in the last file:

    Beginning in Rails 4, Rails ships with a rails binstub at ./bin/rails that should be used instead of the Bundler-generated rails binstub.

    So, at the end of the day there's no difference. But considering the fact that Rails goes through the trouble of shipping its own binstubs, I'd favor bin/rails alternative. Also, it autocompletes better.

    And,

    App executables now live in the bin/ directory: bin/bundle, bin/rails, bin/rake. Run rake rails:update:bin to add these executables to your own app. script/rails is gone from new apps.

    Running executables within your app ensures they use your app's Ruby version and its bundled gems, and it ensures your production deployment tools only need to execute a single script. No more having to carefully cd to the app dir and run bundle exec ....

    Rather than treating bin/ as a junk drawer for generated "binstubs", bundler 1.3 adds support for generating stubs for just the executables you actually use: bundle binstubs unicorn generates bin/unicorn. Add that executable to git and version it just like any other app code.

    https://github.com/rails/rails/blob/4-0-stable/railties/CHANGELOG.md