Ruby’s libraries ecosystem, mainly supported by the community, is one of the language’s most powerful features. These libraries allow developers to reuse and build upon pre-existing, well-tested solutions. For many common functionalities, there is already a library available. This can save you significant time and effort.
Ruby’s ecosystem is structured into three components:
- Ruby Core Library: Built-in functionality that is always available.
- Ruby Standard Library: Built-in functionality that must be explicitly required.
- RubyGems: External, “pluggable” functionality.
To manage RubyGems dependencies effectively, Bundler is a crucial tool. While optional, it simplifies maintenance and ensures consistency across projects.
We will also see how libraries are loaded using the Ruby load path.
The Ruby Core Library: The Foundation of Ruby
The Ruby Core Library provides fundamental features that are always loaded and ready to use. It is available as soon as your Ruby program starts.
Examples of Core Library Features
- Strings and Arrays: Methods to transform strings (like capitalize) and manipulate arrays (like summing all the items).
- Enumerables: The
Enumerable
module provides powerful methods likemap
,select
, andreduce
for collections.
The Ruby Standard Library: Batteries Included
The Ruby Standard Library extends the Core Library with a wide range of optional tools. These libraries cover many areas, such as file handling, data serialization, and network communication. However, they must be explicitly “required” to use.
Examples of Standard Libraries
date
: Manage and manipulate dates.
This library simplifies working with dates, including parsing, formatting, and calculations like adding days or finding differences between dates.
digest
: Provides basic encryption tools.
This library is useful for securing sensitive data, such as passwords or API tokens.
json
: Parse and generate JSON data.
Commonly used to handle APIs and data serialization.
net/http
: Perform HTTP requests.
Essential for working with REST APIs or web scraping.
Try it yourself - Use the JSON gem
Write a Ruby script that uses the JSON gem to parse the following JSON data and display the hex value for the yellow color.
Show me the steps.
-
Create a new file, for example
json_example.rb
. -
Require the JSON gem.
-
Store the JSON in a variable.
-
Parse the JSON and display the hex value for the yellow color.
-
Run the script:
You should see the "#ff0"
hex value for the yellow color.
RubyGems: Ruby’s Package Manager
A Ruby gem is a library, packaged and ready to be distributed and installed easily. These gems are hosted on RubyGems. Think of it as Ruby’s “app store”, hosting thousands of gems for various purposes—from small utilities to full-fledged frameworks like Rails.
A gem page in RubyGems has useful metadata, such as version history, dependencies, and links to the documentation.
Once installed and required, you can use the gem.
How to Use RubyGems
To search, install and manage gems you can use the gem
package manager, which communicates directly with the RubyGems repository and takes care of dependencies. This command is preinstalled with Ruby.
-
List installed gems:
This list applies to the current Ruby version, in case you use a version manager such as rbenv.
-
Install a Gem:
This command installs the dependencies first, and lastly the intended gem.
For example, installing the Sinatra gem (a lightweight framework):
-
Require the gem in your code:
When running this code snippet, the Puma web server starts up and keeps listening at port 4567. When visiting localhost at that port, it returns “Hello world!”.
Bundler: Managing Dependencies
Bundler is a tool that can install gems and annotate the version in a file named Gemfile. Then it resolves the dependencies and installs specific versions that play well together, keeping them all under control using a second file named Gemfile.lock
In other words, you have a list of the gem versions you need for your project in Gemfile, and Bundler manages Gemfile.lock automatically with the technical details on the exact required dependencies.
These files can be shared with a team so everyone uses the same versions and can collaborate effectively.
How is it Different from RubyGems?
The gem
command installs the gem so it is available in general from Ruby. Bundler creates a sandbox for your application, and only uses the specific versions described in Gemfile. That way you can work on several projects, each with their gem versions.
It uses two key files:
- Gemfile: Defines the gems your project requires. If no versions are specified, it installs the latest available.
The source
line specifies the repository where the gems are located. RubyGems is the standard. You can also use a local repository or a private one.
- Gemfile.lock: Locks the specific versions of gems and their dependencies to ensure consistency. This file is automatically updated when you modify your gems list in Gemfile.
Specifying Gem Versions
If you want to use a specific version of a gem, you can specify it like this:
This is good to lock a version to the last known compatible one with your app, not allowing any version different than 4.1.1. If you want to allow any higher version, starting from 4.1.1, you can use the “optimistic version constraint”:
There is a “pessimistic version constriant” too:
This means “greater than or equal to version 4.x.x”, so it allows 4.0.0, 4.0.1, 4.1.0, but not 5.0.0 or higher.
Similarly you can do the same for the minor version:
This allows 4.1.x versions, for example 4.1.0 or 4.1.1, but not 4.2.0 or higher.
Another way to specify versions is using a range:
This allows any version between 4.1.1 and 5.0, but not 5.0.1 or higher.
Using Bundler
-
Initialize a new project:
This command creates a Gemfile in your project directory.
-
Add dependencies to Gemfile. For example let’s add the Chronic gem for natural language date parsing:
Bundler gets the gem metadata from RubyGems, then resolves the dependencies. As it has no dependencies, it just downloads
chronic
and installs it. The gem is added to Gemfile and the dependencies to Gemfile.lock.If you need to reinstall everything in a different computer, after upgrading Ruby, or another developer collaborates in the project, you can use this command:
This uses Gemfile.lock to download and install the same versions.
-
Create a file with some sample code to use the gem:
-
Run your application:
Prepending
bundle exec
ensures that only the gems specified in your Gemfile.lock are used, avoiding potential conflicts with other installed versions.
Ruby Load Path: Where Ruby Looks for Code
Ruby’s $LOAD_PATH
determines where the require
method searches for files. You can inspect it by running this from your program:
This prints an array of directories where Ruby gems are stored.
If you require devise
, Ruby will look for a file with the name devise.rb in each directory listed in the load path until it finds it. Then it will load it.
If Ruby can’t find a required file, you might need to add the enclosing directory to the load path:
As you see, the $LOAD_PATH
is dynamic, meaning you can modify it at runtime to include custom directories.
Conclusion
Ruby libraries significantly enhance productivity by providing reusable, tested components for common tasks. Ruby’s ecosystem is mature and ever-evolving, with updated and new tools constantly emerging.
Test your knowledge
-
What is the Ruby Core Library?
-
How do you use a library from the Ruby Standard Library?
-
What does Bundler do?
-
How can you inspect Ruby’s
$LOAD_PATH
?
-
What is a Gemfile used for?