<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>acts_as_martian</title>
	<atom:link href="http://blog.martiandesigns.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.martiandesigns.com</link>
	<description>%w{ruby rails}.each{ &#124;topic&#124; blog.post(topic) }</description>
	<pubDate>Fri, 15 May 2009 15:36:25 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5</generator>
	<language>en</language>
			<item>
		<title>RailsConf 2009 Recap</title>
		<link>http://blog.martiandesigns.com/2009/05/08/railsconf-2009-recap/</link>
		<comments>http://blog.martiandesigns.com/2009/05/08/railsconf-2009-recap/#comments</comments>
		<pubDate>Sat, 09 May 2009 00:36:36 +0000</pubDate>
		<dc:creator>adam pearson</dc:creator>
		
		<category><![CDATA[rails]]></category>

		<category><![CDATA[ruby]]></category>

		<category><![CDATA[railsconf]]></category>

		<guid isPermaLink="false">http://blog.martiandesigns.com/?p=18</guid>
		<description><![CDATA[Vegas On Rails
This was my first RailsConf, and it was at the Las Vegas Hilton.  Despite the unpopularity of the choice of venue, the conference was overwhelmingly entertaining and intellectually stimulating.  
I highly recommend watching the keynotes. In particular: DHH&#8217;s opening keynote and (Uncle) Bob Martin&#8217;s excellent talk, &#8220;What Killed Smalltalk Could Kill [...]]]></description>
			<content:encoded><![CDATA[<h1 id="vegas_on_rails">Vegas On Rails</h1>
<p>This was my first RailsConf, and it was at the Las Vegas Hilton.  Despite the unpopularity of the choice of venue, the conference was overwhelmingly entertaining and intellectually stimulating.  </p>
<p>I <strong>highly</strong> recommend watching the <a href="http://railsconf.blip.tv">keynotes</a>. In particular: DHH&#8217;s opening keynote and (Uncle) Bob Martin&#8217;s excellent talk, &#8220;What Killed Smalltalk Could Kill Ruby Too&#8221;.</p>
<p>The RailsConf organization encouraged community videos, so hopefully footage of the sessions I highlighted below will become available as time goes on.</p>
<h1 id="rails_3_have_it_your_way">Rails 3 - Have It Your Way</h1>
<p>This new Rails slogan underscores the customizability of Rails 3.  DHH emphasized that you&#8217;ll still be able to hit the ground running with Rails out of the box, while more special problems can be solved by swapping out Rails components for more custom solutions. Want to use DataMapper instead of ActiveRecord?  No problem.  Want to use JQuery instead of Prototype?  As you wish.  </p>
<p>In short, Rails will be fully functional out of the box, but very customizable given time and configuration.</p>
<p>But it didn&#8217;t stop there.  A common theme in many sessions was : is Rails really necessary for <em>every</em> web application you write?  Some sessions even focused entirely on non-Rails technologies.  This was a more open-minded position that I am used to seeing from the Rails community.</p>
<h1 id="rack_metal_sinatra">Rack / Metal / Sinatra</h1>
<p>There was a <em>lot</em> of activity around Rack, Metal and Sinatra at the conference.  At least 3 sessions covered any 2 of the 3 topics.  For me, realizing that Metal allows any Rack compatible application to act as middleware was particularly exciting. In Rails 2.3+, you can bypass most of the Rails stack to optimize a particular resource by using Sinatra.  How cool is that?</p>
<h1 id="cucumber">Cucumber</h1>
<p>Cucumber isn&#8217;t entirely new to me. I&#8217;ve been using it on my pet projects since the <a href="http://www.pragprog.com/titles/achbd/the-rspec-book">RSpec book</a> went into beta.  What was excellent for me to see is the unanimous support it received at RailsConf.  There was an impressive attendance to Aslak Hellesoy&#8217;s cucumber talk (most of which is covered in the recent <a href="http://railscasts.com/episodes/155-beginning-with-cucumber">RailsCast on cucumber</a>).</p>
<p>Aslak asked for show of hands: &#8220;who is using cucumber for integration testing?&#8221;  Overwhelming yes.  &#8220;Keep your hands up if you have non-technical people writing specs&#8221;  At this, an underwhelming few kept their hands up.</p>
<p>But whether or not cucumber is being used for its ideal goal of having stakeholders write value-driven feature specifications&#8212; this is still a powerful technology that is not going to fade out any time soon.</p>
<h1 id="session_highlights">Session Highlights</h1>
<h2 id="git_tricks_scott_chacon">Git Tricks / Scott Chacon</h2>
<p>Man this guy loves git.  I&#8217;ve watched several of his GitCasts and this was like an octane-fueled version.  His 60-second overview of git at the beginning was hilarious.</p>
<p>The tips ranged from extraordinarily geeky to incredibly useful. Definitely check out the <a href="http://assets.en.oreilly.com/1/event/24/Smacking%20Git%20Around%20-%20Advanced%20Git%20Tricks%20Presentation.pdf">slides</a></p>
<h2 id="mocks_and_stubs_david_chelimsky">Mocks and Stubs / David Chelimsky</h2>
<p>David is an excellent speaker.  I fully appreciated his overview of mocks versus stubs&#8212; how they are often combined and confused (I couldn&#8217;t tell you the definitive difference before attending this session).</p>
<blockquote>
<p>we verify stubs by checking state after an action</p>
<p>we tell mocks to verify interactions</p>
</blockquote>
<p>In his session he brought up Pat Metheny&#8217;s response to the question, &#8220;what modes do you use&#8221; which was &#8220;that&#8217;s like asking &#8216;what verbs do you use?&#8217;&#8221;  In other words, verbs, modes, patterns, tests emerge from the context in which their necessity is born.  This resonated with me.  In this session David outlined several reasons for isolated testing using mocks.  As it turned out I had done every single one of these, despite the fact I couldn&#8217;t have named any of them before this talk.</p>
<p><a href="http://assets.en.oreilly.com/1/event/24/Don't%20Mock%20Yourself%20Out%20Presentation.pdf">Slides</a></p>
<h2 id="map_reduce_with_rabbitmq_paulo_negri">Map / Reduce with RabbitMQ / Paulo Negri</h2>
<p>This presentation really opened my eyes to the power of RabbitMQ.  I&#8217;ve been meaning to try out this AMQP-compliant message daemon for a while now. And now with the emergence of <a href="http://github.com/famoseagle/carrot/tree/master">carrot</a> it&#8217;s no longer an issue to use with synchronous Rails servers (mongrel, passenger).</p>
<p>Paulo&#8217;s talk focused on a few real-world business applications of map/reduce on top of RabbitMQ.  </p>
<h2 id="modeling_workflow_in_rails_david_bock">Modeling Workflow in Rails / David Bock</h2>
<p>David Bock gave an excellent overview of State-Based and Process-Based workflow systems, and how to implement them in Rails by combining the excellent <a href="http://github.com/rubyist/aasm/tree/master">AASM</a> gem and some vanilla Rails conventions.</p>
<h1 id="lightning_talks">Lightning Talks</h1>
<p>I caught about two thirds of the lightning talks: 5 minute presentations by anybody about anything interesting.  </p>
<p>Of note:</p>
<ul>
<li><a href="http://smartic.us">Bryan Liles</a>&#8217; TATFN-heavy proselytizing about TDD and being an active member of the community.</li>
<li>Yoshiteru Negishi&#8217;s talk on Cookpad (which serves <strong>6 million unique visitors per month</strong>)</li>
<li><a href="http://github.com/joshbuddy">Joshua Hull</a>&#8217;s <a href="http://www.slideshare.net/joshbuddy/stupid-middleware-tricks">Rack hacks</a> that he had made for each day of the conference</li>
<li><a href="http://github.com/technicalpickles">Josh Nichols</a>&#8217; Jeweler presentation (easy rubygem creation)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.martiandesigns.com/2009/05/08/railsconf-2009-recap/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Dasherizing Builder::XmlMarkup in Rails</title>
		<link>http://blog.martiandesigns.com/2008/10/29/dasherizing-builderxmlmarkup-in-rails/</link>
		<comments>http://blog.martiandesigns.com/2008/10/29/dasherizing-builderxmlmarkup-in-rails/#comments</comments>
		<pubDate>Wed, 29 Oct 2008 22:28:46 +0000</pubDate>
		<dc:creator>adam pearson</dc:creator>
		
		<category><![CDATA[rails]]></category>

		<category><![CDATA[ruby]]></category>

		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://blog.martiandesigns.com/?p=17</guid>
		<description><![CDATA[Rails 2.x automatically dasherizes ActiveRecord inheritors when to_xml is called, but if you want to deal directly with Builder::XmlMarkup you have to go through some hoops to dasherize your element names.  
I solved this problem today with a simple subclass.  Here&#8217;s the code:


# Creates a Builder::Markup implementation that dasherizes all element and attribute [...]]]></description>
			<content:encoded><![CDATA[<p>Rails 2.x automatically <em>dasherizes</em> ActiveRecord inheritors when <code>to_xml</code> is called, but if you want to deal directly with Builder::XmlMarkup you have to go through some hoops to dasherize your element names.  </p>
<p>I solved this problem today with a simple subclass.  Here&#8217;s the code:</p>
<pre name="code" class="ruby:nocontrols">

# Creates a Builder::Markup implementation that dasherizes all element and attribute names
# Use this just like you would Builder::XmlMarkup
class DasherizingBuilder &lt; Builder::XmlMarkup

  def _start_tag(sym, attrs, end_too=false)
    super(sym.to_s.dasherize, attrs, end_too)
  end

  def _end_tag(sym)
    super(sym.to_s.dasherize)
  end

  def _insert_attributes(attrs, order=[])
    return if attrs.nil?
    new_order= []
    order.each {|item| new_order &lt;&lt; item.to_s.dasherize}

    new_attrs = {}
    attrs.each do |k,v|
      new_attrs[k.to_s.dasherize] = v
    end

    super (new_attrs, new_order)
  end

end
</pre>
<p>Put it in your lib/ and just new up a new DasherizingBuilder to make &#8220;&lt;sad_clown&gt;&#8221; into &#8220;&lt;sad-clown&gt;&#8221;.</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.martiandesigns.com/2008/10/29/dasherizing-builderxmlmarkup-in-rails/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Creating a Simple Private Local Gem Repository</title>
		<link>http://blog.martiandesigns.com/2008/10/08/creating-a-simple-private-gem-repository/</link>
		<comments>http://blog.martiandesigns.com/2008/10/08/creating-a-simple-private-gem-repository/#comments</comments>
		<pubDate>Thu, 09 Oct 2008 01:40:28 +0000</pubDate>
		<dc:creator>adam pearson</dc:creator>
		
		<category><![CDATA[code]]></category>

		<category><![CDATA[ruby]]></category>

		<category><![CDATA[ruby gems]]></category>

		<guid isPermaLink="false">http://blog.martiandesigns.com/?p=16</guid>
		<description><![CDATA[I recently wanted to create a simple local gem repository.  Not all of the gems we write are relevant to the world at large, so github or rubyforge are not great solutions for hosting them.  
You can use the gem server command, but if you already have an apache HTTP server somewhere, incredibly [...]]]></description>
			<content:encoded><![CDATA[<p>I recently wanted to create a simple local gem repository.  Not all of the gems we write are relevant to the world at large, so github or rubyforge are not great solutions for hosting them.  </p>
<p>You <i>can</i> use the <code>gem server</code> command, but if you already have an apache HTTP server somewhere, <em>incredibly</em> easy to get a private gem repository going, server why not use that? </p>
<p><strong>1. Copy the .gem file to your server</strong><br />
<code><br />
scp your.gem your.server:/your/gem/path<br />
</code></p>
<p><strong>2. Create a folder for hosting your gems on the server</strong><br />
<code><br />
ssh user@your.server<br />
cd /var/www/html<br />
mkdir my_awesome_gems<br />
cd my_awesome_gems<br />
mkdir gems<br />
cp /your/gem/path/*.gem ./gems<br />
</code></p>
<p><strong>3. Generate the gem index</strong><br />
<code>gem</code> comes with a command <code>generate_index</code> which generates all of the files necessary for serving gems over HTTP.<br />
<code><br />
cd /var/www/html/my_awesome_gems<br />
gem generate_index<br />
</code></p>
<p>At this point you should be able to access <code>http://your.server/my_awesome_gems/</code> and see file listings.</p>
<p><strong>4. Add your new source and install your gem on your client</strong><br />
<code><br />
sudo gem sources -a http://your.server/my_awesome_gems/<br />
</code></p>
<p>You should be able to install your gems from this repository now!<br />
<code><br />
sudo gem install [your gem]<br />
</code></p>
<p>That&#8217;s it, you&#8217;re now stashing gems in your own repo!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.martiandesigns.com/2008/10/08/creating-a-simple-private-gem-repository/feed/</wfw:commentRss>
		</item>
		<item>
		<title>MonkeyPatching Class Methods in Ruby/Rails</title>
		<link>http://blog.martiandesigns.com/2008/04/29/monkeypatching-class-methods-in-rubyrails/</link>
		<comments>http://blog.martiandesigns.com/2008/04/29/monkeypatching-class-methods-in-rubyrails/#comments</comments>
		<pubDate>Wed, 30 Apr 2008 05:33:14 +0000</pubDate>
		<dc:creator>adam pearson</dc:creator>
		
		<category><![CDATA[code]]></category>

		<category><![CDATA[rails]]></category>

		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.martiandesigns.com/?p=15</guid>
		<description><![CDATA[I ran into this problem while trying to MonkeyPatch some class methods into existing Rails classes. 
Say you have the following Mooable module (as a rails plugin) that you want to dynamically inject into ActiveRecord::Base (or any ruby class for that matter).


# app/models/my_model.rb
class MyModel &#60; ActiveRecord::Base
 ...
end

# plugins/mooable/lib/mooable.rb
module Mooable
  def moo
    [...]]]></description>
			<content:encoded><![CDATA[<p>I ran into this problem while trying to MonkeyPatch some class methods into existing Rails classes. </p>
<p>Say you have the following <code>Mooable</code> module (as a rails plugin) that you want to dynamically inject into ActiveRecord::Base (or any ruby class for that matter).</p>
<pre name="code" class="ruby:nocontrols">

# app/models/my_model.rb
class MyModel &lt; ActiveRecord::Base
 ...
end

# plugins/mooable/lib/mooable.rb
module Mooable
  def moo
    return &quot;Moo!&quot;
  end
end

# plugins/mooable/init.irb
ActiveRecord::Base.send :include, Mooable

# test
MyModel.new.moo # =&gt; &quot;Moo!&quot;
</pre>
<p>But what if you wanted <code>#moo</code> to be a class method on ActiveRecord::Base?  I was tempted to do the following:</p>
<pre name="code" class="ruby:nocontrols">

#plugins/mooable/lib/mooable.rb
module Mooable
  def self.moo
   return &quot;Moo!&quot;
  end
end

# test
MyModel.moo # =&gt; NoMethodError: undefined method `moo' for MyModel:Class
</pre>
<p>As you can see, simply defining the module method as a class method is a no-go (I&#8217;m sure this is a major nuby mistake, but it&#8217;s always worth a try!)</p>
<p>The best way I have found so far to monkeypatch new class methods into rails classes with a plugin is to use the <code>Object#extend</code> method inside of the module&#8217;s <code>self.included</code> hook.  The new class methods are defined within a sub-module <code>Mooable::ClassMethods</code> for easy inclusion.</p>
<pre name="code" class="ruby:nocontrols">

# plugins/mooable/lib/mooable.rb
module Mooable

  def self.included(klass)
    klass.extend ClassMethods
  end

  module ClassMethods
      def moo
        return &quot;Moo Static/Class Method&quot;
      end
  end

  def moo
    return &quot;Moo Instance Method!&quot;
  end
end

# test
MyModel.moo # =&gt; &quot;Moo Static/Class Method&quot;
MyModel.new.moo # =&gt; &quot;Moo Instance Method!&quot;
</pre>
<p>This works like a charm.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.martiandesigns.com/2008/04/29/monkeypatching-class-methods-in-rubyrails/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Hemingway on Design Patterns</title>
		<link>http://blog.martiandesigns.com/2008/04/12/hemingway-on-design-patterns/</link>
		<comments>http://blog.martiandesigns.com/2008/04/12/hemingway-on-design-patterns/#comments</comments>
		<pubDate>Sat, 12 Apr 2008 18:25:17 +0000</pubDate>
		<dc:creator>adam pearson</dc:creator>
		
		<category><![CDATA[opinion]]></category>

		<guid isPermaLink="false">http://blog.martiandesigns.com/?p=13</guid>
		<description><![CDATA[I had a shared blog post from kottke.org in my google reader today.  It&#8217;s an Ernest Hemingway quote on the author&#8217;s use of symbolism:
&#8220;No good book has ever been written that has in it symbols arrived at beforehand and stuck in,&#8221; says Hemingway. &#8220;That kind of symbol sticks out like raisins in raisin bread. [...]]]></description>
			<content:encoded><![CDATA[<p>I had a <a href="http://www.kottke.org/remainder/08/04/15427.html">shared blog post from kottke.org</a> in my google reader today.  It&#8217;s an Ernest Hemingway quote on the author&#8217;s use of symbolism:</p>
<blockquote><p>&#8220;No good book has ever been written that has in it symbols arrived at beforehand and stuck in,&#8221; says Hemingway. &#8220;That kind of symbol sticks out like raisins in raisin bread. Raisin bread is all right, but plain bread is better.&#8221; He opens two bottles of beer and continues: &#8220;I tried to make a real old man, a real boy, a real sea and a real fish and real sharks. But if I made them good and true enough they would mean many things. The hardest thing is to make something really true and sometimes truer than true.&#8221;</p></blockquote>
<p>I often get a lot of flack for thinking and talking about design patterns.  I think the main reason is because most people who learn about them, get excited and start wildly trying to apply them everywhere possible&#8211; which subverts the underlying principle of design patterns.</p>
<p>One of the most valuable lessons I&#8217;ve learned about design patterns is to <strong>find them within the context of the problem</strong> and not to let the problem be defined by the pattern.  Don&#8217;t apply your favorite pattern to a problem just because you know or like it. This is what Hemingway is saying; applying a design pattern for design pattern&#8217;s sake &#8220;sticks out like raisins in raisin bread.&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.martiandesigns.com/2008/04/12/hemingway-on-design-patterns/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Gotcha: HABTM Relationships Use Join Table Id As Model Id</title>
		<link>http://blog.martiandesigns.com/2008/04/10/gotcha-habtm-relationships-use-join-table-id-as-model-id/</link>
		<comments>http://blog.martiandesigns.com/2008/04/10/gotcha-habtm-relationships-use-join-table-id-as-model-id/#comments</comments>
		<pubDate>Thu, 10 Apr 2008 17:33:21 +0000</pubDate>
		<dc:creator>adam pearson</dc:creator>
		
		<category><![CDATA[code]]></category>

		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://blog.martiandesigns.com/?p=11</guid>
		<description><![CDATA[Having problems with Has and Belongs To Many(habtm) relationships loading your models with the wrong Ids?  I was, the story follows.
Admittedly, HABTM is a relationship in Rails that I use rarely.  This little snag caught me off-guard last week, and the usual internet searches didn&#8217;t yield particularly fruitful results. 
Say you have a [...]]]></description>
			<content:encoded><![CDATA[<p>Having problems with Has and Belongs To Many(habtm) relationships loading your models with the wrong Ids?  I was, the story follows.</p>
<p>Admittedly, HABTM is a relationship in Rails that I use rarely.  This little snag caught me off-guard last week, and the usual internet searches didn&#8217;t yield particularly fruitful results. </p>
<p>Say you have a simple HABTM relationship:</p>
<pre name="code" class="ruby:nocontrols">

#Predator.rb
class Predator &lt; ActiveRecord::Base
  has_and_belongs_to_many :prey
end

#Prey.rb
class Predator &lt; ActiveRecord::Base
  has_and_belongs_to_many :predators
end
</pre>
<p>So you&#8217;ve added the relationship, now you go to add your join table as a new migration:</p>
<pre name="code" class="ruby:nocontrols">

class CreatePreyPredators &lt; ActiveRecord::Migration
  def self.up
    create_table :prey_predators do |t|
      t.integer :prey_id
      t.integer :predator_id
    end
  end

  def self.down
    drop_table :prey_predators
  end
end
</pre>
<p>Now, say you&#8217;ve added a few relationships in your database: </p>
<pre name="code" class="sql:nocontrols">

select * from prey_predators;
+---+--------------+--------------+
| id |   prey_id   | predator_id  |
+------------------+--------------+
|  1 |   218872420 | 368007386    |
+------------------+--------------+
1 row in set (0.00 sec)
</pre>
<p>BUT, when you look at your shiny new relationship in the console, you see this:</p>
<pre name="code" class="html:nocontrols">

&gt;&gt; Prey.find(:first).predators
#&lt;Predator id: 1, name: &quot;test_predator&quot; &gt;
</pre>
<p>You can see that IRB is reporting the predator&#8217;s id as <strong>1</strong> and not <strong>368007386</strong>.  What you&#8217;re seeing isn&#8217;t the primary key of the predator record, but the primary key of the relationship record in the join table where predator was found.</p>
<p>It would appear that Rails gives any column named &#8216;id&#8217; precedence when determining the id of the record&#8211; ignoring the foreign kesy in the join table.  I tried specifying the <code>:foreign_key</code> and :<code>associated_foreign_key</code> on the has_and_belongs_to_many relationship, but that only appears to affect the query that selects the records, not the model&#8217;s &#8220;reconstitution&#8221; from the database.</p>
<p>Unless you want this behavior, just add <code>:id => false</code> to your migration and you&#8217;re woes will be gone:</p>
<pre name="code" class="ruby:nocontrols">

class CreatePreyPredators &lt; ActiveRecord::Migration
  def self.up
    create_table :prey_predators, :id =&gt; false do |t|
      t.integer :prey_id
      t.integer :predator_id
    end
  end

  def self.down
    drop_table :prey_predators
  end
end
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.martiandesigns.com/2008/04/10/gotcha-habtm-relationships-use-join-table-id-as-model-id/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Feed Url Changing</title>
		<link>http://blog.martiandesigns.com/2008/04/05/feed-url-changing/</link>
		<comments>http://blog.martiandesigns.com/2008/04/05/feed-url-changing/#comments</comments>
		<pubDate>Sat, 05 Apr 2008 21:09:02 +0000</pubDate>
		<dc:creator>adam pearson</dc:creator>
		
		<category><![CDATA[site news]]></category>

		<guid isPermaLink="false">http://blog.martiandesigns.com/?p=12</guid>
		<description><![CDATA[I&#8217;m going to start hosting my feed through feedburner.  Please update your feed urls to: http://feeds.feedburner.com/Acts_as_martian
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m going to start hosting my feed through feedburner.  Please update your feed urls to: <a href="http://feeds.feedburner.com/Acts_as_martian">http://feeds.feedburner.com/Acts_as_martian</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.martiandesigns.com/2008/04/05/feed-url-changing/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Arriving at a DSL for XPath Testing in Rails</title>
		<link>http://blog.martiandesigns.com/2008/02/17/arriving-at-a-dsl-for-xpath-testing-in-rails/</link>
		<comments>http://blog.martiandesigns.com/2008/02/17/arriving-at-a-dsl-for-xpath-testing-in-rails/#comments</comments>
		<pubDate>Sun, 17 Feb 2008 22:05:09 +0000</pubDate>
		<dc:creator>adam pearson</dc:creator>
		
		<category><![CDATA[code]]></category>

		<category><![CDATA[rails]]></category>

		<category><![CDATA[ruby]]></category>

		<category><![CDATA[testing]]></category>

		<category><![CDATA[xml]]></category>

		<category><![CDATA[dsl]]></category>

		<category><![CDATA[ruby testing]]></category>

		<category><![CDATA[tdd]]></category>

		<category><![CDATA[xpath]]></category>

		<guid isPermaLink="false">http://blog.martiandesigns.com/2008/02/17/arriving-at-a-dsl-for-xpath-testing-in-rails/</guid>
		<description><![CDATA[Recently I was writing custom Xml exporting for some of our Rails models.  I favor TDD over just shoot-from-the-hip development, so I had to write some tests.  For testing the validity of the XML, I chose XPath for its simplicity.
As I added functionality (and thereby added tests) I noticed that my tests were [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I was writing custom Xml exporting for some of our Rails models.  I favor <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a> over just shoot-from-the-hip development, so I had to write some tests.  For testing the validity of the XML, I <a href="/2008/02/12/xpath-matching-in-testunit/">chose XPath</a> for its simplicity.</p>
<p>As I added functionality (and thereby added tests) I noticed that my tests were becoming increasingly redundant, and that <code>Test::Unit</code>&#8217;s syntax was making my test files ugly and more importantly hard to read.  As I started <a href="http://en.wikipedia.org/wiki/DRY">DRY</a>-ing up the individual tests and trying to find better ways to share code and make the tests more succinct, I noticed that I was driving very close to creating my own <strong>mini-DSL for testing Xml with Xpath</strong>.</p>
<h4>My Requirements for Xml Exporting</h4>
<ol>
<li>A <strong>required</strong> element <em>must always</em> exist in the resulting Xml regardless of the model&#8217;s state</li>
<li>An <strong>optional</strong> element:
<ul>
<li>Must exist when the model meets a certain state condition (i.e. the member is not null)</li>
<li>Must <em>not</em> exist when that condition is not met</li>
</ul>
</li>
</ol>
<h4>A DSL That Meets My Testing Needs</h4>
<p>As mentioned earlier, this DSL evolved from repeated refactoring my tests in order to make them more clear.  Here is an example of an XPath-based Xml test:</p>
<pre name="code" class="ruby:nocontrols">

xpath_tests_for @video_library do
  # ensure that the Xml always contains:
  #   &lt;library&gt;&lt;videos&gt;&lt;/videos&lt;/library&gt;
  require '/library/videos'

  # ensure that when certain conditions are met, the Xml contains:
  #   &lt;library&gt;&lt;genres&gt;&lt;/genres&gt;&lt;/library&gt;
  optional '/library/genres' do
    before :test_missing do |library|
      library.genres.clear
    end

    before :test_existing do |library|
      library.genres &lt;&lt; Genre.new :name =&gt; &quot;Comedy&quot;
    end
  end
end
</pre>
<p>Here&#8217;s a run-down of the language elements in this mini-DSL:</p>
<dl>
<dt><code>xpath_tests_for @model</code></dt>
<dd>Describe tests for a given instance of a model</p>
</dd>
<dt><code>require &lt;xpath&gt;</code></dt>
<dd>Add a test requiring the xpath in the test-suite&#8217;s Xml blob</p>
</dd>
<dt><code>optional &lt;xpath&gt;</code></dt>
<dd>Add a test requiring the xpath in the Xml under certain conditions</p>
</dd>
<dt><code>before :test_missing</code></dt>
<dd>A block defining the conditions whereby the element must be missing in an optional test</p>
</dd>
<dt><code>before :test_existing</code></dt>
<dd>A block defining the conditions whereby the element must be existing in an optional test</p>
</dd>
</dl>
<h4>How This DSL Emerged</h4>
<p>As I mentioned at the start of this article, I didn&#8217;t approach this testing with a DSL in mind, the entire concept emerged from my testing. Here is an example of the emergent nature of this DSL.  As seen in the earlier example, I can test all of my requirements, but here is a new requirement:</p>
<blockquote><p>
  <em>Since this is custom Xml generation for a specific target application, <em>do not</em> change the default behavior of <code>ActiveRecord#to_xml</em></code>
</p></blockquote>
<p>As you might have imagined the testing currently functions with the test runner calling ActiveRecord&#8217;s built-in to_xml method, and my Library model had code in it to generate the custom xml format.</p>
<pre name="code" class="ruby:nocontrols">

# somewhere in the xpath test runner
xml_for_testing = @video_library.to_xml

# models/library.rb
def to_xml
  # code to render custom xml format
end
</pre>
<p>However, in order to meet the requirement, I had to change my model, moving my custom Xml generation from <code>to_xml</code> to some new method:
<pre name="code" class="ruby:nocontrols">

# models/library.rb
def generate_custom_xml
  # code to render custom xml format
end
</pre>
<p>Now I&#8217;m meeting the requirement, but the tests are broken because the test runner is now calling the wrong method for my tests</p>
<p>In order to accomodate this change, I updated my DSL to include a block for specifying how xml should be generated:</p>
<pre name="code" class="ruby:nocontrols">

xpath_tests_for @video_library do
  generate_xml_as do |library|
    library.generate_custom_xml
  end

  require '/library/videos'
  ...
end
</pre>
<p>This way I my test runner can <code>yield</code> the data model to the generation block and the block can handle the specifics of using the model to generate xml.</p>
<p><em>Note: Because i&#8217;m doing &#8220;red/green&#8221; test-driven-development, I actually wrote the new test syntax first and the code later, but for clarity, wrote the article in the opposite order.</em></p>
<h4>Final Notes</h4>
<p>If I wasn&#8217;t practicing TDD, I probably would have never come up with a succinct mini-language for XPath-based testing.  During the initial design of this feature, it would have seemed like an over-engineering.  Who wants to put that much effort in testing anyway?  However, since the code emerged as necessary from my test-driven-development, I was not only able to write some interesting testing code, but I also now have new plugin for performing XPath testing in other apps.</p>
<p>Not only is this a personal win for TDD in my book, but since this is my first DSL (thanks Ruby!) I learned a few things about development with a DSL.  Most notably, <strong>since the DSL defines an <em>ideal</em> API, I rarely if ever changed the code in my tests</strong>.  Most of the work I did to get this functional and optimized was in the test-runner and supporting classes.  And all of that code was able to be written without changing my tests</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.martiandesigns.com/2008/02/17/arriving-at-a-dsl-for-xpath-testing-in-rails/feed/</wfw:commentRss>
		</item>
		<item>
		<title>XPath matching in Test::Unit</title>
		<link>http://blog.martiandesigns.com/2008/02/12/xpath-matching-in-testunit/</link>
		<comments>http://blog.martiandesigns.com/2008/02/12/xpath-matching-in-testunit/#comments</comments>
		<pubDate>Tue, 12 Feb 2008 23:28:09 +0000</pubDate>
		<dc:creator>adam pearson</dc:creator>
		
		<category><![CDATA[code]]></category>

		<category><![CDATA[rails]]></category>

		<category><![CDATA[ruby]]></category>

		<category><![CDATA[testing]]></category>

		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://blog.martiandesigns.com/2008/02/12/xpath-matching-in-testunit/</guid>
		<description><![CDATA[Inspired by an article on adding XPath matching to RSpec.  I&#8217;m not using RSpec currently, and I also have a need for this functionality in my tests, so I decided to a helper for use in  Test::Unit to achieve XPath matching in my tests.
Add a new helper method:
Add the following code to your [...]]]></description>
			<content:encoded><![CDATA[<p>Inspired by an article on <a href="http://blog.wolfman.com/articles/2008/01/02/xpath-matchers-for-rspec">adding XPath matching to RSpec</a>.  I&#8217;m not using RSpec currently, and I also have a need for this functionality in my tests, so I decided to a helper for use in  Test::Unit to achieve XPath matching in my tests.</p>
<p><strong>Add a new helper method:</strong><br />
Add the following code to your test/test_helper.rb in order to create the <code>assert_has_xpath</code> method.</p>
<pre name="code" class="ruby:nocontrols">

#test/test_helper.rb
require 'rexml/document'

# Asserts that the specified xpath matches
# at least once in the given document
def assert_has_xpath (xpath, doc)
  doc = doc.is_a?(REXML::Document) ? doc : REXML::Document.new(doc)
  match = REXML::XPath.match doc, xpath
  assert !match.empty?, &quot;Missing xpath '#{xpath}' in document: #{doc}&quot;
end
</pre>
<p>Optionally, you can add the above to a module and include it in your test_helper, or in your individual tests.</p>
<p><strong>Use the helper in your tests:</strong><br />
Now, in your tests, you can do something like the following</p>
<pre name="code" class="ruby:nocontrols">

#model.rb
def to_xml options = {}
  xml = options[:builder] ||= Builder::XmlMarkup.new(options)

  xml.toys{
    xml.toy &quot;ball&quot;
    xml.toy &quot;iPhone&quot;
  }
end

#model_test.rb
def test_create_xml_creates_toys
  model = Model.new
  xml = model.to_xml
  assert_has_xpath &quot;/toys[toy='iPhone']&quot;, xml
end
</pre>
<p>And voila!   You now have XPath testing in your Test::Unit tests.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.martiandesigns.com/2008/02/12/xpath-matching-in-testunit/feed/</wfw:commentRss>
		</item>
		<item>
		<title>How To Create A Mixin To Extend Core Types in Rails 2.x</title>
		<link>http://blog.martiandesigns.com/2008/01/21/how-to-create-a-mixin-to-extend-core-types-in-rails-2x/</link>
		<comments>http://blog.martiandesigns.com/2008/01/21/how-to-create-a-mixin-to-extend-core-types-in-rails-2x/#comments</comments>
		<pubDate>Mon, 21 Jan 2008 19:26:00 +0000</pubDate>
		<dc:creator>adam pearson</dc:creator>
		
		<category><![CDATA[rails]]></category>

		<category><![CDATA[howto]]></category>

		<category><![CDATA[mixin]]></category>

		<guid isPermaLink="false">http://blog.martiandesigns.com/2008/01/21/how-to-create-a-mixin-to-extend-core-types-in-rails-2x/</guid>
		<description><![CDATA[Recently I wanted to create a mixin for String in my Rails 2.0 project that allowed me to DRY up pluralization given an arbitrary number.  Here&#8217;s an example usage:


&#34;mile&#34;.pluralize_for(trip.miles) #returns &#34;mile&#34; when trip.miles is one and &#34;miles&#34; otherwise.

The mixin code is simple:


# martian_extensions.rb
module MartianExtensions
  def pluralize_for(number)
    unless number == 1
 [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I wanted to create a mixin for <code>String</code> in my Rails 2.0 project that allowed me to DRY up pluralization given an arbitrary number.  Here&#8217;s an example usage:</p>
<pre name="code" class="ruby:nocontrols">

&quot;mile&quot;.pluralize_for(trip.miles) #returns &quot;mile&quot; when trip.miles is one and &quot;miles&quot; otherwise.
</pre>
<p>The mixin code is simple:</p>
<pre name="code" class="ruby:nocontrols">

# martian_extensions.rb
module MartianExtensions
  def pluralize_for(number)
    unless number == 1
      self.to_s.pluralize
    else
      self.to_s
    end
  end
end
</pre>
<p>The challenge came with finding a simple, configuration-free way to ensure that this mixin is loaded.   Following the guidance of Jamis Buck in this (by now <em>ancient</em>) <a href="http://weblog.jamisbuck.org/2005/10/11/plugging-into-rails">blog article</a>, i eventually settled on his solution of <strong>creating my simple mixin as a full-fledged plugin</strong>.</p>
<p>In order to do this without adding any configuration, you can follow Rails&#8217; automagic loading rules, namely, create an apt folder structure under your <code>vendor/plugins</code> directory:</p>
<pre>
    /vendor/plugins/martian_extensions/
    /vendor/plugins/martian_extensions/init.rb
    /vendor/plugins/martian_extensions/lib
    /vendor/plugins/martian_extensions/lib/martian_extensions.rb
</pre>
<p>You&#8217;ve already seen <code>martian_extensions.rb</code>, as for init.rb, that&#8217;s what does the work of ensuring String loads my module and includes <code>pluralize_for</code>:</p>
<pre name="code" class="ruby:nocontrols">

#init.rb
String.send :include, MartianExtensions
</pre>
<p>Personally, I&#8217;ll keep my core extensions in this single plugin so that I can keep it portable between my applications.  It seems pretty clean to me, but if there&#8217;s a better solution that you have found, please comment!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.martiandesigns.com/2008/01/21/how-to-create-a-mixin-to-extend-core-types-in-rails-2x/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
