<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/atom10full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>lindsaar.net - Home</title>
  <id>tag:lindsaar.net,2008:mephisto/</id>
  <generator version="0.7.3" uri="http://mephistoblog.com">Mephisto Noh-Varr</generator>
  
  <link href="http://lindsaar.net/" rel="alternate" type="text/html" />
  <updated>2008-07-13T11:24:48Z</updated>
  <link rel="license" type="text/html" href="http://creativecommons.org/licenses/by-nc-sa/3.0/" /><logo>http://creativecommons.org/images/public/somerights20.gif</logo><link rel="self" href="http://feeds.feedburner.com/lindsaar-net" type="application/atom+xml" /><entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-07-13:929</id>
    <published>2008-07-13T11:21:00Z</published>
    <updated>2008-07-13T11:24:48Z</updated>
    <link href="http://feeds.feedburner.com/~r/lindsaar-net/~3/334208499/tip-28-separate-the-things-that-change-from-the-things-that-stay-the-same" rel="alternate" type="text/html" />
    <title>Tip #28 - Separate the things that change from the things that stay the same</title>
<summary type="html">&lt;p&gt;When you are coding, you should try to separate out the things that change from the things that stay the same.  This isn’t my idea, but it is worth tip’n here as I just saw a really good, simple example of this…&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;When you are coding, you should try to separate out the things that change from the things that stay the same.  This isn’t my idea, but it is worth tip’n here as I just saw a really good, simple example of this…&lt;/p&gt;
&lt;p&gt;I first read about this concept in learning about Design Patterns.  Then I also read it in Design Patterns in Ruby by &lt;a href="http://www.jroller.com/rolsen/"&gt;Russ Olsen&lt;/a&gt; (good book by the way).&lt;/p&gt;


	&lt;p&gt;The basic concept is that if you can spot the few lines of code in your design that &lt;em&gt;could&lt;/em&gt; change and move these out to a separate part of your code base, when a change comes along, you just have to change one small part of your app and you are done.  You don’t have to dive through lots of classes fixing and correcting code everywhere to implement the change.&lt;/p&gt;


	&lt;p&gt;I recently ran into a good example of this, it is the Active Record Extensions by &lt;a href="http://www.continuousthinking.com/tags/arext"&gt;Zach Dennis&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;I use PostgreSQL, Zach’s Active Record extensions worked out of the box with PostgreSQL, but in the inefficient fail-safe manner, that is, it did bulk inserts by making one complete insert statement per row, which is per the &lt;span class="caps"&gt;SQL&lt;/span&gt; standard.&lt;/p&gt;


	&lt;p&gt;For MySQL, he had implemented the multiple insert method in &lt;span class="caps"&gt;SQL&lt;/span&gt;, which allows you to write on “INSERT &lt;span class="caps"&gt;INTO&lt;/span&gt;…” and give it an insert array of (in my case) 1000 rows.  This cuts down on data transfer between the client and server.  Especially when you are inserting a few hundred thousand rows.&lt;/p&gt;


	&lt;p&gt;I knew PostgreSQL also supported this, so I dove into the code base to find a way to implement.&lt;/p&gt;


	&lt;p&gt;Happily, I found that Zach had followed the above rule to the letter.  To implement this, I had to modify &lt;em&gt;one&lt;/em&gt; line in one file (to include a module) and copy about 20 lines into another file (the MySQL versions) and modify a few of those lines to suit PostgreSQL and I was done!&lt;/p&gt;


	&lt;p&gt;This was a good piece of code, a good example of the above and worth looking at for a Ruby on Rails intermediate type who wants to find out more about plugins and extending ActiveRecord.&lt;/p&gt;


	&lt;p&gt;Mikel&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/334208499" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/7/13/tip-28-separate-the-things-that-change-from-the-things-that-stay-the-same</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-07-08:902</id>
    <published>2008-07-08T02:57:00Z</published>
    <updated>2008-07-08T03:02:24Z</updated>
    <link href="http://feeds.feedburner.com/~r/lindsaar-net/~3/329863824/fortune" rel="alternate" type="text/html" />
    <title>Fortune...</title>
<summary type="html">&lt;p&gt;I got his when I logged into one of my OpenBSD boxes today.  Interestingly true…&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;I got his when I logged into one of my OpenBSD boxes today.  Interestingly true…&lt;/p&gt;
&lt;p&gt;An architect’s first work is apt to be spare and clean. He knows he doesn’t know what he’s doing, so he does it
carefully and with great restraint.&lt;/p&gt;


	&lt;p&gt;As he designs the first work, frill after frill and embellishment after embellishment occur to him. These get
stored away to be used “next time”. Sooner or later the first system is finished, and the architect, with firm
confidence and a demonstrated mastery of that class of systems, is ready to build a second system.&lt;/p&gt;


	&lt;p&gt;This second is the most dangerous system a man ever designs. When he does his third and later ones, his prior
experiences will confirm each other as to the general characteristics of such systems, and their differences will
identify those parts of his experience that are particular and not generalizable.&lt;/p&gt;


	&lt;p&gt;The general tendency is to over-design the second system, using all the ideas and frills that were cautiously
sidetracked on the first one. The result, as Ovid says, is a “big pile”.&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;-- Frederick Brooks, "The Mythical Man Month"&lt;/code&gt;&lt;/pre&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/329863824" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/7/8/fortune</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-06-30:851</id>
    <published>2008-06-30T00:05:00Z</published>
    <updated>2008-06-30T00:06:18Z</updated>
    <category term="RSpec" />
    <category term="Ruby on Rails" />
    <link href="http://feeds.feedburner.com/~r/lindsaar-net/~3/323428855/examples-of-behaviour-spec-n" rel="alternate" type="text/html" />
    <title>Examples of Behaviour Spec'n</title>
<summary type="html">&lt;p&gt;In my previous post (&lt;a href="http://lindsaar.net/2008/6/28/tip-27-spec-a-behaviour-not-an-implementation"&gt;Spec Behaviour not Implementation&lt;/a&gt;) I went on a froth roll about why you should treat controller actions as black boxes.  Here I give an all to common example of why this is good and how you &lt;em&gt;can&lt;/em&gt; write specs that won’t break at the most trivial change.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;In my previous post (&lt;a href="http://lindsaar.net/2008/6/28/tip-27-spec-a-behaviour-not-an-implementation"&gt;Spec Behaviour not Implementation&lt;/a&gt;) I went on a froth roll about why you should treat controller actions as black boxes.  Here I give an all to common example of why this is good and how you &lt;em&gt;can&lt;/em&gt; write specs that won’t break at the most trivial change.&lt;/p&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;AddressesControler&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@person&lt;/span&gt; = &lt;span class="co"&gt;Person&lt;/span&gt;.find(params[&lt;span class="sy"&gt;:person_id&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@addresses&lt;/span&gt; = &lt;span class="co"&gt;Address&lt;/span&gt;.find_by_person_id(params[&lt;span class="sy"&gt;:person_id&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Now obviously this should be refactored (we’ll get to that in a sec) but what are we doing here?  We are assigning person to the view and the person’s addresses to the view.&lt;/p&gt;


	&lt;p&gt;Using a mocks and stubs, I might do something like this:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;describe &lt;span class="co"&gt;AddressesController&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  describe &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;GET index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should ask the Person model for a person&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="iv"&gt;@person&lt;/span&gt; = mock_model(&lt;span class="co"&gt;Person&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="co"&gt;Person&lt;/span&gt;.should_receive(&lt;span class="sy"&gt;:find&lt;/span&gt;).with(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).and_return(&lt;span class="iv"&gt;@person&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;      get &lt;span class="sy"&gt;:index&lt;/span&gt;, &lt;span class="sy"&gt;:person_id&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should assign a person to the view&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="iv"&gt;@person&lt;/span&gt; = mock_model(&lt;span class="co"&gt;Person&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="co"&gt;Person&lt;/span&gt;.stub!(&lt;span class="sy"&gt;:find&lt;/span&gt;).and_return(&lt;span class="iv"&gt;@person&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;      get &lt;span class="sy"&gt;:index&lt;/span&gt;, &lt;span class="sy"&gt;:person_id&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      assigns[&lt;span class="sy"&gt;:person&lt;/span&gt;].should == &lt;span class="iv"&gt;@person&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;    it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should ask the Address model for the addresses&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="co"&gt;Person&lt;/span&gt;.stub!(&lt;span class="sy"&gt;:find&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="iv"&gt;@addrs&lt;/span&gt; = [mock_model(&lt;span class="co"&gt;Address&lt;/span&gt;), mock_model(&lt;span class="co"&gt;Address&lt;/span&gt;)]&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="co"&gt;Address&lt;/span&gt;.should_receive(&lt;span class="sy"&gt;:find_by_person_id&lt;/span&gt;).with(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).and_return(&lt;span class="iv"&gt;@addrs&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;      get &lt;span class="sy"&gt;:index&lt;/span&gt;, &lt;span class="sy"&gt;:person_id&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should assign the person's addresses to the view&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="co"&gt;Person&lt;/span&gt;.stub!(&lt;span class="sy"&gt;:find&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="iv"&gt;@addrs&lt;/span&gt; = [mock_model(&lt;span class="co"&gt;Address&lt;/span&gt;), mock_model(&lt;span class="co"&gt;Address&lt;/span&gt;)]&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="co"&gt;Address&lt;/span&gt;.should_receive(&lt;span class="sy"&gt;:find_by_person_id&lt;/span&gt;).with(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).and_return(&lt;span class="iv"&gt;@addrs&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;      get &lt;span class="sy"&gt;:index&lt;/span&gt;, &lt;span class="sy"&gt;:person_id&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      assigns[&lt;span class="sy"&gt;:addresses&lt;/span&gt;].should == &lt;span class="iv"&gt;@addrs&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Now, no one would complain about that (except that it is not very dry), pretty straight forward. But I say, my fellow RSpecers, what are we doing poking around the internals of that controller?  Why do we give two hoots from a behavioral viewpoint on &lt;span class="caps"&gt;HOW&lt;/span&gt; the controller goes about it’s business?  Can’t we just assign the controller responsibility here?&lt;/p&gt;


	&lt;p&gt;Well, no, you say, I need to know it is getting the addresses properly!.  Well, ok, let’s make one trivial change to one line of that controller and see how many specs break:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;AddressesControler&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@person&lt;/span&gt; = &lt;span class="co"&gt;Person&lt;/span&gt;.find(params[&lt;span class="sy"&gt;:id&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@addresses&lt;/span&gt; = &lt;span class="iv"&gt;@person&lt;/span&gt;.addresses&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Now, you would agree with me that the &lt;em&gt;external&lt;/em&gt; behaviour of that controller action has not changed, we are assigning the requested person to the view and we are assigning the person’s addresses to the view, but guess what, &lt;strong&gt;every one of our specs now fail&lt;/strong&gt;  Why!?  Because we spec’d implementation details.  We setup our stubs and mocks to provide data in only certain ways.&lt;/p&gt;


	&lt;p&gt;The first and second specs fail because @person is a mock model and gets an unexpected message :addresses, the second and third specs fail because we don’t return anything from the Person.find and so you then get nil.addresses which fails.  Even if that didn’t fail, we then have a failing spec because the Address model is never called.&lt;/p&gt;


	&lt;p&gt;Evil. Madness. Insanity, but most importantly, &lt;strong&gt;lost time&lt;/strong&gt;.  Now you need to go and dig in, remember what that spec did, what you were trying to do and re-write the spec, hoping that you aren’t changing the required behaviour.&lt;/p&gt;


	&lt;p&gt;And what is worse, our behaviour driven development specs are failing when the &lt;em&gt;behaviour&lt;/em&gt; didn’t change!&lt;/p&gt;


	&lt;p&gt;Now there is a lot to be said for mock objects and stub methods.  They are useful and have their place, they definitely speed up spec execution time, but I think this whole thing of mock everything in the controllers to make the specs go faster is over rated.&lt;/p&gt;


	&lt;p&gt;I work in a development team.  We user &lt;a href="http://lindsaar.net/2008/5/12/tip-16-valid-models-don-t-have-to-be-hard"&gt;factory objects&lt;/a&gt; and real objects when we can get away with it.  And our specs run slower.  On an app that is about 50% done we have 1500 specs passing, and it takes about 70 seconds to run them.  Not too bad.  About half of them use real objects (from the database).  Sure, if I went through and mocked and stubbed everything out and spent the time doing that, it might get down to 50 seconds, or maybe 40. But it is pretty rare that waiting for the test suite to pass is blocking my development time.&lt;/p&gt;


	&lt;p&gt;So, if we re-wrote the above spec using factories, we would get something like this:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;describe &lt;span class="co"&gt;AddressesController&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  describe &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;GET index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should assign the requested person to the view&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="iv"&gt;@person&lt;/span&gt; = &lt;span class="co"&gt;Person&lt;/span&gt;.build_valid!(&lt;span class="sy"&gt;:id&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;1&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;      get &lt;span class="sy"&gt;:index&lt;/span&gt;, &lt;span class="sy"&gt;:person_id&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      assigns[&lt;span class="sy"&gt;:person&lt;/span&gt;].should == &lt;span class="iv"&gt;@person&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should assign the person's addresses to the view&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="iv"&gt;@person&lt;/span&gt; = &lt;span class="co"&gt;Person&lt;/span&gt;.build_valid!(&lt;span class="sy"&gt;:id&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;1&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="iv"&gt;@address&lt;/span&gt; = &lt;span class="co"&gt;Address&lt;/span&gt;.build_valid(&lt;span class="sy"&gt;:person_id&lt;/span&gt; =&amp;gt; &lt;span class="iv"&gt;@person&lt;/span&gt;.id)&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="iv"&gt;@person&lt;/span&gt;.addresses &amp;lt;&amp;lt; &lt;span class="iv"&gt;@address&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      get &lt;span class="sy"&gt;:index&lt;/span&gt;, &lt;span class="sy"&gt;:person_id&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      assigns[&lt;span class="sy"&gt;:addresses&lt;/span&gt;].should == [&lt;span class="iv"&gt;@address&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Now, even though we have reduced this down to two specs, in reality, that is all the behaviour our controller is showing.  It has no error handling etc.&lt;/p&gt;


	&lt;p&gt;If there were decision path’s in the behaviour of the controller, I would stub these out to do what I wanted for the spec, like @person.stub!(:save).and_return(false) and the like.&lt;/p&gt;


	&lt;p&gt;One other thing that I often read is that you don’t want to do a spec like this because some other developer could go and change the underlying &lt;span class="caps"&gt;API&lt;/span&gt; on how person and address talk to each other or what constitutes a valid object.&lt;/p&gt;


	&lt;p&gt;Well, I work in a team and I humbly submit that:&lt;/p&gt;


	&lt;p&gt;(a) this doesn’t happen too often, especially if you are using factories, because if you change the valid requirements of a person, then you should also be updating the factory.&lt;/p&gt;


	&lt;p&gt;(b) I want to know if my controller broke because of an &lt;span class="caps"&gt;API&lt;/span&gt; change.&lt;/p&gt;


	&lt;p&gt;Anyway, that’s just how I do it, your mileage may vary.&lt;/p&gt;


	&lt;p&gt;blogLater&lt;/p&gt;


	&lt;p&gt;Mikel&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/323428855" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/6/30/examples-of-behaviour-spec-n</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-06-28:831</id>
    <published>2008-06-28T04:35:00Z</published>
    <updated>2008-06-28T23:59:27Z</updated>
    <link href="http://feeds.feedburner.com/~r/lindsaar-net/~3/321929735/us-itunes-gift-vouchers-up-for-sale" rel="alternate" type="text/html" />
    <title>US iTunes Gift Vouchers Up for Sale</title>
<content type="html">
            &lt;p&gt;Bit off topic, but over the past two weeks I have received $75 in US iTunes gift cards.. per apple, I can’t use them from Australia… anyone want to buy them?  I’ll sell the lot for $70 US.&lt;/p&gt;


	&lt;p&gt;Turns out that Shane showed me if it is a voucher, you can redeem it at the US iTunes store… cool :)&lt;/p&gt;


	&lt;p&gt;blogLater&lt;/p&gt;


	&lt;p&gt;Mikel&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/321929735" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/6/28/us-itunes-gift-vouchers-up-for-sale</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-06-28:830</id>
    <published>2008-06-28T03:42:00Z</published>
    <updated>2008-06-28T03:48:50Z</updated>
    <category term="RSpec" />
    <category term="Ruby on Rails" />
    <category term="Ruby on Rails Tips" />
    <link href="http://feeds.feedburner.com/~r/lindsaar-net/~3/321795788/tip-27-spec-a-behaviour-not-an-implementation" rel="alternate" type="text/html" />
    <title>Tip #27 - Spec a Behaviour, Not an Implementation</title>
<summary type="html">&lt;p&gt;This has been said a lot, and doesn’t really need repeating by someone like me, but, as this is a tips page, I should put it here.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;This has been said a lot, and doesn’t really need repeating by someone like me, but, as this is a tips page, I should put it here.&lt;/p&gt;
&lt;p&gt;What does this mean?  Behaviour, not Implementation?&lt;/p&gt;


	&lt;p&gt;Well, it means, what is it you are expecting your code to achieve?  What is the end product that your code is meant to do?  What are the valid states your code can be in &lt;em&gt;after it has finished executing&lt;/em&gt;?&lt;/p&gt;


	&lt;p&gt;The way I draw the line on this is, except for &lt;span class="caps"&gt;RARE&lt;/span&gt; cases, I only spec the public interface of a component.  That is, the bits that the class is presenting out to the bad wide world as valid ways to communicate to it.  If you do this, it means that later you can change your implementation of &lt;span class="caps"&gt;HOW&lt;/span&gt; you got something done without a bunch of specs failing.&lt;/p&gt;


	&lt;p&gt;The applies to controller specs.&lt;/p&gt;


	&lt;p&gt;You should really treat the insides of a controller as sacrosanct, you don’t really have any business hunting and poking around in there, each controller has a right to privacy, &lt;strong&gt;&lt;span class="caps"&gt;THEY HAVE RIGHTS TOO&lt;/span&gt;!...&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;Ok, maybe a bit carried away, but you might see what I mean in a sec:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="iv"&gt;@person&lt;/span&gt; = &lt;span class="co"&gt;Person&lt;/span&gt;.new(params[&lt;span class="sy"&gt;:person&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  respond_to &lt;span class="r"&gt;do&lt;/span&gt; |format|&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;if&lt;/span&gt; &lt;span class="iv"&gt;@person&lt;/span&gt;.save&lt;tt&gt;
&lt;/tt&gt;      flash[&lt;span class="sy"&gt;:notice&lt;/span&gt;] = &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Person was successfully created.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      format.html { redirect_to(&lt;span class="iv"&gt;@person&lt;/span&gt;) }&lt;tt&gt;
&lt;/tt&gt;      format.js&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      format.html { render &lt;span class="sy"&gt;:action&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;      format.js&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;With this simple example, what is it we are actually trying to spec?&lt;/p&gt;


	&lt;p&gt;Well, what is the behaviour?&lt;/p&gt;


	&lt;p&gt;1. If it succeeds, then we should get a flash sent to the view telling us we were a good little user.&lt;/p&gt;


	&lt;p&gt;2. If it succeeds, then we’ll get sent to the person show page&lt;/p&gt;


	&lt;p&gt;3. If it succeeds and we did an &lt;span class="caps"&gt;XHR&lt;/span&gt; request, then we’ll get the create.js template&lt;/p&gt;


	&lt;p&gt;4. If it succeeds we should get a person instance assigned to the view that has been saved.&lt;/p&gt;


	&lt;p&gt;5. If it fails on a &lt;span class="caps"&gt;HTTP&lt;/span&gt; request, then we get the new template rendered&lt;/p&gt;


	&lt;p&gt;6. If it fails on an &lt;span class="caps"&gt;XHR&lt;/span&gt; request, then we’ll still get the create.js template&lt;/p&gt;


	&lt;p&gt;7. If it fails then we should get a person instance assigned to the view that has not been saved.&lt;/p&gt;


	&lt;p&gt;And that’s it.&lt;/p&gt;


	&lt;p&gt;You don’t want to get into what params are being assinged to the person model on the new action, you don’t want to get into if the person model receives the wrong number of values for the new action, or anything like that.&lt;/p&gt;


	&lt;p&gt;Why? Because what the model does with the params is really no business of the controller.  It is not the controller’s responsibility.  All the controller wants to know is &lt;strong&gt;“Did it save or not?”&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;In fact, I would argue that no where in your spec for the controller would you have  ”@person.should_receive(:save).with(some_params).and_return(true)”, no, it is implementation detail, evil.&lt;/p&gt;


	&lt;p&gt;Ideally (though this is hard to achieve in practice) you want to try and treat each executable code block as a black box in terms of describing behaviour.&lt;/p&gt;


	&lt;p&gt;You want to know “If I feed it &lt;span class="caps"&gt;XYZ&lt;/span&gt;, then the result will be &lt;span class="caps"&gt;ABC&lt;/span&gt;”.  You &lt;em&gt;don’t&lt;/em&gt; want to get into ‘If I feed it &lt;span class="caps"&gt;XYZ&lt;/span&gt;, then I need to make sure it will do A through Z so that I can then test to see if it actually did &lt;span class="caps"&gt;ABC&lt;/span&gt;’&lt;/p&gt;


	&lt;p&gt;See the difference?  The first viewpoint allows you to refactor away inside the discrete code block (the create action in this case), but the second requires your behaviour specification code know every minute detail about your code execution, and that my friends is about as brittle as a 10,000 line &lt;span class="caps"&gt;PHP&lt;/span&gt; page.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Use ‘shoulds’ for specifying behaviour and use ‘stubs’ for dictating code execution paths.&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;if you did that, your specs would look something like this:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;35&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;39&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;40&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;41&lt;tt&gt;
&lt;/tt&gt;42&lt;tt&gt;
&lt;/tt&gt;43&lt;tt&gt;
&lt;/tt&gt;44&lt;tt&gt;
&lt;/tt&gt;45&lt;tt&gt;
&lt;/tt&gt;46&lt;tt&gt;
&lt;/tt&gt;47&lt;tt&gt;
&lt;/tt&gt;48&lt;tt&gt;
&lt;/tt&gt;49&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;50&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;51&lt;tt&gt;
&lt;/tt&gt;52&lt;tt&gt;
&lt;/tt&gt;53&lt;tt&gt;
&lt;/tt&gt;54&lt;tt&gt;
&lt;/tt&gt;55&lt;tt&gt;
&lt;/tt&gt;56&lt;tt&gt;
&lt;/tt&gt;57&lt;tt&gt;
&lt;/tt&gt;58&lt;tt&gt;
&lt;/tt&gt;59&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;60&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;61&lt;tt&gt;
&lt;/tt&gt;62&lt;tt&gt;
&lt;/tt&gt;63&lt;tt&gt;
&lt;/tt&gt;64&lt;tt&gt;
&lt;/tt&gt;65&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;describe &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;create action&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;doing_a_successful_save&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@person&lt;/span&gt; = mock_model(&lt;span class="co"&gt;Person&lt;/span&gt;, &lt;span class="sy"&gt;:save&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;true&lt;/span&gt;, &lt;span class="sy"&gt;:new_record?&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;false&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="co"&gt;Person&lt;/span&gt;.stub!(&lt;span class="sy"&gt;:new&lt;/span&gt;).and_return(&lt;span class="iv"&gt;@person&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;doing_a_failed_save&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@person&lt;/span&gt; = mock_model(&lt;span class="co"&gt;Person&lt;/span&gt;, &lt;span class="sy"&gt;:save&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;false&lt;/span&gt;, &lt;span class="sy"&gt;:new_record?&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;true&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="co"&gt;Person&lt;/span&gt;.stub!(&lt;span class="sy"&gt;:new&lt;/span&gt;).and_return(&lt;span class="iv"&gt;@person&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  describe &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;successful request&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should flash a notice to the user that the create succeeded&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      doing_a_successful_save&lt;tt&gt;
&lt;/tt&gt;      post &lt;span class="sy"&gt;:create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      flash[&lt;span class="sy"&gt;:notice&lt;/span&gt;].should == &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Person was successfully created.&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;    it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should assign a person instance to the view&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      doing_a_successful_save&lt;tt&gt;
&lt;/tt&gt;      post &lt;span class="sy"&gt;:create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      assigns[&lt;span class="sy"&gt;:person&lt;/span&gt;].should == &lt;span class="iv"&gt;@person&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;    it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should render the show template for HTTP Request&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      doing_a_successful_save&lt;tt&gt;
&lt;/tt&gt;      post &lt;span class="sy"&gt;:create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      response.should render_template(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;show&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;    it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should render the create template for XH Request&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      doing_a_successful_save&lt;tt&gt;
&lt;/tt&gt;      xhr &lt;span class="sy"&gt;:post&lt;/span&gt;, &lt;span class="sy"&gt;:create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      response.should render_template(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;create&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;    it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should assign a saved person instance to the view&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      doing_a_successful_save&lt;tt&gt;
&lt;/tt&gt;      post &lt;span class="sy"&gt;:create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      assigns[&lt;span class="sy"&gt;:person&lt;/span&gt;].should_not be_new_record&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  describe &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;failed request&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should return the new template for HTTP Request&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      doing_a_failed_save&lt;tt&gt;
&lt;/tt&gt;      post &lt;span class="sy"&gt;:create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      response.should render_template(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;    it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should return the create template for Ajax Request&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      doing_a_failed_save&lt;tt&gt;
&lt;/tt&gt;      xhr &lt;span class="sy"&gt;:post&lt;/span&gt;, &lt;span class="sy"&gt;:create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      response.should render_template(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;create&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;    it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should not save the object&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      doing_a_failed_save&lt;tt&gt;
&lt;/tt&gt;      post &lt;span class="sy"&gt;:create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      assigns[&lt;span class="sy"&gt;:person&lt;/span&gt;].should be_new_record&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;&lt;span class="caps"&gt;BDD&lt;/span&gt; is a discipline.  Getting your head around it really starts with understanding the basic underlying principles of &lt;span class="caps"&gt;WHY&lt;/span&gt; you are doing it.&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;BDD&lt;/span&gt; stands for Behaviour Driven Development.  So stick with that and nothing more and you will find &lt;span class="caps"&gt;BDD&lt;/span&gt; a &lt;em&gt;lot&lt;/em&gt; easier to get done.&lt;/p&gt;


	&lt;p&gt;blogLater,&lt;/p&gt;


	&lt;p&gt;Mikel&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/321795788" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/6/28/tip-27-spec-a-behaviour-not-an-implementation</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-06-27:794</id>
    <published>2008-06-27T10:18:00Z</published>
    <updated>2008-06-27T09:42:07Z</updated>
    <category term="RSpec" />
    <category term="Ruby on Rails" />
    <category term="Ruby on Rails Tips" />
    <link href="http://feeds.feedburner.com/~r/lindsaar-net/~3/321389754/tip-26-start-small" rel="alternate" type="text/html" />
    <title>Tip #26 - Start Small</title>
<summary type="html">&lt;p&gt;If you are getting frustrated with RSpec, then you have probably skipped a gradient.  Start smaller!&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;If you are getting frustrated with RSpec, then you have probably skipped a gradient.  Start smaller!&lt;/p&gt;
&lt;p&gt;When I was trying to teach a co-worker how to write specs, I ran into a gradient problem.  He was trying to write specs for an existing app and controller setup that had the usual create action in the controller, it also had a before filter checking logins and timezones, the controller action was simple enough, something like this:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="iv"&gt;@person&lt;/span&gt; = &lt;span class="co"&gt;Person&lt;/span&gt;.new(params[&lt;span class="sy"&gt;:person&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  respond_to &lt;span class="r"&gt;do&lt;/span&gt; |format|&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;if&lt;/span&gt; &lt;span class="iv"&gt;@person&lt;/span&gt;.save&lt;tt&gt;
&lt;/tt&gt;      flash[&lt;span class="sy"&gt;:notice&lt;/span&gt;] = &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Person was successfully created.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      format.html { redirect_to(&lt;span class="iv"&gt;@person&lt;/span&gt;) }&lt;tt&gt;
&lt;/tt&gt;      format.js&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      format.html { render &lt;span class="sy"&gt;:action&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;      format.js&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Now, if you are really starting out, don’t start with this.  Start with something &lt;span class="caps"&gt;MUCH&lt;/span&gt; simpler… maybe like this:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;new&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;That would be a good gradient :)&lt;/p&gt;


	&lt;p&gt;No, seriously, if you just “don’t get RSpec”, then you skipped a gradient or went past something you don’t understand. Go back to an earlier gradient and come forward again.&lt;/p&gt;


	&lt;p&gt;I can say without a doubt that the #1 problem that new RSpec users have is code that tries to do too much.&lt;/p&gt;


	&lt;p&gt;Let the code evolve step by step from &lt;span class="caps"&gt;NOTHING&lt;/span&gt; and then come forward, the RSpec webpage has it right when it says “take very small steps”.&lt;/p&gt;


	&lt;p&gt;The skipped gradient problem is hard enough for experienced RSpec coders trying to fix an existing broken spec, but for someone who hasn’t understood the basics of how RSpec works, it is simply a killer.  You don’t want to be wondering if your use of response.should have_tag(‘div’, 2) is correct when all the specs are not working and you have red failing tests everywhere… “Thar b’ dragn’s thar matey!”&lt;/p&gt;


	&lt;p&gt;If you run into this problem, then go make a new scratch app and start specing it from the ground up, with minimal code generation.&lt;/p&gt;


	&lt;p&gt;Something like this:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;baci:test mikel$ ./script/generate rspec_controller welcome &lt;tt&gt;
&lt;/tt&gt;      exists  app/controllers/&lt;tt&gt;
&lt;/tt&gt;      exists  app/helpers/&lt;tt&gt;
&lt;/tt&gt;      create  app/views/welcome&lt;tt&gt;
&lt;/tt&gt;      exists  spec/controllers/&lt;tt&gt;
&lt;/tt&gt;      exists  spec/helpers/&lt;tt&gt;
&lt;/tt&gt;      create  spec/views/welcome&lt;tt&gt;
&lt;/tt&gt;      create  spec/controllers/welcome_controller_spec.rb&lt;tt&gt;
&lt;/tt&gt;      create  spec/helpers/welcome_helper_spec.rb&lt;tt&gt;
&lt;/tt&gt;      create  app/controllers/welcome_controller.rb&lt;tt&gt;
&lt;/tt&gt;      create  app/helpers/welcome_helper.rb&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Now go into the spec/controllers/welcome_controller_spec.rb and check it out:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;require &lt;span class="co"&gt;File&lt;/span&gt;.expand_path(&lt;span class="co"&gt;File&lt;/span&gt;.dirname(&lt;span class="pc"&gt;__FILE__&lt;/span&gt;) + &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;/../spec_helper&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;describe &lt;span class="co"&gt;WelcomeController&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;#Delete this example and add some real ones&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should use WelcomeController&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    controller.should be_an_instance_of(&lt;span class="co"&gt;WelcomeController&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Your standard RSpec template.  This is good enough to start.  We are going to build a welcome page here, so lets write our first spec:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;describe &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;getting the home page of the site&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should be a success&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    get &lt;span class="sy"&gt;:index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    response.should be_success&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;And stop &lt;span class="caps"&gt;RIGHT THERE&lt;/span&gt; and run your specs, it will fail because no index action or template exists yet.  Once it has failed, do the next smallest thing that could possibly pass.  Write an empty index action:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;WelcomeController&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;And then run your specs, it will now pass.  Good!  Now you can start building on that stable datum of ‘it is passing now, if I add this &lt;em&gt;one&lt;/em&gt; thing it should fail, then if I code this &lt;em&gt;one&lt;/em&gt; thing, then it will pass again.’&lt;/p&gt;


	&lt;p&gt;While I am at it, ban the script/generate rspec_scaffold command from your development vocabulary until you know how to do every step in the code that the scaffold generates (and even then, the use is questionable).  The great thing that the scaffold does is provide examples.  If you are new to RSpec, you might be tempted to use the scaffold, I would recommend instead to make a scratch up, and use the scaffold there, and then use the code examples step by step in your own app building up your own specs.&lt;/p&gt;


	&lt;p&gt;This will give you a &lt;em&gt;much&lt;/em&gt; broader understanding of how RSpec works.&lt;/p&gt;


	&lt;p&gt;Trying to spec some huge pre-existing code block as your introduction to RSpec is not impossible, but it is a pretty steep gradient and will result in more hair loss than passing specs.&lt;/p&gt;


	&lt;p&gt;blogLater&lt;/p&gt;


	&lt;p&gt;Mikel&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/321389754" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/6/27/tip-26-start-small</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-06-26:793</id>
    <published>2008-06-26T10:16:00Z</published>
    <updated>2008-06-26T04:37:50Z</updated>
    <category term="RSpec" />
    <category term="Ruby on Rails Tips" />
    <link href="http://feeds.feedburner.com/~r/lindsaar-net/~3/320859540/tip-25-rspec-tip" rel="alternate" type="text/html" />
    <title>Tip #25 - Logging is your friend...</title>
<summary type="html">&lt;p&gt;Sometimes when you need someone to just look over your code and figure out what the heck is going on, you can turn to your best coding friend, this friend sits away in the log directory carefully collecting data waiting for your beck and call…&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Sometimes when you need someone to just look over your code and figure out what the heck is going on, you can turn to your best coding friend, this friend sits away in the log directory carefully collecting data waiting for your beck and call…&lt;/p&gt;
&lt;h3&gt;Watch your log files.&lt;/h3&gt;


	&lt;p&gt;This should sort of be obvious, but I know several people (including yours truly) who have been bitten by this one.&lt;/p&gt;


	&lt;p&gt;When you are running your specifications, keep a ‘tail -f log/test.log’ running.  If you are on Windows and can’t do this, then either install cygwin so that you can, or make your system dual boot with Ubuntu or something so you can.&lt;/p&gt;


	&lt;p&gt;The logs will tell you a huge amount about what your app is trying to do when.  This is especially true if you get a controller spec response along the lines of:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;1)&lt;tt&gt;
&lt;/tt&gt;'PeopleController handling GET /people should render index template' FAILED&lt;tt&gt;
&lt;/tt&gt;expected &amp;quot;index&amp;quot;, got nil&lt;tt&gt;
&lt;/tt&gt;./spec/controllers/people_controller_spec.rb:54:&lt;tt&gt;
&lt;/tt&gt;script/spec:4:&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;2)&lt;tt&gt;
&lt;/tt&gt;'PeopleController handling GET /people/new should render new template' FAILED&lt;tt&gt;
&lt;/tt&gt;expected &amp;quot;new&amp;quot;, got nil&lt;tt&gt;
&lt;/tt&gt;./spec/controllers/people_controller_spec.rb:60:&lt;tt&gt;
&lt;/tt&gt;script/spec:4:&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;I expected the new template, but got nil… not very helpful…&lt;/p&gt;


	&lt;p&gt;But in the logs, the truth appears:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;Processing PeopleController#index (for 0.0.0.0 at 2008-06-25 09:15:28) [GET]&lt;tt&gt;
&lt;/tt&gt;  Session ID: &lt;tt&gt;
&lt;/tt&gt;  Parameters: {&amp;quot;action&amp;quot;=&amp;gt;&amp;quot;index&amp;quot;, &amp;quot;controller&amp;quot;=&amp;gt;&amp;quot;people&amp;quot;}&lt;tt&gt;
&lt;/tt&gt;Filter chain halted as [:must_login] rendered_or_redirected.&lt;tt&gt;
&lt;/tt&gt;Completed in &amp;lt;snip&amp;gt; | 200 OK [http://test.host/people]&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;Processing PeopleController#index (for 0.0.0.0 at 2008-06-25 09:15:28) [GET]&lt;tt&gt;
&lt;/tt&gt;  Session ID: &lt;tt&gt;
&lt;/tt&gt;  Parameters: {&amp;quot;action&amp;quot;=&amp;gt;&amp;quot;new&amp;quot;, &amp;quot;controller&amp;quot;=&amp;gt;&amp;quot;people&amp;quot;}&lt;tt&gt;
&lt;/tt&gt;Filter chain halted as [:must_login] rendered_or_redirected.&lt;tt&gt;
&lt;/tt&gt;Completed in &amp;lt;snip&amp;gt; | 200 OK [http://test.host/people]&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Ahh!  Filter chain halted as the must_login method returned false!  So we forgot to log in before we went to try and get the controller action.&lt;/p&gt;


	&lt;p&gt;Simple example, I know… but aren’t all the good tips simple?&lt;/p&gt;


	&lt;p&gt;Mikel&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/320859540" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/6/26/tip-25-rspec-tip</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-06-24:767</id>
    <published>2008-06-24T14:37:00Z</published>
    <updated>2008-06-29T23:58:47Z</updated>
    <category term="RSpec" />
    <category term="Ruby on Rails" />
    <category term="Ruby on Rails Tips" />
    <link href="http://feeds.feedburner.com/~r/lindsaar-net/~3/318972204/tip-24-being-clever-in-specs-is-for-dummies" rel="alternate" type="text/html" />
    <title>Tip #24 - Being clever in specs is for dummies</title>
<summary type="html">&lt;p&gt;This tip is coming to you from a frustrated developer having to read someone else’s specs….&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;This tip is coming to you from a frustrated developer having to read someone else’s specs….&lt;/p&gt;
&lt;p&gt;RSpec is a wonderful tool.&lt;/p&gt;


	&lt;p&gt;In the right hands, it makes behavior driven development almost natural.  It definitely makes producing readable specifications possible and allows you to stop focusing and worrying about writing your specifications, and just get on with life and livingness.&lt;/p&gt;


	&lt;p&gt;Another wonderful tool is the &lt;span class="caps"&gt;DRY&lt;/span&gt; principle.&lt;/p&gt;


	&lt;p&gt;The idea of the &lt;span class="caps"&gt;DRY&lt;/span&gt; (Don’t Repeat Yourself) principle is that every datum in your system that you are programming, and every procedure, should be defined and delimited to one location in your code / system structure.  This is a wonderful principle that allows you later to make changes to your code with simplicity and aplomb, as you only have to look in location A to find all the code relating to A.  You don’t have to look in A, then repeat your change 15 times in different locations in A all to fix one small part of the code.&lt;/p&gt;


	&lt;p&gt;You know unDRY code, you have all seen it.  It’s like someone crossed a big 1980’s &lt;span class="caps"&gt;BASIC&lt;/span&gt; for loop with a code generator and let it loose in your app folder.  It isn’t pretty and it is a pain to maintain.&lt;/p&gt;


	&lt;p&gt;However…&lt;/p&gt;


	&lt;p&gt;Being crispy &lt;span class="caps"&gt;DRY&lt;/span&gt; is the &lt;span class="caps"&gt;WRONG&lt;/span&gt; tool to apply to writing &lt;span class="caps"&gt;SPECS&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;What do I mean?&lt;/p&gt;


	&lt;p&gt;Well, consider this (simple) controller example:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should redirect if we are not logged in&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  get &lt;span class="sy"&gt;:index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  response.should redirect_to login_path&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Simple, this just ensures that the response from the server when we are requesting the index action in the current controller will be a redirect to the login page.&lt;/p&gt;


	&lt;p&gt;Now, we keep coding and we get:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should redirect if we are not logged in&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  get &lt;span class="sy"&gt;:index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  response.should redirect_to login_path&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should let us see the index if we are logged in&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  session[&lt;span class="sy"&gt;:logged_in&lt;/span&gt;] = &lt;span class="pc"&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  session[&lt;span class="sy"&gt;:user_id&lt;/span&gt;] = &lt;span class="i"&gt;99&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  get &lt;span class="sy"&gt;:index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  response.should be_success&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should render the index template if we are logged in&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  session[&lt;span class="sy"&gt;:logged_in&lt;/span&gt;] = &lt;span class="pc"&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  session[&lt;span class="sy"&gt;:user_id&lt;/span&gt;] = &lt;span class="i"&gt;99&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  get &lt;span class="sy"&gt;:index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  response.should render_template(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;people/index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Now, this is where the &lt;span class="caps"&gt;DRY&lt;/span&gt;-o-meter in your head starts going, “Err… Mikel, are you on drugs or what, why not put that logged in thing into a before call?!”&lt;/p&gt;


	&lt;p&gt;Why?  Well, I think it is the wrong place for it, but to humour you, lets try that:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;describe &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;when not logged in&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should redirect if we are not logged in&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    get &lt;span class="sy"&gt;:index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    response.should redirect_to login_path&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;describe &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;when logged in&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  before(&lt;span class="sy"&gt;:each&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    session[&lt;span class="sy"&gt;:logged_in&lt;/span&gt;] = &lt;span class="pc"&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    session[&lt;span class="sy"&gt;:user_id&lt;/span&gt;] = &lt;span class="i"&gt;99&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should be a success&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    get &lt;span class="sy"&gt;:index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    response.should be_success&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should show the index template&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    get &lt;span class="sy"&gt;:index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    response.should render_template(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;people/index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;OK, now you &lt;span class="caps"&gt;DRY&lt;/span&gt;-gurus can cast an evaluative eye over that and grant it a stamp of approval.. except (you all say) that get :index is a bit of a give away, can’t we put that in the before call as well?&lt;/p&gt;


	&lt;p&gt;Well….err… yeah… I guess so… lets try that:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;describe &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;when not logged in&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should redirect if we are not logged in&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    get &lt;span class="sy"&gt;:index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    response.should redirect_to login_path&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;describe &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;when logged in&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  before(&lt;span class="sy"&gt;:each&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    session[&lt;span class="sy"&gt;:logged_in&lt;/span&gt;] = &lt;span class="pc"&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    session[&lt;span class="sy"&gt;:user_id&lt;/span&gt;] = &lt;span class="i"&gt;99&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    get &lt;span class="sy"&gt;:index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should be a success&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    response.should be_success&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should render the index template&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    response.should render_template(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;people/index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;THERE&lt;/span&gt;!&lt;/strong&gt; you shout, &lt;strong&gt;&lt;span class="caps"&gt;THAT IS DRY&lt;/span&gt;!&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;And you are right, it is &lt;span class="caps"&gt;DRY&lt;/span&gt;, nothing is repeated.&lt;/p&gt;


	&lt;p&gt;But you know what?  It is also unmaintainable and will be a nightmare in a few months when you look back on it.&lt;/p&gt;


	&lt;p&gt;Right now, it isn’t a problem, after all, it is only 22 lines of code and you can see everything, but sooner or later, that controller spec could get up to a few hundred lines line, and then you, my dry friend, are up the &lt;span class="caps"&gt;DRY&lt;/span&gt; creek without so much as a paddle.  Because when you go to fix the line ‘it should redirect if we are not logged in’, you are going to have to go hunting up through the before call chain (which could be several levels deep) keeping track of instance variables, session state and any other cobweb that has been inserted in there, and find what in blazes is going on.&lt;/p&gt;


	&lt;p&gt;Of course the above example is simplistic.  But I am sure you can agree that looking at a spec that tells you &lt;span class="caps"&gt;NOTHING&lt;/span&gt; about the context or scope it is running in is useful for a computer, and saves some hard drive space, but basically useless for you, and really, that is who matters, the programmer.&lt;/p&gt;


	&lt;p&gt;Here is a tip:&lt;/p&gt;


	&lt;p&gt;Before calls are to set up and clean up your testing environment, they are not there to setup up your testing expectations&lt;/p&gt;


	&lt;p&gt;Valid use of a before call?  Making sure some directories that you are about to create in a test suite are not there.  Valid use of an after call?  Ensuring that the directories you made in the test suite are no longer there.&lt;/p&gt;


	&lt;p&gt;That is, anything that your program is not designed to handle or is not part of the specification, can go into the before or after calls….&lt;/p&gt;


	&lt;p&gt;N-O-T-H-I-N-G&amp;nbsp;&amp;nbsp;&amp;nbsp;E-L-S-E&lt;/p&gt;


	&lt;p&gt;Get the drift?&lt;/p&gt;


	&lt;p&gt;It might seem harsh, but believe me, you will thank me when you are 6 months down the track and come back to it…&lt;/p&gt;


	&lt;p&gt;So, if you can’t use before and after, what are you to do?  Well, the simple solution is to explicitly call inline helper methods… lets refactor our code above:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;describe &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;when not logged in&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should redirect if we are not logged in&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    get &lt;span class="sy"&gt;:index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    response.should redirect_to login_path&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;describe &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;when logged in&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;given_a_logged_in_user&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    session[&lt;span class="sy"&gt;:logged_in&lt;/span&gt;] = &lt;span class="pc"&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    session[&lt;span class="sy"&gt;:user_id&lt;/span&gt;] = &lt;span class="i"&gt;99&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should let be a success&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    given_a_logged_in_user&lt;tt&gt;
&lt;/tt&gt;    get &lt;span class="sy"&gt;:index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    response.should be_success&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should render the index template&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    given_a_logged_in_user&lt;tt&gt;
&lt;/tt&gt;    get &lt;span class="sy"&gt;:index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    response.should render_template(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;people/index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;There.&lt;/p&gt;


	&lt;p&gt;Now, we have added 3 lines of code and made it &lt;strong&gt;much&lt;/strong&gt; clearer.  Why?  Because now you don’t have to make the mental note of ‘oh, before this spec runs, I set the session params to log in the user’ instead, it is right there in the spec.&lt;/p&gt;


	&lt;p&gt;I have taken the given syntax from Story running, I like it.  And further, you can just read that code.&lt;/p&gt;


	&lt;p&gt;When you come back to it in 6 months, you can look at it and instantly see what is going on, with &lt;span class="caps"&gt;NOTHING&lt;/span&gt; left out.&lt;/p&gt;


	&lt;p&gt;Anyway, end of rant…  I’m off to refactor some 4 deep nested before calls….&lt;/p&gt;


	&lt;p&gt;blogLater&lt;/p&gt;


	&lt;p&gt;Mikel&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/318972204" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/6/24/tip-24-being-clever-in-specs-is-for-dummies</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-06-21:745</id>
    <published>2008-06-21T08:50:00Z</published>
    <updated>2008-06-23T23:59:35Z</updated>
    <category term="PostgreSQL" />
    <category term="Ruby on Rails" />
    <category term="Ruby on Rails Tips" />
    <link href="http://feeds.feedburner.com/~r/lindsaar-net/~3/316790295/tip-23-know-your-fundamentals" rel="alternate" type="text/html" />
    <title>Tip #23 - Know your fundamentals</title>
<summary type="html">&lt;p&gt;You would expect any professional to know their stuff, for a Ruby on Rails beginner, this is no less important.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;You would expect any professional to know their stuff, for a Ruby on Rails beginner, this is no less important.&lt;/p&gt;
&lt;p&gt;One of the things I run into quite a bit is people simply not knowing enough about the underlying model of their database.  Getting them to understand a has many through object relationship, is not going to get very far if they don’t know how an &lt;span class="caps"&gt;SQL&lt;/span&gt; database represents this.&lt;/p&gt;


	&lt;p&gt;Basics are what will make or break you as a programmer.  You can know all the syntactic sugary beliefs out there, but without some hard won understanding of basic principles, you will be out in the cold as soon as some part of the program breaks in a new and unusual way.&lt;/p&gt;


	&lt;p&gt;Each subject has it’s basic fundamentals.  For my Ruby programming, the fundamentals are defined in several key books (like the Pickaxe and the Ruby Programming Language and Design Patterns in Ruby).  For Rails, you can’t really go past Agile Development and the Rails Way for key points.  Each of these become like a ‘Bible’ to you when you are coding.  Each programmer has their bible, it is interesting even that it is called a Bible, as in Christianity, the fundamentals of that belief system is contained in a book &lt;span class="caps"&gt;CALLED&lt;/span&gt; the Bible.  My religion has a set of books that contain our core beliefs, we call them collectively, ‘&lt;a href="http://www.bridgepub.com/list/index.html"&gt;The Basics&lt;/a&gt;’.&lt;/p&gt;


	&lt;p&gt;But a lot of Rails folks in their misguided ‘coding &lt;span class="caps"&gt;SQL&lt;/span&gt; is evil’ forget that underneath all that pretty ActiveRecord sugar are real, cold blooded, raw, writing &lt;span class="caps"&gt;SQL&lt;/span&gt; queries, automagically generated by our core team friends to attempt to leach from our databases the data we and our application so desperately need.&lt;/p&gt;


	&lt;p&gt;It’s all well and good to be able to type ‘person.phones’ and get an array containing all the phone numbers belonging to that person, but if you don’t know that in executing that statement, that an equivalent &lt;span class="caps"&gt;SQL&lt;/span&gt; query approximating “SELECT * phones &lt;span class="caps"&gt;WHERE&lt;/span&gt; person_id = 2;” is occuring, you my friend are in for some nasty surprises.&lt;/p&gt;


	&lt;p&gt;Just like me when I first discovered the has many through, I promptly made a call like paragraph.chapter.book.genre.words and wondered why my DB came to a screeching, painful halt, and my ruby instance blew straight through the available &lt;span class="caps"&gt;RAM&lt;/span&gt; and started playing friendly with my swap space… I did not understand what all those queries were doing and did not thinking with the size of the resulting dataset.  The &lt;span class="caps"&gt;LEFT OUTER JOINS&lt;/span&gt; came to bite me… quite hard.&lt;/p&gt;


	&lt;p&gt;But &lt;span class="caps"&gt;SQL&lt;/span&gt; is a dry subject, not &lt;a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself"&gt;&lt;span class="caps"&gt;DRY&lt;/span&gt;&lt;/a&gt; that is, far from it actually, more like a moist sponge, but it is dry in that most of the materials you have to learn it are bland and quite factually boring.&lt;/p&gt;


	&lt;p&gt;But I found this book online, it has been around for a bit, I am not the first to discover it, but it is an introduction to &lt;span class="caps"&gt;SQL&lt;/span&gt; that I think almost any Rails developer should read.  It covers the basics, where &lt;span class="caps"&gt;RDBMS&lt;/span&gt;’s came from, why you need two apostrophes to get one and how using &lt;span class="caps"&gt;SQL&lt;/span&gt; will get you better dates.&lt;/p&gt;


	&lt;p&gt;So I thoroughly recommend it.  Head over to &lt;a href="http://philip.greenspun.com/sql/"&gt;&lt;span class="caps"&gt;SQL&lt;/span&gt; for Web Nerds&lt;/a&gt; and have a good read.&lt;/p&gt;


	&lt;p&gt;blogLater&lt;/p&gt;


	&lt;p&gt;Mikel&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/316790295" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/6/21/tip-23-know-your-fundamentals</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-06-17:714</id>
    <published>2008-06-17T08:42:00Z</published>
    <updated>2008-06-25T08:47:16Z</updated>
    <category term="Ruby" />
    <link href="http://feeds.feedburner.com/~r/lindsaar-net/~3/313667406/convert-visual-basic-microsoft-long-integer-color-values-to-css-rgb-format" rel="alternate" type="text/html" />
    <title>Convert Visual Basic / Microsoft Long Integer Color Values to CSS RGB Format</title>
<content type="html">
            &lt;p&gt;Here is how to convert the microsoft way of storing color values (which looks like 16777215 for white) into the familiar &lt;span class="caps"&gt;RGB CSS&lt;/span&gt; style &lt;span class="caps"&gt;HEX&lt;/span&gt; values (which look like #FFFFFF) in Ruby.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;long_to_rgb_hex_string&lt;/span&gt;(val)&lt;tt&gt;
&lt;/tt&gt;  r = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;%x&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; % (val % &lt;span class="i"&gt;256&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  g = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;%x&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; % ((val / &lt;span class="i"&gt;256&lt;/span&gt;) % &lt;span class="i"&gt;256&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  b = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;%x&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; % ((val / &lt;span class="i"&gt;65536&lt;/span&gt;) % &lt;span class="i"&gt;256&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + [r,g,b].collect { |c| c.to_s.ljust(&lt;span class="i"&gt;2&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)}.to_s&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;long_to_rgb_hex_string(&lt;span class="i"&gt;2093422&lt;/span&gt;) &lt;span class="c"&gt;# =&amp;gt; #6ef11f&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Or Grant Hutchins gave this as an option from the comments:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;long_to_rgb_hex_string&lt;/span&gt;(val)&lt;tt&gt;
&lt;/tt&gt;  sprintf(&lt;span class="er"&gt;’&lt;/span&gt;&lt;span class="c"&gt;#%06x’, val)&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Any other good options? :)&lt;/p&gt;


	&lt;p&gt;blogLater&lt;/p&gt;


	&lt;p&gt;Mikel&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/313667406" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/6/17/convert-visual-basic-microsoft-long-integer-color-values-to-css-rgb-format</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-06-07:660</id>
    <published>2008-06-07T11:11:00Z</published>
    <updated>2008-06-07T11:12:48Z</updated>
    <link href="http://feeds.feedburner.com/~r/lindsaar-net/~3/306736910/it-s-amazing-what-you-find" rel="alternate" type="text/html" />
    <title>It's amazing what you find...</title>
<summary type="html">&lt;p&gt;When you go looking for a postgres module for puppet…&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;When you go looking for a postgres module for puppet…&lt;/p&gt;
&lt;p&gt;Check this out…&lt;/p&gt;


	&lt;p&gt;I think it is a world wide critical problem…&lt;/p&gt;


	&lt;p&gt;The &lt;a href="http://web.mit.edu/people/marthag/smarties-ticket"&gt;Smarties Ticket&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;blogLater&lt;/p&gt;


	&lt;p&gt;Mikel&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/306736910" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/6/7/it-s-amazing-what-you-find</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-06-06:640</id>
    <published>2008-06-06T00:16:00Z</published>
    <updated>2008-06-06T00:21:00Z</updated>
    <category term="RSpec" />
    <category term="Ruby on Rails" />
    <link href="http://feeds.feedburner.com/~r/lindsaar-net/~3/305690454/rspec-story-xhr-problem" rel="alternate" type="text/html" />
    <title>RSpec Story xhr problem </title>
<summary type="html">&lt;p&gt;If you are using RSpec stories (and if you are not, why not?) you might run into this little problem. doing an xhr :post returns ArgumentError: wrong number of arguments (4 for 3)&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;If you are using RSpec stories (and if you are not, why not?) you might run into this little problem. doing an xhr :post returns ArgumentError: wrong number of arguments (4 for 3)&lt;/p&gt;
&lt;p&gt;This happens on a simple story like this:&lt;/p&gt;


	&lt;p&gt;When “I submit a search name” do
  xhr :post, ’/searches’, {:search =&amp;gt; {:given_name =&amp;gt; “bob”, :family_name =&amp;gt; “smith”}}
end&lt;/p&gt;


	&lt;p&gt;You will get in your story output, something like this:&lt;/p&gt;


	&lt;p&gt;ArgumentError: wrong number of arguments (4 for 3)
stories/searching_story_spec.rb:45 in “I submit a search name”&lt;/p&gt;


	&lt;p&gt;But if you look in the above xhr method, I am only using 3 arguments, (1) a symbol [:post], (2) a string [’/searches’] and a hash [{:search =&amp;gt; {:given_name =&amp;gt; “bob”, :family_name =&amp;gt; “smith”}}]&lt;/p&gt;


	&lt;p&gt;What gives?!&lt;/p&gt;


	&lt;p&gt;Looking in the test.log file doesn’t help either, as no exception is raised (which is weird)&lt;/p&gt;


	&lt;p&gt;Asking on the RSpec mailing list, &lt;a href="http://www.continuousthinking.com/"&gt;Zach Dennis&lt;/a&gt; was good enough to give me the solution.&lt;/p&gt;


	&lt;p&gt;Use ‘xml_http_request’ instead.&lt;/p&gt;


	&lt;p&gt;Apparently, there is some problem with xhr being aliased to the wrong method somewhere internally…&lt;/p&gt;


	&lt;p&gt;Anyway, hope this helps!&lt;/p&gt;


	&lt;p&gt;Mikel&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/305690454" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/6/6/rspec-story-xhr-problem</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-06-05:635</id>
    <published>2008-06-05T12:20:00Z</published>
    <updated>2008-06-05T12:24:15Z</updated>
    <category term="Ruby" />
    <category term="Ruby on Rails" />
    <category term="Ruby on Rails Tips" />
    <link href="http://feeds.feedburner.com/~r/lindsaar-net/~3/305305006/tip-22-how-to-ask-a-question-about-rails" rel="alternate" type="text/html" />
    <title>Tip #22 - How to ask a question about Rails</title>
<summary type="html">&lt;p&gt;This tip actually applies to every open source project out there… it is, how do you ask a question that will get you the maximum chance of a good answer?&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;This tip actually applies to every open source project out there… it is, how do you ask a question that will get you the maximum chance of a good answer?&lt;/p&gt;
&lt;p&gt;The most successful thing I have found, is to make sure you convey that you have looked for the answer intelligently, and also attempted to resolve the problem in question to the best of your ability.&lt;/p&gt;


	&lt;p&gt;You should also show the code snippet in question, or if it is something you are bugged on, the basic steps you took to debug the problem.&lt;/p&gt;


	&lt;p&gt;If you do this, and then ask, you will be more likely to get an answer.&lt;/p&gt;


	&lt;p&gt;Including that you attempted to find the answer on google with what search is also a good idea, as you will be less likely to get “Google ‘Your problem’” as the answer.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.catb.org/~esr/faqs/smart-questions.html"&gt;Here is an interesting write up&lt;/a&gt; by people who have been helping other people for a long time, it is one of those things that I recommend a lot of people to read, and so I’ll link it here as well.&lt;/p&gt;


	&lt;p&gt;blogLater&lt;/p&gt;


	&lt;p&gt;Mikel&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/305305006" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/6/5/tip-22-how-to-ask-a-question-about-rails</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-06-03:616</id>
    <published>2008-06-03T15:06:00Z</published>
    <updated>2008-06-03T15:07:32Z</updated>
    <category term="Ruby on Rails" />
    <category term="Ruby on Rails Tips" />
    <link href="http://feeds.feedburner.com/~r/lindsaar-net/~3/303798418/developer-info-on-every-page" rel="alternate" type="text/html" />
    <title>Tip #21 - Developer Info On Every Page</title>
<summary type="html">&lt;p&gt;When you are making a rails site, you sometimes need to get to the session hash or the params hash and see just what got sent back to the browser, but going in, editing the template and reloading is just a &lt;span class="caps"&gt;PITA&lt;/span&gt;, here is a quick tip that can help you have that (and any other) information no more than a click away, at any time, and any view….&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;When you are making a rails site, you sometimes need to get to the session hash or the params hash and see just what got sent back to the browser, but going in, editing the template and reloading is just a &lt;span class="caps"&gt;PITA&lt;/span&gt;, here is a quick tip that can help you have that (and any other) information no more than a click away, at any time, and any view….&lt;/p&gt;
&lt;p&gt;What we need to do is be able to show, on any page in our site, some quick Developer Information.&lt;/p&gt;


	&lt;p&gt;What I wanted is a little link at the bottom right of every page called “Developer Information” and if I click it, I get a screen popping up with all the information I need, that I could then hide away again.&lt;/p&gt;


	&lt;p&gt;I had a need for this on a site I was making, and in true Ruby style, I thought “What is the simplest thing that could work?”  Well, I think this is about it.&lt;/p&gt;


	&lt;p&gt;First, make a file in your /app/views/common_partials folder called ‘_developer_info.html.erb’&lt;/p&gt;


	&lt;p&gt;Into this, throw the following:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="ta"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="an"&gt;id&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;DevInShow&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="an"&gt;href&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;tt&gt;
&lt;/tt&gt;   &lt;span class="an"&gt;style&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;font-size:small;position:absolute;bottom:10px;right:10px&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;span class="an"&gt;onclick&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$('DevInfo').show(); $('DevInShow').hide();&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="ta"&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt; Show Developer Info&lt;span class="ta"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="ta"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="an"&gt;id&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;DevInfo&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;tt&gt;
&lt;/tt&gt;     &lt;span class="an"&gt;style&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;background:white;padding: 5px;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;            &lt;span class="k"&gt;border:10px solid red;position:absolute;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;            &lt;span class="k"&gt;top:0px;left:0px;display:none&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="ta"&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="an"&gt;href&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;tt&gt;
&lt;/tt&gt;     &lt;span class="an"&gt;onclick&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$('DevInfo').hide(); $('DevInShow').show();&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="ta"&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  Hide Developer Info&lt;span class="ta"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Params&lt;span class="ta"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;pre&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;&amp;lt;%= params.to_yaml %&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;/pre&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Session&lt;span class="ta"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;pre&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;&amp;lt;%= session.to_yaml %&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;/pre&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="an"&gt;href&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;tt&gt;
&lt;/tt&gt;        &lt;span class="an"&gt;onclick&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$('DevInfo').hide();$('DevInShow').show();&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="ta"&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  Hide Developer Info&lt;span class="ta"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="ta"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The above code sets up a hidden div in your view with a link at the bottom right.  When you click the link it makes the hidden div visible (which is absolutely positioned over the top of all your content) and gives you a link to click it away again.  Neat.&lt;/p&gt;


	&lt;p&gt;Now, to make all this Rails-foo goodness work, add the following to the very bottom of your application.html.erb file, just before the &amp;lt;/body&amp;gt; tag is good.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&amp;lt;&lt;span class="s"&gt;&lt;span class="dl"&gt;%-&lt;/span&gt;&lt;span class="k"&gt; if RAILS_ENV == &amp;quot;development&amp;quot; &lt;/span&gt;&lt;span class="dl"&gt;-&lt;/span&gt;&lt;/span&gt;%&amp;gt;&lt;tt&gt;
&lt;/tt&gt;  &amp;lt;%= render &lt;span class="sy"&gt;:partial&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;common_partials/developer_info&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;lt;%- end -%&lt;/span&gt;&lt;span class="dl"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This renders the developer info link, only in development mode, just to be safe :)&lt;/p&gt;


	&lt;p&gt;Of course, you will want to remove this from your pages when you go live, but it is really handy when you are debugging session or params movements in your code.&lt;/p&gt;


	&lt;p&gt;Enjoy!&lt;/p&gt;


	&lt;p&gt;blogLater&lt;/p&gt;


	&lt;p&gt;Mikel&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/303798418" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/6/3/developer-info-on-every-page</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-06-02:599</id>
    <published>2008-06-02T00:11:00Z</published>
    <updated>2008-06-02T00:17:41Z</updated>
    <link href="http://feeds.feedburner.com/~r/lindsaar-net/~3/302624728/and-now-for-something-completely-different" rel="alternate" type="text/html" />
    <title>And now for something completely different...</title>
<summary type="html">&lt;p&gt;Found this video clip while bouncing around the interwebs &amp;trade;&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Found this video clip while bouncing around the interwebs &amp;trade;&lt;/p&gt;
&lt;p&gt;It is a stop motion clip of the making of a stop motion clip…. spooky…. but very cool!&lt;/p&gt;


	&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&amp;lt;object height="282" width="500"&gt;    &amp;lt;param name="allowfullscreen" value="true" /&gt;    &amp;lt;param name="allowscriptaccess" value="always" /&gt;    &amp;lt;param name="movie" value="http://www.vimeo.com/moogaloop.swf?clip_id=739250&amp;amp;server=www.vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=0&amp;amp;show_portrait=0&amp;amp;color=ff9933&amp;amp;fullscreen=1" /&gt;    &amp;lt;embed allowfullscreen="true" type="application/x-shockwave-flash" src="http://www.vimeo.com/moogaloop.swf?clip_id=739250&amp;amp;server=www.vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=0&amp;amp;show_portrait=0&amp;amp;color=ff9933&amp;amp;fullscreen=1" allowscriptaccess="always" height="282" width="500"&gt;&amp;lt;/embed&gt;&amp;lt;/object&gt;

	&lt;p&gt;blogLater&lt;/p&gt;


	&lt;p&gt;Mikel&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/302624728" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/6/2/and-now-for-something-completely-different</feedburner:origLink></entry>
</feed>
