KC on Rails : http://kconrails.com/blog/articles.rss en-us 40 My Pain is Your Gain Ruby on Rails: Bool vs. Boolean in SQLite3 <p>I was looking at a new (to me) project today, and stumbled across a rails "gotcha" that needs attention. I tried to run <i>rake test</i>, but it failed. I received this error on each and every test:</p> <div class="typocode"><div class="codetitle">rake test</div><pre><code class="typocode_default "><notextile> SQLite3::SQLException: no such table</notextile></code></pre></div> <p>There are something like 60 migrations in this project, so I went (almost) straight to <i>db/schema.rb</i> which gives you the all-in-one look at your database structure. That's where I stumbled on this:</p> <div class="typocode"><div class="codetitle">db/schema.rb</div><pre><code class="typocode_default "><notextile> # Could not dump table &quot;generic_table&quot; because of following StandardError # Unknown type 'bool' for column 'generic_column'</notextile></code></pre></div> <p>it turns out a field was created with the type <i>bool</i>. I'm using SQLite3 for this project, but I did flip over to MySQL during debugging. Here's what I found:</p> <p><b>Under MySQL</b>, <i>bool</i> and <i>boolean</i> appear to work just fine as column types.</b> <i>schema.rb</i> is fine, tests are fine, and these two descriptors are synonymous.</p> <p><b>Under SQLite3</b>, <i>boolean</i> is the correct field descriptor. <i>bool</i> won't break your migration, but:</p> <ul> <li><i>rake db:schema:dump</i> (which is called by <i>rake db:migrate</i>) will fail SILENTLY, and your <i>schema.rb</i> file will be corrupted.</li> <li><i>rake db:test:prepare</i> uses <i>schema.rb</i>, so it will fail, also SILENTLY.</li> <li>tests will fail</li> <li><i>rake db:reset</i> also uses <i>schema.rb</i>, and so it will recreate a broken database.</li> <li>Oddly, the <i>bool</i> field in ruby will return 'f' for <i>false</i>, and 't' for <i>true</i>. If you set it to <i>true</i>, it does the "magic" on the backend, and there will be a 't' in that field. Therefore, setting something to <i>false</i> doesn't really work, because that field contains 'f', which equates to <i>true</i>.</li> </ul> <p>Rails will do all of this without complaint. Your migrations, db:test:prepare, even code will run without raising red flags. Scary. Tests are where things will start breaking.</p> Tue, 15 Jul 2008 11:15:00 -0500 urn:uuid:16090c67-bc96-47f5-a378-9f5a2c9d2fc8 http://kconrails.com/blog/articles/2008/07/15/ruby-on-rails-bool-vs-boolean-in-sqlite3#comments Rails Platform Ruby Programming Web Development purple monkey dishwasher kansas city Ruby on Rails test migrations bool boolean mysql sqlite3 http://kconrails.com/blog/articles/2008/07/15/ruby-on-rails-bool-vs-boolean-in-sqlite3 New Laptop Day! <p>I got my new laptop yesterday. Why? Because I took a new and exciting job, and I'll flesh out the details after I've been there for a week or two. Suffice to say, the company seems great, and I'm excited! In the meantime, let's look at some specs:</p> <div class="typocode"><div class="codetitle">Dell Precision M6300</div><pre><code class="typocode_default "><notextile> - 17&quot; Screen - Intel Core 2 Duo processor(s), 2.5GHz each - 2GB Dual-Channel RAM - 80GB 7200RPM Hard Drive - Dual-Band Wireless Card - High Level of Badassery</notextile></code></pre></div> <p>The only "problem" I have with this machine is that it won't fit in my current backpack, which maxes out at 15.4" screen laptops. That prompted me to put together this list of, what I feel, are the most important considerations. This is after having carried my current (and first) laptop backpack around for over a year.</p> <h3>Laptop Backpack Requirements</h3> <p><b>Capacity</b></p> <p>This thing is a monster. At 15.5"x11.3" and just over 1.5 inches thick, it makes my current Dell Latitude look like a kiddy toy. It's also rugged looking, as though Charlton Heston and the lead designer of the Ford F-150 had a lovechild, who grew up to design laptops for Dell. Anyway, this seems to be pushing the norm for laptop sizes, so I need a bag that is specifically designed to carry it.</p> <p><b>Breathable Back</b></p> <p>My laptop bag serves a very functional purpose. I use both straps and tend to carry lots of stuff with me. With my new job, I plan to do even more walking since I'll be working remotely. Breathable mesh backs will hopefully limit overall sweatiness and discomfort.</p> <p><b>Strap Connector Thingy</b></p> <p>Maybe you've noticed, but some backpack straps actually connect across your chest, and this is a huge difference in comfort when you walk. With the weight of a computer/books on your back, the backpack will sag, causing you to pull it back up periodically. Maybe you've seen (or been) someone who walks with their thumbs tucked under the straps. This is not JUST so that their thumbs can soak up all that awesome underarm aroma. They're keeping the straps in place. Chest connector thingies do this for you.</p> <p>Here's a summary of these, and other considerations. I'd love feedback and possibly leads. I'm willing to spend up to around $100 because I'll have this for a while, and I plan to be mobile.</p> <div class="typocode"><div class="codetitle">Ideal Laptop Backpack</div><pre><code class="typocode_default "><notextile> - Capacity for a 17&quot; screen laptop - Breathable back - Strap connector thingies - Two straps - the single sling doesn't look comfy for long walks - Must say, &quot;I'm a geek, but I make a reasonable effort to be fashionable.&quot;</notextile></code></pre></div> Fri, 11 Jul 2008 10:22:00 -0500 urn:uuid:56b10bc3-eae4-4ed9-bc86-aa750898f735 http://kconrails.com/blog/articles/2008/07/11/new-laptop-day#comments Miscellaneous kansas city Ruby on Rails purple monkey dishwasher laptop backpack job http://kconrails.com/blog/articles/2008/07/11/new-laptop-day Do Not Buy Dell "Open-Source" Laptops <p>I'm pricing out laptops on Dell, and I was intrigued by their "open-source" option. What that essentially means is, you don't get Windows with it. You get a basic command-line operating system (FreeDOS) that allows you to install the operating system of your choice, presumably because you want to use an open-source option like Linux.</p> <p>You would think that skipping windows would result in a price drop, and indeed the starting price is lower - by $39. The windows version starts with a slightly slower processor, but the DOS version starts with half the RAM. I walked through and built out identical laptops, the only difference being whether or not Windows Vista was installed. Here are the specs for each system, then the specs for the custom system I built out on each, to make them identical:</p> <table border=1 cellspacing=0> <tr> <th>Feature</th> <th>Dell Latitude D830</th> <th>Dell Latitude D830N</th> <th>Custom</th> </tr> <tr> <td>Operating System</td> <td>Windows Vista</td> <td>Basically Nothing</td> <td>Unchanged</td> </tr> <tr> <td>Base Price</td> <td>$809</td> <td>$770</td> <td>N/A</td> </tr> <tr> <td>Processor</td> <td>Intel Duo 2.00 GHz</td> <td>Intel Duo 2.20 GHz</td> <td>Intel Duo 2.50 GHz</td> </tr> <tr> <td>Warranty</td> <td>3 Year Mail-In</td> <td>3 Year Mail-In</td> <td>3 Year On-Site</td> </tr> <tr> <tr> <td>Screen</td> <td>15.4" WXGA</td> <td>15.4" WXGA</td> <td>15.4" WXGA</td> </tr> <tr> <td>Memory</td> <td>1GB, 2 DIMMs</td> <td>512MB, 1 DIMM</td> <td>2GB, 2 DIMMs</td> </tr> <tr> <td>Hard Drive</td> <td>80GB, 5400 RPM</td> <td>80GB, 5400 RPM</td> <td>80GB, 7200 RPM</td> </tr> <tr> <td>Optical</td> <td>24x CD-RW, DVD-ROM</td> <td>24x CD-RW, DVD-ROM</td> <td>8x DVD-RW</td> </tr> <tr> <td>Graphics Card</td> <td>Integrated</td> <td>Integrated</td> <td>256MB dedicated</td> </tr> <tr> <td>Wireless</td> <td>Dell 802.11g</td> <td>Dell 802.11g</td> <td>Intel 802.11a/g, Dual Band</td> </tr> <tr> <td>Battery</td> <td>6 Cell</td> <td>6 Cell</td> <td>9 Cell</td> </td> <tr> <td>Final Price</td> <td>$1,426</td> <td>$1,396</td> <td>N/A</td> </tr> </table> <p>The difference, after evening out the uneven features and adding some things I wanted, is $30. How much is Windows Vista?? I know they get it at a discount, but $30 is such a small token amount, it's almost a slap in the face. If I choose not to buy a couple hundred dollar operating system, I should save a couple hundred dollars.</p> <p>I say for the $30, get the one with Windows pre-installed. You can still overwrite or even dual-boot, and you'll always have the Windows license if you want/need it.</p> Sat, 28 Jun 2008 09:27:00 -0500 urn:uuid:d207e4b9-7d90-487c-a05c-8b9deabcce42 http://kconrails.com/blog/articles/2008/06/28/do-not-buy-a-dell-open-source-laptops#comments Miscellaneous Ubuntu kansas city dell latitude open source purple monkey dishwasher http://kconrails.com/blog/articles/2008/06/28/do-not-buy-a-dell-open-source-laptops Kansas City Ruby Users Group <p>I just attended my first <a href="http:kcrug.org">KCRUG</a> meeting last night, and it was awesome. This, despite being told the wrong room number and therefore missing the first 30 minutes of the meeting. And getting roped into that wrong room even after realizing my mistake, by a zealous .NET developer who wanted me to join <i>their</i> group. I code RoR on Ubuntu, but they have free pizza. I'm considering it.</p> <p>To the friends I met - Sam, Steven (or Stephen?), John, David, Sean, and Scotty - thanks for making my attendance slightly less awkward. Looking forward to next time!</p> Wed, 25 Jun 2008 12:16:00 -0500 urn:uuid:0cc5f62f-5772-49f7-982d-cb312df9bae9 http://kconrails.com/blog/articles/2008/06/25/kansas-city-ruby-users-group#comments Miscellaneous Ruby Programming kansas city Ruby on Rails ruby user group purple monkey dishwasher http://kconrails.com/blog/articles/2008/06/25/kansas-city-ruby-users-group Microsoft SharePoint Squares Off Against the Competition <p>While debating the value of SharePoint with a friend, I hopped onto microsoft.com to get some ammo, and boy did I find it. This is a direct quote from microsoft:</p> <div class="typocode"><div class="codetitle">http://office.microsoft.com/en-us/sharepointdesigner/HA101314471033.aspx</div><pre><code class="typocode_default "><notextile> Based on ASP.NET technology, SharePoint sites offer powerful, flexible support for interaction and collaboration. More traditional, static Web sites that are not based on ASP.NET may provide an effective venue for one-way presentations, but they cannot support true collaboration of the sort that Windows SharePoint Services 3.0 and ASP.NET 2.0 make possible.</notextile></code></pre></div> <p><b>SharePoint vs. Static HTML???</b> I love this marketing strategy: compare your most advanced offering with the oldest and most feature-poor alternative. The best part is, even the lamest marketer (me) can do it:</p> <div class="typocode"><div class="codetitle">Me, being a bit of a jackass</div><pre><code class="typocode_default "><notextile> The latest Geo Metro is a modern marvel of engineering and safety. The more traditional 1971 Ford Pinto, in contrast, has been called &quot;the barbecue that seats four&quot;. If you wish to roast yourself and your family in a firey grave, by all means purchase the Pinto.</notextile></code></pre></div> Tue, 24 Jun 2008 13:10:00 -0500 urn:uuid:e4fbc9d3-e501-47fb-8070-198107a67f85 http://kconrails.com/blog/articles/2008/06/24/microsoft-sharepoint-squares-off-against-the-competition#comments Miscellaneous Rails Platform Web Development microsoft sharepoint ford pinto purple monkey dishwasher http://kconrails.com/blog/articles/2008/06/24/microsoft-sharepoint-squares-off-against-the-competition Ruby on Rails Schema Migration using schema.rb <p>A few months ago, we had a problem. We had a (relatively) mature application we wanted to deploy to a new server. In this case, waited to deploy to the production server until after several weeks of development/testing in stage. We deployed via Webistrano, then we tried to <i>deploy:migrate</i>, and that's where things went south.</p> <p>Migrations that were written and worked with version X of our app failed 10 versions down the road. You're especially vulnerable when something that was a model attribute (ergo, a table field) before is now an instance method, or vice versa. For example, maybe <i>password</i> starts out as an attribute, but later becomes a method because you want <i>password=(x)</i> to generate a hash.</p> <p>If you're doing a fresh setup on a new server, and your app has been through several migrations already, you should ditch migrations for the initial deploy and run <i>db/schema.rb</i> instead, with the command <i>rake db:schema:load</i>. It will create the latest version of your database schema, including the current version number so future migrations will run without a problem.</p> <p>There is even a note about this in <i>db/schema.rb</i> itself, which I just found today:</p> <div class="typocode"><div class="codetitle">helpful hint provided in schema.rb itself</div><pre><code class="typocode_default "><notextile> Note that this schema.rb definition is the authoritative source for your database schema. If you need to create the application database on another system, you should be using db:schema:load, not running all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations you'll amass, the slower it'll run and the greater likelihood for issues).</notextile></code></pre></div> <p>Also, <i>db/schema.rb</i> is a great place to see the current state of your tables! Just this morning I returned to a dusty project, and needed to know what table fields already existed, and which I needed to add. In fact, that's how I stumbled on the above notice.</p> Tue, 24 Jun 2008 12:06:00 -0500 urn:uuid:a734a26e-a7d6-4415-80f4-e40f4c8c10c4 http://kconrails.com/blog/articles/2008/06/24/ruby-on-rails-schema-migration-using-schema-rb#comments Rails Platform Ruby Programming Web Development kansas city Ruby on Rails purple monkey dishwasher schema.rb schema migrations deploy deploy:migrate http://kconrails.com/blog/articles/2008/06/24/ruby-on-rails-schema-migration-using-schema-rb Ruby on Rails BDD Can be Creepy <p>As an exercise in getting more comfortable in RSpec, I'm porting over some unit tests so my current app (a CMS to administer our online games) can be 100% RSpec moving forward. The keyword <i>it</i> becomes funny and creepy the more you use it, and I found myself writing this:</p> <div class="typocode"><div class="codetitle">creepy ruby</div><pre><code class="typocode_ruby "><notextile> <span class="ident">describe</span> <span class="punct">&quot;</span><span class="string">An editor user</span><span class="punct">&quot;</span> <span class="keyword">do</span> <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">should have read privileges</span><span class="punct">&quot;</span> <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">should have editor privileges</span><span class="punct">&quot;</span> <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">puts the lotion on its skin</span><span class="punct">&quot;</span> <span class="keyword">end</span></notextile></code></pre></div> <p>Then for fun, I wrote this up:</p> <div class="typocode"><div class="codetitle">creepier ruby</div><pre><code class="typocode_ruby "><notextile> <span class="ident">describe</span> <span class="constant">Captive</span> <span class="keyword">do</span> <span class="ident">fixtures</span> <span class="symbol">:captives</span> <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">puts the lotion on its skin</span><span class="punct">&quot;</span> <span class="keyword">do</span> <span class="ident">captive</span><span class="punct">(</span><span class="symbol">:girl</span><span class="punct">).</span><span class="ident">should</span> <span class="ident">be_moisturized</span> <span class="keyword">end</span> <span class="keyword">end</span></notextile></code></pre></div> <p>Yeah, it's sick, but it made me laugh so I thought I'd share. Maybe RSpec should have "he" and "she" aliases to make describing person-based models less creepy. Just kidding - I'm having trouble memorizing all the natural-language idioms as it is.</p> Mon, 23 Jun 2008 12:22:00 -0500 urn:uuid:e90d2764-dabe-4b45-9d49-40815055254b http://kconrails.com/blog/articles/2008/06/23/ruby-on-rails-bdd-can-be-creepy#comments Miscellaneous Rails Platform Ruby Programming kansas city Ruby on Rails behavior driven development bdd creepy silence of the lambs purple monkey dishwasher http://kconrails.com/blog/articles/2008/06/23/ruby-on-rails-bdd-can-be-creepy Building Reliable Tests in Ruby on Rails <p>I've recently delved into TDD (test-driven development) and it's snobbier cousin BDD (behavior-driven). They both rock. Like many, I'm starting to see BDD as the evolutionary next step after TDD. I was somehow conditioned to think Rspec was evil and complicated, but it's growing on me.</p> <p><b>When is 10 less than 9?</b></p> <p>The answer is, when ruby sees them as strings. This is an issue with loosely typed languages like ruby. This recently caught a coworker off guard, and the worst part is that his automated testing did not catch the problem. This caused him to express frustration and doubt with testing in general.</p> <p>A good rule of thumb that I use, and I've heard it echoed all over the knowledgeable net, is to purposely break each test when you create it. Test the test. If this sounds tedious, it's actually very quick in practice. Let's look at some code:</p> <div class="typocode"><div class="codetitle">a simple unit test</div><pre><code class="typocode_ruby "><notextile> <span class="keyword">def </span><span class="method">test_001_new_user_should_be_active_by_default</span> <span class="ident">user</span> <span class="punct">=</span> <span class="constant">User</span><span class="punct">.</span><span class="ident">new</span> <span class="ident">assert</span> <span class="ident">user</span><span class="punct">.</span><span class="ident">active?</span><span class="punct">,</span> <span class="punct">&quot;</span><span class="string">New user should be active by default</span><span class="punct">&quot;</span> <span class="keyword">end</span></notextile></code></pre></div> <p>Or in rspec:</p> <div class="typocode"><div class="codetitle">a simple rspec test</div><pre><code class="typocode_ruby "><notextile> <span class="ident">describe</span> <span class="punct">&quot;</span><span class="string">A new user</span><span class="punct">&quot;</span> <span class="keyword">do</span> <span class="ident">before</span><span class="punct">(</span><span class="symbol">:each</span><span class="punct">)</span> <span class="keyword">do</span> <span class="attribute">@user</span> <span class="punct">=</span> <span class="constant">User</span><span class="punct">.</span><span class="ident">new</span> <span class="keyword">end</span> <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">should be active by default</span><span class="punct">&quot;</span> <span class="keyword">do</span> <span class="attribute">@user</span><span class="punct">.</span><span class="ident">should</span> <span class="ident">be_active</span> <span class="keyword">end</span> <span class="keyword">end</span></notextile></code></pre></div> <p>This simply ensures a user is active by default. Behind the scenes I imagine a <i>status</i> attribute with a default value of 'active', and an instance method called User#active? to check if a user is active. But before I put all my faith into this, I'll purposely poke it to make sure it screams when needed:</p> <div class="typocode"><div class="codetitle">temporarily breaking the unit test</div><pre><code class="typocode_ruby "><notextile> <span class="keyword">def </span><span class="method">test_001_new_user_should_be_active_by_default</span> <span class="ident">user</span> <span class="punct">=</span> <span class="constant">User</span><span class="punct">.</span><span class="ident">new</span><span class="punct">(</span><span class="symbol">:status=</span><span class="punct">&gt;'</span><span class="string">inactive</span><span class="punct">')</span> <span class="ident">assert</span> <span class="ident">user</span><span class="punct">.</span><span class="ident">active?</span><span class="punct">,</span> <span class="punct">&quot;</span><span class="string">New user should be active by default</span><span class="punct">&quot;</span> <span class="keyword">end</span></notextile></code></pre></div> <p>And again, the rspec version:</p> <div class="typocode"><div class="codetitle">temporarily breaking the rspec test</div><pre><code class="typocode_ruby "><notextile> <span class="ident">describe</span> <span class="punct">&quot;</span><span class="string">A new user</span><span class="punct">&quot;</span> <span class="keyword">do</span> <span class="ident">before</span><span class="punct">(</span><span class="symbol">:each</span><span class="punct">)</span> <span class="keyword">do</span> <span class="attribute">@user</span> <span class="punct">=</span> <span class="constant">User</span><span class="punct">.</span><span class="ident">new</span><span class="punct">(</span><span class="symbol">:status=</span><span class="punct">&gt;'</span><span class="string">inactive</span><span class="punct">')</span> <span class="keyword">end</span> <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">should be active by default</span><span class="punct">&quot;</span> <span class="keyword">do</span> <span class="attribute">@user</span><span class="punct">.</span><span class="ident">should</span> <span class="ident">be_active</span> <span class="keyword">end</span> <span class="keyword">end</span></notextile></code></pre></div> <p>I run the purposely broken test, see that it screams, and now I can undo that last tweak, confident that my test will work when needed.</p> <p>Another popular method is to curse at your tests when they let you down. But this is negative reinforcement, which any childless freshman psych major will say is never the answer.</p> <p><span style="color: red;"><b>UPDATE:</b></span> Forgive my newness with TDD/BDD, but if you're doing either of these in their most pure form, you eliminate a LOT of test reliability worries. This is because you write the tests <i>first</i>, and of course they fail right away, until you add the code that makes them work.</p> Fri, 20 Jun 2008 11:30:00 -0500 urn:uuid:9cfed5bf-9509-42b5-9599-dfe63becb0c5 http://kconrails.com/blog/articles/2008/06/20/kansas-city-building-reliable-tests-in-ruby-on-rails#comments Rails Platform Ruby Programming Web Development kansas city Ruby on Rails Testing tdd bdd test driven development behavior driven development break your tests rspec unit tests purple monkey dishwasher http://kconrails.com/blog/articles/2008/06/20/kansas-city-building-reliable-tests-in-ruby-on-rails Hack Your Pedometer <p>Not <i>everything</i> is about rails.</p> <p>If you work at my company, then you might just be part of the new walking initiative that kicked off this week. We were all given pedometers, and have experienced varying levels of success getting them to accurately measure our steps. Ladies and gentlemen, I give you the guide to hacking your pedometer to make it more accurate.</p> <p>This can be done by everyone. Not all hacks require <i>mad computer skillz</i> or a flagrant disregard for the law. Sometimes it's just looking at something and saying, <i>How can I make this work for me, in a way it was never intended?"</i> Let's look at some pictures.</p> <p style="text-align: center"> <img src="/blog/files/hack_your_pedometer/pedometer_01.jpg"> </p> <p>This is everything you'll need. A tiny phillips screwdriver, tweezers, cotton swabs, rubbing alcohol, and of course your pedometer. Drinking alcohol is optional, but highly encouraged.</p> <p style="text-align: center"> <img src="/blog/files/hack_your_pedometer/pedometer_02.jpg"> </p> <p>On the back are two tiny screws. Unscrew them, and open up the case. Set the plastic back aside for now.</p> <p style="text-align: center"> <img src="/blog/files/hack_your_pedometer/pedometer_03.jpg"> </p> <p>This is the inside of your pedometer. The arm at the top is attached to a tiny spring, and bounces up and down as you walk. Each time it strikes the metal stopper below, an electrical circuit is formed, and the counter increments itself by one step.</p> <p style="text-align: center"> <img src="/blog/files/hack_your_pedometer/pedometer_04.jpg"> </p> <p>In the bottom right corner is the battery, under a metal brace. gently push the battery down and to the right, using the screwdriver. Take note of which way the battery faces, so you can put it back the same way.</p> <p style="text-align: center"> <img src="/blog/files/hack_your_pedometer/pedometer_05.jpg"> </p> <p>Dip a cotton swab in the smallest possible amount of rubbing alcohol. You don't want it dripping wet, just moist. Now swab the two metal parts that touch with each step, to remove any oils or corrosion. Even the slightest smudge means you're missing steps.</p> <p style="text-align: center"> <img src="/blog/files/hack_your_pedometer/pedometer_06.jpg"> </p> <p>Rotate the pedometer so the battery is at the top, and you'll see the top of the spring that attaches to a strip of metal with five holes. The middle hole is best, but if your pedometer is too sensitive, or not sensitive enough, try using the tweezers to move the spring over in one direction or the other.</p> <p>This is trial and error. After each adjustment, set the pedometer upright and gently bounce it to simulate walking. Be <i>very</i> careful with the spring, this is the most delicate part of the whole setup, and bending it will make your pedometer cry.</p> <p style="text-align: center"> <img src="/blog/files/hack_your_pedometer/pedometer_07.jpg"> </p> <p>Afterward, replace the battery and reattach the plastic backing. If your pedometer looks like the picture above, chances are, you're in good shape. Enjoy a wonderful lifetime of fitness together. Until the battery dies, and you realize it's just cheaper to buy a whole new one.</p> Tue, 17 Jun 2008 21:44:00 -0500 urn:uuid:ceeacb29-8dd9-419a-9b7b-b01491338183 http://kconrails.com/blog/articles/2008/06/17/kansas-city-hack-your-pedometer#comments Tutorials hack pedometer purple monkey dishwasher http://kconrails.com/blog/articles/2008/06/17/kansas-city-hack-your-pedometer Ruby on Rails Testing: assert_equal is Your Friend <p>If you're not already doing tons of unit testing, then shame on you. Let me give you the rundown on good testing:</p> <ul> <li>Push as much code into the models (class definitions) themselves.</li> <li>Controllers should mostly just call class methods, and be very small.</li> <li>By following the previous two rules, you've made it very easy to test your application. Controllers are slightly complicated to test, but models are super easy. So write tests for every model method, and write assertions for each expected input/output combination.</li> </ul> <p>Now that we have Testing 101 out of the way, are you doing this?</p> <div class="typocode"><div class="codetitle">bad testing</div><pre><code class="typocode_ruby "><notextile> <span class="keyword">def </span><span class="method">test_remove_all_games</span> <span class="constant">Game</span><span class="punct">.</span><span class="ident">remove_all!</span> <span class="ident">assert</span> <span class="constant">Game</span><span class="punct">.</span><span class="ident">find</span><span class="punct">(</span><span class="symbol">:all</span><span class="punct">).</span><span class="ident">length</span> <span class="punct">==</span> <span class="number">0</span><span class="punct">,</span> <span class="punct">&quot;</span><span class="string">There should be zero games left.</span><span class="punct">&quot;</span> <span class="keyword">end</span></notextile></code></pre></div> <p>This will work, provided you've created a "remove_all!" class method for Game that does what it says. However, there's a much more useful way: <i>assert_equal</i>. A good general rule is this: whenever you use the generic <i>assert</i> method, you should ask yourself if there's a more specific method you could be using. Use <a href="http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit/Assertions.html" target="_blank">this page from the ruby api</a>. Let's look at some code:</p> <div class="typocode"><div class="codetitle">good testing</div><pre><code class="typocode_ruby "><notextile> <span class="keyword">def </span><span class="method">test_remove_all_games</span> <span class="constant">Game</span><span class="punct">.</span><span class="ident">remove_all!</span> <span class="ident">assert_equal</span> <span class="number">0</span><span class="punct">,</span> <span class="constant">Game</span><span class="punct">.</span><span class="ident">find</span><span class="punct">(</span><span class="symbol">:all</span><span class="punct">).</span><span class="ident">length</span><span class="punct">,</span> <span class="punct">&quot;</span><span class="string">There should be zero games left</span><span class="punct">&quot;</span> <span class="keyword">end</span></notextile></code></pre></div> <p>Notice I put the zero first. This is a little counter-intuitive to me, but it's important. The first parameter is what you're *expecting*, and the next is what you have. And you can pass anything into this - numbers, strings, objects, even arrays of objects:</p> <div class="typocode"><div class="codetitle">great testing</div><pre><code class="typocode_ruby "><notextile> <span class="keyword">def </span><span class="method">test_remove_all_games</span> <span class="constant">Game</span><span class="punct">.</span><span class="ident">remove_all!</span> <span class="ident">assert_equal</span> <span class="punct">[],</span> <span class="constant">Game</span><span class="punct">.</span><span class="ident">find</span><span class="punct">(</span><span class="symbol">:all</span><span class="punct">),</span> <span class="punct">&quot;</span><span class="string">There should be no games left</span><span class="punct">&quot;</span> <span class="keyword">end</span></notextile></code></pre></div> <p>Why do this? Because the testing will output what was expected and what you received, <b>automatically</b>. It makes for much easier debugging. Try it and see.</p> Mon, 16 Jun 2008 16:34:00 -0500 urn:uuid:5716dff3-059e-43de-bfd7-e7252d0a51c2 http://kconrails.com/blog/articles/2008/06/16/kansas-city-ruby-on-rails-testing-assert_equal-is-your-friend#comments Ruby Programming Web Development Testing assert assert_equal purple monkey dishwasher http://kconrails.com/blog/articles/2008/06/16/kansas-city-ruby-on-rails-testing-assert_equal-is-your-friend