1<section xmlns="http://docbook.org/ns/docbook"
2 xmlns:xlink="http://www.w3.org/1999/xlink"
3 xml:id="sec-language-ruby">
4
5<title>Ruby</title>
6
7<para>There currently is support to bundle applications that are packaged as
8Ruby gems. The utility "bundix" allows you to write a
9<filename>Gemfile</filename>, let bundler create a
10<filename>Gemfile.lock</filename>, and then convert this into a nix
11expression that contains all Gem dependencies automatically.
12</para>
13
14<para>For example, to package sensu, we did:</para>
15
16<screen>
17<![CDATA[$ cd pkgs/servers/monitoring
18$ mkdir sensu
19$ cd sensu
20$ cat > Gemfile
21source 'https://rubygems.org'
22gem 'sensu'
23$ $(nix-build '<nixpkgs>' -A bundix --no-out-link)/bin/bundix --magic
24$ cat > default.nix
25{ lib, bundlerEnv, ruby }:
26
27bundlerEnv rec {
28 name = "sensu-${version}";
29
30 version = (import gemset).sensu.version;
31 inherit ruby;
32 # expects Gemfile, Gemfile.lock and gemset.nix in the same directory
33 gemdir = ./.;
34
35 meta = with lib; {
36 description = "A monitoring framework that aims to be simple, malleable, and scalable";
37 homepage = http://sensuapp.org/;
38 license = with licenses; mit;
39 maintainers = with maintainers; [ theuni ];
40 platforms = platforms.unix;
41 };
42}]]>
43</screen>
44
45<para>Please check in the <filename>Gemfile</filename>,
46<filename>Gemfile.lock</filename> and the
47<filename>gemset.nix</filename> so future updates can be run easily.
48</para>
49
50<para>For tools written in Ruby - i.e. where the desire is to install
51a package and then execute e.g. <command>rake</command> at the command
52line, there is an alternative builder called <literal>bundlerApp</literal>.
53Set up the <filename>gemset.nix</filename> the same way, and then, for
54example:
55</para>
56
57<screen>
58<![CDATA[{ lib, bundlerApp }:
59
60bundlerApp {
61 pname = "corundum";
62 gemdir = ./.;
63 exes = [ "corundum-skel" ];
64
65 meta = with lib; {
66 description = "Tool and libraries for maintaining Ruby gems.";
67 homepage = https://github.com/nyarly/corundum;
68 license = licenses.mit;
69 maintainers = [ maintainers.nyarly ];
70 platforms = platforms.unix;
71 };
72}]]>
73</screen>
74
75<para>The chief advantage of <literal>bundlerApp</literal> over
76<literal>bundlerEnv</literal> is the executables introduced in the
77environment are precisely those selected in the <literal>exes</literal>
78list, as opposed to <literal>bundlerEnv</literal> which adds all the
79executables made available by gems in the gemset, which can mean e.g.
80<command>rspec</command> or <command>rake</command> in unpredictable
81versions available from various packages.
82</para>
83
84<para>Resulting derivations for both builders also have two helpful
85attributes, <literal>env</literal> and <literal>wrappedRuby</literal>.
86The first one allows one to quickly drop into
87<command>nix-shell</command> with the specified environment present.
88E.g. <command>nix-shell -A sensu.env</command> would give you an
89environment with Ruby preset so it has all the libraries necessary
90for <literal>sensu</literal> in its paths. The second one can be
91used to make derivations from custom Ruby scripts which have
92<filename>Gemfile</filename>s with their dependencies specified. It is
93a derivation with <command>ruby</command> wrapped so it can find all
94the needed dependencies. For example, to make a derivation
95<literal>my-script</literal> for a <filename>my-script.rb</filename>
96(which should be placed in <filename>bin</filename>) you should run
97<command>bundix</command> as specified above and then use
98<literal>bundlerEnv</literal> like this:
99</para>
100
101<programlisting>
102<![CDATA[let env = bundlerEnv {
103 name = "my-script-env";
104
105 inherit ruby;
106 gemfile = ./Gemfile;
107 lockfile = ./Gemfile.lock;
108 gemset = ./gemset.nix;
109};
110
111in stdenv.mkDerivation {
112 name = "my-script";
113 buildInputs = [ env.wrappedRuby ];
114 script = ./my-script.rb;
115 buildCommand = ''
116 install -D -m755 $script $out/bin/my-script
117 patchShebangs $out/bin/my-script
118 '';
119}]]>
120</programlisting>
121
122</section>