<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Leonard Garvey, on programming, ruby, mongo and more</title>
  <id>http://bottledup.net</id>
  <updated>2011-03-11</updated>
  <author>
    <name>Leonard Garvey</name>
  </author>
  <entry>
    <title>Dear Backbone. Love letters from a Rails dev.</title>
    <link rel="alternate" href="http://bottledup.net/2013/05/16/dear-backbone-love-letters-from-a-rails-dev/"/>
    <id>http://bottledup.net/2013/05/16/dear-backbone-love-letters-from-a-rails-dev/</id>
    <published>2013-05-16</published>
    <updated>2013-05-16</updated>
    <author>
      <name>Leonard Garvey</name>
    </author>
    <summary type="html">&lt;p&gt;In this blog post I&amp;#39;m going to present a few things. Most of all I&amp;#39;m going to demonstrate how I would implement nice, structured front-end code in an already existing traditional Rails application. I&amp;#39;m going to do this using Backbone but it&amp;#39;s probably unlike how you may have seen Backbone used before. Finally I&amp;#39;m also going to present the technique I use to integrate this in with your Rails application. Importantly I think that we should be adopting sensibile application defaults in addition to the defaults that Rails provides us. By adopting our own per-application defaults we can avoid writing lots of code.&lt;/p&gt;

&lt;h2&gt;On front-end libraries/frameworks&lt;/h2&gt;

&lt;p&gt;Before I get started I&amp;#39;d like to state that Backbone is a library and not a framework so most comparisons between Backbone and Ember or Angular aren&amp;#39;t really relevant. But I would like to demonstrate why I chose Backbone instead of Ember or Angular since it&amp;#39;s such a commonly asked question&amp;hellip;&lt;/p&gt;
</summary>
    <content type="html">&lt;p&gt;In this blog post I&amp;#39;m going to present a few things. Most of all I&amp;#39;m going to demonstrate how I would implement nice, structured front-end code in an already existing traditional Rails application. I&amp;#39;m going to do this using Backbone but it&amp;#39;s probably unlike how you may have seen Backbone used before. Finally I&amp;#39;m also going to present the technique I use to integrate this in with your Rails application. Importantly I think that we should be adopting sensibile application defaults in addition to the defaults that Rails provides us. By adopting our own per-application defaults we can avoid writing lots of code.&lt;/p&gt;

&lt;h2&gt;On front-end libraries/frameworks&lt;/h2&gt;

&lt;p&gt;Before I get started I&amp;#39;d like to state that Backbone is a library and not a framework so most comparisons between Backbone and Ember or Angular aren&amp;#39;t really relevant. But I would like to demonstrate why I chose Backbone instead of Ember or Angular since it&amp;#39;s such a commonly asked question.&lt;/p&gt;

&lt;p&gt;I like Backbone because it doesn&amp;#39;t make assumptions about how my application is built. Most importantly it doesn&amp;#39;t assume that I suddenly have a well-tested JSON API that is suitable for a web interface.&lt;/p&gt;

&lt;p&gt;Traditionally with Backbone, Ember or Angular you query the server and get back JSON. Then you load that JSON into a &amp;quot;model&amp;quot; which is used by the framework to render a template in memory which is then inserted into the DOM. There are a few problems here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Assuming I have a good JSON API.&lt;/li&gt;
&lt;li&gt;Forcing me to either abandon my Rails views and to start writing sections of my app in JST (or similar), or to maintain both.&lt;/li&gt;
&lt;li&gt;It means my app doesn&amp;#39;t work without JavaScript. My issue here is that analytics tools generally don&amp;#39;t capture users who don&amp;#39;t have JS enabled. It&amp;#39;s difficult to get a sense of how large this market but I&amp;#39;d tend to think that it&amp;#39;s a small but vocal minority.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;Why I use Rails&lt;/h2&gt;

&lt;p&gt;Rails is unabashedly an opinionated framework. Many of us Rails developers do what we do because (for the most part) we approve of those opinions. What led me down this path was trying to work in Ember into an existing fairly traditional Rails application. I was in the situation where suddenly I needed to either abandon my existing views or duplicate my HTML across precompiled JavaScript views.&lt;/p&gt;

&lt;p&gt;Personally, I want to work with Rails. Rails has been developed over all these years as an amazing DSL for concatenating strings together to form HTML. I don&amp;#39;t want JS to take over any of that responsibility. I&amp;#39;m happy to build JSON APIs but I think that much of the time we&amp;#39;ll throw together a poorly thought out ad-hoc action that calls &lt;code&gt;to_json&lt;/code&gt; on some model, particularly if we&amp;#39;re retro-fitting some fancy MVC thing into our front-end.&lt;/p&gt;

&lt;p&gt;I will be going through a simplistic and largely contrived example of how I&amp;#39;ve implemented this previously and how this works in both Backbone and Rails. I think that we&amp;#39;re often missing a good direction on how to leverage the strengths of both JavaScript and Rails in our applications.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build your applications to work with plain HTML. I think this is good practice.&lt;/li&gt;
&lt;li&gt;Enhance your views with JavaScript even going so far as to use the History API to make a truly rich application.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Backbone provides my JS some structure, lets me write as little jQuery crap as I possibly can.&lt;/p&gt;

&lt;h2&gt;The code&lt;/h2&gt;

&lt;p&gt;All the code is actually available on Github. Check it out &lt;a href="https://github.com/lengarvey/rails-3-2-intro-blog"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So lets get into it. Here&amp;#39;s a brief description of the feature I&amp;#39;d like to build:&lt;/p&gt;
&lt;pre class="highlight text"&gt;Feature: AJAX commenting
  In order to have a nice commenting experience
  As a troll
  I want to be able to submit comments without a page refresh
&lt;/pre&gt;
&lt;p&gt;And here&amp;#39;s my Rails ERB view. There&amp;#39;s absolutely nothing special here. It&amp;#39;s a standard form for submitting a comment.&lt;/p&gt;
&lt;pre class="highlight erb"&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form_for&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="vi"&gt;@post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Comment&lt;/span&gt;&lt;span class="nf"&gt;.new&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="nf"&gt;.label&lt;/span&gt; &lt;span class="ss"&gt;:body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;New comment&amp;quot;&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;br/&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="nf"&gt;.text_area&lt;/span&gt; &lt;span class="ss"&gt;:body&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="nf"&gt;.submit&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Add comment&amp;quot;&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Now here is the Backbone &amp;quot;view&amp;quot; which I can bind to the form above.&lt;/p&gt;
&lt;pre class="highlight coffeescript"&gt;&lt;span class="nx"&gt;QuickBlog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Comments&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;QuickBlog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Comments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CreateCommentView&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Backbone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;View&lt;/span&gt;
  &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;&amp;quot;submit&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;commentSubmitted&amp;quot;&lt;/span&gt;

  &lt;span class="na"&gt;commentSubmitted&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="vi"&gt;@&lt;/span&gt;&lt;span class="na"&gt;submitForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="vi"&gt;@&lt;/span&gt;&lt;span class="na"&gt;$el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'action'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="vi"&gt;@&lt;/span&gt;&lt;span class="na"&gt;$el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;serialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="na"&gt;submitForm&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="vi"&gt;@&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="vi"&gt;@&lt;/span&gt;&lt;span class="na"&gt;commentPosted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="na"&gt;commentPosted&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="vi"&gt;@&lt;/span&gt;&lt;span class="na"&gt;appendComment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@&lt;/span&gt;&lt;span class="na"&gt;resetForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="na"&gt;resetForm&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="vi"&gt;@&lt;/span&gt;&lt;span class="na"&gt;$el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="vi"&gt;@&lt;/span&gt;&lt;span class="na"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="na"&gt;appendComment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'#comments'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;In order to bind that view to my form I only need to write: &lt;code&gt;new QuickBlog.Views.Comments.CreateCommentView({el: $(&amp;#39;#new_comment&amp;#39;)})&lt;/code&gt;. Right now I do this in my ERB views as inline JavaScript but it would be totally fine to do it in CoffeeScript too.&lt;/p&gt;

&lt;p&gt;This view listens and intercepts the submit event, then it posts it off using AJAX. Once that&amp;#39;s successfully occured the &lt;code&gt;commentPosted&lt;/code&gt; callback is executed with the data that is returned from the server.&lt;/p&gt;

&lt;p&gt;Traditionally with Backbone we&amp;#39;d return JSON from the server, stick it in a Backbone model then there&amp;#39;d be a change event in the view which would update the DOM by rendering a template. BLAAAHHH so many things.&lt;/p&gt;

&lt;p&gt;I&amp;#39;d rather just return a HTML snippet which gets put straight into the DOM. More code on the Backend and simpler JS. I&amp;#39;ve got two options. I could take the approach of rails-ujs which alters the Accepts HTTP Header to prefer JS. This allows us to write:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="n"&gt;respond_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@comment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="nf"&gt;.html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="nf"&gt;.js&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="vi"&gt;@comment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:partial&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;But I&amp;#39;m bad at JavaScript and don&amp;#39;t want to constantly set accept headers so that I get th right format in Rails so instead we end up with this code:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;xhr?&lt;/span&gt;
  &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="vi"&gt;@comment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:partial&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;But that code sucks. How about this instead:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="n"&gt;respond_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@comment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="nf"&gt;.html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;That&amp;#39;s better but we need to do a couple of things to set that up.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;respond_to :html, :xhr&lt;/code&gt; in the controller.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Mime::Type.register_alias &amp;quot;text/html&amp;quot;, :xhr&lt;/code&gt; to setup a new mime type in &lt;code&gt;config/initializers/mime_types.rb&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Then create and use a new responder. It looks like:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;XhrResponder&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Responder&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;xhr?&lt;/span&gt;
    &lt;span class="vi"&gt;@controller&lt;/span&gt;&lt;span class="nf"&gt;.request.xhr?&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# xhr is &amp;quot;rendered&amp;quot; when you request html but do so via AJAX.&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;respond&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;xhr?&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:html&lt;/span&gt;
      &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;to_xhr&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;to_&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="nb"&gt;respond_to?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;to_format&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# render the appropriate partial for the resource&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;to_xhr&lt;/span&gt;
    &lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="nf"&gt;.default_render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="nf"&gt;.merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:partial&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;and to use it in your controller:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;responder&lt;/span&gt;
    &lt;span class="no"&gt;XhrResponder&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;I think this is a really nice way of enhancing existing traditional Rails applications with some front-end magic while at the same time doing as little of that crazy JavaScript stuff as possible.&lt;/p&gt;

&lt;p&gt;PS: This blog post was taken from the notes I used to &lt;a href="https://speakerdeck.com/lengarvey/dear-backbone-love-letters-from-a-rails-dev"&gt;give this talk&lt;/a&gt; at the Ruby or Rails Oceania (RORO) meetup in Sydney on May 14th 2013.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>RubyConf AU was Awesome</title>
    <link rel="alternate" href="http://bottledup.net/2013/02/25/rubyconf-au-was-awesome/"/>
    <id>http://bottledup.net/2013/02/25/rubyconf-au-was-awesome/</id>
    <published>2013-02-25</published>
    <updated>2013-02-25</updated>
    <author>
      <name>Leonard Garvey</name>
    </author>
    <summary type="html">&lt;p&gt;The first (and hopefully annual) &lt;a href="http://www.rubyconf.org.au/"&gt;RubyConf AU&lt;/a&gt; was held in Melbourne in late February
and as the title &amp;quot;suggests&amp;quot; it was pretty awesome. 380 Ruby and Rails geeks
descended upon the Jasper Hotel for 2 days packed full of top quality talks,
by amazing speakers. On the day preceeding the conference proper there was a
full day of workshops.&lt;/p&gt;

&lt;h2&gt;Workshops&lt;/h2&gt;

&lt;p&gt;I attended a &lt;a href="http://coderetreat.org/"&gt;Code Retreat with Corey Haines&lt;/a&gt;. If you haven&amp;#39;t been to a Code
Retreat then you absolutely have to go. I felt like I levelled up as a developer
several times in a single day and I&amp;#39;m very keen to go along to more. Basically
the idea is that in pairs you do several 50ish minute programming spikes attempting&lt;/p&gt;
</summary>
    <content type="html">&lt;p&gt;The first (and hopefully annual) &lt;a href="http://www.rubyconf.org.au/"&gt;RubyConf AU&lt;/a&gt; was held in Melbourne in late February
and as the title &amp;quot;suggests&amp;quot; it was pretty awesome. 380 Ruby and Rails geeks
descended upon the Jasper Hotel for 2 days packed full of top quality talks,
by amazing speakers. On the day preceeding the conference proper there was a
full day of workshops.&lt;/p&gt;

&lt;h2&gt;Workshops&lt;/h2&gt;

&lt;p&gt;I attended a &lt;a href="http://coderetreat.org/"&gt;Code Retreat with Corey Haines&lt;/a&gt;. If you haven&amp;#39;t been to a Code
Retreat then you absolutely have to go. I felt like I levelled up as a developer
several times in a single day and I&amp;#39;m very keen to go along to more. Basically
the idea is that in pairs you do several 50ish minute programming spikes attempting
to implement &lt;a href="http://en.wikipedia.org/wiki/Conway&amp;#x27;s_Game_of_Life"&gt;Conway&amp;#39;s Game of Life&lt;/a&gt;. After each iteration you throw away your code
and start again. Finally, to make things interesting Corey places restrictions
on code you can write which forces you to think about your language and how it
can be used to solve the problem given the restrictions.&lt;/p&gt;

&lt;p&gt;Other workshops (which were all apparently fantastic) were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Advanced Ruby with Dave Thomas&lt;/li&gt;
&lt;li&gt;JRuby with Charles Nutter and Hiro Asari&lt;/li&gt;
&lt;li&gt;Rails for iOS developers with Lori Olsen and Tim Breutkreutz&lt;/li&gt;
&lt;li&gt;A Rails Girls workshop&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;The Conference itself&lt;/h2&gt;

&lt;p&gt;Every talk I attended was fantastic but there were some particular highlights:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Obviously all the keynotes were brilliant.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://vimeo.com/61342267"&gt;Keith and Mario&amp;#39;s guide to fast websites&lt;/a&gt; was really top notch.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://vimeo.com/61172068"&gt;Carina Zona&amp;#39;s&lt;/a&gt; talk about schemas in the real world was very eye-opening.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://vimeo.com/61087282"&gt;Ben Orenstein&amp;#39;s live-coding refactoring&lt;/a&gt; session was fantastic too.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can watch all the sessions on &lt;a href="http://vimeo.com/rubyau/videos"&gt;Vimeo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I do have some criticisms:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;While the talks were fantastic it would have been nicer to see some more diversity in the speaker lineup. Hopefully next year we can put more effort into balancing things out a bit.&lt;/li&gt;
&lt;li&gt;Lack of wireless and no 3G connectivity at the venue. There are arguments for and against here, but I feel that it negatively harms future conferences for there to be less &amp;quot;buzz&amp;quot; about our conference on Twitter. That said I&amp;#39;d prefer no internet to really bad internet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I&amp;#39;m very much looking forward to RubyConf AU 2014!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Founders Five Tech Concerns</title>
    <link rel="alternate" href="http://bottledup.net/2013/01/11/founders-five-tech-concerns/"/>
    <id>http://bottledup.net/2013/01/11/founders-five-tech-concerns/</id>
    <published>2013-01-11</published>
    <updated>2013-01-11</updated>
    <author>
      <name>Leonard Garvey</name>
    </author>
    <summary type="html">&lt;p&gt;Working in &lt;a href="http://www.tankstreamlabs.com"&gt;Tank Stream Labs&lt;/a&gt; (a great new co-working space here in Sydney) I come
into contact with plenty of entrepreneurs looking to start their own Next Big
Thing. Sometimes they have plenty of technology experience in the founding team,
but often it&amp;#39;s &amp;quot;business&amp;quot; people looking to start a great new
&lt;em&gt;technology&lt;/em&gt;-based startup. They&amp;#39;re eager to learn anything about creating an
online business. So rather than explaining everything to them in person, my
hope is that I can direct them to here and give everyone a nice easy list of
tech things you should have covered in your new startup.&lt;/p&gt;

&lt;p&gt;These tips fall into a few key areas but here goes!&lt;/p&gt;

&lt;h2&gt;Owning your stuff&lt;/h2&gt;
</summary>
    <content type="html">&lt;p&gt;Working in &lt;a href="http://www.tankstreamlabs.com"&gt;Tank Stream Labs&lt;/a&gt; (a great new co-working space here in Sydney) I come
into contact with plenty of entrepreneurs looking to start their own Next Big
Thing. Sometimes they have plenty of technology experience in the founding team,
but often it&amp;#39;s &amp;quot;business&amp;quot; people looking to start a great new
&lt;em&gt;technology&lt;/em&gt;-based startup. They&amp;#39;re eager to learn anything about creating an
online business. So rather than explaining everything to them in person, my
hope is that I can direct them to here and give everyone a nice easy list of
tech things you should have covered in your new startup.&lt;/p&gt;

&lt;p&gt;These tips fall into a few key areas but here goes!&lt;/p&gt;

&lt;h2&gt;Owning your stuff&lt;/h2&gt;

&lt;p&gt;1) Your code - A business is worth as much as the assets it possesses. One of
the biggest assets will be the code used to power the product. If you&amp;#39;re going
to get a contractor/consultancy to build your product for you make sure you
still own the code. The best way of doing this is to make sure your developers
put it into a &lt;a href="http://github.com"&gt;Github&lt;/a&gt; account that you own. It&amp;#39;s really cheap and extremely easy
to setup.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ask your contractor what version control system they use. Full marks if they
use git. If they don&amp;#39;t use version control the chances of your code being lost
increase dramatically. All good developers use some sort of version control.
Also if they don&amp;#39;t use version control it&amp;#39;s much harder for a different
contractor to fix any issues with your system.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;2) Your online properties - One of the next largest assets will be your domain
and web hosting. While you&amp;#39;ll probably be guided by your developer on what the
best option here is, it&amp;#39;s vitally important you understand exactly what you&amp;#39;re
paying for. It&amp;#39;s also important you understand how to move to a different
hosting solution should the need arise. If they say they host with
&lt;a href="http://aws.amazon.com/"&gt;AWS&lt;/a&gt;, &lt;a href="http://heroku.com"&gt;Heroku&lt;/a&gt;,
or a reputable hosting company like &lt;a href="http://www.anchor.com.au"&gt;Anchor&lt;/a&gt; you&amp;#39;re in safe hands.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you&amp;#39;re able, create all accounts yourself and create secure passwords with a
tool like &lt;a href="https://agilebits.com/onepassword"&gt;1Password&lt;/a&gt;. You can then easily create accounts for your developers or
share passwords with them if required.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;3) Backup your data (and code). It&amp;#39;s imperative you backup your data and your
code. Imagine if your website gets hacked and all the data is wiped. What is
your disaster recovery plan? At minimum get your developer to setup an automated
backup script. It&amp;#39;s pretty easy to backup to &lt;a href="http://aws.amazon.com/s3/"&gt;Amazon
S3&lt;/a&gt; or &lt;a href="http://aws.amazon.com/glacier/"&gt;Glacier&lt;/a&gt;. If you store
your code on &lt;a href="http://github.com"&gt;Github&lt;/a&gt; it&amp;#39;s pretty safe.&lt;/p&gt;

&lt;h2&gt;Choosing your Developer&lt;/h2&gt;

&lt;p&gt;4) Testing - How does the developer know the site works if it isn&amp;#39;t tested? Ask
any prospective contractor what sort of testing they recommend for your system.
Make sure they have automated tests that get run every time &lt;em&gt;before&lt;/em&gt; code is
deployed to your website. If they don&amp;#39;t do this it&amp;#39;s an indicator of bad
quality.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ideally your developer will mention the words &amp;quot;Continuous Integration&amp;quot; and
possibly talk about &amp;quot;Continuous Deployment&amp;quot;.  If they do it&amp;#39;s a great thing, it
means your dev can push to production multiple times a day.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;5) Community - What sort of community does the developer belong to? Believe it
or not, tech people network to. There are plenty of tech meetups in any large
city covering all types of technology from &lt;a href="http://ruby.org.au/"&gt;Ruby on Rails&lt;/a&gt;,
to &lt;a href="http://sydphp.org/"&gt;PHP&lt;/a&gt; and &lt;a href="http://mongodb.meetup.com/"&gt;MongoDB&lt;/a&gt;.
If your developer is part of that community it&amp;#39;s an indicator that they are
passionate about development because they spend their own time pursuing it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Both these are positive indicators, although many would consider no testing a
very big negative. It&amp;#39;s completely possible to find a fantastic solitary
developer who doesn&amp;#39;t attend community events and don&amp;#39;t test.&lt;/em&gt;&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;Do you have any other concerns that you think I could answer? Get it contact
with me, either by commenting below or tweeting me
&lt;a href="https://twitter.com/lgarvey"&gt;@lgarvey&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Bundler and Gemfile</title>
    <link rel="alternate" href="http://bottledup.net/2013/01/10/bundler-and-gemfile/"/>
    <id>http://bottledup.net/2013/01/10/bundler-and-gemfile/</id>
    <published>2013-01-10</published>
    <updated>2013-01-10</updated>
    <author>
      <name>Leonard Garvey</name>
    </author>
    <summary type="html">&lt;p&gt;With the very &lt;a href="https://groups.google.com/d/topic/rubyonrails-security/t1WFuuQyavI/discussion"&gt;recent and extremely serious Rails security vulnerability&lt;/a&gt;
there have been more than a few people around asking how they update their Rails apps in order to be safe. Luckily Rails makes
the update process relatively easy for any simple apps. If you have a large app with a large team, you probably
shouldn&amp;#39;t be getting basic advice from a blog on the internet anyway!&lt;/p&gt;

&lt;h2&gt;How to Update&lt;/h2&gt;

&lt;p&gt;I&amp;#39;ll be assuming you&amp;#39;re running Rails &lt;code&gt;3.2.x&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open your Gemfile&lt;/li&gt;
&lt;li&gt;Make sure there&amp;#39;s a line like: &lt;code&gt;gem &amp;#39;rails&amp;#39;, &amp;#39;~&amp;gt; 3.2.0&amp;#39;&lt;/code&gt; in there.&lt;/li&gt;
&lt;li&gt;Run: &lt;code&gt;bundle update rails&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Run your test suite (you do have a test suite... right?!)&lt;/li&gt;
&lt;/ol&gt;
</summary>
    <content type="html">&lt;p&gt;With the very &lt;a href="https://groups.google.com/d/topic/rubyonrails-security/t1WFuuQyavI/discussion"&gt;recent and extremely serious Rails security vulnerability&lt;/a&gt;
there have been more than a few people around asking how they update their Rails apps in order to be safe. Luckily Rails makes
the update process relatively easy for any simple apps. If you have a large app with a large team, you probably
shouldn&amp;#39;t be getting basic advice from a blog on the internet anyway!&lt;/p&gt;

&lt;h2&gt;How to Update&lt;/h2&gt;

&lt;p&gt;I&amp;#39;ll be assuming you&amp;#39;re running Rails &lt;code&gt;3.2.x&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open your Gemfile&lt;/li&gt;
&lt;li&gt;Make sure there&amp;#39;s a line like: &lt;code&gt;gem &amp;#39;rails&amp;#39;, &amp;#39;~&amp;gt; 3.2.0&amp;#39;&lt;/code&gt; in there.&lt;/li&gt;
&lt;li&gt;Run: &lt;code&gt;bundle update rails&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Run your test suite (you do have a test suite... right?!)&lt;/li&gt;
&lt;li&gt;Deploy your code.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It&amp;#39;s really that easy!&lt;/p&gt;

&lt;h2&gt;What is happening here&lt;/h2&gt;

&lt;p&gt;Understanding those steps is probably just as important as actually performing them. So I&amp;#39;m going to break it down
for anyone reading this.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Gemfile&lt;/code&gt; and &lt;code&gt;Gemfile.lock&lt;/code&gt; are used by &lt;a href="http://gembundler.com/"&gt;bundler&lt;/a&gt; to manage your application dependencies.
You declare your application dependencies in your &lt;code&gt;Gemfile&lt;/code&gt; and then you run &lt;code&gt;bundle install&lt;/code&gt; to
create the &lt;code&gt;Gemfile.lock&lt;/code&gt; file. When your Rails application starts it reads the &lt;code&gt;Gemfile.lock&lt;/code&gt; file so it can
figure out which gems to require. This work is done in your &lt;code&gt;config/boot.rb&lt;/code&gt; file. You&amp;#39;ll see something like:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rubygems'&lt;/span&gt;
&lt;span class="n"&gt;gemfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="nf"&gt;.expand_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'../../../../Gemfile'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="nf"&gt;.exist?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gemfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'BUNDLE_GEMFILE'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gemfile&lt;/span&gt;
  &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'bundler'&lt;/span&gt;
  &lt;span class="no"&gt;Bundler&lt;/span&gt;&lt;span class="nf"&gt;.setup&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="vg"&gt;$:&lt;/span&gt;&lt;span class="nf"&gt;.unshift&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="nf"&gt;.expand_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'../../../../lib'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Source: https://github.com/rails/rails/blob/3-2-stable/railties/lib/rails/generators/rails/plugin_new/templates/rails/boot.rb&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Bundler.setup&lt;/code&gt; message requires the gems in your &lt;code&gt;Gemfile&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;What is the Gemfile.lock then?&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Gemfile.lock&lt;/code&gt; file is created by bundler (normally when you run &lt;code&gt;bundle install&lt;/code&gt;. This file contains
a snapshot of all the gems (and their dependencies) used by your application. This means that if you share your application
with someone else, when they run &lt;code&gt;bundle install&lt;/code&gt; bundler will skip the dependency calculation process and simply
install the Gems specified in the &lt;code&gt;Gemfile.lock&lt;/code&gt;. *You should always commit both the &lt;code&gt;Gemfile&lt;/code&gt; and &lt;code&gt;Gemfile.lock&lt;/code&gt; to your
source control system (you should be using git).&lt;/p&gt;

&lt;p&gt;The bundler website has some great information on this and other topics. I&amp;#39;d recommend starting with: http://gembundler.com/rationale.html&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>2013 Resolutions</title>
    <link rel="alternate" href="http://bottledup.net/2013/01/09/2013-resolutions/"/>
    <id>http://bottledup.net/2013/01/09/2013-resolutions/</id>
    <published>2013-01-09</published>
    <updated>2013-01-09</updated>
    <author>
      <name>Leonard Garvey</name>
    </author>
    <summary type="html">&lt;p&gt;Over the past few years I&amp;#39;ve been setting goals for myself, and achieving most of them
but it becomes easy to weasle out of some goals if they aren&amp;#39;t written down. So in the
spirit of &lt;a href="https://twitter.com/awws"&gt;@awws&lt;/a&gt;&amp;#39;s post &lt;a href="http://blog.tundramonkey.com/2013/01/07/2013-new-year-s-resolutions"&gt;2013 New Year&amp;#39;s Resolutions&lt;/a&gt;
I&amp;#39;ve decided to write up my goals for the year and post them publically.&lt;/p&gt;

&lt;h2&gt;Health&lt;/h2&gt;

&lt;p&gt;Towards the end of last year I got a personal trainer (Rebecca of &lt;a href="http://www.becompetitivefitness.com"&gt;Becompetitive Fitness&lt;/a&gt; is amazing)
and started my fitness journey. I lost &lt;a href="http://i.imgur.com/UH1eB.jpg"&gt;~6kg over 2 months and put on a bit of muscle&lt;/a&gt;.
More importantly than the numbers I broke my Coca-Cola habit, and established new routines which&lt;/p&gt;
</summary>
    <content type="html">&lt;p&gt;Over the past few years I&amp;#39;ve been setting goals for myself, and achieving most of them
but it becomes easy to weasle out of some goals if they aren&amp;#39;t written down. So in the
spirit of &lt;a href="https://twitter.com/awws"&gt;@awws&lt;/a&gt;&amp;#39;s post &lt;a href="http://blog.tundramonkey.com/2013/01/07/2013-new-year-s-resolutions"&gt;2013 New Year&amp;#39;s Resolutions&lt;/a&gt;
I&amp;#39;ve decided to write up my goals for the year and post them publically.&lt;/p&gt;

&lt;h2&gt;Health&lt;/h2&gt;

&lt;p&gt;Towards the end of last year I got a personal trainer (Rebecca of &lt;a href="http://www.becompetitivefitness.com"&gt;Becompetitive Fitness&lt;/a&gt; is amazing)
and started my fitness journey. I lost &lt;a href="http://i.imgur.com/UH1eB.jpg"&gt;~6kg over 2 months and put on a bit of muscle&lt;/a&gt;.
More importantly than the numbers I broke my Coca-Cola habit, and established new routines which
involve me going to the gym multiple times per week. I found myself sleeping better and experiencing
less ups and down related to sugar levels. I&amp;#39;ve still got a bit of work to do here (cutting out all sweets for instance).&lt;/p&gt;

&lt;p&gt;So my goal for this year is to step it up a notch:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Lose 15kg. (Actually I&amp;#39;d like to hit this by June but it would be pretty close to my goal weight)&lt;/li&gt;
&lt;li&gt;Keep an average of 4 exercise sessions per week.&lt;/li&gt;
&lt;li&gt;Cut out the afternoon and after-dinner sugary treats. I&amp;#39;ll be able to incoporate dessert into my weekly cheat meal instead.&lt;/li&gt;
&lt;li&gt;Take up a martial art.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Overall I just want to be able to feel good about my fitness and health. One more thing that I&amp;#39;m doing
is taking up a martial art. I&amp;#39;ve decided to give Krav Maga a go and have booked an induction session
for later this month.&lt;/p&gt;

&lt;h2&gt;Personal&lt;/h2&gt;

&lt;p&gt;Last year I travelled through Western Europe with my lovely girlfriend, capping off the trip with 3 days
snowboarding in the Dolomites.&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/dolomites.jpg" alt="Dolomites"&gt;&lt;/p&gt;

&lt;p&gt;This year I&amp;#39;d like to do some more snowboarding, and to plan (but possibly not execute) my next big trip.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Spend at least a week snowboarding.&lt;/li&gt;
&lt;li&gt;Plan the next big proper holiday.&lt;/li&gt;
&lt;li&gt;Get on top of my financial situation. This is already in progress with another housemate moving in shortly.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;Professional&lt;/h2&gt;

&lt;p&gt;In 2012 I made a huge change in my career moving firmly into a Rails focused role as Lead Developer
for &lt;a href="https://www.airtasker.com"&gt;Airtasker&lt;/a&gt;. I also taught a Ruby on Rails focused course for
General Assembly at the end of the year.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start contributing to an Open Source project.&lt;/li&gt;
&lt;li&gt;Pick up some small contract work outside of work hours.&lt;/li&gt;
&lt;li&gt;See where the Airtasker ride takes me over the year.&lt;/li&gt;
&lt;li&gt;I&amp;#39;d really love to teach again.&lt;/li&gt;
&lt;li&gt;Continue to participate in the Ruby community going to events like &lt;a href="http://ruby.org.au/meetups/syd.html"&gt;RoRo&lt;/a&gt;, &lt;a href="http://railscamps.com/"&gt;Railscamp&lt;/a&gt; 
and the upcoming &lt;a href="http://rubyconf.org.au/"&gt;RubyConf&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Blog at least once a week.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src="/images/railscamp.jpg" alt="Railscamp"&gt;&lt;/p&gt;

&lt;p&gt;Overall I feel that my fitness goals are going to be the most challenging, but they&amp;#39;re also my most important
ones for this year. Last year I really changed up my professional life with a big job change, focusing heavily
on Rails and web development, and then teaching later in the year.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Cucumber</title>
    <link rel="alternate" href="http://bottledup.net/2013/01/08/cucumber/"/>
    <id>http://bottledup.net/2013/01/08/cucumber/</id>
    <published>2013-01-08</published>
    <updated>2013-01-08</updated>
    <author>
      <name>Leonard Garvey</name>
    </author>
    <summary type="html">&lt;p&gt;Cucumber is a common tool used in many Rails applications to provide Acceptance/Integration
testing. It uses a DSL called &lt;a href="https://github.com/cucumber/gherkin"&gt;Gherkin&lt;/a&gt; which is a
&lt;a href="http://www.martinfowler.com/bliki/BusinessReadableDSL.html"&gt;Business Readable DSL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The idea is that you write the features of your application into Scenarios which are then
executed by Cucumber. As a developer you also provide the steps to execute those Scenarios
often using a tool like &lt;a href="https://github.com/jnicklas/capybara"&gt;Capybara&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the Rails community Cucumber can be slightly contraversial but I&amp;#39;ve come to believe that Cucumber is greatly misunderstood within the community.&lt;/p&gt;

&lt;blockquote class="twitter-tweet tw-align-center" data-in-reply-to="279087947070980096"&gt;&lt;p&gt;@&lt;a href="https://twitter.com/twe4ked"&gt;twe4ked&lt;/a&gt; I’ve come to really like Cucumber. I think it gets an unfair rap from a lot of devs.&lt;/p&gt;&amp;mdash; Leonard Garvey (@lgarvey) &lt;a href="https://twitter.com/lgarvey/status/279088834115940352" data-datetime="2012-12-13T05:02:17+00:00"&gt;December 13, 2012&lt;/a&gt;&lt;/blockquote&gt;
</summary>
    <content type="html">&lt;p&gt;Cucumber is a common tool used in many Rails applications to provide Acceptance/Integration
testing. It uses a DSL called &lt;a href="https://github.com/cucumber/gherkin"&gt;Gherkin&lt;/a&gt; which is a
&lt;a href="http://www.martinfowler.com/bliki/BusinessReadableDSL.html"&gt;Business Readable DSL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The idea is that you write the features of your application into Scenarios which are then
executed by Cucumber. As a developer you also provide the steps to execute those Scenarios
often using a tool like &lt;a href="https://github.com/jnicklas/capybara"&gt;Capybara&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the Rails community Cucumber can be slightly contraversial but I&amp;#39;ve come to believe that Cucumber is greatly misunderstood within the community.&lt;/p&gt;

&lt;blockquote class="twitter-tweet tw-align-center" data-in-reply-to="279087947070980096"&gt;&lt;p&gt;@&lt;a href="https://twitter.com/twe4ked"&gt;twe4ked&lt;/a&gt; I’ve come to really like Cucumber. I think it gets an unfair rap from a lot of devs.&lt;/p&gt;&amp;mdash; Leonard Garvey (@lgarvey) &lt;a href="https://twitter.com/lgarvey/status/279088834115940352" data-datetime="2012-12-13T05:02:17+00:00"&gt;December 13, 2012&lt;/a&gt;&lt;/blockquote&gt;

&lt;p&gt;A really great conversation followed on Twitter, but I do often feel constrained by 140 characters.&lt;/p&gt;

&lt;h3&gt;Is love too strong a word?&lt;/h3&gt;

&lt;p&gt;I really like using Cucumber. Whenever I write a Feature I feel like I&amp;#39;m focused implementing that
functionality, even if the very next thing I do is write a few specs for models and controllers.
I feel that if I ever get sidetracked I can get right back into the flow by just running my Cuke.&lt;/p&gt;

&lt;p&gt;It&amp;#39;s for this reason that I completely agree with Chris Parsons when he says that &lt;a href="http://chrismdp.com/2012/09/cucumber-isnt-a-testing-tool/"&gt;Cucumber isn&amp;#39;t a testing tool&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;A sales issue&lt;/h3&gt;

&lt;p&gt;Besides the whole web-steps awfulness, which is extremely well explained by Jonas Nicklas in his
great post &lt;a href="http://www.elabs.se/blog/15-you-re-cuking-it-wrong"&gt;You&amp;#39;re cuking it wrong&lt;/a&gt;, I think Cucumber has a sales problem.&lt;/p&gt;

&lt;blockquote class="twitter-tweet tw-align-center" data-in-reply-to="279102964893904896"&gt;&lt;p&gt;@&lt;a href="https://twitter.com/mwotton"&gt;mwotton&lt;/a&gt; @&lt;a href="https://twitter.com/lgarvey"&gt;lgarvey&lt;/a&gt; User stories are a great way to describe a system. Cucumber's problem is claiming that you can run them with little effort&lt;/p&gt;&amp;mdash; Warren Seen (@warren_s) &lt;a href="https://twitter.com/warren_s/status/279103716773228545" data-datetime="2012-12-13T06:01:26+00:00"&gt;December 13, 2012&lt;/a&gt;&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;Understanding how to set it up as a newbie can be difficult. It isn&amp;#39;t well described on the &lt;a href="http://cukes.info/"&gt;Cucumber website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;It promises a great deal: &amp;quot;The text is written in a business-readable domain-specific language and serves as documentation, automated tests and development-aid - all rolled into one format&amp;quot;
The issue with this type of promise is that it doesn&amp;#39;t seem to fit in with how most devs view the world. They have
automated tests (written in Ruby!) so don&amp;#39;t see the need for more wordy abstraction. They view the Features as something
else to maintain in addition to tests and documentation.&lt;/li&gt;
&lt;li&gt;Cucumber is often sold as a way for Business people and devs to communicate. I&amp;#39;d argue instead that it&amp;#39;s a way for devs and anyone else to communicate,
you don&amp;#39;t get benefit from Cucumber only if you can convince your Business Analyst to read your feature files.
You should get benefit from Cucumber ever time you on-board a new developer, every time you need to remind yourself, or another dev,
how a complex feature works (at least at a high level).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If Cucumber was instead pitched as a tool that helped you keep (and communicate) simple system requirements
and your app in-sync then I think it would get more acceptance.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Expected: [] Got: [] - Ruby Object Equality</title>
    <link rel="alternate" href="http://bottledup.net/2012/12/13/expected--got----ruby-object-equality/"/>
    <id>http://bottledup.net/2012/12/13/expected--got----ruby-object-equality/</id>
    <published>2012-12-13</published>
    <updated>2012-12-13</updated>
    <author>
      <name>Leonard Garvey</name>
    </author>
    <summary type="html">&lt;p&gt;Recently while working on &lt;a href="https://www.airtasker.com"&gt;Airtasker&lt;/a&gt;
we got the following error from our (pretty extensive) Rspec test suite:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="no"&gt;Failures&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;UsersController&lt;/span&gt;&lt;span class="c1"&gt;#show with user actions gets user actions&lt;/span&gt;
     &lt;span class="no"&gt;Failure&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;assigns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:actions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.should&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;actions&lt;/span&gt;
       &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
            &lt;span class="n"&gt;got&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="c1"&gt;# ./spec/controllers/users_controller_spec.rb:51:in `block (4 levels) in &amp;lt;top (required)&amp;gt;'&lt;/span&gt;

&lt;span class="no"&gt;Finished&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;46&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;
&lt;span class="mi"&gt;11&lt;/span&gt; &lt;span class="n"&gt;examples&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;failure&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The fix ended up being fairly simple, simply reverse the output which causes the test to pass.
This led to one of my collegues commenting that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One of the empty arrays was backwards.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;Not sure if Serious&lt;/h3&gt;

&lt;p&gt;&lt;img src="http://t.qkme.me/3ooht0.jpg" alt="Not Sure if serious"&gt;&lt;/p&gt;
</summary>
    <content type="html">&lt;p&gt;Recently while working on &lt;a href="https://www.airtasker.com"&gt;Airtasker&lt;/a&gt;
we got the following error from our (pretty extensive) Rspec test suite:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="no"&gt;Failures&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;UsersController&lt;/span&gt;&lt;span class="c1"&gt;#show with user actions gets user actions&lt;/span&gt;
     &lt;span class="no"&gt;Failure&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;assigns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:actions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.should&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;actions&lt;/span&gt;
       &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
            &lt;span class="n"&gt;got&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="c1"&gt;# ./spec/controllers/users_controller_spec.rb:51:in `block (4 levels) in &amp;lt;top (required)&amp;gt;'&lt;/span&gt;

&lt;span class="no"&gt;Finished&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;46&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;
&lt;span class="mi"&gt;11&lt;/span&gt; &lt;span class="n"&gt;examples&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;failure&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The fix ended up being fairly simple, simply reverse the output which causes the test to pass.
This led to one of my collegues commenting that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One of the empty arrays was backwards.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;Not sure if Serious&lt;/h3&gt;

&lt;p&gt;&lt;img src="http://t.qkme.me/3ooht0.jpg" alt="Not Sure if serious"&gt;&lt;/p&gt;

&lt;p&gt;I&amp;#39;m fairly certain he was joking, but I wanted to know exactly what was happening.
I was able to replicate the issue in the rails console just by manually executing the test
(which is a fantastic way of understanding code)&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;01&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;01&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;020&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;It turns out that the the &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; are &lt;a href="https://github.com/rails/rails/blob/4657dba60eebc0d7cea11ffd18aa70d7a3d00e45/activerecord/lib/active_record/relation.rb"&gt;&lt;code&gt;ActiveRecord::Relation&lt;/code&gt;&lt;/a&gt;
From there it was pretty easy to figure out what was happening, the &lt;code&gt;Relation&lt;/code&gt; class implements the equality
method &lt;code&gt;==&lt;/code&gt; which Rspec was using. Because both objects are &lt;code&gt;Relations&lt;/code&gt; it compares their sql rather than the result.
When reversing the Relation it executes the sql and compares them as an array.&lt;/p&gt;

&lt;h3&gt;Lessons Learned&lt;/h3&gt;

&lt;p&gt;There are a few cool lessons here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ruby isn&amp;#39;t magic, source code is pretty easy to read.&lt;/li&gt;
&lt;li&gt;Try using irb or a debugger to figure out more about your particular issue.&lt;/li&gt;
&lt;li&gt;In your custom objects implement the equality method, or even better include comparable and implement &lt;code&gt;&amp;lt;=&amp;gt;&lt;/code&gt;
which will give you all of the comparison methods for free!&lt;/li&gt;
&lt;/ol&gt;
</content>
  </entry>
  <entry>
    <title>Deleting you Softly</title>
    <link rel="alternate" href="http://bottledup.net/2012/12/11/deleting-you-softly/"/>
    <id>http://bottledup.net/2012/12/11/deleting-you-softly/</id>
    <published>2012-12-11</published>
    <updated>2012-12-11</updated>
    <author>
      <name>Leonard Garvey</name>
    </author>
    <summary type="html">&lt;h2&gt;A tale of woe&lt;/h2&gt;

&lt;p&gt;You&amp;#39;re building a great new app and the product manager/business person says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hey we&amp;#39;re going to need to be able to delete things, and then restore things that get deleted&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sure no problem, I&amp;#39;ll just include this gem that lets me soft delete and make a few code changes to my models&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You&amp;#39;ve already made a huge mistake, the damage is done just take your hands off the keyboard.&lt;/p&gt;

&lt;h2&gt;What&amp;#39;s the issue?&lt;/h2&gt;

&lt;p&gt;The problem is that your database (and therefore ActiveRecord) is the
source of all truth within your application. You&amp;#39;ve just made that truth inconsistent and more
difficult to define, truth becomes truthish and much pain ensues.&lt;/p&gt;

&lt;p&gt;I could leave this blog post there, but I think some justification is in order. First I need&lt;/p&gt;
</summary>
    <content type="html">&lt;h2&gt;A tale of woe&lt;/h2&gt;

&lt;p&gt;You&amp;#39;re building a great new app and the product manager/business person says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hey we&amp;#39;re going to need to be able to delete things, and then restore things that get deleted&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sure no problem, I&amp;#39;ll just include this gem that lets me soft delete and make a few code changes to my models&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You&amp;#39;ve already made a huge mistake, the damage is done just take your hands off the keyboard.&lt;/p&gt;

&lt;h2&gt;What&amp;#39;s the issue?&lt;/h2&gt;

&lt;p&gt;The problem is that your database (and therefore ActiveRecord) is the
source of all truth within your application. You&amp;#39;ve just made that truth inconsistent and more
difficult to define, truth becomes truthish and much pain ensues.&lt;/p&gt;

&lt;p&gt;I could leave this blog post there, but I think some justification is in order. First I need
to explain what I mean by &amp;quot;soft delete&amp;quot; and explain roughly how that&amp;#39;s implemented. Hopefully
you&amp;#39;ll soon agree with me that it&amp;#39;s generally a bad idea.&lt;/p&gt;

&lt;h2&gt;Soft Delete&lt;/h2&gt;

&lt;p&gt;Soft delete is a process where instead of deleting records in your database you simply flag
them as deleted. In Rails this might mean you use &lt;a href="http://github.com/JackDanger/permanent_records"&gt;permanent_records&lt;/a&gt;
which lets you use a &lt;code&gt;deleted_at&lt;/code&gt; timestamp field in your models to mark the record as &amp;quot;deleted&amp;quot;.
Also you&amp;#39;ll end up defining a default scope which filters out all those &amp;quot;deleted&amp;quot; records:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="n"&gt;default_scope&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:deleted_at&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;What &lt;a href="http://github.com/JackDanger/permanent_records"&gt;permanent_records&lt;/a&gt; does is overrides the standard
&lt;code&gt;destroy&lt;/code&gt; and &lt;code&gt;destroy_all&lt;/code&gt; methods and instead just marks this records with the time they were
&amp;quot;deleted&amp;quot;. It&amp;#39;s smart enough to follow dependencies such as &lt;code&gt;has_many&lt;/code&gt; and so on.&lt;/p&gt;

&lt;h2&gt;The Problem Revealed&lt;/h2&gt;

&lt;p&gt;There are a few issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;If you destroy an object that isn&amp;#39;t soft deleted, but has dependant objects that are
soft-deletable then the parent object is actually deleted, while the child objects are only soft
deleted. You can&amp;#39;t revive them or work with this like normal objects in this case.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Admin panels where you can view soft deleted objects by using &lt;code&gt;unscoped&lt;/code&gt; become problematic,
business people begin to abuse the deletion functionality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you&amp;#39;re viewing a &amp;quot;deleted&amp;quot; record (for example in the Admin panel) none of the
associations will work because they&amp;#39;ll revert to using the &lt;code&gt;default_scope&lt;/code&gt; of the association.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ultimately the problem is that you&amp;#39;re not letting your database manage truth. The database itself
is fantastic at enforcing Foreign Key constraints and it&amp;#39;s something that I think Rails
developers aren&amp;#39;t particularly good at.&lt;/p&gt;

&lt;h2&gt;Partial Solutions&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Make sure you are extremely disciplined about setting up your &lt;code&gt;dependant_destroy&lt;/code&gt; declarations
in your models. This is a remarkably easy trap to fall into, and takes constant developer awareness
in order to avoid. A different strategy is to use &lt;code&gt;after_destroy&lt;/code&gt; (or &lt;code&gt;before_destroy&lt;/code&gt;) callbacks to flag dependant
records as deleted.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="n"&gt;after_destroy&lt;/span&gt; &lt;span class="ss"&gt;:clean_up_your_mess&lt;/span&gt;
&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Train your business and administration staff to not think that deleting and restoring is a
good tactic to try. This isn&amp;#39;t a computer to be turned off then turned back on again in a futile
effort to fix the issue. Because of caching bugs it can be easy to get into the situation where
non-technical staff think that the record needs to be deleted and restored before it works properly (don&amp;#39;t laugh).
And because of &lt;code&gt;timestamps&lt;/code&gt; on many models this deletion and restoration will actually cause
a cache miss if you&amp;#39;re using fragment caching like you should be!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There is soem horribly awful code you can put into your Rails application which will fix
the scoped -&amp;gt; unscoped association issue.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Associations&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Association&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;scoped&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="nf"&gt;.is_permanent?&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="nf"&gt;.deleted_at?&lt;/span&gt;
      &lt;span class="n"&gt;association_scope&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;target_scope&lt;/span&gt;&lt;span class="nf"&gt;.merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;association_scope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Note: this code will need to be changed in Rails 4 where scoped has been deprecated in favour of scope.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Don&amp;#39;t use soft delete&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;More helpfully, don&amp;#39;t use soft delete and propose an alternative solution when this requirement comes up.
It&amp;#39;s a common requirement to never actually &amp;quot;delete&amp;quot; anything from the database, so argue in favour of never
deleting something. It&amp;#39;s better for your business if you keep all that valuable data.&lt;/p&gt;

&lt;p&gt;If you do need to delete something, simply serialize it to json and keep a record of it. I&amp;#39;ve thought of
creating a &lt;code&gt;deleted_things&lt;/code&gt; table where I can throw all the things that get deleted. This way it&amp;#39;s not
impossible to revive an object, but it is sufficiently difficult that you won&amp;#39;t want to do it regularly.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Using a Primary Key Factory for Mongoid</title>
    <link rel="alternate" href="http://bottledup.net/2012/03/19/using-a-primary-key-factory-for-mongoid/"/>
    <id>http://bottledup.net/2012/03/19/using-a-primary-key-factory-for-mongoid/</id>
    <published>2012-03-19</published>
    <updated>2012-03-19</updated>
    <author>
      <name>Leonard Garvey</name>
    </author>
    <summary type="html">&lt;p&gt;I&amp;#39;m developing a joke application for a bit of fun and to fill out my
github with some more public code. So I&amp;#39;m creating
&lt;a href="https://github.com/lengarvey/blitter"&gt;Blitter&lt;/a&gt; which lets me do some
playing and development with mongodb and rails using mongoid.&lt;/p&gt;

&lt;p&gt;One of the things I wanted to support was querying of User objects by
the name of the user rather than the &lt;code&gt;_id&lt;/code&gt;. Obviously I could have
just altered the show action in &lt;code&gt;users_controller.rb&lt;/code&gt; to query by
name:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="nf"&gt;.find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The problem with this is it breaks the standard rails url helpers. You
get the following error: &lt;code&gt;Mongoid::Errors::InvalidFind in
UsersController#show&lt;/code&gt;. So instead what we can do is use the name of&lt;/p&gt;
</summary>
    <content type="html">&lt;p&gt;I&amp;#39;m developing a joke application for a bit of fun and to fill out my
github with some more public code. So I&amp;#39;m creating
&lt;a href="https://github.com/lengarvey/blitter"&gt;Blitter&lt;/a&gt; which lets me do some
playing and development with mongodb and rails using mongoid.&lt;/p&gt;

&lt;p&gt;One of the things I wanted to support was querying of User objects by
the name of the user rather than the &lt;code&gt;_id&lt;/code&gt;. Obviously I could have
just altered the show action in &lt;code&gt;users_controller.rb&lt;/code&gt; to query by
name:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="nf"&gt;.find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The problem with this is it breaks the standard rails url helpers. You
get the following error: &lt;code&gt;Mongoid::Errors::InvalidFind in
UsersController#show&lt;/code&gt;. So instead what we can do is use the name of
each user as the primary key of the class!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mongodb/mongo-ruby-driver"&gt;The mongodb ruby driver&lt;/a&gt;
says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A primary key factory is a class you supply to a DB object that knows
how to generate _id values. If you want to control _id values or even
their types, using a PK factory lets you do so.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The problem with &lt;a href="http://mongoid.org/"&gt;Mongoid&lt;/a&gt; is that there isn&amp;#39;t an
easy way to use a primary key factory. No problems!&lt;/p&gt;

&lt;p&gt;Create config/initializers/mongoid.rb and paste the following:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PKFactory&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_pk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;creating &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="nf"&gt;.inspect&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'_id'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;row&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;Mongoid&lt;/span&gt;&lt;span class="nf"&gt;.configure&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="nf"&gt;.inspect&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="nf"&gt;.master&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Mongo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Connection&lt;/span&gt;&lt;span class="nf"&gt;.new.db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Mongoid&lt;/span&gt;&lt;span class="nf"&gt;.database.name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:pk&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;PKFactory&lt;/span&gt;&lt;span class="nf"&gt;.new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Afterwards just change your user model:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="n"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:type&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;See https://gist.github.com/2072345 or the commit in blitter:
https://github.com/lengarvey/blitter/commit/4cc76b7ede518c8d112e66a49e18ad1090081af7&lt;/p&gt;

&lt;p&gt;Super easy!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>MongoDB Sydney</title>
    <link rel="alternate" href="http://bottledup.net/2012/03/18/mongodb-sydney/"/>
    <id>http://bottledup.net/2012/03/18/mongodb-sydney/</id>
    <published>2012-03-18</published>
    <updated>2012-03-18</updated>
    <author>
      <name>Leonard Garvey</name>
    </author>
    <summary type="html">&lt;p&gt;Yesterday I attended 10gen&amp;#39;s &lt;a href="http://www.10gen.com/events/mongodb-sydney"&gt;first Australian MongoDB
conference&lt;/a&gt;. While most of
the sessions were relatively basic it left me burning to continue
working on some MongoDB projects I&amp;#39;ve been working with lately.
The most informative session of the day was on sharding. I don&amp;#39;t expect
to have cause to use sharding in production any time soon but I have a
better understanding of how the sharding key works to balance data
across the cluster. Certain assumptions I had previously had were
completely wrong so it&amp;#39;s great to get those cleared up.&lt;/p&gt;

&lt;p&gt;The biggest project I&amp;#39;ve had is experimentation with the &lt;a href="http://blog.mongodb.org/post/16015854270/operations-in-the-new-aggregation-framework"&gt;aggregation
framework&lt;/a&gt; which is available in MongoDB 2.1 (2.2 for stable)&amp;hellip;&lt;/p&gt;
</summary>
    <content type="html">&lt;p&gt;Yesterday I attended 10gen&amp;#39;s &lt;a href="http://www.10gen.com/events/mongodb-sydney"&gt;first Australian MongoDB
conference&lt;/a&gt;. While most of
the sessions were relatively basic it left me burning to continue
working on some MongoDB projects I&amp;#39;ve been working with lately.
The most informative session of the day was on sharding. I don&amp;#39;t expect
to have cause to use sharding in production any time soon but I have a
better understanding of how the sharding key works to balance data
across the cluster. Certain assumptions I had previously had were
completely wrong so it&amp;#39;s great to get those cleared up.&lt;/p&gt;

&lt;p&gt;The biggest project I&amp;#39;ve had is experimentation with the &lt;a href="http://blog.mongodb.org/post/16015854270/operations-in-the-new-aggregation-framework"&gt;aggregation
framework&lt;/a&gt; which is available in MongoDB 2.1 (2.2 for stable).&lt;/p&gt;

&lt;h2&gt;Installing MongoDB 2.1 on OSX&lt;/h2&gt;

&lt;p&gt;If you aren&amp;#39;t using &lt;a href="https://github.com/mxcl/homebrew"&gt;homebrew&lt;/a&gt; you should be.
To install the current version of MongoDB it&amp;#39;s as simple as &lt;/p&gt;
&lt;pre class="highlight shell"&gt;brew install mongodb
&lt;/pre&gt;
&lt;p&gt;but if you want to experiment with the Aggregation Framework which won&amp;#39;t
be stable until 2.2 you can install 2.1 with the following instructions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update the mongodb recipe with the following gist
https://gist.github.com/2006403 :&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="n"&gt;brew&lt;/span&gt; &lt;span class="n"&gt;edit&lt;/span&gt; &lt;span class="n"&gt;mongodb&lt;/span&gt;
&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;Install mongodb 2.1!&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="n"&gt;brew&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;mongodb&lt;/span&gt;
&lt;/pre&gt;
&lt;h2&gt;Still Running with MapReduce&lt;/h2&gt;

&lt;p&gt;Even after playing with the Agg framework I&amp;#39;ve still found that my
needs require map reduce. I&amp;#39;d love to use the Agg Framework since it&amp;#39;s
meant to be more performant, it&amp;#39;s written in C++ so doesn&amp;#39;t block single
Javascript server thread, but I just can&amp;#39;t figure out how!&lt;/p&gt;

&lt;p&gt;Unfortunately I can&amp;#39;t really share the concept since it&amp;#39;s fairly work
related.&lt;/p&gt;

&lt;h2&gt;MapReducing&lt;/h2&gt;

&lt;p&gt;Reading on stackoverflow and the mongodb-user google group definitely
reveals that many people have issues with map reduce. I think it&amp;#39;s
pretty simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You loop over all the documents (map)&lt;/li&gt;
&lt;li&gt;You emit some stuff from those documents (emit)&lt;/li&gt;
&lt;li&gt;You combine all the stuff you emit down using some function (reduce)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most common reduce is to just add things together. One little trick
I noticed (and should have realised before) was that MongoDB provides an
Array.prototype.sum function. So in the MongoDB shell the following code
works:&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; returns 1+2+3+4+5 = 15!
&lt;/span&gt;&lt;/pre&gt;</content>
  </entry>
</fe