Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 991
x-yuri Avatar asked Jun 22 '17 00:06

x-yuri


2 Answers

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

like image 112
x-yuri Avatar answered Oct 31 '22 13:10

x-yuri


bundle exec just ensures that all gems in Gemfile are installed (globally or on userspace or in vendor/bundle directory of the project) when running the command. It's explained in more detail in https://bundler.io/man/bundle-exec.1.html (especifically https://bundler.io/man/bundle-exec.1.html#BUNDLE-INSTALL-BINSTUBS section):

Bundle Install --binstubs

If you use the --binstubs flag in bundle install, Bundler will automatically create a directory (which defaults to app_root/bin) containing all of the executables available from gems in the bundle.

After using --binstubs, bin/rspec spec/my_spec.rb is identical to bundle exec rspec spec/my_spec.rb.

Binstubs may also include other customizations like loading spring gem, which preloads and speeds up the Rails application.

like image 4
Pere Joan Martorell Avatar answered Oct 31 '22 13:10

Pere Joan Martorell