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>