Home Explore Blog Models CI



nixpkgs

3rd chunk of `doc/languages-frameworks/ruby.section.md`
91c859842861ccbeff7769bb2f388fa5e14f93c57a9ffa0e0000000100000e8e
    name = "gems-for-some-project";
    gemdir = ./.;
  };
in
mkShell {
  packages = [
    gems
    gems.wrappedRuby
  ];
}
```

With this file in your directory, you can run `nix-shell` to build and use the gems. The important parts here are `bundlerEnv` and `wrappedRuby`.

The `bundlerEnv` is a wrapper over all the gems in your gemset. This means that all the `/lib` and `/bin` directories will be available, and the executables of all gems (even of indirect dependencies) will end up in your `$PATH`. The `wrappedRuby` provides you with all executables that come with Ruby itself, but wrapped so they can easily find the gems in your gemset.

One common issue that you might have is that you have Ruby, but also `bundler` in your gemset. That leads to a conflict for `/bin/bundle` and `/bin/bundler`. You can resolve this by wrapping either your Ruby or your gems in a `lowPrio` call. So in order to give the `bundler` from your gemset priority, it would be used like this:

```nix
# ...
mkShell {
  buildInputs = [
    gems
    (lowPrio gems.wrappedRuby)
  ];
}
```

Sometimes a Gemfile references other files. Such as `.ruby-version` or vendored gems. When copying the Gemfile to the nix store we need to copy those files alongside. This can be done using `extraConfigPaths`. For example:

```nix
{
  gems = bundlerEnv {
    name = "gems-for-some-project";
    gemdir = ./.;
    extraConfigPaths = [ "${./.}/.ruby-version" ];
  };
}
```

### Gem-specific configurations and workarounds {#gem-specific-configurations-and-workarounds}

In some cases, especially if the gem has native extensions, you might need to modify the way the gem is built.

This is done via a common configuration file that includes all of the workarounds for each gem.

This file lives at `/pkgs/development/ruby-modules/gem-config/default.nix`, since it already contains a lot of entries, it should be pretty easy to add the modifications you need for your needs.

In the meanwhile, or if the modification is for a private gem, you can also add the configuration to only your own environment.

Two places that allow this modification are the `ruby` derivation, or `bundlerEnv`.

Here's the `ruby` one:

```nix
{
  pg_version ? "10",
  pkgs ? import <nixpkgs> { },
}:
let
  myRuby = pkgs.ruby.override {
    defaultGemConfig = pkgs.defaultGemConfig // {
      pg = attrs: {
        buildFlags = [
          "--with-pg-config=${pkgs."postgresql_${pg_version}".pg_config}/bin/pg_config"
        ];
      };
    };
  };
in
myRuby.withPackages (ps: with ps; [ pg ])
```

And an example with `bundlerEnv`:

```nix
{
  pg_version ? "10",
  pkgs ? import <nixpkgs> { },
}:
let
  gems = pkgs.bundlerEnv {
    name = "gems-for-some-project";
    gemdir = ./.;
    gemConfig = pkgs.defaultGemConfig // {
      pg = attrs: {
        buildFlags = [
          "--with-pg-config=${pkgs."postgresql_${pg_version}".pg_config}/bin/pg_config"
        ];
      };
    };
  };
in
mkShell {
  buildInputs = [
    gems
    gems.wrappedRuby
  ];
}
```

And finally via overlays:

```nix
{
  pg_version ? "10",
}:
let
  pkgs = import <nixpkgs> {
    overlays = [
      (self: super: {
        defaultGemConfig = super.defaultGemConfig // {
          pg = attrs: {
            buildFlags = [
              "--with-pg-config=${pkgs."postgresql_${pg_version}".pg_config}/bin/pg_config"
            ];
          };
        };
      })
    ];
  };
in
pkgs.ruby.withPackages (ps: with ps; [ pg ])
```

Then we can get whichever postgresql version we desire and the `pg` gem will always reference it correctly:

```ShellSession
$ nix-shell --argstr pg_version 9_4 --run 'ruby -rpg -e "puts PG.library_version"'
90421

$ nix-shell --run 'ruby -rpg -e "puts PG.library_version"'

Title: Nix Ruby Development: `bundlerEnv`, Dependency Conflicts, and Gem Customization
Summary
This chunk details the use of `bundlerEnv` and `wrappedRuby` in Nix for creating Ruby development environments, explaining how they make gem executables and Ruby binaries available. It addresses a common conflict between Ruby's own `bundler` and a `bundler` gem by suggesting the use of `lowPrio` to prioritize one. The text also covers including additional project configuration files via `extraConfigPaths` in `bundlerEnv`. A significant portion is dedicated to configuring individual gems, particularly those with native extensions. It outlines how to modify gem build processes using `defaultGemConfig` or `gemConfig` within `ruby` derivations, `bundlerEnv`, or through Nix overlays, providing a practical example for configuring the `pg` gem to link with specific PostgreSQL versions.