<?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" xml:lang="en-US">
  <id>tag:rhnh.net,2008:/posts</id>
  <link type="text/html" href="http://rhnh.net/posts" rel="alternate" />
  
  <title>Xavier Shay's Blog</title>
  <updated>2009-05-18T16:26:54+10:00</updated>
  <generator uri="http://enkiblog.com">Enki</generator>
  <author>
    <name>Xavier Shay</name>
    <email>notreal@rhnh.net</email>
  </author>
  <link rel="self" href="http://feeds.feedburner.com/rhnh" type="application/atom+xml" /><entry>
    <id>tag:rhnh.net,2008:Post/797</id>
    <published>2009-05-18T16:30:00+10:00</published>
    <updated>2009-05-18T16:26:54+10:00</updated>
    <link type="text/html" href="http://rhnh.net/2009/05/18/selenium-webrat-and-the-firefox-beta?utm_campaign=eyeballs&amp;utm_medium=feed&amp;utm_source=feed" rel="alternate" />
    <title>Selenium, webrat and the firefox beta</title>
    <content type="html">&lt;p&gt;I needed a few hacks to get selenium running with webrat.&lt;/p&gt;


	&lt;p&gt;First, make sure you are running at least 0.4.4 of webrat. Don&amp;#8217;t make the same mistake I did and upgrade your gem version, but not the plugin installed in vendor/plugins.&lt;/p&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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 ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;gem install webrat&lt;tt&gt;
&lt;/tt&gt;gem install selenium-client&lt;tt&gt;
&lt;/tt&gt;gem install bmabey-database_cleaner --source=http://gems.github.com&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;There is a trick to get Firefox 3.5 beta working. The selenium server package with webrat 0.4.4 only supports &lt;span class="caps"&gt;FF 3&lt;/span&gt;.0.*. Follow these instructions, patching the jar that is packaged with webrat (vendor/selenium-server.jar) so that the extensions that selenium uses will be valid for the new FF.&lt;/p&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;cd vendor/ # In webrat dir&lt;tt&gt;
&lt;/tt&gt;jar xf selenium-server.jar \&lt;tt&gt;
&lt;/tt&gt;customProfileDirCUSTFFCHROME/extensions/readystate@openqa.org/install.rdf&lt;tt&gt;
&lt;/tt&gt;jar xf selenium-server.jar \&lt;tt&gt;
&lt;/tt&gt;customProfileDirCUSTFFCHROME/extensions/{538F0036-F358-4f84-A764-89FB437166B4}/install.rdf&lt;tt&gt;
&lt;/tt&gt;jar xf selenium-server.jar \&lt;tt&gt;
&lt;/tt&gt;customProfileDirCUSTFFCHROME/extensions/\{503A0CD4-EDC8-489b-853B-19E0BAA8F0A4\}/install.rdf &lt;tt&gt;
&lt;/tt&gt;jar xf selenium-server.jar \&lt;tt&gt;
&lt;/tt&gt;customProfileDirCUSTFF/extensions/readystate\@openqa.org/install.rdf &lt;tt&gt;
&lt;/tt&gt;jar xf selenium-server.jar \&lt;tt&gt;
&lt;/tt&gt;customProfileDirCUSTFF/extensions/\{538F0036-F358-4f84-A764-89FB437166B4\}/install.rdf&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;replace &amp;quot;3.0.*&amp;quot; &amp;quot;3.*&amp;quot; -- `find . | grep rdf`&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;jar uf selenium-server.jar \&lt;tt&gt;
&lt;/tt&gt;customProfileDirCUSTFFCHROME/extensions/readystate@openqa.org/install.rdf&lt;tt&gt;
&lt;/tt&gt;jar uf selenium-server.jar \&lt;tt&gt;
&lt;/tt&gt;customProfileDirCUSTFFCHROME/extensions/{538F0036-F358-4f84-A764-89FB437166B4}/install.rdf&lt;tt&gt;
&lt;/tt&gt;jar uf selenium-server.jar \&lt;tt&gt;
&lt;/tt&gt;customProfileDirCUSTFFCHROME/extensions/\{503A0CD4-EDC8-489b-853B-19E0BAA8F0A4\}/install.rdf &lt;tt&gt;
&lt;/tt&gt;jar uf selenium-server.jar \&lt;tt&gt;
&lt;/tt&gt;customProfileDirCUSTFF/extensions/readystate\@openqa.org/install.rdf &lt;tt&gt;
&lt;/tt&gt;jar uf selenium-server.jar \&lt;tt&gt;
&lt;/tt&gt;customProfileDirCUSTFF/extensions/\{538F0036-F358-4f84-A764-89FB437166B4\}/install.rdf&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;(hat tip to &lt;a href="http://www.spacevatican.org/2008/9/27/selenium-and-firefox-3"&gt;space vatican&lt;/a&gt;)&lt;/p&gt;


	&lt;p&gt;I haven&amp;#8217;t been able to get Safari working yet.&lt;/p&gt;


	&lt;p&gt;I want to run selenium tests besides normal webrat tests, so I created a new environment &amp;#8220;acceptance&amp;#8221; that I can run tests under. Modify your test helper file:&lt;/p&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span class="c"&gt;# test/test_helper.rb&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;ENV&lt;/span&gt;[&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;RAILS_ENV&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;] ||= &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;raise &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Can't run tests in &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;ENV&lt;/span&gt;[&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;RAILS_ENV&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; environment&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;unless&lt;/span&gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;%w(&lt;/span&gt;&lt;span class="k"&gt;test acceptance&lt;/span&gt;&lt;span class="dl"&gt;)&lt;/span&gt;&lt;/span&gt;.include?(&lt;span class="co"&gt;ENV&lt;/span&gt;[&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;RAILS_ENV&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;webrat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;test/env/&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;ENV&lt;/span&gt;[&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;RAILS_ENV&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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 ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span class="c"&gt;# test/env/test.rb&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;webrat/rails&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;span class="co"&gt;Webrat&lt;/span&gt;.configure &lt;span class="r"&gt;do&lt;/span&gt; |config|&lt;tt&gt;
&lt;/tt&gt;  config.mode = &lt;span class="sy"&gt;:rails&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  config.open_error_files = &lt;span class="pc"&gt;false&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;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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 ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span class="c"&gt;# test/env/acceptance.rb&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;webrat/selenium/silence_stream&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;webrat/selenium&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;test/selenium_helpers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;test/element_helpers&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;span class="c"&gt;# Required because we aren't isolating tests inside a transaction&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;database_cleaner&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;DatabaseCleaner&lt;/span&gt;.strategy = &lt;span class="sy"&gt;:truncation&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;Webrat&lt;/span&gt;.configure &lt;span class="r"&gt;do&lt;/span&gt; |config|&lt;tt&gt;
&lt;/tt&gt;  config.mode = &lt;span class="sy"&gt;:selenium&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;class&lt;/span&gt; &lt;span class="cl"&gt;ActionController::IntegrationTest&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="pc"&gt;self&lt;/span&gt;.use_transactional_fixtures = &lt;span class="pc"&gt;false&lt;/span&gt; &lt;span class="c"&gt;# Necessary, otherwise selenium will never see any changes!&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  setup &lt;span class="r"&gt;do&lt;/span&gt; |session|&lt;tt&gt;
&lt;/tt&gt;    session.host! &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;localhost:3001&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;  teardown &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="co"&gt;DatabaseCleaner&lt;/span&gt;.clean&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="c"&gt;# Hack: webrat requires this, even though we're not using rspec&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;module&lt;/span&gt; &lt;span class="cl"&gt;Spec&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;module&lt;/span&gt; &lt;span class="cl"&gt;Expectations&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;ExpectationNotMetError&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;Exception&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;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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 ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span class="c"&gt;# lib/tasks/test.rake&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;namespace &lt;span class="sy"&gt;:test&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  task &lt;span class="sy"&gt;:force_acceptance&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="co"&gt;ENV&lt;/span&gt;[&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;RAILS_ENV&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;] = &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;acceptance&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;  &lt;span class="co"&gt;Rake&lt;/span&gt;::&lt;span class="co"&gt;TestTask&lt;/span&gt;.new(&lt;span class="sy"&gt;:acceptance&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:force_acceptance&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt; |t|&lt;tt&gt;
&lt;/tt&gt;    t.test_files = &lt;span class="co"&gt;FileList&lt;/span&gt;[&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;test/acceptance/*_test.rb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;    t.verbose = &lt;span class="pc"&gt;true&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;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;Notes&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;selenium and javascript helpers are from &lt;a href="http://pivotallabs.com/users/patn/blog/articles/717-run-javascript-in-selenium-tests-easily"&gt;pivotallabs pat&lt;/a&gt;, they&amp;#8217;re really handy for testing visibilty of &lt;span class="caps"&gt;DOM&lt;/span&gt; elements&lt;/li&gt;
		&lt;li&gt;there&amp;#8217;s some magic in webrat to conditionally require &lt;code&gt;silence_stream&lt;/code&gt; based on something in active_support. I don&amp;#8217;t understand it quite enough, but requiring it explicitly was necessary to get things running for me&lt;/li&gt;
		&lt;li&gt;webrat/selenium assumes some classes are loaded that only happens if you&amp;#8217;re using rspec. I&amp;#8217;m not, so stubbed out the ExpectationNotMetError (it is only referred to in a rescue block).&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;rake test:acceptance&lt;/code&gt; runs the selenium tests. Running acceptance tests directly as a ruby script runs them using normal webrat &amp;#8211; this is actually handy when writing tests because you get a quicker turnaround.&lt;/li&gt;
		&lt;li&gt;to pause selenium mid test run (to see wtf is going on), just add &lt;code&gt;gets&lt;/code&gt; at the appropriate line in your test&lt;/li&gt;
	&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>tag:rhnh.net,2008:Post/796</id>
    <published>2009-03-12T08:45:03+11:00</published>
    <updated>2009-03-12T08:45:03+11:00</updated>
    <link type="text/html" href="http://rhnh.net/2009/03/12/faster-rails-testing-with-ruby-fork?utm_campaign=eyeballs&amp;utm_medium=feed&amp;utm_source=feed" rel="alternate" />
    <title>Faster rails testing with ruby_fork</title>
    <content type="html">&lt;p&gt;A long running test suite isn&amp;#8217;t the problem. Your build server can take care of that. A second or two here or there, no one notices.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;The killer wait is in the red/green/refactor loop.&lt;/strong&gt; You&amp;#8217;re only running one or two tests, and an extra second can mean the difference between getting into flow or switching to twitter. And you know what kills you in rails?&lt;/p&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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 ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;$ time ruby -e '' -r config/environment.rb&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;real    0m3.784s&lt;tt&gt;
&lt;/tt&gt;user    0m2.707s&lt;tt&gt;
&lt;/tt&gt;sys     0m0.687s&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;Yep, the environment. That&amp;#8217;s a lot of overhead to be waiting for everytime you run a test, especially since it&amp;#8217;s the same code every time! You fix this with a clever script called &lt;code&gt;ruby_fork&lt;/code&gt; that&amp;#8217;s included in the &lt;a href="http://zentest.rubyforge.org/ZenTest/"&gt;ZenTest&lt;/a&gt; package. It loads up your environment, then just chills out, waiting. You send a ruby file to it, and it forks itself (the process containing the environment) to execute that file. The beauty of this is that forking is really quick, and it leaves a pristine copy of the environment around for the next test run.&lt;/p&gt;


	&lt;p&gt;&amp;#8216;Environment&amp;#8217; doesn&amp;#8217;t just have be &lt;code&gt;environment.rb&lt;/code&gt;, for bonus points you can load up &lt;code&gt;test_helper.rb&lt;/code&gt;, which will also load your testing framework into memory. In fact, you can preload any ruby code at all &amp;#8211; &lt;code&gt;ruby_fork&lt;/code&gt; isn&amp;#8217;t rails specific.&lt;/p&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;$ ruby_fork -r test/test_helper.rb &amp;amp;&lt;tt&gt;
&lt;/tt&gt;/opt/local/bin/ruby_fork Running as PID 526 on 9084&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;$ time ruby_fork_client -r test/unit/your_test.rb&lt;tt&gt;
&lt;/tt&gt;Started&lt;tt&gt;
&lt;/tt&gt;...&lt;tt&gt;
&lt;/tt&gt;Finished in 0.565636 seconds. # Aside: this time is bollocks&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;3 tests, 4 assertions, 0 failures, 0 errors&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;real    0m0.972s # This is the time you're interested in&lt;tt&gt;
&lt;/tt&gt;user    0m0.225s&lt;tt&gt;
&lt;/tt&gt;sys     0m0.035s&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;That&amp;#8217;s fantastic, though you&amp;#8217;ll notice in newer versions of rails your application code is not reloaded. By default your test environment caches classes &amp;#8211; which normally isn&amp;#8217;t a problem except that newer rails versions also eager load those classes (so they&amp;#8217;re loaded when you load enviornment.rb). You can fix this by clearing out the eager load paths in your test environment file:&lt;/p&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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 ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span class="c"&gt;# config/environments/test.rb&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;config.eager_load_paths = []&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;On my machine this gets individual test runs down from about 4 seconds to less than 1 second. You can sell that to your boss as a four-fold productivity increase.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:rhnh.net,2008:Post/795</id>
    <published>2009-03-10T08:33:15+11:00</published>
    <updated>2009-03-10T08:33:15+11:00</updated>
    <link type="text/html" href="http://rhnh.net/2009/03/10/testing-glue-code?utm_campaign=eyeballs&amp;utm_medium=feed&amp;utm_source=feed" rel="alternate" />
    <title>Testing Glue Code</title>
    <content type="html">&lt;p&gt;&lt;a href="http://github.com/xaviershay/db2s3"&gt;db2s3&lt;/a&gt; combines together 3 external dependencies &amp;#8211; your database, the filesystem, and Amazon&amp;#8217;s S3 service. It has 1 conditional in the main code path (and it&amp;#8217;s not even an important one). The classic unit testing approach of &amp;#8220;stub everything&amp;#8221; provides little benefit.&lt;/p&gt;


	&lt;p&gt;Unit testing is good for ensuring complex code paths execute properly, that edge cases are properly explored, and for answering the question &amp;#8220;what broke?&amp;#8221;. For trivial glue code, none of these are of particular benefit. There are no complex code paths or edge cases, and it will be quickly obvious what broke. In fact, the most likely thing to &amp;#8220;break&amp;#8221; (or change) over time isn&amp;#8217;t your code, but the external services it is sticking together, which stubs cannot protect you from. Considering the high relative cost of stubbing out all your dependencies, unit testing becomes an expensive way of testing something quite simple.&lt;/p&gt;


	&lt;p&gt;For glue code, integration tests are the best solution. Glue code needs to stick, and integration tests ensures that it does. Here is the only test that matters from db2s3:&lt;/p&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;it &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;can save and restore a backup to S3&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;  db2s3 = &lt;span class="co"&gt;DB2S3&lt;/span&gt;.new&lt;tt&gt;
&lt;/tt&gt;  load_schema&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;Person&lt;/span&gt;.create!(&lt;span class="sy"&gt;:name&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;Baxter&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  db2s3.full_backup&lt;tt&gt;
&lt;/tt&gt;  drop_schema&lt;tt&gt;
&lt;/tt&gt;  db2s3.restore&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;Person&lt;/span&gt;.find_by_name(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Baxter&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).should_not be_nil&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;This test costs money to run since it hits the live S3 service, but only in the academic sense. The question you need to ask is &amp;#8220;would I pay one cent to have confidence my backup solution works?&amp;#8221;&lt;/p&gt;


	&lt;p&gt;Always remember why your are testing. &lt;strong&gt;Unit tests are a focussed tool, and not always necessary.&lt;/strong&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:rhnh.net,2008:Post/794</id>
    <published>2009-03-09T15:25:00+11:00</published>
    <updated>2009-03-09T15:25:00+11:00</updated>
    <link type="text/html" href="http://rhnh.net/2009/03/09/backup-mysql-to-s3-with-rails?utm_campaign=eyeballs&amp;utm_medium=feed&amp;utm_source=feed" rel="alternate" />
    <title>Backup MySQL to S3 with Rails</title>
    <content type="html">&lt;p&gt;Here is some code I wrote over the weekend &amp;#8211; &lt;a href="http://github.com/xaviershay/db2s3"&gt;db2s3&lt;/a&gt;. It&amp;#8217;s a rails plugin that provides rake tasks for backing up your database and storing it on Amazon&amp;#8217;s S3 cloud storage. S3 is a trivially cheap offsite backup solution &amp;#8211; for small databases it costs about 4 cents per month, even if you&amp;#8217;re sending full backups every hour.&lt;/p&gt;


	&lt;p&gt;There are &lt;a href="http://info-architects.net/2007/08/25/rake-task-for-mysql-backup-to-amazon-s3/"&gt;many&lt;/a&gt; &lt;a href="http://pauldowman.com/2009/02/08/mysql-s3-backup/"&gt;scripts&lt;/a&gt; &lt;a href="http://therailscoder.typepad.com/the_rails_coder_ruby_on_r/2008/04/automatic-mysql.html"&gt;around&lt;/a&gt; that do this already, but they fail to address the biggest actual problem. The &lt;a href="http://amazon.rubyforge.org"&gt;aws-s3&lt;/a&gt; gem provides a really nice ruby interface to S3, and dumping a backup then storing it really isn&amp;#8217;t that hard. The real problem is that &lt;strong&gt;I really hate system administration.&lt;/strong&gt; I want to spend as little time as possible and I want things to Just Work.&lt;/p&gt;


	&lt;p&gt;A script is great but there&amp;#8217;s still too many things for me to do. Where does it go in my project? How do I set my credentials? How do I call it?&lt;/p&gt;


	&lt;p&gt;That&amp;#8217;s why a plugin was needed. It&amp;#8217;s as little work as possible for a rails developer to backup their database, so they can get back to making their app awesome.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://github.com/xaviershay/db2s3"&gt;db2s3&lt;/a&gt;. Check it out.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:rhnh.net,2008:Post/793</id>
    <published>2009-01-26T04:01:00+11:00</published>
    <updated>2009-01-26T04:01:02+11:00</updated>
    <link type="text/html" href="http://rhnh.net/2009/01/26/singleton-resource-pluralized-controller-fix-for-rails?utm_campaign=eyeballs&amp;utm_medium=feed&amp;utm_source=feed" rel="alternate" />
    <title>Singleton resource, pluralized controller fix for rails</title>
    <content type="html">&lt;p&gt;&lt;code&gt;map.resource&lt;/code&gt; still looks for a pluralized controller. This has always bugged me. Here&amp;#8217;s a quick monkey patch to fix. Tested on rails 2.2.2.&lt;/p&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span class="c"&gt;# config/initializers/singleton_resource_fix.rb&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;module&lt;/span&gt; &lt;span class="cl"&gt;ActionController&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;module&lt;/span&gt; &lt;span class="cl"&gt;Resources&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;SingletonResource&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;Resource&lt;/span&gt; &lt;span class="c"&gt;#:nodoc:&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;initialize&lt;/span&gt;(entity, options)&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="iv"&gt;@singular&lt;/span&gt; = &lt;span class="iv"&gt;@plural&lt;/span&gt; = entity&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="c"&gt;# options[:controller] ||= @singular.to_s.pluralize&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        options[&lt;span class="sy"&gt;:controller&lt;/span&gt;] ||= &lt;span class="iv"&gt;@singular&lt;/span&gt;.to_s &lt;span class="c"&gt;# This is the only line to change&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="r"&gt;super&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;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;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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 ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span class="c"&gt;# config/routes.rb&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="c"&gt;# before fix&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;map.resource &lt;span class="sy"&gt;:session&lt;/span&gt;, &lt;span class="sy"&gt;:controller&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;sessions&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;span class="c"&gt;# after fix&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;map.resource &lt;span class="sy"&gt;:session&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
</content>
  </entry>
  <entry>
    <id>tag:rhnh.net,2008:Post/792</id>
    <published>2008-12-29T13:41:10+11:00</published>
    <updated>2008-12-29T13:41:10+11:00</updated>
    <link type="text/html" href="http://rhnh.net/2008/12/29/evolution-of-a-graph?utm_campaign=eyeballs&amp;utm_medium=feed&amp;utm_source=feed" rel="alternate" />
    <title>Evolution of a graph</title>
    <content type="html">&lt;p&gt;Recently I have wanted to chart some cost data I collected on various foods. As a baseline for discussion, here is a very vanilla excel type graph, reminiscent of ones I am certain you have seen in powerpoint presentations:&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://farm4.static.flickr.com/3211/3141627141_fa64ecf450_o.png" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;This is not a good graph for several reasons&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Only provides a general overview of the data &amp;#8211; some foods are cheaper, some more expensive, so what?&lt;/li&gt;
		&lt;li&gt;Labels feel cramped and ugly.&lt;/li&gt;
		&lt;li&gt;The grid is too prominent and distracting, without being very helpful &amp;#8211; you can&amp;#8217;t read accurate values from it.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;The biggest problem is that it doesn&amp;#8217;t &amp;#8220;invite the eye to compare&amp;#8221;. It doesn&amp;#8217;t leave an impact. The first step to addressing this is to revisit the data &amp;#8211; it&amp;#8217;s quite possible you just have boring data. In this case, I improved the data by coding it according to whether it is vegetarian or not.&lt;/p&gt;


	&lt;h2&gt;Version 2&lt;/h2&gt;


	&lt;p&gt;For the next iteration of this graph, I colored the graph to highlight the vegetarian aspect of the food. To address the other issues, I moved the labels into the legend, and completely removed the grid, instead displaying the values directly on the graph. This technique works due to the low number of data points. You can think of it has &amp;#8220;enhancing&amp;#8221; the table rather than displaying a high level overview of it. Also, a serif font (georgia) was used.&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://farm4.static.flickr.com/3220/3141627109_26f6d3caca_o.png" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;This is certainly an improvement, but it still has its flaws&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;8 different colors, which distracts from the data, and the vegetarian data is muted.&lt;/li&gt;
		&lt;li&gt;It is much harder to identify the food with the data point, now that the labels have been moved into the legend.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h2&gt;Final&lt;/h2&gt;


	&lt;p&gt;I iterated again, moving the labels back down to the x-axis, which in addition to solving the identification problem, allowed me to drop back down to 2 colours. In our initial graph this felt cramped, so I added some more whitespace and also kept the serif font from the last iteration.&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://farm4.static.flickr.com/3292/3142466744_d52132f480_o.png" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;This version of the graph speaks much louder. It&amp;#8217;s easier on the eye, and the conclusion I want to draw from the data is clearly expressed. I am using this graph (with proper references and notes) on a new information site I&amp;#8217;m working on &amp;#8211; it&amp;#8217;s far from complete but you can &lt;a href="http://github.com/xaviershay/vegeinfo"&gt;follow along on github&lt;/a&gt; if you&amp;#8217;re interested.&lt;/p&gt;


	&lt;h2&gt;Tools&lt;/h2&gt;


	&lt;p&gt;The first graph was made with &lt;a href="http://www.openoffice.org/"&gt;OpenOffice&lt;/a&gt; spreadsheet, the second with a hacked version of &lt;a href="http://code.google.com/p/flot/"&gt;flot&lt;/a&gt; for &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt;. The final graph was made with a new jQuery plugin I wrote called &lt;a href="http://xaviershay.github.com/tufte-graph/"&gt;tufte-graph&lt;/a&gt;. There is a meta-lesson here &amp;#8211; I spent hours hacking different JS libraries to try and get them working exactly how I wanted, in the end the quickest solution was to just write what I needed.&lt;/p&gt;


	&lt;p&gt;I use &lt;a href="http://www.colourlovers.com"&gt;Colour Lovers&lt;/a&gt; to find color nice colour palettes. Works much better than trying random &lt;span class="caps"&gt;RGB&lt;/span&gt; codes.&lt;/p&gt;


	&lt;h2&gt;Final word&lt;/h2&gt;


	&lt;p&gt;Spend time on your graphs. A picture is worth a thousand words. They are too often neglected, and it doesn&amp;#8217;t take much effort to make them really shine.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:rhnh.net,2008:Post/791</id>
    <published>2008-12-28T17:16:03+11:00</published>
    <updated>2008-12-28T17:16:03+11:00</updated>
    <link type="text/html" href="http://rhnh.net/2008/12/28/inject-and-collect-with-jquery?utm_campaign=eyeballs&amp;utm_medium=feed&amp;utm_source=feed" rel="alternate" />
    <title>inject and collect with jQuery</title>
    <content type="html">&lt;p&gt;You know, I would have thought someone had already made an enumerable plugin for &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt;. Maybe someone has. Mine is better.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Complete coverage with screw-unit&lt;/li&gt;
		&lt;li&gt;Interface so consistent with jQuery you&amp;#8217;ll think it was core&lt;/li&gt;
	&lt;/ul&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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 ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;squares = $([1,2,3]).collect(function () {&lt;tt&gt;
&lt;/tt&gt;  return this * this;&lt;tt&gt;
&lt;/tt&gt;});&lt;tt&gt;
&lt;/tt&gt;squares // =&amp;gt; [1, 4, 9]&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;&lt;a href="http://github.com/xaviershay/jquery-enumerable/tree/master"&gt;It&amp;#8217;s on github&lt;/a&gt;. It deliberately doesn&amp;#8217;t have the kitchen sink &amp;#8211; fork and add methods you need, there&amp;#8217;s enough code it should be obvious the correct way to do it.&lt;/p&gt;


	&lt;p&gt;As an aside, it&amp;#8217;s really hard to spec these methods concisely. I consulted the rubyspec project and it turns out they had trouble as well, check out this all encompassing spec for inject: &amp;#8220;Enumerable#inject: inject with argument takes a block with an accumulator (with argument as initial value) and the current element. Value of block becomes new accumulator&amp;#8221;. Bit of a mouthful eh.&lt;/p&gt;


	&lt;p&gt;Post your improvements in the comments.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:rhnh.net,2008:Post/790</id>
    <published>2008-12-01T19:16:42+11:00</published>
    <updated>2008-12-01T19:16:42+11:00</updated>
    <link type="text/html" href="http://rhnh.net/2008/12/01/code-for-christmas?utm_campaign=eyeballs&amp;utm_medium=feed&amp;utm_source=feed" rel="alternate" />
    <title>Code for Christmas</title>
    <content type="html">&lt;p&gt;Developers don&amp;#8217;t have enough time.&lt;/p&gt;


	&lt;p&gt;We&amp;#8217;re all too busy working our day job, or looking after our better half, to give our pet projects the attention they deserve.&lt;/p&gt;


	&lt;p&gt;That makes time the most valuable thing we can give. This year for Christmas, why not give a fellow developer some?&lt;/p&gt;


	&lt;p&gt;Ticking off an amazon wishlist never really resonated with me, so this year here is what we are all doing instead:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Find someone&amp;#8217;s pet open source project &amp;#8211; I&amp;#8217;d start at github&lt;/li&gt;
		&lt;li&gt;Contribute! It doesn&amp;#8217;t have to be much &amp;#8211; a spec or two, some documentation, or even just a &amp;#8220;hey it works on my box&amp;#8221;. Fork, commit, pull request.&lt;/li&gt;
		&lt;li&gt;Wish them a Merry Christmas!&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;That shouldn&amp;#8217;t take you more than an hour. It&amp;#8217;s a total win all around &amp;#8211; you get to hone your chops, they get some love on their project, and the open source ecosphere is improved. If you&amp;#8217;re feeling generous, or don&amp;#8217;t have any friends, there&amp;#8217;s &lt;a href="http://github.com/repositories"&gt;no shortage of projects&lt;/a&gt; that I&amp;#8217;m sure would welcome some support.&lt;/p&gt;


	&lt;p&gt;My wishlist is any of the &lt;a href="http://groups.google.com/group/ruby-midi/web/projects"&gt;ruby midi projects&lt;/a&gt; out there.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:rhnh.net,2008:Post/789</id>
    <published>2008-11-14T18:47:00+11:00</published>
    <updated>2008-11-14T18:47:46+11:00</updated>
    <link type="text/html" href="http://rhnh.net/2008/11/14/unique-data-in-dm-sweatshop?utm_campaign=eyeballs&amp;utm_medium=feed&amp;utm_source=feed" rel="alternate" />
    <title>Unique data in dm-sweatshop</title>
    <content type="html">&lt;p&gt;&lt;code&gt;dm-sweatshop&lt;/code&gt; is how you set up test data for your datamapper apps. Standard practice is to generate random data that follows a pattern:&lt;/p&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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 ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span class="co"&gt;User&lt;/span&gt;.fix {{&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="sy"&gt;:login&lt;/span&gt;  =&amp;gt; &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="ch"&gt;\w&lt;/span&gt;&lt;span class="k"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;.gen&lt;tt&gt;
&lt;/tt&gt;}}&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;new_user = &lt;span class="co"&gt;User&lt;/span&gt;.gen&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;Let&amp;#8217;s not now debate whether or not random data in tests is a good idea. What&amp;#8217;s more important is that the above code should make you uneasy if login is supposed to be unique. There was a hack in sweatshop that would try recreating the data if you had a uniqueness constraint on login and it was invalid, but it was exactly that: a hack. As of a few days ago (what will be 0.9.7), you need to be more explicit if you want unique data. It&amp;#8217;s pretty easy:&lt;/p&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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 ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;include &lt;span class="co"&gt;DataMapper&lt;/span&gt;::&lt;span class="co"&gt;Sweatshop&lt;/span&gt;::&lt;span class="co"&gt;Unique&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;User&lt;/span&gt;.fix {{&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="sy"&gt;:login&lt;/span&gt;  =&amp;gt; unique { &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="ch"&gt;\w&lt;/span&gt;&lt;span class="k"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;.gen }&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;Tada! You can also easily get non-random unique data by providing a block with one parameter. &lt;a href="http://github.com/sam/dm-more/tree/master/dm-sweatshop/README.textile"&gt;Check the &lt;span class="caps"&gt;README&lt;/span&gt;&lt;/a&gt; for this and other cool things you can do.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:rhnh.net,2008:Post/788</id>
    <published>2008-11-03T20:02:00+11:00</published>
    <updated>2008-11-03T20:02:52+11:00</updated>
    <link type="text/html" href="http://rhnh.net/2008/11/03/introducing-socialbeat-screencast?utm_campaign=eyeballs&amp;utm_medium=feed&amp;utm_source=feed" rel="alternate" />
    <title>Introducing SocialBeat (screencast)</title>
    <content type="html">&lt;p&gt;Here is a screencast of &lt;a href="http://github.com/xaviershay/socialbeat/tree/master"&gt;socialbeat&lt;/a&gt; in which you will note:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;I don&amp;#8217;t appear drunk&lt;/li&gt;
		&lt;li&gt;I don&amp;#8217;t reveal intra-company communications&lt;/li&gt;
		&lt;li&gt;I show off the full gamut of socialbeat&amp;#8217;s awesomeness in under 3 minutes&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;In these ways you may find it superior to other screencasts you may have seen on the matter.&lt;/p&gt;


&lt;object width="400" height="300"&gt;    &lt;param name="allowfullscreen" value="true" /&gt;    &lt;param name="allowscriptaccess" value="always" /&gt;    &lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=2139958&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" /&gt;    &lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=2139958&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;a href="http://vimeo.com/2139958?pg=embed&amp;amp;sec=2139958"&gt;Introducing SocialBeat&lt;/a&gt;

	&lt;p&gt;If you are behind the times &amp;#8211; socialbeat is some code that lets you live code OpenGL visualizations to &lt;span class="caps"&gt;MIDI&lt;/span&gt; tracks.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:rhnh.net,2008:Post/787</id>
    <published>2008-11-03T08:54:00+11:00</published>
    <updated>2008-11-03T08:54:09+11:00</updated>
    <link type="text/html" href="http://rhnh.net/2008/11/03/comparing-lambdas-in-ruby?utm_campaign=eyeballs&amp;utm_medium=feed&amp;utm_source=feed" rel="alternate" />
    <title>Comparing lambdas in ruby</title>
    <content type="html">&lt;p&gt;&lt;code&gt;to_ruby&lt;/code&gt; is a really convenient way to compare the equality of two lambdas. It&amp;#8217;s a bit slow though. If we get our hands dirty (only a little!) with ParseTree, we can get a result 2 orders of magnitude quicker. I&amp;#8217;d be interested to see if these benchmarks differ significantly on other versions of ruby.&lt;/p&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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 ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;~ $ ruby -v&lt;tt&gt;
&lt;/tt&gt;ruby 1.8.6 (2007-09-23 patchlevel 110) [i686-darwin8.11.1]&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;benchmark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;parse_tree&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;ruby2ruby&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;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;gen_lambda&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  lambda {|x| x + &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;&lt;span class="co"&gt;Parser&lt;/span&gt; = &lt;span class="co"&gt;ParseTree&lt;/span&gt;.new(&lt;span class="pc"&gt;false&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="c"&gt;# This only requires parse tree, not ruby2ruby&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;proc_identity&lt;/span&gt;(block)&lt;tt&gt;
&lt;/tt&gt;  klass = &lt;span class="co"&gt;Class&lt;/span&gt;.new&lt;tt&gt;
&lt;/tt&gt;  name = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;myproc&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  klass.send(&lt;span class="sy"&gt;:define_method&lt;/span&gt;, name, &amp;amp;block)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# .last ignores the method name and definition - they're irrelevant&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;Parser&lt;/span&gt;.parse_tree_for_method(klass, name).last &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;n = &lt;span class="i"&gt;1000&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;Benchmark&lt;/span&gt;.bmbm &lt;span class="r"&gt;do&lt;/span&gt; |x|&lt;tt&gt;
&lt;/tt&gt;  x.report(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;#to_ruby&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) { n.times { gen_lambda.to_ruby == gen_lambda.to_ruby }}&lt;tt&gt;
&lt;/tt&gt;  x.report(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;#to_sexp&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) { n.times { gen_lambda.to_sexp == gen_lambda.to_sexp }}&lt;tt&gt;
&lt;/tt&gt;  x.report(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;manual&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)   { n.times { proc_identity(gen_lambda) == proc_identity(gen_lambda) }}&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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 ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;               user     system      total        real&lt;tt&gt;
&lt;/tt&gt;#to_ruby   4.460000   0.220000   4.680000 (  4.695327)&lt;tt&gt;
&lt;/tt&gt;#to_sexp   0.920000   0.190000   1.110000 (  1.110214)&lt;tt&gt;
&lt;/tt&gt;manual     0.030000   0.000000   0.030000 (  0.032768)&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;In case you were wondering, I was playing around with this while implementing &lt;a href="http://github.com/xaviershay/dm-more/tree/master/dm-sweatshop"&gt;unique data generation for dm-sweatshop&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:rhnh.net,2008:Post/786</id>
    <published>2008-10-01T06:11:00+10:00</published>
    <updated>2008-10-01T06:11:51+10:00</updated>
    <link type="text/html" href="http://rhnh.net/2008/10/01/integration-testing-with-cucumber-rspec-and-thinking-sphinx?utm_campaign=eyeballs&amp;utm_medium=feed&amp;utm_source=feed" rel="alternate" />
    <title>Integration testing with Cucumber, RSpec and Thinking Sphinx</title>
    <content type="html">&lt;p&gt;Ideally you would want to include sphinx in your integration tests. It&amp;#8217;s really just like your database. In practice, this is problematic. Ensuring the DB is started and triggering a re-index after each model load is doable, if slow, with a small bit of hacking of thinking sphinx (hint &amp;#8211; change the initializer for the &lt;code&gt;ThinkingSphinx::Configuration&lt;/code&gt; to allow you to specify the environment). Here&amp;#8217;s the rub though &amp;#8211; if you&amp;#8217;re using transactional fixtures the sphinx indexer won&amp;#8217;t be able to see any of your data! Turning that off can really slow down your tests, and once you add in the re-indexing time you&amp;#8217;re going to be making a few cups of coffee while they run.&lt;/p&gt;


	&lt;p&gt;One approach I&amp;#8217;ve been taking is to stub out the &lt;code&gt;search&lt;/code&gt; methods with &lt;a href="http://github.com/btakita/rr/tree/master"&gt;RR&lt;/a&gt;. I know, I know, stubbing in your integration tests is evil. I&amp;#8217;m being pragmatic here. For most applications your search is trivial (find me results for this keyword), and if you unit test your &lt;code&gt;define_index&lt;/code&gt; block you&amp;#8217;re pretty well covered. To go one step further you could unit test your controllers with an expect on the search method, or have a separate suite of non-transactional integration tests running against sphinx. I like the latter, but haven&amp;#8217;t done it yet.&lt;/p&gt;


	&lt;p&gt;Enough talk! Here&amp;#8217;s the magic you need to get it working with &lt;a href="http://github.com/aslakhellesoy/cucumber/tree/master"&gt;cucumber&lt;/a&gt;:&lt;/p&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span class="c"&gt;# features/steps/env.rb&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;rr&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;Cucumber&lt;/span&gt;::&lt;span class="co"&gt;Rails&lt;/span&gt;::&lt;span class="co"&gt;World&lt;/span&gt;.send(&lt;span class="sy"&gt;:include&lt;/span&gt;, &lt;span class="co"&gt;RR&lt;/span&gt;::&lt;span class="co"&gt;Adapters&lt;/span&gt;::&lt;span class="co"&gt;RRMethods&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="c"&gt;# features/steps/*_steps.rb&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;Given&lt;/span&gt; &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;a car with model '(&lt;/span&gt;&lt;span class="ch"&gt;\w&lt;/span&gt;&lt;span class="k"&gt;+)' exists&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt; |model|&lt;tt&gt;
&lt;/tt&gt;  car = &lt;span class="co"&gt;Car&lt;/span&gt;.create!(&lt;span class="sy"&gt;:model&lt;/span&gt; =&amp;gt; model)&lt;tt&gt;
&lt;/tt&gt;  stub(&lt;span class="co"&gt;Car&lt;/span&gt;).search(model) { [car] }&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
</content>
  </entry>
  <entry>
    <id>tag:rhnh.net,2008:Post/785</id>
    <published>2008-09-27T06:48:00+10:00</published>
    <updated>2008-09-27T06:48:39+10:00</updated>
    <link type="text/html" href="http://rhnh.net/2008/09/27/capturing-output-from-rake?utm_campaign=eyeballs&amp;utm_medium=feed&amp;utm_source=feed" rel="alternate" />
    <title>Capturing output from rake</title>
    <content type="html">&lt;p&gt;Rake has an annoying habit of putting it&amp;#8217;s own diagnostic line on the first line of output. You can strip that out with tail.&lt;/p&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;rake my_report:xml | tail -n+2 &amp;gt; output.xml&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
</content>
  </entry>
  <entry>
    <id>tag:rhnh.net,2008:Post/784</id>
    <published>2008-08-27T13:19:04+10:00</published>
    <updated>2008-08-27T13:19:04+10:00</updated>
    <link type="text/html" href="http://rhnh.net/2008/08/27/no-view-logic-in-models?utm_campaign=eyeballs&amp;utm_medium=feed&amp;utm_source=feed" rel="alternate" />
    <title>You don't need view logic in models</title>
    <content type="html">&lt;p&gt;&lt;a href="http://jakescruggs.blogspot.com/2008/08/im-thinking-of-putting-view-logic-into.html"&gt;Jake Scruggs wrote about moving view logic into his models&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;It&amp;#8217;s hard to tell without knowing the full dataset, but my approach to these sort of problems is to reduce the data down to the simplest possible form (usually a hash), and then use an algorithm to extract what I need.&lt;/p&gt;


	&lt;p&gt;&lt;a href="https://gist.github.com/7062/71ec7c0b47354cc3a06b39974f44c31ae9726a19"&gt;One commenter tried this&lt;/a&gt; and I think it&amp;#8217;s heading in the right direction. There is potentially quite a lot of duplication here &amp;#8211; the repetition of the layouts and scripts. To ease this it can sometimes be easier to inverse the key/values, for a more concise representation. You could reduce this even further if there were sensible defaults (if 90% of cars used a two_column layout, for instance) &amp;#8211; just replace the &lt;code&gt;raise&lt;/code&gt; in the following code.&lt;/p&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span class="c"&gt;# See original post for context&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="c"&gt;# Data&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;layouts = {&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;two_column&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;   =&amp;gt; [&lt;span class="co"&gt;Toyota&lt;/span&gt;, &lt;span class="co"&gt;Saturn&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;three_column&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; =&amp;gt; [&lt;span class="co"&gt;Hyundai&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;ford&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;         =&amp;gt; [&lt;span class="co"&gt;Ford&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;}&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;scripts =&amp;gt; {&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;discount&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; =&amp;gt; [&lt;span class="co"&gt;Hyundai&lt;/span&gt;, &lt;span class="co"&gt;Ford&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;poll&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;     =&amp;gt; [&lt;span class="co"&gt;Saturn&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;}&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="c"&gt;# Algorithm&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;find_key = lambda {|hash, car| &lt;tt&gt;
&lt;/tt&gt;  (&lt;tt&gt;
&lt;/tt&gt;    hash.detect {|key, types| &lt;tt&gt;
&lt;/tt&gt;      types.any? {|type| car.is_a?(type)}&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="c"&gt;# types.include?(car.class) if you're not using inheritance&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    } || raise(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;No entry for car: &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;car&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  ).first&lt;tt&gt;
&lt;/tt&gt;}&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;layout = find_key[layouts, &lt;span class="iv"&gt;@car&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;script = find_key[scripts, &lt;span class="iv"&gt;@car&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="iv"&gt;@stylesheets&lt;/span&gt; += [&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;layout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;theme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;].collect {|suffix| &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;layout&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;suffix&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;.css&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="iv"&gt;@scripts&lt;/span&gt;     += [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;script&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;.js&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;render &lt;span class="sy"&gt;:action&lt;/span&gt; =&amp;gt; find_view, &lt;span class="sy"&gt;:layout&lt;/span&gt; =&amp;gt; layout&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;This is preferable to putting this data in your object hierarchy for all the normal reasons, especially since it keeps view logic where you expect to find it and doesn&amp;#8217;t muddy up your models.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:rhnh.net,2008:Post/783</id>
    <published>2008-08-04T12:03:00+10:00</published>
    <updated>2008-08-04T12:03:55+10:00</updated>
    <link type="text/html" href="http://rhnh.net/2008/08/04/speeding-up-rails-initialization?utm_campaign=eyeballs&amp;utm_medium=feed&amp;utm_source=feed" rel="alternate" />
    <title>Speeding up Rails Initialization</title>
    <content type="html">&lt;p&gt;Chad Wooley just posted a tip to &lt;a href="http://pivots.pivotallabs.com/users/chad/blog/articles/482-standup-8-1-2008"&gt;get rails starting up faster&lt;/a&gt;. Which is real, except it doesn&amp;#8217;t work if you&amp;#8217;re using ActiveScaffold. This is due to a load ordering problem &amp;#8211; ActiveScaffold monkey patches the &lt;code&gt;Resource&lt;/code&gt; class used by routes &lt;em&gt;after&lt;/em&gt; routes have been parsed the first time, and relies on the re-parsing triggered by the inflections change.&lt;/p&gt;


	&lt;p&gt;To fix this, you can explicitly require the monkey patch just before you draw your routes (it doesn&amp;#8217;t depend on anything else in ActiveScaffold).&lt;/p&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&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 ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span class="c"&gt;# config/routes.rb&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;ActionController&lt;/span&gt;::&lt;span class="co"&gt;Routing&lt;/span&gt;::&lt;span class="co"&gt;Routes&lt;/span&gt;.draw &lt;span class="r"&gt;do&lt;/span&gt; |map|&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# Explicitly require this, otherwise it won't get loaded before we parse our resources time&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;vendor/plugins/active_scaffold/lib/extensions/resources.rb&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;span class="c"&gt;# Your routes go here...&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;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;Yes it&amp;#8217;s a hack on top of hack, but I get my console 30% quicker, so I&amp;#8217;m running with it.&lt;/p&gt;


	&lt;p&gt;Tested on 2.0.2&lt;/p&gt;</content>
  </entry>
</feed>
