Execute without `bundle exec` via rubygems-bundler - ruby

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.

Related

Require files from gem in Ruby script without bundle exec

I have a script that needs to require specific files out of gems defined in the project Gemfile.
#!/usr/bin/env ruby
require 'some_gem/helpers/some_helper'
... rest of script
When I run the script, I get an error about not being able to load some_helper.rb. If I run with bundle exec command... then everything works.
I understand that bundle exec exposes the Gems to the $LOAD_PATH which lets require work. Is there a way to move that capability into the script so users don't have to type bundle exec?
Do I just need to add require "bundler/setup" to the script before I require the gem files?
http://bundler.io/v1.12/#getting-started
:)
#!/usr/bin/env ruby
require 'rubygems' # because reasons.. most probably it is not needed unless you are using really old ruby where it is not loaded by default
# also at the moment rubygems and bundler are being merged :)
require 'bundler/setup' # for things installed with bundler
require 'some_gem/helpers/some_helper'
You can also check e.g. http://mislav.net/2013/01/understanding-binstubs/

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.

Building gem, executable not found

I'm in the process of writing my first ruby gem and I'm a little new at the whole structure of setting up gems. My understanding from reading this guide is that in order to create an executable for my gem I need to do the following:
Add a line to my gemspec specifiying the name of the executable like this:
s.executables << 'gemname'
Build the gem with
gem build gemname.gemspec
Install the gem locally (if you try to install by pushing to rubygems each time you'll end up having to change versions constantly) with
gem install gemname-0.0.1.pre.gem
Then test it out with
gemname foo-arguments, --bar-options
If I go through all these steps then on #4 I get the following error:
$ gemname
zsh: command not found: gemname
Assuming that the executable a file starting with a shebang and located at gemname/bin/gemname
Everything works just fine if I navigate to the root of the gem folder and run bin/gemname to test out the executable.
Here is a gist of my current gemspec and the gem source is available on github here.
You need to add all the files that need be included with the gem in spec.files. You missed to add the files that you have in the bin directory.
For example, I have the following configuration from one of my gems:
Gem::Specification.new do |spec|
spec.files = Dir["{bin,lib}/**/*", "LICENSE", "README.md"]
spec.test_files = Dir["spec/**/*"]
spec.require_paths = ["lib"]
spec.executables = ["yarr"]
end
Your gemspec is trying to change the load path. I would suggest fixing that first, because what you're reporting seems to be consistent with a gem not being able to find its files.
Look at your gemspec for this code:
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
Then see http://guides.rubygems.org/patterns/
"Gems should not change the $LOAD_PATH variable. RubyGems manages this for you. Code like this should not be necessary ..."
See http://guides.rubygems.org/patterns/ for various solutions to load using the existing load path, and helpers such as require_relative.
In addition you need to ensure your executable is, well, executable.
$ chmod a+x bin/gemname
Otherwise the command won't be available after building the gem.

How to install a gem to the current folder

I want to use a Ruby gem locally (not install it for the entire machine) for use in a single script. I know how to install gems with Bundler with a Gemfile and bundle install. But for a simple script, this seems overkill to set up bundler.
Is there a way to install a gem to a subfolder of my script and use it, similar to the way npm installs Node.js packages in node_modules?
Here's what I have tried so far.
gem install -i ruby plist installs the plist gem in ruby/gems/plist-3.1.0
I tried to require it in my script extract.rb by doing require './ruby/gems/plist-3.1.0/lib/plist but that fails with require: cannot load such file: plist/generator (plist/generator.rb is required by lib/plist.rb).
Ruby 2.0 on OSX
You can bundle install to a different location with the --path option, for example:
bundle install --path vendor/bundle
Also see http://bundler.io/v1.1/bundle_install.html
If you don't want to involve Bundler, just install your gems locally as in your example and then set the GEM_PATH env in your script before your require, e.g.:
#!/usr/bin/env ruby
ROOT = File.expand_path('..', __FILE__)
ENV['GEM_PATH'] = File.join(ROOT, 'ruby')
# or to just append to
# ENV['GEM_PATH'] += ":#{ File.join(ROOT, 'ruby') }"
require 'plist'
assuming your script is in the same folder as the ruby folder (otherwise adjust the filepath accordingly).
You can do it by creating gemset for particular application. follow these steps for that -
$ rvm gemset create <gemset_name>
It will create a gemset for currently selected ruby version.
you can check currently selected ruby version by this command -
$ rvm list
Then navigate to your app directory by cd into it.
now execute this command -
$ rvm use #<gemset_name>
Now whenever you install any gem it will be installed in current gemset which is being used not for the entire machine.
Make sure - you run gem install bundler in newly created gemset so it will not raise error when you will run bundle install.

Why do I need bundle exec to require this rubygem?

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.

Resources