I Have a Gem Installed But Require 'Gemname' Does Not Work. Why

I have a gem installed but require 'gemname' does not work. Why?

There is no standard for what the file you need to include is. However there are some commonly followed conventions that you can can follow try and make use of:

  • Often the file is called the same
    name as the gem. So require mygem
    will work.
  • Often the file is
    the only .rb file in the lib
    subdirectory of the gem, So if you
    can get the name of the gem (maybe
    you are itterating through
    vendor/gems in a pre 2.1 rails
    project), then you can inspect
    #{gemname}/lib for .rb files, and
    if there is only one, its a pretty
    good bet that is the one to require

If all of that works, then all you can do is look into the gem's directory (which you can find by running gem environment | grep INSTALLATION | awk '{print $4}' and looking in the lib directory, You will probably need to read the files and hope there is a comment explaining what to do

Ruby: Getting a gem's name for require

It seems like that should be part of the gem spec., so I've been nosing around in some of the rubygems gem's modules to see if there was a way to programmatically find out the right require string. So far I haven't found anything. It seems like a hole to me; I've run into the problem you're talking about, and it's a pain. The gem-writers are the ones who know the string, so it should be in the *.gemspec file.

My recommendation is to run gem env at the command-line, and cd into the directories displayed for "GEM PATHS", then into the gems directory, followed by the directory for the gem in question. Inside that directory look for README or similar files and see what they say. If nothing is found run:

grep -r require *

then look through the results for likely candidate strings. If there's a "test" directory, change the "*" to "test" first, to reduce the results to more-likely hits.

For instance, the Net::SSH gem is called "net-ssh", but it's gem is required using net/ssh. Searching with grep showed a lot of instances of require 'net/ssh'.

Ruby - Cannot use locally installed gem

There are potentially two issues. The first is how you are starting Ruby and the second is how you are requiring your module.

First, if you are starting Ruby by running ruby password_reset.rb then you are ignoring the Gemfile. The Gemfile is only used when you're using bundler, so you want to make sure you are starting Ruby by running bundle exec ruby password_reset.rb. This causes bundler to read your Gemfile and execute Ruby in that context.

Second, you're not properly including your module in your Ruby file. Just because you've added the gem to your Gemfile and started Ruby using bundler doesn't mean that the Ruby process knows you intend to use that gem's module; it just makes the module available for use. You might wonder, "Why don't I have to do that in Rails?" Because Rails does that for you automatically via config/application.rb.

Given these two issues, the correct way to accomplish your goal is to configure your app as follows:

First, create your Gemfile:

# Gemfile
gem 'password_generator', path: '~/workspace/gems/password_generator'

Second, create your password_reset.rb file:

# password_reset.rb
# Manually require any libraries that this app will use, even if defined in Gemfile
require 'password_generator'
# Call `puts` so something is printed to the console when this app runs
puts PasswordGenerator.generate

Third, run bundle install to ensure your Gemfile is properly formatted and to generate your Gemfile.lock:

⇒  bundle install
Using bundler 1.16.5
Using password_generator 0.1.0 from source at `../../gems/password_generator`
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

Fourth, run bundle exec ruby password_reset.rb and observe the output:

⇒  bundle exec ruby password_reset.rb
kpiDfyTxtdAsKmYuZqmK

Everything works because:

  1. Ruby is started with Bundler
  2. Bundler reads your Gemfile and makes the gems available to Ruby
  3. Your app requires the module from the gem before attempting to use the module

Ruby loadError when running require 'gemname' on irb

Problem solved.

First I create, on gemname folder, Gemfile. Inside looks like:

# A sample Gemfile
source "https://rubygems.org"
gemspec
# gem "rails"

Reinstalled the gem, Gemfile.lock was created.

Then I ran irb via bundle exec irb instead of typing irb.

require 'gemname' works.

Using gems in rails -- require 'gemname' results in No File Found

I just installed this gem and made a new rails 3 app, added it to the Gemfile and I can access it fine from 'rails console' and from within the app when running 'rails server' and also from 'irb'. Are you sure you've typed the gem name correctly? I confused myself by typing 'twitter_oath' a few times and not 'twitter_oauth'...

Have you got the latest rubygems? perhaps try:

$ sudo gem install rubygems-update
$ sudo gem update --system
$ sudo gem update

Are you using rails 3? What OS & ruby are you using?

How to rescue from a require gem_name when the gem is not installed

require raises a LoadError exception if it can't load the required library. However, you never rescue from LoadError anywhere, you rescue from StandardError.

If you want to rescue from LoadError, you have to say so:

begin 
require 'some_gem'
rescue LoadError
puts 'please install some_gem first!'
end

Even better yet, make sure that you are actually printing the correct missing dependency:

begin 
require 'some_gem'
rescue LoadError => e
raise unless e.message =~ /some_gem/
puts 'please install some_gem first!'
end

(This re-raises the exact same exception that was rescued from, in case that the exception was actually caused by some other missing library somewhere else. You wouldn't want to print misleading information, right?)

Depending on what the intended target audience for the library is and whether or not they might be scared away by a backtrace being dumped to their console, you might want to re-raise the exception in any case, instead of just swallowing it:

begin 
require 'some_gem'
rescue LoadError => e
puts 'please install some_gem first!' if e.message =~ /some_gem/
raise
end

Or, you could skip the puts and instead raise an exception with the message set to what you want to say:

begin 
require 'some_gem'
rescue LoadError => e
raise e.exception('please install some_gem first!') if e.message =~ /some_gem/
raise
end

Except now the exception is raised in the wrong place and thus has the wrong line number and stacktrace and thus is misleading, but that is easily fixed:

begin 
require 'some_gem'
rescue LoadError => e
raise unless e.message =~ /some_gem/
friendly_ex = e.exception('please install some_gem first!')
friendly_ex.set_backtrace(e.backtrace)
raise friendly_ex
end

Now you print pretty much the same thing that you would have printed with the puts, but you have a "proper" exception that for example allows better debugging or allows a consumer of your library to rescue that exception and handle it their way, both of which would have been impossible or at least hard with your solution that just swallows the exception.

Requiring a gem using internally a different name

require 'google/search' is correct for your gem

The return value of false means that Ruby found your gem library file google/search.rb but has already parsed and loaded it. It would return true only if the library had not already been loaded.

Reference: http://www.ruby-doc.org/core-2.1.1/Kernel.html#method-i-require

It is possible that the require has found a conflicting file - anything in the gem search path matching google/search.rb could in theory be loaded, the gem name itself is not relevant other than .../gemname/lib gets added to the search path. It is this potential for gems to claim file names from each other which drives conventions such as naming your main library file identically to the gem, but as long as one derives reasonably directly and/or uniquely from the other, it should be fine to use different names.

For a gem called google-search, the advice on Rubygems says users should expect to use the require as you want it, so you are following normal Ruby convention here.

(...)in `require': no such file to load -- 'gemname' (LoadError)

You could invoke you ruby script with

ruby -rubygems script.rb

or add rubygems to RUBYOPT

$ export RUBYOPT="rubygems"

If a gem is not listed using the following command, does that mean it's not installed?

To see if it's installed:

gem list bundler

Gives:

*** LOCAL GEMS ***

bundler (1.1.3)

To find the gem source code:

gem which bundler

Gives:

/path/to/directory/.rvm/gems/ruby-1.9.3-p125@global/gems/bundler-1.1.3/lib/bundler.rb


Related Topics



Leave a reply



Submit