Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What means 'bin' in '$ bin/rails?'

I'm trying to follow along the "Getting Started with Engines" Rails Guide's tutorial and found this:

$ bin/rails plugin new blorgh --mountable

When I type this on my terminal, I get:

bash: bin/rails: No such file or directory

When I try just $ rails it works OK.

I've been using the command line for a couple of months, and Rails as well. I know the $ sign but I'm confused about the meaning of the "bin" after that. I'm used to type "Rails" right after $, but this tutorial says that use "bin" ...

What does bin/ mean?

like image 875
rovitulli Avatar asked Jul 31 '14 21:07

rovitulli


1 Answers

tl;dr

Run bundle install --binstubs and it'll work. You only have to do it once and Bundler will remember that you asked for it (for that project).

Longer answer

When you install a bundle with bundle --binstubs, Bundler will install all your bundle-specific binstubs into the bin/ subdirectory (relative to the Gemfile), rather than putting them into the gemset's global binstub paths.

You would typically do this to:

  1. Ensure that the rails binstub you're running is the one in your Gemfile (as opposed to a different version that got installed into your gemset later, separate from Bundler), and
  2. To improve execution time (since it's functionally equivalent to bundle exec rails except minus one subprocess invocation).

Global binstubs vs Bundler binstubs

If you type which rails, you will get a long path like /usr/local/rvm/gems/jruby-1.7.18/bin/rails, and the contents of which: cat `which rails`

#!/usr/bin/env jruby_executable_hooks
#
# This file was generated by RubyGems.
#
# The application 'railties' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require 'rubygems'

version = ">= 0"

if ARGV.first
  str = ARGV.first
  str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding
  if str =~ /\A_(.*)_\z/
    version = $1
    ARGV.shift
  end
end

gem 'railties', version
load Gem.bin_path('railties', 'rails', version)

After running bundler --binstubs, if you cat bin/rails, you'll get something like:

#!/usr/bin/env jruby
#
# This file was generated by Bundler.
#
# The application 'rails' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require 'pathname'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
  Pathname.new(__FILE__).realpath)

require 'rubygems'
require 'bundler/setup'

load Gem.bin_path('railties', 'rails')

The key difference there is that the bin/ version sets the BUNDLE_GEMFILE environment variable, and it requires bundler/setup, which is what tells Bundler to go do its thing with gem paths. The bin/rails script is bundler-aware, and is aware of your Gemfile, so it can prepare your environment right off the bat.

I generally recommend using --binstubs and bin/x invocations over the gemset versions.

like image 194
Chris Heald Avatar answered Sep 28 '22 07:09

Chris Heald