<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>The Life of a Radar</title>
 
 <link href="http://ryanbigg.com" />
 <updated>2013-06-12T14:05:27+10:00</updated>
 <id>http://ryanbigg.com/</id>
 <author>
   <name>Ryan Bigg</name>
   <email>radarlistener@gmail.com</email>
 </author>

 
 <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/ryanbigg" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="ryanbigg" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
   <title>About spec/support</title>
   <link href="http://ryanbigg.com/2013/02/about-spec-support" />
   <updated>2013-02-02T00:00:00+11:00</updated>
   <id>http://ryanbigg.com/2013/02/about-spec-support</id>
   <content type="html"><![CDATA[<p>I&#39;m going to expand on a tweet I wrote this morning:</p>

<blockquote>
<p>Thinking more and more that spec/support is
an anti-pattern. I don&#39;t want everything required for every test.</p>
</blockquote>

<p>I came to this thought when I was working on sharing testing support code
between an engine and an application, for an example in Chapter 4 of
<a href="https://leanpub.com/multi-tenancy-rails">Multitenancy with Rails</a>. What I had
originally was a file in <code>spec/support</code> called <code>SubdomainHelpers</code>, defined like
this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">module SubdomainHelpers
  def within_account_subdomain(&amp;block)
    context &quot;within a subdomain&quot; do
      let(:subdomain_url) { &quot;http://#{account.subdomain}.example.com&quot; }
      before { Capybara.default_host = subdomain_url } 
      after { Capybara.default_host = &quot;http://example.com&quot; }
      yield
    end
  end
end
</code></pre></div>
<p>This module is then used to extend the RSpec <code>describe</code> blocks, like this</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">describe &quot;User sign in&quot; do
  extend SubdomainHelpers
  ...
end
</code></pre></div>
<p>And then we can call <code>within_account_subdomain</code> whenever we need it.</p>

<hr>

<p>My problem with this is that this file is required <em>all the damn time</em>, even in
tests which don&#39;t use Capybara. The culprit is this default line in
<code>spec/spec_helper.rb</code></p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">Dir[File.dirname(__FILE__) + &quot;/support/**/*.rb&quot;].each {|f| require f }
</code></pre></div>
<p>This line is used for requiring all the files in <code>spec/support</code> so that you
don&#39;t have to. Seems like a good idea, but isn&#39;t once you have a ton of things
in <code>spec/support</code>.</p>

<p>Making it easy to require the file defining <code>SubdomainHelpers</code> in both the
engine and the application involves moving the helper in to the <code>lib</code> directory
of the engine, and then requiring that file in the appropriate places:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">require &#39;subscribem/testing_support/subdomain_helpers&#39;
</code></pre></div>
<p>Even if we <em>weren&#39;t</em> using an engine and an application and just had the
application, I would much rather just be requiring just the files I need for a
test, like this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">require &#39;support/subdomain_helpers&#39;
</code></pre></div>
<p>Than having the full range of <code>spec/support</code> files loaded all at once on the
off chance a spec might need it. I wouldn&#39;t expect this to <em>dramatically</em> increase a spec suite&#39;s
run time, but it&#39;s got to be helping somewhat.</p>
]]></content>
 </entry>
 
 <entry>
   <title>Multitenancy with Rails</title>
   <link href="http://ryanbigg.com/2013/01/multitenancy-with-rails" />
   <updated>2013-01-21T00:00:00+11:00</updated>
   <id>http://ryanbigg.com/2013/01/multitenancy-with-rails</id>
   <content type="html"><![CDATA[<p>Well before I had even <a href="http://ryanbigg.com/2012/11/no-more-writing-for-manning/">split from
Manning</a>, I had been
working on a new book called <a href="https://leanpub.com/multi-tenancy-rails">&quot;Multitenancy with
Rails&quot;</a>, which you can buy right now.</p>

<p>The idea for the book has been around for a while. A couple of friends (<a href="https://github.com/parndt">Phil
Arndt</a>, <a href="https://github.com/knewter">Josh Adams</a>,
<a href="https://github.com/robyurkowski">Rob Yurkowski</a> and <a href="https://github.com/GeekOnCoffee">Andrew
Hooker</a>) and I had been talking in our secret
IRC back channel about what a more advanced Rails book might cover. Through I
don&#39;t know what process, we came up with this idea and I&#39;m putting it into book
form.</p>

<p>For now, all the book is covering is what we&#39;re building, which is a hosted
forum application, how to build a foundation for the subscriptions
engine and then how we&#39;re going to accomplish the database scoping necessary to
separate the accounts&#39; data. </p>

<p>The engine is what the book&#39;s application is going to heavily rely on. This foundation
building deals with adding things like accounts which have subdomains, and then
authenticating users for those accounts using Warden, and not Devise. To find
out why, you&#39;re going to have to read it.</p>

<p>The chapter on scoping first of all covers using a database field, which is the typical way
that people have been dealing with this problem for years, and then covers the
&quot;new&quot; way of doing it: by using PostgreSQL schemas and the <code>apartment</code> gem.</p>

<p>The next chapter, Chapter 4, will cover building the application which will
combine both the subscriptions engine we build in Chapter 2, as well as the
<a href="https://github.com/radar/forem">Forem</a> forum engine that the aforementioned
folk and I build and maintain.</p>

<p>Chapter 5 will cover subscriptions, where each account could be subscribed to
the application for an amount such as $29/month and that allows them to create 5
forums. That sort of thing. It&#39;ll also cover taking payments for those
subscriptions using Stripe&#39;s wonderful API, and then what to do if somebody
decides to do a dodgy.</p>

<p>Testing (with RSpec and Capybara) is throughout, just like with Rails 3 in
Action.</p>

<p>So if you&#39;re looking for a book that covers all of the above, please <a href="https://leanpub.com/multi-tenancy-rails">buy a copy
of Multitenancy with Rails</a> <em>right
now</em>.</p>
]]></content>
 </entry>
 
 <entry>
   <title>A story about scaffolding</title>
   <link href="http://ryanbigg.com/2013/01/a-story-about-scaffolding" />
   <updated>2013-01-07T00:00:00+11:00</updated>
   <id>http://ryanbigg.com/2013/01/a-story-about-scaffolding</id>
   <content type="html"><![CDATA[<p>When Rails was released, one of the &quot;showy&quot; features in it was the ability to get up and running quickly. That&#39;s always been the focus for Rails.</p>

<p>One of the things that allowed you to get up and running so quickly was the scaffold feature of Rails. You would run <code>rails generate scaffold posts</code> and there you would then have a scaffold for posts that would allow you to perform CRUD (Create, Read, Update and Destroy) actions on these posts. Back in Rails 1 days, it was a simple one line in your controller: <code>scaffold</code>. In later Rails releases (can&#39;t remember right now which one specifically), this was changed to generating the familiar scaffold controllers you see today that provide a HTML and XML response, or even more recently, a HTML and JSON response.</p>

<p>Scaffolding is great for getting something that will allow you to perform those CRUD actions on it. However, the moment you need to step outside that safe cocoon, you run into trouble. You want to add a new field to your database, say an author field if we&#39;re sticking with the Post scaffold idea. So you do that, but then you don&#39;t realise that you need to add the field to the <code>attr_accessible</code> list<a href="which%20you%20had%20no%20idea%20about%20until%20someone%20told%20you%20about%20it%20in%20the%20Rails%20channel">^1</a>, and you&#39;d need to add it to the form partial as well. Newbies don&#39;t learn how to do these very, very basic things first off <em>if they&#39;re using scaffolding</em> and that&#39;s why it&#39;s a bad thing.</p>

<p>If you begin using scaffolding, you can indeed see exactly what functionality Rails is capable of. Goodo, you can create, read, update and delete things. The problem, however, is that you end up not learning how any of it works, and it seems like &quot;a wizard did it&quot;. Of course, as you get more knowledgeable about Rails you&#39;ll know that there&#39;s no such thing as wizards.</p>

<p>Learning from the ground up that in order to be able to display even a list of posts on a page that you need a <code>Post</code> model, that the model responds to an <code>all</code> method, that is then called in a thing called <code>PostsController</code> and then that information is stored in an instance variable which is then accessed by this thing called a &quot;view&quot; which has the same name as your action... that may seem like hard work at first (hint: it is), but it&#39;s worth it. That is because the moment you want to step outside the cocoon of a CRUD resource and do something differently, you&#39;ll probably know how to. </p>

<p>Scaffolding doesn&#39;t teach you the extreme basics of Rails development. Building things from scratch does. This foundation is absolutely critical to understanding how Rails works.</p>

<p>[^1]: <code>attr_accessible</code> is going away in Rails 4, being replaced by https://github.com/rails/strong_parameters</p>
]]></content>
 </entry>
 
 <entry>
   <title>No more writing for Manning</title>
   <link href="http://ryanbigg.com/2012/11/no-more-writing-for-manning" />
   <updated>2012-11-12T00:00:00+11:00</updated>
   <id>http://ryanbigg.com/2012/11/no-more-writing-for-manning</id>
   <content type="html"><![CDATA[<p>As of around this time last week, I am no longer writing for Manning.</p>

<p>This decision has been a long time coming. Ever since I started working for
Manning I&#39;ve had issues with their tooling. I covered these in posts like <a href="http://ryanbigg.com/2011/11/don-t-print-hard-copies/">&quot;Don&#39;t print
hard-copies&quot;</a> and <a href="http://ryanbigg.com/2010/12/the-writing-process/">&quot;The
Writing Process&quot;</a>).
They&#39;ve been saying now for <em>two years</em> that they were going to fix it and...
nothing much has been done.</p>

<p>I got so frustrated with their system two weeks in, I decided to write my own.
I demonstrate part of Manning&#39;s system and part of my own, in <a href="https://vimeo.com/45002976">this short
video</a>. I wrote my own review system in
a relatively short period of time.</p>

<p>The writing tools are something that I need to use everyday and if they&#39;re just
getting in my way, it totally kills my vibe to write. I don&#39;t want to hate
writing, because I <em>love</em> writing. I love the feeling I get when I can clearly
explain something to someone the first time in writing and they just <em>get it</em>.</p>

<p>So, no more writing for Manning because their tools for doing it are terrible.
The people at Manning are nothing short of excellent.</p>

<p>Rails 4 in Action <em>will</em> be published by Manning -- they have the rights to the
book, not me -- meaning they will need to source another author to do it. For
any questions related to that process, contact <a 
href='support@manning.com'>support@manning.com</a>. They&#39;ll know more about it
than I do.</p>

<hr>

<p>All of that doesn&#39;t mean I&#39;ve stopped writing Rails material completely. Oh no no no. You just wait.</p>
]]></content>
 </entry>
 
 <entry>
   <title>I didn't submit a talk to RubyConf Australia</title>
   <link href="http://ryanbigg.com/2012/11/i-didn-t-submit-a-talk-to-rubyconf-australia" />
   <updated>2012-11-01T00:00:00+11:00</updated>
   <id>http://ryanbigg.com/2012/11/i-didn-t-submit-a-talk-to-rubyconf-australia</id>
   <content type="html"><![CDATA[<p>Because I have nothing interesting to talk about.</p>

<p>Honestly: I can&#39;t think of a single thing that I think would be entertaining for a wide audience to listen to me talk about. I don&#39;t want to submit a talk based solely on the notion that I&#39;m supposed to be a mildly-famous member of the Australian Ruby community. What a crap premise to submit a talk on! What on earth could I possibly give a talk about and make informative for a large audience?</p>

<p>I&#39;m not going to talk about writing a book because I already moan and bitch about that enough on Twitter. Plus, the actual act of writing a book isn&#39;t <em>exciting</em>.</p>

<p>I&#39;m not going to talk about documentation because nobody gives a crap about proper documentation, save for a very small select group of people and the people who are reading it. Don&#39;t bullshit me. You know it&#39;s true.</p>

<p>I&#39;m not going to talk about engines in general because there&#39;s already a great guide that covers 95% of what a conference audience needs to know. Chapter 17 of Rails 3 in Action covers it and a bit more also. No point giving a talk about something that&#39;s already been written about. Personally, I go to conferences to see <em>new, cool and interesting stuff</em>. Not things that I can read about or watch on the Internet.</p>

<p>I&#39;m not going to talk about my work on Spree because -- and I say this without intending an arrogant tone -- the work itself is self-evident and you don&#39;t need to hear about it at a conference. I&#39;m especially <em>not</em> going to talk about my thoughts on how to split up a monolithic <em>engine</em> such as Spree into smaller, easier to manage components. That checkout state machine work that I did? Excuse my brashness, but that was fucking awesome and I&#39;m so damn proud of it, but I&#39;m not going to talk about <em>that</em> either. Allowing Spree stores to choose their authentication backend? Please. It was just this thing I did. It doesn&#39;t deserve a whole conference talk.</p>

<p>I&#39;m quite happy, this time, to sit there and be an audience member who is learning about all the <em>new, cool and interesting stuff</em> <strong>other</strong> people are doing.</p>
]]></content>
 </entry>
 
 <entry>
   <title>JavaScript Arrays and Objects</title>
   <link href="http://ryanbigg.com/2012/10/javascript-arrays-and-objects" />
   <updated>2012-10-03T00:00:00+10:00</updated>
   <id>http://ryanbigg.com/2012/10/javascript-arrays-and-objects</id>
   <content type="html"><![CDATA[<p><a href="https://github.com/spree/spree/blob/bf0b85472e477f20f84d030c575382b9c0922903/core/app/views/spree/admin/return_authorizations/_form.html.erb#L54-56">These three little lovely lines</a> of very-much obtrusive JavaScript caused a little bit of frustration this afternoon.</p>

<p>What was happening was that in Google Chrome, the page was giving an &quot;aw snap!&quot; error. So I went to Firefox, where the page didn&#39;t &quot;aw snap&quot;, but instead hung for a moment then asked if I wanted to stop the script.</p>

<p>What could that JavaScript be doing? Well, it&#39;s not that hard to understand <em>now</em>, but it didn&#39;t click the first couple of times I read it.</p>

<p>The script initializes a new JavaScript array, like this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">var variant_prices = new Array();
</code></pre></div>
<p>Fairly innocuous. We would&#39;ve also accepted <code>var variant_prices = [];</code>.</p>

<p>Next, it uses some ERB to go through all the inventory units for an order and then assigns each variant to the array, using the variant&#39;s id <em>as an index in the array</em>. If a variant has an <code>id</code> of say, 1, this is not a problem. Why? Because JavaScript is smart enough to know that it should create a two element with <code>variant_prices[0]</code> being undefined, and <code>variant_prices[1]</code> being whatever value is assigned.</p>

<p><em>However</em>, if the variant&#39;s <code>id</code> is something a little higher, like 1,013,589,413, then you start to run into problems. In that case, JavaScript would create a <strong>one billion, thirteen million, five hundred and eighty-nine thousand, four hundred and fourteen element</strong> array. All to store <em>one</em> value in, right at the end.</p>

<p>Obviously, this is not very efficient and would lead to some performance degredations. Smart browsers would detect this early on and show a vague warning screen and dumber browsers would ask politely if you&#39;d like to stop the script. Which script? Well, they won&#39;t tell you that. You have to play guessing games, like most of the time with the beautiful language that is JavaScript.</p>

<hr>

<p>The <em>now obvious</em> solution to this problem is to <em>not</em> use a JavaScript Array for creating what is obviously a key-value store. Instead, the variable should be initialised like this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">var variant_prices = {};
</code></pre></div>
<p>Then you would be assigning keys to the JS object, rather than values at specific indexes in an Array which could have a billion elements.</p>
]]></content>
 </entry>
 
 <entry>
   <title>On Hiring</title>
   <link href="http://ryanbigg.com/2012/05/on-hiring" />
   <updated>2012-05-25T00:00:00+10:00</updated>
   <id>http://ryanbigg.com/2012/05/on-hiring</id>
   <content type="html"><![CDATA[<p>My previous blog post got <em>very</em> different replies. On one hand they were like this:</p>

<blockquote class="twitter-tweet"><p>AWESOME! " Also, I’m 24. What makes you think I have any damn right being a Chief of any department?" - @<a href="https://twitter.com/ryanbigg">ryanbigg</a></p>&mdash; Federico Soria (@fedesoria) <a href="https://twitter.com/fedesoria/status/205785925924552704" data-datetime="2012-05-24T22:22:42+00:00">May 24, 2012</a></blockquote>

<blockquote class="twitter-tweet" data-in-reply-to="205784403081822208"><p>@<a href="https://twitter.com/ryanbigg">ryanbigg</a> that's just... Wow. Thanks for sharing.</p>&mdash; Robert Pitts (@rbxbx) <a href="https://twitter.com/rbxbx/status/205786385725128704" data-datetime="2012-05-24T22:24:32+00:00">May 24, 2012</a></blockquote>

<blockquote class="twitter-tweet" data-in-reply-to="205784403081822208"><p>@<a href="https://twitter.com/ryanbigg">ryanbigg</a> haha made my day. The hype for programming has ppl heads spinning <a href="https://twitter.com/search/%2523ittakestime">#ittakestime</a></p>&mdash; Marcell Purham (@Marcellpurham) <a href="https://twitter.com/Marcellpurham/status/205801753608859649" data-datetime="2012-05-24T23:25:36+00:00">May 24, 2012</a></blockquote>

<p>Others were humourous:</p>

<blockquote class="twitter-tweet"><p>“@<a href="https://twitter.com/ryanbigg">ryanbigg</a>: What happens when a scummy business guy tries to hire me: <a href="http://t.co/pkONeFg5" title="http://ryanbigg.com/2012/05/how-not-to-hire-me/">ryanbigg.com/2012/05/how-no…</a>” <a href="http://t.co/ICbuuTV5" title="http://Rubydramas.com">Rubydramas.com</a> about to be reset.</p>&mdash; Tom Meier (@pommytom) <a href="https://twitter.com/pommytom/status/205787384275677185" data-datetime="2012-05-24T22:28:30+00:00">May 24, 2012</a></blockquote>

<p>And others really hated it:</p>

<blockquote class="twitter-tweet"><p>You're neither clever or elite when you're rude to recruiters, you're just a dick.</p>&mdash; Ben Schwarz (@benschwarz) <a href="https://twitter.com/benschwarz/status/205793189557321728" data-datetime="2012-05-24T22:51:34+00:00">May 24, 2012</a></blockquote>

<blockquote class="twitter-tweet"><p>.@<a href="https://twitter.com/ryanbigg">ryanbigg</a> just so you know mate, you're a front for our community - a popular person. Don't be a douche - be like matz, be nice.</p>&mdash; Keith Pitt (@keithpitt) <a href="https://twitter.com/keithpitt/status/205809696022609920" data-datetime="2012-05-24T23:57:09+00:00">May 24, 2012</a></blockquote>

<blockquote class="twitter-tweet" data-in-reply-to="205810643742363648"><p>@<a href="https://twitter.com/ryanbigg">ryanbigg</a> "Do you have any idea who you’re writing to?" is the most douche baggy comment of all time. And you started with it…</p>&mdash; Keith Pitt (@keithpitt) <a href="https://twitter.com/keithpitt/status/205810805214679042" data-datetime="2012-05-25T00:01:34+00:00">May 25, 2012</a></blockquote>

<blockquote class="twitter-tweet" data-in-reply-to="205810905391439872"><p>@<a href="https://twitter.com/ryanbigg">ryanbigg</a> oh I'm sorry that you expect that. He should known. You're a fucking idiot mate. I'm thankful for the hard work you've done.</p>&mdash; Keith Pitt (@keithpitt) <a href="https://twitter.com/keithpitt/status/205811282069295106" data-datetime="2012-05-25T00:03:28+00:00">May 25, 2012</a></blockquote>

<blockquote class="twitter-tweet" data-in-reply-to="205808912564359168"><p>@<a href="https://twitter.com/ryanbigg">ryanbigg</a> You fuelled that conversation. Results would have been much different with a simple, polite "no thanks", or even by ignoring.</p>&mdash; Justin French (@justinfrench) <a href="https://twitter.com/justinfrench/status/205810661517828096" data-datetime="2012-05-25T00:01:00+00:00">May 25, 2012</a></blockquote>

<blockquote class="twitter-tweet" data-in-reply-to="205812014768066560"><p>@<a href="https://twitter.com/ryanbigg">ryanbigg</a> @<a href="https://twitter.com/keithpitt">keithpitt</a> Well, to be fair, it isn't hard to just politely reply "thanks but no thanks." We all get these emails...</p>&mdash; Fred Wu (@fredwu) <a href="https://twitter.com/fredwu/status/205812358285766656" data-datetime="2012-05-25T00:07:44+00:00">May 25, 2012</a></blockquote>

<p>Others suggested I just hit ignore:</p>

<blockquote class="twitter-tweet" data-in-reply-to="205811694541352962"><p>@<a href="https://twitter.com/ryanbigg">ryanbigg</a> Long term, your biggest regret will be wasting your life conversing with the fellow.Learn to just hit "Archive" and move on.</p>&mdash; Mike Perham (@mperham) <a href="https://twitter.com/mperham/status/205822000382480384" data-datetime="2012-05-25T00:46:03+00:00">May 25, 2012</a></blockquote>

<blockquote class="twitter-tweet" data-in-reply-to="205812014768066560"><p>@<a href="https://twitter.com/ryanbigg">ryanbigg</a> "No thanks."</p>&mdash; Justin French (@justinfrench) <a href="https://twitter.com/justinfrench/status/205812193105674240" data-datetime="2012-05-25T00:07:05+00:00">May 25, 2012</a></blockquote>

<p>Everyone&#39;s entitled to have their say about this, and I&#39;m sad that so many people took offense to something that I genuinely believe should have been done.</p>

<hr>

<p>To make it clear, I don&#39;t like being cold-called. I think it&#39;s invasive and generally a waste of everyone&#39;s time. In the case of hiring, for a business person
to cold-call a whole bunch of programmers shows that they don&#39;t care about who they hire. They just want somebody to fill their position. </p>

<p>I think that they <em>should</em> care. Why? Well, the business person is going to spend <em>months</em>, perhaps <em>years</em> of their life with this person. How do you know
that person is going to be the right fit for your job? What if that person is a complete douchebag who will post most of the conversation on his blog and
laugh about it?</p>

<p>All I ask is that people who are looking to hire other people do their research first. Find out what they <em>love</em> doing and appeal to that, if you can. Invite
them out for a lunch discussion or if that doesn&#39;t work, a post-work drink or two. Cold-calling just anybody is most likely not going to land you the right person for your job. Go to meetups, programming events and meet people. Don&#39;t meet them just for the sake of seeing if they&#39;re wanting to go work for your company, but meet them to understand what their type is like.</p>

<p>To not do the research first shows a blatant disregard of care for the person that you&#39;re contacting, and I honestly think that contacts made in this fashion
cannot work out. Find common interests, discuss them in polite ways and see if you&#39;re a fit. If you&#39;re not, move on. Do your research on the next person.</p>

<hr>

<p>I agree that I started the email thread wrong. As I said before, I felt invaded by this email. Sure, I could&#39;ve ignored it and sent it to the Archive/Trash,
but that&#39;s not my style. If I am sending an email to a person, I expect a reply. Not an instant one, of course. Perhaps it would take a week or longer. But
still, a reply is always nice.</p>

<p>Replying in the way that I did was most certainly wrong. Cold-calling someone without doing any level of research before is wrong also. We were both wrong. Replying to somebody validates that &quot;Yes, you are worth my time&quot;. That&#39;s the <em>essence</em> of why I reply to every single email that is personally addressed to me.</p>

<hr>

<p>I want to make it so that recruiting in programming <em>doesn&#39;t</em> suck as much as it does now. Companies just want bodies, and while that makes sense in a business
fashion, how do you know if the new hire will be a good fit for the team or not and secondly if the work is interesting to them. If the new hire doesn&#39;t fit
with the team, then there&#39;ll be conflicts and inevitably someone will have an ego bruised, or worse. If the person doesn&#39;t enjoy the work, then they&#39;re
probably not going to work as hard as they could. Both of these things are absolutely vital to making someone fit in at a company, in my opinion.</p>

<p>I know all too well how <em>fucking great</em> we have it in this industry. I can announce on Twitter that I&#39;m leaving my current job and <em>within the day</em> I have at
least 5 companies saying &quot;Come work for us, please&quot;. I know how well we have this because I&#39;ve seen what happens in other industries, in a second person
fashion.</p>

<p>Recently, both my mum and her husband were out of work, and were struggling to find jobs. They weren&#39;t able to put out on Twitter (or Facebook) that
they were looking for a job and get picked up by a spectactular company within the same day. They had to work <em>damn hard</em> to find new jobs, and they&#39;ve done
just that. Even <em>with</em> all their experience (they&#39;re in their 40s), it was still a struggle for them to find a job.</p>

<p>So yeah, I know how great we&#39;ve got it in this fantastic industry of ours.</p>

<hr>

<p>I&#39;ll practice not being an arrogant asshole, and I&#39;ll expect people who are in the business of hiring others to practice doing their research. Together, we can
make this thing work and keep building this great industry.</p>

<script src="http://platform.twitter.com/widgets.js"></script>
]]></content>
 </entry>
 
 <entry>
   <title>How not to hire me</title>
   <link href="http://ryanbigg.com/2012/05/how-not-to-hire-me" />
   <updated>2012-05-25T00:00:00+10:00</updated>
   <id>http://ryanbigg.com/2012/05/how-not-to-hire-me</id>
   <content type="html"><![CDATA[<p>On the 16th of May, I was contacted by a guy I&#39;ll call &quot;M&quot;. M emailed me a 300-word, no paragraph breaks email that went something like this:</p>

<blockquote>
<p>Hi, <em>blah blah blah</em> seed funding <em>blah</em> tech startup <em>blah blah blah</em> no programming experience <em>blah blah blah</em> advertising platform <em>blah blah</em> you will be CTO blah blah blah blah blah*. Thanks, M.</p>
</blockquote>

<p>I&#39;ve obviously taken the liberty here to modify his wording slightly, but you get what he was trying to say.</p>

<p>I was a little upset because he didn&#39;t do <a href="http://ryanbigg.com/about-me">his research</a>. So I emailed back in my best arrogant famous person impression:</p>

<blockquote>
<p>Do you have any idea who you&#39;re writing to?</p>
</blockquote>

<p>To which he replied:</p>

<blockquote>
<p>Yeah I think it was intended at you, that&#39;s why the email was addressed to your inbox...</p>
</blockquote>

<p>It was at this moment that my hand went to my face in a rather quick fashion. The next thing I can remember is only feeling half my face and laying on the
floor. I picked myself up off the floor and wrote a longer email:</p>

<blockquote>
<p>I am not &quot;open minded to the possibility of also becoming CTO later down the track&quot; because I already work at a company called Spree Commerce as the Community Manager. This email does not represent them, because it&#39;s my personal email. I wrote a book too, called Rails 3 in Action. I&#39;m actually writing the second edition now. Also, I&#39;m 24. What makes you think I have any damn right being a Chief of any department?</p>

<p>Do not think that you can simply pull people away from a company with buzzwords and hand-waving. In today&#39;s industry, you need to &quot;court&quot; people and make them want to work for you. Cold-calling them is at the exact opposite end of the &quot;What to do and what not to do&quot; scale.</p>
</blockquote>

<p>He then asks: </p>

<blockquote>
<p>In response to your statement &quot;In today&#39;s industry, you need to &quot;court&quot; people and make them wanting to work for you. Cold-calling them is at the exact opposite end of the &quot;What to do and what not to do&quot; scale&quot;. How can I go about courting people in a way that I can gain their trust and attention without looking like some other annoying business guy? However I must say your advice is flawed in some ways because either way I can&#39;t just wait for people to come to me, so there has to be some element of cold calling whether it&#39;s emailing or approaching them unannounced.. Unless you have better advice and I&#39;m all open to hearing it</p>
</blockquote>

<p>Regarding the &quot;annoying business guy&quot;, he&#39;s gone past this point at this stage.</p>

<p>I reply back suggesting things like user group meetings and Railscamps.</p>

<hr>

<p>Anyway, this kind of goes on for a couple of emails and Mr. M does his research eventually. He then goes into full-sleazy-business-dude mode:</p>

<blockquote>
<p>... but if you wanted to work with me full time I would give you a meaningful amount of equity (at the cofounder level) I would also make sure your rent, internet connectivity, beer and basic essentials would be covered;</p>
</blockquote>

<p>You cannot buy me out with equity, suggestions that you&#39;ll pay my rent, internet connectivity, beer (even though I don&#39;t drink beer) and basic essentials. So I
tell him that:</p>

<blockquote>
<p>No, absolutely not.</p>

<p>You would be dealing a great blow to Spree if you did that, and honestly your work doesn&#39;t interest me. I <em>hate</em> advertising, because most of it is pure crap. I&#39;m actually considering paying $6.99 each month for Spotify <em>not</em> because I want access to new music, but because I want to get rid of the ads.</p>

<p>Your equity offer would be paltry, no doubt. Do you have any idea what I earn at Spree? Do you have any idea what I charge <em>per hour</em> for consulting gigs outside of my daily work?</p>

<p>Yes, you say you would pay for rent, internet connectivity, beer (although I don&#39;t drink it) and basic essentials. That is, in combination with the equity, not even coming close to the emotional compensation I would need for selling my soul to an advertising platform.</p>
</blockquote>

<p>The last part about &quot;emotional compensation&quot; is a joke, by the way.</p>

<p>He also said this:</p>

<blockquote>
<p>In under just three months you would be able to figure out whether it would be worthy or not putting more of your time in this startup since from the launch date for the website to function we need direct money inflow.</p>
</blockquote>

<p>So no direct money inflow at the moment. This is a <em>huge</em> red flag to me. &quot;Yes, please work for a pittance but I <em>promise</em> we&#39;ll be making money hand over fist
any time now!&quot;. I&#39;m not a business guy, but I think this guy is a little crazy by this point.</p>

<p>Oh, he also said I could &quot;influence millions of people&quot;. I replied:</p>

<blockquote>
<p>I have made my decision. I am sticking with Spree and no amount of equity, technical challenges, narrowest possibility of influencing millions of people or
money will change that.</p>
</blockquote>

<p>Then the biggest email from this whole saga arrives in my inbox. It begins with:</p>

<blockquote>
<p>I&#39;ll try to make this quick so that I don&#39;t continue wasting my time as well as your time..</p>
</blockquote>

<p>It&#39;s nine-hundred-and-ninety-five words long. This many words is not <em>quick</em>. </p>

<p>I told him this in a previous email:</p>

<blockquote>
<p>You most likely will not change the world. Fact</p>
</blockquote>

<p>He replied with:</p>

<blockquote>
<p>The fact that you added &quot;most likely&quot; infront of will not change the world, expresses that there might be a slight possibility of it happening, which contradicts the &quot;fact&quot; part at the end. But to answer your statement, I will be very happy one day when things do work out and that everyday when you are browsing the net, you will be faced with a constant reminder of how pessimistic and truly wrong you were, as well as receive an email from me saying &quot;I told you so&quot;... Thank you for giving me another reason to be motivated..</p>
</blockquote>

<p>I honestly believe that he wouldn&#39;t change the world with an advertising platform, so I said so. I would rather be honest with people than to support their broken dreams. For him to reply in such a passive aggressive way threw up the biggest red flag of all of this so far.</p>

<p>Then he leads with this doozy:</p>

<blockquote>
<p>Plus I think I&#39;m starting to agree with Tyler Menezes, I do think that the Ruby on Rails community is run by a bunch of arrogant narrow thinking developers who are too important to show any optimism or support for outsiders..</p>
</blockquote>

<p>Up to this point, I have been as nice as I can be to somebody who cold calls me. Which is actually <em>really</em> nice. I was being painfully honest with this guy,
and he took it as arrogance. Oh well.</p>

<p>Then he drops this other bombshell:</p>

<blockquote>
<p>Therefore I&#39;m choosing python, I&#39;ve already started to learn the basics, I think it has so much more potential in terms of quality and scaling capabilities than ror.. Plus i&#39;m finding it a lot more fun to learn (but it&#39;s still very challenging and definitely not easy, but who cares, within six months I&#39;ll be good enough to lead a team of developers, even by learning part time). </p>
</blockquote>

<p><em>HOLY SHIT</em>. This guy is going to learn Python in 6 months and then lead a team. If I were a self-respecting programmer (hint: I am) I don&#39;t want to be in a
team that&#39;s led by someone who&#39;s got only 6 months experience in my programming language. And by only learning part-time? Please.</p>

<p>He also claimed that I drink beer:</p>

<blockquote>
<p>You don&#39;t drink beer, oh ok well I didn&#39;t know that you just said false things for the fun of it, why would you make multiple references to drinking beer at railscamp if you don&#39;t drink any beer? Or do you just put out a different appearance in public then you do in private? </p>
</blockquote>

<p>Not once in our email correspondence did I ever mention drinking beer. He later brought up and said that in my RubyC talk at around 14:53 I mentioned drinking
beer, but this is not true. This whole passive aggressive tone of the email was extremely off-putting, and exactly the opposite direction of how you would go
about hiring someone.</p>

<p>He finishes off his version of the Iliad with this:</p>

<blockquote>
<p>Ps. this isn&#39;t over, within a year you can expect an email form me saying &quot;I told you so&quot;.... </p>
</blockquote>

<p>I&#39;ve actually put a reminder in my calendar for next year to remind me to go back in my inbox and find his email and ask him how it&#39;s going. I&#39;ll be genuinely
curious to see how far he&#39;s gotten with this idea.</p>

<p>I was extremely offended by his bravado and passive aggressive tone. I replied over two emails. The first was:</p>

<blockquote>
<p>I am bored of this game.
Never email me again.</p>
</blockquote>

<p>The second:</p>

<blockquote>
<p>Also, I never mentioned anything about drinking beer.
Just thought I&#39;d clear that up.</p>
</blockquote>

<p>He replies with a single line:</p>

<blockquote>
<p>I&#39;m pretty sure you did</p>
</blockquote>

<p>I am still extremely frustated at this:</p>

<blockquote>
<p>And now you&#39;ve just devolved to basic trolling. Fucking long sigh.
Seriously dude, look through the emails. Not once did I mention drinking beer.</p>
</blockquote>

<p>He replies back:</p>

<blockquote>
<p>I don&#39;t know why you&#39;re only focusing on this one beer drinking thing, that was the least important comment throughout my email...
I&#39;m not saying you mentioned beer drinking in our emails, you mentioned beer drinking during your how to be awesome at rails presentation [at RubyC]...</p>

<p>I was never trolling, I reached out to you for help and advice and the entire time your responses have been filled with criticism, dream crushing statements, profanity and just fucking plain hypocrisy. </p>
</blockquote>

<p>Not filled with criticism at all, besides the mentions that I would prefer if he used paragraph breaks and didn&#39;t cold call people. I suggested alternatives,
like Railscamps and user groups. You know, actual actionable, effective advice. My statements weren&#39;t intended at all to be &quot;dream crushing&quot;, just my
traditional honesty. The only time I used profanity was the word &quot;Fucking&quot; in my email before. I was also never a hypocrite in my emails.</p>

<p>And then a little later on he replies for the final time:</p>

<blockquote>
<p>Nah but I seriously wish you all the best,
Hopefully there aren&#39;t any lingering hard feelings.
That is that last thing I would have hoped for...</p>
</blockquote>

<p>I wish no ill feelings on this guy. The tone of his emails was exceptionally off-putting and I can&#39;t believe that people think that they can get away with
things like this. A little bit of courtesy on <em>both</em> sides of these types of discussions goes an exceptionally long way.</p>
]]></content>
 </entry>
 
 <entry>
   <title>Engines talk</title>
   <link href="http://ryanbigg.com/2012/05/engines-talk" />
   <updated>2012-05-19T00:00:00+10:00</updated>
   <id>http://ryanbigg.com/2012/05/engines-talk</id>
   <content type="html"><![CDATA[<p>I gave a presentation at SpreeConf and Ruby on Ales about engines.</p>

<p>I recorded it again at home last week and You can <a href="https://s3.amazonaws.com/ryanbigg_screencasts/004-engines_talk.mov">watch/download the video here</a>. It&#39;s a
little over 30 minutes long, but I think it teaches you valuable lessons about engines in Rails.</p>
]]></content>
 </entry>
 
 <entry>
   <title>Caffeine and Sleep</title>
   <link href="http://ryanbigg.com/2012/04/caffeine-and-sleep" />
   <updated>2012-04-27T00:00:00+10:00</updated>
   <id>http://ryanbigg.com/2012/04/caffeine-and-sleep</id>
   <content type="html"><![CDATA[<p>I used to drink a lot of Coca Cola. I think my record was 18 375ml cans of it during a LAN party once. I didn&#39;t feel so good the morning after. I used to not
brush my teeth that often as well (compared with now, which is morning &amp; night as all good dentists recommend), and as a result I have very &quot;holey&quot; teeth and even had one extracted in February. I used to drink Coca Cola because it contained caffeine which would give me a pleasant buzz.</p>

<p>Then my dentist suggested that I stop drinking drinks containing that much sugar, and so I did. I switched to Pepsi Max for a couple of years after that. Then,
one day, I stopped. I can&#39;t remember the exact reason <em>why</em> I stopped drinking it, but I did. This was back in 2009.</p>

<p>The first couple of days were interesting. I had trouble focussing for long periods of time. I never got the caffeine headaches that people talk about. But
then it got gradually better and I&#39;ve been basically caffeine-free for close to 3 years now. Then it <em>kept getting better</em>. I found myself sleeping more
solidly each night and being able to concentrate for longer and longer periods. I very rarely now have moments where I feel completely exhausted. When they do
happen, having a some sugar helps for that last little bit.</p>

<p>Then there was the change in sleeping pattern in 2010, when I started writing Rails 3 in Action. I swithced from getting up at 7:45am to getting up at 6:00am.
And I did this every day, except where I stayed out late the night before. That extra time in the morning allowed me to do some internet catch up, do some
writing, have a shower and get ready for the day and then still have more time to do even more writing. After a late night out, there&#39;s that buffer there that
I can use to catch up on sleep that I&#39;ve otherwise missed. I can also use this time for exercise, which is awesome.</p>

<p>When I get to work it&#39;s no longer just over an hour since I woke up. It&#39;s more like three hours. With me not being a morning person by nature, this is
wonderful. I come in to work and I&#39;ve already woken up fully and I can just get to doing everything.</p>

<p>Tim Riley <a href="http://icelab.com.au/articles/the-benefits-of-waking-up-early/">wrote about his experiences with getting up earlier too</a>. </p>

<blockquote>
<p>However, I&#39;ve found this new approach to be very effective. The early mornings are a good time. It is quiet. The day has just begun and my mind is clear of any distractions, so it is easy to concentrate. Because the time for work has a definite ending, it also encourages me to pick discrete and achievable goals for each morning. Rinse and repeat, and before long, I have demonstrable, consistent, incremental progress towards my goal.</p>
</blockquote>

<p><strong>So, my thing I want you to try is to go the whole month of May by changing one of these two habits. Either cut out caffeine completely from your diet, or start
getting up early in the morning. If you want the &quot;Hard Mode&quot; variety, try both. It&#39;s really improved my life and I reckon it&#39;ll do the same to yours.</strong></p>
]]></content>
 </entry>
 
 <entry>
   <title>Integration testing engines</title>
   <link href="http://ryanbigg.com/2012/04/integration-testing-engines" />
   <updated>2012-04-26T00:00:00+10:00</updated>
   <id>http://ryanbigg.com/2012/04/integration-testing-engines</id>
   <content type="html"><![CDATA[<p>I gave a lightning talk at Railsconf in response to a talk done by Andy Maleh about engines. His talk contained some content that I strongly disagreed with, and so I felt it necessary to set the record straight. You can see the <a href="http://speakerdeck.com/u/radar/p/integration-testing-engines">slides for it here</a>. I will have a more thorough dissection of the talk once the video is online.</p>

<p>To be perfectly honest, I am probably bitter because I <em>was</em> going to submit a talk about engines and then decided to submit another talk instead which
ultimately didn&#39;t get accepted. Nevertheless...</p>

<h3>Drawing routes</h3>

<p>The first thing that I <a href="https://twitter.com/ryanbigg/status/194501115524554754">can recall disagreeing</a> with is Andy&#39;s suggestion to draw routes for the engine on the <code>Rails.application.routes</code> object, by putting
this code inside the <code>config/routes.rb</code> file of the engine:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">Rails.application.routes.draw do
  resources :people
end
</code></pre></div>
<p>The problem with this is that if the application&#39;s routes file has a catch-all route at the bottom, the route for the engine won&#39;t get matched because it is
drawn after the application. </p>

<p>This leads to additional complexity as well, as by drawing these routes on the application like this, they would also correspond to a controller that&#39;s at the
top-level of the namespace, i.e. <code>PeopleController</code>. This can lead to confusion as to where the controller is located. How can someone know if <code>PeopleController</code> is inside the engine or is inside the application? Furthermore, the more engines that get added to this application, the more confusing such a thing would get.</p>

<p>By namespacing the routes <em>properly</em> (as we do in <a href="https://spreecommerce.com">Spree</a> and <a href="http://github.com/radar/forem">Forem</a>) , like this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">Spree::Core::Engine.routes.draw do
  resources :products
end
</code></pre></div>
<p>And by using <code>isolate_namespace</code> inside your engine, the routes will be a completely separate entity for each engine, rather than one big &quot;ball o&#39; mud&quot;. In
Spree this namespace isolation is to the <code>Spree</code> module (i.e. <code>isolate_namespace Spree</code>), so that the controllers will be <code>Spree::ProductsController</code> and not
<code>Spree::Core::ProductsController</code> and the like.</p>

<p>By using a completely isolated namespace like this, your controller would end up being correctly namespaced and then there&#39;s no confusion as to which engine
the controller is located within. You can then mount your engine at whatever path you want inside your application by explicitly defining the mount point
inside <code>config/application.rb</code> like this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">mount Spree::Core::Engine, :at =&gt; &quot;/&quot;
</code></pre></div>
<p>By mounting it at root, it will seem as if the engine were a part of the application itself. If you wanted to change where the engine was mounted, it&#39;s a
simple matter of changing the <code>:at</code>: option and you can carry on like normal.</p>

<p>There&#39;s a whole bunch of other stuff that <code>isolate_namespace</code> does as well, like namespacing of models and tables. It&#39;s absolutely important that you namespace
your engine to avoid confusion.</p>

<p>Oh, and one more thing: by doing this namespacing, if you want to get to an engine route from inside the application, you&#39;ll need to call the engine&#39;s routing
proxy method, like this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">spree.products_path
</code></pre></div>
<p>If you attempted to do <code>products_path</code> it would go to the application&#39;s <code>products_path</code>, which may be undefined.</p>

<p>Similarly, to get to the application&#39;s routes from inside the engine, use <code>main_app</code>:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">main_app.people_path
</code></pre></div>
<h3>Switching back and forth</h3>

<p>The second thing that I disagreed with during Andy&#39;s talk was that he said that when developing an engine you needed to constantly switch back and forth
between the application and the engine. This is simply not true. If you are developing your engine correctly, the development of it can be done in complete
isolation from a real application and instead depend on a dummy application. It should not be a requirement for you to have two separate projects coupled
together like this so you can test one or the other.</p>

<p>How we do it in Forem is that we have a dummy application inside <code>spec/dummy</code> which is generated by running <code>bundle exec rake forem:dummy_app</code>. This
command <a href="https://github.com/radar/forem/blob/master/spec/lib/generators/forem/dummy/dummy_generator.rb">creates a new dummy application</a> with things like
<code>User</code> model already set up inside it. Inside Spree, there&#39;s a similar command called <code>bundle exec rake test_app</code> which <a href="https://github.com/spree/spree/blob/master/core/lib/generators/spree/dummy/dummy_generator.rb">does basically the same thing</a>.</p>

<p>With the dummy application inside the engine, the engine is mounted onto that application and the tests are then run against that application. No need to
switch back and forth from application to engine.</p>

<p>If you have modifications for the engine inside your application, there&#39;s also a way to test that. With Spree, we provide a module called
<code>Spree::Core::UrlHelpers</code> that you can include into your <code>RSpec.configure</code> block like this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">require &#39;spree/core/url_helpers&#39;
RSpec.configure do |c|
  c.include Spree::Core::UrlHelpers, :type =&gt; :integration
end
</code></pre></div>
<p>Then in your integration tests it&#39;s simply a matter of referencing the Spree routes like this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">visit spree.products_path
</code></pre></div>
<p>Now for when you want to test that a customization to a Spree controller is behaving as intended, we&#39;ve got a module for that too. It&#39;s called
<code>Spree::Core::TestingSupport::ControllerRequests</code> and you can include it like this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">require &#39;spree/core/testing_support/controller_requests&#39;
RSpec.configure do |c|
  c.include Spree::Core::TestingSupport::ControllerRequests, :type =&gt; :controller
end
</code></pre></div>
<p>Then you can write your controller specs like this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">describe Spree::ProductsController do
  it &quot;can see all the products&quot; do
    spree_get :index
  end
end
</code></pre></div>
<p>This will then allow you to make requests to the Spree engine from inside your application&#39;s tests.</p>

<h3>Conclusion</h3>

<p>There&#39;s absolutely no reason to mount engine routes directly on <code>Rails.application.routes</code>, nor is there a requirement to switch back and forth. Integration
testing an engine is extremely easy once you know how to do it.</p>
]]></content>
 </entry>
 
 <entry>
   <title>Polymorphic Routes</title>
   <link href="http://ryanbigg.com/2012/03/polymorphic-routes" />
   <updated>2012-03-27T00:00:00+11:00</updated>
   <id>http://ryanbigg.com/2012/03/polymorphic-routes</id>
   <content type="html"><![CDATA[<p>Really early on in Rails, you would write routes like this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">redirect_to :controller =&gt; &quot;posts&quot;, :action =&gt; &quot;show&quot;, :id =&gt; @post.id
</code></pre></div>
<p>What this would do is dutifully redirect to the <code>show</code> action inside the <code>PostsController</code> and pass along the <code>id</code> parameter with a
value of whatever <code>@post.id</code> returns. Typical 302 response.</p>

<p>Then Rails 1.2 came along and allowed you to use routing helpers, like this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">redirect_to post_path(@post)
</code></pre></div>
<p>And the people rejoiced.</p>

<p>This would do effectively the same thing. <code>post_path</code> here would build a route using the <code>@post</code> object that would look something
like <code>/posts/1</code> and then <code>redirect_to</code> would send back a 302 response to that route and the browser would follow it.</p>

<p>Then later versions (I can&#39;t remember which one), allowed syntax like this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">redirect_to @post
</code></pre></div>
<p>And the people rejoiced a second time.</p>

<h3>Magic, but not really</h3>

<blockquote>
<p>Any sufficiently advanced technology is indistinguishable from magic.</p>
</blockquote>

<p>While this seems like magic, it&#39;s not. What this is doing is actually very, very neat. The <code>redirect_to</code> method, much like its cousins <code>link_to</code> and <code>form_for</code> all use a common method to build URLs, called <code>url_for</code>. The <code>url_for</code> method takes many different
varieties of objects, such as strings, hashes or even instances of models, like in the example above.</p>

<p>What it does with these objects then, is quite neat. In the case of the <code>redirect_to @post</code> call above, it inspects the <code>@post</code>
object, sees that it is an object of the <code>Post</code> class (we assume, anyway) and checks to see if that object has been persisted in a
database somewhere by calling <code>persisted?</code> on it. </p>

<p>By &quot;persisted&quot;, I mean that a Ruby object has a matching record in the database somewhere. The <code>persisted?</code> method in Active Record is implemented like this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">def persisted?
  !(new_record? || destroyed?)
end
</code></pre></div>
<p>If the object wasn&#39;t created through a call such as <code>Model.new</code> then it won&#39;t be a new record, and if it hasn&#39;t had the <code>destroy</code> method called on it won&#39;t be
destroyed either. If both of these cases are true, then that makes the object has most likely been <em>persisted</em> to the database in the form of a record.</p>

<p>If it has been persisted, then <code>url_for</code> knows that this object can be found
somewhere, and that the place it can be found is most likely under a method called <code>post_path</code>. So it calls this method, and passes
in the <code>to_param</code> value of this object which is usually the <code>id</code>.</p>

<p>In short, it&#39;s effectively doing this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">#{@post.class.downcase}_path(@post.to_param)
</code></pre></div>
<p>Which comes out to being this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">post_path(1)
</code></pre></div>
<p>And when that method is called you would get this little string:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">&quot;/posts/1&quot;
</code></pre></div>
<p>Lovely!</p>

<p>This is called <em>polymorphic routing</em>. You can pass an object to methods like <code>redirect_to</code>, <code>link_to</code> and <code>form_for</code> and it will
attempt to work out the correct URL of what to use.</p>

<h3>The form of form_for</h3>

<p>Now, when you&#39;re coding Rails you may have used <code>form_for</code> like this a very long time ago:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">&lt;% form_for @post, :url =&gt; { :controller =&gt; &quot;posts&quot;, :action =&gt; &quot;create&quot; } do |f| %&gt;
</code></pre></div>
<p>Of course, with advancements in Rails you could simplify it to this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">&lt;% form_for @post, :url =&gt; posts_path do |f| %&gt;
</code></pre></div>
<p>Because the form is going to default to having a <code>POST</code> HTTP method and therefore a request to <code>posts_path</code> is going to go to the
<code>create</code> action of <code>PostsController</code>, rather than the <code>index</code> action, which is what would result if it were a <code>GET</code> request.</p>

<p>But why stop there? Why not just write this?</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">&lt;%= form_for @post do |f| %&gt;
</code></pre></div>
<p>Personally, I see no reason not to... if it&#39;s something as simple as this. The <code>form_for</code> method uses <code>url_for</code> underneath, just like
<code>redirect_to</code> to work out where the form should go. It knows that the <code>@post</code> object is of the <code>Post</code> class (again, we assume) and it
checks to see if the object is persisted. If it is, then it will use <code>post_path(@post)</code>. If it&#39;s not, then <code>posts_path</code>. </p>

<p>The <code>form_for</code> method itself checks to see if the object passed in is persisted also, and if it is then it&#39;ll default to a <code>PUT</code> HTTP
method, otherwise a <code>POST</code>.</p>

<p>So this is how <code>form_for</code> can be flexible enough to have an identical syntax on both a <code>new</code> and <code>edit</code> view. It&#39;s becoming more and
more common these days for people to even put their whole <code>form_for</code> tags into a single partial and include it in both the <code>new</code> and
<code>edit</code> pages.</p>

<h3>A more complex form</h3>

<p>So <code>form_for</code> is fairly simple for when you pass a normal object, but what happens if you pass an array of objects? Like this, for
instance:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">&lt;%= form_for [@post, @comment] do |f| %&gt;
</code></pre></div>
<p>Well, both <code>url_for</code> and <code>form_for</code> have you covered there too.</p>

<p>The <code>url_for</code> method detects that this is an array and separates out each part and inspects them individually. First, what is this
<code>@post</code> thing? Well, in this case let&#39;s assume it&#39;s a <code>Post</code> instance that <em>is</em> persisted and has the id of 1. Second, what is this
<code>@comment</code> object? It&#39;s a <code>Comment</code> instance that has not yet been persisted to the database.</p>

<p>What <code>url_for</code> will do here is build up the URL helper method piece by piece by placing each part in an array, joining it into a routing method and then calling that routing method with the necessary arguments.</p>

<p>First, it knows that the <code>@post</code> object is of the <code>Post</code> class and is persisted, therefore the URL helper will begin with <code>post</code>. Second, it knows that the <code>@comment</code> object is of the <code>Comment</code> class and is <em>not</em> persisted, and therefore <code>comments</code> will follow <code>post</code> in the URL helper build. The parts that <code>url_for</code> now knows about are <code>[:post, :comments]</code>.</p>

<p>The <code>url_for</code> method combines these individual parts with an underscore, so that it becomes <code>post_comments</code> and then appends <code>_path</code>
to the end of that, resulting in <code>post_comments_path</code>. Then it passes in just the persisted objects to the call to that method, resulting in a call like this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">post_comments_path(@post)
</code></pre></div>
<p>Calling that method results in this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">&quot;/posts/1/comments&quot;
</code></pre></div>
<p>Best part? <code>form_for</code> will still know to use <code>POST</code> if the <code>@comment</code> object is not a persisted object, and <code>PUT</code> if it is. A good
thing to remember is that the <code>form_for</code> is always for the <em>last</em> object specified in the array. The objects prior to it are just its
nesting, nothing more.</p>

<p>The more objects that are added, the more times <code>url_for</code> will do the hard yards and build the path out... although I recommend that
you keep it to just two parts.</p>

<h3>A symbolic form</h3>

<p>Now that we&#39;ve covered using an array containing objects for <code>form_for</code>, let&#39;s take a look at another common use. An array containing
at least one Symbol object, like this:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">&lt;%= form_for [:admin, @post, @comment] do |f| %&gt;
</code></pre></div>
<p>What the <code>url_for</code> method does here is very simple. It sees that there&#39;s a <code>Symbol</code> and takes it as it is. The first part of the
<code>url</code> will simply be the same as the symbol: <code>admin</code>. The URL that <code>url_for</code> knows of at this point is just <code>[:admin]</code>.</p>

<p>Then <code>url_for</code> goes through the remaining parts of the array. In this case, let&#39;s assume both <code>@post</code> and <code>@comment</code> are persisted
and that they have the ids of 1 and 2 respectively. Same classes as before. <code>url_for</code> then adds <code>post</code> to the URL that it&#39;s building,
and <code>comment</code> too, resulting in <code>[:admin, :post, :comment]</code>.</p>

<p>Then the joining happens, resulting in a method of <code>admin_post_comment_path</code>, and because both <code>@post</code> and <code>@comment</code> are persisted here,
they&#39;re passed in, resulting in this method call:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">admin_post_comment_path(@post, @comment)
</code></pre></div>
<p>Which (usually) turns into this path:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">/admin/posts/1/comments/2
</code></pre></div>
<h3>Conclusion</h3>

<p>You can use the array form of polymorphic routing with the <code>redirect_to</code>, <code>link_to</code> and <code>form_for</code> methods. There&#39;s probably other
methods that I&#39;m not remembering right now that can do it too... it&#39;s generally anything in Rails that would normally take a URL.</p>

<p>There&#39;s no need to build your URLs in any Rails version greater-than 2 using hashes; that&#39;s pretty old school.</p>

<p>Instead, experiment with your new knowledge of polymorphic routing and use it to the best of your advantage.</p>
]]></content>
 </entry>
 
 <entry>
   <title>Please learn Rails</title>
   <link href="http://ryanbigg.com/2012/03/please-learn-rails" />
   <updated>2012-03-17T00:00:00+11:00</updated>
   <id>http://ryanbigg.com/2012/03/please-learn-rails</id>
   <content type="html"><![CDATA[<p><em>Tyler Menezes wrote a blog post called <a href="https://tyler.menez.es/articles/i-will-not-learn-rails.html">&quot;I will not learn Rails&quot;</a> which
appeared on my Twitter timeline. After reading it, I felt like I needed to reply to it in long form. Here it is.</em></p>

<p>Hi Tyler,</p>

<p>I&#39;ve been doing Rails since I was your age. I&#39;m now 24. You do the math. Not once have I ever considered quitting it due to anything outlined in your blog post.</p>

<p>Your blog post <a href="https://twitter.com/mikeg1/status/181079537864556544">appeared on my Twitter timeline from MikeG1</a> who is known for his extreme grasp of .Net, Ruby (and Rails) and sarcasm. I couldn&#39;t exactly tell if his post was intended as sarcasm, but a <a href="https://twitter.com/mikeg1/status/181085508280139776">follow up tweet</a> clarified that for me. I have massive respect for Mike for reasons that I won&#39;t go into here. </p>

<p>Still, I feel like I <em>need</em> to reply to your blog post. It contains things that I disagree with on a personal level and I would much rather address these this way than posting it as a comment on your article.</p>

<p>So, here we go. Comments are inline.</p>

<hr>

<p><strong>tl;dr: Assholes are everywhere. Ignore them. They feed on your attention.</strong></p>

<p>You start with this explosive line:</p>

<blockquote>
<p>I will not learn Rails: I don&#39;t want to be associated with a community who call themselves &quot;rockstar developers&quot;.</p>
</blockquote>

<p>Within the Rails community, I find that the people who call themselves &quot;rockstar developers&quot;, aren&#39;t. These people pretend to be much better than what they are. The true fact about this is that no matter what programming community you associate yourself with <strong>will have these people</strong>.</p>

<p>The developers that I admire and respect do not call themselves &quot;rockstar developers&quot;. They are humble, courteous and all around good people to be around. It&#39;s my <em>very, very</em> strong opinion that you will not find a community more open and welcome than the Ruby and Rails communities that <em>isn&#39;t</em> a religious organisation. It&#39;s seriously that level of zealotry and passion about making the community a better place that keeps me within the Ruby community.</p>

<p>&quot;Matz is nice so we are nice&quot; is an expression you&#39;ll probably hear a lot, if you stick around.</p>

<blockquote>
<p>Yet at every event, there&#39;s someone who apparently believes the information is wholly inaccurate, or perhaps that sitting through a presentation without challenging everything is the mark of a weak man. There&#39;s nothing wrong with questioning things, but when your questions are disruptive to the point of forcing the presenter to skip sections of their talk for time, you&#39;re an asshole. If I&#39;m going to an event, I&#39;m going for a reason: the event. Not you.</p>
</blockquote>

<p>Again, these people are everywhere. I can&#39;t speak for your own events, but the events I go to such as local Ruby groups back in Australia and conferences all over the world, I have probably encountered somebody like this twice. That&#39;s over my <em>entire</em> Ruby community experience. These people are usually &quot;dealt with&quot;, by members of the community talking with them, or in a more explosive manner, such as a huge Internet-wide backlash that sometimes comes up.</p>

<p>Point is: you will see these people everywhere too. Ignore them. They mean very, very little.</p>

<blockquote>
<p>Zed Shaw wrote an extremely controversial blog post, “Rails is a Ghetto,” in 2009 in which he pointed out the tendancy of the rails community to behave like a fifth grade classroom after he closed commits to his project because people behaved like a fifth grade classroom:</p>
</blockquote>

<p>A small correction here: Zed wrote this post on 31st December, 2007. Not in 2009. This makes this blog post a little over four years old. The people that are mentioned in that blog post, such as Kevin Clark, are not involved with the community any more. They&#39;ve moved on to other things. Also, the Rails community has evolved dramatically over those four years. My personal aim for the Rails community is to make it <em>nothing</em> like the PHP or C communities, where you&#39;re told to &quot;RTFM&quot; whenever you ask a question. You&#39;ll probably get that kind of thing occasionally in the Ruby community, but 99% of the time you&#39;ll get linked to the perfect spot in the documentation. Then, if you <em>still don&#39;t understand</em>, people will take the time and help you to understand. All for free.</p>

<blockquote>
<p>Yet personally twice I&#39;ve seen these &quot;rockstars&quot; completely killing the passion in young developers. It&#39;s &quot;tough love&quot;, they may argue.</p>
</blockquote>

<p>I used to get insulted when peoeple would simplify what I did. It&#39;s generally these young developers that do that kind of thing. They would say &quot;Oh, you just sit there and write code all day. All I need to do is learn everything there is know about Ruby and Rails and I can write code just like you&quot;. Well, actually, you can&#39;t do that. Ruby and Rails are too big to keep all in one brain at one time, and so that first point is improbable, and secondly: there&#39;s so much more to writing code than just putting characters on a screen.</p>

<p>These rockstars that you&#39;re talking about probably don&#39;t acknowledge that those young developers are exactly as they were X years ago. These young developers may have such a passion for wanting to learn a language, that they don&#39;t realise that the more senior developer just can&#39;t &quot;get it&quot; that the younger guy doesn&#39;t just <em>understand</em>. </p>

<p>I used to hate on people who just wouldn&#39;t go out and learn. Now, I&#39;m more patient. I recognise that they are just trying to learn and that if I spend some time teaching them, showing them whatever it is they want to know, they&#39;ll be so much more appreciative and passionate of both the language and my help that they&#39;ll probably stick around longer. If I dismiss them, then what is there perogative to stick around? There just isn&#39;t one. They would be crazy to do so.</p>

<blockquote>
<p>From presentations full of porn and jokes at the expense of women ...</p>
</blockquote>

<p>I remember this incident well. The enormous backlash <em>against</em> Matt Aimonetti was of a scale that I had never seen before. I have never seen that many people from the Ruby community be so united against any particular thing that one individual has done. This incident was the reason that Mike Gunderloy stopped contributing as much as he used to the Ruby community. </p>

<p>Since this incident, the Ruby community abhorrs any kind of sexism. Yesterday, at Mountain West Ruby Conference, a person gave a talk on &quot;Pinterest for Bros&quot;. Afterwards, some standout members of the community such as Josh Susser messaged him on Twitter and told him off. I haven&#39;t seen his replies, but I don&#39;t think he meant it as much as Matt did.</p>

<blockquote>
<p>... DongML ...</p>
</blockquote>

<p>Again, sometimes you&#39;ll encounter assholes. This is one of them. Ignore, move on. They will be dealt with by the community at-large.</p>

<blockquote>
<p>... to refusing to acknowledge design flaw [semi-colons in URLs] ...</p>
</blockquote>

<p>This one was a mistake from <em>2007</em>. It was a silly thing to do and written by a developer who was eventually corrected. There&#39;s so many examples of this happening in Rails: a developer does something stupid, the community corrects it. It ends up being net positive.</p>

<blockquote>
<p>... design flaw [mass-assignment] </p>
</blockquote>

<p>This is a tricky problem to solve. Rails champions convention over configuration and so having all attributes blacklisted by default means that there would need to be some configuration to whitelist specific attributes. There are other problems which are covered elsewhere. I won&#39;t go into detail here other than to say it&#39;s a problem that&#39;s being addressed by the smartest minds in the community right now.</p>

<blockquote>
<p>... then freaking out when they turn out to be bad choices. [Egor Homakov&#39;s post]</p>
</blockquote>

<p>Mr. Homakov is not representative of the Rails community at all. He is, to me, an outsider who spends his time trying to show that he&#39;s an &quot;uber l33t hacker&quot; by breaking GitHub or any other Rails site.</p>

<blockquote>
<p>The rails group curated the atmosphere of immaturity.</p>
</blockquote>

<p>While it is true that we take ourselves much less seriously than other communities (see: C# developers, the end of Aaron Patterson&#39;s talk at Railsconf in 2011, etc.), I wouldn&#39;t go as far as to claim that we&#39;re immature. Rails has been around for 8 years now and is growing more and more mature by the day. Yes, there is some outliers in the community who are immature, but as I keep saying: they are not representative of the masses AND you will find them elsewhere as well.</p>

<blockquote>
<p>Rails isn&#39;t actually good.</p>
</blockquote>

<p>This is where I went &quot;OH NO HE JUST DINNIT&quot;. Then I chilled out some.</p>

<p>I think Rails is <em>excellent</em>. Of course I&#39;m a little biased, having done it for 6 years, <a href="http://manning.com/katz">written a book</a> about it and <a href="http://contributors.rubyonrails.org">contributed heavily to its documentation</a>.</p>

<p>The framework is exactly what I personally want in a web framework.</p>

<p>Anyway, to address your points that follow:</p>

<blockquote>
<p>A successful framework which runs on Ruby, a language which they didn&#39;t develop.</p>
</blockquote>

<p>I don&#39;t see how this is a problem. There are many other languages and frameworks that are built on top of other things. Like Django, for instance.</p>

<blockquote>
<p>That, in turn, is usually run on a server running a flavor of Linux, which they didn&#39;t develop</p>
</blockquote>

<p>Again, not sure why this is such a big deal. Rails is designed to be cross-platform and so should work on many different operating systems. Whatever system Ruby works on, there&#39;s a very, very high chance that Rails will work there also.</p>

<blockquote>
<p>What Rails actually did was create some classes which simplified repetitive code. They designed something, wrote some pretty simple code, and became more arrogant than the people who did the bulk of the work.</p>
</blockquote>

<p>To be honest, I actually find this a little offensive; almost like you&#39;re trying to start a flamewar. I&#39;ll ignore that and address the points.</p>

<p>Rails is not simple by any means. To understand exactly how Rails works you need to understand quite a lot of things. The code that has been written for Rails is &quot;simple&quot; once you understand it, but that isn&#39;t to say that all parts of Rails are trivial to the uninitiated. For example, explain to me the function of <code>ActiveSupport::Dependencies</code> succinctly. That shit is messed up.</p>

<p>Certain members of the core team are indeed highly arrogant. This mostly comes from them also being highly opinionated. Most of the time, this is not a problem as they are usually right about things. You learn to deal with their arrogance, stroke their ego some and work together on making the world a better place. Yet again, Rails core is not indicative of the community as a whole. No particular group is, really.</p>

<blockquote>
<p>And it doesn&#39;t even run well! The framework+server takes on the order of a gigabyte of RAM</p>
</blockquote>

<p>I would like to disagree here. While a Rails application may use that much RAM, RAM is cheap. Developer time is not. Rails is not designed to operate on a small cluster of RAM, but <em>is</em> designed for developer productivity and happiness. At the end of the day, what&#39;s more important? A small memory footprint or a framework that justs gets out of your way and lets you <em>develop</em>?</p>

<blockquote>
<p>Early rails applications needed to be restarted tens of times a day. </p>
</blockquote>

<p>You are addressing an ancient problem here, almost near the beginning of my Rails career. This was due (to my knowledge) to particular problems within how Rails was configured on a server and has been addressed in more than one way since then. This is most definitely not a problem these days, and is therefore a moot point.</p>

<blockquote>
<p>They ignored the vast number of users who were on shared hosts, requiring very specific configurations which a majority of their target markey do not need. </p>
</blockquote>

<p>Time and time again it is proven that users on shared hosting suffer, I&#39;ll admit. Just the other day somebody couldn&#39;t install a gem onto their Dreamhost server because Dreamhost was still using a 1.3 version of RubyGems. In this case (and many others), it&#39;s generally a configuration issue with the shared hosting provider that causes the problem (such as not staying up-to-date with software releases), not anything in particular to do with Ruby or Rails.</p>

<p>If you can find a case where I&#39;m wrong about this, I would absolutely like to hear about it.</p>

<blockquote>
<p>But the core team are hardly the gods of programming they often purport to be.</p>
</blockquote>

<p>The core team are not gods at all. They are simple human beings just like you and me. The purporting going on is mostly just posturing.</p>

<blockquote>
<p>Rails isn&#39;t even special. The idea of simplifying development has been around for ages ...</p>
</blockquote>

<p>Simplifying development has been around for exactly how long? Rails was the first framework of its kind that gained a huge following and other frameworks followed after it. Django was one (I think, I&#39;m in the air right now and can&#39;t connect to the Internet), CakePHP another.</p>

<blockquote>
<p>The Django community, for instance, has, in my experience, been filled with nice people who enjoy chatting about development.</p>
</blockquote>

<p>I have no <em>personal</em> experience with this, but I have heard reports from people who have switched that the Ruby community is nicer and more welcoming than the Django community. I&#39;m sure there&#39;s nice people in both communities.</p>

<blockquote>
<p>I&#39;d rather not be part of a community which seriously thinks dick jokes are hilarious.</p>
</blockquote>

<p>The truth is that 99.99% of the Rails community thinks dick jokes are immature. There&#39;s a small portion who just won&#39;t give it up, and that&#39;s just in their nature.</p>

<hr>

<p>Thank you for taking the time to read this far.</p>

<p>I would encourage you to check out the Ruby and Rails community again, even if it is just to see that we&#39;re not <em>all</em> arrogant assholes making dick jokes every chance we get. I think you could really benefit from learning more about the language and the framework.</p>

<p><em>Thanks!
Ryan Bigg</em></p>
]]></content>
 </entry>
 
 <entry>
   <title>Frontier, we need to talk</title>
   <link href="http://ryanbigg.com/2012/03/frontier-we-need-to-talk" />
   <updated>2012-03-14T00:00:00+11:00</updated>
   <id>http://ryanbigg.com/2012/03/frontier-we-need-to-talk</id>
   <content type="html"><![CDATA[<p>Hi,</p>

<p>My name is Ryan Bigg and I booked flights to Salt Lake City with a layover in Denver on the 14th of March. I&#39;d never booked you
before. How did I find out about you? Well, there&#39;s a handy site called <a href="http://hipmunk.com">Hipmunk</a> which is an aggregator for
flights, hotels and whatnot. You were ranked as the cheapest, and I figured what harm could there be in booking? The flight was a
perfect time, arriving at 4:25pm in SLC. Nobody else had flights arriving at such a perfect time as you.</p>

<p>First, a little bit of background on why I was going there in the first place. I&#39;m a programmer. There&#39;s a conference there called
<a href="http://mtnwestrubyconf.org/">Mountain West Ruby Conference</a> which I booked tickets to go to right before booking flights with you.
By arriving early in SLC, I hoped to catch up with some other programmer friends of mine and have a pre-conference dinner.</p>

<p>I arrived at San Francisco airport at 9:40am and checked in for the 10:45am flight. I was told there would be a delay of one hour and that I would miss my Denver connection. I would then have to make a later one at 9:20pm to go to SLC, arriving somewhere in the vicinity of 11:25pm. Too late to catch up with my friends.</p>

<p>At 11:45am, the screens still flashed &quot;Delayed&quot;. I didn&#39;t want to approach the counter and ask about times because the hostesses
were already seemingly pushed to their limits. I truly, truly pity them in situations like this where they have to deal with
indignant customers. A very long time ago, I used to work in a similar role and know how bad people can get.</p>

<p>At around 1:30pm, I decided to go have lunch with the screens still flashing delayed. The line for the restaurant nearby was too
busy, so I went over to the store next door and bought some Pringles and a bottle of water. I then moved to one of the charging
stations next to Gate 41, which is right across from Gate 43. There, I waited for the flight. Still flashing delayed.</p>

<p>So I decided I would do some work to pass the time while waiting for your flight. I completely missed the announcement due to one
reason or another, and looked up to see the flight board had changed. Not once was I notified of a departure time for the plane,
either by PA or screens.</p>

<p>I approached the desk and was told that I had missed my flight. The really helpful air hostess with the patience of a monastery (who wasn&#39;t wearing a name badge, so I couldn&#39;t tell you her name) rebooked me on the next available flight, one that was supposed to be leaving at 2:45pm but was delayed until &quot;Around 5&quot;. This would mean that I would be cutting it fairly fine in my layover for Denver, but could still probably make it. (I later checked, the flight actually departed at 5:56pm, meaning I would have missed my connection and had to stay the night in Denver, and I would&#39;ve missed the first day of the conference tomorrow)</p>

<p>As 5pm approached, I checked the flight status on Google. Originally, it told me 5:15pm. Then it told me 5:35pm, with an arrival time
within 19 minutes of my layover. Yeah, nah. Wasn&#39;t going to make that.</p>

<p>Not once did I receive an email telling me that the flight was delayed. No notification over the PA at all. Not a single, iota, of
anything.</p>

<p>I contacted one of my programming buddies and he advised me that there was a SouthWest direct-to-Salt-Lake-City flight leaving
Oakland Airport at 8:40pm that was being sold for $267. I bought it. I approached the desk again and asked how I would go about
getting a refund, and aI was told (again, <em>super</em> politely!) that I would need to call Frontier. That&#39;s very hard for me to do here,
because I don&#39;t have a mobile phone that works in this great country.</p>

<p>I caught a cab ($125, including tip) to Oakland airport. Checked in at SouthWest who informed me that their planes had no such delay
and would depart on time. Yay!</p>

<p>So here I sit, at Gate 31 in Oakland airport, writing this to you in the ultra-vain hope that you&#39;ll improve your systems. When your
flights have delays, PLEASE email your customers. I was constantly on the WiFi in SFO checking for notifications. Notify them over
the PA that a flight <em>may</em> be arriving at a specific time and to not go anywhere.</p>

<p>One final thing: I don&#39;t know where my large suitcase is right now. The suitcase that has <em>all</em> my good clothes, some souveniers and
some other things. It could be in Denver, it could be in Salt Lake City. I don&#39;t know. I can&#39;t call anybody to ask. I will need to go
to Baggage Claim in SLC and hope that they have it there. If they don&#39;t have it, then I&#39;m out around $900 of equipment.</p>

<p>Your @FrontierCare account contacted me earlier and offered me a $50 voucher on future Frontier flights, but I don&#39;t think that I&#39;ll
be using it. I&#39;ll be looking to get a refund (or at least, a partial one) for the flights that I&#39;ve missed today. $50 is a paltry
figure compared to how much I could have potentially lost today.</p>

<p>Please, please, please improve your customer service experience. It is <em>not</em> rocket science.</p>
]]></content>
 </entry>
 
 <entry>
   <title>Engines and Authentication</title>
   <link href="http://ryanbigg.com/2012/03/engines-and-authentication" />
   <updated>2012-03-03T00:00:00+11:00</updated>
   <id>http://ryanbigg.com/2012/03/engines-and-authentication</id>
   <content type="html"><![CDATA[<p>I&#39;ve been in America now longer than I&#39;ve been in my new apartment, but it&#39;s for very good reasons. The first of these was <a
href='http://spreeconf.com'>SpreeConf</a>, which was held in New York City and the second was <a href='http://ruby.onales.com'>Ruby
on Ales</a>, held in Bend, Oregon. Both were amazing conferences for their own reasons.</p>

<p>At both of these conferences, I gave a talk about Rails Engines. In this talk, I covered a lot of the lessons that I learned about
developing an engine, and the one of them that I would like to expand on today is about how an engine should deal with
authentication.</p>

<p>Put simply, the engine should not deal with authentication <em>at all</em>. You can stop reading now, this blog post is over and you&#39;ve
learned everything you&#39;re going to learn. Go forth and develop engines without authentication. Thanks for reading!</p>

<hr>

<p>If you&#39;re staying for after-the-fold, then let me explain my reasonings for this.</p>

<p>When we (Phil Arndt, Josh Adams and I) were developing <a href='https://github.com/radar/forem'>Forem</a>, we talked about what authentication engine we would support inside Forem. The issue was that different people have different opinions on what authentication system is &quot;best&quot;. Some like <a href='https://github.com/technoweenie/restful-authentication'>Restful Authentication</a>, some like <a href='https://github.com/binarylogic/authlogic'>Authlogic</a>, others like <a href='https://github.com/thoughtbot/clearance'>Clearance</a>, others like <a href='https://github.com/NoamB/sorcery'>Sorcery</a>, and finally others like to build their own custom solution. That was something made easier with the inclusion of <code>has_secure_password</code> in Rails 3.1.</p>

<p>That&#39;s a lot of fragmentation!</p>

<p>Therefore, picking <em>one</em> authentication solution means that we would isolate a large group of people. This is what the &quot;auth&quot;
component of Spree does, spree_auth.</p>

<hr>

<p>The way that spree_auth deals with authentication is that it uses Devise. It has a <code>Spree::User</code> model in it, and there&#39;s also some
Devise setup inside <code>config/initializers/devise.rb</code>. The <code>Spree::User</code> model is how Spree deals with authentication inside the
engine.</p>

<p>By having this authentication inside Spree, we are expressly stating that you <em>must</em> use Devise and have it as a dependency of your
application, even if your application uses something completely different.</p>

<p>A bigger problem comes up when your application <em>is also</em> using Devise. <code>spree_auth</code>&#39;s configuration combined with your application&#39;s configuration for Devise may cause slowdowns or conflict with each other. This may not happen though, because the railtie&#39;s (i.e. <code>spree_auth</code>&#39;s) initializers are run before the application&#39;s, and so it would take precedence.</p>

<p>For instance, we&#39;ve had a couple of reports where the Devise configuration in <a href='https://github.com/resolve/refinerycms'>RefineryCMS</a> have been conflicting with Spree&#39;s authentication.</p>

<p>Finally, by having two different User models (one in the application and one in the engine), it doesn&#39;t allow users to be shared
across the two components. This means that you would need to modify Spree to work with your application or your application to work
with Spree, which is not the ideal situation.</p>

<hr>

<p>How we deal with this in Forem is that we simply <em>do not</em> include an authentication engine of any kind. This means that you can use
Restful Authentication or Authlogic or Devise or Clearance or Sorcery or something custom and we couldn&#39;t care less.</p>

<p>The way that this works inside Forem is that we ask two questions when <code>rails g forem:install</code> runs. The first one is effectively
&quot;What is your <code>User</code> class?&quot; and the second one is &quot;What is <code>current_user</code> inside your application?&quot;. Forem then takes these values
and inserts code into <code>config/initializers/forem.rb</code> for the <code>Forem.user_class</code> setting and defines a method in the
<code>ApplicationController</code> class <em>of the application</em> called <code>forem_user</code> that simply calls the <code>current_user</code> method inside your
application.</p>

<p>The <code>Forem.user_class</code> setting is used in a couple of places. Firstly, it&#39;s used in the <code>Post</code> and <code>Topic</code> models to set up the
author/user associations so that we can track who created what topics or posts. Secondly, it&#39;s used in <code>Forem::ApplicationController</code> for
the <code>current_ability</code> method for the CanCan-backed authorization system that Forem uses.</p>

<p>The <code>forem_user</code> method is used to get at the current user of the request and allows Forem to check permissions and determine if a
user is logged in or not.</p>

<p>The application, not the engine, is what is providing the authentication engine. The application is <em>God</em> and should always have
final say on what is happening, not the engine itself.</p>

<hr>

<p>I personally think Forem&#39;s approach is the best that we&#39;re going to get with engines now. This method allows an application to
provide the authentication engine and for the engine to hook into it easily enough.</p>

<p>It&#39;s my thinking that we should remove the <code>spree_auth</code> gem entirely and then rely solely on the application to provide a <code>User</code> (or
similar) class. The authentication parts of RefineryCMS (and engines in similar situations) should also be removed. The application is
what should have the say on what authentication engine to use, and not an engine.</p>
]]></content>
 </entry>
 
 <entry>
   <title>Free Help</title>
   <link href="http://ryanbigg.com/2012/01/free-help" />
   <updated>2012-01-31T00:00:00+11:00</updated>
   <id>http://ryanbigg.com/2012/01/free-help</id>
   <content type="html"><![CDATA[<p>Sigh. Here I&#39;m going to sound like one of <em>those</em> celebrities. But I thought I should lay down some ground rules, so here goes.</p>

<p>Yesterday, I received a 1,063 word email from a non-profit organisataion asking me for advice on whether or not they should use Rails
or Django for their new project. They begin with:</p>

<blockquote>
<p>We found your answers and profile on Stack Overflow. We&#39;re reaching out to you because we&#39;d like your advice on a new nonprofit project, [name], and the language/app framework we should use to develop it.</p>

<p>We have a fairly small budget to build the framework and to do betas of the first seven sites, so it&#39;s crucial we pick the right framework. We are trying to choose between Django and Rails, and we want to make the right choice.</p>
</blockquote>

<p>Quite obviously, my answer is going to be heavily biased in one direction. I&#39;m sure you can guess which one.</p>

<p>Before yesterday, I&#39;d never even heard of this charity, nor spoken to the person who sent me the email. Basically, up until this
point, we&#39;ve done <em>nothing</em> for each other. Their questions obtusely relate to Rails, and definitely doesn&#39;t relate to what I get paid
to work on.</p>

<p>So I read the email anyway. It explains what the charity does and what they&#39;d like their new platform to do. Then at the bottom, they ask if I could &quot;take a look at the high-level requirements&quot; and link me to a Google Docs Spreadsheet. Inside this spreadsheet, there&#39;s 32 very wordy questions, like this one:</p>

<blockquote>
<p>We need the front ends and backends to run fast. Many of the backend pages will have fairly intensive reports drawing on lots of data from user pages, such as nonprofits being able to run reports of total donations over periods of time, recent donations, etc. We think speed is a top priority.</p>
</blockquote>

<p>Each question, by my estimates, would take one hundred to five hundred words to answer adequately. So at a minimum, around 3,200
words of mine to answer their questions. This is from a <em>complete stranger</em> in a private conversation between myself and them. Do you know what other situation this happens
in usually?</p>

<p>Oh yeah, <strong>paid consulting</strong>. But there&#39;s nothing in the email that indicates that I will get anything more than a warm and fuzzy
feeling from answering it.</p>

<p>Like I said before, this is not related to anything that I do. This is <em>extra</em> work. It&#39;s in a private conversation, so my
answers won&#39;t benefit anybody else. If this question pops up again, chances are that I will have to answer it again, and that&#39;s not
cool.</p>

<p>These kinds of emails are basically a three-times-a-week deal, and I&#39;m over it. While I enjoy helping people <em>for free</em>, I will only
do so in <a href='http://stackoverflow.com'>a public forum where other people can benefit from the answers</a>. If you want to contact me privately, then I will ask for some sort of reward for it, because <em>very</em> few people are going to benefit from it.</p>

<p>These kinds of questions have no regard for my time, and all I get from them is a feeling of being used for my talents. Kind of like
a whore, just without the money changing hands thing.</p>

<p>No more.</p>
]]></content>
 </entry>
 
 <entry>
   <title>Moving Out: Down to Melbourne</title>
   <link href="http://ryanbigg.com/2012/01/moving-out-down-to-melbourne" />
   <updated>2012-01-09T00:00:00+11:00</updated>
   <id>http://ryanbigg.com/2012/01/moving-out-down-to-melbourne</id>
   <content type="html"><![CDATA[<p>Oops, spoilers!</p>

<p>One year, four months ago I <a href='http://ryanbigg.com/2010/08/moving-out-for-reals'>moved out of a place in Camperdown in
Sydney</a> to a more remote suburb called Narwee. If you don&#39;t know where that is (and judging by the conversations I&#39;ve had with
many of you, <em>nobody</em> does), it&#39;s a South-Western suburb of Sydney, best described as &quot;Go south to the airport, then about as far
west&quot;. You could Google Maps it if you like. I&#39;ll wait.</p>

<p>It was there that I moved in with a guy called Tim and basically rented a room and shared the house for $200. It suited me fine, as I spent quite a lot of that time in there writing a book. The trainline nearby got me into and out of the city every single day that I needed it, bar one or two times where somebody decided to fight one of the trains.</p>

<p>When I came back from Adelaide recently, Tim arrived back also and told me that he has a friend who he would like to move in and so
he asked me (very nicely, might I add) to move out by the end of January. Fair enough, it&#39;s his place. This was on the 28th of December.</p>

<p>So then I needed to find a place. If I stay until February this year, then it&#39;ll be two years in Sydney. During that time, I&#39;ve
always heard Melbourne compared to Sydney favourably. Things like &quot;Melbourne&#39;s like Sydney, but with more fun&quot;. It also helped a bit
that my friend Tom (who I caught up with over Christmas) was suggesting that I should move to Melbourne as well so that we could hang out.</p>

<p>I was cooking dinner on the 29th and felt like I was doing nothing to further the situation. I needed to move out, but my weekend
plans weren&#39;t exactly conducive to that. So I thought &quot;fuck it&quot; and sent out a tweet asking if anyone had a place for me to
(temporarily) stay in Melbourne.</p>

<p>Tom replied with a half-joking, half-indignant tweet that I should have messaged him first and asked if I could stay there. I sent
him a message and he replied and said I could stay at his. The very next day I drove the ~900km down to Melbourne to stay at Tom&#39;s house.</p>

<hr>

<p>At that point, I had no fucking clue what I was doing in Melbourne. It was one of those spur-of-the-moment things. The drive <em>flew</em>
by, thanks in part to the Hume Highway dual-carriageway upgrades and the most-excellent Back to Work podcast.</p>

<p>Then, I got to see Melbourne for the first non-going-through-in-a-bus-to-the-airport-for-railscamp time. This city reminds me so much of San Francisco, from the cafés, to the over-population of hipsters (which is a con, not a pro) to the amazing food and friendly people. <a href='http://rosshill.com.au/melbourne'>Ross Hill actually wrote about these things</a>, and I can totally agree with him. I&#39;m actually writing this from <a href='http://inspire9.com.au'>Inspire9</a> right now!</p>

<p>I got to experience NYE in Melbourne with some great friends and all of those things combined are what sold me on Melbourne. So I&#39;m
moving there (which is &quot;here&quot; right now, but let&#39;s not get technical).</p>

<hr>

<p>I still had no fucking clue where I wanted to move, but at that point it <em>had</em> to be Melbourne. Some point after that, Tom and I are talking and he brings up that the guy who sold him his apartment (that he shares with two others) had another that he was looking to rent out also.</p>

<p>I got in touch with him, and he showed me the place. It is <a href='http://www.flickr.com/photos/radarlistener/sets/72157628787106371/'>the best place I&#39;ve ever had the pleasure of looking at</a>. Wooden floorboards, a nice upstairs area, two bathrooms, four bedrooms (one will be used as a study / storage area), gas stove kitchen, nice patio, and so on.</p>

<p>On Friday, I looked it over again with two other prospective housemates and they both agreed that it was nice. One of them backed out
due to how long it is out of town, and the other one doesn&#39;t mind. So I told the agent that I would absolutely love to lease the
property.</p>

<p>This morning, I went into the agent&#39;s office, handed over the first month&#39;s rent and signed the lease agreement.</p>

<p>I&#39;ll be moving down and in on the 21st of January. See you around!</p>
]]></content>
 </entry>
 
 <entry>
   <title>Matt Lightner</title>
   <link href="http://ryanbigg.com/2011/12/matt-lightner" />
   <updated>2011-12-27T00:00:00+11:00</updated>
   <id>http://ryanbigg.com/2011/12/matt-lightner</id>
   <content type="html"><![CDATA[<p>Matt Lightner -- <a href='http://www.facebook.com/mlightner'>according to posts on his Facebook</a> -- is dead. It apparently
happened on Christmas day, which just adds supremely to the suckiness of it all.</p>

<p>You may remember him from that little hosting company called <a href='http://site5.com'>Site5</a> he started when he was 15. You know
the one that was one of the, if not <em>the</em> first, hosting company to offer Ruby on Rails support.</p>

<p>I had the pleasure of working with Matt around September last year and ended up visiting him in San Francisco. We went to <a href='http://www.yelp.com/biz/antonios-nut-house-palo-alto'>Antonio&#39;s Nut House</a> where we drank and played darts (and ate way too many free peanuts). Then we went back to his apartment where I got to sleep on an air mattress. That morning we went for bagels at a place not too far away from the Nut House. Those are my favourite memories of San Francisco.</p>

<p>He was such an amazing guy and will be terribly missed.</p>
]]></content>
 </entry>
 
 <entry>
   <title>Deciding what tests to write</title>
   <link href="http://ryanbigg.com/2011/12/deciding-what-tests-to-write" />
   <updated>2011-12-05T00:00:00+11:00</updated>
   <id>http://ryanbigg.com/2011/12/deciding-what-tests-to-write</id>
   <content type="html"><![CDATA[<p>More people who are new to Ruby are getting into TDD and BDD thanks to the wonderful tools like RSpec and
Cucumber that make it easy for them to do so. There&#39;s no real public information on exactly <em>what</em> you should be testing, though.</p>

<h3>Testing Validations</h3>

<p>RSpec supports the shoulda-matchers gem and I see a lot of people using this to test validations on their models,
and this is the <em>first</em> test that they&#39;re writing. I personally think that this is the wrong way of doing things.</p>

<p>The first test should be one that follows the exact steps that the user would need to do in order to approve this
functionality.</p>

<p>In the example test (written in Capybara&#39;s syntax) below, the user fills in the form (ignoring one of the required fields) and then should see that there&#39;s an error on the page.</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">visit root_path
click_link &quot;Posts&quot;
click_link &quot;New Post&quot;

fill_in &quot;Title&quot;, :with =&gt; &quot;Deciding what tests to write&quot;
click_button &quot;Create Post&quot;

within(&quot;#flash_alert&quot;) do
  page.should have_content(&quot;Post could not be created.&quot;)
end

within(&quot;#post_form .errors&quot;) do
  page.should have_content(&quot;Body cannot be blank&quot;)
end
</code></pre></div>
<p>Or if you prefer Cucumber:</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">Given a user is creating a new post
And the user leaves the post text blank
When the user clicks &quot;Create Post&quot;
Then they should see a validation error:
  &quot;&quot;&quot;
    Body cannot be blank
  &quot;&quot;&quot;
</code></pre></div>
<p>You can imagine the steps that Cucumber would use, they&#39;d use the Capybara methods just like the original example.</p>

<p>The point is, this test is testing the user&#39;s interaction with the page, which I think is the most <em>critical</em> part
of the application. If the user cannot see this error message, why does it matter if the model validates the
presence of this field? <em>It doesn&#39;t.</em></p>

<p>Testing that the model contains the validation is a secondary thing, and is generally something I skip doing. The
test for at least one of the form&#39;s validations goes into the request spec. If I&#39;m feeling pedantic I&#39;ll write
another for the other validations, but I can <em>assume</em> that dynamic_form (the thing that provides
<code>error_messages_for</code> is doing the right thing when it comes to its own methods. If one error message is showing
up, good chance the others are.</p>

<p>In the case where validation error messages <em>don&#39;t</em> show up then I write a specific test for that inside the
request spec before going on to fix it wherever I need to.</p>

<h3>Testing Complex Logic</h3>

<p>In <a href='http://spreecommerce.com'>Spree</a>, there&#39;s complex logic involved around orders and tracking
inventory. This is something I <em>could</em> test with a request spec, but how the system works is made up of so many
little parts it makes it slow to test the whole thing:</p>

<ul>
<li>A product exists in the system, has a &quot;count on hand&quot; of 1.</li>
<li>A user wants to buy this product, so clicks &quot;Add to cart&quot;</li>
<li>A new order is created in the system, with this item</li>
<li>User is prompted to sign in</li>
<li>User is prompted for billing + shipping details.</li>
<li>User is prompted for credit card details</li>
<li>User clicks &quot;Confirm&quot; on order page</li>
<li>Order goes through, deducting 1 from &quot;count on hand&quot; total, bringing it to 0.</li>
</ul>

<p>A huge portion of these steps aren&#39;t even required to test the count on hand decreasing. What we care about is
that when an order is placed in the system that the count on hand decreases by one. And so this is where a unit
test would be better.</p>

<p>This unit test would check that when an order is created, a method such as <code>unstock_items!</code> is called. There would then be another unit test for the actual function of the <code>unstock_items!</code>
call, ensuring that it goes through the line items for the order and depletes the stock on the products as necessary.</p>

<p>The unit test is going to be much lighter (and quicker to run!) than the request spec, which is just a massive win.</p>

<h3>Conclusion</h3>

<p>At the final retrospective at the CodeRetreat event on Saturday in Sydney, it was brought up that there&#39;s no &quot;right&quot; way to test. Some people thought that testing from the &quot;bottom-up&quot; (unit test first, request specs or similar later) was better, but then they saw the merits of testing &quot;top-down&quot; (request specs or similar first, then unit tests for the fiddly bits) as well.</p>

<p>I think liberal applications of both of these methodologies is <em>one</em> &quot;right&quot; way to test. The more I test, the more I find myself getting better at knowing what to test and how to test it. I
can see the merits of both ways. I&#39;m preferring top-down though, as that&#39;s, in my opinion, testing what the client is going to be seeing, and that&#39;s what matters most. If there&#39;s a bit of
gnarly code in there, like the order inventory tracking, then that&#39;s when I&#39;d dive down into unit testing.</p>

<p>What are your thoughts on this?</p>
]]></content>
 </entry>
 
 <entry>
   <title>Don't print hard-copies</title>
   <link href="http://ryanbigg.com/2011/11/don-t-print-hard-copies" />
   <updated>2011-11-29T00:00:00+11:00</updated>
   <id>http://ryanbigg.com/2011/11/don-t-print-hard-copies</id>
   <content type="html"><![CDATA[<p><a href="http://www.manning-sandbox.com/thread.jspa?threadID=47354&amp;tstart=0">What a fan-fucking-tasking way to end the day</a>. This honestly <em>really</em> upsets me, because I alone am powerless to do anything to fix this guy&#39;s problem.</p>

<p>You may know that I <a href='http://manning.com/katz'>wrote a book</a>. I may have written during the process
about the difficulties faced and also about how much <em>it fucking rocks</em> to have a book published. I&#39;ve never felt
so damn good for so long.</p>

<p>That&#39;s a topic for another day. Today&#39;s a rant kind of day. Tonight, I feel like shit.</p>

<p>Let the rant begin.</p>

<h3>Authoring tools</h3>

<p>Let&#39;s start with the authoring tools that Manning provides.</p>

<p>To author a book, you use Manning&#39;s DocBook format, which isn&#39;t actually all that bad once you get used to it. Alternatively you could write in Microsoft Word, but I honestly hate it. The documents just feel... unstructured to me. DocBook appealed to me because I <em>obsess</em> about ordering and structure.</p>

<p>I created all kinds of macros in TextMate for DocBook and was fucking awesome at it towards the end of it. If there were world championships in DocBook, I would place high. Mum would be proud.</p>

<p>Once I had a chapter ready, I had to upload it to Manning&#39;s system. This is done through an SVN repository. I
hate (and I mean, <strong>truly hate</strong>) very few things in this world. Microsoft Word&#39;s one of them, and SVN is another. Years of abuse have me close to suffering post-traumatic stress disorder attacks every time it so much as conflicts on a damned file.</p>

<p>Anyway, once the file&#39;s uploaded to Manning&#39;s system through the version control system from Hell, you get to use
the authoring tool also from the same locale. I shit you not, this thing takes <em>4</em> clicks to update a single
chapter. You need to click on the gear icon, click on a chapter, scroll down to the god-damned bottom of the page
listing all the revisions EVER for the chapter (for God knows what reason) (p.s. there&#39;s 80+ for some of the
earlier chapters, with each revision taking 4 lines of 12pt text) and then click on the radio button for
&quot;Latest&quot; (the text next to this field doesn&#39;t trigger it, of course) and then click &quot;Update&quot;.</p>

<p>I got majorly annoyed with this process in about June of last year and created my own system in <em>twelve hours</em>. It&#39;s goal was to a) allow me to publish updates to <em>all the chapters</em> with one command and b) to provide <em>other people</em> with a super-easy way to review the book, and it did both of those things, but it looked like shit. I fixed that with version
two, with the help of a friend.</p>

<p>In total, I received ~1,600 notes on the review systems that <em>I built</em> and they contributed back in <em>major</em> ways to the
book. Want to know why the book&#39;s so damned good? Not me. I was just the dude who typed things and put in terrible jokesas footnotes. It&#39;s the reviewers. They did all the hard work. Honestly. They read the same chapter again and again and hhounded me about problems. One guy and I even used to chat regularly on Skype.</p>

<p>Those guys rock. Over 30 people contributed <em>something</em> to the book. Could&#39;ve been &quot;missed a comma&quot;, could&#39;ve been &quot;Prototype sucks!&quot;. I love them all.</p>

<p>Manning&#39;s counterpart to this review system also looks like shit, but only allows for the author and Manning staff
to have access to the book. On one hand, this is great because it stops the inevitable piracy (which, as far as I
know, never happened on my review system), but on the other hand it really sucks because you don&#39;t get reviews of the book as you go along from people outside your little circle.</p>

<p>So yeah, authoring tools are... depressing to use. I don&#39;t think that any publisher has this nailed yet, although I suspect PragProg has gotten the closest to it.</p>

<h3>The One True Format (But not really)</h3>

<p>When I started writing the book, I was given a choice. You know this already, but let me refresh your memory just
in case you dont: it was DocBook or Microsoft Word. I chose DocBook because it&#39;s a lovely structured format.</p>

<p>I also thought &quot;Sure, these guys probably have the tools to convert this into PDF and ePub and Mobi and monetary
notes that I can give to people to buy things&quot;.</p>

<p>Man, I can be na&#239;ve sometimes.</p>

<p>When we went to review, they went through the XML document with this tool I can&#39;t remember the name of and it seriously messed with my <em>obsessive</em> formatting. I was non-plussed. I asked them to fix it, and they did, which was nice of them. Still, this tool basically crapped all over the XML document.</p>

<p>My review system did not. Notes were kept separate from the content and not stored as fucking metadata inside the document itself. Why did I do it this way? <em>Because it&#39;s sensible</em>. Down the other path lies madness. I know, because I had to live with that.</p>

<p>That was nothing compared with what happened next. To typeset the book they converted the text into a Word
document. I don&#39;t know how exactly they did this (but I suspect it involved the C &amp; V keys on the keyboard, along
with a bit of Control). Seriously.</p>

<p>So now what we have is Word document copies of each of the chapters. Word&#39;s review system is very lol-worthy
itself also. As an author, I only really care about one note at a time, not the gazillion that the editor has left
on the page and Word loves to display.</p>

<p>This means that to <em>update</em> a chapter, I need to ask Manning for a copy of the chapter <em>as a Word document</em>, which
they&#39;ll <em>email</em> to me, make the fix myself and then <em>email it back to them</em>. Or I use their document
management software which was, I&#39;m sure, designed by people who hate their jobs.</p>

<p>Eventually, enough of these changes will be made and there will be the next for a second printing. When that is, not even I know.</p>

<p>So that lovely little DocBook format I got used to, created all the macros and muscle memory for is now toast. My
future is Word documents.</p>

<h3>Why printing technical books is just a bad idea</h3>

<p>See, with printed books, it&#39;s really hard to update them. You may have noticed this if you have a copy of Rails
3 in Action on your shelf and open to any page <a href='http://manning.com/katz/errata.html'>listed in the
Errata</a>. Has yours been updated? No? Neither have the three sitting on my bench right now.</p>

<p>There&#39;s also the problem of this book becoming quickly outdated due to how quickly Rails moves. We actually
upgraded the book to Rails 3.1 in May (the book was printed in September), which was practically &quot;danger close&quot; to
the printing time. I&#39;m so happy that we got this change in, but I fear for the future.</p>

<p>If the book was kept in a proper, structured electronic format and never printed on dead trees, then we wouldn&#39;t have this problem. We wouldn&#39;t have &quot;Sydney&quot; misspelt as &quot;Syndey&quot; on the back cover because someone could have fixed it and everyone would be happy. Actually, we wouldn&#39;t have had that if someone didn&#39;t do a rush-job on the cover, but people make mistakes. It&#39;s an OK thing to do.</p>

<p>We wouldn&#39;t run into issues like when Cucumber decides it wants to divorce <code>web_steps.rb</code> and it <em>breaks the whole
book</em>. You know why? <em>Because we could update the damn thing</em>. We could release a new update <em>every week</em> if we
needed to and people would be happy that it&#39;s a constantly improving, amazing book.</p>

<p>But instead, we print to dead trees, disabling us from updating it efficiently and easily and it stagnates within
6 months.</p>

<p>Now that we <em>finally</em> (just this week) have the ePub and mobi formats available for the book. I suspected they
had to use the afore-mentioned C+V keys to do these too. Updating these is easy in comparison: alter the source, compile a new version, put it on a server and let people know. Done.</p>

<p>And hey, it would be super easy if the source was DocBook and there was a tool to read that XML and convert it
into ePub friendly HTML. But there&#39;s not one in this process.</p>

<p>That&#39;s how tech publishing should be: electronic only. If you want a dead-tree copy, well, I&#39;m sorry, but you&#39;re going to have to print it yourself.</p>

<h3>There will be more</h3>

<p>Yeah, we probably did fail at creating The Best Book Ever. But that was never the goal. The goal was to create a
book that was easy for noobs to read and learn Rails (and to be the best at <em>that</em>).</p>

<p>I think we succeeded, but I also have a ginormous ego.</p>

<p>Yes, there are mistakes but we will fix them. I will do everything in my power to address any and all (reasonable) concerns you have with the book. I want it to be perfect for you.</p>

<p>There will be updates. Even though Manning&#39;s tools are not that great, the people who work there are some of my
favourite people in the world. I will work with these wonderful people and we will release a wonderful Version
Two.</p>

<p>Promise.</p>
]]></content>
 </entry>
 
 
</feed>
