<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>The Geek Blog of Codora </title>
  <id>tag:geekblog.codora.com,2009:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.7.3">Mephisto Noh-Varr</generator>
  
  <link href="http://geekblog.codora.com/" rel="alternate" type="text/html" />
  <updated>2008-04-18T10:46:41Z</updated>
  <link rel="self" href="http://feeds.feedburner.com/TheGeekBlogOfCodora" type="application/atom+xml" /><feedburner:browserFriendly></feedburner:browserFriendly><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry xml:base="http://geekblog.codora.com/">
    <author>
      <name>Duff OMelia</name>
    </author>
    <id>tag:geekblog.codora.com,2008-04-18:1160</id>
    <published>2008-04-18T10:45:00Z</published>
    <updated>2008-04-18T10:46:41Z</updated>
    <link href="http://geekblog.codora.com/2008/4/18/command-history-meme" rel="alternate" type="text/html" />
    <title>Command history meme</title>
<content type="html">
            &lt;p&gt;Why not?  &lt;a href="http://blog.codefront.net/2008/04/18/command-history-meme"&gt;Everyone else&lt;/a&gt; seems to be.&lt;/p&gt;


&lt;code&gt;
history | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head
&lt;/code&gt;

&lt;pre&gt;
125 git
66 gs
64 rake
56 cd
45 cap
33 ls
18 g
16 ./script/server
9 mv
8 svn

&lt;/pre&gt;

&lt;code&gt;g&lt;/code&gt; is an alias for &lt;code&gt;git&lt;/code&gt;.  &lt;code&gt;gs&lt;/code&gt; is an alias for &lt;code&gt;git status&lt;/code&gt;.  I like Chu’s alias of &lt;code&gt;ss&lt;/code&gt; for &lt;code&gt;script/server&lt;/code&gt;.  I think I’ll do that.
          </content>  </entry>
  <entry xml:base="http://geekblog.codora.com/">
    <author>
      <name>Duff OMelia</name>
    </author>
    <id>tag:geekblog.codora.com,2008-04-16:1158</id>
    <published>2008-04-16T09:12:00Z</published>
    <updated>2008-04-16T09:14:45Z</updated>
    <link href="http://geekblog.codora.com/2008/4/16/cap-deploy-pending" rel="alternate" type="text/html" />
    <title>cap deploy:pending</title>
<content type="html">
            &lt;p&gt;Running `cap deploy:pending` displays the commits since your last deploy.  I wanted it’s output to be a bit different primarily so I could send a message to the others on the team about what’s just been deployed.&lt;/p&gt;


	&lt;p&gt;Specifically, I wanted the output to look something like this:&lt;/p&gt;


&lt;pre&gt;
Deployment revision 49c45b7
I deployed the latest. It includes:

* Added avatar support  (Duff)
* Cleaned up the project switcher  (Alex)
&lt;/pre&gt;

	&lt;p&gt;To do that, I added the following capistrano recipe:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;namespace &lt;span class="sy"&gt;:deploy&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;
  namespace &lt;span class="sy"&gt;:pending&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;
    desc &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;lt;&amp;lt;-DESC&lt;/span&gt;&lt;/span&gt;&lt;span class="s"&gt;&lt;span class="k"&gt;
      Show the commits since the last deploy&lt;/span&gt;&lt;span class="dl"&gt;
    DESC&lt;/span&gt;&lt;/span&gt;
    task &lt;span class="sy"&gt;:default&lt;/span&gt;, &lt;span class="sy"&gt;:except&lt;/span&gt; =&amp;gt; { &lt;span class="sy"&gt;:no_release&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;true&lt;/span&gt; } &lt;span class="r"&gt;do&lt;/span&gt;
      deployed_already = current_revision
      to_be_deployed = &lt;span class="sh"&gt;&lt;span class="dl"&gt;`&lt;/span&gt;&lt;span class="k"&gt;git rev-parse --short &amp;quot;HEAD&amp;quot;&lt;/span&gt;&lt;span class="dl"&gt;`&lt;/span&gt;&lt;/span&gt;

      puts &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="k"&gt;Deployment revision &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;to_be_deployed&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
      puts &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;I deployed the latest. It includes:&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
      puts
      system(&lt;span class="s"&gt;&lt;span class="dl"&gt;%Q{&lt;/span&gt;&lt;span class="k"&gt;git log --no-merges --pretty=format:&amp;quot;* %s %b (%cn)&amp;quot; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;deployed_already&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;.. | replace '&amp;lt;unknown&amp;gt;' ''&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;)
      puts &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="r"&gt;end&lt;/span&gt;

  &lt;span class="r"&gt;end&lt;/span&gt;
&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;Then I added a hook in my deploy.rb to run this automatically whenever someone deploys:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;before &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;deploy:update_code&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;deploy:pending:default&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;The next piece of automation I’d like is to have it automatically post a message to &lt;a href="http://basecamphq.com/"&gt;basecamp&lt;/a&gt;.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://geekblog.codora.com/">
    <author>
      <name>Duff OMelia</name>
    </author>
    <id>tag:geekblog.codora.com,2008-01-08:796</id>
    <published>2008-01-08T16:44:00Z</published>
    <updated>2008-01-31T12:17:37Z</updated>
    <link href="http://geekblog.codora.com/2008/1/8/rails-plugin-svn_messages-updated" rel="alternate" type="text/html" />
    <title>Rails plugin - svn_messages (updated)</title>
<content type="html">
            &lt;p&gt;I created a rails plugin to help me keep clients up to date on the status of projects.  This post is an update to &lt;a href="http://geekblog.codora.com/2007/8/22/rails-plugin-svn-messages"&gt;the original&lt;/a&gt; svn_messages plugin.&lt;/p&gt;


	&lt;p&gt;The plugin now uses capistrano 2 (Multistage).  I use it in 2 instances – whenever I deploy a site, and whenever I send a weekly status report.  For a deployment, this is what I type at the command line:&lt;/p&gt;


&lt;pre&gt;
cap staging svn:deployment_report
&lt;/pre&gt;

	&lt;p&gt;This gives me the following output:&lt;/p&gt;


&lt;pre&gt;
Deployment to staging (Revision 34)
I deployed the latest.  It includes:

* Started adding user registration system. (domelia)
* Now translating validation errors and their attribute names. (bjones)
* Reorganized views a bit. (domelia)
* Now sending activation email when user signs up. (fsmith)
* Added support for "remember me" when logging in. (domelia)
&lt;/pre&gt;

I could have also typed:
&lt;pre&gt;
cap production svn:deployment_report
&lt;/pre&gt;

	&lt;p&gt;For a weekly status report, I type the following:&lt;/p&gt;


&lt;pre&gt;
cap svn:messages r=70 u=domelia
&lt;/pre&gt;

	&lt;p&gt;70 is the oldest subversion revision I care about.  domelia is me.  I specify this because I only care about the svn commits that I personally made.  This gives me the following output:&lt;/p&gt;


&lt;pre&gt;
* Started adding user registration system.
* Reorganized views a bit. 
* Added support for "remember me" when logging in.
&lt;/pre&gt;

	&lt;p&gt;I like the plugin because I can keep clients up to date and spend very little time doing it.&lt;/p&gt;


	&lt;p&gt;To install:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;svn export https&lt;span class="sy"&gt;:/&lt;/span&gt;/terralien.devguard.com/svn/projects/plugins/svn_messages vendor/plugins/svn_messages&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


If you’d like this deployment report to happen every time you deploy, you can add the folllowing to your deploy.rb:
&lt;pre&gt;
before  "deploy:update_code", "svn:deployment_report" 
&lt;/pre&gt;
          </content>  </entry>
  <entry xml:base="http://geekblog.codora.com/">
    <author>
      <name>Duff OMelia</name>
    </author>
    <id>tag:geekblog.codora.com,2007-08-22:147</id>
    <published>2007-08-22T16:16:00Z</published>
    <updated>2008-01-08T20:52:38Z</updated>
    <link href="http://geekblog.codora.com/2007/8/22/rails-plugin-svn-messages" rel="alternate" type="text/html" />
    <title>Rails Plugin - svn_messages</title>
<content type="html">
            &lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;:&lt;/strong&gt; This plugin &lt;a href="http://geekblog.codora.com/2008/1/8/rails-plugin-svn_messages-updated"&gt;has been updated&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;I created a rails plugin to help me keep clients up to date on the status of projects.  I use it in 2 instances – whenever I deploy a site, and whenever I send a weekly status report.  For a deployment this is what I type at the command line:&lt;/p&gt;


&lt;pre&gt;
rake svn:messages r=70
&lt;/pre&gt;

	&lt;p&gt;70 is the oldest subversion revision I care about.  This gives me the following output:&lt;/p&gt;


&lt;pre&gt;
* Started adding user registration system. (domelia)
* Now translating validation errors and their attribute names. (domelia)
* Reorganized views a bit. (domelia)
* Now sending activation email when user signs up. (domelia)
* Added support for "remember me" when logging in. (domelia)
&lt;/pre&gt;

	&lt;p&gt;For my deployment report, I typically remove the svn messages that aren’t immediately visible in the site or that don’t matter too much to the client.  So, I’d remove “reorganized views a bit”.&lt;/p&gt;


	&lt;p&gt;For a weekly status report, I only care about the svn commits that I personally made.  In that case, I’d say something like:&lt;/p&gt;


&lt;pre&gt;
rake svn:messages r=32 u=domelia
&lt;/pre&gt;

	&lt;p&gt;This would give me similar output, except it will only show me the commits made by the domelia user.&lt;/p&gt;


	&lt;p&gt;I like the plugin because I can keep clients up to date and spend very little time doing it.&lt;/p&gt;


	&lt;p&gt;To install:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;svn export https&lt;span class="sy"&gt;:/&lt;/span&gt;/terralien.devguard.com/svn/projects/plugins/svn_messages vendor/plugins/svn_messages&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
          </content>  </entry>
  <entry xml:base="http://geekblog.codora.com/">
    <author>
      <name>Duff OMelia</name>
    </author>
    <id>tag:geekblog.codora.com,2007-06-15:118</id>
    <published>2007-06-15T13:51:00Z</published>
    <updated>2007-06-15T13:54:05Z</updated>
    <link href="http://geekblog.codora.com/2007/6/15/custom-mephisto" rel="alternate" type="text/html" />
    <title>Custom Mephisto</title>
<content type="html">
            &lt;p&gt;I’ve really been enjoying &lt;a href="http://mephisto.stikipad.com/help/"&gt;Mephisto&lt;/a&gt;, the blogging software that’s running this site.&lt;/p&gt;


	&lt;p&gt;I wanted to create &lt;a href="http://revnut.com"&gt;another blog for some reviews&lt;/a&gt; I’ve written.  So I started with the standard Mephisto and chose a theme from a &lt;a href="http://mephisto-themes.nanorails.com/gallery"&gt;Mephisto theme gallery&lt;/a&gt; and things were looking pretty nice.  Then I wanted to start making some customizations.  I considered using the plugin system that ships with Mephisto but I thought I’d just opt for a completely custom system and see if it would be difficult to have complete flexibility.&lt;/p&gt;


	&lt;p&gt;It turns out that it was super cinchy to do.  Mephisto is open source, and it’s a well-written rails app.  The technology world sure is changing in some fascinating ways.  When you put some things together like &lt;a href="http://www.ruby-lang.org/en/"&gt;ruby&lt;/a&gt;, &lt;a href="http://www.rubyonrails.org/"&gt;rails&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Open_source"&gt;open source&lt;/a&gt;, the &lt;a href="http://www.apple.com/mac/"&gt;mac&lt;/a&gt;, &lt;a href="http://quicksilver.blacktree.com/"&gt;quicksilver&lt;/a&gt;, and &lt;a href="http://macromates.com/"&gt;textmate&lt;/a&gt;, things start to get pretty exciting for developers.&lt;/p&gt;


	&lt;p&gt;I’ve made a few customizations so far and I’m not sure if I’ll ever want to customize it further.  For now though, it’s much easier to mark a review as thumbs up or thumbs down and it’s easy to specify an amazon url for a review and know that it’ll show up with the correct amazon associates url.&lt;/p&gt;


	&lt;p&gt;One of the many amazing things about Rails is that you can so easily sit down and &lt;strong&gt;completely&lt;/strong&gt; modify a Rails app you’ve never seen before, primarily because the framework makes it painful to step outside convention.  I couldn’t even imagine doing something like this in some of the other web frameworks out there.&lt;/p&gt;


	&lt;p&gt;Here’s what &lt;a href="http://revnut.com"&gt;Revnut&lt;/a&gt; looks like so far.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://geekblog.codora.com/">
    <author>
      <name>Duff OMelia</name>
    </author>
    <id>tag:geekblog.codora.com,2007-05-08:65</id>
    <published>2007-05-08T10:17:00Z</published>
    <updated>2007-05-08T10:18:26Z</updated>
    <link href="http://geekblog.codora.com/2007/5/8/rjs-for-local-javascript" rel="alternate" type="text/html" />
    <title>RJS for local javascript</title>
<content type="html">
            &lt;p&gt;There are times when I need to write a local javascript function (without needing a round trip to the server) and I’d like to use &lt;span class="caps"&gt;RJS&lt;/span&gt; rather than writing the function in pure javascript.  Why would I want to use &lt;span class="caps"&gt;RJS&lt;/span&gt;?&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;The syntax is clean and it’s often less code than pure javscript. &lt;/li&gt;
		&lt;li&gt;When writing this function, I can mix in powerful Ruby constructs. &lt;/li&gt;
		&lt;li&gt;It’s consistent with the other &lt;span class="caps"&gt;RJS&lt;/span&gt; in the project.&lt;/li&gt;
		&lt;li&gt;I automatically get the function wrapped up in a &lt;span class="caps"&gt;CDATA&lt;/span&gt; tag.&lt;/li&gt;
		&lt;li&gt;I automatically get exceptions handled by giving me an alert of the problem.&lt;/li&gt;
		&lt;li&gt;It’s easy to conditionally exclude some of the javascript.&lt;/li&gt;
		&lt;li&gt;My rails views look cleaner.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Here’s an example from a rails view (new.erb):&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&amp;lt;%= define_js_function(&lt;span class="sy"&gt;:my_cool_local_function&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt; | page | 
    page[&lt;span class="sy"&gt;:choice_entry_area&lt;/span&gt;].hide &lt;span class="r"&gt;unless&lt;/span&gt; &lt;span class="iv"&gt;@question&lt;/span&gt;.multiple_choice?
    page[&lt;span class="sy"&gt;:add_answer_link&lt;/span&gt;].show
    page[&lt;span class="sy"&gt;:add_answer_button&lt;/span&gt;].hide
  &lt;span class="r"&gt;end&lt;/span&gt;  
&lt;span class="s"&gt;&lt;span class="dl"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;So where’d this define_js_function method come from?  I added it to ApplicationHelper.  Here it is:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;define_js_function&lt;/span&gt;(function_name, &amp;amp;block)
    parens = function_name.kind_of?(&lt;span class="co"&gt;Symbol&lt;/span&gt;) ? &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;()&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; : &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    update_page_tag &lt;span class="r"&gt;do&lt;/span&gt; | page |
      page &amp;lt;&amp;lt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;function &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;function_name&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;parens&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; {&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span class="r"&gt;yield&lt;/span&gt; page
      page &amp;lt;&amp;lt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="r"&gt;end&lt;/span&gt;  
  &lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


When the view is rendered in the browser, the following javascript gets generated:
&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&amp;lt;script type=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;text/javascript&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&amp;gt;
&lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;&amp;lt;![&lt;span class="co"&gt;CDATA&lt;/span&gt;[
try {
function my_cool_local_function() {
&lt;span class="er"&gt;$&lt;/span&gt;(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;choice_entry_area&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).hide();
&lt;span class="er"&gt;$&lt;/span&gt;(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;add_answer_link&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).show();
&lt;span class="er"&gt;$&lt;/span&gt;(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;add_answer_button&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).hide();
}
} catch (e) { alert(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;RJS error:&lt;/span&gt;&lt;span class="k"&gt;\n&lt;/span&gt;&lt;span class="k"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; + e.toString()); alert(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;function my_cool_local_function() {&lt;/span&gt;&lt;span class="k"&gt;\n&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="k"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;choice_entry_area&lt;/span&gt;&lt;span class="k"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;).hide();&lt;/span&gt;&lt;span class="k"&gt;\n&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="k"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;add_answer_link&lt;/span&gt;&lt;span class="k"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;).show();&lt;/span&gt;&lt;span class="k"&gt;\n&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="k"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;add_answer_button&lt;/span&gt;&lt;span class="k"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;).hide();&lt;/span&gt;&lt;span class="k"&gt;\n&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;); throw e }
&lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;]]&amp;gt;
&amp;lt;&lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;script&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;If the javascript function you’re creating takes no arguments, then you simply pass a symbol to define_js_function to specify the function name.  If your function takes arguments, then you can pass in a string which contains those arguments like so:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&amp;lt;%= define_js_function(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;add_tag(tag)&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt; | page | 
    page &amp;lt;&amp;lt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$('tag_list_str').value += tag&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="r"&gt;end&lt;/span&gt;  
&lt;span class="s"&gt;&lt;span class="dl"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
          </content>  </entry>
  <entry xml:base="http://geekblog.codora.com/">
    <author>
      <name>Duff OMelia</name>
    </author>
    <id>tag:geekblog.codora.com,2007-05-04:55</id>
    <published>2007-05-04T16:19:00Z</published>
    <updated>2007-05-04T16:20:41Z</updated>
    <link href="http://geekblog.codora.com/2007/5/4/tuaw-category-feeds" rel="alternate" type="text/html" />
    <title>TUAW category feeds</title>
<content type="html">
            &lt;p&gt;I’ve been subscribed to the &lt;a href="http://tuaw.com" title="TUAW"&gt;Unofficial Apple Weblog&lt;/a&gt; for quite awhile.  It’s in my NetNewsWire folder entitled “Can’t Keep Up” (the place containing feeds that have so much content that I’ll never be able to read them all.)&lt;/p&gt;


	&lt;p&gt;I’m probably the last person in the Mac universe to realize that there are &lt;a href="http://www.m.tuaw.com/feeds/"&gt;category specific feeds&lt;/a&gt; available so that you can subscribe to a subset of &lt;span class="caps"&gt;TUAW&lt;/span&gt;.  This is outstanding because there are certainly parts of &lt;span class="caps"&gt;TUAW&lt;/span&gt; that are quite interesting to me.&lt;/p&gt;


	&lt;p&gt;I started out by subscribing to the following categories: Mac 101, Hacks, Tips and Tricks, Cool Tools, Terminal Tips, How To’s, and Productivity.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://geekblog.codora.com/">
    <author>
      <name>Duff OMelia</name>
    </author>
    <id>tag:geekblog.codora.com,2007-05-03:50</id>
    <published>2007-05-03T12:50:00Z</published>
    <updated>2008-04-17T18:50:51Z</updated>
    <link href="http://geekblog.codora.com/2007/5/3/rails-plugin-cadillacedgedeploy" rel="alternate" type="text/html" />
    <title>Rails Plugin - cadillac_edge_deploy</title>
<content type="html">
            &lt;p&gt;Is your deployed rails application frozen to a particular revision?  If so, when a new version of rails is released how easy is it for you to upgrade?&lt;/p&gt;


	&lt;p&gt;Are you living on the edge of rails?  If so, how do you move to a more recent revision when you notice an enhancement you want to take advantage of?&lt;/p&gt;


	&lt;p&gt;Switching to a different version of rails should be easy.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.clarkware.com/about.html"&gt;Mike Clark&lt;/a&gt; described a number of ways to manage your rails versions in &lt;a href="http://clarkware.com/cgi/blosxom/2007/01/18#ManagingVersionsWithCap"&gt;this blog post&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Mike wrote of a “Cadillac Edge Deploy Approach” in referring to Rick Olson’s code that makes managing rails versions quite cinchy.&lt;/p&gt;


	&lt;p&gt;This plugin is basically a rip-off of that blog post and Rick’s code.&lt;/p&gt;


	&lt;p&gt;I refactored things a bit primarily because I needed the approach to work even if Rails wasn’t installed on the server I was deploying to. I’ve also changed it since to work with git rather than svn.&lt;/p&gt;


&lt;h1&gt;Example Usage&lt;/h1&gt;


	&lt;p&gt;To use the plugin, all you need to do is add the following to your deploy.rb:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;set &lt;span class="sy"&gt;:rails_revision&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;745359a49452da34978724144eaa318b8a363e08&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;When you’d like the server to start using a different revision of rails, just adjust the rails_revision variable.&lt;/p&gt;


	&lt;p&gt;To install the plugin:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;./script/plugin install git&lt;span class="sy"&gt;:/&lt;/span&gt;/github.com/duff/cadillac_edge_deploy.git&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
          </content>  </entry>
  <entry xml:base="http://geekblog.codora.com/">
    <author>
      <name>Duff OMelia</name>
    </author>
    <id>tag:geekblog.codora.com,2007-03-15:19</id>
    <published>2007-03-15T15:06:00Z</published>
    <updated>2007-03-29T19:37:08Z</updated>
    <link href="http://geekblog.codora.com/2007/3/15/textmate-ternary-operator-command" rel="alternate" type="text/html" />
    <title>TextMate ternary operator command</title>
<content type="html">
            &lt;p&gt;Ever have a simple conditional that you’d like to quickly switch to ternary operator syntax?  For example, you have a simple piece of code like this:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;if&lt;/span&gt; x &amp;gt; y
  result = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Fred&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class="r"&gt;else&lt;/span&gt;
  result = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Joe&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;and you’d rather it look like this:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;result = (x &amp;gt; y) ? &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Fred&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;Joe&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;Or, you’ve got this:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;if&lt;/span&gt; x &amp;gt; y
  &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Fred&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class="r"&gt;else&lt;/span&gt;
  &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Joe&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;And you’d like this:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;(x &amp;gt; y) ? &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Fred&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;Joe&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;I wrote a little &lt;a href="http://macromates.com/"&gt;TextMate&lt;/a&gt; command to help.  It allows you to select the 5 lines of the conditional and convert it to ternary operator syntax by pressing a keyboard shortcut.  Here’s what it looks like:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="c"&gt;#!/usr/bin/env ruby&lt;/span&gt;

original = &lt;span class="co"&gt;STDIN&lt;/span&gt;.read
result = original
&lt;span class="r"&gt;begin&lt;/span&gt;
  lines = original.split(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
  &lt;span class="r"&gt;if&lt;/span&gt; lines.size == &lt;span class="i"&gt;5&lt;/span&gt;
    space, conditional = &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;(&lt;/span&gt;&lt;span class="ch"&gt;\s&lt;/span&gt;&lt;span class="k"&gt;*)if&lt;/span&gt;&lt;span class="ch"&gt;\s&lt;/span&gt;&lt;span class="k"&gt;(.*)$&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;.match(lines.first)[&lt;span class="i"&gt;1&lt;/span&gt;..&lt;span class="i"&gt;2&lt;/span&gt;]
    if_parts = lines[&lt;span class="i"&gt;1&lt;/span&gt;].split(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
    &lt;span class="r"&gt;if&lt;/span&gt; if_parts.size == &lt;span class="i"&gt;2&lt;/span&gt;
      variable = if_parts.first.strip
      if_result = if_parts[&lt;span class="i"&gt;1&lt;/span&gt;].strip
      else_result = &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;.*?=(.*)&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;.match(lines[&lt;span class="i"&gt;3&lt;/span&gt;])[&lt;span class="i"&gt;1&lt;/span&gt;].strip
      result = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;space&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;variable&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; = (&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;conditional&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;) ? &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;if_result&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; : &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;else_result&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="r"&gt;elsif&lt;/span&gt; if_parts.size == &lt;span class="i"&gt;1&lt;/span&gt;
      result = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;space&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;(&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;conditional&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;) ? &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;lines[&lt;span class="i"&gt;1&lt;/span&gt;].strip&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; : &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;lines[&lt;span class="i"&gt;3&lt;/span&gt;].strip&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="r"&gt;end&lt;/span&gt;
  &lt;span class="r"&gt;end&lt;/span&gt;

&lt;span class="r"&gt;rescue&lt;/span&gt; &lt;span class="co"&gt;Exception&lt;/span&gt; =&amp;gt; e
&lt;span class="r"&gt;ensure&lt;/span&gt; 
  print result
&lt;span class="r"&gt;end&lt;/span&gt;  &lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


I set the properties of the command to the following:
	&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Save&lt;/strong&gt; : Nothing&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Input&lt;/strong&gt; : Selected Text or Nothing&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Output&lt;/strong&gt; : Replace Selected Text&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Activation&lt;/strong&gt; : Key Equivalent (Specify whatever Key Equivalent you’d like)&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Scope Selector&lt;/strong&gt; : source.ruby&lt;/li&gt;
	&lt;/ul&gt;
          </content>  </entry>
  <entry xml:base="http://geekblog.codora.com/">
    <author>
      <name>Duff OMelia</name>
    </author>
    <id>tag:geekblog.codora.com,2007-03-01:12</id>
    <published>2007-03-01T17:08:00Z</published>
    <updated>2008-04-18T10:17:53Z</updated>
    <link href="http://geekblog.codora.com/2007/3/1/prettied_up_test_output_using_assert_arrays_equal" rel="alternate" type="text/html" />
    <title>Prettied up test output using assert_arrays_equal</title>
<content type="html">
            &lt;p&gt;I’ve got a pretty simple test:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;test_relationships&lt;/span&gt;
  wellspring = churches(&lt;span class="sy"&gt;:wellspring&lt;/span&gt;)
  cleaning_crew = &lt;span class="co"&gt;Group&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;Cleaning Crew&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:church&lt;/span&gt; =&amp;gt; wellspring)
  assert_equal([cleaning_crew], wellspring.groups)
&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;The problem is that when this test fails, I get a ridiculous amount of output and it’s difficult to quickly determine why the test is failing.  Here’s the output I get:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="i"&gt;1&lt;/span&gt;) &lt;span class="co"&gt;Failure&lt;/span&gt;:
test_relationships:&lt;span class="i"&gt;10&lt;/span&gt;
&amp;lt;[&lt;span class="c"&gt;#&amp;lt;Group:0x3492918&lt;/span&gt;
  &lt;span class="iv"&gt;@attributes&lt;/span&gt;=
   {&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&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;Cleaning Crew&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;church_id&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class="i"&gt;1&lt;/span&gt;,
    &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class="i"&gt;32&lt;/span&gt;,
at top level &lt;span class="r"&gt;in&lt;/span&gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;created_at&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class="co"&gt;Thu&lt;/span&gt; &lt;span class="co"&gt;Mar&lt;/span&gt; &lt;span class="i"&gt;01&lt;/span&gt; &lt;span class="i"&gt;15&lt;/span&gt; at line &lt;span class="i"&gt;56&lt;/span&gt;
  &lt;span class="iv"&gt;@church&lt;/span&gt;=
at top level &lt;span class="r"&gt;in&lt;/span&gt; &lt;span class="c"&gt;#&amp;lt;Church at line 0&lt;/span&gt;
    &lt;span class="iv"&gt;@attributes&lt;/span&gt;=
     {&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&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;Wellspring Community Church&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;account_owner_id&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&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;1&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;timezone&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&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;Alaska&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;subdomain&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&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;wellspring&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;id&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&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;1&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;tz_name&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class="pc"&gt;nil&lt;/span&gt;},
    &lt;span class="iv"&gt;@groups&lt;/span&gt;=
at top level &lt;span class="r"&gt;in&lt;/span&gt; &lt;span class="c"&gt;#&amp;lt;Group at line 0&lt;/span&gt;
  &lt;span class="iv"&gt;@errors&lt;/span&gt;=
at top level &lt;span class="r"&gt;in&lt;/span&gt; &lt;span class="c"&gt;#&amp;lt;ActiveRecord::Errors at line 0&lt;/span&gt;
  &lt;span class="iv"&gt;@new_record&lt;/span&gt;=&lt;span class="pc"&gt;false&lt;/span&gt;&amp;gt;]&amp;gt; expected but was
&amp;lt;[&lt;span class="c"&gt;#&amp;lt;Group:0x348c0a4 @attributes={&amp;quot;name&amp;quot;=&amp;gt;&amp;quot;Elders&amp;quot;, &amp;quot;church_id&amp;quot;=&amp;gt;&amp;quot;1&amp;quot;, &amp;quot;id&amp;quot;=&amp;gt;&amp;quot;1&amp;quot;, &amp;quot;created_at&amp;quot;=&amp;gt;&amp;quot;2007-03-01 10:01:58&amp;quot;}&amp;gt;, #&amp;lt;Group:0x348c07c @attributes={&amp;quot;name&amp;quot;=&amp;gt;&amp;quot;Children's Ministry&amp;quot;, &amp;quot;church_id&amp;quot;=&amp;gt;&amp;quot;1&amp;quot;, &amp;quot;id&amp;quot;=&amp;gt;&amp;quot;4&amp;quot;, &amp;quot;created_at&amp;quot;=&amp;gt;&amp;quot;2007-03-01 10:01:58&amp;quot;}&amp;gt;, #&amp;lt;Group:0x348c054 @attributes={&amp;quot;name&amp;quot;=&amp;gt;&amp;quot;Cleaning Crew&amp;quot;, &amp;quot;church_id&amp;quot;=&amp;gt;&amp;quot;1&amp;quot;, &amp;quot;id&amp;quot;=&amp;gt;&amp;quot;32&amp;quot;, &amp;quot;created_at&amp;quot;=&amp;gt;&amp;quot;2007-03-01 15:56:38&amp;quot;}&amp;gt;]&amp;gt;.&lt;/span&gt;

&lt;span class="i"&gt;1&lt;/span&gt; tests, &lt;span class="i"&gt;1&lt;/span&gt; assertions, &lt;span class="i"&gt;1&lt;/span&gt; failures, &lt;span class="i"&gt;0&lt;/span&gt; errors&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;This is what I’d like the output to look like:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt; &lt;span class="i"&gt;1&lt;/span&gt;) &lt;span class="co"&gt;Failure&lt;/span&gt;:
test_relationships(&lt;span class="co"&gt;GroupTest&lt;/span&gt;)
method assert_arrays_equal &lt;span class="r"&gt;in&lt;/span&gt; test_unit_extras.rb at line &lt;span class="i"&gt;8&lt;/span&gt;
method test_relationships &lt;span class="r"&gt;in&lt;/span&gt; group_test.rb at line &lt;span class="i"&gt;11&lt;/span&gt;
&amp;lt;&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Cleaning Crew&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&amp;gt; expected but was
&amp;lt;&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Elders, Children's Ministry, Cleaning Crew&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&amp;gt;.

&lt;span class="i"&gt;1&lt;/span&gt; tests, &lt;span class="i"&gt;1&lt;/span&gt; assertions, &lt;span class="i"&gt;1&lt;/span&gt; failures, &lt;span class="i"&gt;0&lt;/span&gt; errors&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;To me, that’s a bit easier to read.  Here’s how I did it.  The test has a small change.  Instead of calling assert_equal, it calls assert_arrays_equal.  So the test now looks like this:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;test_relationships&lt;/span&gt;
  wellspring = churches(&lt;span class="sy"&gt;:wellspring&lt;/span&gt;)
  cleaning_crew = &lt;span class="co"&gt;Group&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;Cleaning Crew&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:church&lt;/span&gt; =&amp;gt; wellspring)
  assert_arrays_equal([cleaning_crew], wellspring.groups, &lt;span class="sy"&gt;:name&lt;/span&gt;)
&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;Where did assert_arrays_equal come from?  You can get it by installing the plugin I just created:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;./script/plugin install git://github.com/duff/assert_arrays_equal.git&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;assert_arrays_equal allows you to specify which method you’d like to be called on the objects in your arrays for the output message.  It still asserts that the arrays are actually equal.  The failure error message now uses the method you specify.  In the test above, I specified the :name method because I want Group.#name to be called rather than Group#inspect.  If you don’t specify a method, it defaults to :to_s.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://geekblog.codora.com/">
    <author>
      <name>Duff OMelia</name>
    </author>
    <id>tag:geekblog.codora.com,2007-02-27:9</id>
    <published>2007-02-27T20:01:00Z</published>
    <updated>2007-02-27T20:35:01Z</updated>
    <link href="http://geekblog.codora.com/2007/2/27/viewing-a-page-in-a-browser" rel="alternate" type="text/html" />
    <title>Viewing a page in a browser</title>
<content type="html">
            &lt;p&gt;I’ve been doing a bunch of integration testing of a rails site lately.  I have found it quite useful to be able to quickly view the current page in a browser.&lt;/p&gt;


	&lt;p&gt;I added the following method to my integration testing &lt;span class="caps"&gt;DSL&lt;/span&gt;:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;module&lt;/span&gt; &lt;span class="cl"&gt;IntegrationDsl&lt;/span&gt;

  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;view&lt;/span&gt;
    filename = &lt;span class="co"&gt;File&lt;/span&gt;.dirname(&lt;span class="pc"&gt;__FILE__&lt;/span&gt;) + &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;/integration/.integration_test_output_for_browser.html&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="co"&gt;File&lt;/span&gt;.open(filename, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;w+&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) { | file | file.write(response.body) }
    &lt;span class="sh"&gt;&lt;span class="dl"&gt;`&lt;/span&gt;&lt;span class="k"&gt;open &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;filename&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;`&lt;/span&gt;&lt;/span&gt;
  &lt;span class="r"&gt;end&lt;/span&gt;

&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;It simply writes out the response body to a file and then opens it (using the `open` on a mac).&lt;/p&gt;


	&lt;p&gt;So now in my integration test, I can view the current page in a browser like this:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;test_feature&lt;/span&gt;
  s = new_session_as &lt;span class="sy"&gt;:duff&lt;/span&gt;
  s.view
&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
          </content>  </entry>
  <entry xml:base="http://geekblog.codora.com/">
    <author>
      <name>Duff OMelia</name>
    </author>
    <id>tag:geekblog.codora.com,2007-02-27:8</id>
    <published>2007-02-27T19:17:00Z</published>
    <updated>2007-02-27T20:35:18Z</updated>
    <link href="http://geekblog.codora.com/2007/2/27/clicking-a-link" rel="alternate" type="text/html" />
    <title>Clicking a link</title>
<content type="html">
            &lt;p&gt;There have been times when integration testing a rails site that I’ve wanted to click a link on a page without caring about it’s route or url.&lt;/p&gt;


	&lt;p&gt;So let’s say the following exists on a page in my app:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="ta"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="ta"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="an"&gt;href&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;http://meresheep.com/users/4;resend_activation_email&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="ta"&gt;&amp;gt;&lt;/span&gt;
      resend your activation email
  &lt;span class="ta"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="ta"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;In my integration test, I can now do things like this:&lt;/p&gt;


&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;test_non_activated_user&lt;/span&gt;
  s = new_session_as &lt;span class="sy"&gt;:duff&lt;/span&gt;
  s.click_link(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;resend your activation email&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
  s.assert_template(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;invitation_sent&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


To get this functionality, I added the following method to my integration testing &lt;span class="caps"&gt;DSL&lt;/span&gt;:
&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;module&lt;/span&gt; &lt;span class="cl"&gt;IntegrationDsl&lt;/span&gt;

  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;click_link&lt;/span&gt;(link_text)
    assert_select(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, link_text, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Trying to click a link named '&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;link_text&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;' that did not exist&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt; | links |
      get_via_redirect links.first.attributes[&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;]   
    &lt;span class="r"&gt;end&lt;/span&gt;
  &lt;span class="r"&gt;end&lt;/span&gt;

&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;The test fails if the link doesn’t exist on the current page.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://geekblog.codora.com/">
    <author>
      <name>Duff OMelia</name>
    </author>
    <id>tag:geekblog.codora.com,2007-02-27:7</id>
    <published>2007-02-27T18:29:00Z</published>
    <updated>2007-03-05T19:24:44Z</updated>
    <link href="http://geekblog.codora.com/2007/2/27/tdd-rails-integration-style" rel="alternate" type="text/html" />
    <title>TDD - Rails integration style </title>
<content type="html">
            &lt;p&gt;I’ve been writing unit tests for many years.  I can’t live without them.  Writing code from a test-driven perspective became second nature for me a long time ago.&lt;/p&gt;


	&lt;p&gt;I’ve played with Rails integration tests on a few different projects now and each time I did, I found that there was a slight learning curve for using them.  I also found that the tests were often larger than the code I was actually testing.  The tests seemed brittle and they seemed to take &lt;strong&gt;such&lt;/strong&gt; a long time to write.&lt;/p&gt;


	&lt;p&gt;Recently I decided that I just needed to keep writing them for awhile to see if I could get good enough at them such that they were no longer a burden to write.  A conversation with &lt;a href="http://creativi.st/blog/"&gt;Robert&lt;/a&gt; certainly played a part in this decision.  Since I was working on a personal project this past week, it was a perfect opportunity.&lt;/p&gt;


	&lt;p&gt;What I’ve found is this.  Rails integration tests are amazing.  They were taking such a long time to write because I was new at it.  They were brittle because I didn’t know what I was doing.  The tests were long because I was testing things more than once and I wasn’t refactoring to a Domain Specific Language (DSL) &lt;a href="http://weblog.jamisbuck.org/2006/3/9/integration-testing-in-rails-1-1"&gt;like Jamis wrote about&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;The result is that my integration tests are now slim.  They’re cinchy to write and they’re getting easier as the &lt;span class="caps"&gt;DSL&lt;/span&gt; for the project improves.  I’ve gotten good enough at it that I can now write the integration test before implementing the feature.  They’re not taking very long to write at all.  It feels amazing knowing that the regression tests are accumulating and it’s becoming harder and harder to break the site I’m working on.&lt;/p&gt;


	&lt;p&gt;I realize now that the unit testing I did when starting out wasn’t test-driven at all.  I wrote unit tests after I wrote the code I was testing.  After developing some competence, I was able to switch over to test-driven unit tests.  A similar process has now happened with integration tests.&lt;/p&gt;


	&lt;p&gt;The 2 or 3 days it took to get up to speed was quite worth it.&lt;/p&gt;
          </content>  </entry>
</feed>
