How to check if a gem is installed?
General solution
To get the full list of gems that are installed:
gem list
To test for a particular gem, you can use -i
with a regex:
gem list -i "^gem_name$"
(Credit to Timo in the comments for this technique.)
Specific solution for OP
If you can't find data_mapper, it may be that the gem name is different from what you expect.
Also, if you're just doing which brew
to find brew, you aren't finding the gem called brew, you're finding the location of the brew executable. Try gem which brew
instead.
If you're looking for data_mapper by doing which data_mapper
, you probably won't find it. which
is a unix program for finding unix executables, and data_mapper probably doesn't have one.
Since your goal is to verify a gem is installed with the correct version, use gem list
. You can limit to the specific gem by using gem list data_mapper
.
To verify that it's installed and working, you'll have to try to require
the gem and then use it in your code.
programmatically determine if a certain gem is installed, then install it if not
# The version requirements are optional.
# You can also specify multiple version requirements, just append more at the end
gem_name, *gem_ver_reqs = 'json', '~> 1.8.0'
gdep = Gem::Dependency.new(gem_name, *gem_ver_reqs)
# find latest that satisifies
found_gspec = gdep.matching_specs.max_by(&:version)
# instead of using Gem::Dependency, you can also do:
# Gem::Specification.find_all_by_name(gem_name, *gem_ver_reqs)
if found_gspec
puts "Requirement '#{gdep}' already satisfied by #{found_gspec.name}-#{found_gspec.version}"
else
puts "Requirement '#{gdep}' not satisfied; installing..."
# reqs_string will be in the format: "> 1.0, < 1.2"
reqs_string = gdep.requirements_list.join(', ')
# multi-arg is safer, to avoid injection attacks
system('gem', 'install', gem_name, '-v', reqs_string)
end
More recent rubygems versions provide an installer API, so instead of shelling out to the gem
command you could also use:
# using the same "gdep" variable as above
Gem.install gem_name, gdep.requirement
However, I'm not sure if Gem.install
respects your .gemrc
file.
There are a lot of useful methods for querying your installed gems (see rdocs). Some that might be helpful:
Gem::Specification.find_all_by_name
Gem::Requirement#satisfied_by?(gem_version_instance)
Gem::Specification#satisfies_requirement?(gem_dependency_instance)
Gem.loaded_specs
- hash of the gems you've actually loaded via thegem
method, or byrequire
List of installed gems?
The Gem command is included with Ruby 1.9+ now, and is a standard addition to Ruby pre-1.9.
require 'rubygems'
name = /^/i
dep = Gem::Dependency.new(name, Gem::Requirement.default)
specs = Gem.source_index.search(dep)
puts specs[0..5].map{ |s| "#{s.name} #{s.version}" }
# >> Platform 0.4.0
# >> abstract 1.0.0
# >> actionmailer 3.0.5
# >> actionpack 3.0.5
# >> activemodel 3.0.5
# >> activerecord 3.0.5
Here's an updated way to get a list:
require 'rubygems'
def local_gems
Gem::Specification.sort_by{ |g| [g.name.downcase, g.version] }.group_by{ |g| g.name }
end
Because local_gems
relies on group_by
, it returns a hash of the gems, where the key is the gem's name, and the value is an array of the gem specifications. The value is an array of the instances of that gem that is installed, sorted by the version number.
That makes it possible to do things like:
my_local_gems = local_gems()
my_local_gems['actionmailer']
# => [Gem::Specification.new do |s|
# s.authors = ["David Heinemeier Hansson"]
# s.date = Time.utc(2013, 12, 3)
# s.dependencies = [Gem::Dependency.new("actionpack",
# Gem::Requirement.new(["= 4.0.2"]),
# :runtime),
# Gem::Dependency.new("mail",
# Gem::Requirement.new(["~> 2.5.4"]),
# :runtime)]
# s.description = "Email on Rails. Compose, deliver, receive, and test emails using the familiar controller/view pattern. First-class support for multipart email and attachments."
# s.email = "david@loudthinking.com"
# s.homepage = "http://www.rubyonrails.org"
# s.licenses = ["MIT"]
# s.name = "actionmailer"
# s.require_paths = ["lib"]
# s.required_ruby_version = Gem::Requirement.new([">= 1.9.3"])
# s.requirements = ["none"]
# s.rubygems_version = "2.0.14"
# s.specification_version = 4
# s.summary = "Email composition, delivery, and receiving framework (part of Rails)."
# s.version = Gem::Version.new("4.0.2")
# end]
And:
puts my_local_gems.map{ |name, specs|
[
name,
specs.map{ |spec| spec.version.to_s }.join(',')
].join(' ')
}
# >> actionmailer 4.0.2
...
# >> arel 4.0.1,5.0.0
...
# >> ZenTest 4.9.5
# >> zucker 13.1
The last example is similar to the gem query --local
command-line, only you have access to all the information for a particular gem's specification.
How to find where gem files are installed
Use gem environment
to find out about your gem environment:
RubyGems Environment:
- RUBYGEMS VERSION: 2.1.5
- RUBY VERSION: 2.0.0 (2013-06-27 patchlevel 247) [x86_64-darwin12.4.0]
- INSTALLATION DIRECTORY: /Users/ttm/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0
- RUBY EXECUTABLE: /Users/ttm/.rbenv/versions/2.0.0-p247/bin/ruby
- EXECUTABLE DIRECTORY: /Users/ttm/.rbenv/versions/2.0.0-p247/bin
- SPEC CACHE DIRECTORY: /Users/ttm/.gem/specs
- RUBYGEMS PLATFORMS:
- ruby
- x86_64-darwin-12
- GEM PATHS:
- /Users/ttm/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0
- /Users/ttm/.gem/ruby/2.0.0
- GEM CONFIGURATION:
- :update_sources => true
- :verbose => true
- :backtrace => false
- :bulk_threshold => 1000
- REMOTE SOURCES:
- https://rubygems.org/
- SHELL PATH:
- /Users/ttm/.rbenv/versions/2.0.0-p247/bin
- /Users/ttm/.rbenv/libexec
- /Users/ttm/.rbenv/plugins/ruby-build/bin
- /Users/ttm/perl5/perlbrew/bin
- /Users/ttm/perl5/perlbrew/perls/perl-5.18.1/bin
- /Users/ttm/.pyenv/shims
- /Users/ttm/.pyenv/bin
- /Users/ttm/.rbenv/shims
- /Users/ttm/.rbenv/bin
- /Users/ttm/bin
- /usr/local/mysql-5.6.12-osx10.7-x86_64/bin
- /Users/ttm/libsmi/bin
- /usr/local/bin
- /usr/bin
- /bin
- /usr/sbin
- /sbin
- /usr/local/bin
Notice the two sections for:
INSTALLATION DIRECTORY
GEM PATHS
How to tell which version of a gem a rails app is using
In Rails 3 and Rails 4, use bundle show
In Rails 2, rake gems
will print out what gems, dependencies, and versions are installed, frozen, etc.
How does Homebrew check for installed gems?
The actual check that is run to detect installed gems and similar things is in /usr/local/Library/Homebrew/requirements/language_module_dependency.rb
, which in the case of Ruby does:
/usr/bin/env ruby -rubygems -e require\ 'GEMNAME'
Note that this calls ruby
from the path, so it could be affected by mixups there. Make sure you have the right ruby
first in your path, have the right gem
program that goes with ruby
, and possibly add some debugging to your formula to see what environment it is running under.
Related Topics
Activerecord Objects in Hashes Aren't Garbage Collected -- a Bug or a Sort of Caching Feature
Instance and Class Variables in Rails Controller
"Rmagick" Gem Installation Issue
What Is the Easiest Way I Can Create a 'Beep' Sound from a Ruby Program
Capistrano & Bash: Ignore Command Exit Status
Using Typeahead from Twitter Bootstrap in a Form (Formtastic)
How to Put Assertions in Ruby Code
Ruby Merging Two Arrays into One
Spinach VS Cucumber for Bdd in Rails
Installing Gem Fails with Permissions Error
Using a Ruby Script to Login to a Website via Https
An Error Occurred While Installing Debugger-Linecache (1.1.1), and Bundler Cannot Continue
How to Check What Is Queued in Activejob Using Rspec
Ruby Koan 151 Raising Exceptions
What's the Best Way to Parse a Tab-Delimited File in Ruby