<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>Space Vatican - Home</title>
  <id>tag:www.spacevatican.org,2012:mephisto/</id>
  <generator version="0.8.0" uri="http://mephistoblog.com">Mephisto Drax</generator>
  <link href="http://www.spacevatican.org/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://www.spacevatican.org/" rel="alternate" type="text/html"/>
  <updated>2012-05-12T23:23:57Z</updated>
  <entry xml:base="http://www.spacevatican.org/">
    <author>
      <name>fred</name>
    </author>
    <id>tag:www.spacevatican.org,2012-05-12:670</id>
    <published>2012-05-12T23:17:00Z</published>
    <updated>2012-05-12T23:23:57Z</updated>
    <category term="elasticsearch"/>
    <link href="http://www.spacevatican.org/2012/5/12/elasticsearch-native-scripts-for-dummies" rel="alternate" type="text/html"/>
    <title>Elasticsearch native scripts for dummies</title>
<content type="html">
            &lt;p&gt;One of the cool things about elasticsearch is the ability to provide scripts that calculate custom ordering or that filter based on application specific logic. Out of the box elasticsearch supports mvel and there are also plugins that support python and javascript. I imagine that it would be pretty simple to provide a jruby one too. &lt;/p&gt;

&lt;p&gt;You can also use so called native scripts, written in java. These are faster than the other alternatives and may also be handier if you need to integrate with some existing java code to calculate your scores. There is some info out there on how to build these but they presuppose a certain familiarity with java and its environment. If you're anything like me then you can bumble through java syntax readily enough but classpaths, jars etc. are a bit of a mystery. So here's how I got a native script running with instructions that (hopefully) presuppose almost no knowledge of java.  I'm no java wizard - I may well be doing something dumb - but this is working well enough for us in production.&lt;/p&gt;

&lt;p&gt;This example does the same as one of the examples from the &lt;a href=&quot;http://www.elasticsearch.org/guide/reference/query-dsl/custom-score-query.html&quot;&gt;documentation&lt;/a&gt; - the score is set to a function of one of the doc's fields and two parameters.&lt;/p&gt;

&lt;p&gt;The only thing that elasticsearch requires is that you provide a class that impements the &lt;code&gt;NativeScriptFactory&lt;/code&gt; interface, and all that has to do is implement a &lt;code&gt;newScript&lt;/code&gt; method, that returns an instance of something implementing the &lt;code&gt;ExecutableScript&lt;/code&gt; interface, which in turn implements methods like &lt;code&gt;runAsDouble&lt;/code&gt;, &lt;code&gt;runAsLong&lt;/code&gt; (thank you java for your conciseness and absence of ceremony). This being java you're supposed to put this in a package named in a reverse dns style. My factory class looks like this&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;&lt;span class=&quot;Keyword&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;org.spacevatican.elasticsearchexample&lt;/span&gt;;

&lt;span class=&quot;Keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;org.elasticsearch.common.Nullable&lt;/span&gt;;
&lt;span class=&quot;Keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;org.elasticsearch.script.ExecutableScript&lt;/span&gt;;
&lt;span class=&quot;Keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;org.elasticsearch.script.NativeScriptFactory&lt;/span&gt;;

&lt;span class=&quot;Keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;org.spacevatican.elasticsearchexample.CustomScript&lt;/span&gt;;

&lt;span class=&quot;Keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;java.util.Map&lt;/span&gt;;

&lt;span class=&quot;Storage&quot;&gt;public &lt;/span&gt;&lt;span class=&quot;Storage&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;CustomScriptFactory&lt;/span&gt; &lt;span class=&quot;Storage&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;Storage&quot;&gt;NativeScriptFactory&lt;/span&gt; {

  @&lt;span class=&quot;Support&quot;&gt;Override&lt;/span&gt; &lt;span class=&quot;Storage&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;Storage&quot;&gt;ExecutableScript&lt;/span&gt; newScript (@&lt;span class=&quot;Storage&quot;&gt;Nullable&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;Support&quot;&gt;String&lt;/span&gt;,&lt;span class=&quot;Support&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;&amp;gt;&lt;/span&gt; params){
    &lt;span class=&quot;Keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;Storage&quot;&gt;CustomScript&lt;/span&gt;(params);
  }
}
&lt;/pre&gt;

&lt;p&gt;This is basically 100% boilerplate. The &lt;code&gt;newScript&lt;/code&gt; method just creates an instance of my script class passing through the params object. That params object is just the params option you can specify when you invoke a custom script.&lt;/p&gt;

&lt;p&gt;The script class is where the calculations actually happen&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;&lt;span class=&quot;Keyword&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;org.spacevatican.elasticsearchexample&lt;/span&gt;;

&lt;span class=&quot;Keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;org.elasticsearch.common.Nullable&lt;/span&gt;;
&lt;span class=&quot;Keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;org.elasticsearch.script.ExecutableScript&lt;/span&gt;;
&lt;span class=&quot;Keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;org.elasticsearch.script.NativeScriptFactory&lt;/span&gt;;
&lt;span class=&quot;Keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;org.elasticsearch.script.AbstractDoubleSearchScript&lt;/span&gt;;

&lt;span class=&quot;Keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;java.util.Map&lt;/span&gt;;
&lt;span class=&quot;Keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;java.lang.Math&lt;/span&gt;;

&lt;span class=&quot;Storage&quot;&gt;public &lt;/span&gt;&lt;span class=&quot;Storage&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;CustomScript&lt;/span&gt; &lt;span class=&quot;Storage&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;Storage&quot;&gt;AbstractDoubleSearchScript&lt;/span&gt; {

    &lt;span class=&quot;Storage&quot;&gt;double&lt;/span&gt; base;
    &lt;span class=&quot;Storage&quot;&gt;double&lt;/span&gt; exp;

    &lt;span class=&quot;Storage&quot;&gt;public &lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;CustomScript&lt;/span&gt;(@&lt;span class=&quot;Storage&quot;&gt;Nullable&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;Map&lt;/span&gt;&amp;lt;&lt;span class=&quot;Support&quot;&gt;String&lt;/span&gt;,&lt;span class=&quot;Support&quot;&gt;Object&lt;/span&gt;&amp;gt; params){
      base = ((&lt;span class=&quot;Support&quot;&gt;Double&lt;/span&gt;)params.get(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;base&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)).doubleValue();
      exp = ((&lt;span class=&quot;Support&quot;&gt;Double&lt;/span&gt;)params.get(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;exp&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)).doubleValue();
    }

    @&lt;span class=&quot;Support&quot;&gt;Override&lt;/span&gt;
    &lt;span class=&quot;Storage&quot;&gt;public &lt;/span&gt;&lt;span class=&quot;Storage&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;runAsDouble&lt;/span&gt;() {
      &lt;span class=&quot;Storage&quot;&gt;double&lt;/span&gt; a = doc().numeric(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;a&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).getDoubleValue();

      &lt;span class=&quot;Keyword&quot;&gt;return&lt;/span&gt; a &lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;Math&lt;/span&gt;.pow(base, exp);
    }
}
&lt;/pre&gt;

&lt;p&gt;I'm writing a script that returns a double score, so I've derived from &lt;code&gt;AbstractDoubleSearchScript&lt;/code&gt; and implemented &lt;code&gt;runAsDouble&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the constructor I'm just stashing the parameters I'm interested in. The actual computation happens in &lt;code&gt;runAsDouble&lt;/code&gt;. This part is pretty similar to what you'd do in an mvel script, just with a little more ceremony.&lt;/p&gt;

&lt;h2&gt;Building it&lt;/h2&gt;

&lt;p&gt;Here's where I got confused initially - I know little of java packaging conventions and most of the material I found covering native scripts glossed over this bit. I ended up with the following directory structure&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;elasticsearch-root
  lib/
    elasticsearch-0.19.3.jar
    ...
  config/
    elasticsearch.yml
    ...
  elasticsearch-example
    org/
      spacevatican/
        elasticsearchexample/
          CustomScript.java
          CustomScriptFactory.java
    Rakefile
  ...
&lt;/pre&gt;

&lt;p&gt;elasticsearch-root is just wherever you've installed elastic search. I haven't shown all the files/directories that make up elasticsearch itself. The org/spacevatican/elasticsearch set of directories mirrors the &lt;code&gt;org.spacevatican.elasticsearch&lt;/code&gt; package naming.&lt;/p&gt;

&lt;p&gt;The Rakefile defines a build task that builds a jar from these files. If you've put your elasticsearch install somewhere different relative to the Rakefile, you'll need to change the classpath.&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;&lt;span class=&quot;Keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;fileutils&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
task &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;compile&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do &lt;/span&gt;
  source &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;FileList&lt;/span&gt;[&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;**/*.java&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]
  sh &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;javac &lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;#{&lt;/span&gt;source&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;collect&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;StringEmbeddedSource&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;StringVariable&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;'&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;#{&lt;/span&gt;s&lt;span class=&quot;StringEmbeddedSource&quot;&gt;}&lt;/span&gt;&lt;/span&gt;'&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;StringEmbeddedSource&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;join&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;}&lt;/span&gt;&lt;/span&gt;  -classpath ../lib/elasticsearch-*.jar&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

task &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;clean&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;Support&quot;&gt;FileUtils&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Verbose&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;Dir&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;glob&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;**/*.class&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

task &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;package&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
  objects &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;FileList&lt;/span&gt;[&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;**/*.class&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]
  sh &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;jar cf MyNativeScript.jar &lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;#{&lt;/span&gt;objects&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;collect&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;StringEmbeddedSource&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;StringVariable&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;'&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;#{&lt;/span&gt;s&lt;span class=&quot;StringEmbeddedSource&quot;&gt;}&lt;/span&gt;&lt;/span&gt;'&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;StringEmbeddedSource&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;join&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

task &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;build&lt;/span&gt; =&amp;gt; [&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;clean&lt;/span&gt;, &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;compile&lt;/span&gt;, &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;package&lt;/span&gt;]
&lt;/pre&gt;

&lt;p&gt;All this Rakefile does is compile all the *.java files we can find, adding the elasticsearch jar to the classpath (since we're extending classes provided by elasticsearch). If you wanted to use other java libs, you'd need to add them to this classpath. The package task then just pops them all in a jar file (the &lt;code&gt;jar&lt;/code&gt; command behaves not that differently to &lt;code&gt;tar&lt;/code&gt; in basic use). You then need to place this jar file somewhere where elasticsearch will find and load it. The easiest thing is probably to copy it into elasticsearch's lib folder. &lt;/p&gt;

&lt;h2&gt;Installing it&lt;/h2&gt;

&lt;p&gt;Now that we've got our native script built, the last thing we need to do is tell elasticsearch how to use it. Add something like this to your elastic search configuration (by default this is the config/elasticsearch.yml file in your elasticsearch directory)&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;&lt;span class=&quot;MetaTagAll&quot;&gt;&lt;span class=&quot;MetaTagInline&quot;&gt;script.native&lt;/span&gt;&lt;span class=&quot;MetaTagAll&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;MetaTagAll&quot;&gt;&lt;span class=&quot;MetaTagInline&quot;&gt;mynativescript.type&lt;/span&gt;&lt;span class=&quot;MetaTagAll&quot;&gt;:&lt;/span&gt; &lt;/span&gt;org.spacevatican.elasticsearchexample.CustomScriptFactory
&lt;/pre&gt;

&lt;p&gt;This tells elasticsearch that you're adding a native script called &lt;code&gt;mynativescript&lt;/code&gt; and that when you ask it to use mynativescript it should use the &lt;code&gt;org.spacevatican.elasticsearchexample.CustomScriptFactory&lt;/code&gt; class to create new script instances. The name you use here is completely arbitrary - it doesn't need to match any of your class names, file names etc.&lt;/p&gt;

&lt;p&gt;Restart elasticsearch and you should be able to invoke the script. If it can't find the class referenced here elasticsearch should fail to startup.&lt;/p&gt;

&lt;h2&gt;Using it&lt;/h2&gt;

&lt;p&gt;First, lets stick some entries in the index&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;curl -XPUT 'http://localhost:9200/example/doc/1' -d '{
    &amp;quot;name&amp;quot; : &amp;quot;doc 1&amp;quot;,
    &amp;quot;a&amp;quot; : 4
}'

curl -XPUT 'http://localhost:9200/example/doc/2' -d '{
    &amp;quot;name&amp;quot; : &amp;quot;doc 2&amp;quot;,
    &amp;quot;a&amp;quot; : 16
}'
&lt;/pre&gt;

&lt;p&gt;To use a script you specify the name used in the yaml file (not the name of your script class, factory class, jar file or anything like that). You also need to specify &lt;code&gt;&quot;lang&quot;:&quot;native&quot;&lt;/code&gt; or else elasticsearch will try to interpret your script name as an mvel expression.&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;curl -XGET 'http://localhost:9200/example/doc/_search' -d '{
  &amp;quot;query&amp;quot; :{
     &amp;quot;custom_score&amp;quot;: {
       &amp;quot;query&amp;quot; : { &amp;quot;match_all&amp;quot;: {}},
       &amp;quot;script&amp;quot; : &amp;quot;mynativescript&amp;quot;,
       &amp;quot;params&amp;quot; :{
          &amp;quot;base&amp;quot;: 2.0,
          &amp;quot;exp&amp;quot;: 3.0
       },
       &amp;quot;lang&amp;quot;: &amp;quot;native&amp;quot;
     }
  }
}'
&lt;/pre&gt;

&lt;p&gt;And you should see that the scores for the two hits are 0.5 and 2.0 as you would expect.&lt;/p&gt;

&lt;p&gt;The code for this mini native script is on &lt;a href=&quot;https://github.com/fcheung/elasticsearch-example&quot;&gt;github&lt;/a&gt;. If you try and use it, it assumes that you've checked out the repo into the folder that contains your elasticsearch install.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.spacevatican.org/">
    <author>
      <name>fred</name>
    </author>
    <id>tag:www.spacevatican.org,2012-03-02:640</id>
    <published>2012-03-02T23:54:00Z</published>
    <updated>2012-03-02T23:57:12Z</updated>
    <category term="Ruby"/>
    <link href="http://www.spacevatican.org/2012/3/2/ruby-bindings-for-liblinear" rel="alternate" type="text/html"/>
    <title>Ruby bindings for liblinear</title>
<content type="html">
            &lt;p&gt;There are already some &lt;a href=&quot;https://github.com/tomz/liblinear-ruby-swig&quot;&gt;ruby bindings&lt;/a&gt; but I've written my &lt;a href=&quot;https://github.com/fcheung/rubylinear&quot;&gt;own&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I mostly did this for fun, but I think swig sometimes gives you slightly unnatural feeling interfaces, because you're focussing too much on mapping C++ classes to your ruby classes. For example some liblinear methods take a &lt;code&gt;struct param&lt;/code&gt; argument. liblinear-ruby-swig mirrors this by proving an LParameter class that maps onto this:&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;  param &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;LParameter&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;new&lt;/span&gt;(&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;C&lt;/span&gt; =&amp;gt; &lt;span class=&quot;Constant&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;eps&lt;/span&gt; =&amp;gt; &lt;span class=&quot;Constant&quot;&gt;0.01&lt;/span&gt;)
  &lt;span class=&quot;SupportFunction&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;LModel&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;new&lt;/span&gt;(problem, param)
&lt;/pre&gt;

&lt;p&gt;but I'd rather write:&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;  &lt;span class=&quot;SupportFunction&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;RubyLinear&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Model&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;new&lt;/span&gt; problem, &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;c&lt;/span&gt; =&amp;gt; &lt;span class=&quot;Constant&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;eps&lt;/span&gt; =&amp;gt; &lt;span class=&quot;Constant&quot;&gt;0.01&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;I imagine that SWIG must incur some sort of overhead but I would have thought that was pretty negligible for something like liblinear where most of the heavy lifting happens in the library being wrapped.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.spacevatican.org/">
    <author>
      <name>fred</name>
    </author>
    <id>tag:www.spacevatican.org,2012-01-26:551</id>
    <published>2012-01-26T13:40:00Z</published>
    <updated>2012-01-26T13:45:47Z</updated>
    <category term="iphone"/>
    <category term="Ruby"/>
    <link href="http://www.spacevatican.org/2012/1/26/seeding-coredata-databases-with-ruby" rel="alternate" type="text/html"/>
    <title>Seeding CoreData databases with ruby</title>
<content type="html">
            &lt;p&gt;If you're writing an iOS app that uses Core Data then you may well want to ship it with an initial database (which potentially gets over the air updates later on).&lt;/p&gt;

&lt;p&gt;On iOS, CoreData stores always use sqlite3 as their backend. You could create a sqlite database directly, but you'd have to reverse engineer the way apple uses sqlite, ensure that you use the same name manging for table and column names, generate the same meta data used for persistent store migration etc. Too brittle for my liking.&lt;/p&gt;

&lt;p&gt;Luckily both RubyCocoa and MacRuby allow you to access the Core Data framework from a ruby script. The former is bundled with Mac OS X since 10.5 (you will need to use the system ruby). RubyCocoa has some clunkier syntax because it doesn't have the benefit of the extensions to ruby, however at the moment MacRuby doesn't quite work with Active Record, which is where I was getting my seed data from. If your data is coming from else where, this may not be a problem. Other than the slight syntax differences around the handling of Objective-C's sort-of-named-arguments the code is the same&lt;/p&gt;

&lt;p&gt;The RubyCocoa version looks like this&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;
&lt;span class=&quot;Keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;rubygems&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;osx/cocoa&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;Variable&quot;&gt;OSX&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;require_framework&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;CoreData&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;Keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;CoreDataStore&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;create_entity&lt;/span&gt; name, props&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;{}, relationships&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;{}
    entity &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;OSX&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;NSEntityDescription&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;insertNewObjectForEntityForName_inManagedObjectContext&lt;/span&gt;(name, context)
    props.&lt;span class=&quot;Entity&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do &lt;/span&gt;|&lt;span class=&quot;Variable&quot;&gt;k&lt;/span&gt;,&lt;span class=&quot;Variable&quot;&gt;v&lt;/span&gt;|
      entity.&lt;span class=&quot;Entity&quot;&gt;setValue_forKey&lt;/span&gt; v, k
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
    relationships.&lt;span class=&quot;Entity&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do &lt;/span&gt;|&lt;span class=&quot;Variable&quot;&gt;k&lt;/span&gt;, &lt;span class=&quot;Variable&quot;&gt;objects&lt;/span&gt;|
      collection &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; entity.&lt;span class=&quot;Entity&quot;&gt;mutableSetValueForKey&lt;/span&gt;(k)
      objects.&lt;span class=&quot;Entity&quot;&gt;each&lt;/span&gt; {|&lt;span class=&quot;Variable&quot;&gt;o&lt;/span&gt;| collection.&lt;span class=&quot;Entity&quot;&gt;addObject&lt;/span&gt; o}
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
    entity
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;initialize&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;data_store_path&lt;span class=&quot;Variable&quot;&gt;,&lt;/span&gt; mom_path&lt;/span&gt;)
    &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;data_store_path&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; data_store_path
    &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;mom_path&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; mom_path
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;context&lt;/span&gt;
    &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;context&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;OSX&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;NSManagedObjectContext&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;alloc&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;init&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;tap&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do &lt;/span&gt;|&lt;span class=&quot;Variable&quot;&gt;context&lt;/span&gt;|
      &lt;span class=&quot;SupportFunction&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;OSX&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;NSManagedObjectModel&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;alloc&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;initWithContentsOfURL&lt;/span&gt;(
          &lt;span class=&quot;Variable&quot;&gt;OSX&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;NSURL&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;fileURLWithPath&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;mom_path&lt;/span&gt;))
      coordinator &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;OSX&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;NSPersistentStoreCoordinator&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;alloc&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;initWithManagedObjectModel&lt;/span&gt;(&lt;span class=&quot;SupportFunction&quot;&gt;model&lt;/span&gt;)

      result, error &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; coordinator.&lt;span class=&quot;Entity&quot;&gt;addPersistentStoreWithType_configuration_URL_options_error&lt;/span&gt;(
         &lt;span class=&quot;Variable&quot;&gt;OSX&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;NSSQLiteStoreType&lt;/span&gt;, &lt;span class=&quot;Constant&quot;&gt;nil&lt;/span&gt;, &lt;span class=&quot;Variable&quot;&gt;OSX&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;NSURL&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;fileURLWithPath&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;data_store_path&lt;/span&gt;), &lt;span class=&quot;Constant&quot;&gt;nil&lt;/span&gt;)
      &lt;span class=&quot;Keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;!&lt;/span&gt;result
        &lt;span class=&quot;Keyword&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;Add persistent store failed: &lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;#{&lt;/span&gt;error&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;description&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
      context.&lt;span class=&quot;Entity&quot;&gt;setPersistentStoreCoordinator&lt;/span&gt; coordinator
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;save&lt;/span&gt;
    res, error &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; context.&lt;span class=&quot;Entity&quot;&gt;save_&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;!&lt;/span&gt;res
      &lt;span class=&quot;Keyword&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;Save failed: &lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;#{&lt;/span&gt;error&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;description&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
    res
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Having done this, you use it like this&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;store &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;CoreDataStore&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;new&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;seedData.sqlite&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;yourmodel.mom&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)
blog &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; store.&lt;span class=&quot;Entity&quot;&gt;create_entity&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;Blog&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;title&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt; =&amp;gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;Hello world&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;body&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt; =&amp;gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;it's a fine day&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
store.&lt;span class=&quot;Entity&quot;&gt;create_entity&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;Comment&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;body&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt; =&amp;gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;I Agree&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;blog&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt; =&amp;gt; blog
store.save
&lt;/pre&gt;

&lt;p&gt;The too arguments are the path to the file you want to store the data in, and the path to your model file.&lt;/p&gt;

&lt;h2&gt;Your Mom's a data model&lt;/h2&gt;

&lt;p&gt;You may be wondering what a .mom file is. In XCode you work with a .xcdatamodel file. When you build your app, this is compiled down into a .mom file. You can also do it your self by running
&lt;code&gt;
/Developer/usr/bin/momc my&lt;em&gt;model.xcdatamodel my&lt;/em&gt;model.mom
&lt;/code&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.spacevatican.org/">
    <author>
      <name>fred</name>
    </author>
    <id>tag:www.spacevatican.org,2012-01-26:631</id>
    <published>2012-01-26T13:40:00Z</published>
    <updated>2012-04-26T17:50:48Z</updated>
    <category term="Rails"/>
    <category term="Ruby"/>
    <category term="debugging"/>
    <category term="leaks"/>
    <category term="rails"/>
    <link href="http://www.spacevatican.org/2012/1/26/memory-leak-in-yaml-on-ruby-1-9-2" rel="alternate" type="text/html"/>
    <title>Memory leak in YAML on ruby 1.9.2</title>
<content type="html">
            &lt;p&gt;We recently upgraded to delayed_job 3.0  and immediately started seeing some major memory leaks in our app, in the delayed job workers, passenger instances and even standalone scripts which don't even use delayed job. In the end I tracked it down to a bug in &lt;code&gt;YAML.load&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Out of the box YAML support can be provided by 1 of 2 backends in ruby 1.9 : syck and psych. Syck is an older implementation based around a no longer support C library, whereas psych uses the newer and supported libYAML. The default backend is psych, but earlier version of delayed_job did work with psych, and so were forcing the yaml engine to syck (which doesn't have this bug). When we upgraded to 3.0 they fixed their problems with psych and so we (unintentionally) started used psych. 
 Unfortunately the version of psych that comes with ruby 1.9 has a memory leak in YAML.load. If &lt;code&gt;YAML::ENGINE.yamler&lt;/code&gt; is 'psych'  and &lt;code&gt;Psych::VERSION&lt;/code&gt; is 1.0.0 then you are using an affected version&lt;/p&gt;

&lt;p&gt;In particular this means that &lt;strong&gt;each time you load a model with serialised attributes, you leak memory&lt;/strong&gt;. One of our very frequently used models has some serialized columns so that was why we were leaking. Delayed job obviously does a lot of yaml loading and so its workers were haemorrhaging memory.&lt;/p&gt;

&lt;h1&gt;Plugging the leaks&lt;/h1&gt;

&lt;p&gt;It took a bit of work to narrow down the leaks we were seeing to yaml but once that was done it turn out a few people have already written about this, notably over at &lt;a href=&quot;http://nerdd.dk/posts/YAML-load-considered-harmful&quot;&gt;nerdd.dk&lt;/a&gt; but I am somewhat amazed that knowledge of this issue is not more widespread. The issue is perhaps clouded by the fact that if libyaml isn't available when ruby is built ruby will just skip building psych (in which case syck is the only backend). Ruby 1.9.3 has a fixed version of psych, but disappointingly currently available versions of 1.9.2 (currently p290) still have this bug, 18 months after the release of 1.9.2.&lt;/p&gt;

&lt;p&gt;Luckily there is a gem version of psych, however using it can be a bit fiddly if (as most rails apps do) you use bundler. Bundler loads psych early on its its setup process so you can't just stick psych in your Gemfile - both versions end up being loaded which causes an ugly mess.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://nerdd.dk/posts/YAML-load-considered-harmful&quot;&gt;nerdd.dk&lt;/a&gt; has a series of posts about how they tacked the various issues. In the end what I did was&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;set up &lt;/code&gt;config/setup_load_paths.rb&lt;/code&gt; to keep passenger happy:&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class=&quot;twilight&quot;&gt;&lt;span class=&quot;Keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;rubygems&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
gem &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;psych&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;bundler&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Support&quot;&gt;Bundler&lt;/span&gt;.setup
&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;edit config/boot.rb to do &lt;code&gt;gem 'psych'&lt;/code&gt; just after &lt;code&gt;require 'rubygems'&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;hacked the stub executable for &lt;code&gt;bundle&lt;/code&gt; to also have &lt;code&gt;gem 'psych'&lt;/code&gt; after ruby gems is loaded&lt;/li&gt;
&lt;li&gt;added the same version of psych to the Gemfile as was installed outside of bundler&lt;/li&gt;
&lt;/ul&gt;
          </content>  </entry>
  <entry xml:base="http://www.spacevatican.org/">
    <author>
      <name>fred</name>
    </author>
    <id>tag:www.spacevatican.org,2012-01-25:630</id>
    <published>2012-01-25T09:29:00Z</published>
    <updated>2012-01-27T09:13:01Z</updated>
    <category term="Ruby"/>
    <category term="1.9.2"/>
    <category term="1.9.3"/>
    <category term="ruby"/>
    <category term="upgrade"/>
    <link href="http://www.spacevatican.org/2012/1/25/a-small-difference-between-1-9-2-and-1-9-3" rel="alternate" type="text/html"/>
    <title>A small difference between 1.9.2 and 1.9.3</title>
<content type="html">
            &lt;p&gt;I was looking at moving an application to ruby 1.9.3 and was getting some strange syntax errors along the lines of &quot;syntax error, unexpected keyword_do_block&quot; on code that was working fine on 1.9.2. I spend quite a few minutes staring at the code which looked completely benign.&lt;/p&gt;

&lt;p&gt;It turns out the ruby 1.9.2 is a bit &lt;a href=&quot;https://bugs.ruby-lang.org/issues/5540&quot;&gt;too permissive&lt;/a&gt;: it allows you to write an extra comma after your argument list but before the &lt;code&gt;do&lt;/code&gt; that marks the start of your block.&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;  some_method arg1, arg2, &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
    ...
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;ruby 1.9.3 on the other hand won't accept this.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.spacevatican.org/">
    <author>
      <name>fred</name>
    </author>
    <id>tag:www.spacevatican.org,2012-01-22:629</id>
    <published>2012-01-22T12:56:00Z</published>
    <updated>2012-02-13T09:15:07Z</updated>
    <category term="c"/>
    <category term="ruby"/>
    <link href="http://www.spacevatican.org/2012/1/22/passing-a-block-from-a-method-written-in-c" rel="alternate" type="text/html"/>
    <title>Passing a block from a method written in c</title>
<content type="html">
            &lt;p&gt;Everynow and again I wind up rewriting a ruby performance hotspot in C. It happens infrequently enough that I always forget the C api for passing a block implemented in C to some ruby code. Hopefully writing this down will help me remember this in the future. Today, I wanted to call &lt;code&gt;find_each&lt;/code&gt; on a class, using a C function as the block. Pre ruby 1.9 you need to call &lt;code&gt;rb_iterate&lt;/code&gt; which always did my head in, but in 1.9 you use &lt;code&gt;rb_block_call&lt;/code&gt; which is way more straightforward (&lt;code&gt;rb_iterate&lt;/code&gt; is still there but deprecated)&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;    
&lt;span class=&quot;Storage&quot;&gt;static&lt;/span&gt; VALUE &lt;span class=&quot;Entity&quot;&gt;block_meth&lt;span class=&quot;Entity&quot;&gt;od&lt;/span&gt;&lt;/span&gt;(VALUE yielded_object, VALUE context, &lt;span class=&quot;Storage&quot;&gt;int&lt;/span&gt; argc, VALUE argv[]){
    &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;/*&lt;/span&gt; do work here&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;  Don't forget to return a valid VALUE (eg. Qnil)&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;*/&lt;/span&gt;&lt;/span&gt;
}

&lt;span class=&quot;Storage&quot;&gt;static&lt;/span&gt; VALUE some_method(VALUE self){
    &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;/*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;      set klass to the class we want to call find_each on&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;      set ctx  to a pointer to some context &lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;    &lt;span class=&quot;Comment&quot;&gt;*/&lt;/span&gt;&lt;/span&gt;
    VALUE args[&lt;span class=&quot;Constant&quot;&gt;1&lt;/span&gt;];
    args[&lt;span class=&quot;Constant&quot;&gt;0&lt;/span&gt;] = INT2FIX(&lt;span class=&quot;Constant&quot;&gt;0&lt;/span&gt;);
    &lt;span class=&quot;Keyword&quot;&gt;return&lt;/span&gt; rb_block_call(klass, rb_intern(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;find_each&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;), &lt;span class=&quot;Constant&quot;&gt;1&lt;/span&gt;, args, RUBY_METHOD_FUNC(block_method), (VALUE)ctx);
}
&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;block_method&lt;/code&gt; is the C function that implements my block. &lt;code&gt;some_method&lt;/code&gt; is the function that wishes to call &lt;code&gt;find_each&lt;/code&gt; on &lt;code&gt;klass&lt;/code&gt; passing the block. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;rb_block_call&lt;/code&gt; takes the 4th argument you give it and sets things up so that the ruby method call made will use that method as a block. The last argument passed to &lt;code&gt;rb_block_call&lt;/code&gt; is some context that is the second argument to your block method.&lt;/p&gt;

&lt;p&gt;The first 4 parameters are straight forward: the object to call the method on, what method to call and the arguments for that method, expressed as a length and an array of VALUE (here I am passing just one argument, 0, as an example).&lt;/p&gt;

&lt;p&gt;If you block yields more than one value then they will be in the argc &amp;amp; argv parameters in block_method. As I understand it, yielded_object will always be the same as argv[0]&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.spacevatican.org/">
    <author>
      <name>fred</name>
    </author>
    <id>tag:www.spacevatican.org,2011-12-19:618</id>
    <published>2011-12-19T13:55:00Z</published>
    <updated>2011-12-19T14:15:12Z</updated>
    <link href="http://www.spacevatican.org/2011/12/19/dressipi-is-hiring-again" rel="alternate" type="text/html"/>
    <title>Dressipi is hiring</title>
<content type="html">
            &lt;p&gt;Dressipi is looking for a mid to senior level developer to join their development team. If you love solving problems, teasing meaning out of large volumes of data and have a passion for writing well designed and tested code we'd love to hear from you. We develop recommendation systems that make shopping simpler and looking good effortless, using a combination of knowledgeable stylists and clever technology.&lt;/p&gt;

&lt;p&gt;We're looking for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a seasoned software engineer, with at least a year's experience of Ruby on Rails&lt;/li&gt;
&lt;li&gt;good knowledge of MySQL (exposure to other databases/datastores a plus)&lt;/li&gt;
&lt;li&gt;able to hit the ground running with a large and growing Rails 3 application.&lt;/li&gt;
&lt;li&gt;TDD/BDD experience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some experience of recommendation systems or machine learning techniques would be useful but by no means required. Frontend skills (HTML, CSS, jQuery) appreciated but not required.&lt;/p&gt;

&lt;p&gt;You'll join a small, dynamic team to work on all the technology that powers Dressipi, from consumer facing web applications to heavy backend calculations and mobile apps. No knowledge (or interest in) fashion or clothes required - our delightful stylists have all the clothing expertise we need. &lt;/p&gt;

&lt;p&gt;As well as working with the rest of the development team you will be working closely with the stylists, encoding their unique knowledge and understanding of clothing into Dressipi's algorithms. &lt;/p&gt;

&lt;p&gt;You will take part in the full lifecycle of the product from understanding the business needs, to deploying the solution and analysing the resulting data. &lt;/p&gt;

&lt;p&gt;Dressipi tackles problems in a wide range of areas, including recommendation systems, text extraction, visual recognition, crowd sourcing and more. &lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.spacevatican.org/">
    <author>
      <name>fred</name>
    </author>
    <id>tag:www.spacevatican.org,2011-12-05:607</id>
    <published>2011-12-05T12:52:00Z</published>
    <updated>2011-12-15T13:32:22Z</updated>
    <category term="Rails"/>
    <category term="authlogic"/>
    <category term="rails"/>
    <link href="http://www.spacevatican.org/2011/12/5/request-specs-and-authlogic" rel="alternate" type="text/html"/>
    <title>Request specs and Authlogic</title>
<content type="html">
            &lt;p&gt;I was writing some rspec request specs the other day and was curious to notice that&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;&lt;span class=&quot;Entity&quot;&gt;before&lt;/span&gt;(&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;each&lt;/span&gt;) &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
  activate_authlogic
  &lt;span class=&quot;Support&quot;&gt;UserSession&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;create&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;user&lt;/span&gt;)
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;wasn't working: the code under test didn't think the user was logged in at all. The same code works fine for controller specs and the authlogic documentation asserts that functional and integration tests should behave identically in this respect. Everything should just work.&lt;/p&gt;

&lt;p&gt;Searching around revealed quite a few people with the same problem, all being told &quot;don't do this, have your user login via your login form&quot;. While obviously actually testing the login form is important, to do so for every single request spec that involves a logged in user seems over the top. Taken to its extreme, every single request spec involving a logged in user should have the user signing up, editing their preferences and generally replaying the entirety of the history involving in going from a non user of the site to an active user in the desired state. Also, I was curious as to what was going on.&lt;/p&gt;

&lt;h2&gt;Cookie issues&lt;/h2&gt;

&lt;p&gt;When you call &lt;code&gt;UserSession.create&lt;/code&gt; it validates the credentials provided (which is trivial when the arguments you pass are an actual user) and then stores the user's persistence token in a cookie (called &lt;code&gt;user_credentials&lt;/code&gt; by default). It expects to have access to a controller like object that it can use for accessing cookies, request parameters / headers and so on. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;AuthLogic::TestCase&lt;/code&gt; expects there to be a controller handing around, which in a controller spec / functional test there is (setup hooks create the controller, request &amp;amp; response ahead of time). In an integration spec on the hand the controller/request do not initially exist - Rails doesn't know what you're going to request. Because of this, Authlogic thinks you're testing from a model spec and so sets its cookies on a mock controller object. The Rails integration stack doesn't know anything about this mock controller object so when you make a request the authentication cookies never reach your controller(s).&lt;/p&gt;

&lt;p&gt;In integration tests a thing called an integration session is in charge of maintaining state between requests, such as cookies, so that's where Authlogic needs to be setting its cookies.&lt;/p&gt;

&lt;h2&gt;Solution&lt;/h2&gt;

&lt;p&gt;I would have liked to be able to just use the integration session as Authlogic's controller, but that didn't quite work out. Authlogic expects the controller to have a request from which it can slurp stuff like the &lt;code&gt;remote_ip&lt;/code&gt; but at the start of a request spec the request doesn't exist yet. In the end I did this&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt; cookies[&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;user_credentials&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;] &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;StringVariable&quot;&gt;&lt;span class=&quot;StringVariable&quot;&gt;@&lt;/span&gt;user&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;persistence_token&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;}&lt;/span&gt;&lt;/span&gt;::&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;StringVariable&quot;&gt;&lt;span class=&quot;StringVariable&quot;&gt;@&lt;/span&gt;user&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;send&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;StringVariable&quot;&gt;&lt;span class=&quot;StringVariable&quot;&gt;@&lt;/span&gt;user&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;class&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;primary_key&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;cookies[]=&lt;/code&gt; method falls through (via method_missing) to the integration session object, so this cookie is stored in the right place. It's a bit yucky in that it makes assumptions about what the format of cookie value should be, but I can live with that. You may need to change the name of the cookie - Authlogic sets that based on the name of the user class and that sort of stuff so will vary from app to app. If you're using capybara rather than webrat to make your requests then you can use &lt;code&gt;Capybara.current&lt;em&gt;session.driver.browser.set&lt;/em&gt;cookie&lt;/code&gt; to set the cookie.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.spacevatican.org/">
    <author>
      <name>fred</name>
    </author>
    <id>tag:www.spacevatican.org,2011-08-24:578</id>
    <published>2011-08-24T11:59:00Z</published>
    <updated>2011-08-24T12:00:23Z</updated>
    <category term="Rails"/>
    <category term="jobs"/>
    <link href="http://www.spacevatican.org/2011/8/24/dressipi-is-hiring" rel="alternate" type="text/html"/>
    <title>Dressipi is hiring</title>
<content type="html">
            &lt;p&gt;&lt;a href=&quot;http://dressipi.com&quot;&gt;Dressipi&lt;/a&gt; (where I work) is looking to hire a junior-ish software engineer to work on the guts of our various web applications, recommendation systems and mobile applications. We're a rails shop but we are above all looking for bright minds that can pick up new technologies with ease, so prior knowledge of rails is not required.&lt;/p&gt;

&lt;p&gt;If you're interested drop us a line at jobs ]at[ dressipi.com with a covering letter &amp;amp; CV or any questions you might have.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.spacevatican.org/">
    <author>
      <name>fred</name>
    </author>
    <id>tag:www.spacevatican.org,2011-08-03:569</id>
    <published>2011-08-03T20:04:00Z</published>
    <updated>2011-08-03T20:35:35Z</updated>
    <category term="Ruby"/>
    <category term="hack"/>
    <category term="objective-c"/>
    <category term="ruby"/>
    <link href="http://www.spacevatican.org/2011/8/3/nsdata-and-rubycocoa-on-10-7" rel="alternate" type="text/html"/>
    <title>NSData and RubyCocoa on 10.7</title>
<content type="html">
            &lt;p&gt;For some reason code like&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;OSX&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;NSData&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;dataWithBytes_length&lt;/span&gt;(data, data.&lt;span class=&quot;Entity&quot;&gt;length&lt;/span&gt;)
&lt;/pre&gt;

&lt;p&gt;segfaults on lion. Others have noted that this only occurs when the data contains bytes with the high bit set. This smells like something trying to interpret the string in some encoding when the string is in fact arbitrary binary data. &lt;/p&gt;

&lt;p&gt;I'd love to use MacRuby instead of RubyCocoa, but unfortunately MacRuby doesn't seem to be able to handle Active Record at the moment, so I can't use it (yet). I haven't had time to delve properly into how RubyCocoa converts between ruby and Objective-C objects but I was able to hack around by using ruby inline&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;
&lt;span class=&quot;Keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;inline&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;CFDataGenerator&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;begin&lt;/span&gt; 
    inline &lt;span class=&quot;Keyword&quot;&gt;do &lt;/span&gt;|&lt;span class=&quot;Variable&quot;&gt;builder&lt;/span&gt;|
      builder.&lt;span class=&quot;Entity&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&amp;lt;CoreFoundation/CoreFoundation.h&amp;gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
      builder.&lt;span class=&quot;Entity&quot;&gt;c_raw_singleton&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;String&quot;&gt;      &lt;/span&gt;
&lt;span class=&quot;String&quot;&gt;      static VALUE from_string(int argc, VALUE *args){&lt;/span&gt;
&lt;span class=&quot;String&quot;&gt;        CFDataRef d = CFDataCreate(NULL, RSTRING_PTR(args[0]), RSTRING_LEN(args[0]));    &lt;/span&gt;
&lt;span class=&quot;String&quot;&gt;        &lt;/span&gt;
&lt;span class=&quot;String&quot;&gt;        VALUE result;&lt;/span&gt;
&lt;span class=&quot;String&quot;&gt;        char type = '@';&lt;/span&gt;
&lt;span class=&quot;String&quot;&gt;        ocdata_to_rbobj(Qnil,&amp;amp;type, (const void *)&amp;amp;d, &amp;amp;result, false) ;&lt;/span&gt;
&lt;span class=&quot;String&quot;&gt;        return result;&lt;/span&gt;
&lt;span class=&quot;String&quot;&gt;      }&lt;/span&gt;
&lt;span class=&quot;String&quot;&gt;    &lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Then you can use &lt;code&gt;CFDataGenerator.from_string&lt;/code&gt; to convert ruby strings into nsdata instances. Remember to release the instance when you're done!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.spacevatican.org/">
    <author>
      <name>fred</name>
    </author>
    <id>tag:www.spacevatican.org,2011-07-30:535</id>
    <published>2011-07-30T16:29:00Z</published>
    <updated>2011-07-30T16:30:33Z</updated>
    <category term="Rails"/>
    <category term="spork"/>
    <category term="testing"/>
    <link href="http://www.spacevatican.org/2011/7/30/multispork" rel="alternate" type="text/html"/>
    <title>Spork and parallel_tests</title>
<content type="html">
            &lt;p&gt;What's more terrifying than being stabbed in the face with a spork? Being stabbed in the face with 2 sporks!&lt;/p&gt;

&lt;p&gt;In these days where even laptops are dual or quad-core &lt;a href=&quot;https://github.com/grosser/parallel_tests&quot;&gt;parallel_tests&lt;/a&gt; is a great tool for using all of those cores when running specs. Spork is another great tool for avoiding the overhead of loading rails, gems etc. when running tests. &lt;/p&gt;

&lt;p&gt;Out of the box spork and parallel_tests don't work together. When spork receives a request to run specs it aborts its current run, so only one of your parallel_spec instances actually gets to run. In addition parallel_spec's trick of setting an environment variable to indicate which test environment should be used doesn't work, because the runners forked by spork don't inherit the environment parallel_spec sets up.&lt;/p&gt;

&lt;p&gt;Fortunately there are at least two ways to get around this. I assume that you've already got parallel_tests up and running with the required extra databases, changes to database.yml etc.&lt;/p&gt;

&lt;h1&gt;Method 1: Multiple sporks&lt;/h1&gt;

&lt;h3&gt;Grab the right version of parallel_tests&lt;/h3&gt;

&lt;p&gt;Make sure you've got parallel_tests 0.5 or later (Previous versions deal with the .opts file in a different way)&lt;/p&gt;

&lt;h3&gt;Gentlemen, start your sporks&lt;/h3&gt;

&lt;p&gt;Run as many sporks as you need. Run the first one on port 8989 (the default), the second on port 8991, the third on 8992 and so on. You should set TEST_ENV_NUMBER in each one, so your invocations should look like&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;TEST_ENV_NUMBER&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt; spork &lt;span class=&quot;Keyword&quot;&gt;-&lt;/span&gt;p &lt;span class=&quot;Constant&quot;&gt;8989&lt;/span&gt;
&lt;span class=&quot;Variable&quot;&gt;TEST_ENV_NUMBER&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;2&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt; spork &lt;span class=&quot;Keyword&quot;&gt;-&lt;/span&gt;p &lt;span class=&quot;Constant&quot;&gt;8991&lt;/span&gt;
&lt;span class=&quot;Variable&quot;&gt;TEST_ENV_NUMBER&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;3&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt; spork &lt;span class=&quot;Keyword&quot;&gt;-&lt;/span&gt;p &lt;span class=&quot;Constant&quot;&gt;8992&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;and so on&lt;/p&gt;

&lt;h3&gt;Setup parallel_spec.opts&lt;/h3&gt;

&lt;p&gt;Edit spec/parallel_spec.opts so that it looks like &lt;/p&gt;

&lt;pre&gt;
--drb
--drb-port &amp;lt;%= 8989 + ENV['TEST_ENV_NUMBER'].to_i %&gt;
--format progress
--format ParallelSpecs::SpecRuntimeLogger --out tmp/parallel_profile.log
&lt;/pre&gt;

&lt;h3&gt;Profit:&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;parallel_spec&lt;/code&gt;. When rspec is invoked it passes the .opts file through erb so the first instance (TEST_ENV_NUMBER='') will have --drb-port set to 8989, the second to 8991 and so on. Each rspec will connect to a different spork instance that has the correct TEST_ENV_NUMBER setup.&lt;/p&gt;

&lt;h1&gt;Method 2: Single hacked spork&lt;/h1&gt;

&lt;p&gt;A disadvantage to method 1 is that you have multiple instances of spork sitting around, consuming memory. It requires extra keystrokes to ensure each spork instance is restarted properly and more cpu cycles are consumed everytime you restart spork. &lt;/p&gt;

&lt;h3&gt;Use my spork&lt;/h3&gt;

&lt;p&gt;My &lt;a href=&quot;https://github.com/fcheung/spork&quot;&gt;fork of spork&lt;/a&gt; doesn't prohibit running multiple spec runs concurrently and allows environment data parallel_tests requires to be passed in. I've only modified the forking strategy.&lt;/p&gt;

&lt;h3&gt;Setup script/spec&lt;/h3&gt;

&lt;pre class=&quot;twilight&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;!/usr/bin/env ruby&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;rspec&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;rspec/autorun&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;Keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;RSpec&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Core&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;DRbCommandLine&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;run&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;err&lt;span class=&quot;Variable&quot;&gt;,&lt;/span&gt; out&lt;/span&gt;)
        &lt;span class=&quot;Keyword&quot;&gt;begin&lt;/span&gt;
          &lt;span class=&quot;Variable&quot;&gt;DRb&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;start_service&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;druby://localhost:0&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
        &lt;span class=&quot;Keyword&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;SocketError&lt;/span&gt;, &lt;span class=&quot;Support&quot;&gt;Errno&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;EADDRNOTAVAIL&lt;/span&gt;
          &lt;span class=&quot;Variable&quot;&gt;DRb&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;start_service&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;druby://:0&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
        &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
        spec_server &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;DRbObject&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;new_with_uri&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;druby://127.0.0.1:&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;#{&lt;/span&gt;drb_port&lt;span class=&quot;StringEmbeddedSource&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
        spec_server.&lt;span class=&quot;Entity&quot;&gt;run&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;options&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;drb_argv&lt;/span&gt;, err, out, &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;TEST_ENV_NUMBER&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt; =&amp;gt; &lt;span class=&quot;Variable&quot;&gt;ENV&lt;/span&gt;[&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;TEST_ENV_NUMBER&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;])
      &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;This ensures that when parallel_spec runs script/spec, the test environment number is passed through to the chikd&lt;/p&gt;

&lt;h3&gt;Make sure the right database is used&lt;/h3&gt;

&lt;p&gt;When spork forks a child with a specific TEST_ENV_NUMBER we need to ensure that the child connects to the correct database. This can be done with a Spork.each_run block in your spec_helper.rb. The app I've been working with uses mongomapper as well as Active Record, so my each_run block looks like this.&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;  &lt;span class=&quot;Keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;Variable&quot;&gt;ENV&lt;/span&gt;[&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;TEST_ENV_NUMBER&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;].&lt;span class=&quot;Entity&quot;&gt;blank?&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;  &lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;reconnect to your AR &amp;amp; mongo dbs&lt;/span&gt;
    db_config &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;YAML&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;load&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;ERB&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;new&lt;/span&gt;(&lt;span class=&quot;Support&quot;&gt;File&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;read&lt;/span&gt;(&lt;span class=&quot;Support&quot;&gt;Rails&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;root&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;join&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;config&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;mongo.yml&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;))).&lt;span class=&quot;Entity&quot;&gt;result&lt;/span&gt;)
    &lt;span class=&quot;Keyword&quot;&gt;if&lt;/span&gt; db_config[&lt;span class=&quot;Support&quot;&gt;Rails&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;env&lt;/span&gt;]
      &lt;span class=&quot;Support&quot;&gt;MongoMapper&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;setup&lt;/span&gt; db_config, &lt;span class=&quot;Support&quot;&gt;Rails&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;env&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;Support&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Base&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;configurations&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;DressipiCom&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Application&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;instance&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;config&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;database_configuration&lt;/span&gt;
    &lt;span class=&quot;Support&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Base&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;establish_connection&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;

&lt;h3&gt;Profit&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;bundle exec spork&lt;/code&gt; and run parallel_spec as normal (things won't work if the 'normal' version of the spork binary is run). Your spork will fork multiple instances which will pick up TEST_ENV_NUMBER and reconfigure their database settings as needed.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.spacevatican.org/">
    <author>
      <name>fred</name>
    </author>
    <id>tag:www.spacevatican.org,2011-07-03:534</id>
    <published>2011-07-03T18:20:00Z</published>
    <updated>2011-07-03T18:25:01Z</updated>
    <category term="akephalos"/>
    <category term="cucumber"/>
    <category term="spork"/>
    <link href="http://www.spacevatican.org/2011/7/3/sporking-with-akephalos" rel="alternate" type="text/html"/>
    <title>Sporking with akephalos</title>
<content type="html">
            &lt;p&gt;&lt;a href=&quot;https://github.com/timcharper/spork&quot;&gt;Spork&lt;/a&gt; is a test server for saving on environment startup time when running rspec or cucumber. &lt;a href=&quot;http://oinopa.com/akephalos&quot;&gt;Akephalos&lt;/a&gt; is an awesome capybara driver that wraps the htmlunit library. Because htmlunit is a java library, akephalos spawns a jruby process and then uses DRb to allow non-jruby instances to get at the htmlunit goodness.&lt;/p&gt;

&lt;p&gt;If you try and combine the two, you get a somewhat uninviting error message:&lt;/p&gt;

&lt;pre&gt;
Fs-ElephantBook-2:dressipi fred$ cucumber --drb features/user_signs_up.feature 
Using the default profile...
Disabling profiles...
.F---------------------------

(::) failed steps (::)

0x00000083df8904 is not id value (RangeError)
(druby://127.0.0.1:8990) /Users/fred/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/drb/drb.rb:375:in `_id2ref'
(druby://127.0.0.1:8990) /Users/fred/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/drb/drb.rb:375:in `to_obj'
(druby://127.0.0.1:8990) /Users/fred/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/drb/drb.rb:1405:in `to_obj'
(druby://127.0.0.1:8990) /Users/fred/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/drb/drb.rb:1713:in `to_obj'
(druby://127.0.0.1:8990) /Users/fred/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/drb/drb.rb:613:in `recv_request'
(druby://127.0.0.1:8990) /Users/fred/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/drb/drb.rb:908:in `recv_request'
(druby://127.0.0.1:8990) /Users/fred/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/drb/drb.rb:1533:in `init_with_client'
(druby://127.0.0.1:8990) /Users/fred/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/drb/drb.rb:1545:in `setup_message'
(druby://127.0.0.1:8990) /Users/fred/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/drb/drb.rb:1497:in `perform'
(druby://127.0.0.1:8990) /Users/fred/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/drb/drb.rb:1592:in `block (2 levels) in main_loop'
(druby://127.0.0.1:8990) /Users/fred/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/drb/drb.rb:1588:in `loop'
(druby://127.0.0.1:8990) /Users/fred/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/drb/drb.rb:1588:in `block in main_loop'
(druby://127.0.0.1:60779) -e:1
./features/step_definitions/authentication_steps.rb:31:in `block (2 levels) in '
./features/step_definitions/authentication_steps.rb:30:in `each_pair'
./features/step_definitions/authentication_steps.rb:30:in `/^I sign up with$/'
features/user_signs_up.feature:10:in `When I sign up with'
&lt;/pre&gt;

&lt;p&gt;Which a shame as spork would be especially useful here because akephalos can take quite a few seconds to launch its jruby process.&lt;/p&gt;

&lt;h1&gt;DRb&lt;/h1&gt;

&lt;p&gt;First let's step back and remind ourselves how DRb works. &lt;a href=&quot;http://www.ruby-doc.org/stdlib/libdoc/drb/rdoc/classes/DRb.html&quot;&gt;DRb&lt;/a&gt; (short for distributed ruby) is a distributed object system for ruby. In the simplest of cases, when you call a method on a remote object, your arguments are marshalled and transmitted over the wire. In the remote process, the arguments are unpacked, the method called and then the result is marshalled and sent back to you.&lt;/p&gt;

&lt;p&gt;Obviously this doesn't always work - some objects (procs, IO streams etc.) can't be dumped. A very common example would be if you want to call a method and pass a block. So, in addition to the previously described scheme, DRb also allows making proxies for objects. Instead of getting or passing a marshalled dump of an object it uses a proxy that knows the process the object has come from (a uri like druby://127.0.0.1:8990) and something identifying the object in that process. By default it uses the object_id for the object, which DRb can then use to find the actual object. This can require some careful coding, as if in the remote process the object appears unused it might get garbage collected. If this happens then when you try to call a method on it DRb won't be able to turn the object_id back into an actual object and you get an exception like the one above.&lt;/p&gt;

&lt;p&gt;When you run code such as&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;some_drb_object.&lt;span class=&quot;Entity&quot;&gt;do_foo&lt;/span&gt; { }
&lt;/pre&gt;

&lt;p&gt;Then there are actually DRb calls happening in both directions. The client asks the server process to run do_foo, but because there is a block passed to the method DRb wraps up that block in a proxy object and sends it to the server along with the arguments. When do_foo calls yield, a DRb call happens in the reverse direction in order to invoke the block.&lt;/p&gt;

&lt;h1&gt;Akephalos and Spork&lt;/h1&gt;

&lt;p&gt;Back to the original problem. When you run some specs or cucumber features with spork, spork forks off a new instance and then uses DRb to run your specs/features in that process. It's the combination of that use of DRb with akephalos' use of DRb that causes the problem. After digging around I traced the exception raised to this line in akephalos:&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;page.&lt;span class=&quot;Entity&quot;&gt;find&lt;/span&gt;(selector).&lt;span class=&quot;Entity&quot;&gt;each&lt;/span&gt; { |&lt;span class=&quot;Variable&quot;&gt;node&lt;/span&gt;| nodes &lt;span class=&quot;Keyword&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;Node&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;new&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;self&lt;/span&gt;, node) }
&lt;/pre&gt;

&lt;p&gt;page is a DRb object from akephalos's jruby process that wraps the htmlunit representation of the page. A little more digging revealed that the invalid id was in fact referring to the block passed to each. You may have noticed that the error is being raised from druby://127.0.0.1:8990, ie from spork's parent process.&lt;/p&gt;

&lt;p&gt;There was already a DRb server running in spork parent process ( druby://127.0.0.1:8990 ), and because our test running process was forked from that process, when DRb packaged up that block into a proxy object it gave the uri for that server as the uri to use when making calls to the block. When each yielded to the block, instead of the method call going to the process that called each, it went to the spork parent process. Because the call went to the wrong process, the object id passed is entirely meaningless.&lt;/p&gt;

&lt;h1&gt;Fixing it&lt;/h1&gt;

&lt;p&gt;I'm not entirely sure of the best way to fix this - akephalos is blissfuly ignorant of this aspect of its environment. I was able to get my cucumber features running with both spork and akephalos by doing this in my env.rb&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;&lt;span class=&quot;Support&quot;&gt;Spork&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;prefork&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
  ... &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;my usual Spork.prefork stuff&lt;/span&gt;
  &lt;span class=&quot;Support&quot;&gt;Akephalos&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;RemoteClient&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;manager&lt;/span&gt; &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;force akephalos to be started by the parent process&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;                                  &lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;so that we don't keep starting it again and again&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;Support&quot;&gt;Spork&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;each_run&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;Support&quot;&gt;Thread&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;current&lt;/span&gt;[&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;DRb&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;] &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; { &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;server&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt; =&amp;gt; &lt;span class=&quot;Variable&quot;&gt;DRb&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;DRbServer&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;new&lt;/span&gt; }
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;This ensures that when DRb is constructing a proxy object it uses the uri for the freshly constructed DRbServer as the uri for any proxy objects it passes, and so block invocations and the like go to the correct process.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.spacevatican.org/">
    <author>
      <name>fred</name>
    </author>
    <id>tag:www.spacevatican.org,2011-04-28:490</id>
    <published>2011-04-28T20:11:00Z</published>
    <updated>2011-07-25T12:01:47Z</updated>
    <category term="rails"/>
    <link href="http://www.spacevatican.org/2011/4/28/adding-to-rails-log-file-performance-breakdown" rel="alternate" type="text/html"/>
    <title>Adding to Rails' log file performance breakdown</title>
<content type="html">
            &lt;p&gt;You'll all have seen lines like this in your log files:&lt;/p&gt;

&lt;pre&gt;
Completed 200 OK in 14ms (Views: 0.2ms | ActiveRecord: 2.7ms)
&lt;/pre&gt;

&lt;p&gt;While obviously a very high level view of your application's performance, it's still a good place to start when you're wondering where the time has gone. If you're using a different datastore or if external services (solr, sphinx, external API calls) are important contributors to your application's performance you might want time spent in those services listed too.&lt;/p&gt;

&lt;p&gt;Prior to Rails 3, it was hard to add information to this summary without making a mess of things. What was reported on was just hardcoded into Action Controller. Things are a lot easier in Rails 3.&lt;/p&gt;

&lt;p&gt;New in Rails 3 is &lt;code&gt;ActiveSupport::Notifications&lt;/code&gt;. The idea here is to decouple things producing performance data and things consuming them.&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;&lt;span class=&quot;Support&quot;&gt;ActiveSupport&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Notifications&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;instrument&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;some_task.my_app&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, data) &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;  &lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;do some processing&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;will record how long it took to do the task, and then yield that data to anyone interested (instances of subclasses of ActiveSupport::LogSubscriber). Action Controller's process action is wrapped by a call to instrument and one particular subscriber  to that is one that writes what Action Controller has been up toto the app's log file. If you wanted to analyze your app's data other than by eyeballing the log files you could write your own class that could subscribe to these notifications and do whatever processing you wanted, instead of writing something to parse your log files.&lt;/p&gt;

&lt;h1&gt;A simple example&lt;/h1&gt;

&lt;p&gt;Suppose we want the time we spend query solr to be logged. Following the way Active Record does things, you need to do three things: instrument the action we wish to monitor using ActiveSupport::Notifications, record the information in a subscriber and then plug the resulting data into Action Controller.&lt;/p&gt;

&lt;p&gt;At its barest, the instrumentation might look like this&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;&lt;span class=&quot;Keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Solr&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Connection&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;send_with_instrumentation&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;request&lt;/span&gt;)
      &lt;span class=&quot;Support&quot;&gt;ActiveSupport&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Notifications&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;instrument&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;send_query.solr&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;Entity&quot;&gt;send_without_instrumentation&lt;/span&gt;(request)
      &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
    alias_method_chain &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;send&lt;/span&gt;, &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;instrumentation&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Here &lt;code&gt;send&lt;/code&gt; is a funnel through which all queries to solr flow.&lt;/p&gt;

&lt;p&gt;The log subscriber might look a little like this:&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;&lt;span class=&quot;Keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Solr&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;LogSubscriber&lt;span class=&quot;EntityInheritedClass&quot;&gt; &lt;span class=&quot;EntityInheritedClass&quot;&gt;&amp;lt;&lt;/span&gt; ActiveSupport::LogSubscriber&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;self.runtime=&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;value&lt;/span&gt;)
      &lt;span class=&quot;Support&quot;&gt;Thread&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;current&lt;/span&gt;[&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;solr_runtime&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;] &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; value
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;self.runtime&lt;/span&gt;
      &lt;span class=&quot;Support&quot;&gt;Thread&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;current&lt;/span&gt;[&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;solr_runtime&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;] &lt;span class=&quot;Keyword&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;self.reset_runtime&lt;/span&gt;
      rt, &lt;span class=&quot;Variable&quot;&gt;self&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;runtime&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; runtime, &lt;span class=&quot;Constant&quot;&gt;0&lt;/span&gt;
      rt
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;send_query&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;event&lt;/span&gt;)
      &lt;span class=&quot;Variable&quot;&gt;self&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;class&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;runtime&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;+=&lt;/span&gt; event.&lt;span class=&quot;Entity&quot;&gt;duration&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;Support&quot;&gt;Solr&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;LogSubscriber&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;attach_to&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;solr&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;The call to &lt;code&gt;attach_to&lt;/code&gt; means that whenever a &lt;code&gt;foo.solr&lt;/code&gt; event is fired, our subscriber's &lt;code&gt;foo&lt;/code&gt; method will be called. The only thing we do in our subscriber is keep track of how much time has been spent, using the &lt;code&gt;runtime&lt;/code&gt; and &lt;code&gt;runtime=&lt;/code&gt; method. &lt;code&gt;reset_runtime&lt;/code&gt; resets the counter and returns the time accumulated so far.&lt;/p&gt;

&lt;p&gt;The last thing we need to do is use the hooks that Action Controller helpfully provides. The following is lifted pretty much line for line from Active Record[1]:&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;&lt;span class=&quot;Keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Solr&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Railties&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;ControllerRuntime&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;ActiveSupport&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Concern&lt;/span&gt;

    &lt;span class=&quot;Keyword&quot;&gt;protected&lt;/span&gt;

      attr_internal &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;solr_runtime_before_render&lt;/span&gt;
      attr_internal &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;solr_runtime_during_render&lt;/span&gt;

      &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;cleanup_view_runtime&lt;/span&gt;
        &lt;span class=&quot;Variable&quot;&gt;self&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;solr_runtime_before_render&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;Solr&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;LogSubscriber&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;reset_runtime&lt;/span&gt;
        runtime &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;super&lt;/span&gt;
        &lt;span class=&quot;Variable&quot;&gt;self&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;solr_runtime_during_render&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;Solr&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;LogSubscriber&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;reset_runtime&lt;/span&gt;
        runtime &lt;span class=&quot;Keyword&quot;&gt;-&lt;/span&gt; solr_runtime_during_render
      &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;append_info_to_payload&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;payload&lt;/span&gt;)
        &lt;span class=&quot;Keyword&quot;&gt;super&lt;/span&gt;
        payload[&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;solr_runtime&lt;/span&gt;] &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; (solr_runtime_before_render &lt;span class=&quot;Keyword&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;Keyword&quot;&gt;+&lt;/span&gt; 
                                 (solr_runtime_during_render &lt;span class=&quot;Keyword&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;Keyword&quot;&gt;+&lt;/span&gt;
                                 &lt;span class=&quot;Support&quot;&gt;Solr&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;LogSubscriber&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;reset_runtime&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;Keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;ClassMethods&lt;/span&gt;
        &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;log_process_action&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;payload&lt;/span&gt;)
          messages, solr_runtime &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;super&lt;/span&gt;, payload[&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;solr_runtime&lt;/span&gt;]
          messages &lt;span class=&quot;Keyword&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; (&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;Solr: %.1fms&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;%&lt;/span&gt; solr_runtime) &lt;span class=&quot;Keyword&quot;&gt;if&lt;/span&gt; solr_runtime
          messages
        &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;Support&quot;&gt;ActiveSupport&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;on_load&lt;/span&gt;(&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;action_controller&lt;/span&gt;) &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;Keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;Solr&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Railties&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;ControllerRuntime&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;cleanup_view_runtime&lt;/code&gt; is used to prevent double counting of time spent performing database queries etc. as both database time and view rendering time. The call to super in &lt;code&gt;cleanup_view_runtime&lt;/code&gt; will wind up actually rendering the view, so looking at the solr time before and after this tells us how much time we need to deduct from the view render time (which is what the call to super returns).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;append_info_to_payload&lt;/code&gt; is where we record how much time has been used in total, which is the sum of solr time before, during and after rendering the view.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;log_process_action&lt;/code&gt; (a class method) acts on a payload hash and produces an array of components such as 'ActiveRecord: 32.2ms'.&lt;/p&gt;

&lt;p&gt;Finally we add an &lt;code&gt;on_load&lt;/code&gt; hook that will include this module in &lt;code&gt;ActionController::Base&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Put all this together and you should see stuff like&lt;/p&gt;

&lt;pre&gt;Completed 200 OK in 17ms (Views: 10.8ms | ActiveRecord: 0.3ms | Solr: 3.7ms)&lt;/pre&gt;

&lt;p&gt;in your logs.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;[1] At the time of writing rails 3.0.7 actually does this incorrectly because it doesn't consider time after rendering, or when no view was rendered at all&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.spacevatican.org/">
    <author>
      <name>fred</name>
    </author>
    <id>tag:www.spacevatican.org,2011-04-19:482</id>
    <published>2011-04-19T09:24:00Z</published>
    <updated>2011-04-19T09:24:20Z</updated>
    <category term="Rails"/>
    <category term="rails"/>
    <category term="rspec"/>
    <link href="http://www.spacevatican.org/2011/4/19/showing-view-spec-exceptions" rel="alternate" type="text/html"/>
    <title>Showing view spec exceptions</title>
<content type="html">
            &lt;p&gt;When an exception is raised during rendering of a view it is wrapped inside an ActionView::Template::Error which is then reraised.&lt;/p&gt;

&lt;p&gt;This leads to unhelpful failure messages in view specs, along the lines of&lt;/p&gt;

&lt;pre&gt;
contact/index.html.haml renders a form to send feedback
     Failure/Error: it &quot;renders a form to send feedback&quot; do render
     ActionView::Template::Error
     # ./app/views/contact/index.html.haml:19
     # ./spec/views/contact/index.html.haml_spec.rb:10:in `block (2 levels) in '
&lt;/pre&gt;

&lt;p&gt;This little monkey patch&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;&lt;span class=&quot;Keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;RSpec&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Core&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Example&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;set_exception&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;exception&lt;/span&gt;)
        &lt;span class=&quot;Keyword&quot;&gt;if&lt;/span&gt; exception.&lt;span class=&quot;Entity&quot;&gt;is_a?&lt;/span&gt;(&lt;span class=&quot;Support&quot;&gt;ActionView&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Template&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Error&lt;/span&gt;)
          &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;exception&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;||=&lt;/span&gt; exception.&lt;span class=&quot;Entity&quot;&gt;original_exception&lt;/span&gt;
        &lt;span class=&quot;Keyword&quot;&gt;else&lt;/span&gt;
          &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;exception&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;||=&lt;/span&gt; exception
        &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;ensures that the original exception is the one that is displayed.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.spacevatican.org/">
    <author>
      <name>fred</name>
    </author>
    <id>tag:www.spacevatican.org,2011-04-06:481</id>
    <published>2011-04-06T12:38:00Z</published>
    <updated>2011-04-06T12:38:10Z</updated>
    <category term="Rails"/>
    <category term="helpers"/>
    <category term="rails"/>
    <link href="http://www.spacevatican.org/2011/4/6/unhelpfully-helpful" rel="alternate" type="text/html"/>
    <title>Unhelpfully helpful</title>
<content type="html">
            &lt;p&gt;I loathe &lt;code&gt;helper :all&lt;/code&gt;. What's the point of nicely divided helper modules if they're all injected into same namespace, overwriting each other at random? I like to write reusable helpers that individual controllers can use by implementing their version of a &lt;code&gt;foo&lt;/code&gt; method. I see no reason why two completely unrelated helper modules couldn't both has a &lt;code&gt;display_help_text&lt;/code&gt; method. &lt;code&gt;helper :all&lt;/code&gt; prevents both of these and creates situations where you can accidentally overwrite a helper method in a completely different part of your application.&lt;/p&gt;

&lt;p&gt;Obviously not everyone agrees with me because Rails continues to move in the other direction. Once upon a time, a bare controller only pulled in its default helper (ie &lt;code&gt;Bar::FooController&lt;/code&gt; gets &lt;code&gt;Bar::FooHelper&lt;/code&gt;) and the helpers for its ancestors. Later, the default application skeleton added &lt;code&gt;helper :all&lt;/code&gt; to &lt;code&gt;ApplicationController&lt;/code&gt; but this was still an opt in scheme. With Rails 3 it is an opt out scheme: you have to put &lt;code&gt;clear_helpers&lt;/code&gt; in a controller to clear out the helpers Rails includes automatically for it.&lt;/p&gt;

&lt;h1&gt;View Specs&lt;/h1&gt;

&lt;p&gt;Rspec tries to do the right thing - if you poke into &lt;code&gt;view_example_group.rb&lt;/code&gt; in rspec-rails you can see it determining the default helper class and including that and &lt;code&gt;ApplicationHelper&lt;/code&gt; into the view object. Unforunately it also includes &lt;code&gt;controller._helpers&lt;/code&gt;. This controller isn't an instance of the controller class that will use the view - it's an instance of &lt;code&gt;ActionView::TestCase::TestController&lt;/code&gt;, so has Rails' default of the full set of helpers, irrespective of how the controller in the app is configured.&lt;/p&gt;

&lt;p&gt;The first step is of course calling &lt;code&gt;clear_helpers&lt;/code&gt; on &lt;code&gt;ActionView::TestCase::TestController&lt;/code&gt; but if your application has helper modules that are used by multiple controllers then some of your view specs may start to fail. You could of course add those helpers to the view from your &lt;code&gt;before(:each)&lt;/code&gt; blocks but that is a slightly nasty piece of duplication: you've already specified once which helpers should be used. More dangerously you could develop a situation where your view specs pass because they specify one set of helpers but your app fails because your controllers specify a different set.&lt;/p&gt;

&lt;p&gt;To remedy this I've got the following in one of my apps:&lt;/p&gt;

&lt;pre class=&quot;twilight&quot;&gt;&lt;span class=&quot;Keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;ViewHelpersSpecHelper&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;ActiveSupport&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Concern&lt;/span&gt;

  included &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;if&lt;/span&gt; metadata[&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;type&lt;/span&gt;] &lt;span class=&quot;Keyword&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;view&lt;/span&gt;
      name_parts &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; metadata[&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;example_group&lt;/span&gt;][&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;description&lt;/span&gt;].&lt;span class=&quot;Entity&quot;&gt;split&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;/&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)
      name_parts.&lt;span class=&quot;Entity&quot;&gt;pop&lt;/span&gt;

      controller_name &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;#{&lt;/span&gt;name_parts&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;join&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;/&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;camelize&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;StringEmbeddedSource&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;unless&lt;/span&gt; controller_name &lt;span class=&quot;Keyword&quot;&gt;=~&lt;/span&gt; &lt;span class=&quot;StringRegexp&quot;&gt;&lt;span class=&quot;StringRegexp&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;StringRegexp&quot;&gt;&lt;span class=&quot;StringRegexpSpecial&quot;&gt;\w&lt;/span&gt;Mailer&lt;/span&gt;&lt;span class=&quot;StringRegexp&quot;&gt;&lt;span class=&quot;StringRegexp&quot;&gt;/&lt;/span&gt;&lt;/span&gt;
        controller_name &lt;span class=&quot;Keyword&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;Controller&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

      helpers &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; controller_name.&lt;span class=&quot;Entity&quot;&gt;constantize&lt;/span&gt;._helpers
      before &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
        view.&lt;span class=&quot;Entity&quot;&gt;singleton_class&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;class_eval&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
          &lt;span class=&quot;Keyword&quot;&gt;include&lt;/span&gt; helpers &lt;span class=&quot;Keyword&quot;&gt;unless&lt;/span&gt; included_modules.&lt;span class=&quot;Entity&quot;&gt;include?&lt;/span&gt;(helpers)
        &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;This works out what controller class the view will normally be used with, for admin/foo/bar.html.haml this would be &lt;code&gt;Admin::FooController&lt;/code&gt; and uses the helpers that controller would use normally.&lt;/p&gt;

&lt;p&gt;A call to &lt;code&gt;config.include(ViewHelpersSpecHelper)&lt;/code&gt; in my &lt;code&gt;RSpec.configure&lt;/code&gt; block ensures that this module gets included everywhere relevant.&lt;/p&gt;

&lt;h1&gt;Cells&lt;/h1&gt;

&lt;p&gt;This starts to break down for partials that are rendered by multiple different controllers or for shared ones that don't have a natural controller they can be tested with. This is perhaps the one thing that &lt;code&gt;helper :all&lt;/code&gt; doesn't make worse, since it does mean that a given view is always rendered with the same set of helper functions available. If you do have such units of view and helper code, the &lt;a href=&quot;http://cells.rubyforge.org&quot;&gt;cells library&lt;/a&gt; is well worth a look.&lt;/p&gt;
          </content>  </entry>
</feed>

