Generate only the binstubs that your project needs
When you generate all binstubs for a bundle:
bundle install --binstubs
Your ./bin
directory will get populated with binstubs for every gem in the bundle that has executables. However, you won't need most of those binstubs since developers generally just use a few like rake
, rspec
and similar.
Moreover, the --binstubs
option is sticky, meaning Bundler will keep adding binstubs for new gems in the future when you run just bundle install
. This can get tiresome if you checked the ./bin
directory in version control (which you should), because git will keep displaying new untracked binstubs—most of which you probably won't care about—and you'll be forced to either gitignore them or add them to version control as well.
A much more thoughtful and controlled approach is to generate only the binstubs that you actually need:
bundle binstubs rake
bundle binstubs rspec-core
bundle binstubs cucumber
Now check these files in version control once and you don't have to worry about babysitting the ./bin
directory in the future.
See Understanding binstubs for a broad overview of the purpose of RubyGems, rbenv and Bundler binstubs, and how you can use them to avoid having to prefix everything with bundle exec
.
Written by Mislav Marohnić
Related protips
7 Responses
Question,
after reading the Understanding binstubs article, I tried your tip of adding export PATH="./bin:$PATH"
to my bash_profile
But, in a new shell window, when I run rbenv which rake
inside my rails project, I am shown:
/Users/julieng/.rbenv/versions/2.0.0-p247/bin/rake
Is that correct? I expected it to show me the rake binstub in my projects bin
folder.
Am I misunderstanding something?
The rbenv which
command is not PATH-aware; it just looks at the currently selected version to find the rake
executable. This doesn't reflect what would actually be run when you run rake
, though.
Your PATH is correct, so running which rake
should show /path/to/yourproject/bin/rake
, which means everything is as you wanted. Now all calls to rake
in your project will activate the local binstub and not ~/.rbenv/versions/2.0.0-p247/bin/rake
.
which rake
still doesn't show the local rake…but rather the shim.
I checked rbenv's Unterstanding Shims and it seems that is wanted behavior, that the shims are before other PATH
.
Assuming that, would my local rake ever take precedence (see console log below)?
Or is everything working behind-the-scenes correctly and I shouldn't expect which rake
to show my local rake? When you run the command in your projects, do you get your local rake? Then maybe it's me…
Sorry for all the newbie questions!
$ echo $PATH
/Users/julieng/.rbenv/shims:./bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin
$ ls bin/
bundle* guard* rails* rake*
$ which rake
/Users/julieng/.rbenv/shims/rake
$ rbenv which rake
/Users/julieng/.rbenv/versions/2.0.0-p247/bin/rake
Edit: commands were executed inside my rails project folder root.
You want the local executables (bin/rake
) to have precedence over global ones, including rbenv's shims. That means you want ./bin
at the very front of your PATH.
Whenever you're thinking how to order things in your PATH, it helps to think about your priorities. Ask yourself, what do you want to happen when you type rake
:
- You want the local binstub (
bin/rake
) to get activated if it exists, as it guarantees that the correct rake version will be activated; - If a local binstub doesn't exist, you want rbenv's shim to get activated, as it guarantees that it will get executed with the correct version of Ruby for this project;
- Then, for non-Ruby commands, you want
/usr/local/bin
to be searched because that's where Homebrew lives (if you use it), or other software that you install manually; - Finally, you want system paths such as
/usr/bin
to get searched.
Considering the above, it means your PATH would then be (pseudo-code):
./bin : (rbenv shims) : /usr/local/bin : /usr/bin
Also, just a heads-up for the future, which rake
might not show you the correct result if you've just changed PATH in this shell. This is due to caching; some shells cache the location of rake
for performance reasons. So after you change PATH, you should call hash -r
in your shell just in case, or use command which rake
which actually calls the which
executable on the filesystem rather than which
shell built-in. You have every right to be confused; this stuff is hard! :(
Yes, I am trying to get the PATH you typed above to work.
./bin : (rbenv shims) : /usr/local/bin : /usr/bin
But from what I understand, it's not possible because rbenv always enters the shims before all other PATHs
Anyway, I find the tip to enter ./bin
to the PATH
. I just can't get it to work and will give up for now. But thanks for all your help :-)
rbenv always enters the shims before all other PATHs
Aha, now I finally understand what you're struggling with. rbenv does add the shims to the front of PATH, but it does so only at the point where you call rbenv init
in your .bash_profile
:
eval "$(rbenv init -)"
If you edit your PATH after this point, you will be able to add paths in the front:
export PATH=./bin:"$PATH"
Maybe you could add that you can add --path
flag to the binstubs command, since it's not documented (in case you are interested in putting the binstubs in another directory of course).