Why do I need bundle exec to require this rubygem? - ruby

I have a Rails app with some non-Rails-dependent files under `lib/services'. One of these files uses the Domainatrix gem.
require "domainatrix"
class SuggestionParser
# various suggestion parsing methods
end
I have an empty spec for this file under spec/lib.
require "services/suggestion_parser"
describe SuggestionParser do
end
Unfortunately, when I try to run that spec without bundle exec I hit an error:
$: rspec spec/lib/services/suggestion_parser_spec.rb
-> /Users/davidtuite/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:55:in `require': cannot load such file -- domainatrix (LoadError)
Every other spec and gem in my project will run without using bundle exec. Why do I need to prefix this one in order to get it to run?
For convenience, here's a link to the Domainatrix gemspec.

My guess would be that domainatrix is declared using the :path or :git options in the Gemfile, neither of which install the gem in a way that makes it accessible to rubygems.
This could be confirmed if you post the line for domainatrix from the Gemfile.

try running the following commands:
$ rvm get head && rvm reload
$ chmod +x $rvm_path/hooks/after_cd_bundler
$ bundle install --without production --binstubs=./bundler_stubs
This won't solve the specific problem with your gem, but it will take away the necessity to type in bundle exec every time you run your tests if you're using rvm.

Related

Ruby script cannot load a gem installed via bundler

I am trying to include the ruby-mysql gem in my ruby script. I have installed the gem using bundler but when I run bundle exec ./mysql_connector, I receive the error ./mysql_connector:4:in ``require': cannot load such file -- ruby-mysql (LoadError). Can you please help me troubleshoot what the problem is?
What I did
Installed rails in my home directory.
I do not have root access to the server so I have installed rails in my local directory by following the instructions here:
http://www.r-bloggers.com/installing-ruby-on-linux-as-a-user-other-than-root/
Created a directory for my application.
My application resides in my home directory in a folder called connector. It has a Gemfile that looks like this:
source 'https://rubygems.org'
gem 'ruby-mysql'
Call bundle install.
Using ruby-mysql 2.9.14
Using bundler 1.11.2
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Bundled gems are installed into ./vendor/bundle.
Add dependencies to my script. My script is in connector/mysql_connector and it reads:
#!/home/dcox/bin/ruby
require 'rubygems'
require 'bundler/setup'
require 'ruby-mysql'
Make script executable. I saw that you need to run bundle exec using an executable file, so I followed the instructions here to make my script executable: http://commandercoriander.net/blog/2013/02/16/making-a-ruby-script-executable/
Run the script. I execute using bundle exec mysql_connector and see:
/home/dcox/bin/mysql_connector:4:in `require': cannot load such file -- ruby-mysql (LoadError)
from /home/dcox/bin/mysql_connector:4:in `<main>'
Is it the $LOAD_PATH? After searching around for answers, I discovered a lot of SO answers as well as a blog post (https://codedecoder.wordpress.com/2013/09/23/require-and-load-in-ruby-loaderror-cannot-load-such-file/) that seem to suggest the problem is that the gem is not installed in a directory on the $LOAD_PATH. Here is what I see when I run $LOAD_PATH from IRB:
irb(main):002:0> $LOAD_PATH
=> ["/home/dcox/lib/ruby/site_ruby/2.1.0",
"/home/dcox/lib/ruby/site_ruby/2.1.0/x86_64-linux",
"/home/dcox/lib/ruby/site_ruby", "/home/dcox/lib/ruby/vendor_ruby/2.1.0",
"/home/dcox/lib/ruby/vendor_ruby/2.1.0/x86_64-linux",
"/home/dcox/lib/ruby/vendor_ruby", "/home/dcox/lib/ruby/2.1.0",
"/home/dcox/lib/ruby/2.1.0/x86_64-linux"]
Next I checked to see the location of ruby-mysql:
dcox#analytics1:~/connector$ bundle show ruby-mysql
/data/home/dcox/connector/vendor/bundle/ruby/2.1.0/gems/ruby-mysql-2.9.14
Obviously my connector/vendor/bundle path is not on the $LOAD_PATH. I could add it, but I have a feeling I am missing something simple here because bundler is supposed to work as long as you follow the instructions, right?
Any advice or help is very much appreciated! Thanks!!
If you just want to require this specific gem, require 'mysql' should work (e.g., https://github.com/tmtm/ruby-mysql/blob/master/test/test_mysql.rb#L10).
Your file should call Bundler.setup http://bundler.io/bundler_setup.html
Better yet, if you instead call Bundler.require(:default) it will setup and require all the gems in your Gemfile for you.

Run gem from local source code

I am currently working on developing a gem and I would like to be able to run that gem from command line and point it to my local source. Previously I've done this in rails by specifying the path in the gem file but now I would like to run the gem on a non rails app. So I would like to know how to call the gem from command line and specify that I want to use the source code in a certain directory.
For example can I cd into the directory that I want to run it on and do something like: ruby my_gem --path=~/code/mygem
Also do I have to build them gem or can I run it from source without building it?
From the root directory of your gem, try this to execute lib/MyGem.rb:
ruby -Ilib lib/MyGem.rb
or test your gem interactive:
irb -Ilib
> require 'mygem'
true

Using rspec with a local gem

I am using a local gem (on my machine) with another application that is a command line app.
I have something like this in the gemfile to refer to the local gem:
gem 'mygem', :path => '/Users/devmachine/Projects/mygem'
When I run bundle console I am able to use the gem and all is well. However, whenever I run my test suite (rspec) I get the following message:
ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- mygem (LoadError)
I'm confused. Any ideas?
You need to run:
bundle exec rspec
If you are not using the bundle evironment rspec won't know what you put in your Gemfile and just use the Gems it finds installed.

Bundler and wrong binstubs?

I run rails s or bundle exec rails s and I get this warning:
Bundler is using a binstub that was created for a different gem.
This is deprecated, in future versions you may need to `bundle binstub rails` to work around a system/bundle conflict.
What does this mean? From looking around the bundler site, my understanding of binstubs is that you can set executables to them, so instead of running bundle exec blabla you can just do bin/blabla. So this error is saying my bundler isn't set to the right binstub?
When I run the bundle binstub rails I get this output
rails has no executables, but you may want one from a gem it depends on.
railties has: rails
bundler has: bundle, bundler
I do not understand what my system is trying to tell me, and it's not breaking anything, but I have a hunch this could turn into a bigger issue if I don't fix it
ruby 2.0.0p247
which ruby
/Users/evan/.rvm/rubies/ruby-2.0.0-p247/bin/ruby
which bundler
/Users/evan/.rvm/gems/ruby-2.0.0-p247/bin/bundler
Rails 4.0.2
Edit:
So, if I run the commands in the nag message:
bundle config --delete bin # Turn off Bundler's stub generator
rake rails:update:bin # Use the new Rails 4 executables
I end up getting uninitialized constant Bundler errors with bundle exec commands and the only way I've found to fix that is to rerun bundle install --binstubs which brings back the nag message at the start of this post.
What worked for me was
rm -rf bin/*
Then open a new terminal session and
bundle exec rake app:update:bin
Solution in my case: - Other solutions didn't work for me.
In your Rails directory:
mv /usr/bin/rails /usr/bin/rails.old
bundle config --delete bin
rm -rf bin
# for rails 4.x:
rake rails:update:bin
# for rails 3.x:
bundle install --binstubs
# if you're using rbenv
rbenv rehash
rm -rf ~/.rbenv/plugins/{rbenv-bundle-exec,rbenv-gemset,bundler}
Also be sure that bin/rails is added to the path like:
PATH=./bin:$PATH
Good luck.
This error may raise when you update your ruby but not the related gems.
To check if this is your case, try to make a new rails app in a new empty directory (to be sure RVM is not autoloading any gemset)
make /tmp/test && cd test && rails new test
If this fails stating that it cannot find a suitable 'rails', then simply run
gem update
and overwrite any conflicting rails.
gem uninstall bundler
gem install bundler
Uninstalling all my versions of Bundler, and then installing the latest version fixed it for me. I had multiple versions of bundler installed, so when I ran bundle exec rails s I think the wrong Bundler was used, giving me the warning message.
You may need to generate new stubs after reinstalling Bundler, but I didn't have to.
I was able to fix this by looking at the commit history for bin/rails using git log -p bin/rails
The current, error producing content is:
#!/usr/bin/env ruby
#
# 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 original, non-error content was:
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rails/commands'
When I restored the original bin/rails content, the warning message disappeared. Previous attempts had returned uninitialized constant Bundler errors on all bundle exec commands, but now they work. It's worth noting that the original content appears to be exactly what rails new blabla generates in rails 4.0.x.
Still, I would like to know why the first code block causes issues because it's exactly what bundle install --binstubs generates.
Edit: turns out this solution does not work. Pushed this fix to a heroku staging server and heroku errors on startup: all bin/rails commands throw uninitialized constant Bundler and heroku starts up with bin/rails server ..... so this is a not really a fix.
Edit2:
If I add these two lines to the second block (the original bin/rails content), all bin/rails commands are working again:
require 'rubygems'
require 'bundler/setup'
My guess is that the second line is what fixes the bundler errors I was having.
Interestingly, when I tried to edit the first block of code in this post to try and debug which line was throwing the warning, any change I made caused all rails commands to failure, with no information except for the nag note in the OP. weird.
Final bin/rails that fixed my issue:
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rubygems'
require 'bundler/setup'
require 'rails/commands'
Any additional insight from people who find this would be welcome!

Execute without `bundle exec` via rubygems-bundler

I have a standard gem scaffold, and in inside the bin directory I have a simple executable (bin/do_things.rb):
#!/usr/bin/env ruby
require 'my_gem'
MyGem::doThings()
The gem hasn't been installed via gem install, so running bin/do_things.rb without bundle exec fails (my Gemfile has the gemspec line in it).
Is there a simple way to have rubygems-bundler execute my script in the bundler context? Should I just modify the $LOAD_PATH in my executable instead?
I could create a wrapper script to execute under Bundler as well, but I'd rather leverage rubygems-bundler somehow.
Or should I just type bundle exec?
try:
bundle exec bash -l
it will set you into bundler context - it's an extra shell so running exit will get you back to bundler less context.
Change the file permission
chmod a+x bin/do_things.rb
and resolve bin path, ignoring symlinks
require "pathname"
bin_file = Pathname.new(__FILE__).realpath
post, add self to libpath
$:.unshift File.expand_path("../../lib", bin_file)
Generating binstubs via bundle install --binstubs creates a wrapper script for all executables listed in my gemspec.
#!/usr/bin/env ruby
#
# This file was generated by Bundler.
#
# The application 'do_things.rb' 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('my_gem', 'do_things.rb')
However, by default, the binstubs path is bin, which conflicts with gem's executable path, and will overwrite files in bin.
Running bundle install --binstubs=SOME_DIR and then adding SOME_DIR to .gitignore seem to be the most maintainable way.
Then, I can simple execute SOME_DIR/do_things or any other project-specific executable I add down the line.

Resources