Ruby on Rails gem collisions

I am trying to get my Ruby on Rails development environment up and running. I followed the ‘Development shell’ instructions in this repo but I cannot get passed collisions in the nix store.

In my gemset.nix generated by bundix there’s multiple gems which all reference the same source, I believe this is why I am getting the collisions. Example below, but there’s lots of these with the same source!

  actioncable = {
    dependencies = ["actionpack" "activesupport" "nio4r" "websocket-driver" "zeitwerk"];
    groups = ["default" "development"];
    platforms = [];
    source = {
      fetchSubmodules = false;
      rev = "1f6cef4ca546b3a9f7aa12c0f10c7d1d1cfbab5a";
      sha256 = "0fk0a0kq1wcgdnccpxix7r7x2y21awh2ipi808gy7wma5rgayxm9";
      type = "git";
      url = "https://github.com/rails/rails.git";
    };
    version = "7.2.0.alpha";
  };
  actionmailbox = {
    dependencies = ["actionpack" "activejob" "activerecord" "activestorage" "activesupport" "mail"];
    groups = ["default"];
    platforms = [];
    source = {
      fetchSubmodules = false;
      rev = "1f6cef4ca546b3a9f7aa12c0f10c7d1d1cfbab5a";
      sha256 = "0fk0a0kq1wcgdnccpxix7r7x2y21awh2ipi808gy7wma5rgayxm9";
      type = "git";
      url = "https://github.com/rails/rails.git";
    };
    version = "7.2.0.alpha";
  };

My flake.nix looks like this:

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
    nixpkgs-ruby.url = "github:bobvanderlinden/nixpkgs-ruby";
    nixpkgs-ruby.inputs.nixpkgs.follows = "nixpkgs";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, nixpkgs-ruby, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
        ruby = nixpkgs-ruby.lib.packageFromRubyVersionFile {
          file = ./.ruby-version;
          inherit system;
        };

        gems = pkgs.bundlerEnv {
          name = "gemset";
          inherit ruby;
          gemfile = ./Gemfile;
          lockfile = ./Gemfile.lock;
          gemset = ./gemset.nix;
          groups = [ "default" "production" "development" "test" ];
        };
      in
      {
        devShell = with pkgs;
          mkShell {
            buildInputs = [
              gems
              ruby
              bundix
            ];
          };
      });
}

How would I avoid this?

I went through this just recently. In the call to pkgs.bundlerEnv, add:

ignoreCollisions = true;

You will still see the warnings in the build process, but it will finish successfully.

1 Like

Hi,
Great you got your issue solved. I believe packaging gems using bundix and bundlerEnv is more suitable for production use, for development devenv or similar tools are very straight to go, if you’re interested here is an example using rails.

I can’t speak for the OP, but in my case I am streamlining the development environment of an established project with a large codebase. My devenv modules (those passed in the modules attribute to devenv.lib.mkShell in flake.nix) are already numerous, and some of them are getting complex. Thanks for sharing, anyway!

In the project I am working on, the bundle includes gems with compiled extensions that depend on external libraries, which need to be available in the environment. This is where bundlerEnv comes in, since those external dependencies can be directly tied to the specific gems that require them, using the gemConfig attribute. nixpkgs already includes defaults for many popular gems in defaultGemConfig, and my project adds a couple more on top (which I intend to submit upstream).

I am curious, if you consider bundlerEnv more suitable only for production, then what do you do in development? Do you leave the bundle outside of the Nix closure, and require each developer to run bundle install on their own?

1 Like

I must say that I have only made some testings to use nix for development with RoR, we are still using docker compose in my team. I packaged only one RoR app for production with a NixOS module (using pg, redis and sidekiq), so I’m clearly not an expert :slight_smile:

We are a small team with a few mid-size codebase projects and a lot of small ones. Using flake for development seemed to me to require too much work for setting each stack (ruby/node processes, databases, etc).

Yes with devenv in my testings I was just using bundler and yarn to manage dependencies, I didn’t have issues for gems using external libs (like nokogiri or pg), but I didn’t tried many gems. To automate bundle install, I added this in my devenv config:

process.before = "install-dependencies";

scripts.install-dependencies.exec = ''
  bundle install
  yarn install --frozen-lockfile
'';
1 Like