Resolving Default Ruby Version Issues on macOS with Homebrew

Installing newer versions of Ruby on macOS using Homebrew is a common practice for developers needing specific language features or compatibility.

However, a frequent challenge arises when the system continues to use the pre-installed macOS Ruby version (often found at /usr/bin/ruby) even after a successful Homebrew installation (e.g., brew install ruby).

This situation prevents access to the features of the newer Ruby version and can cause issues with tools like Jekyll or when installing gems that require specific Ruby versions. This article examines the reasons behind this behavior and outlines several effective strategies based on common configuration practices to ensure the Homebrew-installed Ruby becomes the default in your shell environment.

Understanding the Root Cause: The PATH Environment Variable

The core reason the system Ruby might still be used lies in how the command-line shell locates executable programs. This process is governed by the PATH environment variable.

  • The PATH variable contains a list of directories, separated by colons.
  • When you type a command like ruby, the shell searches these directories *in the order they appear* in the PATH.
  • The first directory containing an executable named ruby is the one that gets used.

macOS typically includes /usr/bin (where the system Ruby resides) in the default PATH. Homebrew usually installs its executables or creates symbolic links (symlinks) in /usr/local/bin. If /usr/bin appears earlier in your PATH than /usr/local/bin, the shell finds the system Ruby first and stops searching.

Furthermore, Homebrew sometimes installs certain software as “keg-only,” meaning it doesn’t automatically create the symlink in /usr/local/bin, often because macOS provides its own version of that software (like Ruby). In such cases, even if /usr/local/bin is first in your PATH, the Homebrew Ruby executable isn’t found there directly, and additional configuration is required.

Read: Launching VS Code from the macOS Terminal: Resolving the code Command Issue

Solutions to Set the Homebrew Ruby as Default

Several approaches can resolve this issue, ranging from direct PATH manipulation to using version managers.

Solution 1: Modify PATH Precedence in Shell Profile

This method ensures that the Homebrew’s executables’ directory is listed *before* the system directories in your PATH variable. This is typically done by editing your shell’s profile file.

  1. Identify your shell and profile file: Determine your current shell by running echo $SHELL.
    • If it returns /bin/zsh (common on newer macOS), you’ll likely edit ~/.zshrc.
    • If it returns /bin/bash (older macOS), you’ll likely edit ~/.bash_profile (or potentially ~/.profile if the former doesn’t exist).
  2. Edit the profile file: Add the following line to the *end* of the appropriate file (creating it if it doesn’t exist). This prepends the Homebrew binary directory to the existing PATH.
    export PATH="/usr/local/bin:$PATH"

    Alternatively, to specifically target the path where Homebrew installs Ruby (even if keg-only), use the path provided by Homebrew’s caveats (see Solution 4) or a dynamic approach:

    # For Zsh (recommended for newer macOS)
    echo 'export PATH="/usr/local/opt/ruby/bin:$PATH"' >> ~/.zshrc
    
    # Or for Bash
    echo 'export PATH="/usr/local/opt/ruby/bin:$PATH"' >> ~/.bash_profile
    
    # A potentially more robust method using brew --prefix
    # echo 'export PATH="$(brew --prefix ruby)/bin:$PATH"' >> ~/.your_profile_file

    Note: Some discussions mention adding the export line to ~/.zshenv for Zsh as another alternative.

  3. Reload the configuration: Apply the changes by either closing and reopening your terminal window/tab, or by running:
    source ~/.zshrc  # Or source ~/.bash_profile

This method directly tells the shell to look in Homebrew’s primary binary location first.

Read: 15 Proven Ways to Fix Wi-Fi Problems on Your Mac

Solution 2: Use `brew link` (If Applicable)

Homebrew uses linking to create symlinks from its installation directories (like /usr/local/opt/ruby) to the general Homebrew binary directory (/usr/local/bin). If Ruby was installed but not linked (perhaps as “keg-only”), you can attempt to force the link.

  1. Attempt to link Ruby:
    brew link --overwrite ruby
  2. If needed, use force: In some cases, you might need to add the --force flag (use with caution):
    brew link --overwrite ruby --force
  3. Reload shell: Restart your terminal or source your profile file.

Important Consideration: Homebrew may intentionally refuse to link software like Ruby that macOS provides, displaying a warning like Warning: Refusing to link macOS provided/shadowed software: ruby. In this scenario, modifying the PATH (Solution 1 or 4) is the recommended approach outlined in Homebrew’s own caveats.

Solution 3: Employ a Ruby Version Manager (rbenv)

For developers working with multiple Ruby projects that might require different Ruby versions, using a dedicated version manager like rbenv or RVM is a highly recommended practice. These tools manage multiple Ruby installations and make switching between them straightforward.

Steps using rbenv (installable via Homebrew):

  1. Install rbenv and ruby-build:
    brew update
    brew install rbenv ruby-build
  2. Install the desired Ruby version: (Replace `1.9.3-p125` with the specific version you need)
    rbenv install 1.9.3-p125
  3. Set the global default Ruby version:
    rbenv global 1.9.3-p125
  4. Configure shell integration: Ensure rbenv’s initialization command is added to your shell profile (~/.zshrc or ~/.bash_profile). Follow the instructions provided by `brew info rbenv` or the rbenv documentation, which usually involves adding a line like `eval “$(rbenv init -)”`.
  5. Reload shell: Restart your terminal or source your profile file.

Version managers handle the PATH adjustments internally through “shims,” providing a cleaner way to manage different Ruby environments.

Solution 4: Directly Add Homebrew’s `opt` Path

When Homebrew installs a formula as “keg-only” (not linked into /usr/local/bin), it often provides specific instructions (caveats) on how to add its dedicated path to your environment. This path usually resides within /usr/local/opt/.

  1. Find the correct path: Homebrew typically installs Ruby (even specific versions) under /usr/local/opt/. The general path might be /usr/local/opt/ruby/bin or a version-specific one like /usr/local/opt/ruby@2.7/bin. You can check the output from brew info ruby or when (re)installing.
  2. Add the path to your shell profile: Similar to Solution 1, add the export command to ~/.zshrc or ~/.bash_profile:
    # Example for the generic path (adjust if needed)
    echo 'export PATH="/usr/local/opt/ruby/bin:$PATH"' >> ~/.zshrc
    
    # Example for a specific version
    # echo 'export PATH="/usr/local/opt/ruby@2.7/bin:$PATH"' >> ~/.zshrc

    As mentioned before, ~/.zshenv is also suggested as a place for such exports in Zsh environments.

  3. Reload the shell: Restart your terminal or run source ~/.your_profile_file.

This directly prioritizes the specific Homebrew installation path, bypassing the need for linking into /usr/local/bin.

Verification Steps

After applying a solution and reloading your shell configuration, verify that the correct Ruby version is now default:

  • Check the active Ruby path:
    which ruby

    This should now point to a path within /usr/local/ (e.g., /usr/local/bin/ruby or /usr/local/opt/ruby/bin/ruby) or your version manager’s path (e.g., involving .rbenv/shims). It should *not* show /usr/bin/ruby.

  • Check the Ruby version:
    ruby -v

    This should display the version number you installed via Homebrew or the version manager.

  • List all Ruby executables found in PATH (optional):
    which -a ruby

    This shows all occurrences of the `ruby` executable found by searching the directories in your `PATH`, listed in order of precedence. The desired Homebrew/version manager path should appear first.

Potential Issues and Considerations

  • System Ruby and Gem Permissions: Attempting to install gems using the system Ruby (/usr/bin/ruby) often fails with permission errors (e.g., Gem::FilePermissionError). This is because the default system gem directory (e.g., /Library/Ruby/Gems/...) requires administrator privileges (sudo) to modify. Using the Homebrew-installed Ruby or a version manager typically installs gems into user-writable directories, avoiding this problem. This highlights a key reason for not using the system Ruby for active development.
  • Homebrew Link Failures: Remember that brew link might be intentionally blocked for Ruby. Check Homebrew’s output for warnings and prefer the PATH modification methods if linking is refused.
  • Compiler and Linker Flags: When installing gems that require compiling native extensions, you might need to tell the compiler where to find the Homebrew Ruby headers and libraries. Homebrew’s caveats often suggest setting environment variables like:
    export LDFLAGS="-L/usr/local/opt/ruby/lib"
    export CPPFLAGS="-I/usr/local/opt/ruby/include"

    (Adjust the path if using a version-specific formula like ruby@2.7). Similarly, `pkg-config` might need configuration:

    export PKG_CONFIG_PATH="/usr/local/opt/ruby/lib/pkgconfig"

    These should also be added to your shell profile file (e.g., ~/.zshrc, ~/.bash_profile, or ~/.zshenv).

  • Shell Reload Required: Changes to shell profile files only take effect in new shell sessions or after manually reloading the configuration using source ~/.your_profile_file or fully restarting the terminal application (Cmd+Q and reopen).

Conclusion

Ensuring that macOS uses a Homebrew-installed Ruby version instead of the system default primarily involves correcting the order of directories in the PATH environment variable. This can be achieved by directly modifying the PATH in your shell profile (~/.zshrc or ~/.bash_profile), using Homebrew’s specific `opt` path, or employing a dedicated Ruby version manager like rbenv. While `brew link` is an option, it may be intentionally prevented for Ruby by Homebrew. Properly configuring the PATH ensures that the desired Ruby executable is found first by the shell, resolving version conflicts and enabling a smoother development workflow.

Frequently Asked Questions (FAQ)

Why shouldn’t I edit `/etc/paths` directly?

While technically possible, modifying the system-wide `/etc/paths` file is generally discouraged. Changes there affect all users and can potentially interfere with system operations or updates. Managing the PATH via user-specific profile files (like ~/.zshrc or ~/.bash_profile) is safer, more standard, and provides per-user control.

What is the difference between `.bash_profile`, `.bashrc`, and `.zshrc` / `.zshenv`?

These are shell configuration files. .bash_profile is typically read by Bash for login shells (like opening a new terminal window), while .bashrc is often for non-login shells. On macOS, interactive terminal shells usually act like login shells, making .bash_profile the common choice for Bash PATH modifications. Zsh (the default on newer macOS) primarily uses ~/.zshrc for interactive shell configuration. ~/.zshenv is sourced earlier for all Zsh invocations and is sometimes suggested for environment variables like PATH, LDFLAGS, etc., though placing them in ~/.zshrc is also very common and effective for interactive use.

Why might `brew link –overwrite ruby` fail or require `–force`?

Homebrew often prevents linking formulae that macOS provides system versions of (like Ruby) to avoid conflicts. This is indicated by a warning. The --force flag overrides this protection but should be used cautiously as it could potentially cause unexpected behavior if not fully understood. Using the PATH modification method is generally preferred when Homebrew refuses to link.

Should I use RVM or rbenv?

Both RVM (Ruby Version Manager) and rbenv are popular tools for managing multiple Ruby versions. The discussion provided detailed steps for rbenv. Both achieve similar goals but use slightly different mechanisms (RVM modifies the shell environment more extensively, while rbenv uses shims). The choice often comes down to personal preference or project requirements.

Is restarting the terminal always necessary after changing the PATH?

No, you don’t always need to fully restart the terminal application. You can apply the changes to your *current* shell session by running source ~/.your_profile_file (e.g., source ~/.zshrc). However, any *new* terminal windows or tabs you open after saving the profile file will automatically inherit the updated PATH. Restarting is a simple way to ensure all subsequent sessions use the new configuration.

When do I need to set `LDFLAGS`, `CPPFLAGS`, or `PKG_CONFIG_PATH`?

You typically need these environment variables when installing Ruby gems that include native C extensions (parts written in C that need to be compiled). These flags tell the compiler and linker where to find the necessary header files and libraries associated with the specific Homebrew Ruby version you intend to use for compiling the gem.

 


If you like the content, we would appreciate your support by buying us a coffee. Thank you so much for your visit and support.

 

Nikolaus Oosterhof

Nikolaus holds a degree in software development and has a strong passion for all things tech-related, especially gadgets with screens. Though he is nostalgic for older phone models, he's a retired gamer and continues to enjoy programming in open-source environments. Additionally, Nikolaus enjoys writing about Linux, macOS and Windows and has experience designing web pages.

Leave a Reply