使用nix-shell的简单Rails开发环境的详细步骤及代码展示

408 阅读3分钟

这是继我之前关于使用nix-shell建立一个简单的Ruby开发环境的文章之后的又一篇文章。我想尝试的下一件事是建立一个简单的Rails开发环境。为此,我决定把重点放在GFR网站上,这是一个Rails应用程序,但它的优点是不使用数据库。

这个项目的Gemfile ,指定了Ruby v2.5.7,所以和以前一样,我升级到使用最新的v2.5补丁版本,即v2.5.8,这样我就可以使用nix提供的ruby_2_5包。

与此类似,Gemfile.lockBUNDLED WITH v1.17.3 的 bundler;而nixpkgs 提供的bundler 版本是 v2.1.4。Gemfile.lock 中的这一行并不是一个强制约束,我不想破坏我们的Heroku部署,所以我妥协了,升级到Heroku Ruby buildpack支持的bundler的v2版本,即v2.0.2。

我的shell.nix ,结果是这样的。

with (import <nixpkgs> {});
let
  env = bundlerEnv {
    name = "site-bundler-env";
    ruby = ruby_2_5;
    gemdir  = ./.;
  };
in mkShell {
  buildInputs = [ env env.wrappedRuby ];
}

包括bundix生成的gemset.nix 的全部修改都在这个提交中。

这时,我惊讶地发现,我可以在我的nix-shell 中运行rails server ,一切都运行得很好🚀

$ nix-shell

# ...

$ rails s
=> Booting Puma
=> Rails 5.2.4.3 application starting in development
=> Run `rails server -h` for more startup options

# ...

Started GET "/" for ::1 at 2020-09-10 18:05:37 +0100
Processing by PagesController#show as HTML

# ...

Completed 200 OK in 170ms (Views: 23.9ms)

观察结果

值得注意的是,在上述诡计的早期,我被错误的Ruby版本困住了一段时间,我所做的一切都无法改变它。最后我删除了我的/nix/store 目录中的一堆东西来解决这个问题。虽然这可能不是解决这个问题的正确方法,但我真的很欣赏这种方式,即通过一系列的符号链接,比较容易弄清楚各种可执行文件是如何被提供给你的环境的。

我还发现,不可能(至少在使用bundlerEnv )指定你想使用的捆绑器的版本--它似乎在v2.1.4版本中被修复了

接下来的步骤

我仍然有兴趣研究如何让一个项目使用特定的Ruby补丁版本,并且能够锁定bundler的确切版本。我一直在阅读关于nix flakes的文章,虽然我还没有完全理解它们,但我认为它们可能是我正在寻找的东西,因为它们有一个 "锁文件",我相信它可以锁定你的依赖关系,以确保可重复性。

不过,我还是觉得这有点扯远了。我的主要目标是能够在同一台电脑上拥有多个Rails项目,并使用不同口味和版本的数据库,等等。所以我想我的下一步应该是为一个使用数据库的Rails项目建立一个开发环境。

更新:我很晚才意识到,一些运行时的依赖(例如node.js和yarn)是由安装在我的OSX环境中的操作系统包来满足的,也就是说,我忘了把nix shell从这个环境中隔离出来,我计划很快解决这个问题。