<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>lindsaar.net - Home</title>
  <id>tag:lindsaar.net,2009: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>2009-05-03T15:00:20Z</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" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2009-05-03:5743</id>
    <published>2009-05-03T14:59:00Z</published>
    <updated>2009-05-03T15:00:20Z</updated>
    <category term="Javascript" />
    <category term="Ruby on Rails" />
    <link href="http://feedproxy.google.com/~r/lindsaar-net/~3/fxFAGqyHsNo/always-getting-an-invalid-authenticity-token-error" rel="alternate" type="text/html" />
    <title>Always getting an invalid authenticity token error</title>
<summary type="html">&lt;p&gt;I had a Ruby on Rails app giving a bunch of invalid authenticity token errors.  I spent a while hunting down the solution until I found this write up.  Very useful.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;I had a Ruby on Rails app giving a bunch of invalid authenticity token errors.  I spent a while hunting down the solution until I found this write up.  Very useful.&lt;/p&gt;
&lt;p&gt;This write up was by &lt;a href="http://www.workingwithrails.com/person/5484-peter-de-berdt"&gt;Peter De Berdt&lt;/a&gt; on one of the Ruby mailing lists, I am putting it here more for my own future (maybe) reference as it is a very good solution for the situation I was running into.  The entire thread is at the &lt;a href="http://www.ruby-forum.com/topic/167917#751085"&gt;ruby forum site&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;If you have a situation where you are getting invalid authenticity tokens and are doing strange things with forms on your website with file uploads etc, and can’t for some reason just use the authenticity form helper, then this solution worked for me and should work for you too.&lt;/p&gt;


&lt;hr /&gt;

	&lt;p&gt;The solution is pretty simple to be honest:&lt;/p&gt;


	&lt;p&gt;In your view layout file, add this to the &amp;lt;header&gt; section:&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="ta"&gt;&amp;lt;script&lt;/span&gt; &lt;span class="an"&gt;type&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;text/javascript&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="an"&gt;charset&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;utf-8&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;    window._token = '&lt;span class="c"&gt;&amp;lt;%= form_authenticity_token -%&amp;gt;&lt;/span&gt;';&lt;tt&gt;
&lt;/tt&gt;&lt;span class="ta"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;In application.js, add 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;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;Ajax.Base.prototype.initialize = Ajax.Base.prototype.initialize.wrap(&lt;tt&gt;
&lt;/tt&gt;   &lt;span class="r"&gt;function&lt;/span&gt;(p, options){&lt;tt&gt;
&lt;/tt&gt;     p(options);&lt;tt&gt;
&lt;/tt&gt;     &lt;span class="pc"&gt;this&lt;/span&gt;.options.parameters = &lt;span class="pc"&gt;this&lt;/span&gt;.options.parameters || {};&lt;tt&gt;
&lt;/tt&gt;     &lt;span class="pc"&gt;this&lt;/span&gt;.options.parameters.authenticity_token = &lt;span class="pt"&gt;window&lt;/span&gt;._token || &lt;span class="s"&gt;&lt;span class="dl"&gt;'&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;);&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;It will automatically add the authenticity token to &lt;span class="caps"&gt;ALL&lt;/span&gt; ajax requests,
even those you invoke from custom code (graceful degrading and/or even
delegated events for example).&lt;/p&gt;


	&lt;p&gt;A similar solution for those swapping out Prototype with JQuery has
been posted &lt;a href="http://henrik.nyh.se/2008/05/rails-authenticity-token-with-jquery"&gt;here&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;As for file uploaders, a normal field within a form (multipart=true)
will be sent as part of the form (and isn’t an ajax request in the
first place) and shouldn’t be a problem. If you are using &lt;span class="caps"&gt;ANY&lt;/span&gt; other
“ajax” uploader, there’s more to it. I already posted several times on
how to get SWFUpload to play nicely with Rails, an overview with links
to the appropriate posts can be found &lt;a href="http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/45f70281a5992fa7"&gt;here.&lt;/a&gt;&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/fxFAGqyHsNo" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2009/5/3/always-getting-an-invalid-authenticity-token-error</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2009-01-06:2830</id>
    <published>2009-01-06T13:30:00Z</published>
    <updated>2009-01-06T13:32:51Z</updated>
    <link href="http://feedproxy.google.com/~r/lindsaar-net/~3/Q0uatC28pb4/windows-ipconfig-does-not-show-anything" rel="alternate" type="text/html" />
    <title>Windows ipconfig does not show anything</title>
<summary type="html">&lt;p&gt;I had a Windows XP system (service pack 2) that would only return “Windows IP configuration” and then nothing, no indication of network disconnection nothing, well, there’s a good fix for it.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;I had a Windows XP system (service pack 2) that would only return “Windows IP configuration” and then nothing, no indication of network disconnection nothing, well, there’s a good fix for it.&lt;/p&gt;
&lt;p&gt;The system wouldn’t pickup an IP address from &lt;span class="caps"&gt;DHCP&lt;/span&gt;, it was like it was just confused.&lt;/p&gt;


	&lt;p&gt;You can do the following at a &lt;span class="caps"&gt;CMD&lt;/span&gt; prompt to reset the network configurations:&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;C:\&amp;gt; netsh winsock reset catalog&lt;tt&gt;
&lt;/tt&gt;C:\&amp;gt; netsh int ip reset reset.log&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The first line resets all the &lt;span class="caps"&gt;WINSOCK&lt;/span&gt; entries to their defaults, the second line resets all the &lt;span class="caps"&gt;TCP&lt;/span&gt;/IP entries to their defaults.&lt;/p&gt;


	&lt;p&gt;The first one will ask you to reboot, don’t.  Do both commands and then reboot your system.&lt;/p&gt;


	&lt;p&gt;Once I did this, the computer got it’s &lt;span class="caps"&gt;DHCP&lt;/span&gt; address again quite happily.&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/Q0uatC28pb4" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2009/1/6/windows-ipconfig-does-not-show-anything</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2009-01-05:2819</id>
    <published>2009-01-05T20:18:00Z</published>
    <updated>2009-01-05T20:20:39Z</updated>
    <link href="http://feedproxy.google.com/~r/lindsaar-net/~3/-lQ67ft7Bsg/freebsd-rc-scripts" rel="alternate" type="text/html" />
    <title>FreeBSD rc scripts</title>
<summary type="html">&lt;p&gt;I’ve always wanted a concise practical guide to rc scripting in FreeBSD, well, &lt;a href="http://www.freebsd.org/doc/en/articles/rc-scripting/"&gt;here it is&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/-lQ67ft7Bsg" height="1" width="1"/&gt;</summary>  <feedburner:origLink>http://lindsaar.net/2009/1/5/freebsd-rc-scripts</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-11-24:2432</id>
    <published>2008-11-24T06:37:00Z</published>
    <updated>2008-11-24T06:41:42Z</updated>
    <link href="http://feedproxy.google.com/~r/lindsaar-net/~3/mdNoGsM3Ju4/how-to-monitor-a-logged-in-professional" rel="alternate" type="text/html" />
    <title>How to monitor a logged in professional</title>
<summary type="html">&lt;p&gt;Sometimes you will need to get a professional to log into your system to help you out.  You should watch what they do, and this is the easiest way I know.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Sometimes you will need to get a professional to log into your system to help you out.  You should watch what they do, and this is the easiest way I know.&lt;/p&gt;
&lt;p&gt;I needed to get someone from a hardware company to log into one of our phone servers to help debug a problem, but I wasn’t just about to give them full carte blanche access to my server.  Especially as it is behind a firewall.&lt;/p&gt;


	&lt;p&gt;I trust these guys somewhat, I mean, if they screw up, no more customer and hello to bad PR… but at the same time, you should always watch.&lt;/p&gt;


	&lt;p&gt;So, I went hunting around, and Screen is the best answer.&lt;/p&gt;


	&lt;p&gt;Get them to log into your system and type:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;$ screen -S support&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Then, from your shell:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;$ screen -x support&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;And bam, you are both sharing the same screen.&lt;/p&gt;


	&lt;p&gt;Nice and simple.&lt;/p&gt;


	&lt;p&gt;Of course, this isn’t fool proof, and it only really lets you follow what the other guy is doing.  But it is a hell of a lot better than sitting there blind listening on the phone to a few hundred key strokes wondering ‘what is he up to?’&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/mdNoGsM3Ju4" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/11/24/how-to-monitor-a-logged-in-professional</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-11-22:2415</id>
    <published>2008-11-22T16:35:00Z</published>
    <updated>2008-11-22T16:36:49Z</updated>
    <link href="http://feedproxy.google.com/~r/lindsaar-net/~3/SOf7GkjaijE/tmail-moves-to-git" rel="alternate" type="text/html" />
    <title>TMail Moves to GIT</title>
<summary type="html">&lt;p&gt;Social networking here we come!&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Social networking here we come!&lt;/p&gt;
&lt;p&gt;I have moved TMail onto &lt;span class="caps"&gt;GIT&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;You can &lt;a href="http://github.com/mikel/tmail/tree/master"&gt;see it here&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Please fork / patch / follow / help out :)&lt;/p&gt;


	&lt;p&gt;Mikel&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/SOf7GkjaijE" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/11/22/tmail-moves-to-git</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-11-20:2397</id>
    <published>2008-11-20T22:39:00Z</published>
    <updated>2008-11-20T22:48:48Z</updated>
    <link href="http://feedproxy.google.com/~r/lindsaar-net/~3/ECzzUwq1f9I/funny" rel="alternate" type="text/html" />
    <title>Funny...</title>
<summary type="html">&lt;p&gt;Some people think that rails is getting bloated… but through the hard efforts of core committers, the fluff and fat is getting sliced and trimmed down like a Döner kebab spit at a turkish festival…&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Some people think that rails is getting bloated… but through the hard efforts of core committers, the fluff and fat is getting sliced and trimmed down like a Döner kebab spit at a turkish festival…&lt;/p&gt;
&lt;p&gt;And here is the perfect example seen on Rails-Contrib on freenode last night:&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;GitHub142: rails: David Heinemeier Hansson 2-2-stable&lt;tt&gt;
&lt;/tt&gt;SHA1-9d8cc60&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;[19:07] GitHub142: Reduced the number of literal aliases to the&lt;tt&gt;
&lt;/tt&gt;range that has actually seen personal use. With the massive&lt;tt&gt;
&lt;/tt&gt;savings in overhead, I was able to fit Array#fourty_two&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Here’s the &lt;a href="http://is.gd/8oJA"&gt;commit&lt;/a&gt; if you are interested…&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/ECzzUwq1f9I" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/11/20/funny</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-11-02:2295</id>
    <published>2008-11-02T19:47:00Z</published>
    <updated>2008-11-02T19:49:37Z</updated>
    <link href="http://feedproxy.google.com/~r/lindsaar-net/~3/mm-WHuTdPUg/how-to-reset-a-sequence-with-postgresql" rel="alternate" type="text/html" />
    <title>How to reset a sequence with PostgreSQL</title>
<content type="html">
            &lt;p&gt;I would think 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;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;ALTER SEQUENCE sequence_name&lt;tt&gt;
&lt;/tt&gt;      RESTART WITH (SELECT max(id) FROM table_name);&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;would work, but it doesn’t.  Use:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;SELECT SETVAL('sequence_name', (SELECT MAX(id) FROM table_name) + 1);&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;instead and you will be a lot more happier.&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/mm-WHuTdPUg" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/11/2/how-to-reset-a-sequence-with-postgresql</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-11-01:2280</id>
    <published>2008-11-01T20:17:00Z</published>
    <updated>2008-11-01T20:19:29Z</updated>
    <link href="http://feedproxy.google.com/~r/lindsaar-net/~3/C13Hxt_9AOg/openbsd-raid-and-temp-sensors-on-hp-proliant-dl-360-and-380-series" rel="alternate" type="text/html" />
    <title>OpenBSD RAID and Temp Sensors on HP Proliant DL 360 and 380 Series</title>
<summary type="html">&lt;p&gt;I have a bunch of &lt;span class="caps"&gt;HP DL 360&lt;/span&gt; and &lt;span class="caps"&gt;DL 380&lt;/span&gt; servers that I run OpenBSD on as gateways.  This is how to monitor their &lt;span class="caps"&gt;RAID&lt;/span&gt; drive status and temperature status…&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;I have a bunch of &lt;span class="caps"&gt;HP DL 360&lt;/span&gt; and &lt;span class="caps"&gt;DL 380&lt;/span&gt; servers that I run OpenBSD on as gateways.  This is how to monitor their &lt;span class="caps"&gt;RAID&lt;/span&gt; drive status and temperature status…&lt;/p&gt;
&lt;p&gt;What you need to do is enable the &lt;span class="caps"&gt;IPMI&lt;/span&gt; driver.&lt;/p&gt;


	&lt;p&gt;If you read the man page, the &lt;span class="caps"&gt;IPMI&lt;/span&gt; driver provides an &lt;span class="caps"&gt;API&lt;/span&gt; like interface to the hardware it is running on.&lt;/p&gt;


	&lt;p&gt;This means you can query sysctl to get data 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;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;$ sysctl hw.sensors&lt;tt&gt;
&lt;/tt&gt;hw.sensors.acpitz0.temp0=8.35 degC (zone temperature)&lt;tt&gt;
&lt;/tt&gt;hw.sensors.ciss0.drive0=online (sd0), OK&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;If you then yank one of a mirror set you 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;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;$ sysctl hw.sensors.ciss0.drive0&lt;tt&gt;
&lt;/tt&gt;hw.sensors.ciss0.drive0=degraded (sd0), WARNING&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;If you then put a new drive back into the mirror set you 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;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;$ sysctl hw.sensors.ciss0.drive0&lt;tt&gt;
&lt;/tt&gt;hw.sensors.ciss0.drive0=rebuilding (sd0), WARNING&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Once the system has rebuilt, you 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;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;$ sysctl hw.sensors.ciss0.drive0&lt;tt&gt;
&lt;/tt&gt;hw.sensors.ciss0.drive0=online (sd0), OK&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Which is very useful and basic data needed for monitoring systems like Nagios.&lt;/p&gt;


	&lt;p&gt;There is a catch though, the &lt;span class="caps"&gt;IPMI&lt;/span&gt; driver is not enabled by default in OpenBSD &lt;span class="caps"&gt;GENERIC&lt;/span&gt; (at least at 4.4).  To enable it, you have two options.&lt;/p&gt;


	&lt;p&gt;At boot time, you can enable it by doing:&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;&amp;gt;&amp;gt; OpenBSD BOOT 640/31744 k [1.29]&lt;tt&gt;
&lt;/tt&gt;use ? for file list, or carriage return for defaults&lt;tt&gt;
&lt;/tt&gt;use hd(1,a)/bsd to boot sd0 when sd0 is also installed&lt;tt&gt;
&lt;/tt&gt;Boot: -c&lt;tt&gt;
&lt;/tt&gt;Booting...&lt;tt&gt;
&lt;/tt&gt;=======snip=======&lt;tt&gt;
&lt;/tt&gt;User Kernel Config&lt;tt&gt;
&lt;/tt&gt;UKC&amp;gt; enable ipmi&lt;tt&gt;
&lt;/tt&gt;441 ipmi0 enabled&lt;tt&gt;
&lt;/tt&gt;UKC&amp;gt; quit&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This will then boot normally and if everything worked, you’ll have an operational system that you can type the above commands in to query the status of your &lt;span class="caps"&gt;RAID&lt;/span&gt; set.&lt;/p&gt;


	&lt;p&gt;If it won’t start, then reboot without doing anything and it will go back to the way it was before, then contact openbsd misc with a copy of your dmesg.&lt;/p&gt;


	&lt;p&gt;If it all worked, you’ll probably want to enable this feature permanently, to do this, use the config(8) utility like so:&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;# config -u -o /bsd.new -e /bsd&lt;tt&gt;
&lt;/tt&gt;(tells you about the kernel)&lt;tt&gt;
&lt;/tt&gt;Enter 'help' for information&lt;tt&gt;
&lt;/tt&gt;ukc&amp;gt; enable ipmi&lt;tt&gt;
&lt;/tt&gt;441 ipmi0 enabled&lt;tt&gt;
&lt;/tt&gt;ukc&amp;gt; quit&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This then will produce an output file /bsd.new which is your new kernel.&lt;/p&gt;


	&lt;p&gt;To install the new kernel, 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;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;# cp /bsd /bsd-original &amp;amp;&amp;amp; cp -f /bsd.new /bsd&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;And then you can reboot to an &lt;span class="caps"&gt;IPMI&lt;/span&gt; enabled system.&lt;/p&gt;


	&lt;p&gt;Enjoy.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/lindsaar-net/~4/C13Hxt_9AOg" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/11/1/openbsd-raid-and-temp-sensors-on-hp-proliant-dl-360-and-380-series</feedburner:origLink></entry>
  <entry xml:base="http://lindsaar.net/">
    <author>
      <name>mikel</name>
    </author>
    <id>tag:lindsaar.net,2008-09-11:1912</id>
    <published>2008-09-11T10:40:00Z</published>
    <updated>2008-09-13T01:47:28Z</updated>
    <link href="http://feedproxy.google.com/~r/lindsaar-net/~3/qt-N3O4QNWU/terminator-timeout-without-mercy" rel="alternate" type="text/html" />
    <title>Terminator - Timeout without Mercy</title>
<summary type="html">&lt;p&gt;If you have been following my posts on Ruby-Talk and Ruby on Rails and even RSpec mailing list (and who wouldn’t?!  I mean, aside from my mother) then you would have noticed I have been banging my head against a brick wall on the subject of System calls not being handled by the Timeout libraries in Ruby…&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;If you have been following my posts on Ruby-Talk and Ruby on Rails and even RSpec mailing list (and who wouldn’t?!  I mean, aside from my mother) then you would have noticed I have been banging my head against a brick wall on the subject of System calls not being handled by the Timeout libraries in Ruby…&lt;/p&gt;
&lt;p&gt;I’ve done a lot of work with this.  I mean a lot.&lt;/p&gt;


	&lt;p&gt;So I thought I would share.&lt;/p&gt;


	&lt;p&gt;It all starts with a basic requirement I have, which is to replicate a data set from one side of the planet to the other.  This involves logging into a database server remotely using ActiveRecord across some encrypted VPNs, querying some tables, and then inside of a transaction, replicating down certain data on certain rows.&lt;/p&gt;


	&lt;p&gt;The solution I have works well, I can replicate about 2-5 rows per second across the link which is more than adequate (the dataset changes upto about 100 rows per minute).  The problem is that occasionally, ActiveRecord’s link to the remote database will hit a snag, then Ruby will wait, and wait, and wait to Timeout…. This can take hours, and in fact, sometimes, it never does timeout, leaving a zombie process.&lt;/p&gt;


	&lt;p&gt;To avoid multiple replication problems, I have lock files which prevent further copies of the replicator firing up if it detects that one is already running.&lt;/p&gt;


	&lt;p&gt;So, in the end, I get stuck with several replicators “running”, all hung, all waiting for a link to come back that never will, and no replication happening.  In the mean time, the rows are still changing and I am getting backlogged.  Leave it for a day and you are 80,000 rows backlogged and people start asking questions and I start looking for old travel tickets that I had ‘forgotten about’.&lt;/p&gt;


	&lt;p&gt;But why does ruby do this?&lt;/p&gt;


	&lt;p&gt;Shouldn’t the Timeout library protect us from such evilness?&lt;/p&gt;


	&lt;p&gt;Well, yes and no.  The problem is because ruby uses Green threads.  Green threads mean that there is only one real Ruby process running on the server, and it “internally” makes other “threads” that it schedules within the main ruby process’ kernel time.  Green threads are very efficient (they save a lot of context switching) but the problem is that if you get a System call that ‘blocks’, then the kernel will stop servicing your main ruby thread until your system call is complete, and &lt;span class="caps"&gt;THIS&lt;/span&gt; means that the little ‘Timeout.timeout(5) { my code }’ block you put in, will never get called…&lt;/p&gt;


	&lt;p&gt;And then you get a hang… forever.&lt;/p&gt;


	&lt;p&gt;I tried a couple of handlings, the first was the &lt;a href="http://ph7spot.com/articles/system_timer"&gt;SystemTimer&lt;/a&gt; library by Philippe Hanrigou.  This entry actually has a really good and simple example of what Green threads and blocking system calls mean. If you want to brush up, it is a good read.&lt;/p&gt;


	&lt;p&gt;But SystemTimer didn’t work.  It uses alarm signals which could have some problems.  But in my case, it didn’t work and I still got never ending timeouts.&lt;/p&gt;


	&lt;p&gt;So I asked again on the Ruby-Talk mailing list and &lt;a href="http://codeforpeople.com/"&gt;Ara T. Howard&lt;/a&gt; came back with a quick script that created little homicidal external ruby processes to kill the ruby process I was in if it didn’t “make it” in time.&lt;/p&gt;


	&lt;p&gt;The approach was actually very clever, and it works!&lt;/p&gt;


	&lt;p&gt;What he did was go “We can’t be sure that the existing Ruby process will be able to nuke itself, so instead, lets start up another Ruby instance, running on it’s own, that has the PIDs of the ruby instance that spawned it, and if the time runs out, do a system based kill &lt;span class="caps"&gt;TERM&lt;/span&gt; on the pids.”&lt;/p&gt;


	&lt;p&gt;You could say that our little ruby processes have a license to kill.  Literally.&lt;/p&gt;


	&lt;p&gt;So I implemented his idea, found a couple of problems, gave back some ideas, and he coded, I spec’d, tested and described and we released a brand new gem…&lt;/p&gt;


	&lt;h4&gt;The Terminator.&lt;/h4&gt;


	&lt;p&gt;You can get it with;&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;gem install terminator&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Or grab the &lt;a href="http://codeforpeople.com/lib/ruby/terminator"&gt;source code.&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;And how do you use it?  Simple:&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;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;terminator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;Terminator&lt;/span&gt;.terminate &lt;span class="i"&gt;1&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  sleep &lt;span class="i"&gt;2&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  puts &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;I'll never print&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;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This will never print because the terminator times out after 1 second, which is before the sleep of 2 seconds inside the block.  This will raise a Terminator::Error, which you could catch and try again if you want.&lt;/p&gt;


	&lt;p&gt;This will always work.  It is because we are starting a separate process of Ruby (which has some minor overhead) that waits the specified number of seconds and then just simple does a system kernel &lt;span class="caps"&gt;TERM&lt;/span&gt; on our misbehaving process.&lt;/p&gt;


	&lt;p&gt;Why should you use it?&lt;/p&gt;


	&lt;p&gt;Well, if you are making &lt;span class="caps"&gt;ANY&lt;/span&gt; calls to external web services, external databases, OpenID, Youtube, Google Maps… anything, then you should have a fail fast policy in place and time out rapidly if these fail.  As these are external system calls, they will most likely not be caught by Ruby’s timeout.rb library… and that means that your application will just hang, waiting for the call that never comes back.&lt;/p&gt;


	&lt;p&gt;It is much better to go “Ok, 2 seconds are up, no response, let’s tell the user to try again in a minute” and render an appropriate message, than have the user frustratingly whack the reload button a few hundred more times wondering why your application is not responding.&lt;/p&gt;


	&lt;p&gt;So yes, I think you should use Terminator.&lt;/p&gt;


	&lt;p&gt;Besides, how many other gems do you know that have the method ‘plot_to_kill’ ?&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/qt-N3O4QNWU" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/9/11/terminator-timeout-without-mercy</feedburner:origLink></entry>
  <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://feedproxy.google.com/~r/lindsaar-net/~3/REjdnrNiGUI/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/REjdnrNiGUI" 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://feedproxy.google.com/~r/lindsaar-net/~3/gI7Ig-Q7FY4/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/gI7Ig-Q7FY4" 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://feedproxy.google.com/~r/lindsaar-net/~3/aL8Ck-3FtoU/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/aL8Ck-3FtoU" 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: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://feedproxy.google.com/~r/lindsaar-net/~3/fgHh2Grgfew/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/fgHh2Grgfew" 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://feedproxy.google.com/~r/lindsaar-net/~3/sC1OJ5ItcSg/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/sC1OJ5ItcSg" 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://feedproxy.google.com/~r/lindsaar-net/~3/uTb3mtlMyYs/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/uTb3mtlMyYs" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://lindsaar.net/2008/6/26/tip-25-rspec-tip</feedburner:origLink></entry>
</feed>
