I recently set up a Cedar (Rails 3.1) app on Heroku, and to run, for example, a migration, you'd do
heroku run rake db:migrate
I learned that it's good practice to use "bundle exec" before any rake command (as Katz says http://yehudakatz.com/). So, I thought perhaps the following is actually better practice:
heroku run bundle exec rake db:migrate
But to reduce verbosity, is it alright to use the former command, or is the one with bundle exec critical?
On Heroku when the slug is compiled the Gems are installed from into a clean slug as specified in your Gemfile so there's not going to be extraneous Gems floating around the place - there's no need to use bundle exec on Heroku - else I'm sure the Heroku documentation would tell you to do it.
"In some cases, running executables without bundle exec may work, if the executable happens to be installed in your system and does not pull in any gems that conflict with your bundle. However, this is unreliable and is the source of considerable pain. Even if it looks like it works, it may not work in the future or on another machine"
Quoting from bundler's Documentation
Related
What does bundle exec rake db:migrate really means? or bundle exec rails s
I understand that bundle handle all the gems we specify in our Gemfile,and rake handle all the things which you can do through scripts but these commands don't get executed without prefixing bundle exec and I couldn't find any documentation about this on internet !!
Bundler - The best way to manage your application's dependencies
Run the command in context of the bundle
$ bundle exec
Exec runs a command, providing it access to the gems in the bundle. While using bundle exec you can require and call the bundled gems as if they were installed into the systemwide RubyGems repository
With:
bundle exec rake db:migrate
In an informal way, it means that your rails environment will
-Install dependencies with bundler
then
-Run your database migrations in your rails app (/yourapp/db/migrate)
Instead of a database operation, you could do any other command line stuff that can be controlled by rake (like building your app, extensions, cleaning some files, etc.)
This can be useful if you want to avoid confusing scenarios where maybe some gems in your setup are outdated, or missing from your environment. It's a good practice because calling rake by itself will not guarantee that you got all your dependencies in check.
Bundler acts to create a somewhat isolated Ruby language programming environment separate from the underlying host system. There are limits to what it can do. For example, you need something like RVM to manage different versions of the Ruby language virtual machine. And of course both Ruby and Bundler itself have to be available outside your project in order to run.
However, within a single project bundle exec will restrict access to gems installed by Bundler into that project. This means that the Rake utility when invoked via bundle exec will be the version of rake installed in your project and not the system-wide version. It also means that `bundle rake db:migrate' will use the correct version of rails installed for your project. This isolates your project from updates done to the Ruby environment on the host and thereby prevents compatibility issues from arising.
You can get around the verbosity by creating aliases in your .bash_profile (assuming you are using OSX or Linux/unix) for bundle exec, bundle exec rake and bundle exec rails. I use bexec, brake and brails.
What is the difference between using bin/rake and bundle exec rake.
And which is one preferred style?
bin/rake db:migrate
bundle exec rake db:migrate
bundle exec executes a command in the context of your application.
As each application can have different versions of gem used. Using bundle exec guarantees that you use the correct versions.
I use bundle exec always instead of rake because i have multiple applications running on my system.
Try to use bundle exec rake db:migrate always.
You can learn more about it here Official documentation
bin/rake is a kind of stub for the rake command from bundled Gems. It has exactly the same function as bundle exec rake. See http://bundler.io/v1.14/man/bundle-install.1.html and search for binstubs for more about stub. And also note that bin/rake and bin/rails are stubs generated by Rails, which are different in code from the stubs generated by bundler. However, they all serve the same purpose and have the same function.
You have 3 options on a typical system:
bin/rake db:migrate
rake db:migrate
bundle exec db:migrate
The first option is simply calling the path to the rake program, whose launcher can be found in the hidden /bin folder. This launcher is usually just a symlink to the program's content found in your /.rvm directory. You can find its original location by executing $ which rake, which will give you something like /home/ubuntu/.rvm/gems/ruby-2.2.3-p481#devonzuegel/bin/rake.
By default, the second option is essentially the same as the first on most systems. It's what is called an alias, which is basically just a shorthand command for some other program. This is defined somewhere in your shell settings as something like alias rake='/bin/rake'. It's possible that this alias is pointed to a different program on your machine though, so check that before taking my word for it.
When you use bundle exec you're telling bundler to ensure that only the gems and their specified versions from your Gemfile.lock are loaded. This will only work if you're in a directory that contains a Gemfile.lock or whose parent/grandparent directory contains one.
I'm going through Mhartl's tutorial and I'm sporadically getting this error when I run tests in the sublime text 2 console. If I use bundle exec rspec/rspec in the the terminal it works fine, but it's not the case when call shortcut commands in sublime text to run tests. I don't know if it makes a difference but I'm also running guard
Users/User/.rvm/gems/ruby-2.0.0-p247#global/gems/bundler-1.3.5/lib/bundler/runtime.rb:33:in `block in setup': You have already activated rspec-core 2.14.5, but your Gemfile requires rspec-core 2.13.1. Using bundle exec may solve this. (Gem::LoadError)
I tried searching stack overflow for solutions and tried bundle exec rake db:migrate(I normally don't specify bundle exec) as well as bundle exec rake test:prepare. Neither of which work.
I'd appreciate not only an answer to the problem but perhaps a more in-depth answer of when to use rake db:migrate and rake test:prepare. I know their main uses, but there are perhaps some less obvious times where i would need to run it. SPecifically, for this problem I would have thought rake test:prepare would be relevant and I'm still not sure what effect rake db:migrate has on the testing suite/rspec part of the application
To answer part of your question, you can delete unused gems through bundle clean, although when I've had multiple versions of gems, I've found that I had to use bundle clean --force which may mean that I had "system gems" coming into play, per https://stackoverflow.com/a/10190608/1008891.
I learned Rails using just the rake command like rake db:migrate; however, I read that I should be using the bundle exec rake ... instead of just plain rake. Now I'm confused about which to use.
Should I be using bundle exec rake instead of just plain rake or is it just a preference thing? Any insight would be much appreciated! Thanks!
bundle exec executes a command in the context of your bundle.
That means it uses the gems specified in your Gemfile. Much of the time, running bundle exec rake foo has the same results as if you just ran rake foo, especially if you have the same gems installed systemwide as in your Gemfile. However, some applications may specify different versions of gems than the ones you have installed systemwide, and may want those exact gems and versions to be able to run correctly. If you just run without bundle exec, you may get some weird errors.
Using bundle exec guarantees that the program is run with the environment specified in the gemfile, which hopefully means it is the environment that the creators of the program want it to be run in, which hopefully means it should run correctly no matter what weird setup you have on your computer.
It basically standardizes the environment under which the program is run. This helps avoid version hell and makes life much easier.
See http://bundler.io/v1.3/man/bundle-exec.1.html for more info.
$ bundle exec rake db:migrate
Uses the version of rake specified in the Gemfile to execute the rake task db:migrate.
But there is no rake gem specified in the Gemfile!
Yes, but a rake gem was installed as a dependency of some other gem--look in Gemfile.lock. So the rule must be: Uses the version of rake specified in Gemfile.lock.
But Gemfile.lock doesn't specify a specific version--it specifies a version greater than x.y!
Then the rule must be: Uses the version of rake that was installed in the current gemset.
$ rake db:migrate
Normally, when you issue a command on the command line, e.g. rake, your system searches for the command in the list of directories specified in your PATH environment variable. The first directory that contains the command is the version of the command that is used. To see which directory that is, you can do:
$ which rake
So if you execute,
$ rake db:migrate
that may use a different rake gem than the one you installed with bundle install. But, even if your system finds the same rake version as bundle exec, any gems required by the rake source code will be searched for in places outside your project's gemset. Therefore, there are many ways that just:
$ rake db:migrate
can screw things up.
According to the Ruby on Rails Tutorial Book(free online), section 3.6, if you are using rvm 1.11.x+ then you do not need to preface commands with bundle exec.
running any exacutable without bundle exec will have Rubygems fetching the latest version of the gem installed in your system.
By adding the bundle exec prefix instead will have the executable running in the context of your Gemfile.lock, which means that will be run using the version defined in the gem file.
In Rails 2 you're able to run
script/console --sandbox
so you can play with production data and not accidentally break anything.
I can't seem to find the equivalent command for Rails 3. Does anyone know what it is?
Easy, type in:
bundle exec rails c -s
and that is it.
$ bundle exec rails c --help
Usage: console [environment] [options]
-s, --sandbox Rollback database modifications on exit.
--debugger Enable ruby-debugging for the console.
--irb DEPRECATED: Invoke `/your/choice/of/ruby script/rails console` instead
It is simple, but, sometimes, if you are not running rails executable using bundle exec, it may, or may not, result in an error. In order to avoid this, ALWAYS use bundle exec.
To quote bundler page (if not documentation):
In some cases, running executables without bundle exec may work, if
the executable happens to be installed in your system and does not
pull in any gems that conflict with your bundle.
However, this is unreliable and is the source of considerable pain.
Even if it looks like it works, it may not work in the future or on
another machine.