Don't Understand Bundler Interaction with Gems - ruby-on-rails

I thought I understood how Bundler works with gems, but after something that recently happened, I am not sure I have it right.
I am developing an Rails application. To start off (and just so I would get familiar with the Rails environment which I haven't worked in before), I did not use an IDE. But, because I'm missing out on some of the advantages of an IDE, I just started using RubyMine. As part of the RubyMine setup, it asked to update all my gems for my existing project.
After that, I could not run "rake [anything]". Every time I did, I received an error of:
You have already activated rake 0.9.3.beta.1, but your Gemfile
requires rake 0.9.2.2. Using bundle exec may solve this.
I was okay updating to the next version of rake - that wasn't a problem - but I don't understand what happened in the first place. What happened that I "activated" a newer version of rake. Ultimately, I ended up solving the problem by putting
gem 'rake', '0.9.3.beta.1'
in my Gemfile and running
bundle update rake
But, I'm still not sure what happened here. If I was using 9.2.2 before, why did it all of a sudden blow up like that and how can I prevent that in the future?

If you are using Rubymine, you should configure it to run rake tasks with bundle exec.
Go to:
Run -> Edit Configurations -> Defaults -> Rake -> Bundler tab and check "Run the script in context of the bundle (bundle exec)"
Delete all tasks already created and the default will apply the next time you create them again. You can also configure individually each task created.

You should really consider installing and using RVM or Rbenv to manage your ruby versions and gemsets. If you go the Rbenv way, the rbenv-gemset plugin can be used to manage gemsets similar to how RVM natively does.
You have already activated rake 0.9.3.beta.1, but your Gemfile requires rake 0.9.2.2. Using bundle exec may solve this.
At some point between your last bundle execution and installing/configuring/running RubyMine you must have installed rake 0.9.3.beta.1. Because you're not managing your gems through gemsets like RVM or Rbenv will do for you, the default version of Rake became 0.9.3.beta.1 instead of the version installed by bundler, 0.9.2.2.
The above error suggests your Gemfile had something like
gem 'rake', '0.9.2.2'
which does not allow the version of rake being used to be anything but 0.9.2.2.
If you do in fact have 0.9.2.2 on your system in addition to the 0.9.3.beta.1 and your Gemfile is configured for 0.9.2.2, instead of running
rake some:task
you can run
bundle exec rake some:task
and bundler will run some:task through the 0.9.2.2 version of rake. Running tasks related to gems found in a Gemfile through bundleer with bundle exec ... is considered good practice regardless of using RVM or Rbenv.
You can read about bundle exec here.

Related

New Gems Not Found in Production with Rails 3, Bundler and RVM

I recently set up a production server for a Rails 3 app.
On the initial deploy everything worked fine. On a subsequent deploy, new gems that were added to the project are not being found. I am getting uninitialized constant and undefined method errors when I reference classes and methods from the newly added gems, respectively.
When I originally set things up I was using a gemset with RVM, but have tried to simplify things by removing the gemset and only using RVM to manage rubies.
When I run bundle list every thing is there. All of the gem are in <app_root>/shared/bundle/ruby/1.9.1/gems/
It seems like maybe it's loading the gems from some other location, like the original gemset, but I have deleted it.
Some other details, I am using Capistrano, of course, Unicorn, my GEM_HOME=/home/deployer/.rvm/gems/ruby-1.9.3-p286
Let me know if there is any other info I can provide.
Thanks.
if you use bundle install --deployment then you also have to prefix commands with bundle exec when you execute the command, like:
bundle exec rake db:migrate
If you use bundler/capistrano integration then it does it for you in capistano but in console you need to use bundle exec manually.
RVM was helping you to avoid it with rubygems-bundler gem - but you changed gemset so the generated wrappers are no more available. You would have to clean <app_root>/shared/bundle/ruby/1.9.1/gems/ and run bundle install again to regenerate the wrappers to avoid typing bundle exec again.
I have similar problems. It turns out Capistrano isn't properly restarting unicorn. SSHing into the server and stopping then starting unicorn did the job. Now to find a fix for Capistrano's shenanigans...

How to run a specific version of rake

Background:
I get errors whenever I run rake in an older project. (uninitialized constant Rake::DSL).
The rails project in question is an old project that was started with Rails 2.1 (I think), and since then I've updated the OS on my laptop a couple of times, and made updates along the way to make it run.
Right now, the rails app works fine, provided I have RAILS_GEM_VERSION set to 2.3.5. I'm not sure if the app was completely updated to Rails 2.3.5.
There is no Gemfile in my older project.
If I create a brand-new rails project (and unset RAILS_GEM_VERSION), rake runs fine.
My question: To troubleshoot, I'd like to try newer versions of rake. I'd like to know how to force one specific version to be used, since it appears I have multiple versions installed.
Info on my environment:
$ gem list rake
*** LOCAL GEMS ***
rake (0.9.2.2, 0.9.2, 0.8.7, 0.8.3)
$ rake --version
rake, version 0.8.7
So it looks like it's picking up the 0.8.7 version.
All the help files online seem to tell me to specify the rake version in the Gemfile, but there isn't one in this project. (Maybe it predates gemfiles?)
If I unset the RAILS_GEM_ENVIRONMENT variable altogether, and try to run rake, I get:
rake aborted!
can't activate rails (= 2.3.5, runtime) for [], already activated rails-3.2.8 for []
None of the environment config files in my older project set that variable either.
This may be of help. Have you tried the underscore solution?
Example:
rake _0.9.2_
you can run rake specific version by using this
bundle exec rake ...
more detail see this - bundle exec, rake
You can uninstall the current version of rake and install another desired version using commands similar to the following:
gem uninstall rake 12.3.1
gem install rake 10.5.0
(Note: you might need to run as sudo for permissions)
I had a problem where I received the following error while trying to install rake 10.5.0:
Could not find a valid gem '0.8.7' (>= 0) in any repository
I resolved this problem by adding the following line to my Gemfile:
gem 'rake', ' <11.0'
After editing Gemfile I was able to successfully downgrade rake by updating my gems:
bundle update

Persistent Rake DSL method warning

Alright, well I'm trying to fix this problem again. I followed this fix to eliminate the error by reverting to version 0.8.7, which worked the first time. However, now I'm trying to use cucumber and I'm getting it all again.
I tried it again by running gem uninstall rake -v=0.9.2.2 which lists all the gem dependencies. Successfully uninstalled. Then I ran bundle update rake. Using rake (0.8.7). Cool. rake -V. rake, version 0.9.2.2. wat. Same problems return. What am I missing? I thought 9.2 was supposed to fix this bug anyway?
I think this fix is obsolete. Rake 0.9.0 got fixed, and 0.9.2.2 is certainly working. You want to uninstall and completely eradicate rake 0.8.x. Try something like:
gem list -d rake
The -d switch will show the installation directories. If you're using RVM, there may be multiple search paths that get hit, running rvm info will tell you the search path and preference ordering. Depending on the system you're on, your OS may also ship with an old rake version. Try uninstalling everything other than the local gemset (if using RVM) or the latest rake (if not using RVM).
The problem with the rake gem uninstall sounds like you have Rake in your default gemset, check ~/.rvm/gemsets/global.gems It will no doubt have rake in it

How do I keep all gems in Gemfile compatible after an update

My question has already been asked here, but I am trying to understand the reasons behind it as opposed to how to work around it.
The error I got was;
You have already activated rspec-core 2.7.1, but your Gemfile requires rspec-core 2.6.4. Using bundle exec may solve this. (Gem::LoadError)
Now I have been given various solutions like using "mpapis-bundler", or to create a shorthand for "bundle exec", but I was under the impression that that was what
$bundle install --binstubs
was for.
More specifically, since I have no version numbers stated in my gemfile for rspec-rails, why do I have this incompatibility? My error also occurred when I tried
$rake db:migrate
telling me that
You have already activated rake 0.9.2.2, but your Gemfile requires rake 0.9.2. Consider using bundle exec.
Any explanations would be appreciated.
EDIT:
All my gems for my app are in a gemset, and I have updated my gems again. Should an update not make sure that related gems are compatible?
This happens when you install more recent gems in your system than the one in your Rails app.
Bundler simply tells ou that you must stick with those your Gemfile states.
This is the purpose of running:
bundle exec rake db:migrate
-> running the very same rake version your Gemfile provides.
Concerning updating gems from gemfile, simply do:
bundle update
The easiest way to avoid this kind of boring stuff is to isolate your gems by creating gemsets. I use RVM for this purpose.
Regarding the rake version 0.9.2.2, either ways to do is create a new gemset for the project and maintain the gem version matching your Gemfile.
For instance if there are two rake gem containing versions 0.9.2 and 0.9.2.2, specifying rake version '0.9.2' though installs, but does not run any tasks apart from blowing error saying
'You have already activated rake 0.9.2.2, but your Gemfile requires rake 0.9.2. Using bundle exec may solve this.'
I expect bundle install to lock the gem version in Gemfile.lock and pick the rake 0.9.2, but it looks in the gemset, where by default rake 0.9.2.2 is enabled.
Just reminding the purpose of bundle install from agile web development with rails book,
'bundle install will use the Gemfile.lock as a starting point, and install only the
versions of the various gems as specified in this file. For this reason, it is
important that this file gets checked into your version control system, as this
will ensure that your colleagues and deployment targets will all be using the
exact same configuration.'
but it doesn't work that way,
The better is to uninstall rake 0.9.2.2 and use rake 0.9.2 or, use bundle update rake, that updates the rake version in Gemfile.lock to 0.9.2.2
As #apneadiving said, running "$bundle install" updates all your bunldes. However, after running "$bundle install --binstubs" I still got errors for incompatible gems whenever I omitted the "bundle exec" part.
Subsequently I needed to update my Gemfile as I added another gem, and now they work. I'm assuming the incompatibilities were solved by the gem creators.

What does bundle exec rake mean?

What does bundle exec rake db:migrate mean? Or just bundle exec rake <command> in general?
I understand that bundle takes care of maintaining things in the Gemfile. I know what the word "exec" means. I understand that rake maintains all the different scripty things you can do, and I know that db:migrate is one of those. I just don't know what all these words are doing together. Why should bundle be used to execute rake to execute a database migrate?
bundle exec is a Bundler command to execute a script in the context of the current bundle (the one from your directory's Gemfile). rake db:migrate is the script where db is the namespace and migrate is the task name defined.
So bundle exec rake db:migrate executes the rake script with the command db:migrate in the context of the current bundle.
As to the "why?" I'll quote from the bundler page:
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.
You're running bundle exec on a program. The program's creators wrote it when certain versions of gems were available. The program Gemfile specifies the versions of the gems the creators decided to use. That is, the script was made to run correctly against these gem versions.
Your system-wide Gemfile may differ from this Gemfile. You may have newer or older gems with which this script doesn't play nice. This difference in versions can give you weird errors.
bundle exec helps you avoid these errors. It executes the script using the gems specified in the script's Gemfile rather than the systemwide Gemfile. It executes the certain gem versions with the magic of shell aliases.
See more on the man page.
Here's an example Gemfile:
source 'http://rubygems.org'
gem 'rails', '2.8.3'
Here, bundle exec would execute the script using rails version 2.8.3 and not some other version you may have installed system-wide.
This comes up a lot when your gemfile.lock has different versions of the gems installed on your machine. You may get a warning after running rake (or rspec or others) such as:
You have already activated rake 10.3.1, but your Gemfile requires rake 10.1.0. Prepending "bundle exec" to your command may solve this.
Prepending bundle exec tells the bundler to execute this command regardless of the version differential. There isn't always an issue, however, you might run into problems.
Fortunately, there is a gem that solves this: rubygems-bundler.
$ gem install rubygems-bundler
$ $ gem regenerate_binstubs
Then try your rake, rspec, or whatever again.
It should probably be mentioned, that there are ways to omit bundle exec (they are all stated in chapter 3.6.1 of Michael Hartls Ruby on Rails Tutorial book).
The simplest is to just use a sufficiently up-to-date version of RVM (>= 1.11.x).
If you're restricted to an earlier version of RVM, you can always use this method also mentioned by calasyr:
$ rvm get head && rvm reload
$ chmod +x $rvm_path/hooks/after_cd_bundler
$ bundle install --binstubs=./bundler_stubs
The bundler_stubs directory should then also be added to the .gitignore file.
A third option is to use the rubygems-bundler gem if you're not using RVM:
$ gem install rubygems-bundler
$ gem regenerate_binstubs
When you directly run the rake task or execute any binary file of a gem, there is no guarantee that the command will behave as expected. Because it might happen that you already have the same gem installed on your system which have a version say 1.0 but in your project you have higher version say 2.0. In this case you can not predict which one will be used.
To enforce the desired gem version you take the help of bundle exec command which would execute the binary in context of current bundle. That means when you use bundle exec, bundler checks the gem version configured for the current project and use that to perform the task.
I have also written a post about it which also shows how we can avoid using it using bin stubs.
I have not used bundle exec much, but am setting it up now.
I have had instances where the wrong rake was used and much time wasted tracking down the problem. This helps you avoid that.
Here's how to set up RVM so you can use bundle exec by default within a specific project directory:
https://thoughtbot.com/blog/use-bundlers-binstubs
It means use rake that bundler is aware of and is part of your Gemfile over any rake that bundler is not aware of and run the db:migrate task.

Resources