# RubyGems Guides > Everything about library management in Ruby: learn what gems are, how to use them in your projects, and how to build and publish your own. --- # Installation Source: https://guides.rubygems.org/installation/ How to get RubyGems and Bundler and keep them up to date. RubyGems and Bundler ship with Ruby, so installing Ruby gives you both tools. To check that they are available: gem --version bundle --version If you do not have Ruby yet, see the [official installation guide](https://www.ruby-lang.org/en/documentation/installation/) for the options available on your platform. Updating RubyGems ----------------- Ruby comes with the RubyGems version that was current when that Ruby was released. To upgrade to the latest version: gem update --system To upgrade to a specific version instead, pass the version number: gem update --system Both forms download the `rubygems-update` gem and run its `setup.rb`, so they need network access. On a machine without it, fetch the release archive from the [download page](https://rubygems.org/pages/download) elsewhere, copy it over, then unpack it and install from the unpacked directory: ruby setup.rb Run `ruby setup.rb --help` for the available options. Updating Bundler ---------------- To install the latest Bundler: gem install bundler Bundler is a [default gem](/default-gems-and-bundled-gems), so every Ruby installation always contains a version of it that cannot be uninstalled. Installing a newer version does not replace the default one. Both stay available. Which Bundler version runs -------------------------- A project's `Gemfile.lock` records the Bundler version that created it under `BUNDLED WITH`. When you run `bundle` commands in that project, Bundler automatically switches to the recorded version if it is installed, even when a newer version is present. To update the recorded version to the latest installed Bundler, run `bundle update --bundler`. See [Bundler compatibility](/bundler-compatibility) for the Ruby and RubyGems versions each Bundler release supports. --- # RubyGems Basics Source: https://guides.rubygems.org/rubygems-basics/ Use of common RubyGems commands The `gem` command allows you to interact with RubyGems. RubyGems ships with Ruby, so the `gem` command is available as soon as Ruby is installed. See the [Installation guide](/installation) to check your setup or to upgrade RubyGems itself. If you want to see how to require files from a gem, skip ahead to [What is a gem](/what-is-a-gem) * [Finding Gems](#finding-gems) * [Installing Gems](#installing-gems) * [Running Executables Without Installing](#running-executables-without-installing) * [Requiring Code](#requiring-code) * [Listing Installed Gems](#listing-installed-gems) * [Uninstalling Gems](#uninstalling-gems) * [Viewing Documentation](#viewing-documentation) * [Fetching and Unpacking Gems](#fetching-and-unpacking-gems) * [Further Reading](#further-reading) Finding Gems ------------ The `search` command lets you find remote gems by name. You can use regular expression characters in your query: $ gem search ^rails *** REMOTE GEMS *** rails (8.1.3) rails-3-settings (0.1.1) rails-access-control (0.0.3) rails-acm (0.1.0) rails-action-args (0.1.1) [...] If you see a gem you want more information on you can add the details option. You'll want to do this with a small number of gems, though, as listing gems with details requires downloading more files: $ gem search ^rails$ -d *** REMOTE GEMS *** rails (8.1.3) Author: David Heinemeier Hansson Homepage: https://rubyonrails.org License: MIT Full-stack web application framework. You can also search for gems on rubygems.org such as [this search for rake](https://rubygems.org/search?query=rake) Installing Gems --------------- The `install` command downloads and installs the gem and any necessary dependencies then builds documentation for the installed gems. $ gem install drip Fetching drip-0.1.1.gem Fetching rbtree-0.4.5.gem Building native extensions. This could take a while... Successfully installed rbtree-0.4.5 Successfully installed drip-0.1.1 Parsing documentation for rbtree-0.4.5 Installing ri documentation for rbtree-0.4.5 Parsing documentation for drip-0.1.1 Installing ri documentation for drip-0.1.1 Done installing documentation for rbtree, drip after 0 seconds 2 gems installed Here the drip command depends upon the rbtree gem which has an extension. RubyGems installs the dependency rbtree and builds its extension, installs the drip gem, then builds documentation for the installed gems. You can disable documentation generation using the `--no-document` argument when installing gems. Running Executables Without Installing -------------------------------------- The `exec` command runs an executable from a gem, installing the gem first if necessary. It is a shortcut for running `gem install` and then the command itself: $ gem exec rails new my_app RubyGems uses the most recent version of the gem unless you specify one with `--version` or allow prereleases with `--prerelease`. Pass `--conservative` to prefer the most recent version that is already installed. If the executable name differs from the gem name, name the gem with `--gem`. Gems installed this way are kept separate from your user-installed gems. See [gem exec](/command-reference#gem-exec) in the Command Reference for details. Requiring code -------------- RubyGems modifies your Ruby load path, which controls how your Ruby code is found by the `require` statement. When you `require` a gem, really you're just placing that gem's `lib` directory onto your `$LOAD_PATH`. Let's try this out in `irb`. % irb irb(main):001> pp $LOAD_PATH [".../lib/ruby/site_ruby/4.0.0", ".../lib/ruby/site_ruby/4.0.0/arm64-darwin27", ".../lib/ruby/site_ruby", ".../lib/ruby/vendor_ruby/4.0.0", ".../lib/ruby/vendor_ruby/4.0.0/arm64-darwin27", ".../lib/ruby/vendor_ruby", ".../lib/ruby/4.0.0", ".../lib/ruby/4.0.0/arm64-darwin27"] By default you have just a few system directories on the load path and the Ruby standard libraries. To add the awesome_print directories to the load path, you can require one of its files: $ gem install awesome_print [...] $ irb irb(main):001> require "ap" => true irb(main):002> pp $LOAD_PATH.first ".../gems/awesome_print-1.9.2/lib" *Tip: Passing `-r` to `irb` will automatically require a library when irb is loaded.* $ irb -rap irb(main):001> ap $LOAD_PATH [ [0] ".../gems/awesome_print-1.9.2/lib", [1] ".../lib/ruby/site_ruby/4.0.0", [2] ".../lib/ruby/site_ruby/4.0.0/arm64-darwin27", [3] ".../lib/ruby/site_ruby", [4] ".../lib/ruby/vendor_ruby/4.0.0", [5] ".../lib/ruby/vendor_ruby/4.0.0/arm64-darwin27", [6] ".../lib/ruby/vendor_ruby", [7] ".../lib/ruby/4.0.0", [8] ".../lib/ruby/4.0.0/arm64-darwin27" ] Once you've required `ap`, RubyGems automatically places its `lib` directory on the `$LOAD_PATH`. That's basically it for what's in a gem. Drop Ruby code into `lib`, name a Ruby file the same as your gem (for the gem "freewill" the file should be `freewill.rb`, see also [name your gem](/name-your-gem)) and it's loadable by RubyGems. The `lib` directory itself normally contains only one `.rb` file and a directory with the same name as the gem which contains the rest of the files. For example: % tree freewill/ freewill/ └── lib/ ├── freewill/ │ ├── user.rb │ ├── widget.rb │ └── ... └── freewill.rb Listing Installed Gems ---------------------- The `list` command shows your locally installed gems: $ gem list *** LOCAL GEMS *** abbrev (0.1.2) awesome_print (1.9.2) base64 (0.3.0) benchmark (0.5.0) bigdecimal (4.0.1) bundler (default: 4.0.16) csv (3.3.5) date (default: 3.5.1) debug (1.11.1) delegate (default: 0.6.1) did_you_mean (default: 2.0.0) digest (default: 3.2.1) drb (2.2.3) drip (0.1.1) english (default: 0.8.1) [...] The list includes default gems and bundled gems both of which were shipped with Ruby by default. In Ruby 4.0, the default gems are 46 gems in total including bundler, erb, json, psych etc. and the bundled gems are csv, debug, rake etc. Uninstalling Gems ----------------- The `uninstall` command removes the gems you have installed. $ gem uninstall drip Successfully uninstalled drip-0.1.1 If you uninstall a dependency of a gem RubyGems will ask you for confirmation. $ gem uninstall rbtree You have requested to uninstall the gem: rbtree-0.4.5 drip-0.1.1 depends on rbtree (>= 0) If you remove this gem, these dependencies will not be met. Continue with Uninstall? [yN] n ERROR: While executing gem ... (Gem::DependencyRemovalException) Uninstallation aborted due to dependent gem(s) Viewing Documentation --------------------- You can view the documentation for your installed gems with `ri`: $ ri RBTree = RBTree < MultiRBTree (from gem rbtree-0.4.5) ------------------------------------------------------------------------ A sorted associative collection that cannot contain duplicate keys. RBTree is a subclass of MultiRBTree. ------------------------------------------------------------------------ Fetching and Unpacking Gems --------------------------- If you wish to audit a gem's contents without installing it you can use the `fetch` command to download the .gem file then extract its contents with the `unpack` command. $ gem fetch malice Fetching malice-13.gem Downloaded malice-13 $ gem unpack malice-13.gem Unpacked gem: '.../malice-13' $ more malice-13/README Malice v. 13 DESCRIPTION A small, malicious library. [...] $ rm -r malice-13* You can also unpack a gem you have installed, modify a few files, then use the modified gem in place of the installed one: $ gem unpack rake Unpacked gem: '.../rake-13.4.2' $ vim rake-13.4.2/lib/rake/... $ ruby -I rake-13.4.2/lib -S rake some_rake_task [...] The `-I` argument adds your unpacked rake to the ruby `$LOAD_PATH` which prevents RubyGems from loading the gem version (or the default version). The `-S` argument finds `rake` in the shell's `$PATH` so you don't have to type out the full path. Further Reading --------------- This guide only shows the basics of using the `gem` command. For information on what's inside a gem and how to use one you've installed see the next section, [What is a gem](/what-is-a-gem). For a complete reference of gem commands see the [Command Reference](/command-reference). --- # Getting Started Source: https://guides.rubygems.org/getting_started/ ## What is Bundler? Bundler provides a consistent environment for Ruby projects by tracking and installing the exact gems and versions that are needed. Bundler is an exit from dependency hell, and ensures that the gems you need are present in development, staging, and production. Starting work on a project is as simple as `bundle install`. What's new in Bundler Managing dependencies ## Getting Started This guide assumes that you have [Ruby](https://www.ruby-lang.org/en/downloads/) installed. If you do not have Ruby installed, do that first and then check back here! Any modern distribution of Ruby comes with Bundler preinstalled by default. Getting started with bundler is easy! Specify your dependencies in a Gemfile in your project's root: ~~~ruby source 'https://rubygems.org' gem 'nokogiri' gem 'rack', '~> 2.2.4' gem 'rspec' ~~~ Learn More: Gemfiles Install all of the required gems from your specified sources: ~~~ $ bundle install $ git add Gemfile Gemfile.lock ~~~ Learn More: bundle install The second command adds the Gemfile and Gemfile.lock to your repository. This ensures that other developers on your app, as well as your deployment environment, will all use the same third-party code that you are using now. Inside your app, load up the bundled environment: ~~~ruby require 'bundler/setup' # require your gems as usual require 'nokogiri' ~~~ Learn More: Bundler.setup Run an executable that comes with a gem in your bundle: ~~~ $ bundle exec rspec spec/models ~~~ In some cases, running executables without `bundle exec` may work, if the executable happens to be installed in your system and does not pull in any gems that conflict with your bundle. However, this is unreliable and is the source of considerable pain. Even if it looks like it works, it may not work in the future or on another machine. Finally, if you want a shortcut to the executables of a gem in your bundle, generate binstubs for it: ~~~ $ bundle binstubs rspec-core $ bin/rspec spec/models ~~~ The executables installed into `bin` are scoped to the bundle, and will always work. Learn More: Executables ## Create a rubygem with Bundler Bundler is also an easy way to create new gems. Just like you might create a standard Rails project using `rails new`, you can create a standard gem project with `bundle gem`. Create a new gem with a README, .gemspec, Rakefile, directory structure, and all the basic boilerplate you need to describe, test, and publish a gem: ~~~ $ bundle gem my_gem Creating gem 'my_gem'... create my_gem/Gemfile create my_gem/.gitignore create my_gem/lib/my_gem.rb create my_gem/lib/my_gem/version.rb create my_gem/my_gem.gemspec create my_gem/Rakefile create my_gem/README.md create my_gem/bin/console create my_gem/bin/setup create my_gem/CODE_OF_CONDUCT.md create my_gem/LICENSE.txt create my_gem/.travis.yml create my_gem/test/test_helper.rb create my_gem/test/my_gem_test.rb Initializing git repo in ./my_gem ~~~ Learn More: bundle gem ## Use Bundler with Rails Sinatra RubyGems ## Get involved Bundler has a lot of contributors and users, and they all talk to each other quite a bit. If you have questions, try [the IRC channel](http://webchat.freenode.net/?channels=bundler) or [mailing list](http://groups.google.com/group/ruby-bundler). If you're interested in contributing to the project (no programming skills needed), read [the contributing guide](/contributing) or [the development guide](https://github.com/ruby/rubygems/tree/master/doc#development). While participating in the Bundler project, please keep the [code of conduct](https://github.com/ruby/rubygems/blob/HEAD/CODE_OF_CONDUCT.md) in mind, and be inclusive and friendly towards everyone. If you have sponsorship or security questions, please contact the core team directly. Code of Conduct #bundler on IRC Mailing list Contributing GitHub Discussions --- # Make your own gem Source: https://guides.rubygems.org/make-your-own-gem/

From start to finish, learn how to package your Ruby code in a gem.

* [Introduction](#introduction) * [Your first gem](#your-first-gem) * [Starting with bundle gem](#starting-with-bundle-gem) * [Requiring more files](#requiring-more-files) * [Using other gems](#using-other-gems) * [Writing tests](#writing-tests) * [Adding an executable](#adding-an-executable) * [Documenting your code](#documenting-your-code) * [Releasing your gem](#releasing-your-gem) * [Wrapup](#wrapup) Introduction ------------ Why create a gem? You could just throw some code into your other project and use it directly. But what if you want to use that code elsewhere, or share it with others? A gem lets you package your library separately and reuse it across projects with a simple `gem install` or a line in a Gemfile. When you need it in another project, it’s a tiny modification rather than a whole lot of copying. Creating and publishing your own gem is simple thanks to the tools baked right into RubyGems. Let’s make a simple “hello world” gem, and feel free to play along at home! The code for the gem we’re going to make here is up [on GitHub](https://github.com/qrush/hola). Your first gem -------------- I started with just one Ruby file for my `hola` gem, and the gemspec. You'll need a new name for yours (maybe `hola_yourusername`) to publish it. Check the Patterns guide for [basic recommendations](/patterns/#consistent-naming) to follow when naming a gem. $ tree . ├── hola.gemspec └── lib └── hola.rb Code for your package is placed within the `lib` directory. The convention is to have *one* Ruby file with the *same* name as your gem, since that gets loaded when `require "hola"` is run. That one file is in charge of setting up your gem's code and API. The code inside of `lib/hola.rb` is pretty bare bones. It just makes sure that you can see some output from the gem: $ cat lib/hola.rb class Hola def self.hi puts "Hello world!" end end The gemspec defines what’s in the gem, who made it, and the version of the gem. It’s also your interface to [RubyGems.org](https://rubygems.org). All of the information you see on a gem page (like [jekyll](https://rubygems.org/gems/jekyll)’s) comes from the gemspec. $ cat hola.gemspec Gem::Specification.new do |s| s.name = "hola" s.version = "0.0.0" s.summary = "Hola!" s.description = "A simple hello world gem" s.authors = ["Nick Quaranto"] s.email = "nick@quaran.to" s.files = ["lib/hola.rb"] s.homepage = "https://rubygems.org/gems/hola" s.license = "MIT" end > The description member can be much longer than you see in this example. If it > matches `/^== [A-Z]/` then the description will be run through > [RDoc's markup formatter](https://github.com/ruby/rdoc) for display on > the RubyGems web site. Be aware though that other consumers of the data might > not understand this markup. Look familiar? The gemspec is also Ruby, so you can wrap scripts to generate the file names and bump the version number. There are lots of fields the gemspec can contain. To see them all check out the full [reference](/specification-reference/). After you have created a gemspec, you can build a gem from it. Then you can install the generated gem locally to test it out. $ gem build hola.gemspec Successfully built RubyGem Name: hola Version: 0.0.0 File: hola-0.0.0.gem $ gem install ./hola-0.0.0.gem Successfully installed hola-0.0.0 Parsing documentation for hola-0.0.0 Installing ri documentation for hola-0.0.0 Done installing documentation for hola after 0 seconds 1 gem installed Of course, the smoke test isn’t over yet: the final step is to `require` the gem and use it: $ irb 3.1.2 :001 > require "hola" => true 3.1.2 :002 > Hola.hi Hello world! => nil Now you can share hola with the rest of the Ruby community. See the [Releasing your gem](#releasing-your-gem) section below to learn how to publish it to RubyGems.org. Starting with bundle gem ------------------------ While you can set up a gem manually as shown above, Bundler provides a convenient `bundle gem` command that generates a scaffold with everything you need. This is the recommended way to start a new gem: $ bundle gem foodie This creates a directory with the following structure: * **Gemfile**: Manages gem dependencies for development. Contains a `gemspec` line meaning that Bundler will include dependencies specified in _foodie.gemspec_ too. Runtime dependencies belong in the _gemspec_, while development dependencies are declared here. See [Gemfile and gemspec](/gemfile-and-gemspec) for how the two files divide the work. * **Rakefile**: Includes Bundler’s `build`, `install` and `release` Rake tasks by way of calling `Bundler::GemHelper.install_tasks`. * **foodie.gemspec**: The gem specification file, just like the one we wrote manually. Fields to complete include `description`, `homepage`, `metadata["source_code_uri"]`, and `metadata["changelog_uri"]`. * **lib/foodie.rb**: The main file loaded when the gem is required. * **lib/foodie/version.rb**: Defines a `VERSION` constant used by the gemspec. * **.gitignore**: Ignores the _pkg_ directory, _.gem_ files, and _.bundle_ directory. The command will also ask whether you want to include a `CODE_OF_CONDUCT.md` and `LICENSE.txt`. For information on gem naming conventions, see the [Name Your Gem](/name-your-gem/) guide. After running `bundle gem`, you can build and install the gem using Rake tasks: $ rake build # Build the gem into the pkg directory $ rake install # Build and install the gem to your system Requiring more files -------------------- Having everything in one file doesn't scale well. Let's add some more code to this gem. $ cat lib/hola.rb class Hola def self.hi(language = "english") translator = Translator.new(language) translator.hi end end class Hola::Translator def initialize(language) @language = language end def hi case @language when "spanish" "hola mundo" else "hello world" end end end This file is getting pretty crowded. Let's break out the `Translator` into a separate file. As mentioned before, the gem's root file is in charge of loading code for the gem. The other files for a gem are usually placed in a directory of the same name of the gem inside of `lib`. We can split this gem out like so: $ tree . ├── hola.gemspec └── lib ├── hola │ └── translator.rb └── hola.rb The `Translator` is now in `lib/hola`, which can easily be picked up with a `require` statement from `lib/hola.rb`. The code for the `Translator` did not change much: $ cat lib/hola/translator.rb class Hola::Translator def initialize(language) @language = language end def hi case @language when "spanish" "hola mundo" else "hello world" end end end But now the `hola.rb` file has some code to load the `Translator`: $ cat lib/hola.rb class Hola def self.hi(language = "english") translator = Translator.new(language) translator.hi end end require 'hola/translator' > Gotcha: > For newly created folder/file, do not forget to add one entry in hola.gemspec > file, as shown- $ cat hola.gemspec Gem::Specification.new do |s| ... s.files = ["lib/hola.rb", "lib/hola/translator.rb"] ... end > without the above change, the new folder would not be included into the > installed gem. Let's try this out. First, fire up `irb`: $ irb -Ilib -rhola 3.1.2 :001 > Hola.hi("english") => "hello world" 3.1.2 :002 > Hola.hi("spanish") => "hola mundo" We need to use a strange command line flag here: `-Ilib`. Usually RubyGems includes the `lib` directory for you, so end users don't need to worry about configuring their load paths. However, if you're running the code outside of RubyGems, you have to configure things yourself. It's possible to manipulate the `$LOAD_PATH` from within the code itself, but that's considered an anti-pattern in most cases. There are many more anti-patterns (and good patterns!) for gems, explained in [this guide](/patterns/). If you've added more files to your gem, make sure to remember to add them to your gemspec's `files` array before publishing a new gem! For this reason (among others), many developers automate this with [Hoe](https://github.com/seattlerb/hoe), [Jeweler](https://github.com/technicalpickles/jeweler), [Rake](https://github.com/ruby/rake), [lorem](https://github.com/railscasts/245-new-gem-with-bundler/tree/HEAD/lorem), or [just a dynamic gemspec ](https://github.com/wycats/newgem-template/blob/master/newgem.gemspec). Adding more directories with more code from here is pretty much the same process. Split your Ruby files up when it makes sense! Making a sane order for your project will help you and your future maintainers from headaches down the line. Using other gems ----------------- If your gem depends on another gem, you can specify it in your gemspec using `add_dependency`. For example, to depend on `activesupport`: Gem::Specification.new do |s| ... s.add_dependency "activesupport", ">= 7.0" end Using `>=` (an optimistic version constraint) is recommended in most cases, so that your gem does not artificially lock its users out of future releases of the dependency. See [Optimistic vs. pessimistic constraints](/versioning#optimistic-vs-pessimistic-constraints) for when a pessimistic (`~>`) constraint may be more appropriate. You can also specify development-only dependencies that are needed for testing but not at runtime: s.add_development_dependency "minitest", ">= 5.0" When using Bundler, running `bundle install` will resolve and install all dependencies specified in the gemspec. Anyone who runs `gem install yourgemname --dev` will get the development dependencies installed too. If your gem has a Gemfile alongside the gemspec, prefer declaring development dependencies in the Gemfile instead. See [Gemfile and gemspec](/gemfile-and-gemspec) for the reasoning. Writing tests -------------- Testing your gem is extremely important. Not only does it help assure you that your code works, but it helps others know that your gem does its job. When evaluating a gem, Ruby developers tend to view a solid test suite (or lack thereof) as one of the main reasons for trusting that piece of code. Gems support adding test files into the package itself so tests can be run when a gem is downloaded. In short: *TEST YOUR GEM!* Please! There are two popular test frameworks in the Ruby community: [Minitest](https://github.com/minitest/minitest) and [RSpec](https://rspec.info/). Minitest is Ruby's built-in test framework and requires no additional setup. RSpec is a widely used alternative that provides an expressive DSL for writing specs. Either works great — pick whichever you prefer and see the corresponding section below. ### Testing with Minitest Let's add some tests to Hola. This requires adding a few more files, namely a `Rakefile` and a brand new `test` directory: $ tree . ├── Rakefile ├── bin │ └── hola ├── hola.gemspec ├── lib │ ├── hola │ │ └── translator.rb │ └── hola.rb └── test └── test_hola.rb The `Rakefile` gives you some simple automation for running tests: $ cat Rakefile require "rake/testtask" Rake::TestTask.new do |t| t.libs << "test" end desc "Run tests" task default: :test Now you can run `rake test` or simply just `rake` to run tests. Woot! Here's a basic test file for hola: $ cat test/test_hola.rb require "minitest/autorun" require "hola" class HolaTest < Minitest::Test def test_english_hello assert_equal "hello world", Hola.hi("english") end def test_any_hello assert_equal "hello world", Hola.hi("ruby") end def test_spanish_hello assert_equal "hola mundo", Hola.hi("spanish") end end Finally, to run the tests: $ rake test Run options: --seed 9351 # Running: ... Finished in 0.005645s, 531.4108 runs/s, 531.4108 assertions/s. 3 runs, 3 assertions, 0 failures, 0 errors, 0 skips It's green! Well, depending on your shell colors. ### Testing with RSpec [RSpec](https://rspec.info/) is another popular testing framework. To use it, first add it as a development dependency in your gemspec: s.add_development_dependency "rspec", "~> 3.0" Then create a `spec` directory and a spec file: $ tree . ├── hola.gemspec ├── lib │ ├── hola │ │ └── translator.rb │ └── hola.rb └── spec └── hola_spec.rb Write your specs in `spec/hola_spec.rb`: $ cat spec/hola_spec.rb require "hola" describe Hola do it "says hello world in english" do expect(Hola.hi("english")).to eql("hello world") end it "says hello world by default" do expect(Hola.hi("ruby")).to eql("hello world") end it "says hola mundo in spanish" do expect(Hola.hi("spanish")).to eql("hola mundo") end end Run the specs with: $ bundle exec rspec spec 3 examples, 0 failures For more great examples, the best thing you can do is to hunt around [GitHub](https://github.com/search?q=stars%3A%3E1000+forks%3A%3E100&type=Repositories&l=Ruby) and read some code. Adding an executable -------------------- In addition to providing libraries of Ruby code, gems can also expose one or many executable files to your shell's `PATH`. Probably the best known example of this is `rake`. Another very useful one is the [Nokogiri](https://rubygems.org/gems/nokogiri) gem, which parses HTML/XML documents. Here's an example: $ gem install -N nokogiri [...] $ nokogiri https://www.ruby-lang.org/ Your document is stored in @doc... 3.1.2 :001 > @doc.title => "Ruby Programming Language" Adding an executable to a gem is a simple process. You just need to place the file in your gem's `bin` directory, and then add it to the list of executables in the gemspec. Let's add one for the Hola gem. First create the file and make it executable: $ mkdir bin $ touch bin/hola $ chmod a+x bin/hola The executable file itself just needs a [shebang](http://www.catb.org/jargon/html/S/shebang.html) in order to figure out what program to run it with. Here's what Hola's executable looks like: $ cat bin/hola #!/usr/bin/env ruby require 'hola' puts Hola.hi(ARGV[0]) All it's doing is loading up the gem, and passing the first command line argument as the language to say hello with. Here's an example of running it: $ ruby -Ilib ./bin/hola hello world $ ruby -Ilib ./bin/hola spanish hola mundo Finally, to get Hola's executable included when you push the gem, you'll need to add it in the gemspec. $ head -4 hola.gemspec Gem::Specification.new do |s| s.name = "hola" s.version = "0.0.1" s.executables << "hola" Push up that new gem, and you'll have your own command line utility published! You can add more executables as well in the `bin` directory if you need to, there's an `executables` array field on the gemspec. > Note that you should change the gem's version when pushing up a new release. > For more information on gem versioning, see [Versioning and compatibility](/versioning) Documenting your code --------------------- By default most gems use RDoc to generate docs. There are plenty of [great tutorials](https://ruby.github.io/rdoc/RDoc/Markup.html) for learning how to mark up your code with RDoc. Here's a simple example: # The main Hola driver class Hola # Say hi to the world! # # Example: # >> Hola.hi("spanish") # => hola mundo # # Arguments: # language: (String) def self.hi(language = "english") translator = Translator.new(language) puts translator.hi end end Another great option for documentation is [YARD](https://yardoc.org/), since when you push a gem, [RubyDoc.info](https://rubydoc.info/) generates YARDocs automatically from your gem. YARD is backwards compatible with RDoc, and it has a [good introduction](https://rubydoc.info/gems/yard/file/docs/GettingStarted.md) on what's different and how to use it. Releasing your gem ------------------ Publishing your gem to RubyGems.org requires an account on the site. To set up your computer with your RubyGems account, run the following command (replacing with your own Email, Password, and OTP if enabled): $ gem signin Enter your RubyGems.org credentials. Don't have an account yet? Create one at https://rubygems.org/sign_up Email: (your-email-address@example.com) Password: (your password for RubyGems.org) API Key name [host-user-20220102030405]: Please select scopes you want to enable for the API key (y/n) index_rubygems [y/N]: n push_rubygem [y/N]: y yank_rubygem [y/N]: n add_owner [y/N]: n remove_owner [y/N]: n access_webhooks [y/N]: n show_dashboard [y/N]: n You have enabled multi-factor authentication. Please enter OTP code. Code: 123456 Signed in with API key: host-user-20220102030405. > If you're having problems with curl, OpenSSL, or certificates, you might want to > simply try entering the above URL in your browser's address bar. Your browser will > ask you to login to RubyGems.org. Enter your username and password. Your browser > will now try to download the file api_key.yaml. Save it in ~/.gem and call it 'credentials' ### With gem push Once signed in, you can push the gem directly: $ gem push hola-0.0.0.gem Pushing gem to RubyGems.org... Successfully registered gem: hola (0.0.0) In just a short time (usually less than a minute), your gem will be available for installation by anyone. You can see it [on the RubyGems.org site](https://rubygems.org/gems/hola) or grab it from any computer with RubyGems installed: $ gem list -r hola *** REMOTE GEMS *** hola (0.1.3) $ gem install hola Fetching hola-0.1.3.gem Successfully installed hola-0.1.3 Parsing documentation for hola-0.1.3 Installing ri documentation for hola-0.1.3 Done installing documentation for hola after 0 seconds 1 gem installed ### With rake release If you created your gem with `bundle gem`, you can use the `rake release` command instead. This command: 1. Builds the gem into the _pkg_ directory 2. Creates a git tag for the current version 3. Pushes the tag to the git remote 4. Pushes the gem to RubyGems.org Before releasing, make sure to update the version number in your version file (e.g. `lib/hola/version.rb`) and commit all changes. To make version bumping easier, you can use the [gem-release](https://github.com/svenfuchs/gem-release) gem: $ gem install gem-release $ gem bump --version minor # bumps to the next minor version $ gem bump --version major # bumps to the next major version $ gem bump --version 1.1.1 # bumps to the specified version Wrapup ------ With this basic understanding of building your own RubyGem, we hope you'll be on your way to making your own! The next few guides cover patterns in making a gem and the other capabilities of the RubyGems system. Credits ------- This tutorial was adapted from "Gem Sawyer, Modern Day Ruby Warrior" <`http://rubylearning.com/blog/2010/10/06/gem-sawyer-modern-day-ruby-warrior/`>. The code for this gem can be found [on GitHub](https://github.com/qrush/hola). --- # Publishing your gem Source: https://guides.rubygems.org/publishing/ Start with an idea, end with a distributable package of Ruby code. Ways to share your gem code with other users. * [Introduction](#introduction) * [Sharing Source Code](#sharing-source-code) * [Serving Your Own Gems](#serving-your-own-gems) * [Publishing to RubyGems.org](#publishing-to-rubygemsorg) * [Push Permissions on RubyGems.org](#push-permissions-on-rubygemsorg) * [Gem Security](#gem-security) Introduction ------------ Now that you've [created your gem](/make-your-own-gem), you're probably ready to share it. While it is perfectly reasonable to create private gems solely to organize the code in large private projects, it's more common to build gems so that they can be used by multiple projects. This guide discusses the various ways that you can share your gem with the world. Sharing Source Code ------------------- The simplest way (from the author's perspective) to share a gem for other developers' use is to distribute it in source code form. If you place the full source code for your gem on a public git repository (often, though not always, this means sharing it via [GitHub](https://github.com)), then other users can install it with [Bundler's git functionality](/gemfile/#GIT). For example, you can install the latest code for the wicked_pdf gem in a project by including this line in your Gemfile: gem "wicked_pdf", :git => "https://github.com/mileszs/wicked_pdf.git" > Installing a gem directly from a git repository is a feature of Bundler, not > a feature of RubyGems. Gems installed this way will not show up when you run > `gem list`. Serving Your Own Gems --------------------- If you want to control who can install a gem, or directly track the activity surrounding a gem, then you'll want to set up a private gem server. You can [set up your own gem server](/run-your-own-gem-server) or use a commercial service such as [Gemfury](http://www.gemfury.com/). RubyGems 2.2.0 and newer support the `allowed_push_host` metadata value to restrict gem pushes to a single host. If you are publishing private gems you should set this value to prevent accidental pushes to rubygems.org: Gem::Specification.new 'my_gem', '1.0' do |s| # ... s.metadata['allowed_push_host'] = 'https://gems.my-company.example' end Publishing to RubyGems.org -------------------------- The simplest way to distribute a gem for public consumption is to use [RubyGems.org](https://rubygems.org/). Gems that are published to RubyGems.org can be installed via the `gem install` command or through the use of tools such as Isolate or Bundler. To begin, you'll need to create an account on RubyGems.org. Visit the [sign up](https://rubygems.org/users/new) page and supply an email address that you control, a handle (username) and a password. After creating the account, use your email and password when pushing the gem. (RubyGems saves the credentials in ~/.gem/credentials for you so you only need to log in once.) Note that your gem name must be unique. It cannot have a name that is already in use by another gem already published to [RubyGems.org](https://rubygems.org/). To publish version 0.1.0 of a new gem named 'squid-utils': $ gem push squid-utils-0.1.0.gem Enter your RubyGems.org credentials. Don't have an account yet? Create one at https://rubygems.org/sign_up Email: gem_author@example Password: Signed in. Pushing gem to RubyGems.org... Successfully registered gem: squid-utils (0.1.0) Congratulations! Your new gem is now ready for any ruby user in the world to install! Push Permissions on RubyGems.org -------------------------------- If you have multiple maintainers for your gem you can give your fellow maintainers permission to push the gem to rubygems.org through the [gem owner command](/command-reference/#gem-owner). "Access Denied" Error When Pushing to RubyGems.org -------------------------------------------------- In certain situations, you may get this error: Pushing gem to https://rubygems.org... Access Denied. Please sign up for an account at https://rubygems.org If you encounter this error and aren't sure why, try running `gem signout` and then `gem signin`. There is [an open issue about improving how this is handled](https://github.com/rubygems/rubygems/issues/7595). Gem Security ------------ See [Security](/security) page. --- # How to manage application dependencies with Bundler Source: https://guides.rubygems.org/using_bundler_in_applications/ This guide was originally written for Bundler v1.12. If you are using a different version, keep in mind that the output can differ. To check your Bundler version, simply run `bundle -v`. ## What's Inside? 1. [Getting Started - Installing Bundler and **bundle init**](#getting-started---installing-bundler-and-bundle-init) 1. [Editing Gemfile](#editing-gemfile) 1. [Sources](#sources) 1. [Adding Gems](#adding-gems) 1. [Gemfile Syntax](#gemfile-syntax) 1. [Installing Gems - **bundle install**](#installing-gems---bundle-install) 1. [Development](#development) 1. [Deployment](#deployment) 1. [Gemfile.lock](#gemfilelock) 1. [Executing Commands - **bundle exec**](#executing-commands---bundle-exec) 1. [Updating Gems - **bundle outdated** and **bundle update**](#updating-gems---bundle-outdated-and-bundle-update) 1. [Troubleshooting](#troubleshooting) 1. [Running `git bisect` in projects using Bundler](#running-git-bisect-in-projects-using-bundler) ## Getting Started - Installing Bundler and **bundle init** **Some of the frameworks have builtin support for Bundler, e.g. when you run `rails new app` it will automatically init Bundler.** Firstly, we need to install Bundler. $ gem install bundler This command will also update already installed bundler. You should get something similar as output: ~~~ bash $ gem install bundler Successfully installed bundler-1.12.5 1 gem installed ~~~ To init Bundler manually, let's do this (`bundler_example` will be folder with our app): $ mkdir bundler_example && cd bundler_example $ bundle init This will create `Gemfile` inside `bundler_example` folder: ~~~ ruby # frozen_string_literal: true # A sample Gemfile source "https://rubygems.org" # gem "rails" ~~~ ## Editing Gemfile ### Sources Auto-generated Gemfile consists of `source "https://rubygems.org"`. It means that Bundler will search for gems in `https://rubygems.org`. If you want to use your own RubyGems server or different one, just change it: ~~~ ruby source "https://your_ruby_gem_server.url" ~~~ *** If you have more gem sources, you can use block or `:source`: ~~~ ruby source "https://your_ruby_gem_server.url" do # gems end gem "my_gem", source: "https://your_2_ruby_gem_server.url" ~~~ Gems inside block will be retrieved from given source. *** Learn more about `source` [here](/gemfile/#GLOBAL-SOURCE). ### Adding Gems Let's now add some dependencies to project: ~~~ ruby # frozen_string_literal: true # A sample Gemfile source "https://rubygems.org" gem "rails" ~~~ Using above Gemfile, `bundler install` will install latest version of `rails` gem. *** What to do when we want to install specified version? Just specify it after comma: ~~~ ruby gem "rails", "3.0.0" ~~~ or use this syntax: ~~~ ruby gem "rails", "~> 4.0.0" # which is same as gem "rails", ">= 4.0.0", "< 4.1.0" gem "nokogiri", ">= 1.4.2" ~~~ *** Learn more about gems in Gemfile [here](/gemfile/#GEMS). ### Gemfile Syntax Learn more about Gemfile syntax from the [gemfile manpage](/gemfile/#SYNTAX). ## Installing Gems - **bundle install** ### Development To install gems for development, simply run `bundle install`. This should give you similar output: Fetching gem metadata from https://rubygems.org/ Fetching version metadata from https://rubygems.org/ Fetching dependency metadata from https://rubygems.org/ Resolving dependencies... Using mini_portile2 2.1.0 Using pkg-config 1.1.7 Using bundler 1.12.5 Using nokogiri 1.6.8 Bundle complete! 1 Gemfile dependency, 4 gems now installed. Use `bundle show [gemname]` to see where a bundled gem is installed. It should also create [`Gemfile.lock` file](/command-reference/bundle-install/#THE-GEMFILE-LOCK): GEM remote: https://rubygems.org/ specs: mini_portile2 (2.1.0) nokogiri (1.6.8) mini_portile2 (~> 2.1.0) pkg-config (~> 1.1.7) pkg-config (1.1.7) PLATFORMS ruby DEPENDENCIES nokogiri (>= 1.4.0) BUNDLED WITH 1.12.5 This Gemfile.lock is described in [next chapter](#gemfilelock). ### Deployment For deployment you should use [`--deployment` option](/command-reference/bundle-install/#DEPLOYMENT-MODE): $ bundle install --deployment This will install all dependencies to `./vendor/bundle`. To run this command, there are some requirements: 1. `Gemfile.lock` file is required. 1. `Gemfile.lock` must be up to date. *** To learn more about `bundle install` command click [here](/command-reference/bundle-install/). ## Gemfile.lock Bundler uses this file to save names and versions of all gems. It guarantees that you always use the same exact code, even as your application moves across machines. After specified gem is installed for the first time, Bundler will lock its version. To update it, you must use: [`bundler update`](#updating-gems---bundle-outdated-and-bundle-update) or/and modify its version in `Gemfile`. This file is created/updated automatically when you use some of Bundler's commands (e.g. `bundle install` or `bundle update`) and you should check it into version control. We will use Gemfile.lock from previous chapter as an example. GEM remote: https://rubygems.org/ specs: mini_portile2 (2.1.0) nokogiri (1.6.8) mini_portile2 (~> 2.1.0) pkg-config (~> 1.1.7) pkg-config (1.1.7) PLATFORMS ruby DEPENDENCIES nokogiri (>= 1.4.0) BUNDLED WITH 1.12.5 Let's break it down: * `GEM` * `remote` - source of gems * `specs` - installed gems (with versions). We can see here that `mini_portile2` is dependency of `nokogiri` because it's beneath and indented * `PLATFORMS` - platform that is used in your application ([see more here](/gemfile/#PLATFORMS)). * `DEPENDENCIES` - gems defined in our Gemfile. * `BUNDLED WITH` - version of Bundler which was last used to change `Gemfile.lock` ## Executing Commands - **bundle exec** Let's see examples first: $ bundle exec rspec $ bundle exec rails s This will allow you to run command (`rspec` and `rails s` here) in current bundle context, making all gems in Gemfile available to `require` and use. *** To learn more about `bundle exec` command click [here](/command-reference/bundle-exec/). ## Updating Gems - **bundle outdated** and **bundle update** Now let's update some gems. With `bundle outdated` we can list installed gems with newer versions available: $ bundle outdated Fetching gem metadata from https://rubygems.org/ Fetching version metadata from https://rubygems.org/ Fetching dependency metadata from https://rubygems.org/ Resolving dependencies....... Outdated gems included in the bundle: * nokogiri (newest 1.6.8, installed 1.6.7.2) in group "default" You can also specify gems (`bundle outdated *gems`). We've got `nokogiri` locked on version 1.6.7.2. How can we update it? `bundle install` won't install newer version because it's locked in `Gemfile.lock` file. We must use `bundle update`. $ bundle update Fetching git://github.com/middleman/middleman-syntax.git Fetching gem metadata from https://rubygems.org/ Fetching version metadata from https://rubygems.org/ Fetching dependency metadata from https://rubygems.org/ Resolving dependencies..... Installing nokogiri 1.6.8 (was 1.6.7.2) with native extensions Using i18n 0.7.0 ... (and more) Bundle updated! Using `bundle update` without any argument will try to update every gem to newest available version (restrained by `Gemfile`). To update specific gems, use `bundle update *gems` *** To learn more about `bundle outdated` command click [here](/command-reference/bundle-outdated/). To learn more about `bundle update` command click [here](/command-reference/bundle-update/). ## Troubleshooting ### Running `git bisect` in projects using Bundler See [Git Bisect Guide](/git_bisect). --- # How to manage dependencies with Bundler Source: https://guides.rubygems.org/dependency_management/ This guide explains how Bundler manages your application's dependencies, why `Gemfile.lock` matters, and how to share a consistent environment with other developers and deployment targets. ### Declaring dependencies You declare your dependencies in a file at the root of your application called `Gemfile`. It looks something like this: ~~~ruby source 'https://rubygems.org' gem 'rails', '8.1.3.1' gem 'rack-cache' gem 'nokogiri', '~> 1.19.4' ~~~ This `Gemfile` says a few things. First, it says that bundler should look for gems declared in the `Gemfile` at `https://rubygems.org` by default. If some of your gems need to be fetched from a private gem server, this default source can be overridden for those gems. Next, you declare a few dependencies: - on version `8.1.3.1` of `rails` - on any version of `rack-cache` - on a version of `nokogiri` that is `>= 1.19.4` but `< 1.20.0` Learn More: Gemfiles ### Installing dependencies After declaring your first set of dependencies, you tell bundler to go get them: ~~~ $ bundle install ~~~ Bundler will connect to `rubygems.org` (and any other sources that you declared) and find a list of all of the required gems that meet the requirements you specified. Because all of the gems in your `Gemfile` have dependencies of their own (and some of those have their own dependencies), running `bundle install` on the `Gemfile` above will install quite a few gems. If any of the needed gems are already installed, Bundler will use them. After installing any needed gems to your system, bundler writes a snapshot of all of the gems and versions that it installed to `Gemfile.lock`. ### Checking Your Code into Version Control As you develop your application, `Gemfile.lock` accumulates a record of the exact versions of all of the gems that you used the last time you know for sure that the application worked. Keep in mind that while your `Gemfile` lists only three gems (with varying degrees of version strictness), your application depends on dozens of gems, once you take into consideration all of the implicit requirements of the gems you depend on. See [The Day-to-day Workflow](#the-day-to-day-workflow) below for when to commit it. This is important: **the `Gemfile.lock` makes your application a single package of both your own code and the third-party code it ran the last time you know for sure that everything worked**. Specifying exact versions of the third-party code you depend on in your `Gemfile` would not provide the same guarantee, because gems usually declare a range of versions for their dependencies. The next time you run `bundle install` on the same machine, bundler will see that it already has all of the dependencies you need and skip the installation process. Do not check in the `.bundle` directory or any of the files inside it. Those files are specific to each particular machine and are used to persist installation options between runs of the `bundle install` command. If you have run `bundle cache`, the gems required by your bundle will be downloaded into `vendor/cache`. Bundler can run without connecting to the internet (or the RubyGems server) if all the gems you need are present in that folder and checked in to your source control. This is an **optional** step and not recommended due to the increase in size of your source control repository. ### Sharing Your Application With Other Developers When your co-developers (or you on another machine) check out your code, it will come with the exact versions of all the third-party code your application used on the machine that you last developed on (in the `Gemfile.lock`). When **they** run `bundle install`, bundler will find the `Gemfile.lock` and skip the dependency resolution step. Instead, it will install all of the same gems that you used on the original machine. In other words, you don't have to guess which versions of the dependencies you should install. In the example we've been using, even though `rack-cache` declares a dependency on `rack >= 0.4`, we know for sure it works with `rack 3.2.6`. Even if the Rack team releases `rack 3.2.7`, bundler will always install `3.2.6`, the exact version of the gem that we know works. This relieves a large maintenance burden from application developers because all machines always run the exact same third-party code. ### The Day-to-day Workflow Once the `Gemfile` and `Gemfile.lock` are in version control, the routine is short: - Add or change a dependency in the `Gemfile`, then run `bundle install`. - Commit the updated `Gemfile.lock` together with the `Gemfile`, so that everyone else installs the same versions you tested with. This applies to applications: code that is deployed or run directly, not consumed as a dependency by other software. If you are developing a library that other applications will depend on, do not commit `Gemfile.lock`. A library's lockfile is ignored by any application that depends on it, and locking your own development environment would narrow the range of dependency versions you actually exercise. Add `lockfile false` to the `Gemfile` (or pass `--no-lock` to `bundle install`) instead. See the [FAQs](/faqs) for the case of a gem's own development checkout, where the tradeoffs differ. - If `bundle install` reports a conflict between the `Gemfile` and the `Gemfile.lock`, update only the gems you changed: ~~~ $ bundle update rails puma ~~~ - Run `bundle update` with no arguments only when you intend to move every gem to the newest version your `Gemfile` allows. - On a deployment machine or in CI, enable deployment mode before installing: ~~~ $ bundle config set --local deployment true $ bundle install ~~~ Deployment mode requires an up-to-date `Gemfile.lock` and installs gems into `vendor/bundle` inside the application. Do not enable it on a development machine, where editing the `Gemfile` would then raise an error. ### Loading and Running Your Bundle Inside your application, load the bundled environment before requiring anything: ~~~ruby require 'bundler/setup' # require your gems as usual require 'nokogiri' ~~~ To run an executable that comes with a gem in your bundle, prefix it with `bundle exec`: ~~~ $ bundle exec rspec spec/models ~~~ Running the executable without `bundle exec` sometimes works, if it also happens to be installed on your system and pulls in no gems that conflict with your bundle. That is unreliable. It may stop working later, or on another machine. If you want a shortcut for a gem you run often, generate binstubs for it: ~~~ $ bundle binstubs rspec-core $ bin/rspec spec/models ~~~ The executables in `bin` are scoped to the bundle, and will always work.
Learn More: Executables Learn More: Bundler.setup Learn More: Updating gems Learn More: Deploying
--- # How to update gems with Bundler Source: https://guides.rubygems.org/updating_gems/ ### Updating a Dependency Of course, at some point, you might want to update the version of a particular dependency your application relies on. For instance, you might want to update `rails` to `3.0.0` final. Importantly, just because you're updating one dependency, it doesn't mean you want to re-resolve all of your dependencies and use the latest version of everything. In our example, you only have three dependencies, but even in this case, updating everything can cause complications. To illustrate, the `rails 3.0.0.rc` gem depends on `actionpack 3.0.0.rc` gem, which depends on `rack ~> 1.2.1` (which means `>= 1.2.1` and `< 1.3.0`). The `rack-cache` gem depends on `rack >= 0.4`. Let's assume that the `rails 3.0.0` final gem also depends on `rack ~> 1.2.1`, and that since the release of `rails 3.0.0`, the Rack team released `rack 1.2.2`. If we naïvely update all of our gems in order to update Rails, we'll get `rack 1.2.2`, which satisfies the requirements of both `rails 3.0.0` and `rack-cache`. However, we didn't specifically ask to update `rack-cache`, which may not be compatible with `rack 1.2.2` (for whatever reason). And while an update from `rack 1.2.1` to `rack 1.2.2` probably won't break anything, similar scenarios can happen that involve much larger jumps. (see [1] below for a larger discussion) In order to avoid this problem, when you update a gem, bundler will not update a dependency of that gem if another gem still depends on it. In this example, since `rack-cache` still depends on `rack`, bundler will not update the `rack` gem. This ensures that updating `rails` doesn't inadvertently break `rack-cache`. Since `rails 3.0.0`'s dependency `actionpack 3.0.0` remains compatible with `rack 1.2.1`, bundler leaves it alone, and `rack-cache` continues to work even in the face of an incompatibility with `rack 1.2.2`. Since you originally declared a dependency on `rails 3.0.0.rc`, if you want to update to `rails 3.0.0`, simply update your `Gemfile` to `gem 'rails', '3.0.0'` and run: ~~~ $ bundle install ~~~ As described above, the `bundle install` command always does a conservative update, refusing to update gems (or their dependencies) that you have not explicitly changed in the `Gemfile`. This means that if you do not modify `rack-cache` in your `Gemfile`, bundler will treat it **and its dependencies** (`rack`) as a single, unmodifiable unit. If `rails 3.0.0` was incompatible with `rack-cache`, bundler will report a conflict between your snapshotted dependencies (`Gemfile.lock`) and your updated `Gemfile`. If you update your `Gemfile`, and your system already has all of the needed dependencies, bundler will transparently update the `Gemfile.lock` when you boot your application. For instance, if you add `mysql` to your `Gemfile`, and have already installed it in your system, you can boot your application without running `bundle install`, and bundler will persist the "last known good" configuration to the `Gemfile.lock` snapshot. This can come in handy when adding or updating gems with minimal dependencies (database drivers, `wirble`, `ruby-debug`). It will probably fail if you update gems with significant dependencies (`rails`), or that a lot of gems depend on (`rack`). If a transparent update fails, your application will fail to boot, and bundler will print out an error instructing you to run `bundle install`. ### Updating a Gem Without Modifying the Gemfile Sometimes, you want to update a dependency without modifying the Gemfile. For example, you might want to update to the latest version of `rack-cache`. Because you did not declare a specific version of `rack-cache` in the `Gemfile`, you might want to periodically get the latest version of `rack-cache`. To do this, you want to use the `bundle update` command: ~~~ $ bundle update rack-cache ~~~ This command will update `rack-cache` and its dependencies to the latest version allowed by the `Gemfile` (in this case, the latest version available). It will not modify any other dependencies. It will, however, update dependencies of other gems if necessary. For instance, if the latest version of `rack-cache` specifies a dependency on `rack >= 1.2.2`, bundler will update `rack` to `1.2.2` even though you have not asked bundler to update `rack`. If bundler needs to update a gem that another gem depends on, it will let you know after the update has completed. If you want to update every gem in the Gemfile to the latest possible versions, run: ~~~ $ bundle update ~~~ This will resolve dependencies from scratch, ignoring the `Gemfile.lock`. If you do this, keep `git reset --hard` and your test suite in your back pocket. Resolving all dependencies from scratch can have surprising results, especially if a number of the third-party packages you depend on have released new versions since you last did a full update. ## Notes [1] For instance, if a new version of a gem depended on `rack 2.0`, that gem would still satisfy the requirement of `rack-cache`, which declares `>= 0.4` as a dependency. Of course, you could argue that `rack-cache` is silly for depending on open-ended versions, but these situations exist (extensively) in the wild, and projects often find themselves between a rock and a hard place when deciding what version to depend on. Constrain the dependency too much (`rack =1.5.1`) and you make it hard to use your project in other compatible projects. Constrain it too little (`rack >= 1.0`) and a new release of Rack may break your code. Using dependencies like `rack ~> 1.5.2` and versioning code in a SemVer compliant way mostly solves this problem, but it assumes universal compliance. Since RubyGems has over 100,000 packages, this assumption simply doesn't hold in practice. --- # How to manage groups of gems Source: https://guides.rubygems.org/groups/ Grouping your dependencies allows you to perform operations on the entire group. ~~~ruby # These gems are in the :default group gem 'nokogiri' gem 'sinatra' gem 'wirble', group: :development group :test do gem 'faker' gem 'rspec' end group :test, :development do gem 'capybara' gem 'rspec-rails' end gem 'cucumber', group: [:cucumber, :test] ~~~ Configure bundler so that subsequent `bundle install` invocations will install all gems, except those in the listed groups. Gems in at least one non-excluded group will still be installed. ~~~ $ bundle config set --local without test development ~~~ Require the gems in particular groups, noting that gems outside of a named group are in the :default group ~~~ruby Bundler.require(:default, :development) ~~~ Require the default gems, plus the gems in a group named the same as the current Rails environment ~~~ruby Bundler.require(:default, Rails.env) ~~~ Restrict the groups of gems that you want to add to the load path. Only gems in these groups will be requireable. Note though that `Bundler.setup` can be called only once, all subsequent calls are no-op. In particular, since running a script through `bundle exec` already calls `Bundler.setup`, any later calls inside your user code will be ignored. In order to control the groups that are loaded by `bundle exec` you can use the `BUNDLE_WITH` and `BUNDLE_WITHOUT` configurations. ~~~ruby require 'bundler' Bundler.setup(:default, :ci) require 'nokogiri' ~~~ Learn More: Bundler.setup ## Optional groups and `BUNDLE_WITH` Mark a group as optional using `group :name, optional: true do` and then opt into installing an optional group with `bundle config set --local with name`. ## Grouping your dependencies You'll sometimes have groups of gems that only make sense in particular environments. For instance, you might develop your app (at an early stage) using SQLite but deploy it using `mysql2` or `pg`. In this example, you might not have MySQL or Postgres installed on your development machine and want bundler to skip it. To do this, you can group your dependencies: ~~~ruby source 'https://rubygems.org' gem 'rails', '3.2.2' gem 'rack-cache', require: 'rack/cache' gem 'nokogiri', '~> 1.4.2' group :development do gem 'sqlite3' end group :production do gem 'pg' end ~~~ Now, in development, you can instruct bundler to skip the `production` group: ~~~ $ bundle config set --local without production ~~~ Bundler stores the flag in `APP_ROOT/.bundle/config` and the next time you run `bundle install`, it will skip production gems. Similarly, when you require `bundler/setup`, Bundler will ignore gems in these groups. You can see all of the settings that Bundler saved there by running `bundle config`, which will also print out global settings (stored in `~/.bundle/config`) and settings set via environment variables. For more information on configuring Bundler, please see: [`bundle config`](/command-reference/bundle-config/) You can also specify which groups to automatically require through the parameters to `Bundler.require`. The `:default` group includes all gems not listed under any group. If you call `Bundler.require(:default, :development)`, bundler will `require` all the gems in the `:default` group as well as the gems in the `:development` group. By default, a Rails generated app calls `Bundler.require(:default, Rails.env)` in your `application.rb`, which links the groups in your `Gemfile` to the Rails environment. If you use other groups (not linked to a Rails environment), you can add them to the call to `Bundler.require` if you want them to be automatically required. Remember that you can always leave groups of gems out of `Bundler.require` and then require them manually using Ruby's `require` at the appropriate place in your app. You might do this because requiring a certain gem takes some time and you don't need it every time you boot your application. --- # How to install gems from git repositories Source: https://guides.rubygems.org/git/ This document is written for Bundler 2.1 or higher. Use `bundle config X Y` instead of `bundle config set X Y` if you are still using Bundler 2.0 or earlier, which were already deprecated. Bundler has the ability to install gems directly from git repositories. Installing a gem using git is as easy as adding a gem to your Gemfile. Note that because RubyGems lacks the ability to handle gems from git, any gems installed from a git repository will not show up in `gem list`. They will, however, be available after running `Bundler.setup`. Specify that a gem should come from a git repository with a .gemspec at its root ~~~ruby gem 'rack', git: 'https://github.com/rack/rack' ~~~ If there is no .gemspec at the root of a git repository, you must specify a version that bundler should use when resolving dependencies ~~~ruby gem 'nokogiri', '1.7.0.1', git: 'https://github.com/sparklemotion/nokogiri' ~~~ If the gem is located within a subdirectory of a git repository, you can use the `:glob` option to specify the location of its .gemspec ~~~ruby gem 'cf-copilot', git: 'https://github.com/cloudfoundry/copilot', glob: 'sdk/ruby/*.gemspec' ~~~ Specify that a git repository containing multiple .gemspec files should be treated as a gem source ~~~ruby git 'https://github.com/rails/rails.git' do gem 'railties' gem 'actionpack' gem 'activemodel' end ~~~ From the previous example, you may specify a particular ref, branch or tag ~~~ruby git 'https://github.com/rails/rails.git', ref: '4aded' do git 'https://github.com/rails/rails.git', branch: '5-0-stable' do git 'https://github.com/rails/rails.git', tag: 'v5.0.0' do ~~~ Specifying a ref, branch, or tag for a git repository specified inline works exactly the same way ~~~ruby gem 'nokogiri', git: 'https://github.com/sparklemotion/nokogiri.git', ref: '0bd839d' gem 'nokogiri', git: 'https://github.com/sparklemotion/nokogiri.git', tag: '2.0.1' gem 'nokogiri', git: 'https://github.com/sparklemotion/nokogiri.git', branch: 'rack-1.5' ~~~ Bundler can use HTTP(S), SSH, or git ~~~ruby gem 'rack', git: 'https://github.com/rack/rack.git' gem 'rack', git: 'git@github.com:rack/rack.git' gem 'rack', git: 'git://github.com/rack/rack.git' ~~~ Specify that the submodules from a git repository also should be expanded by bundler ~~~ruby gem 'rugged', git: 'git://github.com/libgit2/rugged.git', submodules: true ~~~ If you are getting your gems from a public GitHub repository, you can use the shorthand ~~~ruby gem 'rack', github: 'rack/rack' ~~~ If the repository name is the same as the GitHub account hosting it, you can omit it ~~~ruby gem 'rails', github: 'rails' ~~~ *NB:* This shorthand can only be used for public repos in Bundler version 1.x. Use HTTPS for read and write: ~~~ruby gem 'rails', git: 'https://github.com/rails/rails' ~~~ All of the usual `:git` options apply, like `:branch` and `:ref`. ~~~ruby gem 'rails', github: 'rails', ref: 'a9752dcfd15bcddfe7b6f7126f3a6e0ba5927c56' ~~~ There are analogous shortcuts for Bitbucket (`:bitbucket`) and GitHub Gists (`:gist`). The `:gist` value is the id from the gist's URL. ~~~ruby gem 'keystone', bitbucket: 'musicone/keystone' gem 'microg', gist: 'bf6b8689108da1b9c4ddbe7f2acdd26c' ~~~ A gist cannot contain directories, so a gem served from a gist keeps all of its files at the top level. Put the gemspec at the root of the gist and set `require_paths = ["."]` so ruby files are loaded from there: ~~~ruby Gem::Specification.new do |spec| spec.name = "microg" spec.version = "0.1.0" spec.authors = ["x-yuri"] spec.summary = "a micro gem" spec.files = ["microg.rb"] spec.require_paths = ["."] end ~~~ ## Custom git sources The `:github` shortcut used above is one of Bundler's built in git sources. Bundler comes with shortcuts for `:github`, `:gist`, and `:bitbucket`, but you can also add your own. If you're using GitHub Enterprise, Stash, or just have a custom git setup, create your own shortcuts by calling `git_source` before you use your custom option. Here's an example for Stash: ~~~ruby git_source(:stash){ |repo_name| "https://stash.corp.acme.pl/#{repo_name}.git" } gem 'rails', stash: 'forks/rails' ~~~ ## Security `http://` and `git://` URLs are insecure. A man-in-the-middle attacker could tamper with the code as you check it out, and potentially supply you with malicious code instead of the code you meant to check out. Because the `:github` shortcut uses a `git://` URL in Bundler 1.x versions, we recommend using HTTPS URLs or overriding the `:github` shortcut with your own HTTPS git source. ## Local Git Repos Bundler also allows you to work against a git repository locally instead of using the remote version. This can be achieved by setting up a local override: ~~~ $ bundle config set local.GEM_NAME /path/to/local/git/repository ~~~ For example, in order to use a local Rack repository, a developer could call: ~~~ $ bundle config set local.rack ~/Work/git/rack ~~~ and setup the git repo pointing to a branch: ~~~ruby gem 'rack', github: 'rack/rack', branch: 'master' ~~~ Now instead of checking out the remote git repository, the local override will be used. Similar to a path source, every time the local git repository changes, the changes will be automatically picked up by Bundler. This means a commit in the local git repo will update the revision in the `Gemfile.lock` to the local git repo revision. This requires the same attention as git submodules. Before pushing to the remote, you need to ensure the local override was pushed, otherwise you may point to a commit that only exists in your local machine. **Please note!** Bundler does many checks to ensure a developer won't work with invalid references. Particularly, **we force a developer to specify a branch in the `Gemfile` in order to use this feature**. If the branch specified in the `Gemfile` and the current branch in the local git repository do not match, Bundler will abort. This ensures that a developer is always working against the correct branches, and prevents accidental locking to a different branch. Finally, Bundler also ensures that the current revision in the `Gemfile.lock` exists in the local git repository. By doing this, Bundler forces you to fetch the latest changes in the remotes. If you do not want bundler to make these branch checks, you can override it by setting this option: ~~~ $ bundle config set disable_local_branch_check true ~~~ --- # How to develop multiple gems in one repository Source: https://guides.rubygems.org/monorepo/ Using path gems to develop a family of related gems side by side. Some projects outgrow a single gem. A library gains plugins, or a framework splits into components, and it becomes easier to develop the pieces together in one repository. Rust's Cargo and Python's uv call this arrangement a workspace. In Ruby the same workflow is built from Bundler's path source: each gem keeps its own directory and gemspec, and a shared Gemfile wires them together. Path gems --------- The `path:` option tells Bundler that a gem lives in a directory on the local file system instead of on a gem server: ~~~ruby gem "mygem", path: "gems/mygem" ~~~ Relative paths are resolved against the directory containing the Gemfile. The directory must contain the gem's `.gemspec`, or the `gem` entry must specify an explicit version. Bundler loads the gem's code straight from that directory, so edits take effect the next time the code is loaded, with no rebuild or reinstall step. `bundle install` records a path source in `Gemfile.lock` as a `PATH` block holding the relative path and the version from the gemspec: ~~~ PATH remote: gems/mygem specs: mygem (1.0.0) DEPENDENCIES mygem! ~~~ The `!` marks a dependency pinned to a source declared in the Gemfile. See [How Gemfile.lock works](/gemfile-lock) for the full format. A path source exists only in the Gemfile. A gemspec dependency can name nothing more than a gem and a version requirement, so a published gem cannot direct its users to a local directory. When a gem released from a monorepo is installed, its dependencies are resolved from a gem server like anyone else's. The path wiring is a development convenience that stays behind in the repository. One Gemfile for many gems ------------------------- A typical layout keeps each gem in its own directory, each with its own gemspec, and puts a single Gemfile at the root: ~~~ mygem/ ├── Gemfile ├── Rakefile └── gems/ ├── mygem/ │ ├── mygem.gemspec │ └── lib/ └── mygem-cli/ ├── mygem-cli.gemspec └── lib/ ~~~ The root Gemfile can list each gem individually, or use the block form of `path`, which scans subdirectories of the given directory for gemspecs: ~~~ruby source "https://rubygems.org" path "gems" do gem "mygem" gem "mygem-cli" end ~~~ One `bundle install` at the root resolves everything, and both gems land in the same `PATH` block of the lockfile: ~~~ PATH remote: gems specs: mygem (1.0.0) mygem-cli (1.0.0) mygem (~> 1.0) ~~~ An alternative is the [`gemspec` method](/gemfile#GEMSPEC) with its `:path` option, one call per gem: ~~~ruby source "https://rubygems.org" gemspec path: "gems/mygem" gemspec path: "gems/mygem-cli" ~~~ The difference is what comes along. A `gem` entry with `path:` adds only the gem itself. `gemspec path:` also pulls that gem's runtime dependencies into the default group and its development dependencies into the `:development` group, which is useful when the root bundle is the development environment for every gem in the repository. Gems that depend on each other ------------------------------ When one gem in the repository depends on another, the dependency is declared in the gemspec with an ordinary version constraint: ~~~ruby Gem::Specification.new do |s| s.name = "mygem-cli" # ... s.add_dependency "mygem", "~> 1.0" end ~~~ The division of labor follows [Gemfile and gemspec](/gemfile-and-gemspec). The gemspec states which released versions are compatible, and that constraint is what ships in the built gem. The Gemfile's path source decides where the dependency comes from during development, so Bundler satisfies the `mygem (~> 1.0)` requirement with the local copy rather than a release from rubygems.org. Because the dependency is pinned to its path source, versions on the gem server are never considered, and resolution fails outright if the local version stops matching the constraint. Releasing --------- Each gem is still packaged and published on its own. Run [`gem build` and `gem push`](/publishing), or the `rake release` task that `bundle gem` generates, inside each gem's directory. Repositories with many gems commonly add tasks to the root Rakefile that loop over the gem directories to build, tag, and push them together. Whether the gems share one version number or are versioned independently is a policy choice for the project. The constraints in the gemspecs are what keep a mixed set of released versions working together. Rails is the best-known Ruby monorepo. The [rails/rails](https://github.com/rails/rails) repository holds railties, activesupport, actionpack, and the other framework gems, each in its own directory with its own gemspec, all released with the same version number. The [ruby/rubygems](https://github.com/ruby/rubygems) repository develops RubyGems and Bundler side by side in the same way. --- # How to use Bundler with Ruby Source: https://guides.rubygems.org/bundler_setup/ Configure the load path so all dependencies in your Gemfile can be required ~~~ruby require 'bundler/setup' require 'nokogiri' ~~~ Only add gems from specified groups to the load path. If you want the gems in the default group, make sure to include it ~~~ruby require 'bundler' Bundler.setup(:default, :ci) require 'nokogiri' ~~~ Learn More: Groups ## Compatibility Ruby 2.0 and RubyGems 2.0 both require Bundler 1.3 or later. If you have questions about compatibility between Bundler and your system, please check the compatibility list. Learn More: Compatibility ## Setting Up Your Application to Use Bundler Bundler makes sure that Ruby can find all of the gems in the `Gemfile` (and all of their dependencies). If your app is a Rails app, your default application already has the code necessary to invoke bundler. For another kind of application (such as a Sinatra application), you will need to set up bundler before trying to require any gems. At the top of the first file that your application loads (for Sinatra, the file that calls `require 'sinatra'`), put the following code: ~~~ruby require 'bundler/setup' ~~~ This will automatically discover your `Gemfile` and make all of the gems in your `Gemfile` available to Ruby (in technical terms, it puts the gems "on the load path"). Now that your code is available to Ruby, you can require the gems that you need. For instance, you can `require 'sinatra'`. If you have a lot of dependencies, you might want to say "require all of the gems in my `Gemfile`". To do this, put the following code immediately following `require 'bundler/setup'`: ~~~ruby Bundler.require(:default) ~~~ For our example Gemfile, this line is exactly equivalent to: ~~~ruby require 'rails' require 'rack-cache' require 'nokogiri' ~~~ Astute readers will notice that the correct way to require the `rack-cache` gem is `require 'rack/cache'`, not `require 'rack-cache'`. To tell bundler to use `require 'rack/cache'`, update your Gemfile: ~~~ruby source 'https://rubygems.org' gem 'rails', '5.0.0' gem 'rack-cache', require: 'rack/cache' gem 'nokogiri', '~> 1.4.2' ~~~ For such a small `Gemfile`, we'd advise you to skip `Bundler.require` and just require the gems by hand (especially given the need to put in a `:require` directive in the `Gemfile`). For much larger `Gemfile`s, using `Bundler.require` allows you to skip repeating a large stack of requirements. --- # How to use Bundler in a single-file Ruby script Source: https://guides.rubygems.org/bundler_in_a_single_file_ruby_script/ To use Bundler in a single-file script, add `require 'bundler/inline'` at the top of your Ruby file. Then, use the `gemfile` method to declare any gem sources and gems that you need. Here's an example: ~~~ ruby require 'bundler/inline' gemfile do source 'https://rubygems.org' gem 'json', require: false gem 'nap', require: 'rest' gem 'cocoapods', '~> 0.34.1' end puts 'Gems installed and loaded!' puts "The nap gem is at version #{REST::VERSION}" ~~~ To run this script, including installing any missing gems, save the script into a file (for example, `bundler_inline_example.rb`) and then run the file with the command `ruby bundler_inline_example.rb`. Running the script will automatically install any missing gems, require the gems you listed, and then run your code. --- # How to deploy bundled applications Source: https://guides.rubygems.org/deploying/ Before deploying an app that uses Bundler, add your `Gemfile` and `Gemfile.lock` to source control, but ignore the `.bundle` folder, which is specific to each machine. ~~~ $ echo ".bundle" >> .gitignore $ git add Gemfile Gemfile.lock .gitignore $ git commit -m "Add Bundler support" ~~~ After updating to the latest code, install your bundle to the `vendor/bundle` directory, ensuring all your dependencies are met. ~~~ $ bundle install --deployment ~~~ Start your application servers as usual, and your application will use your bundled environment with the exact same gems you use in development. If you have run `bundle package`, the cached gems will be used automatically. Learn More: Packing ### After deploying Make sure to use `bundle exec` to run any executables from gems in the bundle ~~~ $ bundle exec rake db:setup ~~~ Alternatively, you can run `bundle binstubs GEM_NAME` (or `bundle binstubs --all`) to generate executable binaries that can be used instead of `bundle exec`. Learn More: Executables ### Heroku When you deploy to Heroku, Bundler will be run automatically as long as a Gemfile is present. If you check in your Gemfile.lock, Heroku will run `bundle install --deployment`. If you want to exclude certain groups using the `--without` option, you need to use `heroku config`. ~~~ $ heroku config:set BUNDLE_WITHOUT="test development" --app app_name ~~~ Heroku Bundler Documentation ## Deploying Your Application When you run `bundle install`, bundler will (by default), install your gems to your system repository of gems. This means that they will show up in `gem list`. Additionally, if you are developing a number of applications, you will not need to download and install gems in common for each application. This is nice for development, but somewhat problematic for deployment. In a deployment scenario, the Unix user you deploy with may not have access to install gems to a system location. Even if the user does (or you use `sudo`), the user that boots the application may not have access to them. For instance, Passenger runs its Ruby subprocesses with the user `nobody`, a somewhat restricted user. The tradeoffs in a deployment environment lean more heavily in favor of isolation (even at the cost of a somewhat slower deploy-time `bundle install` when some third-party dependencies have changed). As a result, bundler comes with a `--deployment` flag that encapsulates the best practices for using bundler in a deployment environment. These practices are based on significant feedback we have received during the development of bundler, as well as a number of bug reports that mostly reflected a misunderstanding of how to best configure bundler for deployment. The `--deployment` flag adds the following defaults: - Instead of installing gems to the system location, bundler will install gems to `vendor/bundle` inside your application. Bundler will transparently remember this location when you invoke it inside your application (with `Bundler.setup` and `Bundler.require`). - Bundler will not use gems already installed to your system, even if they exist. - If you have run `bundle pack`, checked in the `vendor/cache` directory, and do not have any git gems, Bundler will not contact the internet while installing your bundle. - Bundler will require a `Gemfile.lock` snapshot, and fail if you did not provide one. - Bundler will not transparently update your `Gemfile.lock` if it is out of date with your `Gemfile` By defaulting the bundle directory to `vendor/bundle`, and installing your bundle as part of your deployment process, you can be sure that the same Unix user that checked out your application also installed the third-party code your application needs. This means that if Passenger (or Unicorn) can see your application, it can also see its dependencies. The `--deployment` flag requires an up-to-date `Gemfile.lock` to ensure that the testing you have done (in development and staging) actually reflects the code you put into production. You can run `bundle check` before deploying your application to make sure that your `Gemfile.lock` is up-to-date. Note that it will always be up-to-date if you have run `bundle install`, successfully booted your application (or run your tests) since the last time you changed your `Gemfile`. --- # Name your gem Source: https://guides.rubygems.org/name-your-gem/ Our recommendation on the use of "_" and "-" in your gem's name. Here are some examples of our recommendations for naming gems: Gem name | Require statement | Main class or module ---------------------- | -------------------------------- | ----------------------- `ruby_parser` | `require 'ruby_parser'` | `RubyParser` `rdoc-data` | `require 'rdoc/data'` | `RDoc::Data` `net-http-persistent` | `require 'net/http/persistent'` | `Net::HTTP::Persistent` `net-http-digest_auth` | `require 'net/http/digest_auth'` | `Net::HTTP::DigestAuth` The main goal of these recommendations is to give the user some clue about how to require the files in your gem. Following these conventions also lets Bundler require your gem with no extra configuration. If you publish a gem on [rubygems.org][rubygems] it may be removed if the name is objectionable, violates intellectual property or the contents of the gem meet these criteria. You can report such a gem to [support@rubygems.org](mailto:support@rubygems.org) via email. [rubygems]: https://rubygems.org Use underscores for multiple words ---------------------------------- If a class or module has multiple words, use underscores to separate them. This matches the file the user will require, making it easier for the user to start using your gem. Use dashes for extensions ------------------------- If you're adding functionality to another gem, use a dash. This usually corresponds to a `/` in the require statement (and therefore your gem's directory structure) and a `::` in the name of your main class or module. Mix underscores and dashes appropriately ---------------------------------------- If your class or module has multiple words and you're also adding functionality to another gem, follow both of the rules above. For example, [`net-http-digest_auth`][digest-gem] adds [HTTP digest authentication][digest-standard] to `net/http`. The user will `require 'net/http/digest_auth'` to use the extension (in class `Net::HTTP::DigestAuth`). [digest-gem]: https://rubygems.org/gems/net-http-digest_auth [digest-standard]: https://tools.ietf.org/html/rfc2617 Don't use UPPERCASE letters --------------------------- OS X and Windows have case-insensitive filesystems by default. Users may mistakenly require files from a gem using uppercase letters which will be non-portable if they move it to a non-windows or OS X system. While this will mostly be a newbie mistake we don't need to be confusing them more than necessary. Credits ------- This guide was expanded from [How to Name Gems][how-to-name-gems] by Eric Hodel. [how-to-name-gems]: https://web.archive.org/web/20130821183311/https://blog.segment7.net/2010/11/15/how-to-name-gems --- # Patterns Source: https://guides.rubygems.org/patterns/ Common practices to make your gem users' and other developers' lives easier. This page covers conventions for naming and structuring a gem and for loading its code. Guidance that used to live here has moved: for version numbering, prerelease versions, and dependency constraints see [Versioning and compatibility](/versioning), and for where to declare runtime and development dependencies see [Gemfile and gemspec](/gemfile-and-gemspec). * [Consistent naming](#consistent-naming) * [Loading code](#loading-code) Consistent naming ----------------- > There are only two hard things in Computer Science: cache invalidation and naming things. > -[Phil Karlton](https://martinfowler.com/bliki/TwoHardThings.html) ### File names Be consistent with how the files of your gem are named. This is the layout `bundle gem hola --exe` generates, with the support files trimmed: % tree hola hola ├── Gemfile ├── Rakefile ├── exe │ └── hola ├── hola.gemspec ├── lib │ ├── hola │ │ └── version.rb │ └── hola.rb └── test ├── test_helper.rb └── test_hola.rb The executable in `exe` and the primary file in `lib` are named after the gem. A developer can easily jump in and call `require 'hola'` with no problems. Everything beyond the primary file lives in a directory with the gem's name, like `lib/hola/version.rb`, for reasons covered in the [Loading code](#loading-code) section below. ### Naming your gem Naming your gem is important. Before you pick a name for your gem, do a quick search on [RubyGems.org](https://rubygems.org) and [GitHub](https://github.com/search) to see if someone else has taken it. Every published gem must have a unique name. Be sure to read our [naming recommendations](/name-your-gem) when you've found a name you like. Loading code ------------ At its core, RubyGems exists to help you manage Ruby's `$LOAD_PATH`, which is how the `require` statement picks up new code. There's several things you can do to make sure you're loading code the right way. ### Respect the global load path When packaging your gem files, you need to be careful of what is in your `lib` directory. Every gem you have installed gets its `lib` directory appended onto your `$LOAD_PATH`. This means any file on the top level of the `lib` directory could get required. For example, let's say we have a `foo` gem with the following structure: . └── lib ├── foo │ └── cgi.rb ├── erb.rb ├── foo.rb └── set.rb This might seem harmless since your custom `erb` and `set` files are within your gem. However, this is not harmless, anyone who requires this gem will not be able to bring in the [ERB](https://docs.ruby-lang.org/en/master/ERB.html) or [Set](https://docs.ruby-lang.org/en/master/Set.html) classes provided by Ruby's standard library. The best way to get around this is to keep files in a different directory under `lib`. The usual convention is to be consistent and put them in the same folder name as your gem's name, for example `lib/foo/cgi.rb`. ### Requiring files relative to each other Gems should not have to use `__FILE__` to bring in other Ruby files in your gem. Code like this is surprisingly common in gems: require File.join( File.dirname(__FILE__), "foo", "bar") Or: require File.expand_path(File.join( File.dirname(__FILE__), "foo", "bar")) The fix is simple, just require the file relative to the load path: require 'foo/bar' Or use require_relative: require_relative 'foo/bar' The [make your own gem](/make-your-own-gem) guide has a great example of this behavior in practice, including a working test suite. The code for that gem is [on GitHub](https://github.com/qrush/hola) as well. ### Mangling the load path Gems should not change the `$LOAD_PATH` variable. RubyGems manages this for you. Code like this should not be necessary: lp = File.expand_path(File.dirname(__FILE__)) unless $LOAD_PATH.include?(lp) $LOAD_PATH.unshift(lp) end Or: __DIR__ = File.dirname(__FILE__) $LOAD_PATH.unshift __DIR__ unless $LOAD_PATH.include?(__DIR__) || $LOAD_PATH.include?(File.expand_path(__DIR__)) When RubyGems activates a gem, it adds your package's `lib` folder to the `$LOAD_PATH` ready to be required normally by another lib or application. It is safe to assume you can then `require` any file in your `lib` folder. ### Don't use `gem` from within your gem You may have seen some code like this around to make sure a specific version of a gem is activated before requiring it: gem "extlib", ">= 1.0.8" require "extlib" Gems **should not** do this. Declare the requirement in the gemspec instead, so the resolver can weigh it together with every other gem's requirements, and let RubyGems handle activating the right version. Applications control their dependency versions with [Bundler](/getting_started) rather than `gem` calls. Credits ------- Several sources were used for content for this guide: * [Rubygems Good Practice](https://yehudakatz.com/2009/07/24/rubygems-good-practice/) * [Gem Packaging: Best Practices](https://weblog.rubyonrails.org/2009/9/1/gem-packaging-best-practices) --- # Gems with Extensions Source: https://guides.rubygems.org/gems-with-extensions/ Creating a gem that includes an extension that is built at install time. Many gems use extensions to wrap libraries that are written in C with a ruby wrapper. Examples include [nokogiri][nokogiri] which wraps [libxml2 and libxslt](http://www.xmlsoft.org), [pg](https://rubygems.org/gems/pg) which is an interface to the [PostgreSQL database](https://www.postgresql.org) and the [mysql](https://rubygems.org/gems/mysql) and [mysql2](https://rubygems.org/gems/mysql2) gems which provide an interface to the [MySQL database](https://www.mysql.com). Creating a gem that uses an extension involves several steps. This guide will focus on what you should put in your gem specification to make this as easy and maintainable as possible. The extension in this guide will wrap `malloc()` and `free()` from the C standard library. Extensions don't have to be written in C. This guide uses C for its main example, but you can also write extensions in [Rust](#rust-extensions); see the Rust Extensions section below. Gem layout ---------- Every gem should start with a Rakefile which contains the tasks needed by developers to work on the gem. The files for the extension should go in the `ext/` directory in a directory matching the extension's name. For this example we'll use "my_malloc" for the name. Some extensions will be partially written in C and partially written in ruby. If you are going to support multiple languages, such as C and Java extensions, put the ruby files that are specific to the C extension in a `lib/` directory under the extension's directory (`ext/my_malloc/lib/` here), not in the top-level `lib/` directory. Rakefile ext/my_malloc/extconf.rb # extension configuration ext/my_malloc/my_malloc.c # extension source ext/my_malloc/lib/my_malloc/helper.rb # ruby code for the C extension lib/my_malloc.rb # generic features When the extension is built the files in `ext/my_malloc/lib/` will be installed into the `lib/` directory for you. extconf.rb ---------- The extconf.rb configures a Makefile that will build your extension. The extconf.rb must check for the necessary functions, macros and shared libraries your extension depends upon. The extconf.rb must exit with an error if any of these are missing. Here is an extconf.rb that checks for `malloc()` and `free()` and creates a Makefile that will install the built extension at `lib/my_malloc/my_malloc.so`: require "mkmf" abort "missing malloc()" unless have_func "malloc" abort "missing free()" unless have_func "free" create_makefile "my_malloc/my_malloc" See the [mkmf documentation][mkmf.rb] and [extension.rdoc][extension.rdoc] for further information about creating an extconf.rb and for documentation on these methods. C Extension ----------- The C extension that wraps `malloc()` and `free()` goes in `ext/my_malloc/my_malloc.c`. Here's the listing: #include struct my_malloc { size_t size; void *ptr; }; static void my_malloc_free(void *p) { struct my_malloc *ptr = p; if (ptr->size > 0) free(ptr->ptr); } static VALUE my_malloc_alloc(VALUE klass) { VALUE obj; struct my_malloc *ptr; obj = Data_Make_Struct(klass, struct my_malloc, NULL, my_malloc_free, ptr); ptr->size = 0; ptr->ptr = NULL; return obj; } static VALUE my_malloc_init(VALUE self, VALUE size) { struct my_malloc *ptr; size_t requested = NUM2SIZET(size); if (0 == requested) rb_raise(rb_eArgError, "unable to allocate 0 bytes"); Data_Get_Struct(self, struct my_malloc, ptr); ptr->ptr = malloc(requested); if (NULL == ptr->ptr) rb_raise(rb_eNoMemError, "unable to allocate %ld bytes", requested); ptr->size = requested; return self; } static VALUE my_malloc_release(VALUE self) { struct my_malloc *ptr; Data_Get_Struct(self, struct my_malloc, ptr); if (0 == ptr->size) return self; ptr->size = 0; free(ptr->ptr); return self; } void Init_my_malloc(void) { VALUE cMyMalloc; cMyMalloc = rb_const_get(rb_cObject, rb_intern("MyMalloc")); rb_define_alloc_func(cMyMalloc, my_malloc_alloc); rb_define_method(cMyMalloc, "initialize", my_malloc_init, 1); rb_define_method(cMyMalloc, "free", my_malloc_release, 0); } This extension is simple with just a few parts: * `struct my_malloc` to hold the allocated memory * `my_malloc_free()` to free the allocated memory after garbage collection * `my_malloc_alloc()` to create the ruby wrapper object * `my_malloc_init()` to allocate memory from ruby * `my_malloc_release()` to free memory from ruby * `Init_my_malloc()` to register the functions in the `MyMalloc` class. Now we can create the actual `MyMalloc` class and bind newly defined methods in Ruby (`lib/my_malloc.rb` is the correct place for that), e.g.: class MyMalloc VERSION = "1.0" end require "my_malloc/my_malloc" You can test building the extension as follows: $ cd ext/my_malloc $ ruby extconf.rb checking for malloc()... yes checking for free()... yes creating Makefile $ make compiling my_malloc.c linking shared-object my_malloc.bundle $ cd ../.. $ ruby -Ilib:ext -r my_malloc -e "p MyMalloc.new(5).free" # But this will get tedious after a while. Let's automate it! rake-compiler ------------- [rake-compiler][rake-compiler] is a set of rake tasks for automating extension building. rake-compiler can be used with C or Java extensions in the same project ([nokogiri][nokogiri] uses it this way). First install the gem: $ gem install rake-compiler Adding rake-compiler to the `Rakefile` is very simple: require "rake/extensiontask" Rake::ExtensionTask.new "my_malloc" do |ext| ext.lib_dir = "lib/my_malloc" end Now you can build the extension with `rake compile` and hook the compile task into other tasks (such as tests). Setting `lib_dir` places the shared library in `lib/my_malloc/my_malloc.so` (or `.bundle` or `.dll`). This allows the top-level file for the gem to be a ruby file. This allows you to write the parts that are best suited to ruby in ruby. For example: class MyMalloc VERSION = "1.0" end require "my_malloc/my_malloc" Setting the `lib_dir` also allows you to build a gem that contains pre-built extensions for multiple versions of ruby. (An extension for Ruby 1.9.3 cannot be used with an extension for Ruby 2.0.0). `lib/my_malloc.rb` can pick the correct shared library to install. Gem specification ----------------- The final step to building the gem is adding the extconf.rb to the extensions list in the gemspec: Gem::Specification.new "my_malloc", "1.0" do |s| # [...] s.extensions = %w[ext/my_malloc/extconf.rb] end Now you can build and release the gem! Extension Naming ---------------- To avoid unintended interactions between gems, it's a good idea for each gem to keep all of its files in a single directory. Here are the recommendations for a gem with the name ``: 1. `ext/` is the directory that contains the source files and `extconf.rb` 2. `ext//.c` is the main source file (there may be others) 3. `ext//.c` contains a function `Init_`. (The name following `Init_` function must exactly match the name of the extension for it to be loadable by require.) 4. `ext//extconf.rb` calls `create_makefile('/')` only when the all the pieces needed to compile the extension are present. 5. The gemspec sets `extensions = ['ext//extconf.rb']` and includes any of the necessary extension source files in the `files` list. 6. `lib/.rb` contains `require '/'` which loads the C extension Rust Extensions --------------- Native extensions can also be written in [Rust][rust] instead of C. Since [RubyGems 3.3.11][pr-5175] a gem can declare a Rust extension that is compiled at install time, giving you Rust's memory safety and the Cargo build system while still producing an ordinary shared library that Ruby loads with `require`. The recommended toolchain is maintained by the [oxidize-rb][oxidize-rb] project: * [rb-sys][rb-sys] wires Cargo into the standard `rake-compiler` workflow, so building, testing, and cross-compiling work the same way they do for C extensions. * [magnus][magnus] provides a high-level, safe API for defining Ruby modules, classes, and methods from Rust. You can drop down to the raw `rb-sys` bindings when you need to, but most gems should use magnus. You'll need a [Rust toolchain][rustup] installed in addition to Ruby. ### Generating the gem The quickest way to start is to let Bundler scaffold the whole project: $ bundle gem --ext=rust my_gem This produces a working gem with all of the Rust wiring already in place: Cargo.toml # Cargo workspace Rakefile my_gem.gemspec ext/my_gem/Cargo.toml # crate definition and dependencies ext/my_gem/extconf.rb # extension configuration ext/my_gem/src/lib.rs # extension source lib/my_gem.rb # generic features The rest of this section walks through the pieces that differ from a C extension. ### extconf.rb Instead of `mkmf`'s `create_makefile`, a Rust extension uses `create_rust_makefile` from `rb_sys/mkmf`. It generates a Makefile that drives Cargo: require "mkmf" require "rb_sys/mkmf" create_rust_makefile("my_gem/my_gem") The argument is the install path of the compiled library, exactly like the argument to `create_makefile`. Here it places the shared object at `lib/my_gem/my_gem.so`. ### Cargo.toml Each extension is a Cargo crate. The two things that matter for a Ruby extension are the `cdylib` crate type, so Cargo produces a shared library Ruby can load, and the `magnus` dependency: [package] name = "my_gem" version = "0.1.0" edition = "2021" publish = false [lib] crate-type = ["cdylib"] [dependencies] magnus = "0.8" A `Cargo.toml` in the project root declares a [workspace][cargo-workspace] so that editors and `cargo` commands run from the top of the gem behave correctly: [workspace] members = ["./ext/my_gem"] resolver = "2" ### The Rust source `ext/my_gem/src/lib.rs` defines the extension. The function marked with `#[magnus::init]` is called when Ruby loads the library, and it's where you define your modules, classes, and methods: use magnus::{function, prelude::*, Error, Ruby}; fn hello(subject: String) -> String { format!("Hello {subject}, from Rust!") } #[magnus::init] fn init(ruby: &Ruby) -> Result<(), Error> { let module = ruby.define_module("MyGem")?; module.define_singleton_method("hello", function!(hello, 1))?; Ok(()) } magnus converts between Ruby and Rust types for you, so `hello` takes and returns an ordinary Rust `String`. Calling `MyGem.hello("world")` from Ruby returns `"Hello world, from Rust!"`. ### Rakefile `rb_sys` ships a drop-in replacement for `Rake::ExtensionTask` that knows how to drive Cargo. Use `RbSys::ExtensionTask` and it hooks into `rake compile` just like the C workflow: require "rb_sys/extensiontask" task build: :compile GEMSPEC = Gem::Specification.load("my_gem.gemspec") RbSys::ExtensionTask.new("my_gem", GEMSPEC) do |ext| ext.lib_dir = "lib/my_gem" end task default: %i[compile test] ### lib/my_gem.rb The top-level Ruby file requires the compiled library, just like a C extension: require_relative "my_gem/version" require "my_gem/my_gem" module MyGem class Error < StandardError; end # Your code goes here... end ### Gem specification Point `extensions` at the `extconf.rb` and add a dependency on `rb_sys`: Gem::Specification.new do |spec| spec.name = "my_gem" spec.version = MyGem::VERSION # [...] spec.extensions = ["ext/my_gem/extconf.rb"] spec.add_dependency "rb_sys", ">= 0.9.128" end Make sure the gemspec's `files` list includes the Rust sources and the `Cargo.toml` files (for example `ext/**/*.rs` and `**/Cargo.*`) so they ship in the packaged gem. The scaffold generated by `bundle gem` already does this via `git ls-files`. ### Building and testing locally Compile the extension and try it out: $ bundle install $ bundle exec rake compile $ bundle exec ruby -Ilib -r my_gem -e "puts MyGem.hello('world')" Hello world, from Rust! `rake compile` builds the crate with Cargo and copies the resulting shared library into `lib/my_gem/`, where `lib/my_gem.rb` can `require` it. From here `rake test` works exactly as it would for a C extension. Although Cargo omits `Cargo.lock` from version control for library crates by default, you should commit it for a gem. The native extension is built from source on the user's machine at install time, so a checked-in `Cargo.lock` gives everyone the same, reproducible set of Rust dependencies. The `.gitignore` generated by `bundle gem` ignores only the `target/` build directory, leaving `Cargo.lock` tracked. Further Reading --------------- * [my_malloc](https://github.com/rubygems/guides/tree/my_malloc) contains the source for this extension with some additional comments. * [extension.rdoc][extension.rdoc] describes in greater detail how to build extensions in ruby * [MakeMakefile][mkmf.rb] contains documentation for mkmf.rb, the library extconf.rb uses to detect ruby and C library features * [rake-compiler][rake-compiler] integrates building C and Java extensions into your Rakefile in a smooth manner. * [Writing C extensions part 1](https://tenderlovemaking.com/2009/12/18/writing-ruby-c-extensions-part-1.html) and [part 2](https://tenderlovemaking.com/2010/12/11/writing-ruby-c-extensions-part-2.html)) by Aaron Patterson * Interfaces to C libraries can be written using ruby and [fiddle](https://docs.ruby-lang.org/en/master/Fiddle.html) (part of the standard library) or [ruby-ffi](https://github.com/ffi/ffi) * [The Ruby on Rust Book][rb-sys-book] is the official guide to writing extensions in Rust with rb-sys and magnus * [magnus][magnus] provides the high-level Rust API used in the Rust example above * [oxi-test][oxi-test] is a minimal, cross-compiled reference gem built with rb-sys [extension.rdoc]: https://github.com/ruby/ruby/blob/master/doc/extension.rdoc [mkmf.rb]: https://github.com/ruby/ruby/blob/master/lib/mkmf.rb [rake-compiler]: https://github.com/luislavena/rake-compiler [nokogiri]: https://rubygems.org/gems/nokogiri [pr-5175]: https://github.com/rubygems/rubygems/pull/5175 [rust]: https://www.rust-lang.org [rustup]: https://rustup.rs [oxidize-rb]: https://github.com/oxidize-rb [rb-sys]: https://github.com/oxidize-rb/rb-sys [magnus]: https://github.com/matsadler/magnus [cargo-workspace]: https://doc.rust-lang.org/cargo/reference/workspaces.html [rb-sys-book]: https://oxidize-rb.github.io/rb-sys/ [oxi-test]: https://github.com/oxidize-rb/oxi-test --- # Bundler in gems Source: https://guides.rubygems.org/rubygems/ ## Using Bundler while developing a gem If you're creating a gem from scratch, you can use bundler's built in gem skeleton to create a base gem for you to edit. ~~~ $ bundle gem my_gem ~~~ This will create a new directory named `my_gem` with your new gem skeleton. If you already have a gem, you can create a Gemfile and use Bundler to manage your development dependencies. Here's an example. ~~~ruby source "https://rubygems.org" gemspec gem "rspec", "~> 3.9" gem "rubocop", "0.79.0" ~~~ In this Gemfile, the `gemspec` method imports gems listed with `add_runtime_dependency` in the `my_gem.gemspec` file, and it also installs rspec and rubocop to test and develop the gem. All dependencies from the gemspec and Gemfile will be installed by `bundle install`, but rspec and rubocop will not be included by `gem install mygem` or `bundle add mygem`. Declaring development dependencies in the Gemfile like this, rather than with `add_development_dependency` in the gemspec, is the recommended layout. See [Gemfile and gemspec](/gemfile-and-gemspec) for the reasoning. Runtime dependencies in your gemspec are treated as if they are listed in your Gemfile, and development dependencies are added by default to the group, `:development`. You can change that group with the `:development_group` option: ~~~ruby gemspec :development_group => :dev ~~~ You can also point to a specific gemspec directory using the `:path` option. If your gemspec is in `/gemspec/path`, use: ~~~ruby gemspec :path => '/gemspec/path' ~~~ If you omit `:path`, Bundler will look for gemspecs in the same directory as the Gemfile (usually the project root). If you have multiple gemspecs in the same directory, specify which one you'd like to reference using `:name`. This refers to the gem name **declared inside the gemspec**, not the gemspec filename: ~~~ruby gemspec :name => 'my_awesome_gem' ~~~ This will match the gemspec where `spec.name = "my_awesome_gem"`, regardless of whether it's defined in `my_awesome_gem.gemspec` or another file. That's it! Use bundler when developing your gem, and otherwise, use gemspecs normally! ~~~ $ gem build my_gem.gemspec ~~~ --- # Trusted Publishing Source: https://guides.rubygems.org/trusted-publishing/ With Trusted Publishing, releasing a new version of your gem is as simple as pushing a git tag to GitHub. There are no API tokens to create, rotate, or store as secrets — GitHub Actions securely authenticates with RubyGems.org on your behalf using short-lived tokens. Under the hood, Trusted Publishing uses OpenID Connect (OIDC) to exchange short-lived identity tokens between GitHub Actions and RubyGems.org. Once configured, you never need to touch credentials again. * [Adding a trusted publisher to an existing gem](#adding-a-trusted-publisher-to-an-existing-gem) * [Releasing gems with a trusted publisher](#releasing-gems-with-a-trusted-publisher) * [Pushing a new gem with a trusted publisher](#pushing-a-new-gem-with-a-trusted-publisher) * [Using reusable workflows](#using-reusable-workflows) * [How it works](#how-it-works) * [Further reading](#further-reading) ## Adding a trusted publisher to an existing gem Adding a trusted publisher to a gem only requires a single setup step. On [your profile page](https://rubygems.org/profile/me), click the link to any gem you'd like to configure. ![List of gems on a RubyGems.org profile](/images/trusted-publishing/profile-gem-list.png){:class="t-img"} If you're a gem owner, you'll see a link to "Trusted publishers" on the right side of the page. Click that link. ![Links shown on the sidebar of a gem page when the user is an owner](/images/trusted-publishing/gem-owner-sidebar-links.png){:class="t-img t-img--small"} This will take you to the gem's trusted publishers page. ![Gem's trusted publisher page with a create button](/images/trusted-publishing/rubygem-trusted-publisher-create.png){:class="t-img"} Click the "Create" button, which will take you to the publisher configuration page. ![Gem trusted publisher creation form](/images/trusted-publishing/rubygem-trusted-publisher-form.png){:class="t-img"} Providing the owner name, repository name, and GitHub Actions workflow name allows RubyGems to securely accept uploaded gems from the GitHub Actions infrastructure. If you have multiple workflows that push gems, you can create one Trusted Publisher for each workflow. The environment allows GitHub to constrain who can publish your gem if many people have access to the repository. We suggest using the [GitHub Action Environment](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/using-environments-for-deployment) name "release", which we will use in our workflow examples below. Once you click "Create Rubygem trusted publisher", your publisher will be registered and will appear in the list of trusted publishers for this gem. ![List of configured gem trusted publishers](/images/trusted-publishing/rubygem-trusted-publishers-index.png){:class="t-img"} Once registered, the `release.yml` workflow on `rubygems/sample-gem` will be able to generate short-lived API tokens from RubyGems.org that are scoped to push only to this gem. A repo and workflow can be registered to multiple gems. For example, the `release.yml` workflow from the `rails/rails` repo can be registered for both the `rails` and `activerecord` gems. Each gem can likewise allow multiple publishers, for example a single gem could allow both workflows `release-linux.yml` and `release-mac.yml`. ## Releasing gems with a trusted publisher Once you have a trusted publisher configured, you can use RubyGems' [`release-gem`](https://github.com/rubygems/release-gem) GitHub Action to set up your workflow to push gems to RubyGems.org. This looks almost exactly the same as normal, except that you don't need any explicit usernames, passwords, or API tokens: GitHub's OIDC identity provider will take care of everything for you: ```yaml name: Push gem on: push: tags: - "v*" jobs: push: runs-on: ubuntu-latest permissions: contents: write id-token: write # If you configured a GitHub environment on RubyGems, you must use it here. environment: release steps: # Set up - uses: actions/checkout@v5 with: persist-credentials: false - name: Set up Ruby uses: ruby/setup-ruby@v1 with: bundler-cache: true ruby-version: ruby # Release - uses: rubygems/release-gem@v1 ``` Note the `id-token: write` permission: you **must** provide this permission at either the job level (strongly recommended) or workflow level (discouraged). Without it, the publishing action won't have sufficient permissions to identify itself to RubyGems.org. For more about `environment` setting, see: [Using Environment for your deployment (GitHub.com)](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/using-environments-for-deployment) That's it! With the trusted publisher configured and this workflow in your repository, you can release a new version of your gem by simply pushing a git tag. No API tokens, no manual `gem push` — just tag and push. --- The sections below cover additional topics: publishing a brand-new gem, using reusable workflows, and the underlying OIDC mechanism. If you've already set up trusted publishing for an existing gem, you're all set. ## Pushing a new gem with a trusted publisher Trusted publishers are not just for existing gems, they can also be used to push new gems! This helps reduce the friction for setting up fully automated publishing workflows for new gems, since the same workflow will work for the first released version of a gem as well as all future versions. To set up a trusted publisher for a new gem, you'll need to set up a "pending" trusted publisher under your RubyGems.org profile. The process is the same as for [adding a trusted publisher to an existing gem](#adding-a-trusted-publisher-to-an-existing-gem), except that you'll also need to specify a gem name. To configure a pending trusted publisher, go to your [pending trusted publisher page](https://rubygems.org/profile/oidc/pending_trusted_publishers) ![User's pending trusted publisher page with a create button](/images/trusted-publishing/pending-trusted-publisher-create.png){:class="t-img"} Click the "Create" button, which will take you to the publisher configuration page. ![Pending trusted publisher creation form](/images/trusted-publishing/pending-trusted-publisher-form.png){:class="t-img"} For example, if you have a repository at `https://github.com/rubygems/sample-gem` with a release workflow at `push_gem.yml` and an environment named `release` that you would like to push to RubyGems.org as the `sample-gem` gem, you would enter the following values: ![Pending trusted publisher creation form with values filled in](/images/trusted-publishing/pending-trusted-publisher-form-filled.png){:class="t-img"} If your workflow uses a reusable workflow from another repository, you'll also need to fill in the optional "Workflow Repository Owner" and "Workflow Repository Name" fields. See [Using reusable workflows](#using-reusable-workflows) for details. Once you click "Create Pending trusted publisher", your publisher will be registered and will appear in the list of pending publishers for your account. ![List of configured pending trusted publishers](/images/trusted-publishing/pending-trusted-publishers-index.png){:class="t-img"} From this point, the "pending" publisher will act like a "normal" publisher. After its first successful push, it will be converted to a "normal" trusted publisher for the new gem, and you will be added as the owner of the gem. ## Using reusable workflows If your release workflow uses a [reusable workflow](https://docs.github.com/en/actions/sharing-automations/reusing-workflows) from a different repository, you'll need to configure the optional "Workflow Repository" fields. When a workflow calls a reusable workflow from another repository, the OIDC token's `job_workflow_ref` claim points to the reusable workflow's location, not the calling repository's workflow. The "Workflow Repository Owner" and "Workflow Repository Name" fields tell RubyGems.org where the actual workflow file lives. For example, if your gem's repository (`my-org/my-gem`) calls a shared release workflow from `shared-org/shared-workflows`: ```yaml # In my-org/my-gem/.github/workflows/release.yml jobs: release: uses: shared-org/shared-workflows/.github/workflows/ruby-gem-release.yml@main ``` You would configure the trusted publisher with: - **Repository owner**: `my-org` - **Repository name**: `my-gem` - **Workflow filename**: `ruby-gem-release.yml` - **Workflow Repository Owner**: `shared-org` - **Workflow Repository Name**: `shared-workflows` Leave the Workflow Repository fields blank if your workflow file is in the same repository as your gem. ## How it works Trusted publishing is a mechanism for uploading gems to RubyGems.org without using long-lived secret credentials. You don't need to be an OIDC expert to use trusted publishing, but it's helpful to understand the basics of how it works. 1. Certain platforms, such as GitHub Actions, are OIDC _identity providers_, meaning they can issue short-lived identity tokens that third parties can **strongly** verify came from the CI service (as well as the repository, workflow, and commit that triggered the build). 1. Gems on RubyGems.org can be configured to trust particular configurations from particular providers, making that configuration a trusted publisher for that gem. 1. Release automation (such as GitHub Actions) can exchange the identity token for a short-lived API token from RubyGems.org, provided the token matches any trusted publishers that have been configured on RubyGems.org. 1. The API token can be used only to push to the gems that are configured to trust the publisher, and only for a short period of time. This mechanism has significant security & usability advantages compared to traditional authentication mechanisms: - **Usability**: trusted publishing does not require manually creating & storing API tokens from RubyGems.org. The only manual step is configuring the trusted publisher on RubyGems.org. - **Security**: RubyGems.org's normal API tokens are long-lived, meaning an attacker who obtains one can use it indefinitely. Trusted publishing tokens are short-lived, meaning they can only be used for a short period of time. ## Further reading We highly recommend checking out the excellent docs written by our friends over at PyPI for some more in-depth information on how Trusted Publishing works: - [PyPI: Security model and considerations](https://docs.pypi.org/trusted-publishers/security-model/) --- # Setting up multi-factor authentication Source: https://guides.rubygems.org/setting-up-multifactor-authentication/ Want to better protect your RubyGems.org account? Your RubyGems.org account is important! Unauthorized access of your account can lead to irrevocable damage to your gem's reputation. We highly recommend that you enable MFA for both UI and API. When enabled, this will mean that you need to use MFA for signing into RubyGems.org and when running `gem signin`, `push`, `owner --add`, `owner --remove` and `yank`. You may enable MFA using [WebAuthn](#setting-up-webauthn-recommended) or by using [one-time passwords (OTP)](#setting-up-otp). Both are set up in the "Multi-factor Authentication" section of the [edit settings](https://rubygems.org/settings/edit) page, so sign in to your account and open that page before following either set of steps below. ## Setting up WebAuthn (recommended) Using WebAuthn for multi-factor authentication is the best way to protect your account from takeover. It's stronger and easier to use than OTP codes. You will need at least _one_ of the following: * A hardware security token (sometimes called a security key), such as a YubiKey or Google Titan Key. * A built-in hardware device, such as TouchID, FaceID or Windows Hello. * A browser that supports the "Passkey" standard. Up-to-date versions of Chrome, Safari, Firefox and Edge all support this standard. Unfortunately implementations of these experiences vary, so we can't show the exact details, but we will point out the steps that are specific to using RubyGems.org. 1. In the "Multi-factor Authentication" section you will see two options: "Authentication App" and "Security Device". Under "Security Device" you will see a field for "Nickname". ![Nickname for security device on the edit settings page](/images/enabling_webauthn_nickname.png){:class="t-img"} 2. Choose a name for your device. Use something that helps you remember which device you used. For example, you might use nicknames like "Mary's YubiKey" or "Naveen's iPhone". 3. Below the Nickname field, click **Register device**. 4. Your browser will prompt you to set up a device or a Passkey. This experience varies according to browser. Chrome tries to set up a Passkey that it manages, though you can select "Try another way" to use a USB hardware token. Safari asks you to enable iCloud Keychain, but you can click "Other Options" to use a hardware token. Other browsers may vary. 5. You will now see your security device on the screen above the Nickname field. ## Setting up OTP You should have an authenticator app (like [Google Authenticator](https://support.google.com/accounts/answer/1066447), [Authy](https://authy.com/download/), or [Authenticator Plus](https://www.authenticatorplus.com)) which supports time-based one-time password (TOTP) to scan the QR code and generate an access code. SMS-based authentication or recovery is **not** supported. The Google Authenticator app only allows an MFA account to be installed on one device and there is no backup or cloud sync of the data. So if you lose or upgrade your phone, you'll have to set up MFA again on the new phone. On the other hand, the Authy and Authenticator Plus apps allow you to use multiple devices by providing cloud backups and cross-device sync capabilities. 1. Click **register a new device** in the "Multi-factor Authentication" section. ![Multi-factor authentication section on the edit settings page](/images/enabling_mfa_step1.png){:class="t-img"} 2. You will be redirected to a page with a QR code and a text box for verifying OTP code. Please use your authenticator to scan the QR code. A new account for rubygems.org will be added to your authenticator app as soon as the scan completes. You can also add a new account manually using "Account" and "Key" shown next to the QR code. Please make sure you choose the option "time based" as MFA type. On successful registration, you will see a 6-digit access code (30 seconds expiry) in your authenticator app for your rubygems.org account. Enter the shown access code in the "OTP Code" text field and click **Enable**. 3. If the code is correct and the QR code has not expired, on next page you will see a list of recovery codes. Please copy and store these codes in a safe place, and see [Using recovery codes](#using-recovery-codes) for what they are for. 4. Sign out and sign in again. Signing in will now ask for an OTP code. ![OTP prompt at login page](/images/mfa_login.png){:class="t-img"} ## Authentication levels When you register a new device or enable MFA for the first time, we will enable MFA for both the UI and the API. If you go to the edit settings page again, in the "Multi-factor Authentication" section, you will see a dropdown menu with these options: - **UI and API (Recommended)**: UI operations, `gem signin`, `push`, `owner --add` and `owner --remove` will require OTP code. - **UI and gem signin**: UI operations and `gem signin` will require OTP code. **UI only** was previously a valid MFA level. However, it has been removed, and only accounts that are currently at that level will still see it in the dropdown. Note: If you are on the **UI and gem signin** authentication level, you can selectively enable MFA on specific API keys (see [API key scopes](/api-key-scopes/#enable-mfa-on-specific-api-keys)). This is different from the **UI and API** level as MFA is enabled on all API keys by default and cannot be selectively enabled. Steps to change your MFA level: 1. In the "Multi-factor Authentication" section, select your intended option from the dropdown menu, and click **Update**. ![Multi-factor section on the edit settings page](/images/changing_mfa_step1.png){:class="t-img"} 2. You will be asked to authorize the change on the same screen you see when signing in. Enter a code from your MFA device. ## Using recovery codes Recovery codes are shown once, when you enable MFA. They let you get back into your account when you no longer have access to your MFA device. Each recovery code can *only be used once* and you may need up to *2 recovery codes* to re-setup a previously enabled MFA RubyGems.org account on a new device. 1. To login into your account, enter an unused recovery code as the OTP code when prompted. 2. To reconfigure an [authenticator app](https://rubygems.org/settings/edit#authenticator-app), you'll need to use a recovery code to remove the current authenticator app. Then, you are able to enable and configure your authenticator app again. For security devices, you are able to associate a new security device to your account in the [security devices section](https://rubygems.org/settings/edit#security-device). ## Requiring MFA for your gems You can make your gems more secure by requiring all owners to enable MFA on their account. Opt in a gem you are managing by releasing a version that has `metadata.rubygems_mfa_required` set to `true`. % cat hola.gemspec Gem::Specification.new do |s| ... s.metadata = { "rubygems_mfa_required" => "true" } ... end The version being released with `rubygems_mfa_required` set and all the following versions will require you to have MFA enabled. Once enabled, the gem page will show `NEW VERSIONS REQUIRE MFA` in the sidebar, and all versions published with `rubygems_mfa_required` set will also show `VERSION PUBLISHED WITH MFA`: ![MFA status indicators](/images/mfa-required-since.png){:class="t-img t-img--small"} You will see the following error message if you have not enabled MFA and you are trying to release a new version for a gem that requires MFA: $ gem push hola-1.0.0.gem Pushing gem to https://rubygems.org... Rubygem requires owners to enable MFA. You must enable MFA before pushing new version. ### Disabling the requirement You can disable the MFA requirement by setting `rubygems_mfa_required` to `"false"` or any [`ActiveRecord::Type::Boolean::FALSE_VALUES`](https://api.rubyonrails.org/classes/ActiveModel/Type/Boolean.html). **Note:** We will enforce the MFA requirement on the version being published. MFA requirement will be disabled after you have successfully published a gem with rubygems_mfa_required set to false. ## Using MFA from the command line Once MFA is enabled, `gem` commands such as `signin`, `push` and `yank` will prompt you for it. See [Using multi-factor authentication in command line](/using-mfa-in-command-line) for how each authentication method behaves. --- # Using multi-factor authentication in command line Source: https://guides.rubygems.org/using-mfa-in-command-line/ How to use multi-factor authentication with gem CLI. Multi-factor authentication (MFA) greatly increases the security of your account. RubyGems currently requires that owners of any gem with more than 180 million cumulative downloads must enable MFA. You can use MFA with the gem CLI via [WebAuthn](#using-webauthn) or [one-time passwords (OTP)](#using-otp). * [Using WebAuthn](#using-webauthn) * [Using OTP](#using-otp) Using WebAuthn -------------- Multi-factor authentication (MFA) using WebAuthn works by using a removable hardware token or touch biometric / facial biometric capabilities built into your phone or computer. This is distinct from MFA based on typing or copying a code generated by an authentication app or password manager, called OTP. For OTP MFA see "[Using OTP](#using-otp)" below. When you have enabled WebAuthn MFA, we will ask you to perform authentication on certain commands based on your [authentication level](/setting-up-multifactor-authentication/#authentication-levels). Enter your RubyGems.org credentials. Don't have an account yet? Create one at https://rubygems.org/sign_up Email: gem_author@example Password: [snip of API key setup] You have enabled multi-factor authentication. Please visit http://localhost:3000/webauthn_verification/?port= to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin command with the `--otp [your_code]` option. Depending on your terminal program, you may be able to click, command-click or control-click on the link to open it in your default browser. Otherwise you will need to copy and paste the link into a new tab. A webpage titled "Authenticate with Security Device" appears. Click "Authenticate". Your browser will show a popup asking you to use a Passkey or other authentication device (the exact popup will vary according to the browser). Once you have authenticated using your WebAuthn device, you will see a "Success" page. At this point you can close your browser tab and return to the command line, which will say: You are verified with a security device. You may close the browser window. Signed in with API key: Using OTP --------- Multi-factor authentication (MFA) using OTP works by using an authenticator app on your phone to generate a one-time password (OTP) that you then enter at the command line. For WebAuthn instructions, see "[Using WebAuthn](#using-webauthn)" above. When you have only enabled OTP MFA, and your MFA level is _UI and API_, we will ask you to provide an OTP for `gem signin`, `gem push`, `gem owner --add` and `gem owner --remove`. Check [setting up multi-factor authentication](/setting-up-multifactor-authentication) for enabling MFA. This level requires a recent enough `gem` command as shipped with Ruby 2.6+, or [RubyGems 3.0+](https://rubygems.org/pages/download). You can preemptively pass an OTP code using `--otp` flag or else we will prompt for the OTP code when required: $ gem signin Enter your RubyGems.org credentials. Don't have an account yet? Create one at https://rubygems.org/sign_up Email: gem_author@example Password: You have enabled multi-factor authentication. Please enter OTP code. Code: 111111 Signed in. Passing OTP as flag: $ gem signin --otp 111111 Enter your RubyGems.org credentials. Don't have an account yet? Create one at https://rubygems.org/sign_up Email: gem_author@example Password: Signed in. Note that `gem signin` only fetches and stores your rubygems.org api key. `gem signin` is not equivalent to creating a user session. We will check for OTP code every time you use any of the commands mentioned above. Publishing a gem after signing in from CLI: $ gem push hello-0.0.1.gem Pushing gem to https://rubygems.org... You have enabled multi-factor authentication. Please enter OTP code. Code: 111111 Successfully registered gem: hello (0.0.1) --- # Managing Owners via UI Source: https://guides.rubygems.org/managing-owners-using-ui/ How to add or remove owners to your gem using the web UI? Similar to `gem owner --add` and `gem owner --remove` commands of the gem CLI, you can add or remove the owners of the gem you own using the web UI. Ownership section of your gem ----------------------------- If you are an owner of a gem, a link to *Ownership* will be visible in the Links section, as shown in the image below. ![Rubygem page](/images/managing-owners-using-ui/rubygem-page.png){:class="t-img t-img--small"} You will be asked to enter your account's password when you visit this page. You won't be prompted for the password confirmation for the next 10 minutes. It is a precautionary measure to ensure that no one abuses your unattended logged in session. ![Confirm Password](/images/managing-owners-using-ui/confirm-password.png){:class="t-img"} You will be able to see the confirmation status, MFA level and the user who authorized the owner's addition. Confirmed owners will have the time they confirmed their ownership. *ADDED BY* column may be empty for owners who were added before we started tracking authorizers. ![Owners Index](/images/managing-owners-using-ui/owners-index.png){:class="t-img"} Adding user as an owner to your gem -------------------------------- Step: 1 Enter the email or handle of the user in the text field labels *Email/Handle* Select the role that best suits the user, see [Owner & Maintainer Roles](#owner--maintainer-roles) for more details. Finally, click *Add Owner*. Step: 2 The user added as an owner will be sent an email with a link to confirm the ownership. The ownership will be confirmed after the user clicks on the confirmation link within `48 hours`. On confirmation, all the existing owners will be notified about the owner addition. `Note that` the user won't have access to the gem until they confirm the ownership addition. Owner & Maintainer Roles ------------------------ When managing owners, you have the option to select a role, either Owner or Maintainer. Owners have full control over the gem, including the ability to add or remove owners. Maintainers, have the ability to publish and yank gem versions, but cannot manage users, or configure gem security settings. Owners & Maintainers have access to the following permissions: | Permission | Owner | Maintainer | |:--------------------------------------:|:-----:|:----------:| | Can publish new gem versions | ✅ | ✅ | | Can yank gem versions | ✅ | ✅ | | Can add or remove owners | ✅ | ❌ | | Configure OIDC and Trusted Publishing | ✅ | ❌ | Updating an owner role ---------------------- To update the role of an owner, visit `https://rubygems.org/gems//owners` and click on the *Edit* button of the corresponding user. You can select the role of the user edit page and click on *Update Owner*. Resend ownership confirmation link ---------------------------------- In case you weren't able to confirm the ownership within 48 hours, you can resend the confirmation link by visiting the gem page. `https://rubygems.org/gems/` ![Resend confirmation](/images/managing-owners-using-ui/rubygem-resend-confirmation.png){:class="t-img t-img--small"} Clicking on *Resend Confirmation* will send an email with the confirmation link to your email address. Removing owner from your gem ---------------------------- To remove an owner from your gem, visit `https://rubygems.org/gems//owners` and click on the *Remove Owner* button of the corresponding user. A notification email will be sent to the removed user. --- # Organizations Source: https://guides.rubygems.org/organizations/
⚠️ Private Beta: Organizations are currently in limited private beta testing. If you're interested in joining the beta program, please contact support@rubygems.org.
Organizations help teams and businesses collaborate, share gem ownership, manage permissions, and work together under a unified identity. ## What are Organizations? Organizations provide a shared space for multiple users to collectively manage RubyGems. Instead of individual ownership, gems belong to the organization, making it easier to: - **Maintain continuity** when team members change - **Control access** with role-based permissions - **Collaborate effectively** on gem development - **Establish identity** for your company or project ## Getting Started Ready to create your organization? Follow our [Getting Started Guide](/organizations/getting-started) to set up your first organization in minutes. ### Quick Links - [Create an Organization](/organizations/getting-started) - [Understanding Roles](/organizations/roles-and-permissions) - [Managing Members](/organizations/managing-members) - [Transferring Gems](/organizations/transferring-gems) ## Need Help? - Contact [support@rubygems.org](mailto:support@rubygems.org) for assistance - Report issues on [GitHub](https://github.com/rubygems/rubygems.org/issues) --- # Getting Started with Organizations Source: https://guides.rubygems.org/organizations/getting-started/
⚠️ Private Beta: Organizations are currently in limited private beta testing. If you're interested in joining the beta program, please contact support@rubygems.org.
Create your first Organization and start collaborating on RubyGems.org in minutes. ## Before You Begin To create an organization, you'll need: - A RubyGems.org account with **multi-factor authentication (MFA)** enabled - At least one gem where you're listed as an owner ## Creating Your Organization Navigate to your [dashboard](https://rubygems.org/dashboard) and click **Create Organization**. ### Step 1: Set Organization Details Provide your Organization's information: - **Handle**: Your unique identifier (selected from a list of gems the current user is listed as an owner of) - **Display Name**: How your Organization appears publicly (2-255 characters) The handle becomes part of your organization URL: `rubygems.org/organizations/your-handle` ### Step 2: Select Gems to Transfer If you own multiple gems, choose which ones to transfer to the Organization: - Only gems where you're an owner appear in the list - Gems already belonging to other organizations are excluded - You can transfer additional gems later **Important:** Once transferred, gems belong to the Organization. Individual ownership is replaced by organization membership. ### Step 3: Invite Team Members Add your collaborators to the Organization: **Automatic Suggestions:** We'll suggest users who co-own your selected gems. This makes it easy to maintain existing collaborations. **Assign Roles:** Choose the appropriate role for each member: - **Owner**: Full organization control - **Admin**: Gem and member management - **Maintainer**: Basic access and gem operations - **Outside Collaborator**: Limited access, retains personal ownership of gems and is not a member of the orgnization ### Step 4: Confirm and Create Review your organization setup: - Organization name and handle - Selected gems for transfer - Invited members and their roles Click **Create Organization** to finalize your Organization. You'll see: - Your Organization is created - Selected gems are transferred - Members receive an email to join your Organization. - You're redirected to your organization page ## After Creation ### Immediate Next Steps 1. **Wait for Invitations**: Members must accept their invitations to join the Organization 2. **Configure Settings**: Visit organization settings to customize further 3. **Transfer More Gems**: Add additional gems as needed ### Managing Your Organization Access your Organization at `rubygems.org/organizations/your-handle` to: - View organization gems - Manage members - Update settings - Monitor activity ### API and Automation Currently, onboarding an Organization must be done through the web interface. API support may be added in future. ## Troubleshooting ### Can't Create Organization? - Verify MFA is enabled on your account - Ensure you own at least one gem (for gem-based organizations) - Check that your desired handle isn't already taken ### Invitation Issues? - Invitations expire after a set period - Members must have RubyGems.org accounts - Check spam folders for invitation emails ### Need More Help? - Review our [Roles and Permissions](/organizations/roles-and-permissions) guide - Learn about [Managing Members](/organizations/managing-members) - Contact [support@rubygems.org](mailto:support@rubygems.org) for assistance --- Ready to collaborate? [Create your Organization](https://rubygems.org/organizations/new) now. --- # Managing Organization Members Source: https://guides.rubygems.org/organizations/managing-members/
⚠️ Private Beta: Organizations are currently in limited private beta testing. If you're interested in joining the beta program, please contact support@rubygems.org.
This guide covers inviting new members, managing existing ones, and handling common membership scenarios. ## Viewing Members Access your member list from your organization page: 1. Navigate to `rubygems.org/organizations/your-handle` 2. Click **Members** in the navigation 3. View all current members with their roles and join dates The member list shows: - Member username - Current role (Owner, Admin, or Maintainer) ## Inviting New Members ### Who Can Invite? - **Owners** can invite members at any level - **Admins** can invite new Admins and Maintainers - **Maintainers** cannot send invitations ### Sending Invitations 1. Click **Invite** from the members page 2. Enter the invitee's username 3. Select their role 5. Click **Invite** ### Invitation Process **What happens next:** - Invitee receives an email with a link to join the Organization - MFA must be enabled before joining - Invitation expires after 7 days - You'll see pending invitations in your member list **Tracking invitations:** - Pending invitations appear with a "Pending" status - See when invitations were sent - Resend or cancel pending invitations ## Managing Existing Members ### Changing Roles Adjust member permissions as responsibilities evolve: 1. Find the member in your list 3. Select the new role from the dropdown 4. Confirm the change **Important considerations:** - Only Owners can change Owner roles - Admins cannot modify Owner permissions - Changes take effect immediately ### Removing Members When team members leave or no longer need access: 1. Locate the member to remove 2. Click **Delete** 3. Confirm the removal **Removal rules:** - Owners can remove anyone except themselves - Admins can remove Maintainers and other Admins - Members cannot remove themselves - Removed members lose all organization access immediately ### API and Automation Currently, managing Organization Members must be done through the web interface. API support may be added in future. ## Troubleshooting ### Invitation Not Received - Check spam/junk folders - Resend invitation if needed - Confirm recipient has email access ### Cannot Change Roles - Verify you have appropriate permissions - Owners cannot be modified by Admins - Contact an Owner for help ### Member Cannot Access Gems - Confirm MFA is enabled - Verify membership is active (not pending) - Check organization gem list - Review member's role permissions ### Accidental Removal - Removed members must be re-invited - Previous role not automatically restored - Act quickly to minimize disruption ## Getting Help - Review our [Roles and Permissions](/organizations/roles-and-permissions) guide - Contact [support@rubygems.org](mailto:support@rubygems.org) for complex issues --- Keep your team organized and secure with proper member management. --- # Organization Roles and Permissions Source: https://guides.rubygems.org/organizations/roles-and-permissions/
⚠️ Private Beta: Organizations are currently in limited private beta testing. If you're interested in joining the beta program, please contact support@rubygems.org.
Organizations use role-based access control to ensure team members have appropriate permissions. Understanding these roles helps you build an effective collaboration structure. ## Available Roles ### Owner The highest level of access. Owners have complete control over the organization. **Best for:** Organization founders, CTOs, or team leads who need full control. ### Admin Administrators handle day-to-day organization management. **Best for:** Senior developers, team managers, or trusted contributors who manage gems and team members. ### Maintainer The base level of organization membership with essential access. **Best for:** Developers who need to work with organization gems but don't require administrative privileges. ## Permission Comparison | Action | Owner | Admin | Maintainer | |--------|--------|--------|--------| | View organization info | ✓ | ✓ | ✓ | | Push gem versions | ✓ | ✓ | ✓ | | Yank gem versions | ✓ | ✓ | ✓ | | View member list | ✓ | ✓ | ✓ | | Invite members | ✓ | ✓ | ✗ | | Remove members | ✓ | ✓¹ | ✗ | | Change member roles | ✓ | ✓¹ | ✗ | | Add gems | ✓ | ✓ | ✗ | | Remove gems | ✓ | ✗ | ✗ | | Update organization | ✓ | ✗ | ✗ | | Delete organization | ✓ | ✗ | ✗ | ¹ *Admins cannot modify or remove Owners* ## Next Steps - Learn about [Managing Organization Members](/organizations/managing-members) - Understand [Transferring Gems](/organizations/transferring-gems) to organizations --- Questions about roles? Contact [support@rubygems.org](mailto:support@rubygems.org) for assistance. --- # Transferring Gems to Organizations Source: https://guides.rubygems.org/organizations/transferring-gems/
⚠️ Private Beta: Organizations are currently in limited private beta testing. If you're interested in joining the beta program, please contact support@rubygems.org.
Move your gems from individual ownership to organization management for better collaboration and continuity. This guide covers the transfer process, requirements, and best practices. ## Before You Transfer ### Requirements To transfer a gem, you need: - **Owner permissions** on the gem - **Admin or Owner role** in the target organization - **MFA enabled** on your account ### Important Considerations **Ownership changes are significant:** - Individual owners lose direct gem access - Organization members manage the gem based on roles - The organization name appears as the gem owner - Transfer cannot be reserved once completed **Plan your transfer:** - Notify co-owners before transferring - Document the transfer for your team - Update gem documentation with new ownership ## The Transfer Process Transferring a rubygem to an organization works very similarly to creating a new organization. Follow these steps: Navigate to the rubygems you want to transfer and click the **Transfer to Organization** link. ### Step 1: Select destination Organization Select the organization you want to transfer your gem from the dropdown menu. ### Step 2: Invite Team Members Add your collaborators to the Organization: **Automatic Suggestions:** We'll suggest users who co-own your selected gems. This makes it easy to maintain existing collaborations. **Existing Members:** If the user is already a member of the organization, they will show as already being a member. **Assign Roles:** Choose the appropriate role for each member: - **Owner**: Full organization control - **Admin**: Gem and member management - **Maintainer**: Basic access and gem operations - **Outside Collaborator**: Limited access, retains personal ownership of gems and is not a member of the orgnization ### Step 4: Confirm and Create Review your organization setup: - Organization name and handle - Selected gems for transfer - Invited members and their roles Click **Transfer** to finalize the migration. You'll see: - Your gem has been transferred to the selected organization. - New members receive an email to join your Organization. - You're redirected to your organization page ## Need Help? - See [Managing Members](/organizations/managing-members) guide - Contact [support@rubygems.org](mailto:support@rubygems.org) for assistance --- Transfer gems confidently to enable better collaboration. --- # Removing a published gem Source: https://guides.rubygems.org/removing-a-published-gem/ Published a gem before it was ready for release? Published a gem with the wrong name? Here's how you can fix it. You can use the gem yank command to remove versions from RubyGems.org's index using the command: ```ruby gem yank GEM -v VERSION ``` Running gem yank will remove your gem from being available with gem install and the other gem commands. This also removes the gem file, as of April 20, 2015. Note: Our webhook and mirror system means that several hundred services get pinged when new gems are pushed, so it's prudent to immediately reset any passwords/sensitive data you accidentally pushed even if you yank a gem right away. --- # Security Source: https://guides.rubygems.org/security/ How to protect your account as a gem author, harden the gems you install, and report vulnerabilities. Installing a gem runs someone else's code on your machine, with your privileges. RubyGems and Bundler provide several layers of defense against compromised accounts and malicious releases. This page is an index to those layers. * [Securing your account](#securing-your-account) * [Securing your dependencies](#securing-your-dependencies) * [Gem signing](#gem-signing) * [Reporting security vulnerabilities](#reporting-security-vulnerabilities) Securing your account --------------------- If you publish gems, your RubyGems.org account is part of your users' supply chain. Protecting it protects everyone who installs your gems. Enable multi-factor authentication. It is the most effective defense against account takeover. Prefer [WebAuthn](/setting-up-multifactor-authentication#setting-up-webauthn-recommended) with a security key or passkey, which resists the phishing attacks behind recent account takeovers in other packaging ecosystems. See [Setting up multi-factor authentication](/setting-up-multifactor-authentication) to enable it and [Using MFA in the command line](/using-mfa-in-command-line) for how it affects `gem` commands. You can also [require MFA from all owners of your gems](/setting-up-multifactor-authentication#requiring-mfa-for-your-gems). Limit what your API keys can do. Instead of one all-powerful key, create keys scoped to the specific actions they need, such as a push-only key for a release pipeline, and set an expiration date so a forgotten key cannot be abused indefinitely. See [API key scopes](/api-key-scopes). Publish from CI without long-lived credentials. [Trusted Publishing](/trusted-publishing) lets a configured CI workflow push your gem using short-lived tokens, so there is no API key to leak or rotate. Only add people you trust as owners of your gems. Every owner has the same permissions you have, including pushing new versions, yanking existing ones, and adding or removing other owners. See [Managing gem owners](/managing-owners-using-ui), or use [Organizations](/organizations) for finer-grained roles. Keep credentials out of the gems you publish. A pushed gem is public and widely mirrored, so a leaked API key or password cannot be recalled by yanking the version. Build the `files` list in your gemspec from an explicit allowlist such as `git ls-files` instead of a broad glob that can pick up local configuration, and review the packaged files with `gem unpack` before pushing. If a secret does ship, revoke it first, then yank the version. If you suspect your account has been compromised or a malicious version of your gem has been published, [yank the affected versions](/removing-a-published-gem) immediately and report the incident to . Securing your dependencies -------------------------- Bundler records the exact version of every dependency in `Gemfile.lock`, so later installs from the same lockfile use the same code that you tested. The protections below build on it. ### Lockfile checksums Bundler records a `CHECKSUMS` section in newly generated lockfiles and verifies each gem against its checksum during installation. A gem that has been tampered with after the lockfile was created fails to install. Existing lockfiles are not rewritten automatically. Add checksums to one with: bundle lock --add-checksums ### Cooldown Most malicious releases are detected and yanked within days of publication. A cooldown excludes gem versions newer than a given number of days from dependency resolution, so your application never installs a release before the ecosystem has had time to vet it. Enable it for a project with: bundle config set cooldown 7 You can also pass `--cooldown N` to `bundle install`, `bundle update`, `bundle add`, and `bundle outdated`, or set a per-source value in the Gemfile with `source "https://rubygems.org", cooldown: 7`. The CLI flag takes precedence over the config setting, which takes precedence over the per-source value. To exempt a trusted internal source, declare it with `cooldown: 0`. Cooldown relies on the gem server publishing a creation time for each version through the v2 compact index. Versions from servers that do not provide it are treated as outside the cooldown window. See [How to delay new gem versions with cooldown](/cooldown) for details. ### Pinning gem sources If you install gems from more than one source, such as an internal gem server alongside rubygems.org, a public gem published under the same name as an internal one could be substituted for it. Assign every internal gem to its server with a `source` block, so Bundler installs it only from there. A source declared in a block still remains a candidate for gems without an explicit source, so give every gem in the Gemfile an explicit source. See the [Gemfile manual](/gemfile) for the block form of `source`. ### Auditing for known vulnerabilities [bundler-audit](https://github.com/rubysec/bundler-audit) checks your `Gemfile.lock` against [ruby-advisory-db](https://github.com/rubysec/ruby-advisory-db), the community database of known vulnerabilities in Ruby gems. Run it in CI so newly disclosed advisories surface quickly. Vulnerabilities in RubyGems itself are listed on the [CVE page](/cve). Gem signing ----------- RubyGems can cryptographically sign gems. Authors create a certificate with `gem cert`, and users opt into verification with a trust policy, using `gem install -P MediumSecurity` or `bundle install --trust-policy MediumSecurity`. In practice signing is rarely used because there is no established chain of trust for signing certificates, and each certificate must be trusted manually. Prefer the protections above. If you still want to sign your gems, see the [Gem::Security documentation](https://docs.ruby-lang.org/en/master/Gem/Security.html). Reporting security vulnerabilities ---------------------------------- ### In RubyGems, Bundler, or RubyGems.org Report vulnerabilities in RubyGems, Bundler, or the RubyGems.org service, as well as malicious gems published on RubyGems.org, to or through [HackerOne](https://hackerone.com/rubygems). Do not open a public issue. ### In Ruby itself Vulnerabilities in the Ruby language belong to a separate program. Report them to the Ruby security team through [HackerOne](https://hackerone.com/ruby) or . See the [Ruby security page](https://www.ruby-lang.org/en/security/) for the scope of that program. ### In someone else's gem First check whether the vulnerability is already known by searching [RubySec](https://rubysec.com). If it appears to be new, contact the authors privately rather than through a public issue or pull request. Explain the issue, how it can be exploited, and ideally how it might be fixed. If the gem is developed on GitHub, the repository may accept [private vulnerability reports](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability). ### In your own gem Request a CVE identifier by creating a [GitHub Security Advisory](https://docs.github.com/en/code-security/security-advisories/working-with-repository-security-advisories/about-repository-security-advisories), then release a patched version and tell your users which versions are affected and what to do. Announce the fix on and submit the advisory to [ruby-advisory-db](https://github.com/rubysec/ruby-advisory-db) so that audit tools pick it up. --- # How to delay new gem versions with cooldown Source: https://guides.rubygems.org/cooldown/ How to keep Bundler from resolving to gem versions published in the last few days. Most malicious gem releases are detected and yanked within days of publication. A cooldown excludes gem versions newer than a given number of days from dependency resolution, so your application never installs a release before the ecosystem has had time to vet it. Enabling cooldown ----------------- To enable a cooldown for every Bundler run in a project, set the number of days in Bundler's configuration: bundle config set cooldown 7 The setting can also come from the `BUNDLE_COOLDOWN` environment variable. For a single run, pass `--cooldown N` to `bundle install`, `bundle update`, or `bundle add`. Passing `--cooldown 0` disables cooldown for that run. `bundle outdated` also accepts `--cooldown N`. Instead of hiding versions still inside the window, it annotates them, appending "in cooldown for Nd more days" in the prose output and "(cooldown Nd)" in the Latest column of the table form. Per-source cooldown ------------------- A cooldown can also be declared for an individual source in the Gemfile: source "https://rubygems.org", cooldown: 7 The effective cooldown for any given gem is resolved from three layers. The CLI flag takes precedence over the config setting, which takes precedence over the per-source value. The CLI flag and the config setting apply uniformly to every source, including sources declared with their own `cooldown:` value. To keep a trusted private gem server permanently exempt while still cooling down public gems, declare it with `cooldown: 0` in the Gemfile. Note that `--cooldown N` on the command line still overrides that exemption for the run. Trade-offs ---------- A cooldown delays every new version, including releases that fix security vulnerabilities. When you need an urgent fix before the window has elapsed, bypass the cooldown for that run with `bundle update --cooldown 0`, combined with `--conservative` to minimize changes to other gems. Server support -------------- Cooldown filtering depends on the gem server providing a per-version `created_at` timestamp in the v2 compact-index format. Versions without that metadata are treated as outside the cooldown window and remain resolvable. That includes older gem servers, private registries that still emit the v1 format, and historical entries that predate the v2 cutover on rubygems.org. If you rely on cooldown for supply-chain protection, confirm that your gem server emits `created_at` in its `/info/` responses. For the full description of the setting, see the `cooldown` entry in [bundle config](/command-reference/bundle-config/). --- # How to use Bundler with Rails Source: https://guides.rubygems.org/rails/ Rails comes with baked-in support for Bundler. ## How to use Bundler with Rails Install Rails as you normally would. Use sudo if you would normally use sudo to install gems. ~~~ $ gem install rails ~~~ We recommend using rvm for dependable Ruby installations, especially if you are switching between different versions of Ruby Generate a Rails app as usual ~~~ $ rails new myapp $ cd myapp ~~~ Run the server. Bundler is transparently managing your dependencies! ~~~ $ rails server ~~~ Add new dependencies to your Gemfile as you need them. ~~~ruby gem 'nokogiri' gem 'geokit' ~~~ If you want a dependency to be loaded only in a certain Rails environment, place it in a group named after that Rails environment ~~~ruby group :test do gem 'rspec' gem 'faker' end ~~~ You can place a dependency in multiple groups at once as well ~~~ruby group :development, :test do gem 'wirble' gem 'ruby-debug' end ~~~ Learn More: Groups After adding a dependency, if it is not yet installed, install it ~~~ $ bundle install ~~~ This will update all dependencies in your Gemfile to the latest versions that do not conflict with other dependencies --- # How to use Bundler with Sinatra Source: https://guides.rubygems.org/sinatra/ To use bundler with a Sinatra application, you only need to do two things. First, create a Gemfile. ~~~ruby gem 'sinatra' ~~~ Then, set up your config.ru file to load the bundle before it loads your Sinatra app. ~~~ruby require 'bundler' Bundler.require require './my_sinatra_app' run MySinatraApp ~~~ Start your development server with rackup, and Sinatra will be loaded via Bundler. ~~~ $ bundle exec rackup ~~~ --- # How to use Bundler with Docker Source: https://guides.rubygems.org/bundler_docker_guide/ ## Introduction The official Docker images for Ruby assume that you will use only one application, with one Gemfile, and no other gems or Ruby applications will be installed or run in your container. If you want to install more than one Gemfile in your container, or simply install gems via RubyGems and use them as system gems, this situation is confusing, and has historically led to many confusing errors that appear to be bugs in Bundler. However, these errors ultimately come from the way the Dockerfile tells Bundler to create [binstubs](/command-reference/bundle-binstubs/) (which are linked to one application and Gemfile) in a single global place for the entire container. If you install two Gemfiles with `rake`, for example, running the `rake` command will always load the last Gemfile that was installed, and never any others. ## Dockerfiles for multiple Ruby applications and gems To build a Docker container that can run more than one Ruby application or global commands installed with `gem install`, you will need to change some environment variables from the defaults set in the official Docker image for Ruby. In your Dockerfile, change the `PATH` and `GEM_HOME` so that Bundler will install all gems to the same location, and running commands will use the RubyGems binstubs instead of Bundler's application-locked binstubs: ENV GEM_HOME="/usr/local/bundle" ENV PATH $GEM_HOME/bin:$GEM_HOME/gems/bin:$PATH You will also need to unset `BUNDLE_PATH` and `BUNDLE_BIN`. Unsetting environment variables can be somewhat tricky in Docker, but the most common way is at the beginning of your `ENTRYPOINT` script: #!/bin/bash unset BUNDLE_PATH unset BUNDLE_BIN # your script goes here Once you've done that, you'll be able to run commands without a bundle by calling them directly, like `rake`. You'll be able to run commands in a specific bundle by `cd`ing to that bundle's directory and then using `bundle exec`. For example, to run rake inside your application bundle, you would use `bundle exec rake`. --- # How to use Bundler in CI Source: https://guides.rubygems.org/ci/ How to install gems quickly and reproducibly on GitHub Actions, GitLab CI, and other CI systems. A CI job needs the same gems as your development machine, installed from scratch on every run. The recipe is the same everywhere. Cache installed gems, keyed on the `Gemfile.lock` when the repository has one, and configure Bundler through `BUNDLE_*` environment variables instead of running `bundle config` in each job. GitHub Actions -------------- Use the [ruby/setup-ruby](https://github.com/ruby/setup-ruby) action. With `bundler-cache: true` it runs `bundle install` for you and caches the installed gems, so you do not need a separate `gem install bundler` or `bundle install` step. When a `Gemfile.lock` is present, it installs in deployment mode, so the job fails if the lockfile is out of date instead of silently resolving new versions. jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - uses: ruby/setup-ruby@v1 with: bundler-cache: true - run: bundle exec rake The `ruby-version` input can be omitted if the repository has a `.ruby-version`, `.tool-versions`, or `mise.toml` file. To test against several Ruby versions, use a matrix: jobs: test: strategy: matrix: ruby: ["3.3", "3.4", "4.0"] runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true - run: bundle exec rake To test against multiple Gemfiles, set `BUNDLE_GEMFILE` in a job-level `env` block (for example from a matrix value) so that both `setup-ruby` and later steps use the same Gemfile. GitLab CI --------- On GitLab, install gems into the project directory and cache that path, keyed on `Gemfile.lock` so the cache is invalidated when dependencies change: test: image: ruby:4.0 cache: key: files: - Gemfile.lock paths: - vendor/ruby script: - bundle config set --local path 'vendor/ruby' - bundle install - bundle exec rake Setting `BUNDLE_PATH: vendor/ruby` and `BUNDLE_FROZEN: "true"` in the `variables` block is an equivalent alternative to the `bundle config` line, and keeps the configuration visible in one place. Dependency bots and cooldown ---------------------------- If CI runs against pull requests opened by a dependency bot, align the bot's update delay with the [cooldown](/cooldown) configured in Bundler. Otherwise the bot proposes versions that `bundle install` refuses to resolve, or bypasses the waiting period that cooldown is meant to enforce. On GitHub, Dependabot supports a `cooldown` block for version updates in `dependabot.yml`: version: 2 updates: - package-ecosystem: "bundler" directory: "/" schedule: interval: "weekly" cooldown: default-days: 7 The `cooldown` block also accepts `semver-major-days`, `semver-minor-days`, and `semver-patch-days` to set different delays per update type, and `include` and `exclude` lists to scope which dependencies it applies to. Renovate, which runs on both GitHub and GitLab, offers the same control through `minimumReleaseAge`, a duration string such as `"7 days"`. Set it in `renovate.json`, either at the top level or scoped to Bundler: { "packageRules": [ { "matchManagers": ["bundler"], "minimumReleaseAge": "7 days" } ] } In both cases, use the same number of days as your Bundler cooldown. See [the cooldown guide](/cooldown) for how the Bundler side works. Publishing from CI ------------------ To release gems from a CI pipeline without long-lived API keys, see [Trusted Publishing](/trusted-publishing). --- # Run your own gem server Source: https://guides.rubygems.org/run-your-own-gem-server/ Need to serve gems locally or for your organization? There are times you would like to run your own gem server. You may want to share gems with colleagues when you are both without internet connectivity. You may have private code, internal to your organization, that you'd like to distribute and manage as gems without making the source publicly available. There are a few options to set up a server to host gems from within your organization. This guide covers the [Gemstash](https://github.com/rubygems/gemstash) and [Gem in a Box](https://github.com/geminabox/geminabox) projects. It also discusses how to use these servers as gem sources during development. If you would rather not run a server at all, you can [serve gems from an S3 bucket](/using-s3-source) instead. ## Running Gemstash Gemstash is both a cache for remote servers (such as ), and a private gem source. To get started, install `gemstash`: $ gem install gemstash After it is installed, start the Gemstash server with the following command: $ gemstash start By default, the server runs on port 9292. If you want to use it as a cache, you can tell Bundler to use Gemstash to find gems from RubyGems.org: $ bundle config set mirror.https://rubygems.org http://localhost:9292 With this configuration, all gems fetched from RubyGems.org via bundler are cached by Gemstash. You can also push your own gems and use the gemstash server as a private gem source. For more information about gemstash features and commands, read the [Gemstash](https://github.com/rubygems/gemstash) documentation. ## Running Gem in a Box For a standalone private gem server with a web interface, try out the [Gem in a Box](https://github.com/geminabox/geminabox) project. Gem in a Box is a Rack application, so it needs a web server to run. To get started, install `geminabox` along with a server: $ gem install geminabox puma rackup Make a data directory for storing gems: $ mkdir data Include the following in a `config.ru` file: require "geminabox" Geminabox.data = "./data" run Geminabox::Server And run the server: $ rackup Puma starting in single mode... * Listening on http://127.0.0.1:9292 Now you can push gems using the `gem inabox` command. The first time you do this, you'll be prompted for the location of your gem server. $ gem build secretgem.gemspec Successfully built RubyGem Name: secretgem Version: 0.0.1 File: secretgem-0.0.1.gem $ gem inabox ./secretgem-0.0.1.gem Enter the root url for your personal geminabox instance (e.g. http://gems/). Host: http://localhost:9292 Pushing secretgem-0.0.1.gem to http://localhost:9292/... Gem secretgem-0.0.1.gem received and indexed. There is a web interface available on [http://localhost:9292](http://localhost:9292) as well. For more information, read the [Gem in a Box](https://github.com/geminabox/geminabox) README. ## Using gems from your server Whether you use Gemstash, Gem in a Box, or another gem server, you can configure RubyGems to use your local or internal source alongside other sources such as [https://rubygems.org](https://rubygems.org). Use the `gem sources` command to add the gem server to your system-wide gem sources: $ gem sources --add http://localhost:9292 Then install gems as usual: $ gem install secretgem Successfully installed secretgem-0.0.1 1 gem installed If you're using [Bundler](/getting_started) then you can add the server to your `Gemfile`. Use a source block so that only your private gems are looked up there: source "https://rubygems.org" source "http://localhost:9292" do gem "secretgem" end If your server requires a username and password, configure the credentials with `bundle config` instead of writing them into the `Gemfile`. See [credentials for gem sources](/command-reference/bundle-config/#CREDENTIALS-FOR-GEM-SOURCES) for details. --- # Using S3 as gem source Source: https://guides.rubygems.org/using-s3-source/ How to use S3 bucket as gem source. [Gem server solutions](/run-your-own-gem-server) with their wide feature set, come in very handy for usecases like private hosting, mirroring and inter-release builds. With s3 bucket as your gem source, you get convenience of a private gem server, without the hassle of running or maintaining a host. In this guide, we cover steps required for setting up a private gem source using a s3 bucket and configuration for its use with the `gem` command. > Please check [s3 documentation](https://docs.aws.amazon.com/s3/index.html) if you would like to learn about creating a s3 buckets and their pricing. Make sure you are running on ruby gems version that supports s3 signing. You can update your ruby gems with the following command: $ gem update --system ## Setting up repo For a static gem source, you will need 4 additional files beside the `.gem` file: - `specs..gz` - `latest_specs..gz` - `prerelease_specs..gz` - `quick/Marshal./.gemspec.rz` You can generate all of them using one command: `gem generate_index`. $ mkdir ~/repo && cd ~/repo # .gem must exist in a directory named `gems` $ mkdir gems && wget -P gems/ https://rubygems.org/downloads/rake-12.3.2.gem $ gem generate_index --directory . # replace bucket1 with name of the bucket you created $ aws s3 sync . s3://bucket1 ## Use with gem command > It's good practice to create a separate IAM user with only read rights on the S3 bucket. Use a other IAM user for pushing the gems with write rights. You can use your s3 source using `--source` flag: $ gem install rake -v 12.3.2 --source s3://:@bucket1 Use `.gemrc` if you would like to pre configure multiple s3 sources. It also helps avoid issues related to special characters in the secret key and allows you to specify s3 bucket region. Add your s3 source under `:sources` key. Each s3 bucket should have its own set of credentials in a hash under `s3_source` key. You can use one of the providers to extract AWS credentials: - `env` - [AWS environment variables](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html) - `instance_profile` - [AWS EC2 Instance Metadata](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) - will only work on the actual EC2 instance Or set AWS access id, secret and session token explicitly. > Note that you need to add `/` to your s3 source uri, if your gem repo doesn't exist at the root of the bucket. NOTE: The trailing slash. $ cat ~/.gemrc :sources: - s3://bucket1/ - s3://bucket2/ - s3://bucket3/path_to_gems_dir/ - s3://bucket4/ - https://rubygems.org/ :s3_source: :bucket1: :provider: env :bucket2: :provider: instance_profile :region: us-west-2 :bucket3: :id: AOUEAOEU123123AOEUAO :secret: aodnuhtdao/saeuhto+19283oaehu/asoeu+123h :region: us-east-2 :bucket4: :id: AOUEAOEU123123AOEUAO :secret: aodnuhtdao/saeuhto+19283oaehu/asoeu+123h :security_token: AQoDYXdzEJr :region: us-west-1 #### Read more: [Setting up Travis for inter-release builds](https://simonwo.net/code/gem-server-in-s3/) --- # Plugins Source: https://guides.rubygems.org/plugins/ Extensions that use the RubyGems plugin API. RubyGems will load plugins in the latest version of each installed gem or `$LOAD_PATH`. Plugins must be named 'rubygems\_plugin' (.rb, .so, etc) and placed at the root of your gem's #require\_path. Plugins are installed at a special location and loaded on boot. Make your own plugin -------------------- The first step is to follow the conventional file name, we will use ruby for this example and check that our plugin is loaded correctly: % cat lib/rubygems_plugin.rb puts 'hello from my plugin!' % RUBYOPT=-Ilib gem hello from my plugin! RubyGems is a sophisticated package manager for Ruby. This is a basic help message containing pointers to more information. Usage: […] Of course, our plugin would better be packaged as a gem, which is described in detail in the [make your own gem][make-your-own-gem] guide. ### Hooks RubyGems provides various hooks we can use to add custom features and even modify how RubyGems behaves. For example, existing hooks allow executing code before a single gem is installed, after it's built, after it's installed, after all gem are installed and many others (see code and documentation for `Gem` as a reference). Let's consider a simple example plugin that would ask confirmation interactively before installing gems while supporting a whitelist. We will leverage the `pre_install` hook, passing a block to `Gem.pre_install` method. Reading this method documentation, we learn that our hook will be called with a `Gem::Installer` instance, and that we can return `false` to abort the installation: % cat lib/rubygems_plugin.rb WHITELIST_PATH = "#{ENV['HOME']}/.gem/install_audit/whitelist" Gem.pre_install do |installer| gem_name = installer.spec.name whitelist = if File.exist? WHITELIST_PATH File.read(WHITELIST_PATH).split else [] end unless whitelist.include? gem_name print "`#{gem_name}' is not whitelisted, install? (y/n): " case choice = $stdin.gets.chomp when /\Ay/i when /\An/i then next false else fail "cannot understand `#{choice}'" end end end % echo rake > ~/.gem/install_audit/whitelist % RUBYOPT=-Ilib gem install hoe Fetching: rake-12.3.0.gem (100%) Successfully installed rake-12.3.0 Fetching: hoe-3.16.2.gem (100%) `hoe' is not whitelisted, install? (y/n): y Successfully installed hoe-3.16.2 2 gems installed % RUBYOPT=-Ilib gem install pry Fetching: coderay-1.1.2.gem (100%) `coderay' is not whitelisted, install? (y/n): n ERROR: Error installing pry: pre-install hook at /…/lib/rubygems_plugin.rb:3 failed for coderay-1.1.2 As expected, RubyGems calls our hook before each gem installation, and when our hook returns false, it aborts with an explanation. If you find that the plugin system API lacks the extension point you need for your needs, please read `CONTRIBUTING.rdoc` in RubyGems source code, or see the [contributing][contributing] guide. ### Commands Some plugins also add their own commands to the RubyGems CLI. As an example, the `graph` plugin listed below registers its own `graph` command this way: require 'rubygems/command_manager' Gem::CommandManager.instance.register_command :graph And implement the command similarly to this: require 'rubygems/command' class Gem::Commands::GraphCommand < Gem::Command def initialize super 'graph', 'Graph dependency relationships of installed gems' end def execute # [real command implementation removed for this guide] end end We can then use it by executing `gem graph`, and it is also documented like other RubyGems builtin commands (`gem help commands`, `gem help graph`…). Existing plugins ---------------- The following list of RubyGems plugins is probably not exhaustive. If you know of plugins that we missed, feel free to update this page. * [executable-hooks](#executable-hooks) * [gem-browse](#gem-browse) * [gem-ctags](#gem-ctags) * [gem-empty](#gem-empty) * [gem_info](#gem_info) * [gem-init](#gem-init) * [gem-compare](#gem-compare) * [gem-man](#gem-man) * [gem-nice-install](#gem-nice-install) * [gem-orphan](#gem-orphan) * [gem-patch](#gem-patch) * [gem-toolbox](#gem-toolbox) * [gem-wrappers](#gem-wrappers) * [graph](#graph) * [maven_gem](#maven_gem) * [manpages](#manpages) * [open_gem](#open_gem) * [push_safety](#push_safety) * [rbenv-gem-rehash](#rbenv-gem-rehash) * [rubygems-desc](#rubygems-desc) * [rubygems-openpgp](#rubygems-openpgp) * [rubygems-sandbox](#rubygems-sandbox) * [rubygems_snapshot](#rubygems_snapshot) * [specific_install](#specific_install) * [rubygems-tasks](#rubygems-tasks) * [rubygems_plugin_generator](#rubygems_plugin_generator) ### executable-hooks [https://github.com/mpapis/executable-hooks](https://github.com/mpapis/executable-hooks) Extends rubygems to support executables plugins. In gem lib dir create rubygems_executable_plugin.rb: Gem.execute do |original_file| warn("Executing: #{original_file}") end ### gem-browse [https://github.com/tpope/gem-browse](https://github.com/tpope/gem-browse) Adds four commands: - `gem edit` opens a gem in your editor - `gem open` opens a gem by name in your editor - `gem clone` clones a gem from GitHub - `gem browse` opens a gem's homepage in your browser ### gem-empty [https://github.com/rvm/gem-empty](https://github.com/rvm/gem-empty) Adds command `gem empty` to remove all gems from current `GEM_HOME`. ### gem-ctags [https://github.com/tpope/gem-ctags](https://github.com/tpope/gem-ctags) Adds a `gem ctags` command to invoke the Exuberant Ctags indexer on already-installed gems, and then automatically invokes it on gems as they are installed. ### gem_info [https://github.com/oggy/gem_info](https://github.com/oggy/gem_info) Adds a `gem info` command with fuzzy matching on name and version. Designed for scripting use. ### gem-init [https://github.com/mwhuss/gem-init](https://github.com/mwhuss/gem-init) Adds `gem init` to create a barebones gem. ### gem-compare [https://github.com/fedora-ruby/gem-compare](https://github.com/fedora-ruby/gem-compare) Adds `gem compare` command that can help you to track upstream changes in the released .gem files by comparing gemspec values, gemspec and Gemfile dependencies and files. ### gem-man [https://github.com/defunkt/gem-man](https://github.com/defunkt/gem-man) The `gem man` command lets you view a gem's man page. ### gem-nice-install [https://github.com/voxik/gem-nice-install](https://github.com/voxik/gem-nice-install) Tries to install system dependencies needed to install your gems with binary extensions using standard `gem install` command. This currently works only for Fedora, but hopefully will be extended. ### gem-orphan [https://github.com/sakuro/gem-orphan](https://github.com/sakuro/gem-orphan) Adds a `gem orphan` command that finds and lists gems on which no other gems are depending. ### gem-patch [https://github.com/strzibny/gem-patch](https://github.com/strzibny/gem-patch) Adds `gem patch` command, which enables you to apply patches directly on `.gem` files. Supports both RubyGems 1.8 and RubyGems 2.0. ### gem-toolbox [https://github.com/gudleik/gem-toolbox](https://github.com/gudleik/gem-toolbox) Adds six commands: - `gem open` - opens a gem in your default editor - `gem cd` - changes your working directory to the gem's source root - `gem readme` - locates and displays a gem's readme file - `gem history` - locates and display's a gem's changelog - `gem doc` - Browse a gem's documentation in your default browser - `gem visit` - Open a gem's homepage in your default browser ### gem-wrappers [https://github.com/rvm/gem-wrappers](https://github.com/rvm/gem-wrappers) Create gem wrappers for easy use of gems in cron and other system locations. By default wrappers are installed when a gem is installed. Adds this commands: - `gem wrappers regenerate` - force rebuilding wrappers for all gem executables - `gem wrappers` - show current configuration ### graph [https://github.com/seattlerb/graph](https://github.com/seattlerb/graph) Adds a `gem graph` command to output a gem dependency graph in graphviz's dot format. ### maven_gem [https://github.com/jruby/maven_gem](https://github.com/jruby/maven_gem) Adds `gem maven` to install any Maven-published Java library as though it were a gem. ### manpages [https://github.com/bitboxer/manpages](https://github.com/bitboxer/manpages) Exposes manpages inside of a gem to the `man` command without the need to call `gem man` or another command to read the man page of a gem. ### open_gem [https://github.com/adamsanderson/open_gem](https://github.com/adamsanderson/open_gem) Adds two commands: - `gem open` opens a gem in your default editor - `gem read` opens a gem's rdoc in your default browser ### push_safety [https://github.com/jdleesmiller/push_safety](https://github.com/jdleesmiller/push_safety) Applies a whitelist to `gem push` to prevent accidentally pushing private gems to the public RubyGems repository. ### rbenv-gem-rehash [https://github.com/sstephenson/rbenv-gem-rehash](https://github.com/sstephenson/rbenv-gem-rehash) Automatically runs `rbenv rehash` after installing or uninstalling gems. > This plugin is deprecated since its behavior is now included in > rbenv core. ### rubygems-desc [https://github.com/chad/rubygems-desc](https://github.com/chad/rubygems-desc) Adds `gem desc` to describe a gem by name. ### rubygems-openpgp [https://github.com/grant-olson/rubygems-openpgp](https://github.com/grant-olson/rubygems-openpgp) Adds commands and flags to allow OpenPGP signing of gems. - `gem sign foo.gem` to sign a gem. - `gem verify foo.gem --trust` to verify a gem. - `gem build foo.gemspec --sign` to sign at build time. - `gem install foo --verify --trust` to verify on install. ### rubygems-sandbox [https://github.com/seattlerb/rubygems-sandbox](https://github.com/seattlerb/rubygems-sandbox) Manages command-line gem tools and dependencies with a `gem sandbox` command. This lets you install things like flay and rdoc outside of the global rubygems repository. ### rubygems_snapshot [https://github.com/rogerleite/rubygems_snapshot](https://github.com/rogerleite/rubygems_snapshot) Adds `gem snapshot` to create exports of all your current gems into a single file that you can import later. ### specific_install [https://github.com/rdp/specific_install](https://github.com/rdp/specific_install#readme) Allows you to install an "edge" gem straight from its GitHub repository, or install one from an arbitrary web URI. ### rubygems-tasks [https://github.com/postmodern/rubygems-tasks](https://github.com/postmodern/rubygems-tasks#readme) rubygems-tasks provides agnostic and unobtrusive Rake tasks for building, installing and releasing Ruby Gems. ### rubygems_plugin_generator [https://github.com/brianstorti/rubygems_plugin_generator](https://github.com/brianstorti/rubygems_plugin_generator) `rubygems_plugin_generator` is a plugin that generates plugins. Just run `gem plugin ` and you are good to go. [contributing]: /contributing [make-your-own-gem]: /make-your-own-gem --- # How to write a Bundler plugin Source: https://guides.rubygems.org/bundler_plugins/ Extend Bundler with new commands, gem sources, and lifecycle hooks. A Bundler plugin is a regular gem with one extra file, `plugins.rb`, at its root. Through that file the gem can register three kinds of extensions: - Commands, so that `bundle my_command` runs your code - Gem sources, so that a Gemfile can install gems from somewhere other than a gem server, git, or a local path - Lifecycle hooks, so that your code runs at events such as before or after `bundle install` Installing and using plugins ---------------------------- Plugins install from a gem server by default, or from a git repository or local path: bundle plugin install my_plugin bundle plugin install my_plugin --git https://github.com/example/my_plugin bundle plugin install my_plugin --path /path/to/my_plugin Once installed, the plugin's commands are available and its hooks are registered. `bundle plugin list` shows installed plugins and their commands, and `bundle plugin uninstall my_plugin` removes one. A Gemfile can also declare plugins, and `bundle install` will install them: plugin "my_plugin" plugin "my_plugin", git: "https://github.com/example/my_plugin.git" plugin "my_plugin", path: "/path/to/my_plugin" A plugin is a regular gem ------------------------- Start by [creating a gem](/make-your-own-gem) as usual. That guide builds a command-line executable with Thor, but a plugin needs none of that. No executable, no CLI framework. Bundler talks to your plugin through `plugins.rb` instead. `plugins.rb` lives at the top level of the gem, next to the gemspec, and is the entry point Bundler loads. Usually it just requires your gem's main file: require "my_plugin" Make sure the gemspec ships this file. If `spec.files` is a hand-maintained list rather than `git ls-files`, add `plugins.rb` to it. When the plugin is installed, Bundler runs `plugins.rb` once and records every command, source, and hook it registers into a plugin index. After that, Bundler loads the plugin again only when one of those registrations is used. Registration must therefore happen at load time, in code that runs when `plugins.rb` is required. Adding a command ---------------- A command class needs two things: it registers itself for a command name, and it defines an instance method `exec`. The smallest working command plugin looks like this, with the class reached from `plugins.rb`: require "bundler/plugin/api" module MyPlugin class Hello < Bundler::Plugin::API command "hello" def exec(command, args) puts "Hello! You passed #{args.inspect}" end end end When a user runs `bundle hello world --loud`, Bundler instantiates the registered class with no arguments and calls `exec("hello", ["world", "--loud"])`. The second argument is the raw list of remaining command-line arguments. Parse it however you like, for example with `OptionParser` as [bundler-graph](https://github.com/rubygems/bundler-graph) does. Bundler routes only on the first word after `bundle`. Subcommands such as `bundle hello status` are yours to implement by dispatching on `args[0]`. If you prefer not to inherit from `Bundler::Plugin::API`, register a plain class explicitly. It must still be a class with a public `exec` instance method, because Bundler calls `.new` on whatever you register: require "bundler/plugin/api" module MyPlugin class Hello Bundler::Plugin::API.command("hello", self) def exec(command, args) puts "Hello! You passed #{args.inspect}" end end end ### Raising errors When something goes wrong, raise `Bundler::BundlerError` (or a subclass). Bundler rescues it and prints the message concisely. Any other exception makes Bundler print its bug report template asking users to file an issue against Bundler itself. The details are in [friendly_errors.rb](https://github.com/ruby/rubygems/blob/master/lib/bundler/friendly_errors.rb). raise Bundler::BundlerError, "my_command requires an argument" if args.empty? ### Commands and Thor If your gem already has a Thor CLI, do not register the Thor class itself as the command. Thor classes define no `exec` instance method, so Bundler's call lands on the private `Kernel#exec` and the command crashes with `NoMethodError: private method 'exec' called`. Keep the Bundler command in its own small class and delegate to Thor from there: module MyPlugin class BundlerCommand < Bundler::Plugin::API command "my_command" def exec(command, args) MyPlugin::CLI.start(args) end end end `MyPlugin::CLI.start(args)` here is the same entry point the gem's own executable would use. Delegating to Thor also gives you subcommands: [bundler-sbom](https://github.com/hsbt/bundler-sbom) registers the single command `sbom` and delegates to a Thor class with `dump` and `license` tasks, which is what makes `bundle sbom dump` work. Thor receives `["dump", ...]` and dispatches as usual. ### Plugin commands vs. executables on PATH There is a second, older way to add a `bundle` subcommand that has nothing to do with plugins. When `bundle foo` matches neither a built-in command nor an installed plugin command, Bundler searches PATH for an executable named `bundler-foo` and runs it. [bundler-audit](https://github.com/rubysec/bundler-audit) works this way: installing the gem puts a `bundler-audit` executable on PATH, which makes `bundle audit` work. It is not a Bundler plugin and does not use the plugin API. The two mechanisms differ in how they are installed and where they run. A PATH executable comes from a gem installed with `gem install` or a Gemfile, runs in its own process, and does not appear in `bundle plugin list`. A plugin command is installed with `bundle plugin install`, runs inside the Bundler process with access to Bundler's API, and is listed by `bundle plugin list`. If both exist for the same name, the plugin command wins. For a new project, prefer the plugin API. Adding command registration to a gem that already ships a `bundler-`prefixed executable changes nothing for its users except the installation method. Running code at lifecycle events -------------------------------- Hooks run your code when Bundler reaches specific events. Register a hook with the event name and a block. The block arguments depend on the event: require "bundler/plugin/api" Bundler::Plugin::API.hook("before-install-all") do |dependencies| puts "About to install #{dependencies.map(&:name).join(", ")}" end The full list of events, with their descriptions and block arguments, is in [events.rb](https://github.com/ruby/rubygems/blob/master/lib/bundler/plugin/events.rb). Check the copy in the Bundler version you target, since events have been added over time. A hook registered for an event the running Bundler does not define raises an error at plugin install time. For real-world examples, [bundler-multilock](https://github.com/instructure/bundler-multilock) uses an `after-install-all` hook, and [bundler-timing-plugin](https://github.com/hsbt/bundler-timing-plugin) times fetches and installs by registering several hooks in `plugins.rb` that share one tracker object. Adding a gem source ------------------- A source plugin lets a Gemfile install gems from a place Bundler does not support natively, such as Amazon S3. Subclass `Bundler::Plugin::API::Source` and override at least `fetch_gemspec_files` and `install`. The required and overridable methods are documented in [api/source.rb](https://github.com/ruby/rubygems/blob/master/lib/bundler/plugin/api/source.rb). Bundler's own sources implement the same interface, so their code is a useful reference: the [rubygems source](https://github.com/ruby/rubygems/blob/master/lib/bundler/source/rubygems.rb), the [git source](https://github.com/ruby/rubygems/blob/master/lib/bundler/source/git.rb), and the [path source](https://github.com/ruby/rubygems/blob/master/lib/bundler/source/path.rb). Developing your plugin locally ------------------------------ Install your work-in-progress plugin straight from its source directory: bundle plugin install my_plugin --path /path/to/my_plugin Run this inside a project with a Gemfile and the plugin installs into the project's `.bundle/plugin` directory, keeping the experiment local. Run it outside any project and the plugin installs globally for your user. A path-installed plugin runs directly from the source directory, so edits to your code take effect on the next `bundle` invocation. The exception is `plugins.rb` registrations, which Bundler caches in its index at install time. After adding or renaming a command, source, or hook, reinstall: bundle plugin uninstall my_plugin bundle plugin install my_plugin --path /path/to/my_plugin Releasing your plugin --------------------- A plugin is released like any other gem. [Publish it to RubyGems.org](/publishing) so others can install it with `bundle plugin install`. Example plugins --------------- - [bundler-graph](https://github.com/rubygems/bundler-graph) adds a command. It is maintained by the rubygems organization and is a good reference for the command API. - [bundler-sbom](https://github.com/hsbt/bundler-sbom) delegates its command to a Thor CLI with subcommands. - [bundler-multilock](https://github.com/instructure/bundler-multilock) uses a lifecycle hook. - [bundler-timing-plugin](https://github.com/hsbt/bundler-timing-plugin) registers multiple hooks that share state. - Bundler's built-in [rubygems](https://github.com/ruby/rubygems/blob/master/lib/bundler/source/rubygems.rb), [git](https://github.com/ruby/rubygems/blob/master/lib/bundler/source/git.rb), and [path](https://github.com/ruby/rubygems/blob/master/lib/bundler/source/path.rb) sources implement the source interface. More are listed in the [known plugins list](/bundler_known_plugins). --- # Troubleshooting common issues Source: https://guides.rubygems.org/troubleshooting/ What to do when a gem fails to build, dependencies will not resolve, or you are not sure what is broken. Native extension build failures ------------------------------- Some gems compile C code during installation. When that compilation fails, `gem install` and `bundle install` stop with an error like "Failed to build gem native extension". The error output includes the path to a `mkmf.log` file. Read it first. It records every check the build ran and shows which compiler or header was missing. The most common cause is a missing compiler toolchain. Install it with your system's package manager: # macOS xcode-select --install # Debian, Ubuntu apt-get install build-essential # Fedora dnf install gcc make # Alpine apk add build-base If you use the Ruby packaged by your distribution, also install its header package, such as `ruby-dev` on Debian, Ubuntu, and Alpine, or `ruby-devel` on Fedora. Skip this if you installed Ruby with a version manager such as ruby-build. Those rubies ship their own headers, and installing the distribution package would add a second Ruby to the system. The next most common cause is a missing library header. A gem that wraps a system library needs that library's development package, not just the runtime package. For example, the `pg` gem needs the libpq development package, such as `libpq-dev` on Debian and Ubuntu. If the library is installed in a location the build cannot find, pass build flags to the gem installer after a `--` separator: gem install pg -- --with-pg-config=/path/to/pg_config To make Bundler pass the same flags every time it installs a particular gem, store them in its configuration: bundle config set --global build.mysql --with-mysql-config=/usr/local/mysql/bin/mysql_config Many popular gems ship [precompiled platform gems](/platforms), so on common platforms no compilation happens at all. If you hit a build failure, check whether a newer version of the gem provides a precompiled binary for your platform. If you are a gem author who wants to ship extensions, see [Gems with Extensions](/gems-with-extensions). Dependency resolution conflicts ------------------------------- When no set of gem versions satisfies every requirement in your Gemfile and lockfile, Bundler fails with an error reporting that it could not find compatible versions. The error lists the conflicting requirement chains. Each chain shows which gem in your Gemfile pulled in which dependency, with the version constraint it declared. Follow the chains to find the two constraints that cannot both hold. Work through fixes in this order: 1. Update just the gem you were changing with `bundle update `. This keeps the rest of the lockfile untouched. 2. If that updates more than you want, add `--conservative` so indirect dependencies stay at their locked versions. 3. If the conflict remains, loosen the version constraint in your Gemfile for one of the gems named in the error, then run `bundle update ` again. 4. Run `bundle outdated` to see which gems have newer versions available and how far behind your lockfile is. If your project uses a [cooldown](/cooldown), recently published versions are excluded from resolution until the window elapses, which can cause a conflict even though a compatible version exists. Pass `--cooldown 0` to bypass it for a single run. bundle doctor ------------- When you are not sure what is wrong, run `bundle doctor`. It checks your Gemfile and gem environment for common problems, including invalid Bundler settings, mismatched Ruby versions, mismatched platforms, uninstalled gems, and missing dependencies. If it finds issues, it prints them and exits with status 1. For connection problems with https://rubygems.org, run `bundle doctor ssl`. It verifies your Ruby OpenSSL setup and CA certificates, then opens a test TLS connection. The `--host`, `--tls-version`, and `--verify-mode` options narrow the diagnosis. For certificate errors and how to fix them, see the [TLS/SSL troubleshooting guide](/rubygems_tls_ssl_troubleshooting_guide). See [bundle doctor](/command-reference/bundle-doctor/) for all options. --- # How to troubleshoot RubyGems and Bundler TLS/SSL Issues Source: https://guides.rubygems.org/rubygems_tls_ssl_troubleshooting_guide/ What `certificate verify failed` means and how to fix it. What the error means -------------------- When RubyGems or Bundler connects to https://rubygems.org, it verifies the server's TLS certificate against the CA certificate bundle on your machine. When that verification fails, `gem` and `bundle` commands stop with an error like: OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed Two causes account for almost all of these errors: 1. **Missing or outdated CA certificates.** Ruby uses the CA bundle provided by your operating system or your Ruby installation. If that bundle is too old to contain the root certificate that RubyGems.org's certificate chains to, verification fails. 2. **A wrong system clock.** Certificates are only valid within a time window. If your system clock is set in the past or future, an otherwise valid certificate appears expired or not yet valid. Diagnosing the problem ---------------------- Run `bundle doctor ssl`. It verifies the Ruby OpenSSL version on your system, checks that CA certificates are set up correctly, then opens a test TLS connection to https://rubygems.org and reports the outcome. Use `--host` to diagnose a different gem server, and `--tls-version` and `--verify-mode` to narrow down which protocol version or verification mode fails. See [Troubleshooting common issues](/troubleshooting) for general diagnosis and [bundle doctor](/command-reference/bundle-doctor/) for all options. Fixing the problem ------------------ Work through these steps in order: 1. **Update RubyGems and Bundler.** Recent versions ship a current CA bundle for RubyGems.org, so updating fixes most certificate errors. See [Installing RubyGems and Bundler](/installation) for `gem update --system` and `bundle update --bundler`. 2. **Check your system clock.** If it is off by more than a few minutes, correct it and enable automatic time synchronization. 3. **Update your OS CA certificates.** Install pending OS updates or update the CA certificate package with your system's package manager. If none of these steps fixes the problem, open an issue in the [RubyGems issue tracker](https://github.com/rubygems/rubygems/issues) and include the output of `bundle doctor ssl`, `gem env`, and `bundle env`. --- # How to use git bisect with Bundler Source: https://guides.rubygems.org/git_bisect/ ## How to use git bisect [`git bisect`](https://git-scm.com/docs/git-bisect) is a useful debugging tool. For context, `git bisect` is a git command that can be used to track down the specific commit which a bug was introduced into the codebase. If you can find a commit where the code works properly and a commit with the offending bug, you don’t have to trace down the buggy commit by hand. The `git bisect` command, via binary search, will help you find the offending commit. For example, the Git documentation has [a handy `git bisect` guide](https://git-scm.com/book/en/v2/Git-Tools-Debugging-with-Git) that shows two ways to use it. ## How to git bisect in projects using Bundler A few things that may not be obvious are needed for `git bisect` to work in a project that uses Bundler. 1. The `Gemfile.lock` needs to be in the git repo, so that each commit will load the same dependencies every time. 1. Each step during the bisect needs to run `bundle install` first, so that the correct dependencies are installed and available to be loaded. 1. After determining if the commit is good or bad, each step needs to `git reset`. If `bundle install` or running the test can cause changes on the file system, which would prevent `git checkout` of the next commit to test if they are not reset. Here's a minimal example script that runs the rake task `spec`: ~~~ bash #!/usr/bin/env bash bundle install bin/rake spec status=$? git reset --hard HEAD exit $status ~~~ See also the discussion at [rubygems/bundler#3726](https://github.com/rubygems/bundler/issues/3726). --- # What is a gem? Source: https://guides.rubygems.org/what-is-a-gem/ Unpack the mystery behind what's in a RubyGem. Structure of a Gem ------------------ Each gem has a name, version, and platform. For example, the [rake](https://rubygems.org/gems/rake) gem has a `13.0.6` version (from Jul 2021). Rake's platform is `ruby`, which means it works on any platform Ruby runs on. Platforms are based on the CPU architecture, operating system type and sometimes the operating system version. Examples include "x86-mingw32" or "java". The platform indicates the gem only works with a ruby built for the same platform. RubyGems will automatically download the correct version for your platform. See `gem help platform` for full details. Inside gems are the following components: * Code (including tests and supporting utilities) * Documentation * gemspec Each gem follows the same standard structure of code organization: % tree freewill freewill/ ├── bin/ │ └── freewill ├── lib/ │ └── freewill.rb ├── test/ │ └── test_freewill.rb ├── README ├── Rakefile └── freewill.gemspec Here, you can see the major components of a gem: * The `lib` directory contains the code for the gem * The `test` or `spec` directory contains tests, depending on which test framework the developer uses * A gem usually has a `Rakefile`, which the [rake](https://rubygems.org/gems/rake) program uses to automate tests, generate code, and perform other tasks. * This gem also includes an executable file in the `bin` directory, which will be loaded into the user's `PATH` when the gem is installed. * Documentation is usually included in the `README` and inline with the code. When you install a gem, documentation is generated automatically for you. Most gems include [RDoc](https://ruby.github.io/rdoc/) documentation, but some use [YARD](https://yardoc.org/) docs instead. * The final piece is the gemspec, which contains information about the gem. The gem's files, test information, platform, version number and more are all laid out here along with the author's email and name. [More information on the gemspec file](/specification-reference/) [Building your own gem](/make-your-own-gem/) The Gemspec ----------- The gemspec specifies the information about a gem such as its name, version, description, authors and homepage. Here's an example of a gemspec file. You can learn more in [how to make a gem](/make-your-own-gem/). % cat freewill.gemspec Gem::Specification.new do |s| s.name = 'freewill' s.version = '1.0.0' s.summary = "Freewill!" s.description = "I will choose Freewill!" s.authors = ["Nick Quaranto"] s.email = 'nick@quaran.to' s.homepage = 'http://example.com/freewill' s.files = ["lib/freewill.rb", ...] end For more information on the gemspec, please check out the full [Specification Reference](/specification-reference/) which goes over each metadata field in detail. Credits ------- This guide was adapted from [Gonçalo Silva](https://twitter.com/goncalossilva)'s original tutorial on docs.rubygems.org and from Gem Sawyer, Modern Day Ruby Warrior. --- # Gemfile and gemspec Source: https://guides.rubygems.org/gemfile-and-gemspec/ Which file your dependencies belong in, and why Ruby projects have two of them. Ruby projects declare dependencies in two different files, a `.gemspec` and a `Gemfile`. Newcomers often ask which one to use. The answer depends on what you are building. A gemspec describes a gem. A Gemfile describes an application's environment. Two files, two jobs ------------------- A gemspec is the manifest of a gem. It declares the gem's name, version, summary, files, and the other gems it needs, and it is packaged into the `.gem` file that `gem build` produces. When someone installs your gem, RubyGems reads the gemspec to decide what else to install. Every gem has one. The [Specification Reference](/specification-reference) covers all of its fields. A Gemfile is the input to [Bundler](/getting_started). It declares the set of gems an application uses, and `bundle install` resolves that set into an exact snapshot recorded in `Gemfile.lock`. The Gemfile exists so the same versions can be reproduced on every machine that runs the application. See [How to manage dependencies with Bundler](/dependency_management) and the [Gemfile Reference](/gemfile). Declaring dependencies ---------------------- A gemspec declares dependencies with `add_dependency` for gems needed at runtime and `add_development_dependency` for gems needed only to work on the gem itself: ~~~ruby Gem::Specification.new do |s| # ... s.add_dependency "activesupport", ">= 7.0" s.add_development_dependency "rspec", ">= 3.0" end ~~~ A Gemfile declares dependencies with the `gem` method: ~~~ruby source "https://rubygems.org" gem "rails", "8.1.3.1" gem "nokogiri", "~> 1.19" ~~~ The version constraints look alike but pull in opposite directions. A gem's constraints should stay wide, because your gem must coexist with every other gem an application installs alongside it, and strict constraints cause resolution conflicts for your users. See [Optimistic vs. pessimistic constraints](/versioning#optimistic-vs-pessimistic-constraints). An application can afford loose constraints in its Gemfile, because exactness comes from `Gemfile.lock` rather than from the requirements themselves. Using both while developing a gem --------------------------------- While developing a gem you still want Bundler to set up a working environment, so a gem's repository usually contains both files. The convention is to declare runtime dependencies in the gemspec, pull them into the bundle with the `gemspec` method, and declare development dependencies directly in the Gemfile: ~~~ruby source "https://rubygems.org" gemspec gem "rspec", "~> 3.13" gem "rubocop" ~~~ The `gemspec` method treats the gemspec's runtime dependencies as Gemfile entries in the default group, puts any `add_development_dependency` entries in the `:development` group, and adds the gem itself as a `path` dependency so your tests can require it. Declaring development dependencies only in the gemspec works fine on its own, but once both files are in play, prefer the Gemfile for them. A gemspec can only name a gem and a version requirement, while the Gemfile lets you adjust each dependency to the needs of the library you are developing, with groups, git or path sources, and platform conditions. This is the layout `bundle gem` generates. See [Bundler in gems](/rubygems) for the `gemspec` method's options and [Make your own gem](/make-your-own-gem) for the full workflow. Building a library vs. building an application ---------------------------------------------- The deeper difference is who resolves the versions. An application is the end of the dependency chain, so it locks: `Gemfile.lock` is committed and every deployment installs exactly those versions. A library is a link in someone else's chain, so it cannot lock. When an application depends on your gem, Bundler ignores any `Gemfile` and `Gemfile.lock` shipped inside it and resolves your gemspec's runtime dependencies together with everything else in the application's Gemfile. Your gem will run with whatever versions that resolution picks, which is why wide constraints and testing against a range of versions matter for libraries. Whether to commit the lockfile of a gem's own repository is a separate tradeoff, discussed in the [FAQs](/faqs#using-gemfiles-inside-gems). Which file gets what -------------------- | What you are declaring | Where it goes | |------------------------|---------------| | The gem's name, version, and metadata | gemspec | | Gems your gem needs at runtime | gemspec, `add_dependency` | | Gems needed only to develop your gem | gemspec, `add_development_dependency`, or the Gemfile when you use both files | | Gems your application uses | Gemfile | | Exact versions for reproducible installs | `Gemfile.lock`, written by Bundler | --- # Where gems are installed and how they load Source: https://guides.rubygems.org/gem-installation-and-loading/ How RubyGems decides where a gem lives on disk, and what happens when you require it. `gem install` copies files into a directory on your machine, and `require` finds them there later. Knowing where that directory is and how the lookup works explains most surprises with missing commands, wrong versions, and load errors. Where gems are installed ------------------------ `gem env` prints the directories RubyGems is using. Three entries matter most: $ gem env RubyGems Environment: - RUBYGEMS VERSION: 4.0.16 ... - INSTALLATION DIRECTORY: /Users/you/.local/share/mise/installs/ruby/4.0.5/lib/ruby/gems/4.0.0 - USER INSTALLATION DIRECTORY: /Users/you/.gem/ruby/4.0.0 ... - EXECUTABLE DIRECTORY: /Users/you/.local/share/mise/installs/ruby/4.0.5/bin ... - GEM PATHS: - /Users/you/.local/share/mise/installs/ruby/4.0.5/lib/ruby/gems/4.0.0 - /Users/you/.gem/ruby/4.0.0 The installation directory, often called the gem home, is where `gem install` puts gems. Inside it, each gem version gets its own directory under `gems/`, such as `gems/rake-13.4.2/`, with metadata under `specifications/` and compiled extensions under `extensions/`. Because every version has its own directory, any number of versions of the same gem can be installed side by side. The gem home belongs to one Ruby installation. It normally lives inside the Ruby installation itself, and its path includes the Ruby ABI version, `4.0.0` above, because gems with compiled extensions only work with the Ruby they were built for. The `GEM_HOME` environment variable overrides where gems are installed, and `GEM_PATH` overrides the list of directories searched when loading them. You rarely need to set either by hand. In scripts, `gem env gemdir` and `gem env gempath` print the values directly. These and the other variables RubyGems reads are listed in [Environment variables](/environment-variables). Installing without root permission ---------------------------------- With a Ruby that came with the operating system, the installation directory sits somewhere like `/usr/lib` and is not writable by a normal user. RubyGems then falls back to a user install automatically: $ gem install rake Defaulting to user installation because default installation directory (/usr/lib/ruby/gems/4.0.0) is not writable. You can also request this explicitly with `gem install --user-install`. Either way the gem goes to the user installation directory shown by `gem env`, which is `~/.gem/ruby/` when a `~/.gem` directory already exists and `~/.local/share/gem/ruby/` otherwise. This directory is on `GEM_PATH` by default, so gems installed there load normally. Avoid `sudo gem install`. It scatters files owned by root through system directories, and a user install or a version manager achieves the same goal safely. Executables and PATH -------------------- Many gems ship commands, like `rake` or `rubocop`. On a plain install these go to the executable directory shown by `gem env`, which is the same `bin` directory that holds `ruby` itself, so they are on `PATH` whenever `ruby` is. After a user install, however, executables land in `bin` under the user installation directory, and that directory is not on `PATH`. This is why a gem can install successfully and still leave you with `command not found`. Add the directory to `PATH` in your shell configuration: export PATH="$(ruby -e 'puts Gem.user_dir')/bin:$PATH" Open a new terminal after the change, then the commands resolve. Version managers ---------------- Version managers such as rbenv, RVM, chruby, and mise install each Ruby under its own prefix in your home directory, and each of those Rubies brings its own gem home and executable directory. Switching Ruby versions therefore switches the whole set of installed gems, and nothing needs root permission. Gem homes are kept separate per Ruby version by default, so after installing a new Ruby you install your gems again for it. This is intentional. Compiled extensions built for one Ruby version do not load into another. The gem home does not always sit inside the Ruby prefix. chruby, for example, sets `GEM_HOME` to a directory under `~/.gem` that is still separate for each Ruby version, so installed gems survive reinstalling the Ruby itself. Some setups go further and point every Ruby at one shared `GEM_HOME`. Gems written in pure Ruby are then genuinely shared across versions. Gems with compiled extensions keep their builds under `extensions/` separated by platform and Ruby ABI, and a version whose extension is not built for the running Ruby is skipped as if it were not installed, until `gem install` on that Ruby builds it. Default gems ------------ Parts of Ruby's standard library are gems that ship inside Ruby itself, such as `json` and `psych`. Their specifications live in `specifications/default/` under the installation directory, and they can be required without installing anything. Unlike normal gems they cannot be uninstalled, though installing a newer version from RubyGems.org takes precedence over the shipped one. See [Default gems and bundled gems](/default-gems-and-bundled-gems). How require finds a gem ----------------------- Ruby loads RubyGems at startup, and RubyGems extends the built-in `require`. When you require a file that is not already on `$LOAD_PATH`, RubyGems searches the installed gems for one that contains it, picks the newest version, and activates it. Activation adds the gem's `lib` directory, and those of its dependencies, to `$LOAD_PATH`, and then the ordinary require proceeds: $ ruby -e 'require "rake"; puts $LOAD_PATH.grep(/rake/)' /Users/you/.local/share/mise/installs/ruby/4.0.5/lib/ruby/gems/4.0.0/gems/rake-13.4.2/lib Installed versions coexist on disk, but activation picks exactly one per gem for the life of the process. To load something other than the newest version, call `gem` before requiring: $ ruby -e 'gem "rake", "= 13.3.1"; require "rake"; puts Rake::VERSION' 13.3.1 Once a version is activated, activating a different one raises an error: $ ruby -e 'gem "rake", "= 13.3.1"; gem "rake", "= 13.4.2"' ... can't activate rake-13.4.2, already activated rake-13.3.1 (Gem::LoadError) This is the error behind version conflicts in plain Ruby scripts. When you are unsure which file a require resolves to, `gem which rake` prints the full path. When Bundler manages the process -------------------------------- `bundle install` puts gems into the same gem home that `gem install` uses, so all projects on the same Ruby share one pool of installed gems. To give a project its own isolated location instead, run `bundle config set --local path vendor/bundle`, after which gems install under `vendor/bundle/ruby/` inside the project. Loading also changes. `require "bundler/setup"` reads the `Gemfile` and `Gemfile.lock` and rebuilds `$LOAD_PATH` so that only the locked versions of the gems in the Gemfile are visible. Anything else in the gem home stays installed but cannot be required: $ ruby -rbundler/setup -e 'require "rspec"' ... cannot load such file -- rspec (LoadError) Here `rspec` is installed, but it is not in the Gemfile, so the process cannot see it. This is what makes Bundler-managed applications reproducible. The versions that load are the ones in the lockfile, not whatever happens to be newest on the machine. See [How to use Bundler with Ruby](/bundler_setup). --- # How dependency resolution works Source: https://guides.rubygems.org/dependency-resolution/ How Bundler picks one set of gem versions that satisfies your Gemfile and every gemspec at once. Before installing anything, `bundle install` has to decide which version of every gem to use. That decision is dependency resolution. Knowing what the resolver is trying to do makes version constraints, `Gemfile.lock`, and conflict errors much easier to reason about. The resolution problem ---------------------- Your Gemfile declares the gems your application uses directly. Each of those gems declares its own dependencies in its gemspec, those dependencies declare more, and so on. See [Gemfile and gemspec](/gemfile-and-gemspec) for how the two files relate. The result is a graph in which the same gem often appears several times with different version requirements. Resolving means choosing exactly one version of every gem in the graph so that all requirements hold at the same time. Simply taking the newest version of everything does not work. Suppose your Gemfile lists `payments` and `reporting`, the newest `payments` release requires `money >= 7.0`, and every version of `reporting` requires `money ~> 6.1`. No single `money` satisfies both, so newest-of-everything fails. A valid answer still exists. The resolver can pick an older `payments` release that accepts `money 6.x`. Choosing a version for one gem narrows the choices for its dependencies, and those choices narrow the next gem's, so resolution is a search across combinations rather than a per-gem lookup. `gem install` performs the same kind of resolution for a single gem and its dependencies. Bundler resolves the whole application at once and records the answer in `Gemfile.lock`. Without that record, two machines installing the same list of gems at different times can resolve to different versions, which is the problem Bundler was created to solve. What version constraints mean ----------------------------- A requirement is one or more comparisons against a version: gem "rack", ">= 2.2" # 2.2.0 or later gem "rack", ">= 2.2", "< 4.0" # within a range gem "rack", "= 3.2.6" # exactly this version The pessimistic operator `~>` allows the last given digit to grow but not the ones before it. `~> 3.2` means `>= 3.2` and `< 4.0`. `~> 3.2.6` means `>= 3.2.6` and `< 3.3.0`. The extra digit matters. `~> 2.2` allows 2.9.9, while `~> 2.2.0` stops within the 2.2.x series and rejects 2.3.0. Pick the level of change you are prepared to absorb automatically. Prerelease versions contain a letter, like `8.1.0.beta1`, and sort before the release they lead up to. The resolver never considers them unless a requirement explicitly names one, so `gem "rails", ">= 8.1.0.beta1"` opts in and plain `gem "rails"` does not. How the resolver works ---------------------- Both Bundler and `gem install` resolve with PubGrub, a version solving algorithm originally developed for Dart's package manager and since adopted across ecosystems. PubGrub explores candidate versions, learns from each dead end which combinations can never work, and uses that knowledge to skip whole regions of the search space. This keeps resolution fast even for large graphs, and when no solution exists it can explain why rather than just giving up. That explanation is what a conflict error shows. Bundler walks through the conflicting requirement chains, each step naming which gem demanded which versions of which dependency. How to read those chains and work out of a conflict is covered in [Troubleshooting common issues](/troubleshooting#dependency-resolution-conflicts). Resolution and the lockfile --------------------------- Resolution does not happen on every install. The first `bundle install` resolves and writes the chosen versions to `Gemfile.lock`. From then on `bundle install` reuses the locked versions exactly, which is why it is fast and gives every machine and deploy the same gems. If you edit the Gemfile, the next `bundle install` re-resolves only as much as the change requires and leaves the rest of the lockfile untouched. Re-resolving on purpose is what `bundle update` is for: bundle update # everything, to the newest allowed versions bundle update rack # one gem, allowing its dependencies to move bundle update rack --conservative # one gem, keeping its dependencies locked Cooldown -------- A [cooldown](/cooldown) excludes gem versions published less than a chosen number of days ago from resolution. This narrows the candidate set, so the resolver may pick an older version than it otherwise would, and a resolution can even fail although a compatible version exists, because that version is still inside the window. Error messages note when candidates were excluded by the cooldown, and versions already in your lockfile are never retracted by it. --- # How Gemfile.lock works Source: https://guides.rubygems.org/gemfile-lock/ How to read the file that pins every gem version your application installs. `Gemfile.lock` is the output of [dependency resolution](/dependency-resolution). The first `bundle install` resolves your Gemfile and writes the exact version of every gem, direct or transitive, into the lockfile. Every later install reuses those versions instead of resolving again, so every machine, every teammate, and every deploy runs the same code. Bundler maintains the file. You never edit it by hand. A lockfile, section by section ------------------------------ The examples below come from the lockfile that `bundle install` with Bundler 4.0 generates for this Gemfile: source "https://rubygems.org" ruby "3.4.10" gem "rspec" gem "rack-test", git: "https://github.com/rack/rack-test" gem "billing", path: "vendor/billing" ### GEM Each source the Gemfile uses gets its own block, and `GEM` is the block for a gem server. It names the server under `remote:` and lists under `specs:` every gem resolved from it, at the exact version chosen: GEM remote: https://rubygems.org/ specs: diff-lcs (1.6.2) rack (3.2.6) rspec (3.13.2) rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) rspec-mocks (~> 3.13.0) rspec-core (3.13.6) rspec-support (~> 3.13.0) rspec-expectations (3.13.5) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) rspec-mocks (3.13.8) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) rspec-support (3.13.7) The lines indented under a gem are its own dependencies with the constraints from its gemspec. They explain why versions were chosen, but they are requirements, not choices. The choice for `rspec-core` is its top-level entry, `rspec-core (3.13.6)`. Note that the Gemfile above asked for one gem from this server and six appear here. Transitive dependencies are locked just as precisely as direct ones. ### GIT and PATH Gems taken from a git repository or a local directory get their own source blocks, which appear before `GEM` in the file: GIT remote: https://github.com/rack/rack-test revision: 1fc57f3d26275c51ba6ecea860182b94c9c242fa specs: rack-test (2.2.0) rack (>= 1.3) PATH remote: vendor/billing specs: billing (0.1.0) For a git source the pinned commit under `revision:` plays the role that the version number plays in `GEM`. Later installs fetch exactly that commit, even if the branch has moved on. A path source records only the location. Its contents are read from that directory on every install, which is what makes `path:` useful while developing a gem alongside the application. ### PLATFORMS PLATFORMS arm64-darwin-27 ruby This lists the platforms the resolution covers. `ruby` is the generic platform of pure-Ruby gems, and the others are concrete platforms the lockfile was resolved for, which matters for gems that ship precompiled platform-specific versions. See [Platforms and native gems](/platforms) for the platform concept itself. If you develop on macOS and deploy to Linux, add the deploy platform so resolution covers it too: bundle lock --add-platform x86_64-linux Rather than curating the list by hand, normalize it before committing, as covered in [When to commit it](#when-to-commit-it). ### DEPENDENCIES DEPENDENCIES billing! rack-test! rspec These are the direct dependencies, one line per `gem` call in the Gemfile. Anything in the source blocks that is missing here is a transitive dependency. A trailing `!` marks a gem pinned to a non-default source, one of the `GIT` or `PATH` blocks above. ### CHECKSUMS CHECKSUMS billing (0.1.0) bundler (4.0.16) sha256=d6ca5dd440c24f9abce9844cf44cc8e18c6a553de65a47efb4544137af92c47d diff-lcs (1.6.2) sha256=9ae0d2cba7d4df3075fe8cd8602a8604993efc0dfa934cff568969efb1909962 rack (3.2.6) sha256=5ed78e1f73b2e25679bec7d45ee2d4483cc4146eb1be0264fc4d94cb5ef212c2 rack-test (2.2.0) rspec (3.13.2) sha256=206284a08ad798e61f86d7ca3e376718d52c0bc944626b2349266f239f820587 ... Each checksum is the SHA-256 digest of the packaged `.gem` file, and Bundler verifies every gem against it during installation. A gem that was tampered with after the lockfile was written fails to install, which protects deploys against a compromised gem source. Gems from git and path sources have no packaged file to digest, so their entries carry no checksum. Bundler writes this section into new lockfiles by default. To add it to an existing lockfile, see [Lockfile checksums](/security#lockfile-checksums). ### RUBY VERSION RUBY VERSION ruby 3.4.10 This section appears only when the Gemfile declares a `ruby` version, and records the Ruby the project was locked with. Without the declaration the lockfile has no opinion about the Ruby version. ### BUNDLED WITH BUNDLED WITH 4.0.16 The Bundler version that wrote the lockfile. When another machine runs `bundle` commands in this project, Bundler automatically switches to this version if it is installed, so the whole team locks with the same Bundler. See [Which Bundler version runs](/installation#which-bundler-version-runs). When to commit it ----------------- For an application, always commit `Gemfile.lock`. The lockfile is how a deploy or a teammate reproduces your exact gem versions, and an uncommitted lockfile silently turns every install back into a fresh resolution. For a gem, the lockfile is not part of the package. When an application depends on your gem, Bundler resolves your gemspec's dependencies together with everything else and ignores any lockfile your gem ships, as covered in [Gemfile and gemspec](/gemfile-and-gemspec). Whether to commit the lockfile of the gem's own repository for development is a separate tradeoff, discussed in the [FAQs](/faqs#using-gemfiles-inside-gems). Before committing a lockfile, normalize its platform list. Treat this as a required step: bundle lock --normalize-platforms Normalizing fixes two problems at once. First, on macOS the concrete platform records the Darwin major version, `arm64-darwin-27` in the example above. That number differs between macOS releases, so lockfiles generated on different Macs disagree about the platform for no useful reason. Normalizing rewrites the entry to the versionless `arm64-darwin`, which covers every macOS release, and later installs keep that form. Second, for gems that ship precompiled platform-specific versions, normalizing adds every platform the locked versions are precompiled for in one step, instead of one `bundle lock --add-platform` per deploy target. A lockfile freshly generated by Bundler 4 already locks all of those precompiled platforms, but the first problem remains. The example at the top of this page is a fresh Bundler 4 lockfile and still records `arm64-darwin-27`. So run the command on new lockfiles too, and on older lockfiles it catches up both points at once. Because Bundler regenerates the file, never resolve a merge conflict in `Gemfile.lock` by hand. Bundler refuses to load a lockfile containing conflict markers and asks for a clean copy. Restore one side with `git checkout HEAD -- Gemfile.lock`, merge the Gemfile normally, then run `bundle install` and Bundler re-locks whatever the merged Gemfile changed while keeping unrelated pins in place. --- # Versioning and compatibility Source: https://guides.rubygems.org/versioning/ What a version number can and cannot promise, and how RubyGems compares and constrains versions. Every gem carries a version number, and dependency resolution runs on what those numbers mean. A version number is a message from the gem's author about how much changed. It is not a contract, and RubyGems does not enforce one. This page covers versioning schemes and their limits, how to version your own gem, how RubyGems actually compares versions, and how to write constraints without trusting numbers more than they deserve. Versioning schemes ------------------ RubyGems accepts any version number and attaches no meaning to its parts. What a bump signifies is decided by each gem's author. The best known scheme is [semantic versioning](https://semver.org), or SemVer, which gives the three parts of `MAJOR.MINOR.PATCH` defined roles: * **PATCH** `0.0.x` changes fix bugs without changing any documented behavior. * **MINOR** `0.x.0` changes add functionality in a backwards compatible way. * **MAJOR** `x.0.0` changes are backwards *incompatible*. Much of the ecosystem loosely assumes this vocabulary, and the `~>` constraint operator is built around the idea that a change further to the left carries more risk. But SemVer is a communication convention, not a rule of RubyGems, and this guide does not tell you to adopt it. Read as a contract, it would require a maintainer to decide for every change whether any user's code could break, and almost every observable change breaks somebody. Nobody owes that guarantee, least of all volunteers. Well-known projects define their own schemes instead. Ruby itself releases a new minor version every Christmas and allows incompatible changes in it, and Rails documents its own scheme in which minor releases may add features and remove deprecated behavior. The variety only grows outside Ruby. Ubuntu numbers releases by date, with 24.04 meaning April 2024, a scheme known as [calendar versioning](https://calver.org). Python cuts a new 3.x every year and removes deprecated features in those releases, so its minor number carries what SemVer would call major changes. A version number tells you what a project's own policy says it tells you, nothing more. What helps your users is not which scheme you pick but that you say what you do. Document your policy, keep a changelog, and make disruptive releases easy to spot. In the other direction, whatever scheme a dependency claims to follow, the only reliable compatibility check is running your own test suite against the new version. [Gemfile.lock](/gemfile-lock) exists so that upgrades happen when you choose to take them, not when a number changes. Versioning your gem ------------------- In the layout `bundle gem` generates, the version is a single constant in `lib//version.rb` and the gemspec reads it from there. Changing that constant and releasing is the whole mechanism. A new gem conventionally starts at `0.1.0`, which is what `bundle gem` generates, and `1.0.0` is widely read as a signal that the API has settled. If you have no strong preference for a scheme, the SemVer vocabulary is what most of your users will assume by default: bump the last part for fixes, the middle part for additions, the first part for changes that can break existing code. A gentle way to deliver breaking changes, when you can afford the effort, is to deprecate with a warning in one release and remove in a later one, so users see the warning before anything breaks. How far you go in guaranteeing any of this is your call as the author. When judging how loudly to signal a change, remember that compatibility is wider than the method list. Changing a return value or a default, raising `required_ruby_version`, and tightening a dependency constraint can all stop an application that resolved and ran before, so they deserve the same visibility as a removed API. One hard rule does exist: a version number on [RubyGems.org](https://rubygems.org) can never be reused, and yanking a release does not free its number. A broken release is fixed by pushing a new version, not by replacing the old one. Prerelease versions ------------------- Any version containing a letter, like `1.0.0.pre`, `2.0.0.rc1`, or `1.5.0.beta.3`, is a prerelease version. Use one to ship a release candidate for testing before the real release: Gem::Specification.new do |s| s.name = "hola" s.version = "1.0.0.rc1" Push it like any other release. It stays out of everyone's way because installers ignore prereleases unless asked. `gem install hola` installs the newest stable version, and only `gem install hola --pre` picks the release candidate. The same rule applies during dependency resolution. Bundler considers a prerelease only when a requirement explicitly names one, such as `gem "hola", ">= 1.0.0.rc1"`. See [How dependency resolution works](/dependency-resolution) for the details. How RubyGems compares versions ------------------------------ Constraints are evaluated with `Gem::Version`, which you can probe directly: $ ruby -e 'puts %w[2.0.0 1.0.0 1.0.1 1.0.0.rc1 1.0.0.beta2 1.1.0.beta 1.0.0.alpha].map { |v| Gem::Version.new(v) }.sort' 1.0.0.alpha 1.0.0.beta2 1.0.0.rc1 1.0.0 1.0.1 1.1.0.beta 2.0.0 A version string is split into segments at dots and at letter/digit boundaries, so `1.0.0.beta10` becomes `1, 0, 0, "beta", 10`. Numeric segments compare numerically, which is why `beta10` sorts after `beta9`. String segments compare alphabetically and always sort before numeric ones, which is why every prerelease sorts before the release it leads up to. The common identifiers happen to be alphabetical in the right order, `alpha` before `beta` before `pre` before `rc`, so sticking to them keeps a sequence of prereleases sorted as intended. Trailing zeros are ignored, so `1.0` and `1.0.0` are the same version. A hyphen is read as `.pre.`, so SemVer-style `1.0.0-rc1` is accepted but normalized to `1.0.0.pre.rc1`. SemVer build metadata like `1.0.0+001` is not valid in a gem version. Constraining your dependencies ------------------------------ A version constraint states how much change you accept from a dependency. The operators and their exact semantics are covered in [How dependency resolution works](/dependency-resolution#what-version-constraints-mean). Keep in mind what a constraint can actually rely on. A constraint written against version numbers encodes trust in the author's numbering, and that numbering is a courtesy, not a contract. Check a project's own policy and changelog before leaning on it, and let your lockfile and test suite do the real protecting. In an application's Gemfile, constraints only bound what `bundle update` may do, because the exact versions installed come from `Gemfile.lock`. See [How Gemfile.lock works](/gemfile-lock). A pessimistic constraint like `~> 8.1` is a reasonable way to say that major upgrades should be a deliberate act rather than a side effect of an update. ### Optimistic vs. pessimistic constraints In a gemspec the stakes are different, because your constraints combine with every other gem's in your users' applications. An optimistic constraint sets only a lower bound: spec.add_dependency "library", ">= 2.2" A pessimistic constraint adds an upper bound at the next release the numbering scheme calls incompatible. `~> 2.2` means `>= 2.2` and `< 3.0`: spec.add_dependency "library", "~> 2.2" Prefer optimistic constraints in a gemspec. You cannot predict the future, and a new major version of the dependency often leaves the parts your gem uses untouched. A pessimistic constraint in a published gem also locks the whole graph. If your gem pins `~> 2.2`, no application using your gem can move to the dependency's 3.x, even when everything would have worked. This transitive lock-in is a common problem in practice, while breakage from an optimistic constraint can be fixed in the affected application by pinning the dependency there. Reserve `~>` in a gemspec for cases where it is genuinely warranted, such as a dependency that has already announced an incompatible change you know will break your gem. Two details worth knowing. With only two digits given, `~> 2` allows the 2.x series and stops before 3.0, it does not mean "2 or anything newer". And requirements compose as a list, so you can combine bounds or exclude a single broken release: spec.add_dependency "library", ">= 2.2", "< 4.0" spec.add_dependency "library", ">= 2.0", "!= 2.2.1" --- # Platforms and native gems Source: https://guides.rubygems.org/platforms/ How RubyGems names the system a gem was built for, and how precompiled native gems skip compilation at install time. Most gems are pure Ruby and install identically everywhere. Gems that include native extensions compile C or Rust code during installation, and many of them also publish precompiled binaries so that on common systems nothing is compiled at all. This page explains what a gem platform is, how the matching variant is chosen at install time, how platforms interact with `Gemfile.lock`, and how to force the source build when a binary does not suit you. What a gem platform is ---------------------- Every published gem carries a platform. The platform `ruby` means the gem is delivered as source and installs on any system. Gems whose extensions are compiled on your machine at install time are `ruby` platform gems too. A concrete platform names the CPU architecture and operating system a prebuilt binary targets, such as `x86_64-linux-gnu`, `arm64-darwin`, or `x64-mingw-ucrt`, and the platform `java` marks builds for JRuby. Your machine has a local platform, derived from your Ruby's build configuration: $ gem env platform ruby:arm64-darwin-27 The output lists the platforms RubyGems will install on this machine, `ruby` plus the local platform. The local platform is also available in code as `Gem::Platform.local`. A gem is only considered for installation when its platform matches one of these. The full matching rules are described in `gem help platform`. Precompiled native gems ----------------------- A gem that ships precompiled binaries publishes the same version number several times, once per platform. For example, [nokogiri](https://rubygems.org/gems/nokogiri) 1.19.4 exists on RubyGems.org as the source `ruby` gem, a `java` build, `arm64-darwin` and `x86_64-darwin` builds for macOS, an `x64-mingw-ucrt` build for Windows, and Linux builds for three CPU architectures in both `-gnu` and `-musl` variants. You do not choose among them. `gem install` and `bundle install` pick the variant matching your local platform automatically, and fall back to the `ruby` gem when no binary matches. You can watch the choice with `gem fetch`, which downloads a gem without installing it: $ gem fetch nokogiri Downloaded nokogiri-1.19.4-arm64-darwin When a binary matches, installation is fast and needs no compiler. When only the `ruby` gem matches, the extension is compiled on your machine, which requires a working toolchain and the libraries the gem wraps. If that build fails, see [Troubleshooting](/troubleshooting#native-extension-build-failures). If you maintain a gem with an extension and want to publish your own precompiled binaries, see [Gems with Extensions](/gems-with-extensions). Linux and musl -------------- Linux platform names end with the C library the binary was linked against. `x86_64-linux-gnu` targets glibc systems, which covers most distributions, and `x86_64-linux-musl` targets musl systems such as Alpine. A `-gnu` binary is never selected on a musl system. If a gem publishes no `-musl` build, a musl system falls back to the `ruby` gem and compiles the extension. Older gem releases used the bare name `x86_64-linux` instead. A bare Linux platform matches both glibc and musl systems, so such a binary installs on Alpine whether or not it can actually run there. If a precompiled gem installs but fails to load, force the source build as described [below](#forcing-the-source-build). Platforms in Gemfile.lock ------------------------- Bundler records the platforms a resolution covers in the `PLATFORMS` section of `Gemfile.lock` and locks the platform-specific gem versions for each. A fresh Bundler 4 lockfile for an application depending on nokogiri covers every platform the precompiled builds support: PLATFORMS aarch64-linux-gnu aarch64-linux-musl arm-linux-gnu arm-linux-musl arm64-darwin x86_64-darwin x86_64-linux-gnu x86_64-linux-musl Installing on a platform the lockfile does not cover normally just works. Bundler adds the local platform, re-resolves, and updates the lockfile. In CI and production the lockfile is typically frozen, so the same situation fails instead. This is the classic error when an application is developed on macOS with an older lockfile and deployed to Linux: Your bundle only supports platforms ["arm64-darwin-27"] but your local platform is x86_64-linux. Add the current platform to the lockfile with `bundle lock --add-platform x86_64-linux` and try again. The fix is what the message says. Run `bundle lock --add-platform x86_64-linux` on your development machine, commit the updated lockfile, and deploy again. The error only occurs when the `PLATFORMS` section contains neither your platform nor `ruby`, which is why it usually involves precompiled native gems. Rather than adding platforms one by one, run `bundle lock --normalize-platforms` before committing. One run adds every platform your locked gems are precompiled for, and it also strips the OS version from entries like `arm64-darwin-27` so that lockfiles generated on different machines agree. [How Gemfile.lock works](/gemfile-lock#when-to-commit-it) covers when to run it, and [bundle lock](/command-reference/bundle-lock/) documents the command. Despite the name, the `platforms` block in a Gemfile is a different concept. Its values, such as `ruby`, `windows`, and `jruby`, group dependencies by Ruby implementation rather than naming lockfile platforms. See [the Gemfile reference](/gemfile/#PLATFORMS). Forcing the source build ------------------------ Sometimes the precompiled binary is the wrong choice. It may misbehave on your system, or its `required_ruby_version` may exclude a Ruby that the source gem still supports. The `force_ruby_platform` setting tells Bundler to ignore your machine's platform, install only `ruby` platform gems, and compile native extensions from source: bundle config set --local force_ruby_platform true To force the source build for a single gem, set the option in the Gemfile: gem "ffi", force_ruby_platform: true With plain `gem install`, pick the platform explicitly instead: gem install nokogiri --platform ruby See the `force_ruby_platform` entries in [bundle config](/command-reference/bundle-config/) and [the Gemfile reference](/gemfile/#FORCE_RUBY_PLATFORM). --- # Caching and vendoring Source: https://guides.rubygems.org/caching-and-vendoring/ The caches RubyGems and Bundler keep on your machine, and how to vendor an application's gems for installs that need no network. Every gem you install is downloaded once and remembered. RubyGems keeps the downloaded `.gem` files next to the installed gems, Bundler adds a per-user cache of its own, and `bundle cache` copies an application's whole dependency set into the repository so it can be shipped with the code. This page maps out where these caches live, how to install from them without network access, and how to clean them up. The gem download cache ---------------------- When `gem install` or `bundle install` downloads a gem, the original `.gem` file is kept after its contents are unpacked. It sits in the `cache/` directory of the gem repository described in [Where gems are installed and how they load](/gem-installation-and-loading): $ ls "$(gem env gemdir)/cache" ... rack-3.2.2.gem rake-13.4.2.gem ... Each gem repository has its own `cache/` directory. When Bundler installs into an application-local path such as `vendor/bundle`, the cache is inside that path, at `vendor/bundle/ruby/3.4.0/cache` for example. Installing a version that is already in the cache reuses the cached file instead of downloading it again. These files exist purely to save a download. Deleting one costs nothing except a re-download the next time that exact version is installed. Bundler's user-level cache -------------------------- Bundler also keeps a cache that belongs to you rather than to any application. It defaults to `~/.bundle/cache` and can be moved with the `BUNDLE_USER_CACHE` environment variable. Bundler always stores [compact index](/rubygems-org-compact-index-api) data there, the catalog of gem names and versions it fetches from RubyGems.org during [dependency resolution](/dependency-resolution). The catalog updates incrementally, which is why resolving against RubyGems.org is fast after the first run. Downloaded gems can be cached at the user level too, but only if you opt in: bundle config set global_gem_cache true With this setting, Bundler saves every downloaded `.gem` file and every compiled native extension in the user-level cache, keyed by the source it came from. This pays off when you keep many applications with separate install paths. Each application still gets its own copy of the installed gems, but a gem version is downloaded and compiled only once per user. See `global_gem_cache` in [bundle config](/command-reference/bundle-config/). Vendoring gems with bundle cache -------------------------------- The caches above are machine-local conveniences. `bundle cache` is different in kind. It copies every `.gem` file the application needs into `vendor/cache`, inside the application itself: $ bundle cache Updating files in vendor/cache * rack-3.2.2.gem * rake-13.4.2.gem From then on, `bundle install` prefers the files in `vendor/cache` over downloading from RubyGems.org. Since Bundler 4, [git and path dependencies](/git) are cached as well, so the directory covers the whole `Gemfile`. Setting `cache_all` to `false` restricts it to ordinary gems again. By default the command caches gems for your current platform only. If the [lockfile covers several platforms](/platforms), pass `--all-platforms` to cache the gems for all of them, which is what you want when the cache is built on macOS and consumed on Linux. `bundle cache` also installs the gems as a side effect, and `--no-install` skips that. The full option list is in [bundle cache](/command-reference/bundle-cache/). Should you commit vendor/cache? ------------------------------- Committing `vendor/cache` means a checkout of your repository contains everything needed to run `bundle install` with no network at all. Deploys stop depending on RubyGems.org being reachable, and the exact bytes of every dependency are recorded alongside the code that uses them. The cost is repository size. Every cached gem, and every updated version of it, stays in your version control history forever. For most applications a committed `Gemfile.lock` already makes installs reproducible, as described in [How Gemfile.lock works](/gemfile-lock), so committing the cache is optional and most teams skip it. It earns its place when deploy targets have no network access or when you must be able to rebuild the application without any external service. Installing offline ------------------ With a populated `vendor/cache`, or with the needed versions already in the gem download cache, Bundler can install without touching the network: bundle install --local There is one caveat. During a normal install Bundler checks RubyGems.org for a [precompiled variant](/platforms) matching your platform even when every gem is cached. `--local` skips that check, so it only picks from the gems the cache actually contains. Building the cache with `--all-platforms` on a machine of the deployment platform avoids surprises here. Plain RubyGems can install from a local `.gem` file directly, either by path or by name with `--local` in a directory containing the file: $ gem install --local ./rake-13.4.2.gem Successfully installed rake-13.4.2 Cleaning up ----------- Caches and gem repositories only grow, and two commands prune them. `gem cleanup` uninstalls old versions of installed gems that no other installed gem depends on, and removes their cached `.gem` files along the way. `gem cleanup -n` shows what would be removed without doing it, and the exact rules are in `gem help cleanup`. For an application's bundle, `bundle clean` removes gems in the application's install path that the current `Gemfile.lock` no longer references. It refuses to run against gems installed to the shared system location unless you pass `--force`, because those gems may be used by other applications. `--dry-run` previews the removals. See [bundle clean](/command-reference/bundle-clean/). --- # Default Gems and Bundled Gems Source: https://guides.rubygems.org/default-gems-and-bundled-gems/ Understanding Ruby's standard library gems. * [What are Default Gems and Bundled Gems?](#what-are-default-gems-and-bundled-gems) * [Default Gems](#default-gems) * [Bundled Gems](#bundled-gems) * [Differences Between Default and Bundled Gems](#differences-between-default-and-bundled-gems) * [Finding Version Information](#finding-version-information) What are Default Gems and Bundled Gems? ---------------------------------------- Large portions of Ruby's standard library come in the form of RubyGems, which can be updated independently from Ruby itself. These gems are divided into two categories: default gems and bundled gems. Default Gems ----------- Default gems are gems that are part of Ruby and you can always require them directly. They have the following characteristics: * **Shipped with Ruby**: They are included in every Ruby installation * **Cannot be uninstalled**: They are part of the core Ruby distribution * **Can be updated**: You can update them using `gem update ` * **Always available**: You can require them without adding them to your Gemfile * **Flexible versioning**: You can specify any version in your Gemfile (e.g., `gem "json", ">= 2.6"`) * **Maintained by Ruby core**: These gems are maintained as part of the Ruby project For a complete list of default gems in your Ruby version, you can visit [stdgems.org](https://stdgems.org/) or check the [official Ruby documentation](https://docs.ruby-lang.org/en/master/standard_library_md.html). Bundled Gems ------------ Bundled gems are similar to normal gems, but they are automatically installed when you install Ruby. They have the following characteristics: * **Shipped with Ruby**: They are included in Ruby installations * **Can be uninstalled**: Unlike default gems, you can remove them if needed * **Can be updated**: Like default gems, you can update them independently * **Require Gemfile declaration**: When using Bundler, you need to declare them in your Gemfile * **Maintained outside Ruby core**: These gems are maintained separately from Ruby itself For a complete list of bundled gems in your Ruby version, visit [stdgems.org](https://stdgems.org/). Differences Between Default and Bundled Gems -------------------------------------------- | Feature | Default Gems | Bundled Gems | |---------|-------------|--------------| | Shipped with Ruby | Yes | Yes | | Can be uninstalled | No | Yes | | Can be updated | Yes | Yes | | Require in Gemfile (with Bundler) | Optional | Required | | Version flexibility in Gemfile | Any version | Any version | | Maintenance | Ruby core team | External maintainers | | Always available without Gemfile | Yes | No (when using Bundler) | Finding Version Information --------------------------- To find out which default gems and bundled gems are included in your Ruby version: ### Using the Command Line Check your Ruby version: $ ruby -v ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin23] List installed gems: $ gem info json ### Using stdgems.org Visit [https://stdgems.org/](https://stdgems.org/) to see: * Complete lists of default and bundled gems for each Ruby version * Version numbers for each gem in each Ruby release * Links to gem documentation and source code * Comparison views between Ruby versions * JSON data files for programmatic access ### Using Ruby Documentation The [official Ruby documentation](https://docs.ruby-lang.org/en/master/standard_library_md.html) provides information about: * Default gems with links to their documentation and GitHub repositories * Bundled gems with links to their documentation and GitHub repositories * Default libraries (non-gem standard libraries) ### Compatibility Across Ruby Versions Keep in mind that different Ruby versions ship with different versions of default and bundled gems. When developing applications that need to work across multiple Ruby versions: * Check [stdgems.org](https://stdgems.org/) to see which gem versions are included in each Ruby version * Specify version constraints in your Gemfile when necessary * Test your application against the target Ruby versions ## Additional Resources * [stdgems.org](https://stdgems.org/) - Comprehensive information about Ruby's standard gems * [Ruby Standard Library Documentation](https://docs.ruby-lang.org/en/master/standard_library_md.html) - Official Ruby documentation * [What is a gem?](/what-is-a-gem) - Learn more about RubyGems basics * [RubyGems Basics](/rubygems-basics) - Getting started with RubyGems --- # RubyGems Common Vulnerabilities and Exposures Source: https://guides.rubygems.org/cve/ ## CVE-2013-4287: Algorithmic complexity vulnerability in RubyGems 2.0.7 and older RubyGems validates versions with a regular expression that is vulnerable to denial of service due to backtracking. For specially crafted RubyGems versions attackers can cause denial of service through CPU consumption. RubyGems versions 2.0.7 and older, 2.1.0.rc.1 and 2.1.0.rc.2 are vulnerable. Ruby versions 1.9.0 through 2.0.0p247 are vulnerable as they contain embedded versions of RubyGems. It does not appear to be possible to exploit this vulnerability by installing a gem for RubyGems 1.8.x or 2.0.x. Vulnerable uses of RubyGems API include packaging a gem (through `gem build`, Gem::Package or Gem::PackageTask), sending user input to Gem::Version.new, Gem::Version.correct? or use of the Gem::Version::VERSION_PATTERN or Gem::Version::ANCHORED_VERSION_PATTERN constants. Notably, users of bundler that install gems from git are vulnerable if a malicious author changes the gemspec to an invalid version. The vulnerability can be fixed by changing the first grouping to an atomic grouping in Gem::Version::VERSION_PATTERN in lib/rubygems/version.rb. For RubyGems 2.0.x: - VERSION_PATTERN = '[0-9]+(\.[0-9a-zA-Z]+)*(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?' # :nodoc: + VERSION_PATTERN = '[0-9]+(?>\.[0-9a-zA-Z]+)*(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?' # :nodoc: For RubyGems 1.8.x: - VERSION_PATTERN = '[0-9]+(\.[0-9a-zA-Z]+)*' # :nodoc: + VERSION_PATTERN = '[0-9]+(?>\.[0-9a-zA-Z]+)*' # :nodoc: This vulnerability was discovered by Damir Sharipov ## CVE-2013-4363: Algorithmic complexity vulnerability in RubyGems 2.1.4 and older The patch for CVE-2013-4287 was insufficiently verified so the combined regular expression for verifying gem version remains vulnerable following CVE-2013-4287. RubyGems validates versions with a regular expression that is vulnerable to denial of service due to backtracking. For specially crafted RubyGems versions attackers can cause denial of service through CPU consumption. RubyGems versions 2.1.4 and older are vulnerable. Ruby versions 1.9.0 through 2.0.0p247 are vulnerable as they contain embedded versions of RubyGems. It does not appear to be possible to exploit this vulnerability by installing a gem for RubyGems 1.8.x or newer. Vulnerable uses of RubyGems API include packaging a gem (through `gem build`, Gem::Package or Gem::PackageTask), sending user input to Gem::Version.new, Gem::Version.correct? or use of the Gem::Version::VERSION_PATTERN or Gem::Version::ANCHORED_VERSION_PATTERN constants. Notably, users of bundler that install gems from git are vulnerable if a malicious author changes the gemspec to an invalid version. The vulnerability can be fixed by changing the "*" repetition to a "?" repetition in Gem::Version::ANCHORED_VERSION_PATTERN in lib/rubygems/version.rb. For RubyGems 2.1.x: - ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})*\s*\z/ # :nodoc: + ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})?\s*\z/ # :nodoc: For RubyGems 2.0.x: - ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})*\s*\z/ # :nodoc: + ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})?\s*\z/ # :nodoc: For RubyGems 1.8.x: - ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})*\s*\z/ # :nodoc: + ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})?\s*\z/ # :nodoc: This vulnerability was discovered by Alexander Cherepanov ## CVE-2015-3900: Request hijacking vulnerability in RubyGems 2.4.6 and earlier RubyGems provides the ability of a domain to direct clients to a separate host that is used to fetch gems and make API calls against. This mechanism is implemented via DNS, specifically a SRV record _rubygems._tcp under the original requested domain. For example, this is the one that users who use rubygems.org see: > dig _rubygems._tcp.rubygems.org SRV ;; ANSWER SECTION: _rubygems._tcp.rubygems.org. 600 IN SRV 0 1 80 api.rubygems.org. RubyGems did not validate the hostname returned in the SRV record before sending requests to it. This left clients open to a DNS hijack attack, whereby an attacker could return a SRV of their choosing and get the client to use it. For example: > dig _rubygems._tcp.rubygems.org SRV ;; ANSWER SECTION: _rubygems._tcp.rubygems.org. 600 IN SRV 0 1 80 gems.nottobetrusted.wtf The fix, detailed at https://github.com/rubygems/rubygems/commit/6bbee35, shows that we validate the record now to be under the original domain. This restricts the client to be using the original trust/security domain as they would have otherwise. RubyGems versions between 2.0 and 2.4.6 are vulnerable. RubyGems version 2.0.16, 2.2.4, and 2.4.7 have been released that fix this issue. Ruby versions 1.9.0 through 2.2.0 are vulnerable as they contain embedded versions of RubyGems. This vulnerability was reported by Jonathan Claudius . --- # Command Reference Source: https://guides.rubygems.org/command-reference/ What each `gem` command does, and how to use it. This reference was automatically generated from RubyGems version 4.0.18. * [gem build](#gem-build) * [gem cert](#gem-cert) * [gem check](#gem-check) * [gem cleanup](#gem-cleanup) * [gem contents](#gem-contents) * [gem dependency](#gem-dependency) * [gem environment](#gem-environment) * [gem exec](#gem-exec) * [gem fetch](#gem-fetch) * [gem generate_index](#gem-generate_index) * [gem help](#gem-help) * [gem info](#gem-info) * [gem install](#gem-install) * [gem list](#gem-list) * [gem lock](#gem-lock) * [gem mirror](#gem-mirror) * [gem open](#gem-open) * [gem outdated](#gem-outdated) * [gem owner](#gem-owner) * [gem pristine](#gem-pristine) * [gem push](#gem-push) * [gem rdoc](#gem-rdoc) * [gem rebuild](#gem-rebuild) * [gem search](#gem-search) * [gem server](#gem-server) * [gem signin](#gem-signin) * [gem signout](#gem-signout) * [gem sources](#gem-sources) * [gem specification](#gem-specification) * [gem stale](#gem-stale) * [gem uninstall](#gem-uninstall) * [gem unpack](#gem-unpack) * [gem update](#gem-update) * [gem which](#gem-which) * [gem yank](#gem-yank) ## gem build Build a gem from a gemspec ### Usage gem build GEMSPEC_FILE [options] ### Options * `--platform PLATFORM` - Specify the platform of gem to build * `--force` - skip validation of the spec * `--strict` - consider warnings as errors when validating the spec * `-o, --output FILE` - output gem with the given filename ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEMSPEC_FILE* - gemspec file name to build a gem for ### Description The build command allows you to create a gem from a ruby gemspec. The best way to build a gem is to use a Rakefile and the Gem::PackageTask which ships with RubyGems. The gemspec can either be created by hand or extracted from an existing gem with gem spec: $ gem unpack my_gem-1.0.gem Unpacked gem: '.../my_gem-1.0' $ gem spec my_gem-1.0.gem --ruby > my_gem-1.0/my_gem-1.0.gemspec $ cd my_gem-1.0 [edit gem contents] $ gem build my_gem-1.0.gemspec Gems can be saved to a specified filename with the output option: $ gem build my_gem-1.0.gemspec --output=release.gem ## gem cert Manage RubyGems certificates and signing settings ### Usage gem cert [options] ### Options * `-a, --add CERT` - Add a trusted certificate. * `-l, --list [FILTER]` - List trusted certificates where the subject contains FILTER * `-r, --remove FILTER` - Remove trusted certificates where the subject contains FILTER * `-b, --build EMAIL_ADDR` - Build private key and self-signed certificate for EMAIL_ADDR * `-C, --certificate CERT` - Signing certificate for `--sign` * `-K, --private-key KEY` - Key for `--sign` or `--build` * `-A, --key-algorithm ALGORITHM` - Select which key algorithm to use for `--build` * `-s, --sign CERT` - Signs CERT with the key from `-K` and the certificate from `-C` * `-d, --days NUMBER_OF_DAYS` - Days before the certificate expires * `-R, --re-sign` - Re-signs the certificate from `-C` with the key from `-K` ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Description The cert command manages signing keys and certificates for creating signed gems. Your signing certificate and private key are typically stored in ~/.gem/gem-public_cert.pem and ~/.gem/gem-private_key.pem respectively. To build a certificate for signing gems: gem cert --build you@example If you already have an RSA key, or are creating a new certificate for an existing key: gem cert --build you@example --private-key /path/to/key.pem If you wish to trust a certificate you can add it to the trust list with: gem cert --add /path/to/cert.pem You can list trusted certificates with: gem cert --list or: gem cert --list cert_subject_substring If you wish to remove a previously trusted certificate: gem cert --remove cert_subject_substring To sign another gem author's certificate: gem cert --sign /path/to/other_cert.pem For further reading on signing gems see `ri Gem::Security`. ## gem check Check a gem repository for added or missing files ### Usage gem check [OPTIONS] [GEMNAME ...] [options] ### Options * `-a, --[no-]alien` - Report "unmanaged" or rogue files in the gem repository * `--[no-]doctor` - Clean up uninstalled gems and broken specifications * `--[no-]dry-run` - Do not remove files, only report what would be removed * `--[no-]gems` - Check installed gems for problems * `-v, --version VERSION` - Specify version of gem to check ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEMNAME* - name of gem to check ### Description The check command can list and repair problems with installed gems and specifications and will clean up gems that have been partially uninstalled. ## gem cleanup Clean up old versions of installed gems ### Usage gem cleanup [GEMNAME ...] [options] ### Options * `-n, -d, --dry-run` - Do not uninstall gems * `-D, --[no-]check-development` - Check development dependencies while uninstalling (default: true) * `--[no-]user-install` - Cleanup in user's home directory instead of GEM_HOME. ### Deprecated Options * `--dryrun` - Do not uninstall gems ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEMNAME* - name of gem to cleanup ### Description The cleanup command removes old versions of gems from GEM_HOME that are not required to meet a dependency. If a gem is installed elsewhere in GEM_PATH the cleanup command won't delete it. If no gems are named all gems in GEM_HOME are cleaned. ## gem contents Display the contents of the installed gems ### Usage gem contents GEMNAME [GEMNAME ...] [options] ### Options * `-v, --version VERSION` - Specify version of gem to contents * `--all` - Contents for all gems * `-s, --spec-dir a,b,c` - Search for gems under specific paths * `-l, --[no-]lib-only` - Only return files in the Gem's lib_dirs * `--[no-]prefix` - Don't include installed path prefix * `--[no-]show-install-dir` - Show only the gem install dir ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEMNAME* - name of gem to list contents for ### Description The contents command lists the files in an installed gem. The listing can be given as full file names, file names without the installed directory prefix or only the files that are requireable. ## gem dependency Show the dependencies of an installed gem ### Usage gem dependency REGEXP [options] ### Options * `-v, --version VERSION` - Specify version of gem to dependency * `--platform PLATFORM` - Specify the platform of gem to dependency * `--[no-]prerelease` - Allow prerelease versions of a gem * `-R`, `--[no-]reverse-dependencies` - Include reverse dependencies in the output * `--pipe` - Pipe Format (name `--version` ver) ### Deprecated Options * `-u, --[no-]update-sources` - Update local source cache ### Local/Remote Options * `-l, --local` - Restrict operations to the LOCAL domain * `-r, --remote` - Restrict operations to the REMOTE domain * `-b, --both` - Allow LOCAL and REMOTE operations * `-B, --bulk-threshold COUNT` - Threshold for switching to bulk synchronization (default 1000) * `--clear-sources` - Clear the gem sources * `-s, --source URL` - Append URL to list of remote gem sources * `-p, --[no-]http-proxy [URL]` - Use HTTP proxy for remote operations ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *REGEXP* - show dependencies for gems whose names start with REGEXP ### Description The dependency commands lists which other gems a given gem depends on. For local gems only the reverse dependencies can be shown (which gems depend on the named gem). The dependency list can be displayed in a format suitable for piping for use with other commands. ## gem environment Display information about the RubyGems environment ### Usage gem environment [arg] [options] ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *home* - display the path where gems are installed. Aliases: gemhome, gemdir, GEM_HOME * *path* - display path used to search for gems. Aliases: gempath, GEM_PATH * *user_gemhome* - display the path where gems are installed when `--user-install` is given. Aliases: user_gemdir * *version* - display the gem format version * *remotesources* - display the remote gem servers * *platform* - display the supported gem platforms * *credentials* - display the path where credentials are stored * *<omitted>* - display everything ### Description The environment command lets you query rubygems for its configuration for use in shell scripts or as a debugging aid. The RubyGems environment can be controlled through command line arguments, gemrc files, environment variables and built-in defaults. Command line argument defaults and some RubyGems defaults can be set in a ~/.gemrc file for individual users and a gemrc in the SYSTEM CONFIGURATION DIRECTORY for all users. These files are YAML files with the following YAML keys: :sources: A YAML array of remote gem repositories to install gems from :verbose: Verbosity of the gem command. false, true, and :really are the levels :update_sources: Enable/disable automatic updating of repository metadata :backtrace: Print backtrace when RubyGems encounters an error :gempath: The paths in which to look for gems :disable_default_gem_server: Force specification of gem server host on push : A string containing arguments for the specified gem command Example: :verbose: false install: --no-wrappers update: --no-wrappers :disable_default_gem_server: true RubyGems' default local repository can be overridden with the GEM_PATH and GEM_HOME environment variables. GEM_HOME sets the default repository to install into. GEM_PATH allows multiple local repositories to be searched for gems. If you are behind a proxy server, RubyGems uses the HTTP_PROXY, HTTP_PROXY_USER and HTTP_PROXY_PASS environment variables to discover the proxy server. If you would like to push gems to a private gem server the RUBYGEMS_HOST environment variable can be set to the URI for that server. If you are packaging RubyGems all of RubyGems' defaults are in lib/rubygems/defaults.rb. You may override these in lib/rubygems/defaults/operating_system.rb ## gem exec Run a command from a gem ### Usage gem exec [options --] COMMAND [args] [options] ### Options * `-v, --version VERSION` - Specify version of gem to exec * `--[no-]prerelease` - Allow prerelease versions of a gem to be installed * `-g, --gem GEM` - run the executable from the given gem ### Install/Update Options * `--conservative` Prefer the most recent installed version, - rather than the latest version overall ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *COMMAND* - the executable command to run ### Description The exec command handles installing (if necessary) and running an executable from a gem, regardless of whether that gem is currently installed. The exec command can be thought of as a shortcut to running `gem install` and then the executable from the installed gem. For example, `gem exec rails new .` will run `rails new .` in the current directory, without having to manually run `gem install rails`. Additionally, the exec command ensures the most recent version of the gem is used (unless run with `--conservative`), and that the gem is not installed to the same gem path as user-installed gems. ## gem fetch Download a gem and place it in the current directory ### Usage gem fetch GEMNAME [GEMNAME ...] [options] ### Options * `-v, --version VERSION` - Specify version of gem to fetch * `--platform PLATFORM` - Specify the platform of gem to fetch * `--[no-]prerelease` - Allow prerelease versions of a gem * `--[no-]suggestions` - Suggest alternates when gems are not found ### Local/Remote Options * `-B, --bulk-threshold COUNT` - Threshold for switching to bulk synchronization (default 1000) * `-p, --[no-]http-proxy [URL]` - Use HTTP proxy for remote operations * `-s, --source URL` - Append URL to list of remote gem sources * `--clear-sources` - Clear the gem sources ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEMNAME* - name of gem to download ### Description The fetch command fetches gem files that can be stored for later use or unpacked to examine their contents. See the build command help for an example of unpacking a gem, modifying it, then repackaging it. ## gem generate_index Generates the index files for a gem server directory (requires rubygems-generate_index) ### Usage gem generate_index [options] ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Description The generate_index command has been moved to the rubygems-generate_index gem. ## gem help Provide help on the 'gem' command ### Usage gem help ARGUMENT [options] ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ## gem info Show information for the given gem ### Usage gem info GEMNAME [options] ### Options * `-i, --[no-]installed` - Check for installed gem * `-I` - Equivalent to `--no-installed` * `-v, --version VERSION` - Specify version of gem to info for use with `--installed` * `--[no-]versions` - Display only gem names * `-a, --all` - Display all gem versions * `-e, --exact` - Name of gem(s) to query on matches the provided STRING * `--[no-]prerelease` - Display prerelease versions ### Deprecated Options * `-u, --[no-]update-sources` - Update local source cache ### Local/Remote Options * `-l, --local` - Restrict operations to the LOCAL domain * `-r, --remote` - Restrict operations to the REMOTE domain * `-b, --both` - Allow LOCAL and REMOTE operations * `-B, --bulk-threshold COUNT` - Threshold for switching to bulk synchronization (default 1000) * `--clear-sources` - Clear the gem sources * `-s, --source URL` - Append URL to list of remote gem sources * `-p, --[no-]http-proxy [URL]` - Use HTTP proxy for remote operations ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEMNAME* - name of the gem to print information about ### Description Info prints information about the gem such as name, description, website, license and installed paths ## gem install Install a gem into the local repository ### Usage gem install [options] GEMNAME [GEMNAME ...] -- --build-flags [options] ### Options * `--platform PLATFORM` - Specify the platform of gem to install * `-v, --version VERSION` - Specify version of gem to install * `--[no-]prerelease` - Allow prerelease versions of a gem to be installed. (Only for listed gems) ### Deprecated Options * `--default` - Add the gem's full specification to specifications/default and extract only its bin * `-u, --[no-]update-sources` - Update local source cache ### Install/Update Options * `-i, --install-dir DIR` - Gem repository directory to get installed gems * `-n, --bindir DIR` - Directory where executables will be placed when the gem is installed * `-j, --build-jobs VALUE` - Specify the number of jobs to pass to `make` when installing gems with native extensions. Defaults to the number of processors. This option is ignored on the mswin platform or if the MAKEFLAGS environment variable is set. * `--document [TYPES]` - Generate documentation for installed gems List the documentation types you wish to generate. For example: rdoc,ri * `--build-root DIR` - Temporary installation root. Useful for building packages. Do not use this when installing remote gems. * `--vendor` - Install gem into the vendor directory. Only for use by gem repackagers. * `-N, --no-document` - Disable documentation generation * `-E, --[no-]env-shebang` - Rewrite the shebang line on installed scripts to use /usr/bin/env * `-f, --[no-]force` - Force gem to install, bypassing dependency checks * `-w, --[no-]wrappers` - Use bin wrappers for executables Not available on dosish platforms * `-P, --trust-policy POLICY` - Specify gem trust policy * `--ignore-dependencies` - Do not install any required dependent gems * `--[no-]format-executable` - Make installed executable names match Ruby. If Ruby is ruby18, foo_exec will be foo_exec18 * `--[no-]user-install` - Install in user's home directory instead of GEM_HOME. * `--development` - Install additional development dependencies * `--development-all` - Install development dependencies for all gems (including dev deps themselves) * `--conservative` - Don't attempt to upgrade gems already meeting version requirement * `--[no-]minimal-deps` - Don't upgrade any dependencies that already meet version requirements * `--[no-]post-install-message` - Print post install message * `-g, --file [FILE]` - Read from a gem dependencies API file and install the listed gems * `--without GROUPS` - Omit the named groups (comma separated) when installing from a gem dependencies file * `--explain` - Rather than install the gems, indicate which would be installed * `--[no-]lock` - Create a lock file (when used with `-g`/`--file`) * `--[no-]suggestions` - Suggest alternates when gems are not found * `--target-rbconfig [FILE]` - rbconfig.rb for the deployment target platform ### Local/Remote Options * `-l, --local` - Restrict operations to the LOCAL domain * `-r, --remote` - Restrict operations to the REMOTE domain * `-b, --both` - Allow LOCAL and REMOTE operations * `-B, --bulk-threshold COUNT` - Threshold for switching to bulk synchronization (default 1000) * `--clear-sources` - Clear the gem sources * `-s, --source URL` - Append URL to list of remote gem sources * `-p, --[no-]http-proxy [URL]` - Use HTTP proxy for remote operations ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEMNAME* - name of gem to install ### Description The install command installs local or remote gem into a gem repository. For gems with executables ruby installs a wrapper file into the executable directory by default. This can be overridden with the --no-wrappers option. The wrapper allows you to choose among alternate gem versions using _version_. For example `rake _0.7.3_ --version` will run rake version 0.7.3 if a newer version is also installed. Gem Dependency Files ==================== RubyGems can install a consistent set of gems across multiple environments using `gem install -g` when a gem dependencies file (gem.deps.rb, Gemfile or Isolate) is present. If no explicit file is given RubyGems attempts to find one in the current directory. When the RUBYGEMS_GEMDEPS environment variable is set to a gem dependencies file the gems from that file will be activated at startup time. Set it to a specific filename or to "-" to have RubyGems automatically discover the gem dependencies file by walking up from the current directory. NOTE: Enabling automatic discovery on multiuser systems can lead to execution of arbitrary code when used from directories outside your control. Extension Install Failures ========================== If an extension fails to compile during gem installation the gem specification is not written out, but the gem remains unpacked in the repository. You may need to specify the path to the library's headers and libraries to continue. You can do this by adding a -- between RubyGems' options and the extension's build options: $ gem install some_extension_gem [build fails] Gem files will remain installed in \ /path/to/gems/some_extension_gem-1.0 for inspection. Results logged to /path/to/gems/some_extension_gem-1.0/gem_make.out $ gem install some_extension_gem -- --with-extension-lib=/path/to/lib [build succeeds] $ gem list some_extension_gem *** LOCAL GEMS *** some_extension_gem (1.0) $ If you correct the compilation errors by editing the gem files you will need to write the specification by hand. For example: $ gem install some_extension_gem [build fails] Gem files will remain installed in \ /path/to/gems/some_extension_gem-1.0 for inspection. Results logged to /path/to/gems/some_extension_gem-1.0/gem_make.out $ [cd /path/to/gems/some_extension_gem-1.0] $ [edit files or what-have-you and run make] $ gem spec ../../cache/some_extension_gem-1.0.gem --ruby > \ ../../specifications/some_extension_gem-1.0.gemspec $ gem list some_extension_gem *** LOCAL GEMS *** some_extension_gem (1.0) $ Command Alias ========================== You can use `i` command instead of `install`. $ gem i GEMNAME ## gem list Display local gems whose name matches REGEXP ### Usage gem list [REGEXP ...] [options] ### Options * `-i, --[no-]installed` - Check for installed gem * `-I` - Equivalent to `--no-installed` * `-v, --version VERSION` - Specify version of gem to list for use with `--installed` * `-d, --[no-]details` - Display detailed information of gem(s) * `--[no-]versions` - Display only gem names * `-a, --all` - Display all gem versions * `-e, --exact` - Name of gem(s) to query on matches the provided STRING * `--[no-]prerelease` - Display prerelease versions ### Deprecated Options * `-u, --[no-]update-sources` - Update local source cache ### Local/Remote Options * `-l, --local` - Restrict operations to the LOCAL domain * `-r, --remote` - Restrict operations to the REMOTE domain * `-b, --both` - Allow LOCAL and REMOTE operations * `-B, --bulk-threshold COUNT` - Threshold for switching to bulk synchronization (default 1000) * `--clear-sources` - Clear the gem sources * `-s, --source URL` - Append URL to list of remote gem sources * `-p, --[no-]http-proxy [URL]` - Use HTTP proxy for remote operations ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *REGEXP* - regexp to look for in gem name ### Description The list command is used to view the gems you have installed locally. The --details option displays additional details including the summary, the homepage, the author, the locations of different versions of the gem. To search for remote gems use the search command. ## gem lock Generate a lockdown list of gems ### Usage gem lock GEMNAME-VERSION [GEMNAME-VERSION ...] [options] ### Options * `-s, --[no-]strict` - fail if unable to satisfy a dependency ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEMNAME* - name of gem to lock * *VERSION* - version of gem to lock ### Description The lock command will generate a list of +gem+ statements that will lock down the versions for the gem given in the command line. It will specify exact versions in the requirements list to ensure that the gems loaded will always be consistent. A full recursive search of all effected gems will be generated. Example: gem lock rails-1.0.0 > lockdown.rb will produce in lockdown.rb: require "rubygems" gem 'rails', '= 1.0.0' gem 'rake', '= 0.7.0.1' gem 'activesupport', '= 1.2.5' gem 'activerecord', '= 1.13.2' gem 'actionpack', '= 1.11.2' gem 'actionmailer', '= 1.1.5' gem 'actionwebservice', '= 1.0.0' Just load lockdown.rb from your application to ensure that the current versions are loaded. Make sure that lockdown.rb is loaded *before* any other require statements. Notice that rails 1.0.0 only requires that rake 0.6.2 or better be used. Rake-0.7.0.1 is the most recent version installed that satisfies that, so we lock it down to the exact version. ## gem mirror Mirror all gem files (requires rubygems-mirror) ### Usage gem mirror [options] ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Description The mirror command has been moved to the rubygems-mirror gem. ## gem open Open gem sources in editor ### Usage gem open [-e COMMAND] GEMNAME [options] ### Options * `-e, --editor COMMAND` - Prepends COMMAND to gem path. Could be used to specify editor. * `-v, --version VERSION` - Opens specific gem version ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEMNAME* - name of gem to open in editor ### Description The open command opens gem in editor and changes current path to gem's source directory. Editor command can be specified with -e option, otherwise rubygems will look for editor in $EDITOR, $VISUAL and $GEM_EDITOR variables. ## gem outdated Display all gems that need updates ### Usage gem outdated [options] ### Options * `--platform PLATFORM` - Specify the platform of gem to outdated ### Deprecated Options * `-u, --[no-]update-sources` - Update local source cache ### Local/Remote Options * `-l, --local` - Restrict operations to the LOCAL domain * `-r, --remote` - Restrict operations to the REMOTE domain * `-b, --both` - Allow LOCAL and REMOTE operations * `-B, --bulk-threshold COUNT` - Threshold for switching to bulk synchronization (default 1000) * `--clear-sources` - Clear the gem sources * `-s, --source URL` - Append URL to list of remote gem sources * `-p, --[no-]http-proxy [URL]` - Use HTTP proxy for remote operations ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Description The outdated command lists gems you may wish to upgrade to a newer version. You can check for dependency mismatches using the dependency command and update the gems with the update or install commands. ## gem owner Manage gem owners of a gem on the push server ### Usage gem owner GEM [options] ### Options * `-k, --key KEYNAME` - Use the given API key from ~/.local/share/gem/credentials * `--otp CODE` - Digit code for multifactor authentication You can also use the environment variable GEM_HOST_OTP_CODE * `-a, --add NEW_OWNER` - Add an owner by user identifier * `-r, --remove OLD_OWNER` - Remove an owner by user identifier * `--host HOST` - Use another gemcutter-compatible host (e.g. https://rubygems.org) ### Local/Remote Options * `-p, --[no-]http-proxy [URL]` - Use HTTP proxy for remote operations ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEM* - gem to manage owners for ### Description The owner command lets you add and remove owners of a gem on a push server (the default is https://rubygems.org). Multiple owners can be added or removed at the same time, if the flag is given multiple times. The supported user identifiers are dependent on the push server. For rubygems.org, both e-mail and handle are supported, even though the user identifier field is called "email". The owner of a gem has the permission to push new versions, yank existing versions or edit the HTML page of the gem. Be careful of who you give push permission to. ## gem pristine Restores installed gems to pristine condition from files located in the gem cache ### Usage gem pristine [GEMNAME ...] [options] ### Options * `--all` - Restore all installed gems to pristine condition * `--skip=gem_name` - used on `--all`, skip if name == gem_name * `--[no-]extensions` - Restore gems with extensions in addition to regular gems * `--only-missing-extensions` - Only restore gems with missing extensions * `--only-executables` - Only restore executables * `--only-plugins` - Only restore plugins * `-E, --[no-]env-shebang` - Rewrite executables with a shebang of /usr/bin/env * `-i, --install-dir DIR` - Gem repository to get gems restored * `-n, --bindir DIR` - Directory where executables are located * `-v, --version VERSION` - Specify version of gem to restore to pristine condition ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEMNAME* - gem to restore to pristine condition (unless --all) ### Description The pristine command compares an installed gem with the contents of its cached .gem file and restores any files that don't match the cached .gem's copy. If you have made modifications to an installed gem, the pristine command will revert them. All extensions are rebuilt and all bin stubs for the gem are regenerated after checking for modifications. Rebuilding extensions also refreshes C-extension gems against updated system libraries (for example after OS or package upgrades) to avoid mismatches like outdated library version warnings. If the cached gem cannot be found it will be downloaded. If --no-extensions is provided pristine will not attempt to restore a gem with an extension. If --extensions is given (but not --all or gem names) only gems with extensions will be restored. ## gem push Push a gem up to the gem server ### Usage gem push GEM [options] ### Options * `-k, --key KEYNAME` - Use the given API key from ~/.local/share/gem/credentials * `--otp CODE` - Digit code for multifactor authentication You can also use the environment variable GEM_HOST_OTP_CODE * `--host HOST` - Push to another gemcutter-compatible host (e.g. https://rubygems.org) * `--attestation FILE` - Push with sigstore attestations ### Local/Remote Options * `-p, --[no-]http-proxy [URL]` - Use HTTP proxy for remote operations ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEM* - built gem to push up ### Description The push command uploads a gem to the push server (the default is https://rubygems.org) and adds it to the index. The gem can be removed from the index and deleted from the server using the yank command. For further discussion see the help for the yank command. The push command will use ~/.gem/credentials to authenticate to a server, but you can use the RubyGems environment variable GEM_HOST_API_KEY to set the api key to authenticate. ## gem rdoc Generates RDoc for pre-installed gems ### Usage gem rdoc [args] [options] ### Options * `--all` - Generate RDoc/RI documentation for all installed gems * `--[no-]rdoc` - Generate RDoc HTML * `--[no-]ri` - Generate RI data * `--[no-]overwrite` - Overwrite installed documents * `-v, --version VERSION` - Specify version of gem to rdoc ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEMNAME* - gem to generate documentation for (unless --all) ### Description The rdoc command builds documentation for installed gems. By default only documentation is built using rdoc, but additional types of documentation may be built through rubygems plugins and the Gem.post_installs hook. Use --overwrite to force rebuilding of documentation. ## gem rebuild Attempt to reproduce a build of a gem. ### Usage gem rebuild GEM_NAME GEM_VERSION [options] ### Options * `--diff` - If the files don't match, compare them using diffoscope. * `--force` - Skip validation of the spec. * `--strict` - Consider warnings as errors when validating the spec. * `--source GEM_SOURCE` - Specify the source to download the gem from. * `--original GEM_FILE` - Specify a local file to compare against (instead of downloading it). * `--gemspec GEMSPEC_FILE` - Specify the name of the gemspec file. * `-C PATH` - Run as if gem build was started in instead of the current working directory. ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEM_NAME* - gem name on gem server * *GEM_VERSION* - gem version you are attempting to rebuild ### Description The rebuild command allows you to (attempt to) reproduce a build of a gem from a ruby gemspec. This command assumes the gemspec can be built with the `gem build` command. If you use any of `gem build`, `rake build`, or`rake release` in the build/release process for a gem, it is a potential candidate. You will need to match the RubyGems version used, since this is included in the Gem metadata. If the gem includes lockfiles (e.g. Gemfile.lock) and similar, it will require more effort to reproduce a build. For example, it might require more precisely matched versions of Ruby and/or Bundler to be used. ## gem search Display remote gems whose name matches REGEXP ### Usage gem search [REGEXP] [options] ### Options * `-i, --[no-]installed` - Check for installed gem * `-I` - Equivalent to `--no-installed` * `-v, --version VERSION` - Specify version of gem to search for use with `--installed` * `-d, --[no-]details` - Display detailed information of gem(s) * `--[no-]versions` - Display only gem names * `-a, --all` - Display all gem versions * `-e, --exact` - Name of gem(s) to query on matches the provided STRING * `--[no-]prerelease` - Display prerelease versions ### Deprecated Options * `-u, --[no-]update-sources` - Update local source cache ### Local/Remote Options * `-l, --local` - Restrict operations to the LOCAL domain * `-r, --remote` - Restrict operations to the REMOTE domain * `-b, --both` - Allow LOCAL and REMOTE operations * `-B, --bulk-threshold COUNT` - Threshold for switching to bulk synchronization (default 1000) * `--clear-sources` - Clear the gem sources * `-s, --source URL` - Append URL to list of remote gem sources * `-p, --[no-]http-proxy [URL]` - Use HTTP proxy for remote operations ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *REGEXP* - regexp to search for in gem name ### Description The search command displays remote gems whose name matches the given regexp. The --details option displays additional details from the gem but will take a little longer to complete as it must download the information individually from the index. To list local gems use the list command. ## gem server Starts up a web server that hosts the RDoc (requires rubygems-server) ### Usage gem server [options] ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Description The server command has been moved to the rubygems-server gem. ## gem signin Sign in to any gemcutter-compatible host. It defaults to https://rubygems.org ### Usage gem signin [options] ### Options * `--host HOST` - Push to another gemcutter-compatible host * `--otp CODE` - Digit code for multifactor authentication You can also use the environment variable GEM_HOST_OTP_CODE ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Description The signin command executes host sign in for a push server (the default is https://rubygems.org). The host can be provided with the host flag or can be inferred from the provided gem. Host resolution matches the resolution strategy for the push command. ## gem signout Sign out from all the current sessions. ### Usage gem signout [options] ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Description The `signout` command is used to sign out from all current sessions, allowing you to sign in using a different set of credentials. ## gem sources Manage the sources and cache file RubyGems uses to search for gems ### Usage gem sources [options] ### Options * `-a, --add SOURCE_URI` - Add source * `--append SOURCE_URI` - Append source (can be used multiple times) * `--prepend SOURCE_URI` - Prepend source (can be used multiple times) * `-l, --list` - List sources * `-r, --remove SOURCE_URI` - Remove source * `-c, --clear-all` - Remove all sources (clear the cache) * `-u, --update` - Update source cache * `-f, --[no-]force` - Do not show any confirmation prompts and behave as if 'yes' was always answered ### Local/Remote Options * `-p, --[no-]http-proxy [URL]` - Use HTTP proxy for remote operations ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Description RubyGems fetches gems from the sources you have configured (stored in your ~/.gemrc). The default source is https://rubygems.org, but you may have other sources configured. This guide will help you update your sources or configure yourself to use your own gem server. Without any arguments the sources lists your currently configured sources: $ gem sources *** NO CONFIGURED SOURCES, DEFAULT SOURCES LISTED BELOW *** https://rubygems.org This may list multiple sources or non-rubygems sources. You probably configured them before or have an old `~/.gemrc`. If you have sources you do not recognize you should remove them. RubyGems has been configured to serve gems via the following URLs through its history: * http://gems.rubyforge.org (RubyGems 1.3.5 and earlier) * http://rubygems.org (RubyGems 1.3.6 through 1.8.30, and 2.0.0) * https://rubygems.org (RubyGems 2.0.1 and newer) Since all of these sources point to the same set of gems you only need one of them in your list. https://rubygems.org is recommended as it brings the protections of an SSL connection to gem downloads. To add a private gem source use the --prepend argument to insert it before the default source. This is usually the best place for private gem sources: $ gem sources --prepend https://my.private.source https://my.private.source added to sources RubyGems will check to see if gems can be installed from the source given before it is added. To add or move a source after all other sources, use --append: $ gem sources --append https://rubygems.org https://rubygems.org moved to end of sources To remove a source use the --remove argument: $ gem sources --remove https://my.private.source/ https://my.private.source/ removed from sources ## gem specification Display gem specification (in yaml) ### Usage gem specification [GEM_OR_FILE] [FIELD] [options] ### Options * `-v, --version VERSION` - Specify version of gem to examine * `--platform PLATFORM` - Specify the platform of gem to specification * `--[no-]prerelease` - Allow prerelease versions of a gem * `--all` - Output specifications for all versions of the gem * `--ruby` - Output ruby format * `--yaml` - Output YAML format * `--marshal` - Output Marshal format ### Deprecated Options * `-u, --[no-]update-sources` - Update local source cache ### Local/Remote Options * `-l, --local` - Restrict operations to the LOCAL domain * `-r, --remote` - Restrict operations to the REMOTE domain * `-b, --both` - Allow LOCAL and REMOTE operations * `-B, --bulk-threshold COUNT` - Threshold for switching to bulk synchronization (default 1000) * `--clear-sources` - Clear the gem sources * `-s, --source URL` - Append URL to list of remote gem sources * `-p, --[no-]http-proxy [URL]` - Use HTTP proxy for remote operations ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEM_OR_FILE* - gem name or a .gem file to show the gemspec for * *FIELD* - name of gemspec field to show ### Description The specification command allows you to extract the specification from a gem for examination. The specification can be output in YAML, ruby or Marshal formats. Specific fields in the specification can be extracted in YAML format: $ gem spec rake summary --- Ruby based make-like utility. ... ## gem stale List gems along with access times ### Usage gem stale [options] ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Description The stale command lists the latest access time for all the files in your installed gems. You can use this command to discover gems and gem versions you are no longer using. ## gem uninstall Uninstall gems from the local repository ### Usage gem uninstall GEMNAME [GEMNAME ...] [options] ### Options * `-a, --[no-]all` - Uninstall all matching versions * `-I, --[no-]ignore-dependencies` - Ignore dependency requirements while uninstalling * `-D, --[no-]check-development` - Check development dependencies while uninstalling (default: false) * `-x, --[no-]executables` - Uninstall applicable executables without confirmation * `-i, --install-dir DIR` - Directory to uninstall gem from * `-n, --bindir DIR` - Directory to remove executables from * `--[no-]user-install` - Uninstall from user's home directory in addition to GEM_HOME. * `--[no-]format-executable` - Assume executable names match Ruby's prefix and suffix. * `--[no-]force` - Uninstall all versions of the named gems ignoring dependencies * `--[no-]abort-on-dependent` - Prevent uninstalling gems that are depended on by other gems. * `-v, --version VERSION` - Specify version of gem to uninstall * `--platform PLATFORM` - Specify the platform of gem to uninstall * `--vendor` - Uninstall gem from the vendor directory. Only for use by gem repackagers. ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEMNAME* - name of gem to uninstall ### Description The uninstall command removes a previously installed gem. RubyGems will ask for confirmation if you are attempting to uninstall a gem that is a dependency of an existing gem. You can use the --ignore-dependencies option to skip this check. ## gem unpack Unpack an installed gem to the current directory ### Usage gem unpack GEMNAME [options] ### Options * `--target=DIR` - target directory for unpacking * `--spec` - unpack the gem specification * `-v, --version VERSION` - Specify version of gem to unpack ### Install/Update Options * `-P, --trust-policy POLICY` - Specify gem trust policy ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEMNAME* - name of gem to unpack ### Description The unpack command allows you to examine the contents of a gem or modify them to help diagnose a bug. You can add the contents of the unpacked gem to the load path using the RUBYLIB environment variable or -I: $ gem unpack my_gem Unpacked gem: '.../my_gem-1.0' [edit my_gem-1.0/lib/my_gem.rb] $ ruby -Imy_gem-1.0/lib -S other_program You can repackage an unpacked gem using the build command. See the build command help for an example. ## gem update Update installed gems to the latest version ### Usage gem update GEMNAME [GEMNAME ...] [options] ### Options * `--system [VERSION]` - Update the RubyGems system software * `--platform PLATFORM` - Specify the platform of gem to update * `--[no-]prerelease` - Allow prerelease versions of a gem as update targets ### Deprecated Options * `--default` - Add the gem's full specification to specifications/default and extract only its bin * `-u, --[no-]update-sources` - Update local source cache ### Install/Update Options * `-i, --install-dir DIR` - Gem repository directory to get installed gems * `-n, --bindir DIR` - Directory where executables will be placed when the gem is installed * `-j, --build-jobs VALUE` - Specify the number of jobs to pass to `make` when installing gems with native extensions. Defaults to the number of processors. This option is ignored on the mswin platform or if the MAKEFLAGS environment variable is set. * `--document [TYPES]` - Generate documentation for installed gems List the documentation types you wish to generate. For example: rdoc,ri * `--build-root DIR` - Temporary installation root. Useful for building packages. Do not use this when installing remote gems. * `--vendor` - Install gem into the vendor directory. Only for use by gem repackagers. * `-N, --no-document` - Disable documentation generation * `-E, --[no-]env-shebang` - Rewrite the shebang line on installed scripts to use /usr/bin/env * `-f, --[no-]force` - Force gem to install, bypassing dependency checks * `-w, --[no-]wrappers` - Use bin wrappers for executables Not available on dosish platforms * `-P, --trust-policy POLICY` - Specify gem trust policy * `--ignore-dependencies` - Do not install any required dependent gems * `--[no-]format-executable` - Make installed executable names match Ruby. If Ruby is ruby18, foo_exec will be foo_exec18 * `--[no-]user-install` - Install in user's home directory instead of GEM_HOME. * `--development` - Install additional development dependencies * `--development-all` - Install development dependencies for all gems (including dev deps themselves) * `--conservative` - Don't attempt to upgrade gems already meeting version requirement * `--[no-]minimal-deps` - Don't upgrade any dependencies that already meet version requirements * `--[no-]post-install-message` - Print post install message * `-g, --file [FILE]` - Read from a gem dependencies API file and install the listed gems * `--without GROUPS` - Omit the named groups (comma separated) when installing from a gem dependencies file * `--explain` - Rather than install the gems, indicate which would be installed * `--[no-]lock` - Create a lock file (when used with `-g`/`--file`) * `--[no-]suggestions` - Suggest alternates when gems are not found * `--target-rbconfig [FILE]` - rbconfig.rb for the deployment target platform ### Local/Remote Options * `-l, --local` - Restrict operations to the LOCAL domain * `-r, --remote` - Restrict operations to the REMOTE domain * `-b, --both` - Allow LOCAL and REMOTE operations * `-B, --bulk-threshold COUNT` - Threshold for switching to bulk synchronization (default 1000) * `--clear-sources` - Clear the gem sources * `-s, --source URL` - Append URL to list of remote gem sources * `-p, --[no-]http-proxy [URL]` - Use HTTP proxy for remote operations ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEMNAME* - name of gem to update ### Description The update command will update your gems to the latest version. The update command does not remove the previous version. Use the cleanup command to remove old versions. ## gem which Find the location of a library file you can require ### Usage gem which FILE [FILE ...] [options] ### Options * `-a, --[no-]all` - show all matching files * `-g, --[no-]gems-first` - search gems before non-gems ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *FILE* - name of file to find ### Description The which command is like the shell which command and shows you where the file you wish to require lives. You can use the which command to help determine why you are requiring a version you did not expect or to look at the content of a file you are requiring to see why it does not behave as you expect. ## gem yank Remove a pushed gem from the index ### Usage gem yank -v VERSION [-p PLATFORM] [--key KEY_NAME] [--host HOST] GEM [options] ### Options * `-v, --version VERSION` - Specify version of gem to remove * `--platform PLATFORM` - Specify the platform of gem to remove * `--otp CODE` - Digit code for multifactor authentication You can also use the environment variable GEM_HOST_OTP_CODE * `--host HOST` - Yank from another gemcutter-compatible host (e.g. https://rubygems.org) * `-k, --key KEYNAME` - Use the given API key from ~/.local/share/gem/credentials ### Common Options * `-h, --help` - Get help on this command * `-V, --[no-]verbose` - Set the verbose level of output * `-q, --quiet` - Silence command progress meter * `--silent` - Silence RubyGems output * `--config-file FILE` - Use this config file instead of default * `--backtrace` - Show stack backtrace on errors * `--debug` - Turn on Ruby debugging * `--norc` - Avoid loading any .gemrc file ### Arguments * *GEM* - name of gem ### Description The yank command permanently removes a gem you pushed to a server. Once you have pushed a gem several downloads will happen automatically via the webhooks. If you accidentally pushed passwords or other sensitive data you will need to change them immediately and yank your gem. --- # Ruby Directive Source: https://guides.rubygems.org/gemfile_ruby/ ## Specifying a Ruby Version Like gems, developers can setup a dependency on Ruby. This makes your app fail faster in case you depend on specific features in a Ruby VM. This way, the Ruby VM on your deployment server will match your local one. You can do this by using the `ruby` directive in the `Gemfile`: ~~~ruby ruby 'RUBY_VERSION', :engine => 'ENGINE', :engine_version => 'ENGINE_VERSION', :patchlevel => 'RUBY_PATCHLEVEL' ~~~ If you wanted to use JRuby 9.4.10.0 using Ruby 3.1.4, you would simply do the following: ~~~ruby ruby '3.1.4', :engine => 'jruby', :engine_version => '9.4.10.0' ~~~ It's also possible to restrict the patchlevel of the Ruby used by doing the following: ~~~ruby ruby '3.3.6', :patchlevel => '108' ~~~ If you wish to derive your Ruby version from a version file (i.e. `.ruby-version`), you can use the `file` option instead. ~~~ruby ruby file: ".ruby-version" ~~~ The version file should conform to any of the following formats: - `3.1.2` (`.ruby-version`) - `ruby-3.1.2` (`.ruby-version`) - `ruby 3.1.2` ([`.tool-versions`](https://asdf-vm.com/manage/configuration.html#tool-versions)) - `ruby = '3.1.2'` ([`mise.toml`](https://mise.jdx.dev/dev-tools/)) Bundler will make checks against the current running Ruby VM to make sure it matches what is specified in the `Gemfile`. If things don't match, Bundler will raise an Exception explaining what doesn't match. ~~~ Your Ruby version is 3.3.7, but your Gemfile specified 3.4.1 ~~~ Both `:engine` and `:engine_version` are optional. When these options are omitted, this means the app is compatible with a particular Ruby ABI but the engine is irrelevant. When `:engine` is used, `:engine_version` must also be specified. Using the `platform` command with the `--ruby` flag, you can see what `ruby` directive is specified in the `Gemfile`. ~~~ ruby 3.1.4p0 (jruby 9.4.10.0) ~~~ Learn More: bundle platform In the `ruby` directive, `:patchlevel` is optional, as patchlevel releases are usually compatible and include important security fixes. The patchlevel option checks the `RUBY_PATCHLEVEL` constant, and if not specified then bundler will simply ignore it. Version operators for specifying a Ruby version are also available. The set of supported version operators is that of Rubygems (`gem` version operators). (ie. `<`, `>`, `<=`, `>=`, `~>`, `=`) ~~~ruby ruby '~> 3.3.0' ~~~ Learn More: Version Operators --- # Specification Reference Source: https://guides.rubygems.org/specification-reference/

The Specification class contains the information for a gem. Typically defined in a .gemspec file or a Rakefile, and looks like this:

Gem::Specification.new do |s|
  s.name        = 'example'
  s.version     = '0.1.0'
  s.licenses    = ['MIT']
  s.summary     = "This is an example!"
  s.description = "Much longer explanation of the example!"
  s.authors     = ["Ruby Coder"]
  s.email       = 'rubycoder@example.com'
  s.files       = ["lib/example.rb"]
  s.homepage    = 'https://rubygems.org/gems/example'
  s.metadata    = { "source_code_uri" => "https://github.com/example/example" }
end

Starting in RubyGems 2.0, a Specification can hold arbitrary metadata. See metadata for restrictions on the format and size of metadata items you may add to a specification.

Specifications must be deterministic, as in the example above. For instance, you cannot define attributes conditionally:

# INVALID: do not do this.
unless RUBY_ENGINE == "jruby"
  s.extensions << "ext/example/extconf.rb"
end
## Required gemspec attributes * [authors=](#authors=) * [files](#files) * [name](#name) * [summary](#summary) * [version](#version) ## Recommended gemspec attributes * [description](#description) * [email](#email) * [homepage](#homepage) * [license=](#license=) * [licenses=](#licenses=) * [metadata](#metadata) * [required_ruby_version](#required_ruby_version) ## Read-only attributes * [extensions_dir](#extensions_dir) * [rubygems_version](#rubygems_version) ## Optional gemspec attributes * [add_dependency](#add_dependency) * [add_development_dependency](#add_development_dependency) * [author=](#author=) * [bindir](#bindir) * [cert_chain](#cert_chain) * [executables](#executables) * [extensions](#extensions) * [extra_rdoc_files](#extra_rdoc_files) * [platform=](#platform=) * [post_install_message](#post_install_message) * [rdoc_options](#rdoc_options) * [require_paths=](#require_paths=) * [required_ruby_version=](#required_ruby_version=) * [required_rubygems_version](#required_rubygems_version) * [required_rubygems_version=](#required_rubygems_version=) * [requirements](#requirements) * [signing_key](#signing_key) # Required gemspec attributes ## authors=(`value`)

A list of authors for this gem.

Alternatively, a single author can be specified by assigning a string to spec.author

Usage:

spec.authors = ['John Jones', 'Mary Smith']
## files

Files included in this gem. You cannot append to this accessor, you must assign to it.

Only add files you can require to this list, not directories, etc.

Directories are automatically stripped from this list when building a gem, other non-files cause an error.

Usage:

require 'rake'
spec.files = FileList['lib/**/*.rb',
                      'bin/*',
                      '[A-Z]*'].to_a

# or without Rake...
spec.files = Dir['lib/**/*.rb'] + Dir['bin/*']
spec.files += Dir['[A-Z]*']
spec.files.reject! { |fn| fn.include? "CVS" }
## name

This gem’s name.

Usage:

spec.name = 'rake'
## summary

A short summary of this gem’s description. Displayed in gem list -d.

The description should be more detailed than the summary.

Usage:

spec.summary = "This is a small summary of my gem"
## version

This gem’s version.

The version string can contain numbers and periods, such as 1.0.0. A gem is a ‘prerelease’ gem if the version has a letter in it, such as 1.0.0.pre.

Usage:

spec.version = '0.4.1'
# Recommended gemspec attributes ## description

A long description of this gem

The description should be more detailed than the summary but not excessively long. A few paragraphs is a recommended length with no examples or formatting.

Usage:

spec.description = <<~EOF
  Rake is a Make-like program implemented in Ruby. Tasks and
  dependencies are specified in standard Ruby syntax.
EOF
## email

A contact email address (or addresses) for this gem

Usage:

spec.email = 'john.jones@example.com'
spec.email = ['jack@example.com', 'jill@example.com']
## homepage

The URL of this gem’s home page

Usage:

spec.homepage = 'https://github.com/ruby/rake'
## license=(`o`)

The license for this gem.

The license must be no more than 64 characters, and should be a single SPDX license identifier from spdx.org/licenses/. Ideally, you should pick one that is OSI (Open Source Initiative) opensource.org/licenses/ approved.

The most commonly used OSI-approved licenses are MIT and Apache-2.0. GitHub also provides a license picker at choosealicense.com/.

The full text of the license should be inside of the gem (at the top level) when you build it.

RubyGems validates the license against the SPDX license list when you run gem build and warns about unknown or deprecated identifiers. An identifier may carry a trailing + (this version or any later version) and a license exception joined with WITH, for example Apache-2.0 WITH LLVM-exception.

Compound SPDX license expressions such as MIT OR Apache-2.0 are not currently supported. RubyGems treats the whole string as a single identifier and warns that it is invalid. For a gem available under more than one license, set each license as a separate entry with licenses=.

For a license that has no SPDX identifier, use Nonstandard, or LicenseRef-<idstring> where idstring is the name of the file containing the license text.

You should specify a license for your gem so that people know how they are permitted to use it and any restrictions you’re placing on it. Not specifying a license means all rights are reserved; others have no right to use the code for any purpose.

Usage:

spec.license = 'MIT'
## licenses=(`licenses`)

The license(s) for the library.

Each entry must be a single SPDX license identifier, no more than 64 characters. Entries are validated independently, so a compound expression such as MIT OR Apache-2.0 is not valid as an entry. Listing the identifiers as separate array elements is currently the only way RubyGems supports declaring a dual- or multi-licensed gem.

Note that the array itself does not state how the licenses combine. Include the full text of each license in the gem and describe the exact terms there.

See license= for more discussion

Usage:

spec.licenses = ['MIT', 'GPL-2.0-only']
## metadata

The metadata holds extra data for this gem that may be useful to other consumers and is settable by gem authors.

Metadata items have the following restrictions:

  • The metadata must be a Hash object

  • All keys and values must be Strings

  • Keys can be a maximum of 128 bytes and values can be a maximum of 1024 bytes

  • All strings must be UTF-8, no binary data is allowed

You can use metadata to specify links to your gem’s homepage, codebase, documentation, wiki, mailing list, issue tracker and changelog.

s.metadata = {
  "bug_tracker_uri"   => "https://example.com/user/bestgemever/issues",
  "changelog_uri"     => "https://example.com/user/bestgemever/CHANGELOG.md",
  "documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1",
  "homepage_uri"      => "https://bestgemever.example.io",
  "mailing_list_uri"  => "https://groups.example.com/bestgemever",
  "source_code_uri"   => "https://example.com/user/bestgemever",
  "wiki_uri"          => "https://example.com/user/bestgemever/wiki",
  "funding_uri"       => "https://example.com/donate"
}

These links will be used on your gem’s page on rubygems.org and must pass validation against following regex.

%r{\Ahttps?:\/\/([^\s:@]+:[^\s:@]*@)?[A-Za-z\d\-]+(\.[A-Za-z\d\-]+)+\.?(:\d{1,5})?([\/?]\S*)?\z}
## required_ruby_version

The version of Ruby required by this gem

Usage:

spec.required_ruby_version = '>= 2.7.0'
# Read-only attributes ## extensions_dir

The path where this gem installs its extensions.

## rubygems_version

The version of RubyGems used to create this gem.

# Optional gemspec attributes ## add_dependency(`gem`, `*requirements`)

Adds a runtime dependency named gem with requirements to this gem.

Usage:

spec.add_dependency 'example', '>= 1.1.4', '< 2'
Also known as: **add_runtime_dependency** ## add_development_dependency(`gem`, `*requirements`)

Adds a development dependency named gem with requirements to this gem.

Usage:

spec.add_development_dependency 'example', '>= 1.1.4', '< 2'

Development dependencies aren’t installed by default and aren’t activated when a gem is required.

## author=(`o`)

Singular (alternative) writer for authors

Usage:

spec.author = 'John Jones'
## bindir

The path in the gem for executable scripts. Usually ‘exe’

Usage:

spec.bindir = 'exe'
## cert_chain

The certificate chain used to sign this gem. See Gem::Security for details.

## executables

Executables included in the gem.

For example, the rake gem has rake as an executable. You don’t specify the full path (as in bin/rake); all application-style files are expected to be found in bindir. These files must be executable Ruby files. Files that use bash or other interpreters will not work.

Executables included may only be ruby scripts, not scripts for other languages or compiled binaries.

Usage:

spec.executables << 'rake'
## extensions

Extensions to build when installing the gem, specifically the paths to extconf.rb-style files used to compile extensions.

These files will be run when the gem is installed, causing the C (or whatever) code to be compiled on the user’s machine.

Usage:

spec.extensions << 'ext/rmagic/extconf.rb'

See Gem::Ext::Builder for information about writing extensions for gems.

## extra_rdoc_files

Extra files to add to RDoc such as README or doc/examples.txt

When the user elects to generate the RDoc documentation for a gem (typically at install time), all the library files are sent to RDoc for processing. This option allows you to have some non-code files included for a more complete set of documentation.

Usage:

spec.extra_rdoc_files = ['README', 'doc/user-guide.txt']
## platform=(`platform`)

The platform this gem runs on.

This is usually Gem::Platform::RUBY or Gem::Platform::CURRENT.

Most gems contain pure Ruby code; they should simply leave the default value in place. Some gems contain C (or other) code to be compiled into a Ruby “extension”. The gem should leave the default value in place unless the code will only compile on a certain type of system. Some gems consist of pre-compiled code (“binary gems”). It’s especially important that they set the platform attribute appropriately. A shortcut is to set the platform to Gem::Platform::CURRENT, which will cause the gem builder to set the platform to the appropriate value for the system on which the build is being performed.

If this attribute is set to a non-default value, it will be included in the filename of the gem when it is built such as: nokogiri-1.6.0-x86-mingw32.gem

Usage:

spec.platform = Gem::Platform.local
## post_install_message

A message that gets displayed after the gem is installed.

Usage:

spec.post_install_message = "Thanks for installing!"
## rdoc_options

Specifies the rdoc options to be used when generating API documentation.

Usage:

spec.rdoc_options << '--title' << 'Rake -- Ruby Make' <<
  '--main' << 'README' <<
  '--line-numbers'
## require_paths=(`val`)

Paths in the gem to add to $LOAD_PATH when this gem is activated. If you have an extension you do not need to add "ext" to the require path, the extension build process will copy the extension files into “lib” for you.

The default value is "lib"

Usage:

# If all library files are in the root directory...
spec.require_paths = ['.']
## required_ruby_version=(`req`)

The version of Ruby required by this gem. The ruby version can be specified to the patch-level:

$ ruby -v -e 'p Gem.ruby_version'
ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin12.4.0]
#<Gem::Version "2.0.0.247">

Prereleases can also be specified.

Usage:

# This gem will work with 1.8.6 or greater...
spec.required_ruby_version = '>= 1.8.6'

# Only with final releases of major version 2 where minor version is at least 3
spec.required_ruby_version = '~> 2.3'

# Only prereleases or final releases after 2.6.0.preview2
spec.required_ruby_version = '> 2.6.0.preview2'

# This gem will work with 2.3.0 or greater, including major version 3, but lesser than 4.0.0
spec.required_ruby_version = '>= 2.3', '< 4'
## required_rubygems_version

The RubyGems version required by this gem

## required_rubygems_version=(`req`)

The RubyGems version required by this gem

## requirements

Lists the external (to RubyGems) requirements that must be met for this gem to work. It’s simply information for the user.

Usage:

spec.requirements << 'libmagick, v6.0'
spec.requirements << 'A good graphics card'
## signing_key

The key used to sign this gem. See Gem::Security for details.

--- # RubyGems.org API Source: https://guides.rubygems.org/rubygems-org-api/ Details on interacting with RubyGems.org over HTTP. Most endpoints are under API v1. API v2 covers lookups scoped to one specific gem version. > NOTE: The API is a work in progress, and [can use your help!](https://github.com/rubygems/rubygems.org) > RubyGems itself and the > [RubyGems gem](https://github.com/rubygems/rubygems) use the API to push gems, > add owners, and more. * [API Authorization](#api-authorization): How to authenticate with RubyGems.org * [Rate Limits](#rate-limits) * [Gem Methods](#gem-methods): Query or create gems to be hosted * [Gem Version Methods](#gem-version-methods): Query for information about versions of a particular gem * [Gem Download Methods](#gem-download-methods): Query for download statistics * [Owner Methods](#owner-methods): Manage owners for gems * [Profile Methods](#profile-methods): Query for user information * [Webhook Methods](#webhook-methods): Manage notifications for when gems are pushed * [Activity Methods](#activity-methods): Query for information about site-wide activity * [Misc Methods](#misc-methods): Various other interactions with the site API Authorization ----------------- Some API calls require an Authorization header. To create or view existing API keys, click on your username when logged in to [RubyGems.org](https://rubygems.org), 'Settings', and then 'API Keys'. Here's an example of using an API key: $ curl -H 'Authorization:YOUR_API_KEY' \ https://rubygems.org/api/v1/some_api_call.json If you are using Multi-factor authentication, you will need to provide one-time passcode in the `OTP` header. Here's an example of using your API key with a OTP: $ curl -H 'Authorization:YOUR_API_KEY' \ -H 'OTP:YOUR_ONE_TIME_PASSCODE' \ https://rubygems.org/api/v1/some_api_call.json Each key carries a set of scopes, and a call fails if the key lacks the scope it needs. Pushing a gem, for example, requires `push_rubygem`. See [API key scopes](/api-key-scopes) for the full list. Ruby Library ------------ You can also interact with RubyGems.org using Ruby. The [gems](https://rubygems.org/gems/gems) client provides a Ruby interface to all the resources listed below. This library has [full documentation](https://rubydoc.info/gems/gems) that includes some basic usage examples in the README. You can install the library with the command: gem install gems Rate Limits ----------- Please see [RubyGems.org ratelimits](/rubygems-org-rate-limits) Gem Methods ----------- ### GET - `/api/v1/gems/[GEM NAME].(json|yaml)` Returns some basic information about the given gem. See below an example response for the gem "rails" in JSON format: $ curl https://rubygems.org/api/v1/gems/rails.json { "name": "rails", "downloads": 769153204, "version": "8.1.3.1", "version_created_at": "2026-07-29T15:02:41.060Z", "version_downloads": 78333, "platform": "ruby", "authors": "David Heinemeier Hansson", "info": "Ruby on Rails is a full-stack web framework optimized for programmer happiness and sustainable productivity.", "licenses": ["MIT"], "metadata": { "changelog_uri": "https://github.com/rails/rails/releases/tag/v8.1.3.1", "bug_tracker_uri": "https://github.com/rails/rails/issues", "source_code_uri": "https://github.com/rails/rails/tree/v8.1.3.1", "rubygems_mfa_required": "true" }, "yanked": false, "sha": "ccd11a36bfc171bf9c66d585d14c0ece91c0c9dde840aae60c0118d6f5c9c52a", "spec_sha": "5b60af49df6edf722925a85d144f1118abda22485a820da2c516e97cab8347b8", "project_uri": "https://rubygems.org/gems/rails", "gem_uri": "https://rubygems.org/gems/rails-8.1.3.1.gem", "homepage_uri": "https://rubyonrails.org", "wiki_uri": null, "documentation_uri": "https://api.rubyonrails.org/v8.1.3.1/", "mailing_list_uri": "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri": "https://github.com/rails/rails/tree/v8.1.3.1", "bug_tracker_uri": "https://github.com/rails/rails/issues", "changelog_uri": "https://github.com/rails/rails/releases/tag/v8.1.3.1", "funding_uri": null, "dependencies": { "development": [], "runtime": [ { "name": "actioncable", "requirements": "= 8.1.3.1" }, { "name": "actionmailbox", "requirements": "= 8.1.3.1" }, { "name": "actionmailer", "requirements": "= 8.1.3.1" }, ... ] } } ### GET - `/api/v1/search.(json|yaml)?query=[YOUR QUERY]` Submit a search to RubyGems.org for active gems, just like a search query on the site. Returns an array of the JSON or YAML representation of gems that match. $ curl 'https://rubygems.org/api/v1/search.json?query=cucumber' $ curl 'https://rubygems.org/api/v1/search.yaml?query=cucumber' The results are paginated so the API call will return only the first 30 matched gems. To get subsequent results, use the page query parameter until an empty response is received. $ curl 'https://rubygems.org/api/v1/search.json?query=cucumber&page=2' ### GET - `/api/v1/search/autocomplete?query=[YOUR QUERY]` Returns an array of gem names matching the query, for populating a search box. $ curl 'https://rubygems.org/api/v1/search/autocomplete?query=nokogiri' ["nokogiri","nokogiri-diff","nokogiri-happymapper","nokogiri-styles", ...] ### GET - `/api/v1/gems.(json|yaml)` List all gems that you own. Returns an array of the JSON or YAML representation of gems you own. $ curl -H 'Authorization:rubygems_b9ce70c306b3a2e248679fbbbd66722d408d3c8c4f00566c' \ https://rubygems.org/api/v1/gems.json ### POST - `/api/v1/gems` Submit a gem to RubyGems.org. Must post a built RubyGem in the request body. $ curl --data-binary @gemcutter-0.2.1.gem \ -H 'Authorization:rubygems_b9ce70c306b3a2e248679fbbbd66722d408d3c8c4f00566c' \ https://rubygems.org/api/v1/gems Successfully registered gem: gemcutter (0.2.1) ### DELETE - `/api/v1/gems/yank` Remove a gem from RubyGems.org's index. Platform is optional. $ curl -X DELETE -H 'Authorization:rubygems_b9ce70c306b3a2e248679fbbbd66722d408d3c8c4f00566c' \ -d 'gem_name=bills' -d 'version=0.0.1' \ -d 'platform=x86-darwin-10' \ https://rubygems.org/api/v1/gems/yank Successfully deleted gem: bills (0.0.1) ### GET - `/api/v1/gems/[GEM NAME]/reverse_dependencies.json` List dependants of the specified gem. This is all the dependants whose latest version depend on the particular gem. Returns an array that includes names of the dependant gems. Pass `only=runtime` or `only=development` to restrict the result to that dependency type. Both types are returned by default. $ curl https://rubygems.org/api/v1/gems/shoulda/reverse_dependencies.json [ "jeweler", "rubigen", "verhoeff", "vanilla", "soup", ... ] Gem Version Methods ------------------- ### GET - `/api/v1/versions/[GEM NAME].(json|yaml)` Returns an array of gem version details like the below: $ curl https://rubygems.org/api/v1/versions/coulda.json [ { "authors": "Evan David Light", "built_at": "2011-08-08T04:00:00.000Z", "created_at": "2011-08-08T21:23:40.254Z", "description": "Behaviour Driven Development derived from Cucumber but as an internal DSL with methods for reuse", "downloads_count": 9676, "metadata": { "homepage_uri": "http://coulda.tiggerpalace.com" }, "number": "0.7.1", "summary": "Test::Unit-based acceptance testing DSL", "platform": "ruby", "rubygems_version": ">= 0", "ruby_version": null, "prerelease": false, "licenses": null, "requirements": null, "sha": "777c3a7ed83e44198b0a624976ec99822eb6f4a44bf1513eafbc7c13997cd86c", "spec_sha": "57b863cff56029a0085eaf1b3416b701ed4fa75418d062358b45753e270c9ffa" } ] ### GET - `/api/v1/versions/[GEM NAME]/latest.json` Returns an object containing the latest version of particular gem. $ curl https://rubygems.org/api/v1/versions/rails/latest.json { "version": "4.2.1" } ### GET - `/api/v2/rubygems/[GEM NAME]/versions/[VERSION NUMBER].(json|yaml)` (API v2) Returns a dictionary with versions details for a specific gem version. To return the version for a specific platform (e.g. "ruby", "java", "x86_64-linux"), use the `platform` query parameter. $ curl https://rubygems.org/api/v2/rubygems/coulda/versions/0.7.1.json { "name": "coulda", "downloads": 101713, "version": "0.7.1", "version_created_at": "2011-08-08T21:23:40.254Z", "version_downloads": 9676, "platform": "ruby", "authors": "Evan David Light", "info": "Behaviour Driven Development derived from Cucumber but as an internal DSL with methods for reuse", "licenses": null, "metadata": { "homepage_uri": "http://coulda.tiggerpalace.com" }, "yanked": false, "sha": "777c3a7ed83e44198b0a624976ec99822eb6f4a44bf1513eafbc7c13997cd86c", "spec_sha": "57b863cff56029a0085eaf1b3416b701ed4fa75418d062358b45753e270c9ffa", "project_uri": "https://rubygems.org/gems/coulda", "gem_uri": "https://rubygems.org/gems/coulda-0.7.1.gem", "homepage_uri": "http://coulda.tiggerpalace.com", "wiki_uri": null, "documentation_uri": null, "mailing_list_uri": null, "source_code_uri": null, "bug_tracker_uri": null, "changelog_uri": null, "funding_uri": null, "dependencies": { "development": [], "runtime": [ { "name": "yourdsl", "requirements": "~> 0.7" } ] }, "built_at": "2011-08-08T04:00:00.000Z", "created_at": "2011-08-08T21:23:40.254Z", "description": "Behaviour Driven Development derived from Cucumber but as an internal DSL with methods for reuse", "downloads_count": 9676, "number": "0.7.1", "summary": "Test::Unit-based acceptance testing DSL", "rubygems_version": ">= 0", "ruby_version": null, "prerelease": false, "requirements": null } ### GET - `/api/v2/rubygems/[GEM NAME]/versions/[VERSION NUMBER]/contents.(json|yaml|sha256)` (API v2) Returns the checksum of every file packaged in a specific gem version. The `platform` query parameter selects a non-default platform, as above. Only versions pushed after RubyGems.org started recording file manifests have this data. Older versions respond `404` with "Content is unavailable for this version." $ curl https://rubygems.org/api/v2/rubygems/rails/versions/8.1.3.1/contents.json { "MIT-LICENSE": { "sha256": "717ba1949502290f8e47688ae2e323acd06c8ca47aec9f7596b15f678c1af4a2" }, "README.md": { "sha256": "293a6407fb786e32297e2ac50f216affe95779ab182fc64ec764dece160a4f80" } } The `sha256` format returns the same data as a shasum file instead: $ curl https://rubygems.org/api/v2/rubygems/rails/versions/8.1.3.1/contents.sha256 717ba1949502290f8e47688ae2e323acd06c8ca47aec9f7596b15f678c1af4a2 MIT-LICENSE 293a6407fb786e32297e2ac50f216affe95779ab182fc64ec764dece160a4f80 README.md ### GET - `/api/v1/attestations/[GEM NAME]-[VERSION].json` Returns the [sigstore](/trusted-publishing) attestations published with a gem version, as an array of sigstore bundles. Versions pushed without attestations return an empty array. $ curl https://rubygems.org/api/v1/attestations/rails-8.1.3.1.json [ { "mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "messageSignature": { ... }, "verificationMaterial": { ... } } ] ### GET - `/api/v1/timeframe_versions.json` Returns an array of gem versions that were created within the timeframe specified by the timestamp parameters. An iso8601 timestamp parameter named `from` is required. This is the time from which you'd like to start querying. You may include an iso8601 timestamp parameter named `to`. If present, only the versions created within `from` and `to` will be returned. If `to` is not given, all versions created between `from` and the current time will be returned. NOTE: The timeframe you specify with `from` and `to` cannot exceed a 7 day span. The results are paginated so the API call will return only the first 30 versions in your timeframe. To get subsequent results, use the page query parameter until an empty response is received. Example response: $ curl 'https://rubygems.org/api/v1/timeframe_versions.json?from=2019-01-18T21:24:29Z&to=2019-01-18T21:24:31Z [{ "name": "rails", "downloads": 158094751, "version": "6.0.0.beta1", "version_downloads": 677, "platform": "ruby", "authors": "David Heinemeier Hansson", "info": "Ruby on Rails is a full-stack web framework optimized for programmer happiness and sustainable productivity. It encourages beautiful code by favoring convention over configuration.", "licenses": ["MIT"], "metadata": {}, "sha": "f70cc2e606eafd6c3fd1d7e15f015d6a3e5626d34724ba5c0114922a8eb864b8", "project_uri": "http://localhost/gems/rails", "gem_uri": "http://localhost/gems/rails-6.0.0.beta1.gem", "homepage_uri": "http://rubyonrails.org", "wiki_uri": "", "documentation_uri": "http://api.rubyonrails.org", "mailing_list_uri": "http://groups.google.com/group/rubyonrails-talk", "source_code_uri": "http://github.com/rails/rails", "bug_tracker_uri": "http://github.com/rails/rails/issues", "changelog_uri": null, "dependencies": { "development": [], "runtime": [{ "name": "actioncable", "requirements": "= 6.0.0.beta1" }, { "name": "actionmailbox", "requirements": "= 6.0.0.beta1" }, { "name": "actionmailer", "requirements": "= 6.0.0.beta1" }, { "name": "actionpack", "requirements": "= 6.0.0.beta1" }, { "name": "actiontext", "requirements": "= 6.0.0.beta1" }, { "name": "actionview", "requirements": "= 6.0.0.beta1" }, { "name": "activejob", "requirements": "= 6.0.0.beta1" }, { "name": "activemodel", "requirements": "= 6.0.0.beta1" }, { "name": "activerecord", "requirements": "= 6.0.0.beta1" }, { "name": "activestorage", "requirements": "= 6.0.0.beta1" }, { "name": "activesupport", "requirements": "= 6.0.0.beta1" }, { "name": "bundler", "requirements": "\u003e= 1.3.0" }, { "name": "railties", "requirements": "= 6.0.0.beta1" }, { "name": "sprockets-rails", "requirements": "\u003e= 2.0.0" }] }, "built_at": "2019-01-18T00:00:00.000Z", "created_at": "2019-01-18T21:24:30.197Z", "description": "Ruby on Rails is a full-stack web framework optimized for programmer happiness and sustainable productivity. It encourages beautiful code by favoring convention over configuration.", "downloads_count": 677, "number": "6.0.0.beta1", "summary": "Full-stack web application framework.", "rubygems_version": "\u003e= 1.8.11", "ruby_version": "\u003e= 2.5.0", "prerelease": true, "requirements": [] }] Gem Download Methods -------------------- ### GET - `/api/v1/downloads.(json|yaml)` Returns an object containing the total number of downloads on RubyGems. $ curl https://rubygems.org/api/v1/downloads.json { "total": 461672727 } ### GET - `/api/v1/downloads/[GEM NAME]-[GEM VERSION].(json|yaml)` Returns an object containing the total number of downloads for a particular gem as well as the total number of downloads for the specified version. $ curl https://rubygems.org/api/v1/downloads/rails_admin-0.0.0.json { "version_downloads": 3142, "total_downloads": 3142 } ### GET - `/api/v1/downloads/all.(json|yaml)` Returns the 50 most downloaded gem versions, each as a pair of the version record and its download count. $ curl https://rubygems.org/api/v1/downloads/all.json { "gems": [ [{ "number": "1.6.2", "full_name": "jmespath-1.6.2", ... }, 648386198], ... ] } Owner Methods ------------- ### GET - `/api/v1/owners/[USER HANDLE|USER ID]/gems.(json|yaml)` View all gems for a user. This is all the gems a user can push to. Owner gems list can be requested with both user handle or user id. $ curl https://rubygems.org/api/v1/owners/qrush/gems.json [ { "name": "factory_bot", ... }, ... ] ### GET - `/api/v1/gems/[GEM NAME]/owners.(json|yaml)` View all owners of a gem. These users can all push to this gem. `role` is either `owner` or `maintainer`. `email` appears only for users who have made their email address public. $ curl https://rubygems.org/api/v1/gems/gemcutter/owners.json [ { "id": 1, "handle": "qrush", "email": "nick@quaran.to", "role": "owner" }, { "id": 7644, "handle": "gemcutter", "role": "owner" } ] ### POST - `/api/v1/gems/[GEM NAME]/owners` Add an owner to a RubyGem you own, giving that user permission to manage it. See [Owner & Maintainer Roles](/managing-owners-using-ui#owner--maintainer-roles) for more details on roles. The new owner is added unconfirmed. Ownership access begins once they click the confirmation link mailed to them. $ curl -H 'Authorization:rubygems_b9ce70c306b3a2e248679fbbbd66722d408d3c8c4f00566c' \ -F 'email=josh@technicalpickles.com&role=owner' \ https://rubygems.org/api/v1/gems/gemcutter/owners techpickles was added as an unconfirmed owner. Ownership access will be enabled after the user clicks on the confirmation mail sent to their email. ### DELETE - `/api/v1/gems/[GEM NAME]/owners` Remove a user's permission to manage a RubyGem you own. $ curl -X DELETE -H 'Authorization:rubygems_b9ce70c306b3a2e248679fbbbd66722d408d3c8c4f00566c' \ -d "email=josh@technicalpickles.com" \ https://rubygems.org/api/v1/gems/gemcutter/owners Owner removed successfully. ### PATCH - `/api/v1/gems/[GEM NAME]/owners` Update an existing owner's role for a RubyGem you own. See [Owner & Maintainer Roles](/managing-owners-using-ui/#owner--maintainer-roles) for more details on roles. $ curl -X PATCH -H 'Authorization:rubygems_b9ce70c306b3a2e248679fbbbd66722d408d3c8c4f00566c' \ -d "email=josh@technicalpickles.com&role=maintainer" \ https://rubygems.org/api/v1/gems/gemcutter/owners Owner updated successfully. Profile Methods ------------- ### GET - `/api/v1/profiles/[USER HANDLE|USER ID].(json|yaml)` View basic user info for a user. `email` appears only if the user has made their email address public. $ curl https://rubygems.org/api/v1/profiles/qrush { "id": 1, "handle": "qrush", "email": "nick@quaran.to" } The same user can be requested by id: $ curl https://rubygems.org/api/v1/profiles/1 ### GET - `/api/v1/profile/me.(json|yaml)` View basic user information for your account, including Multi-factor authentication status. Requires username and password to be passed. `mfa` is one of `disabled`, `ui_only`, `ui_and_api` or `ui_and_gem_signin`. A `warning` key is present when the account's MFA level is below the recommended one. $ curl -u "nick@gemcutter.org:schwwwwing" \ https://rubygems.org/api/v1/profile/me { "id": 1, "handle": "qrush", "email": "nick@quaran.to", "mfa": "ui_and_api" } WebHook Methods --------------- ### GET - `/api/v1/web_hooks.(json|yaml)` List the webhooks registered under your account. $ curl -H 'Authorization:rubygems_b9ce70c306b3a2e248679fbbbd66722d408d3c8c4f00566c' \ https://rubygems.org/api/v1/web_hooks.json { "all gems": [ { "url": "http://gemwhisperer.heroku.com", "failure_count": 1 } ], "rails": [ { "url": "http://example.com", "failure_count": 0 } ] } ### POST - `/api/v1/web_hooks` Create a webhook. Requires two parameters: `gem_name` and `url`. Specify `*` for the `gem_name` parameter to apply the hook globally to all gems. $ curl -X POST -H 'Authorization:rubygems_b9ce70c306b3a2e248679fbbbd66722d408d3c8c4f00566c' \ -F 'gem_name=rails' -F 'url=http://example.com' \ https://rubygems.org/api/v1/web_hooks Successfully created webhook for rails to http://example.com $ curl -X POST -H 'Authorization:rubygems_b9ce70c306b3a2e248679fbbbd66722d408d3c8c4f00566c' \ -F 'gem_name=*' -F 'url=http://example.com' \ https://rubygems.org/api/v1/web_hooks Successfully created webhook for all gems to http://example.com ### DELETE - `/api/v1/web_hooks/remove` Remove a webhook. Requires two parameters: `gem_name` and `url`. Specify `*` for the `gem_name` parameter to apply the hook globally to all gems. $ curl -X DELETE -H 'Authorization:rubygems_b9ce70c306b3a2e248679fbbbd66722d408d3c8c4f00566c' \ -d 'gem_name=rails' -d 'url=http://example.com' \ https://rubygems.org/api/v1/web_hooks/remove Successfully removed webhook for rails to http://example.com $ curl -X DELETE -H 'Authorization:rubygems_b9ce70c306b3a2e248679fbbbd66722d408d3c8c4f00566c' \ -d 'gem_name=*' -d 'url=http://example.com' \ https://rubygems.org/api/v1/web_hooks/remove Successfully removed webhook for all gems to http://example.com ### POST - `/api/v1/web_hooks/fire` Test fire a webhook. This can be used to test out an endpoint at any time, for example when you're developing your application. Requires two parameters: `gem_name` and `url`. Specify `*` for the gem_name parameter to apply the hook globally to all gems. An `Authorization` header is included with every fired webhook so you can be sure the request came from RubyGems.org. The value of the header is the SHA2-hashed concatenation of the gem name, the gem version and your API key. $ curl -H 'Authorization:rubygems_b9ce70c306b3a2e248679fbbbd66722d408d3c8c4f00566c' \ -F 'gem_name=rails' -F 'url=http://example.com' \ https://rubygems.org/api/v1/web_hooks/fire Successfully deployed webhook for rails to http://example.com $ curl -H 'Authorization:rubygems_b9ce70c306b3a2e248679fbbbd66722d408d3c8c4f00566c' \ -F 'gem_name=*' -F 'url=http://example.com' \ https://rubygems.org/api/v1/web_hooks/fire Successfully deployed webhook for all gems to http://example.com Activity Methods ------------ ### GET - `/api/v1/activity/latest` Pulls the 50 gems most recently added to RubyGems.org (for the first time). Returns an array of the JSON or YAML representation of the gems. $ curl 'https://rubygems.org/api/v1/activity/latest.json' ### GET - `/api/v1/activity/just_updated` Pulls the 50 most recently updated gems. Returns an array of the JSON or YAML representation of the gem versions. $ curl 'https://rubygems.org/api/v1/activity/just_updated.json' Misc Methods ------------ ### POST - `/api/v1/api_key.(json|yaml)` Create a new API key using HTTP basic auth, and return it. Keys are stored hashed, so this response is the only chance to read the key. Accepts `name`, the scopes to enable (see [API key scopes](/api-key-scopes)), and optionally `expires_at`, `rubygem_name` to scope the key to a single gem, and `mfa` to require an OTP when the key is used. $ curl -X POST -u "nick@gemcutter.org:schwwwwing" \ -d 'name=ci-push' -d 'push_rubygem=true' \ https://rubygems.org/api/v1/api_key.json { "rubygems_api_key": "rubygems_701243f217cdf23b1370c7b66b65ca97", "status": "ok" } ### PATCH - `/api/v1/api_key` Update the scopes of an existing key, passed as the `api_key` parameter. $ curl -X PATCH -u "nick@gemcutter.org:schwwwwing" \ -d 'api_key=rubygems_701243f217cdf23b1370c7b66b65ca97' \ -d 'yank_rubygem=true' \ https://rubygems.org/api/v1/api_key Scopes for the API key ci-push updated > NOTE: `GET /api/v1/api_key`, which `gem signin` used to call, has been retired > and now responds `410 Gone`. Create keys with the request above or on the > [API keys page](https://rubygems.org/profile/api_keys). ### POST - `/api/v1/oidc/trusted_publisher/exchange_token` Exchange an OIDC ID token for a RubyGems API key. This endpoint is intended to be used by the [`release-gem`](https://github.com/rubygems/release-gem) GitHub Action for [trusted publishing](/trusted-publishing#releasing-gems-with-a-trusted-publisher). The request body must be a JSON object with a single key, `jwt`, whose value is the ID token (as a string). $ curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" \ -d '{"jwt": $ID_TOKEN}' \ https://rubygems.org/api/v1/oidc/trusted_publisher/exchange_token" { "rubygems_api_key": "rubygems_701243f217cdf23b1370c7b66b65ca97", "name": "GitHub Actions rubygems/configure-rubygems-credentials @ .github/workflows/token.yml", "scopes": ["push_rubygem"], "expires_at": "2021-01-01T00:00:00Z" } --- # RubyGems.org Compact Index API Source: https://guides.rubygems.org/rubygems-org-compact-index-api/ Details of the Compact Index API used for Bundler dependency resolution Compact Index API ----------------- The Compact Index API is considered a stable public API. The primary index file is the `versions` file, which provides the name, versions and the MD5 checksum of each rubygem `info` file. If you need to collect all info about all rubygems, please use the [public data dumps](https://rubygems.org/pages/data) of the rubygems.org database. ### Fetching and Caching Example Response (with some headers ignored): $ curl -I https://rubygems.org/info/bundler HTTP/2 200 last-modified: Fri, 22 Mar 2024 13:09:59 GMT etag: "40148273a7c7cd16b49d00a9935fd445" cache-control: max-age=60, public content-type: text/plain; charset=utf-8 repr-digest: sha-256="pf7Ts7NTRac//JxO9ke3IYbcWx8kcVn9N0mbm5EJpP0=" accept-ranges: bytes All compact index endpoints support ETags with the `If-None-Match` header. If-None-Match: "40148273a7c7cd16b49d00a9935fd445" The compact index is designed to be fetched using the HTTP `Range` header. When a previously fetched copy is present, a ranged request to take advantage of the appended line pattern. Range: bytes=#{range_start}- Responses from the `/versions` and `/info/[GEM]` endpoints will include the `Repr-Digest` header. The digests will have at least the SHA256 checksum of the entire file whether the response includes the full file or a partial response. *Please note that a `Digest` header is present, but it is deprecated and may be removed without notice.* When the Range header is satisfied, append the contents at exactly the starting byte, then compute the SHA256 checksum of the resulting file. If the result matches the `Repr-Digest` header's SHA256 checksum, the file is considered complete and up-to-date. Each line in the `/versions` file includes the latest MD5 calculation of the matching `/info` file for that rubygem at the time the line was written. The latest MD5, closest to the end of the file, will match the MD5 of the up-to-date `/info` file. Exact implementation details are available in the [Bundler CompactIndexClient::Updater](https://github.com/ruby/rubygems/blob/master/lib/bundler/compact_index_client/updater.rb). ### GET - `/versions` Returns a custom text based format containing information about all versions of all rubygems. This API endpoint is intended to be a compact index of all possible rubygem versions. When new rubygems or rubygems versions are added or when a rubygem is yanked, it is added to the end of the file using the format detailed below. The file is append only during the month which improves caching performance. It is recalculated at the start of each month, removing yanked rubygems and compressing new versions into one line for each rubygem. *Warning: this is a big file. Example is truncated.* $ curl https://rubygems.org/versions created_at: 2024-04-01T00:00:05Z --- - 1 05d0116933ba44b0b5d0ee19bfd35ccc -A 0.0.0 8b1527991f0022e46140907a7fc4cfd4 .cat 0.0.1 631fd60a806eaf5026c86fff3155c289 .omghi 1,2 7a67c0434100c2ab635b9f4865ee86bd 0mq 0.1.0,0.1.1,0.1.2,0.2.0,0.2.1,0.3.0,0.4.0,0.4.1,0.5.0,0.5.1,0.5.2,0.5.3 6146193f8f7e944156b0b42ec37bad3e [...SNIP...] active_model_serializers -0.9.10 7ad37af4aec8cc089e409e1fdec86f3d active_model_serializers 0.9.11 a6d40e97b289ee6c806e5e9f7031623b openapi_first 1.4.1 40fbfdebcbfee3863df697e1d641f637 #### `versions` File Format The format of the `versions` file uses one line per rubygem at computation time, with additional lines appended to the end that may include new or yanked versions of a rubygem already present earlier in the file. The lines preceeding `---` should be considered opaque metadata. created_at: 2024-04-01T00:00:05Z --- Each following line gives information about 1 rubygem with the format: RUBYGEM [-]VERSION_PLATFORM[,VERSION_PLATFORM],...] MD5 The parts of this line are as follows: 1. **`RUBYGEM`** - The name of the rubygem. 2. **`(SPACE)`** - The space character. 3. **`[(MINUS)]`** - (optional) The `-` (minus) character. Only present if the version following it has been yanked since the `versions` file was last recalculated. 4. **`VERSION_PLATFORM`** - A rubygem VERSION wich may include the PLATFORM. This combined format is described in more detail in the `info` file format section. 5. **`[(COMMA)VERSION]`** - (optional) A `,` (comma) character, indicating that another VERSION will follow. Read comma delimited VERSION chunks until a space is encountered. 6. **`(SPACE)`** - The space character. 7. **`MD5`** - The MD5 of the rubygem "info" file, described below. Only the *last* MD5 for a gem name in the `versions` file should be considered accurate for the related info file. For more detail, see [the parser in Bundler](https://github.com/rubygems/rubygems/blob/master/lib/rubygems/resolver/api_set/gem_parser.rb). ### GET - `/info/` Returns a custom text based format for the single rubygem named by `` with a line for each version of the rubygem. *Example is truncated.* $ curl https://rubygems.org/info/rails --- 2.2.2 actionmailer:= 2.2.2,actionpack:= 2.2.2,activerecord:= 2.2.2,activeresource:= 2.2.2,activesupport:= 2.2.2,rake:>= 0.8.3|checksum:84fd0ee92f92088cff81d1a4bcb61306bd4b7440b8634d7ac3d1396571a2133f 2.3.2 actionmailer:= 2.3.2,actionpack:= 2.3.2,activerecord:= 2.3.2,activeresource:= 2.3.2,activesupport:= 2.3.2,rake:>= 0.8.3|checksum:ac61e0356987df34dbbafb803b98f153a663d3878a31f1db7333b7cd987fd044 2.0.5 actionmailer:= 2.0.5,actionpack:= 2.0.5,activerecord:= 2.0.5,activeresource:= 2.0.5,activesupport:= 2.0.5,rake:>= 0.7.2|checksum:5e8a6e36f2537b795b7bb237e2aea18a166349e1e54e463a64beba5ae84cd406 [...SNIP...] 7.0.8.1 actioncable:= 7.0.8.1,actionmailbox:= 7.0.8.1,actionmailer:= 7.0.8.1,actionpack:= 7.0.8.1,actiontext:= 7.0.8.1,actionview:= 7.0.8.1,activejob:= 7.0.8.1,activemodel:= 7.0.8.1,activerecord:= 7.0.8.1,activestorage:= 7.0.8.1,activesupport:= 7.0.8.1,bundler:>= 1.15.0,railties:= 7.0.8.1|checksum:7deb37884ac5e9afeaeb6ad503c56e819f68e53746d621b2187322f874ba2ded,ruby:>= 2.7.0,rubygems:>= 1.8.11 7.1.3.1 actioncable:= 7.1.3.1,actionmailbox:= 7.1.3.1,actionmailer:= 7.1.3.1,actionpack:= 7.1.3.1,actiontext:= 7.1.3.1,actionview:= 7.1.3.1,activejob:= 7.1.3.1,activemodel:= 7.1.3.1,activerecord:= 7.1.3.1,activestorage:= 7.1.3.1,activesupport:= 7.1.3.1,bundler:>= 1.15.0,railties:= 7.1.3.1|checksum:73aa0775e7dc698cebad542de2eea6d5b62957290e6a23a96e915281df36f026,ruby:>= 2.7.0,rubygems:>= 1.8.11 7.1.3.2 actioncable:= 7.1.3.2,actionmailbox:= 7.1.3.2,actionmailer:= 7.1.3.2,actionpack:= 7.1.3.2,actiontext:= 7.1.3.2,actionview:= 7.1.3.2,activejob:= 7.1.3.2,activemodel:= 7.1.3.2,activerecord:= 7.1.3.2,activestorage:= 7.1.3.2,activesupport:= 7.1.3.2,bundler:>= 1.15.0,railties:= 7.1.3.2|checksum:2d787a65e87b70ee65f9d1cb644aaa5bb80eea12298982f474da949772c1bfa0,ruby:>= 2.7.0,rubygems:>= 1.8.11 #### `info` File Format The format of the `info` file uses one line per version. When a new version is added, additional lines are appended to the end of the file. When a version is yanked, the `info` file is recalculated. The file will never list a version as yanked. It will only be excluded from the file. Any lines preceeding `---` should be considered opaque. --- Each following line gives information about 1 version of a rubygem with the format: VERSION[-PLATFORM] [DEPENDENCY[,DEPENDENCY,...]]|REQUIREMENT[,REQUIREMENT,...] The pieces of each line are: 1. **`VERSION`** - The version of the rubygem. Read VERSION until either `-` (minus) or space character is encountered. 2. **`[-PLATFORM]`** - The platform, if it is not the default platform `ruby`. The first `-` (minus) character in the `VERSION[-PLATFORM]` chunk splits the VERSION and PLATFORM. The PLATFORM may contain more dashes. Read platform until a space is encountered. 3. **`(SPACE)`** - The space character. 4. **`[DEPENDENCY]`** - (optional) A dependency is another rubygem required by this gem. DEPENDENCY may contain spaces. See below for format. 5. **`[(COMMA)DEPENDENCY]`** - (optional) A `,` (comma) character, indicating that another DEPENDENCY will follow. Read comma delimited DEPENCENCY chunks until the `|` (pipe) character is encountered. 6. **`(PIPE)`** - The `|` (pipe) character. 7. **`REQUIREMENT`** - Additional requirements for the rubygem, which always includes at least the SHA256 checksum. REQUIREMENT may contain spaces. See below for format. 8. **`[(COMMA)REQUIREMENT]`** - (optional) A `,` (comma) character, indicating that another REQUIREMENT will follow. Read comma delimited REQUIREMENT chunks until the end of the line. **`DEPENCENCY` Format** Examples: actionmailer:= 2.2.2 parser:>= 3.2.2.3 rainbow:< 4.0 unicode-display_width:< 3.0&>= 2.4.0 rack:~> 1.0 tilt:!= 1.3.0&~> 1.1 Format: GEM:CONSTRAINT[&CONSTRAINT] 1. **`RUBYGEM`** - The rubygem depended on. 2. **`(COLON)`** - The `:` (colon) character. 3. **`CONSRAINT`** - A version constraint. An OPERATOR in `[=, >, <, >=, <=, ~>, !=]` then an (optional) space character, then a VERSION. 4. **`[(AMPERSAND)CONSTRAINT]`** - A `&` (ampersand) character, indicating that an additional CONSTRAINT follows relating to the same GEM. Read ampersand delimited CONSTRAINT chunks until the `,` (comma) character is encountered. **`REQUIREMENT` Format** The REQUIREMENT chunk will always contain the `checksum` key. The `ruby` and `rubygems` keys are like a CONSTRAINT above, indicating a required ruby or rubygems version. The `created_at` key was added in version 2 of the format, described in the Format Versions section below. The `checksum` is the SHA256 checksum of the `GEM-VERSION-PLATFORM.gem` file originally uploaded to rubygems.org. The SHA256 computed from the matching downloaded `.gem` file must match this checksum or the `.gem` must be considered corrupted. Examples: checksum:2c4af8d4a65ac5290445bfe7582be4490162d6934f49d76858b55647b4c4428d ruby:< 3.3.dev&>= 2.7 rubygems:>= 1.8.11 created_at:2009-07-25T18:02:12Z Format: KEY:VALUE 1. **`KEY`** - An alphanumeric key. 2. **`(COLON)`** - A `:` (colon) character. 3. **`VALUE`** - The value of the key. The VALUE must not contain `,` (comma) or `:` (colon) characters. ### GET - `/names` Returns a custom text based format of all rubygem names, with one rubygem name per line. *The API is not currently used by any official rubygems tools. The order may be subject to change. Example is truncated.* $ curl https://rubygems.org/names --- _ - 0mq 0xdm5 [...SNIP...] #### `names` File Format The format of the `names` file is a simple newline delimited list of rubygem names. Any lines preceeding `---` should be considered opaque. --- Each following line consists only of a rubygem name: RUBYGEM The parts of this line are as follows: 1. **`RUBYGEM`** - The name of the rubygem. ### Format Versions The compact index format has two versions. rubygems.org serves version 2. There is no version negotiation. The endpoints above always serve the current format, and clients cannot request an older format with an `Accept` header or a separate URL. The only difference between v1 and v2 is an additional `created_at` REQUIREMENT at the end of each line in the `info` file, giving the UTC time at which that version was published: 1.0.0 |checksum:b1147fd2991884dfbac9b101b0c88a0f0fc71abbd1bd24fb29cde3fdfc8ebd77,created_at:2009-07-25T18:02:12Z Because a REQUIREMENT is a generic `KEY:VALUE` pair, clients written for v1 can read v2 files by ignoring the unknown key. Adding `created_at` changed the MD5 checksum of every `info` file, so the `versions` file was recalculated when rubygems.org switched to v2, and cached clients picked up the changed files through the mechanism described in Fetching and Caching above. The per-version `created_at` timestamp is the metadata that [Bundler's cooldown feature](/cooldown) relies on to exclude recently published versions from dependency resolution. rubygems.org backfilled `created_at` for versions published before the switch, so every line includes it. Versions without a `created_at` value, such as those served by a gem server that only emits the v1 format, are treated as outside the cooldown window and remain resolvable. Cooldown therefore offers no protection for those sources. --- # RubyGems.org rate limits Source: https://guides.rubygems.org/rubygems-org-rate-limits/ Why are you seeing 429 responses? Load balancer rate limits ---- To protect the RubyGems.org service from abuse, both intentionally and unintentionally, we have rate limits in place for some of our endpoints. Some endpoints may be cached by our CDN at times and therefore, _may_ allow higher request rates. The following is a general guideline for the rate limit rules. * API and website: 10 requests per second * Dependency API: 15 requests per second Application rate limits ---- We use [rack-attack](https://github.com/kickstarter/rack-attack) for throttling clients attempting brute force on login, signup, and MFA endpoints. Additionally, we rate limit endpoints which send email to prevent abuse of our paid email service. When you have hit one of the application rate limits, you will see `Retry-After` header in the response with seconds until the rate limit resets. Unless mentioned, all rate limits are on client IP. ## Endpoints with 100 requests/10 minutes rate limit * User sign in - `POST /session` * User sign up - `POST /users` * Password reset request - `POST /passwords` * Profile update - `PATCH /profile` * Profile delete - `DELETE /profile` * Email confirmation request - `POST /email_confirmations` ## Rate limits with exponential backoff It is not possible to brute force your MFA code in a single time window. However, an attacker's chance of successfully guessing the code at least once increases when the brute force is attempted over an extended period. You can read more about this [here](https://security.stackexchange.com/a/185917) and check our calculation of the backoff period [here](https://github.com/rubygems/rubygems.org/pull/2330#issuecomment-643931531). Following endpoints have rate limits of **300 requests/5 minutes** and **600 requests/25 hours**: * OTP verification on sign in - `POST /session/mfa_create` * OTP verification on password reset - `POST /users/:user_id/password/mfa_edit` * Registering a new MFA device - `POST /multifactor_auth` * Updating or disabling MFA level - `PUT /multifactor_auth` * Yanking a gem - `DELETE /api/v1/gems/yank` * Adding an owner - `POST /api/v1/gems/:rubygem_id/owners` * Removing owner - `DELETE /api/v1/gems/:rubygem_id/owners` * Show API key (`gem signin`) - `GET /api/v1/api_key` ## Gem push rate limit `POST /api/v1/gems` has following two rate limits: * 400 requests/1 hour * 300 requests/5 minutes and 600 requests/25 hours on *failed requests* (response status not equal to 200). ## Miscellaneous rate limits * 10 request/10 minutes on gem yank - `DELETE /api/v1/gems/yank` * 100 request/10 minutes/email or username on sign in - `POST /session` * 100 request/10 minutes/email or username on API key show - `GET /api/v1/api_key` * 10 request/10 minutes/email on password reset request - `POST /passwords` * 10 request/10 minutes/email on email confirmation request - `POST /email_confirmations` The RubyGems.org team may occasionally blackhole user IP addresses for extreme cases to protect the platform. If you think this has happened to you, please email to [support@rubygems.org](mailto:support@rubygems.org), and we'll be happy to look at it. --- # API key scopes Source: https://guides.rubygems.org/api-key-scopes/ RubyGems.org API keys, their scopes, and CLI usage You can create multiple API keys based on your requirements. API keys have varying scopes that grant specific privileges. Using API keys with the least amount of privilege makes your RubyGems.org account more secure by limiting the impact a compromised key may have. Create a new API key ----------------------- Visit your RubyGems.org account [settings page](https://rubygems.org/settings/edit) and click on **API KEYS**. You will be prompted for your account password to confirm your identity. ![Settings API key](/images/settings-api-key.png){:class="t-img"} If you have never visited this page before, you should see at least one key with the name *legacy-key*. The *legacy-key* is relic of the time when RubyGems.org used to have a single API key per account with full access. We recommend that you [migrate away from *legacy-key*](#migration-from-legacy-api-key) as soon as possible. Click on **New API Key** to create a new API key for your account. ![Settings API key](/images/api-keys-index.png){:class="t-img"} Enter a name to help you identify the environment the API key may be used in (eg: ci-push-key, mirror-webhook-key, etc.). Check all the scopes you may want to enable. You can also optionally set an [expiration date](#set-an-expiration-date) for the key. Click create when done. **Note:** *Show dashboard* is an exclusive scope, and it can't be enabled in combination with any other scope. ![New API key](/images/new-api-key.png){:class="t-img"} On the following page, you should see the new API key. ![API key created](/images/api-key-created.png){:class="t-img"} The *Age* column shows how old the key is, the *Expiration* column shows when the key will expire (if an expiration was set), and the *Last access* column shows the last time (in UTC) the key was used in a successful authentication. You can use the **Edit** button to update the scopes of the key. You can use the **Reset** button in the last row to delete *all* the API keys associated with your account. Usage with gem CLI ------------------ An API key created as outlined above can be used in the `gem` CLI directly by setting it in an environment variable called `GEM_HOST_API_KEY`, e.g. $ GEM_HOST_API_KEY=rubygems_123456 gem push example-1.2.3.gem This approach is suitable for non-interactive situations, e.g. for CI/CD-based gem publishing processes. On a personal development machine that you can directly access, the interactive sign-in using `gem signin` (see below) is usually preferrable. Creating from gem CLI --------------------- **Note:** You need rubygems 3.2.0 or newer if you like to create API keys with scopes from the gem CLI. Running `gem signin` will prompt you for your RubyGems.org credentials, key name, and scopes to enable for the key. The default choice for all scopes is not to enable them. $ gem signin Enter your RubyGems.org credentials. Don't have an account yet? Create one at https://rubygems.org/sign_up Email: john@doe.com Password: API Key name [4458ffe32b0c-unknown-user-20201231104303]: docker-push-key Please select scopes you want to enable for the API key (y/n) index_rubygems [y/N]: push_rubygem [y/N]: Y yank_rubygem [y/N]: add_owner [y/N]: remove_owner [y/N]: access_webhooks [y/N]: show_dashboard [y/N]: Signed in with API key: docker-push-key. An API key will automatically be created (default key name: *hostname-whoami-timestamp*) with the required scope when we couldn't find any API key on your host. Similarly, the scope of the existing API key on the host will be updated with the required scope if the key didn't have the correct scope. $ gem yank begone -v 4.1.48 Yanking gem from https://rubygems.org... The existing key doesn't have access of yank_rubygem on https://rubygems.org. Please sign in to update access. Email: john@doe.com Password: Added yank_rubygem scope to the existing API key Successfully deleted gem: begone (4.1.48) API key scopes -------------- * [Index rubygems](/rubygems-org-api/#get---apiv1gemsjsonyaml): List all RubyGems of your account * [Push rubygems](/rubygems-org-api/#post---apiv1gems): Create a new RubyGem or publish a new version of any RubyGem you own * [Yank rubygems](/rubygems-org-api/#delete---apiv1gemsyank): Remove a published version of any RubyGem you own * [Add owner](/rubygems-org-api/#post---apiv1gemsgem-nameowners): Add a user to owners of any RubyGem you own * [Remove owner](/rubygems-org-api/#delete---apiv1gemsgem-nameowners): Remove a user from owners of any RubyGem you own * [Access webhooks](/rubygems-org-api/#webhook-methods): List, create, delete or fire webhooks associated with your account * [Show dashboard](https://rubygems.org/dashboard): Access to atom feed of your RubyGems.org dashboard. It is an exclusive scope and can't be enabled with any other scope. Scope an API key to a gem ------------------------- Enabling one or more of the key scopes related to creating or updating a gem ([Push rubygems](/rubygems-org-api/#post---apiv1gems), [Yank rubygems](/rubygems-org-api/#delete---apiv1gemsyank), [Add owner](/rubygems-org-api/#post---apiv1gemsgem-nameowners), and [Remove owner](/rubygems-org-api/#delete---apiv1gemsgem-nameowners)) will allow you to scope one of your gems to the API key. The operations corresponding to these scopes will only be valid on the selected gem. ![New API key with gem scope](/images/new-api-key-gem-scope.png){:class="t-img"} If you are using a key to modify only one of your gems, please consider gem scoping your keys. **Note:** When your ownership to a gem is removed, API keys scoped to that gem will become invalid and cannot be used. Set an expiration date ----------------------- When creating an API key, we highly recommend you set an **expiration date** using the expiration field on the form. Once the expiration date passes, the key becomes invalid and can no longer be used for authentication. ![New API key with expiration](/images/new-api-key-expiration.png){:class="t-img"} Setting an expiration is useful for temporary access to make changes, such as pushing a gem, adding or removing ownership, or other one-off operations. The expiration must be set to at least 5 minutes in the future. If no expiration is set, the key will remain valid indefinitely (until manually deleted or reset). **Note:** The expiration date cannot be changed after the key is created. If you need a key with a different expiration, create a new one. Enable MFA on specific API keys ----------------------------- If your account has MFA enabled on the **UI and gem signin** [authentication level](/setting-up-multifactor-authentication/#authentication-levels), you have the option to enable MFA on a specific API key. This will require an OTP code for `gem push`, `yank`, `owner --add/--remove` commands. You can toggle this option when creating or editing an API key on the UI. ![New API key with MFA enabled](/images/new-mfa-api-key.png){:class="t-img"} Migration from legacy-api key ----------------------------- The legacy API key of your account has been migrated to one with all scopes enabled. We strongly recommend that you delete this key and replace it with a new API key with minimum scopes enabled. * Visit [API keys page](https://rubygems.org/profile/api_keys) of your account and click on **delete** button for the key named *legacy-key*. * Run `gem signout` on all hosts where you have used the legacy API key * Make sure you have rubygems 3.2.0 or newer installed. Run `gem update --system` to update your rubygem to the latest release. * Run `gem signin` to create a new API key. If it is not possible for you to update your rubygems, you can still use the new API key by creating a new key using the web UI and replacing the key in `~/.gem/credentials` or `~/.local/share/gem/credentials` file. $ cat ~/.local/share/gem/credentials :rubygems_api_key: rubygems_cec9db9373ea171daaaa0bf2337edce187f09558cb19c1b2 **Note:** The legacy endpoint to fetch API keys, `GET /api/v1/api_key`, has been retired and now responds `410 Gone`. Use [`POST /api/v1/api_key`](/rubygems-org-api#post---apiv1api_keyjsonyaml) to create a key instead. As a security precaution, API keys are stored in our database after one-way encryption. It is no longer possible for us to fetch the same API key in plain text. --- # Bundler compatibility with Ruby Source: https://guides.rubygems.org/bundler-compatibility/ ## Bundler compatibility with Ruby & RubyGems Bundler and RubyGems are developed in the same repository, [ruby/rubygems](https://github.com/ruby/rubygems), and every release ships them as a matching pair. Starting with the 4.0 series they share the same version number. Each Ruby release also bundles a matching pair, for example Ruby 4.0 ships RubyGems 4.0 and Bundler 4.0. The latest Bundler release supports, at the very least, all Ruby versions that have not yet reached their End of Life date. Its minimum RubyGems version is the RubyGems that shipped with the oldest supported Ruby. RubyGems cannot be downgraded below the version a Ruby shipped with, so any supported Ruby satisfies both requirements out of the box. The currently supported and recent Bundler series require: | Bundler | Ruby | RubyGems | | ------- | ---- | -------- | | 4.0 | >= 3.2.0 | >= 3.4.1 | | 2.7 | >= 3.2.0 | >= 3.4.1 | | 2.6 | >= 3.1.0 | >= 3.3.3 | | 2.5 | >= 3.0.0 | >= 3.2.3 | Older series have reached their End of Life. If you need the exact requirements of an old release, check its version page on [rubygems.org](https://rubygems.org/gems/bundler), which lists the required Ruby and RubyGems versions. In practice you rarely choose a Bundler version by hand. A project's `Gemfile.lock` records the version that created it under `BUNDLED WITH`, and Bundler automatically switches to that version when you run it. See [Installing Bundler](/installation) for details. --- # Configuration (.gemrc) Source: https://guides.rubygems.org/configuration/ Where the `gem` command reads its configuration, and the options a `.gemrc` file accepts. The `gem` command works fine with no configuration at all. A gemrc file exists to change defaults you would otherwise repeat on every invocation, such as disabling documentation generation or adding a private gem server. ## Files and precedence RubyGems merges configuration from several places. Later entries override earlier ones: 1. Defaults set by the operating system packager and the Ruby implementation. 2. The system-wide file, `gemrc` in the system configuration directory, typically `/etc/gemrc`. 3. The user file, `~/.gemrc`. When that file does not exist, RubyGems reads `$XDG_CONFIG_HOME/gem/gemrc` instead, which is usually `~/.config/gem/gemrc`. 4. Files listed in the `GEMRC` environment variable, separated by `:` on Unix and `;` on Windows. `gem --config-file FILE` reads a specific file in place of the user file, and `gem --norc` ignores gemrc files entirely. ## Format A gemrc file is a YAML hash with two kinds of keys. Symbol keys, written with a leading colon, set RubyGems options. String keys naming a gem command set default command-line arguments for that command, and the special key `gem` sets default arguments for every command. ```yaml :sources: - https://rubygems.org/ :backtrace: true :concurrent_downloads: 16 install: --no-document update: --no-document ``` With this file, `gem install rails` behaves as if you had typed `gem install rails --no-document`. Arguments given on the command line are appended after the defaults. ## Options These are the symbol keys RubyGems understands, with their built-in defaults. | Key | Description | |-----|-------------| | `:sources` | Array of gem server URLs that gems are installed from. Default: `https://rubygems.org/`. | | `:backtrace` | Print a full backtrace when the gem command hits an error. Default: `true`. | | `:verbose` | Output level. `false` is quiet, `true` is normal, and any other value such as `:really` enables extra output. Default: `true`. | | `:update_sources` | Update repository metadata automatically. Default: `true`. | | `:concurrent_downloads` | Number of gem downloads performed in parallel. Default: `8`. | | `:cert_expiration_length_days` | Validity period, in days, of certificates created or re-signed by `gem cert`. Default: `365`. | | `:install_extension_in_lib` | Install built extensions into the gem's `lib` directory as well as the extension directory. Default: `true`. | | `:ipv4_fallback_enabled` | Experimental. Fall back to IPv4 when IPv6 is unreachable or slow. Default: `false`. | | `:global_gem_cache` | Cache downloaded `.gem` files in one directory shared across all Ruby installations, `~/.cache/gem/gems` by default. Default: `false`. | | `:use_psych` | Parse gemrc and other RubyGems YAML files with Psych instead of the built-in minimal YAML parser. Default: `false`. | | `:prevent_update_suggestion` | Never suggest running `gem update --system` when a newer RubyGems is available. | | `:disable_default_gem_server` | Require an explicit `--host` when pushing gems instead of defaulting to RubyGems.org. | | `:gemhome` | The directory gems are installed into. More commonly set with the `GEM_HOME` environment variable. | | `:gempath` | Array of directories searched for installed gems. More commonly set with the `GEM_PATH` environment variable. | | `:ssl_verify_mode` | OpenSSL verification mode for HTTPS connections to gem servers. | | `:ssl_ca_cert` | Path to a CA certificate file or directory used for HTTPS connections. | | `:ssl_client_cert` | Path to a client certificate used for HTTPS connections that require client authentication. | API keys for pushing gems are not stored in gemrc. They live in a separate credentials file, `~/.gem/credentials`. See [API key scopes](/api-key-scopes) for how keys are created and scoped. Bundler is configured separately through `bundle config`, and its settings do not come from gemrc. See [bundle config](/command-reference/bundle-config/). --- # Environment variables Source: https://guides.rubygems.org/environment-variables/ The environment variables the `gem` command and the RubyGems runtime respond to. None of these are required. They override defaults per shell or per process, which makes them useful in CI, in version manager hooks, and for one-off experiments. Persistent preferences belong in a gemrc file instead. See [Configuration](/configuration). ## Paths | Variable | Description | |----------|-------------| | `GEM_HOME` | The directory gems are installed into. See [Where gems are installed and how they load](/gem-installation-and-loading). | | `GEM_PATH` | Directories searched for installed gems, separated by `:` on Unix and `;` on Windows. | | `GEM_SPEC_CACHE` | The directory where gem specifications fetched from remote sources are cached. Defaults to `~/.gem/specs`, or to `$XDG_CACHE_HOME/gem/specs` when `~/.gem/specs` does not exist. | | `GEMRC` | Additional gemrc files to read, separated by `:` on Unix and `;` on Windows. See [Configuration](/configuration). | ## Loading gems | Variable | Description | |----------|-------------| | `RUBYGEMS_GEMDEPS` | Path to a gem dependencies file (`Gemfile`, `gem.deps.rb`, or `Isolate`) whose gems RubyGems activates automatically at startup. The special value `-` searches the current directory and its parents for one. Automatic discovery can execute code from a directory you do not control, so avoid `-` on multiuser systems. | | `GEM_REQUIREMENT_` | A version requirement applied when RubyGems activates the gem ``, uppercased. For example, `GEM_REQUIREMENT_BUNDLER="~> 2.7"` restricts which Bundler version is activated. | ## Building and pushing gems | Variable | Description | |----------|-------------| | `SOURCE_DATE_EPOCH` | A Unix timestamp used instead of the current time when packaging a gem, so that building the same input twice produces byte-identical `.gem` files. | | `RUBYGEMS_HOST` | The gem server that `gem push` sends gems to when no `--host` is given. | | `GEM_HOST_API_KEY` | An API key used to authenticate against the gem server instead of the key stored in `~/.gem/credentials`. | | `GEM_HOST_OTP_CODE` | A one-time password for pushing when the account has multi-factor authentication enabled. Equivalent to `--otp`. | | `GEM_PRIVATE_KEY_PASSPHRASE` | The passphrase of the private signing key, read by `gem cert` and when building signed gems instead of prompting for it. | ## Network | Variable | Description | |----------|-------------| | `HTTP_PROXY`, `HTTP_PROXY_USER`, `HTTP_PROXY_PASS` | The proxy server, and credentials for it, used for connections to gem servers. | | `NO_PROXY` | Hosts that are connected to directly, bypassing the proxy. | ## Other | Variable | Description | |----------|-------------| | `RUBYGEMS_PREVENT_UPDATE_SUGGESTION` | When set, the gem command never suggests running `gem update --system` after noticing a newer RubyGems release. | ## Bundler Bundler variables are not listed here. Every setting understood by `bundle config` can also be set through a corresponding `BUNDLE_*` environment variable, for example `BUNDLE_PATH` or `BUNDLE_WITHOUT`. See [bundle config](/command-reference/bundle-config/). --- # Known Plugins Source: https://guides.rubygems.org/bundler_known_plugins/ - [bootboot](https://github.com/shopify/bootboot) - Dualbooting your ruby app made easy. - [bundler-as_of](https://github.com/flavorjones/bundler-as_of) - Resolve gem dependencies as-of a date in the past. - [bundler-changelogs](https://github.com/jdar/bundler-changelogs) - A bundler plugin that shows changelogs of your gem dependencies that specify changelog urls [not yet filtered to git version updates]. - [bundler-commentate](https://gitlab.com/fjc/bundler-commentate) - Bundler plugin to add gem summaries to a Gemfile - [bundler-console](https://github.com/kddnewton/bundler-console) - A bundler plugin that starts a console session with your gem dependencies. - [bundler-ctags_generator](https://github.com/okuramasafumi/bundler-ctags_generator) - Provides a hook after gem installation to generate ctags - [bundler-dependency_graph](https://github.com/kerrizor/bundler-dependency_graph) - Generate a visual representation of your gem dependencies. - [bundler-download](http://github.com/AndyObtiva/bundler-download) - bundler-download is a Bundler plugin for auto-downloading specified extra files on `bundle install` - [bundler-ecology](https://github.com/eco-rb/bundler-ecology) - Bundler plugin to avoid installing unwanted gems - [bundler-graph](https://github.com/rubygems/bundler-graph) - Generates a visual dependency graph for your Gemfile - [bundler-inject](https://github.com/ManageIQ/bundler-inject) - A bundler plugin that allows extension of a project with personal and overridden gems - [bundler-install_dash_docs](https://github.com/e28eta/bundler-install_dash_docs) - Bundler plugin to install gem documentation into the macOS documentation browser Dash https://kapeli.com/dash - [bundler-licensed](https://github.com/sergey-alekseev/bundler-licensed) - A bundler hook for https://github.com/github/licensed - [bundler-mac](https://github.com/indirect/bundler-mac) - exclude your bundle from Time Machine and Spotlight on macOS - [bundler-multilock](https://github.com/instructure/bundler-multilock) - Support Multiple Lockfiles - [bundler-override](https://github.com/tarnowsc/bundler-override) - This bundler plugin allows to change dependencies for a gem. It can be helpful in situation when a developer needs to use some other dependency than default for the gem. - [bundler-private_install](https://github.com/fphilipe/bundler-private_install) - A Bundler plugin that installs gems in an additional private Gemfile after bundle install. - [bundler-sbom](https://github.com/hsbt/bundler-sbom) - Generate SBOM (Software Bill of Materials) files with Bundler. - [bundler-source-aws-s3](https://github.com/eki/bundler-source-aws-s3) - Add aws-s3 source to bundler via plugin. - [bundler-symlink](https://github.com/petekinnecom/bundler-symlink) - Post-install hook for bundler to symlink to all gems from a local directory - [bundler-timing-plugin](https://github.com/hsbt/bundler-timing-plugin) - Display elapsed time of each gem fetch and install during bundle install. - [bundler-versions_report](https://github.com/igneus/bundler-versions_report) - At the end of `bundle update` report all updated major and minor versions - [bundler-why](https://github.com/jaredbeck/bundler-why) - Explains the presence of a dependency. - [extended_bundler-errors](http://github.com/jules2689/extended_bundler-errors) - Extended Errors for Bundler --- # Frequently Asked Questions Source: https://guides.rubygems.org/faqs/ More of the "why" and "wtf" than "how". * [RubyGems FAQ](#rubygems-faq) * [Bundler FAQ](#bundler-faq) RubyGems FAQ ============ Short answers to questions that come up repeatedly. Most topics are covered in more depth elsewhere in these guides: * Where gems are installed, and how `require` finds them: [Where gems are installed and how they load](/gem-installation-and-loading) * Failed installations and native extension build errors: [Troubleshooting common issues](/troubleshooting) * Updating RubyGems and Bundler: [Installation](/installation) * SSL certificate errors: [TLS/SSL troubleshooting](/rubygems_tls_ssl_troubleshooting_guide) Questions answered on this page: * [I installed gems with `--user-install` and their commands are not available](#i-installed-gems-with---user-install-and-their-commands-are-not-available) * [How can I trust Gem code that's automatically downloaded?](#how-can-i-trust-gem-code-thats-automatically-downloaded) * [Why does `require 'some-gem'` fail?](#why-does-require-some-gem-fail) * [Why does require return false when loading a file from a gem?](#why-does-require-return-false-when-loading-a-file-from-a-gem) * [How can I use a different gem version on the command line?](#how-can-i-use-a-different-gem-version-on-the-command-line) I installed gems with `--user-install` and their commands are not available --------------------------------------------------------------------------- `--user-install` puts gems in a directory under your home directory, such as `~/.gem/ruby/3.4.0`, and their executables in the `bin` directory below it. That `bin` directory is not on your `PATH` by default. Add it, for example in `~/.bashrc`: if which ruby >/dev/null && which gem >/dev/null; then PATH="$(ruby -e 'puts Gem.user_dir')/bin:$PATH" fi Then restart your shell. See [Executables and PATH](/gem-installation-and-loading#executables-and-path) for how RubyGems installs executables. How can I trust Gem code that's automatically downloaded? --------------------------------------------------------- The same way you can trust any other code you install from the net: ultimately, you can't. You are responsible for knowing the source of the gems that you are using. In a setting where security is critical, you should only use known-good gems, and possibly perform your own security audit on the gem code. The [Security](/security) guide covers the protections rubygems.org provides, including checksums, multi-factor authentication for publishers, and gem signing. Why does `require 'some-gem'` fail? ----------------------------------- The name of a gem and the name of the file you require are not always the same. Check which files the gem actually ships: $ ruby -e 'require "RedCloth"' -e:1:in 'Kernel#require': cannot load such file -- RedCloth (LoadError) $ gem contents --no-prefix RedCloth | grep lib lib/redcloth/version.rb lib/redcloth.rb $ ruby -e 'require "redcloth"' $ # success! If you are requiring the correct file and it still fails, `gem` and `ruby` may belong to different Ruby installations. Compare `which ruby` with the `RUBY EXECUTABLE` line in `gem env`, and check that your version manager selects the Ruby you expect. See [How require finds a gem](/gem-installation-and-loading#how-require-finds-a-gem) for the loading mechanism, and [Troubleshooting](/troubleshooting) if the gem failed to install in the first place. Why does require return false when loading a file from a gem? ------------------------------------------------------------- A false return from `require` is not an error. It means the file was already loaded, so `require` had nothing to do. This commonly happens when another file, or RubyGems itself while activating the gem, loaded it first. How can I use a different gem version on the command line? ---------------------------------------------------------- If you have multiple versions of a gem installed, you can pick the version of its executable with an underscore argument. For example, with two versions of Rails installed: $ rails _7.1.5_ new app This runs the `rails` command from exactly that version instead of the newest installed one. Bundler FAQ =========== ### Why Can't I Just Specify Only `=` Dependencies? **Q:** I understand the value of locking my gems down to specific versions, but why can't I just specify `=` versions for all my dependencies in the `Gemfile` and forget about the `Gemfile.lock`? **A:** Your dependencies have dependencies of their own, and those are not declared with `=`, so `=` requirements in your `Gemfile` alone cannot pin the whole dependency graph. The `Gemfile.lock` records the exact version of every gem in the graph, while loose requirements in the `Gemfile` (such as `nokogiri ~> 1.4.2`) let you run `bundle update nokogiri` to update just one gem when you choose to. See [How dependency resolution works](/dependency-resolution) and [Gemfile.lock](/gemfile-lock). ### Why Can't I Just Submodule Everything? **Q:** Why can't I just get the gems I need, stick them in submodules, and put each submodule on the load path? **A:** You would be resolving the dependency graph by hand, including dependencies of dependencies, and redoing that work for every update. Worse, you would get no feedback about version conflicts, only subtle runtime errors when a gem calls a method that does not exist in the version you picked. Dependency resolution is exactly the problem Bundler automates. See [How dependency resolution works](/dependency-resolution). ### Why Is Bundler Downloading Gems From `--without` Groups? **Q:** I excluded the `:production` group, for example with `bundle config set --local without production`, and Bundler still downloads the gems in it. Why? **A:** `Gemfile.lock` must contain exact versions of every dependency in your `Gemfile`, regardless of groups. If excluded groups were left out of resolution, deploying to production could change your whole dependency set, and a conflict between a production-only gem and the rest of your bundle would only surface at deployment time. Bundler therefore resolves and downloads all groups, but only installs the ones you asked for. See [Groups](/groups). ### I Have a C Extension That Requires Special Flags to Install **Q**: I have a gem with a C extension that needs special flags to compile. How can I pass these flags into the installation process? **A**: Use `bundle config` to store build flags for that gem: ~~~ $ bundle config set --global build.mysql2 --with-mysql-config=/usr/local/mysql/bin/mysql_config ~~~ Bundler stores this in `~/.bundle/config` and applies it to every following `bundle install`. See [Gems with extensions](/gems-with-extensions) for how extensions are built, and [Troubleshooting](/troubleshooting) for diagnosing build failures. ### I Do Not Have an Internet Connection and Bundler Keeps Trying to Connect to the Gem Server **Q**: I do not have an internet connection but I have installed the gem before. How do I get bundler to use my local gem cache and not connect to the gem server? **A**: Use the `--local` flag, which tells Bundler to use the local gem cache instead of reaching out to the remote gem server: ~~~ $ bundle install --local ~~~ You can populate that cache ahead of time with `bundle cache`. ### Bundling From RubyGems is Really Slow **Q**: When I bundle from RubyGems.org, it is really slow. Is there anything I can do to make it faster? **A**: First, make sure you are on a recent version of Bundler, which downloads gem metadata incrementally and installs gems in parallel. See [Updating Bundler](/installation#updating-bundler). If it is still slow, the bottleneck is usually the network or native extension compilation, not Bundler itself. ### Using Gemfiles inside gems **Q**: What happens if I put a `Gemfile` in my gem? **A**: When someone installs your gem, the `Gemfile` and `Gemfile.lock` are completely ignored, even if you include them in the `.gem` file you upload to rubygems.org. A `Gemfile` inside a gem only serves the developers of that gem, to install development and test dependencies. Read more in [Bundler in gems](/rubygems) and [Make your own gem](/make-your-own-gem/). **Q**: Should I commit my `Gemfile.lock` when writing a gem? **A**: No. Applications should always commit their lockfile, but for a gem the tradeoff points the other way. Bundler ignores the lockfile when your gem is installed as a dependency, and locking your own development environment narrows the range of dependency versions your tests actually exercise. Add `lockfile false` to the `Gemfile` (or pass `--no-lock` to `bundle install`) so no lockfile is generated. See [Dependency management](/dependency_management) for the reasoning. **Q**: Doesn't that expose contributors to breakage from new dependency releases? **A**: Yes, and that early signal is the point. Fresh checkouts, including CI, resolve to the latest versions your constraints allow, so an incompatible release surfaces immediately, before your users hit the same resolution. When a bad release blocks work, add a temporary pin to the `Gemfile` until the incompatibility is fixed. ### Why Don't Git Gems Show Up in `gem list`? **Q**: I added a gem with a `:git` source in my `Gemfile`, but it doesn't appear in `gem list` and its executables are not in my PATH. Where did it go? **A**: Bundler installs git gems into a separate internal directory, not into the same location as gems installed from RubyGems.org. This means they will not appear in `gem list` output, and their executables will not be available in the shell PATH directly. To run executables from git gems, use `bundle exec`. To check which git gems are installed in your bundle, run `bundle list`. ### Why Can't I Use Different Versions of a Gem in Different Groups? **Q**: I want to use one version of a gem in development and a different version in production. Can I specify different versions in different groups? **A**: No. Bundler resolves a single version for each gem across all groups and all platforms. This is by design. `Gemfile.lock` must contain one resolved version per gem so that every environment uses the same dependency set. If Bundler allowed different versions per group, installing in one environment could silently change which version of a gem you get in another, defeating the purpose of the lockfile. --- # Glossary Source: https://guides.rubygems.org/glossary/ Definitions of the terms used throughout these guides. binstub ------- A small wrapper script that Bundler generates into an application's `bin/` directory with `bundle binstubs GEM`. Running a binstub loads the bundle first, so the command runs against the exact gem versions in `Gemfile.lock` without needing a `bundle exec` prefix. See the [bundle binstubs reference](/command-reference/bundle-binstubs). bundled gem ----------- A gem that is installed automatically when you install Ruby but is not part of Ruby itself. Unlike a default gem it can be uninstalled, and when using Bundler it must be declared in the Gemfile. See [Default Gems and Bundled Gems](/default-gems-and-bundled-gems). cooldown -------- A Bundler setting that excludes gem versions published within the last N days from dependency resolution. Most malicious releases are detected and yanked within days of publication, so a cooldown keeps an application from installing a release before the ecosystem has had time to vet it. See [How to delay new gem versions with cooldown](/cooldown). default gem ----------- A gem that ships as part of every Ruby installation. It can be required without appearing in a Gemfile and cannot be uninstalled, but it can be updated independently of Ruby. See [Default Gems and Bundled Gems](/default-gems-and-bundled-gems). dependency ---------- A gem that another gem or an application needs in order to work. Gems declare their dependencies in the gemspec and applications declare theirs in the Gemfile, and each dependency can bring dependencies of its own, forming the graph that resolution works on. See [Gemfile and gemspec](/gemfile-and-gemspec). gem --- A packaged Ruby library or program. Each gem has a name, a version, and a platform, and contains code, documentation, and a gemspec. See [What is a gem?](/what-is-a-gem/). Gemfile ------- The file that describes an application's gem environment for Bundler. It lists the gems the application uses directly, along with the sources to fetch them from. The file does not have to be named `Gemfile`: Bundler also recognizes `gems.rb`, and the `BUNDLE_GEMFILE` environment variable can point to any file. See [Gemfile and gemspec](/gemfile-and-gemspec) and the [Gemfile reference](/gemfile). Gemfile.lock ------------ The file Bundler writes after dependency resolution, recording the exact version of every gem, direct or transitive. Often called simply the lockfile, and named after the Gemfile when that file uses another name, such as `gems.locked` for `gems.rb`. Later installs reuse those versions instead of resolving again, so every machine and every deploy runs the same code. Bundler maintains the file, and you never edit it by hand. See [How Gemfile.lock works](/gemfile-lock). gemspec ------- The manifest of a gem. It declares the gem's name, version, summary, files, and dependencies, and it is packaged into the `.gem` file that `gem build` produces. See the [Specification Reference](/specification-reference). lockfile checksums ------------------ The `CHECKSUMS` section of `Gemfile.lock`, recording the SHA-256 digest of each packaged `.gem` file. Bundler verifies every gem against its checksum during installation, so a gem that was tampered with after the lockfile was written fails to install. See [Lockfile checksums](/security#lockfile-checksums). native extension ---------------- Code, typically C, that is part of a gem and is compiled on the user's machine at install time, often to wrap an existing system library. Building one requires a compiler toolchain and the library's development headers. See [Gems with Extensions](/gems-with-extensions). platform -------- The CPU architecture, operating system type, and sometimes operating system version a gem is built for. The generic `ruby` platform means pure Ruby code that works on any platform Ruby runs on. See [What is a gem?](/what-is-a-gem/). precompiled gem --------------- A gem published in platform-specific variants with its native extension already compiled, so installation skips the compile step and needs no toolchain. Also called a fat gem. The platforms a lockfile covers for such gems are recorded in its `PLATFORMS` section. See [How Gemfile.lock works](/gemfile-lock#platforms). prerelease ---------- A version containing a letter, like `1.0.0.pre` or `2.0.0.rc1`, published for testing before the real release. Installers and the resolver ignore prereleases unless a requirement explicitly names one. See [Versioning and compatibility](/versioning#prerelease-versions). requirement ----------- One or more comparisons against a version, like `>= 1.0` or `~> 2.2`, stating which versions of a dependency are acceptable. Also called a version constraint. See [How dependency resolution works](/dependency-resolution#what-version-constraints-mean) and [Versioning and compatibility](/versioning). resolution ---------- The process of choosing exactly one version of every gem in the dependency graph so that all requirements hold at the same time. Bundler runs it on the first `bundle install` and writes the result to `Gemfile.lock`. See [How dependency resolution works](/dependency-resolution). source ------ A place gems are fetched from: a gem server such as RubyGems.org, a git repository, or a local directory. Sources are declared in the Gemfile, and each one gets its own block in `Gemfile.lock`. See [How Gemfile.lock works](/gemfile-lock). trusted publishing ------------------ A way to publish gems from CI without long-lived credentials. A configured workflow authenticates with RubyGems.org using short-lived OpenID Connect tokens, so there is no API key to create, rotate, or leak. See [Trusted Publishing](/trusted-publishing). vendoring --------- Storing copies of an application's dependencies inside its own repository, so installs do not need to reach a remote source. `bundle cache` puts the packaged `.gem` files of the bundle into `vendor/cache`. See the [bundle cache reference](/command-reference/bundle-cache). yank ---- Removing a published version from RubyGems.org with `gem yank`. A yanked version can no longer be installed, but the name and version number stay taken and cannot be reused. See [Removing a published gem](/removing-a-published-gem). --- # Contributing to RubyGems Source: https://guides.rubygems.org/contributing/ How you can help make RubyGems and the surrounding ecosystem better. Looking to contribute to a RubyGems project? You've come to the right place! There are many development efforts going on right now, and they could use your help. Just follow the links below to get started contributing or to contact the project maintainers. * [Core Projects](#core-projects) * [Ecosystem Projects](#ecosystem-projects) * [3rd Party Projects](#3rd-party-projects) * [Add Your Own Idea](#add-your-own-idea) Core Projects ------------- These projects are maintained by the core RubyGems team across the [ruby](https://github.com/ruby/) and [rubygems](https://github.com/rubygems/) organizations. RubyGems & Bundler Ruby's package management system. This monorepo contains two CLI tools: `gem` for installing and managing individual gems, and `bundle` for managing application dependencies. Both are bundled with Ruby.

Alumni:

RubyGems.org The Ruby community's gem hosting service and registry.

Alumni:

Ecosystem Projects ------------------ These projects are part of the [RubyGems organization](https://github.com/rubygems/) and support the core infrastructure. RubyGems Guides The central home for RubyGems documentation, including tutorials and reference material. Contributions are welcome!

Alumni:

RubyGems.org API Library A Ruby client library for the RubyGems.org API.

Alumni:

RubyGems Mirror The `gem mirror` command for creating local mirrors of all gems from a remote gem source. Useful for running RubyGems behind a firewall or for availability.

Alumni:

Gemstash A RubyGems.org cache and private gem server.

Alumni:

release-gem The official GitHub Action for publishing gem files to RubyGems.org.

Alumni:

configure-rubygems-credentials A GitHub Action to configure RubyGems.org credential environment variables for use in CI/CD workflows.

configure_trusted_publisher A CLI tool to automate the process of configuring a trusted publisher for a gem.

Alumni:

3rd Party Projects ------------------ These projects are outside of the RubyGems organization, but work closely with RubyGems to improve the gem experience for everyone. RubyDoc.info Provides [YARD](https://yardoc.org) documentation for every RubyGem available. Push a gem, and you get docs created instantly!

Geminabox A simple way to host RubyGems internally and allow uploading of private gems.

bundler-audit Patch-level verification for Bundler. Checks for known vulnerabilities in gems listed in Gemfile.lock.

ruby-advisory-db A community-maintained database of security advisories for Ruby gems. Used by bundler-audit and other tools to check for vulnerable dependencies.

Add Your Own Idea ----------------- We'd love for your new idea to be on this list. If you're working on a RubyGems related project, just [fork this repo](https://github.com/rubygems/guides) and add the link! --- # Credits Source: https://guides.rubygems.org/credits/ This site is [open source](https://github.com/rubygems/guides) and its content is [Creative Commons](https://github.com/rubygems/guides/blob/gh-pages/CC-LICENSE) licensed. Contributors ------------ These people have donated time to creating and improving the RubyGems Guides site: * [Gabe Berke-Williams](https://github.com/gabebw) * [Gregory Brown](https://github.com/sandal) * [Amaia Castro](https://github.com/amaia) * [Ryan Davis](https://github.com/zenspider) * [Vijay Dev](https://github.com/vijaydev) * [Evgene Dzhelyov](https://github.com/edzhelyov) * [Mike Gunderloy](https://github.com/ffmike) * [Gabriel Horner](https://github.com/cldwalker) * [Richard Michael](https://github.com/richardkmichael) * [John Lees-Miller](https://github.com/jdleesmiller) * [Mark McSpadden](https://github.com/markmcspadden) * [Erik Michaels-Ober](https://github.com/sferik) * [Scott Moak](https://github.com/smoak) * [Jason Morrison](https://github.com/jasonm) * [Ryan Neufeld](https://github.com/rkneufeld) * [Nick Quaranto](https://github.com/qrush) * [Sebastian Spier](https://github.com/spier) * [Antonio Terceiro](https://github.com/terceiro) * [thrackle](https://github.com/thrackle) Acknowledgments --------------- Material for the Guides was adapted from these sources: * [Gem Packaging: Best Practices](https://weblog.rubyonrails.org/2009/9/1/gem-packaging-best-practices) * [Gem Sawyer, Modern Day Ruby Warrior](http://rubylearning.com/blog/2010/10/06/gem-sawyer-modern-day-ruby-warrior/) * [How to Name Gems](http://blog.segment7.net/2010/11/15/how-to-name-gems) * [Rubygems Good Practice](https://yehudakatz.com/2009/07/24/rubygems-good-practice/) * [Writing Ruby C extensions: Part 1](http://tenderlovemaking.com/2009/12/18/writing-ruby-c-extensions-part-1) * [Writing Ruby C extensions: Part 2](http://tenderlovemaking.com/2010/12/11/writing-ruby-c-extensions-part-2) Hosting ------- Hosted by [GitHub Pages](https://pages.github.com/).