Script Runs With 'bundler Exec Ruby Script.rb' But Fails When Using 'ruby Script.rb'
I have a script that requires a gem that i'm getting from a private github repo with a specific branch (lets just call this gem
I'm using rvm, rails verson 2.3.0, and a gemset (lets call it testset). I'm using bundler to install my gems.
When I execute my script using
bundler exec ruby script.rb it runs fine. However when I try running it using
ruby script.rb I get the following error:
require': cannot load such file -- foobar (LoadError)
Its also worth noting that using only ruby works if I use the path to the gem as follows:
require '~/.rvm/gems/[email protected]/bundler/gems/foobar-a41fed1fcab7/lib/foobar.rb'
Is there anyway I can use
ruby script.rb while only using
If you don't use
bundle exec, then
require will work to require gems that are installed in your system gems. It will require the latest (larger number version) gem currently installed in the system; if no gems with that name are installed in the system, it will give you the LoadError.
require isn't only used for loading gems, it can also be used to load other files on the load path, but for the purpose of this question we're talking about it's ability to load gems).
You don't have the
foobar gem installed on your system, so you get the LoadError.
So why does it work with
bundle exec? bundler is a dependency management tool. When you use
bundle exec, bundler loads the exact versions of gems you specified in your Gemfile/Gemfile.lock files, and makes them available to
require. In this case,
require gemname won't neccesarily load the latest version installed on your system, it will load exactly the version specified in the Gemfile.lock -- because
bundle exec sets things up to do that.
Ordinarily bundler also installs all gems to the system location when you run
bundle install. But there are some cases where bundler installs the gems only "locally" in the current directory, and not in the general system gem location. One of these cases is if you tell it to with the
path argument. But that's not what's going on for you. Another case is if you tell bundler to load a gem directly from a git repo, with the
:github arguments in a Gemfile. The general gem system isn't capable of loading gems directly from a git repo, that's only a bundler feature. So if you have something listed in your Gemfile with
:git option, it will always only be installed for the local app, not in the system-wide gem location. I think that's what's going on in this case, the clue was the
gems/foobar-a41fed1fcab7 in the path of your example that works -- gems listed with something like
-a41fed1fcab7 on the end of their name are typically direct-from-git-repo gems, the
a41fed1fcab7 is a git SHA identifying exactly what version from the git repo is currently being used.
I can tell from your path that you are also using rvm gemsets, which complicates the matter a bit further, but this is confusing enough so I didn't go into that -- everything I wrote still stands, except "your system-wide gems" is really "the current rvm gemset". Personally, I believe you'd be better off not using the rvm gemset feature -- things are confusing enough without it, and it isn't really needed anymore now that we have bundler, rvm gemsets were invented before bundler existed (several years ago). And I'm not totally sure why people keep using them now!
Is there anyway I can use ruby script.rb while only using require 'foobar?
Sure. You just need to make sure
foobar is installed to your system gems, with
gem install foobar. Then
require "foobar" will load the latest version installed to your system gems. (But you can only install released gems with specific version numbers to your system gems, not arbitrary checkouts from git). What if you want to load a specific version? Well, you can do something like
gem 'foobar', "1.0.2" instead of
require 'foobar'. But with a list of gem dependencies that are at all non-trivial, you will soon start to get into a terrible mess of managing exactly what version of a gem you are using is compatible with what version of another gem you are using. As well as setting up a new system and figuring out exactly what version of gems you need to install from scratch to work with
script.rb. It becomes a real mess. It is for this that
bundler was invented, and you'd be wise to use it.
(Although sure, you could use rvm gemsets instead of bundler -- but not with gems installed direct from git, only bundler supports that, at least without a lot of manual hackery, and rvm gemsets aren't very good when it comes to setting up a new system from scratch, bundle solves that a lot better).
If you do have a Gemfile and Gemfile.lock in the same directory as
script.rb (as you seem to), and you just want to avoid having to write
bundle exec, you can just put this at the top of
script.rb (before any other
require 'bundler' Bundler.setup
That basically just tells bundler to do the equivalent of
bundle exec when
script.rb is run, without actually having to write
bundle exec. Then you can just run
ruby script.rb (or even
./script.rb), and it'll still do the same thing as
bundle exec, but without having to write it on the command line.
Hope this helps.
- → Trigger a click with jQuery using link_to of rails 4
- → Adding html data attribute to simple_forms input
- → How to remove parameters from the root URL if it does I18n
- → passing parameters to rails back end from an ajax call
- → Blocking ?page= in robots.txt
- → react js and rails Updating state on a component with active record relationship
- → State not passed into prop
- → Cannot read property 'modalIsOpen' of undefined
- → Objects not valid issue
- → How can I add a featured image from a blog post to my homepage on shopify
- → Need "add to cart" button price to update with correct amount depending on what checkbox is checked
- → GET /admin/webhooks.json returns an empty array