<?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"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>All Things (v8) &#187; Ruby</title>
	<atom:link href="http://www.anthonyeden.com/category/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.anthonyeden.com</link>
	<description>Technology Blog</description>
	<lastBuildDate>Sat, 19 Nov 2011 18:06:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Temporarily Redefine (not stub) Methods for Testing</title>
		<link>http://www.anthonyeden.com/2011/07/temporarily-redefine-not-stub-methods-for-testing/</link>
		<comments>http://www.anthonyeden.com/2011/07/temporarily-redefine-not-stub-methods-for-testing/#comments</comments>
		<pubDate>Thu, 07 Jul 2011 09:03:48 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.anthonyeden.com/?p=234</guid>
		<description><![CDATA[Today I came across a case where I wanted to temporarily redefine a method&#8217;s implementation for purposes of testing. Specifically I want to test with a condition of a large number of records in a database. Since I don&#8217;t actually want to load a large number of records into the database I just want to [...]]]></description>
			<content:encoded><![CDATA[<p>Today I came across a case where I wanted to temporarily redefine a method&#8217;s implementation for purposes of testing. Specifically I want to test with a condition of a large number of records in a database. Since I don&#8217;t actually want to load a large number of records into the database I just want to make the system think there is a large number of records for the purposes of the test.</p>
<p>Here&#8217;s a gist showing what I ended up doing:</p>
<div id="gist-1069124" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">module</span> <span class="nn">Count</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="k">def</span> <span class="nf">fake_count</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">words</span><span class="o">.</span><span class="n">count</span> <span class="o">+</span> <span class="mi">500</span></div><div class='line' id='LC4'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC5'><span class="k">end</span></div><div class='line' id='LC6'><br/></div><div class='line' id='LC7'><span class="k">class</span> <span class="nc">Thing</span></div><div class='line' id='LC8'>&nbsp;&nbsp;<span class="k">def</span> <span class="nf">words</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="sx">%w(one two three)</span></div><div class='line' id='LC10'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC11'>&nbsp;&nbsp;<span class="k">def</span> <span class="nf">count</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">words</span><span class="o">.</span><span class="n">count</span></div><div class='line' id='LC13'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC14'><span class="k">end</span></div><div class='line' id='LC15'><br/></div><div class='line' id='LC16'><span class="k">def</span> <span class="nf">assert</span><span class="p">(</span><span class="n">value</span><span class="p">)</span></div><div class='line' id='LC17'>&nbsp;&nbsp;<span class="k">raise</span> <span class="s2">&quot;Assertion failed&quot;</span> <span class="k">unless</span> <span class="n">value</span> <span class="o">==</span> <span class="kp">true</span></div><div class='line' id='LC18'><span class="k">end</span></div><div class='line' id='LC19'><br/></div><div class='line' id='LC20'><span class="n">thing</span> <span class="o">=</span> <span class="no">Thing</span><span class="o">.</span><span class="n">new</span></div><div class='line' id='LC21'><span class="n">assert</span> <span class="n">thing</span><span class="o">.</span><span class="n">count</span> <span class="o">==</span> <span class="mi">3</span></div><div class='line' id='LC22'><span class="nb">puts</span> <span class="n">thing</span><span class="o">.</span><span class="n">count</span></div><div class='line' id='LC23'><br/></div><div class='line' id='LC24'><span class="k">class</span> <span class="nc">Thing</span></div><div class='line' id='LC25'>&nbsp;&nbsp;<span class="kp">include</span> <span class="no">Count</span></div><div class='line' id='LC26'>&nbsp;&nbsp;<span class="n">alias_method</span> <span class="ss">:real_count</span><span class="p">,</span> <span class="ss">:count</span></div><div class='line' id='LC27'>&nbsp;&nbsp;<span class="n">alias_method</span> <span class="ss">:count</span><span class="p">,</span> <span class="ss">:fake_count</span></div><div class='line' id='LC28'><span class="k">end</span></div><div class='line' id='LC29'><br/></div><div class='line' id='LC30'><span class="n">thing</span> <span class="o">=</span> <span class="no">Thing</span><span class="o">.</span><span class="n">new</span></div><div class='line' id='LC31'><span class="n">assert</span> <span class="n">thing</span><span class="o">.</span><span class="n">count</span> <span class="o">==</span> <span class="mi">503</span></div><div class='line' id='LC32'><span class="nb">puts</span> <span class="n">thing</span><span class="o">.</span><span class="n">count</span></div><div class='line' id='LC33'><br/></div><div class='line' id='LC34'><span class="k">class</span> <span class="nc">Thing</span></div><div class='line' id='LC35'>&nbsp;&nbsp;<span class="n">alias_method</span> <span class="ss">:count</span><span class="p">,</span> <span class="ss">:real_count</span></div><div class='line' id='LC36'><span class="k">end</span></div><div class='line' id='LC37'><br/></div><div class='line' id='LC38'><span class="n">thing</span> <span class="o">=</span> <span class="no">Thing</span><span class="o">.</span><span class="n">new</span></div><div class='line' id='LC39'><span class="n">assert</span> <span class="n">thing</span><span class="o">.</span><span class="n">count</span> <span class="o">==</span> <span class="mi">3</span></div><div class='line' id='LC40'><span class="nb">puts</span> <span class="n">thing</span><span class="o">.</span><span class="n">count</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1069124/6bc6f4a4ee8d21112cf2a28b8691aa2dc17328a7/test.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1069124#file_test.rb" style="float:right;margin-right:10px;color:#666">test.rb</a>
            <a href="https://gist.github.com/1069124">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<ol>
<li>Create a module that has the faked version of the method</li>
<li>Open up the original class and include the module (I want it on all instances &#8211; if it were just one I&#8217;d use extend)</li>
<li>While the class is open call alias_method :real_count, :count which creates an alias of real_count that points to the count method</li>
<li>While still in the open class, call alias_method :count, :fake_count which creates an alias of count to the fake_count method. Note that real_count still points to the original implementation</li>
</ol>
<p>Once the class has been opened and modified it will return the new value. To undo the change I can just open up the class again and call alias_method :count, :real_count which makes count behave as it did originally.</p>
<p>Why not stub? In this case I wanted to use a method in Thing and just add 500 to it. I probably could have also called real_count + 500 which would have effectively decorated the original count method.</p>
<p>Can you think of alternative approaches? Let me know in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2011/07/temporarily-redefine-not-stub-methods-for-testing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Experimental Resolution of Gem Dependencies with DNS</title>
		<link>http://www.anthonyeden.com/2011/07/experimental-resolution-of-gem-dependencies-with-dns/</link>
		<comments>http://www.anthonyeden.com/2011/07/experimental-resolution-of-gem-dependencies-with-dns/#comments</comments>
		<pubDate>Sat, 02 Jul 2011 18:37:54 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[dns]]></category>
		<category><![CDATA[rubygems]]></category>

		<guid isPermaLink="false">http://www.anthonyeden.com/?p=228</guid>
		<description><![CDATA[This week Jeremy Hinegardner (aka @copiousfreetime) was in Montpellier to visit. In addition to enjoying some good meals, good wine and time in the pool we also took this opportunity to work on an experimental gem dependency resolution system using DNS. I&#8217;ve written about this before and the latest gist has some new details in [...]]]></description>
			<content:encoded><![CDATA[<p>This week Jeremy Hinegardner (aka <a href="http://twitter.com/copiousfreetime">@copiousfreetime</a>) was in Montpellier to visit. In addition to enjoying some good meals, good wine and time in the pool we also took this opportunity to work on an experimental gem dependency resolution system using DNS. I&#8217;ve written about this before and the <a href="https://gist.github.com/1057357">latest gist</a> has some new details in it as the result of our work this week.</p>
<p>First of all we&#8217;ve outlined how to deal with some of the dependency issues we had not yet dealt with, such as less-than, less-than-or-equals-to and not-equals. Additionally we outlined how to deal with situations where a dependency defines 2 or more requirements (such as ["> 1.0.0", "<= 2.0.0"]). We&#8217;ve also added in support for listing all known versions of a specific gem by moving the notion of the latest gem version so it uses a prefix of latest and then putting one PTR for each version of the gem on the gem domain name.</p>
<p>In addition to working on the details of the spec we also got some data loaded! Thanks to the work Jeremy did previously on his <a href="https://github.com/copiousfreetime/gemology">Gemology project</a> a lot of the code had already been written. I spent some time working on moving the code we needed into the <a href="https://github.com/aeden/rubygems-dns">rubygems-dns</a> project while Jeremy worked on exporting the existing specs we needed from his database and writing an import script. While the implementation is far from complete I&#8217;m happy to say that you can actually query the DNS server now and answer questions with it.</p>
<p>First a query to list all of the versions of a gem. We&#8217;ll use the Sinatra gem as an example:</p>
<p><code><br />
dig @ns8.dnsimple.com sinatra.index.rubygems.org PTR<br />
</code></p>
<p>The result will be an unordered list of PTR records, with each record representing a version with the version number in reverse order:</p>
<p><code><br />
sinatra.index.rubygems.org. 86400 IN	PTR	1.3.0.sinatra.index.rubygems.org.<br />
sinatra.index.rubygems.org. 86400 IN	PTR	0.1.0.sinatra.index.rubygems.org.<br />
sinatra.index.rubygems.org. 86400 IN	PTR	5.1.0.sinatra.index.rubygems.org.<br />
sinatra.index.rubygems.org. 86400 IN	PTR	6.1.0.sinatra.index.rubygems.org.<br />
sinatra.index.rubygems.org. 86400 IN	PTR	7.1.0.sinatra.index.rubygems.org.<br />
sinatra.index.rubygems.org. 86400 IN	PTR	0.2.0.sinatra.index.rubygems.org.<br />
...snip...<br />
</code></p>
<p>So the first line indicates that there was a 0.3.1 version of Sinatra and line 2 indicates there was a 0.1.0 version of Sinatra.</p>
<p>Next, let&#8217;s get the latest version:</p>
<p><code><br />
dig @ns8.dnsimple.com latest.sinatra.index.rubygems.org CNAME<br />
</code></p>
<p><code><br />
latest.sinatra.index.rubygems.org. 600 IN CNAME	e.0.3.1.sinatra.index.rubygems.org.<br />
</code></p>
<p>This shows us that 1.3.0.e is the latest sinatra version published (as of the snapshot).</p>
<p>Next, we can query for PTR records for that same name:</p>
<p><code><br />
dig @ns8.dnsimple.com latest.sinatra.index.rubygems.org PTR<br />
</code></p>
<p><code><br />
latest.sinatra.index.rubygems.org. 600 IN CNAME	e.0.3.1.sinatra.index.rubygems.org.<br />
e.0.3.1.sinatra.index.rubygems.org. 86400 IN PTR 1.tilt.index.rubygems.org.<br />
e.0.3.1.sinatra.index.rubygems.org. 86400 IN PTR 1.rack.index.rubygems.org.<br />
</code></p>
<p>This shows us that the version 1.3.0.e has two runtime dependencies, tilt and rack, and that they require the latest version of the 1.x releases for each of those. We can then use:</p>
<p><code><br />
dig @ns8.dnsimple.com 1.tilt.index.rubygems.org PTR<br />
</code></p>
<p>To show us that the latest version:</p>
<p><code><br />
1.tilt.index.rubygems.org. 600	IN	CNAME	2.3.1.tilt.index.rubygems.org<br />
</code></p>
<p>That&#8217;s it for now. There is more work to do, like encoding the <, <=, != and dependencies with 2 or more requirements, but this will at least give an example how this all might actually work.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2011/07/experimental-resolution-of-gem-dependencies-with-dns/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Refactoring to Modules</title>
		<link>http://www.anthonyeden.com/2011/05/refactoring-to-modules/</link>
		<comments>http://www.anthonyeden.com/2011/05/refactoring-to-modules/#comments</comments>
		<pubDate>Sat, 07 May 2011 17:01:58 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[RSpec]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.anthonyeden.com/?p=217</guid>
		<description><![CDATA[Keeping any application healthy and under control as it grows requires attention to the application&#8217;s organization and structure among other things. With DNSimple I&#8217;ve been spending some time thinking about how to reduce the size and complexity of some of the larger classes. The impetuous for this refactoring is to make the code easier to [...]]]></description>
			<content:encoded><![CDATA[<p>Keeping any application healthy and under control as it grows requires attention to the application&#8217;s organization and structure among other things. With DNSimple I&#8217;ve been spending some time thinking about how to reduce the size and complexity of some of the larger classes. The impetuous for this refactoring is to make the code easier to understand and easier to test. For the later the goal is to eventually be able to test business logic without needing to load the entire Rails environment.</p>
<p>I currently am trying two approaches to extracting logic into modules. First, I have created a directory in lib where extracted modules will live. I choose to call this directory <code>logic</code> since essentially I&#8217;m trying to use it as a place to store logic (as opposed to storing code that describes data models, which will remain in the app/models directory. For simpler classes that only have a small amount of logic I am extracting all of the logic into a single file with the same name as the existing model. For example, for a Contact model the logic would go into a Logic::Contact module. This module is then mixed back into the module. Here is a (somewhat contrived) example:</p>
<p>Before the extraction:</p>
<div id="gist-960637" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">class</span> <span class="nc">Contact</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="n">belongs_to</span> <span class="ss">:user</span></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'>&nbsp;&nbsp;<span class="k">def</span> <span class="nf">name</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;</span><span class="si">#{</span><span class="n">first_name</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">last_name</span><span class="si">}</span><span class="s2">&quot;</span></div><div class='line' id='LC6'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC7'><span class="k">end</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/960637/213796db220e416b53a6e103250e0da8d82f9439/contact.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/960637#file_contact.rb" style="float:right;margin-right:10px;color:#666">contact.rb</a>
            <a href="https://gist.github.com/960637">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>After the extraction:  </p>
<div id="gist-960637" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">class</span> <span class="nc">Contact</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="kp">include</span> <span class="no">Logic</span><span class="o">::</span><span class="no">Contact</span></div><div class='line' id='LC3'>&nbsp;&nbsp;<span class="n">belongs_to</span> <span class="ss">:user</span></div><div class='line' id='LC4'><span class="k">end</span></div><div class='line' id='LC5'><br/></div><div class='line' id='LC6'><span class="k">module</span> <span class="nn">Logic</span></div><div class='line' id='LC7'>&nbsp;&nbsp;<span class="k">module</span> <span class="nn">Contact</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">name</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;</span><span class="si">#{</span><span class="n">first_name</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">last_name</span><span class="si">}</span><span class="s2">&quot;</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC11'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC12'><span class="k">end</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/960637/f020763008918ed2f501646c59c0dbdd6299eafa/logic_contact.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/960637#file_logic_contact.rb" style="float:right;margin-right:10px;color:#666">logic_contact.rb</a>
            <a href="https://gist.github.com/960637">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>This is the simplest form of extraction. Beyond this however is another form of extraction that I am using in cases of larger, more complex classes. In this case I group together some of the logic into a module, usually naming it so it describes the behavior. For example, I have a module in DNSimple called Logic::Domain::Renewable which contains logic for domain renewal.</p>
<div id="gist-960637" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">class</span> <span class="nc">Domain</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="c1"># ...lots of code...</span></div><div class='line' id='LC3'>&nbsp;&nbsp;<span class="k">def</span> <span class="nf">auto_renew?</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;<span class="n">registry_domain</span><span class="o">.</span><span class="n">auto_renew?</span></div><div class='line' id='LC5'>&nbsp;&nbsp;<span class="k">rescue</span> <span class="o">=&gt;</span> <span class="n">e</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">logger</span><span class="o">.</span><span class="n">error</span> <span class="n">e</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kp">false</span></div><div class='line' id='LC8'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC9'>&nbsp;&nbsp;<span class="c1"># ... more code ...</span></div><div class='line' id='LC10'><span class="k">end</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/960637/7fff6d9f04ae0bba0f820d57039a57d178f07a17/domain.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/960637#file_domain.rb" style="float:right;margin-right:10px;color:#666">domain.rb</a>
            <a href="https://gist.github.com/960637">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>Becomes </p>
<div id="gist-960637" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">class</span> <span class="nc">Domain</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="kp">include</span> <span class="no">Logic</span><span class="o">::</span><span class="no">Domain</span><span class="o">::</span><span class="no">Renewable</span></div><div class='line' id='LC3'><span class="k">end</span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'><span class="k">module</span> <span class="nn">Logic</span></div><div class='line' id='LC6'>&nbsp;&nbsp;<span class="k">module</span> <span class="nn">Domain</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">module</span> <span class="nn">Renewable</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">auto_renew?</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">registry_domain</span><span class="o">.</span><span class="n">auto_renew?</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">rescue</span> <span class="o">=&gt;</span> <span class="n">e</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">logger</span><span class="o">.</span><span class="n">error</span> <span class="n">e</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kp">false</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC15'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC16'><span class="k">end</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/960637/99018a91946f3b769f22a10459e54870d5395295/logic_domain_renewable.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/960637#file_logic_domain_renewable.rb" style="float:right;margin-right:10px;color:#666">logic_domain_renewable.rb</a>
            <a href="https://gist.github.com/960637">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>The beauty of extracting in this way is that the different behaviors required by the system seem to align nicely into modules which make it much easier to locate code as I continue to develop the system.</p>
<p>So what might the tests look like after these extractions? I already have a fairly comprehensive test suite for DNSimple (yes, there are gaps) so it already is a little bit slow (although not as slow as it would eventually become). With the extractions I can began to test the logic in isolation. For example:</p>
<div id="gist-960637" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="nb">require</span> <span class="s1">&#39;lib/logic/contact&#39;</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'><span class="k">class</span> <span class="nc">FakeContact</span></div><div class='line' id='LC4'>&nbsp;&nbsp;<span class="kp">include</span> <span class="no">Logic</span><span class="o">::</span><span class="no">Contact</span></div><div class='line' id='LC5'>&nbsp;&nbsp;<span class="kp">attr_accessor</span> <span class="ss">:first_name</span><span class="p">,</span> <span class="ss">:last_name</span></div><div class='line' id='LC6'><span class="k">end</span></div><div class='line' id='LC7'><br/></div><div class='line' id='LC8'><span class="n">describe</span> <span class="no">Logic</span><span class="o">::</span><span class="no">Contact</span> <span class="k">do</span></div><div class='line' id='LC9'>&nbsp;&nbsp;<span class="n">subject</span> <span class="k">do</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">contact</span> <span class="o">=</span> <span class="no">FakeContact</span><span class="o">.</span><span class="n">new</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">contact</span><span class="o">.</span><span class="n">first_name</span> <span class="o">=</span> <span class="s2">&quot;Anthony&quot;</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">contact</span><span class="o">.</span><span class="n">last_name</span> <span class="o">=</span> <span class="s2">&quot;Eden&quot;</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">contact</span></div><div class='line' id='LC14'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC15'><br/></div><div class='line' id='LC16'>&nbsp;&nbsp;<span class="n">it</span> <span class="s2">&quot;has a name&quot;</span> <span class="k">do</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">subject</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">should</span> <span class="n">eq</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">#{</span><span class="n">subject</span><span class="o">.</span><span class="n">first_name</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">subject</span><span class="o">.</span><span class="n">last_name</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span></div><div class='line' id='LC18'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC19'><span class="k">end</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/960637/67da7edcbc2fc47effde7156c9a4790b7e9cdc4f/contact_spec.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/960637#file_contact_spec.rb" style="float:right;margin-right:10px;color:#666">contact_spec.rb</a>
            <a href="https://gist.github.com/960637">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>What I&#8217;m doing here is creating a contact class that is not in any way tied to ActiveRecord. This allows me to completely bypass the Rails loading process and these logic tests will run extremely fast. If you take this route you&#8217;ll need to make sure to use a modified spec helper that does not load the Rails environment. I call mine lightweight_spec_helper and only load what I need in it.</p>
<p>In closing, all of this is designed to make the application code easier to manage so that I can continue to improve DNSimple and make my customers happier. All of this is really only possible because I have a decent amount of test coverage, allowing me to refactor and not blow up everything in the process. Inevitably during refactorings like this things will break, but my tests cover me and protect me from myself, and thus I can extract and improve without feeling like I&#8217;ll shoot myself in the foot.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2011/05/refactoring-to-modules/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Presentations in Stockholm</title>
		<link>http://www.anthonyeden.com/2011/03/presentations-in-stockholm/</link>
		<comments>http://www.anthonyeden.com/2011/03/presentations-in-stockholm/#comments</comments>
		<pubDate>Mon, 28 Mar 2011 14:27:30 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[Cucumber]]></category>
		<category><![CDATA[Presentations]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.anthonyeden.com/?p=191</guid>
		<description><![CDATA[This month I had the pleasure of traveling up to Stockholm to speak at a couple of events there. First let me just say that Stockholm is an amazing city full of style, character and charm. From classic coffee houses to modern restaurants there is something for anyone. I highly recommend visiting if you have [...]]]></description>
			<content:encoded><![CDATA[<p>This month I had the pleasure of traveling up to Stockholm to speak at a couple of events there. First let me just say that Stockholm is an amazing city full of style, character and charm. From classic coffee houses to modern restaurants there is something for anyone. I highly recommend visiting if you have a chance &#8211; you won&#8217;t regret it.</p>
<p>While I was there I gave a talk called &#8220;Why Ruby, Why Now?&#8221; at the first dyncon as well as a talk titled Harnessing Cucumber at Valtech Labs. The first talk was an introduction to Ruby. I have been itching to give an introductory talk for a while and I&#8217;m glad this gave me the chance. The audience was a bit more knowledgeable about Ruby than I expected, so some of the items weren&#8217;t new to them, however I believe there was still enough in the talk to keep people interested. I also blazed through it since it was right before lunch so maybe people were enthralled merely by my lightning-fast presentation skills. <img src='http://www.anthonyeden.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':-D' class='wp-smiley' />  The presentation is available online on Github: <a href="https://github.com/aeden/presentation_why_ruby">https://github.com/aeden/presentation_why_ruby</a> and was created using Scott Chacon&#8217;s <a href="https://github.com/schacon/showoff">Show Off</a>.</p>
<p>The second talk I gave was an intermediate to advanced talk on Cucumber where I covered a lot of what I have learned about Cucumber over the last year of using it. Cucumber has become an important part of my test suites because it allows me to test the experience of using my software. This talk covered some of the various command-line switches and cucumber.yml configuration options in the first section and then moves onto testing APIs and CLIs. I&#8217;ve found that testing both of these interfaces to my applications has helped tremendously in improving the application and at the same time providing a safety net for refactoring, which is exactly what I want from Cucumber. This talk is available <a href="http://dl.dropbox.com/u/3308516/harnessing_cucumber.pdf">as a PDF</a> and was created using Keynote.</p>
<p>I appreciate the support from both of the audiences and the discussions that followed both talks and I look forward to the opportunity to visit Stockholm again in the not-to-distant future. Thanks as well to Peter Svensson for putting together dyncon and to Peter Lind for opening up the Valtech offices for my talk there.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2011/03/presentations-in-stockholm/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Retryable</title>
		<link>http://www.anthonyeden.com/2010/12/retryable/</link>
		<comments>http://www.anthonyeden.com/2010/12/retryable/#comments</comments>
		<pubDate>Tue, 21 Dec 2010 15:38:08 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[Flotsam]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.anthonyeden.com/?p=181</guid>
		<description><![CDATA[Today I wanted to use the retry keyword in Ruby to retry a section of code when an error is raised. In the process I came up with a simple bit of code for handling retries easily in any class, including a callback for putting any necessary fixes in place before executing the retry: And [...]]]></description>
			<content:encoded><![CDATA[<p>Today I wanted to use the retry keyword in Ruby to retry a section of code when an error is raised. In the process I came up with a simple bit of code for handling retries easily in any class, including a callback for putting any necessary fixes in place before executing the retry:</p>
<p><script src="https://gist.github.com/750063.js?file=retryable.rb"></script></p>
<p>And here is how it might be used:</p>
<p><script src="https://gist.github.com/750065.js?file=retryable_test.rb"></script></p>
<p>Give it a try using the following:</p>
<p><code>ruby retryable_test.rb</code></p>
<p>What do you think? How can this be improved?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2010/12/retryable/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Testing REST APIs with Cucumber and Rack::Test</title>
		<link>http://www.anthonyeden.com/2010/11/testing-rest-apis-with-cucumber-and-rack-test/</link>
		<comments>http://www.anthonyeden.com/2010/11/testing-rest-apis-with-cucumber-and-rack-test/#comments</comments>
		<pubDate>Tue, 02 Nov 2010 21:44:22 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[Cucumber]]></category>
		<category><![CDATA[DNSimple]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[cucumber]]></category>
		<category><![CDATA[rack]]></category>
		<category><![CDATA[rest]]></category>

		<guid isPermaLink="false">http://www.anthonyeden.com/?p=173</guid>
		<description><![CDATA[Corey Haines has been staying here in South France with me for the last few days and we had been meaning to pair up on some coding tasks, but hadn&#8217;t been able to until today. I had in my mind already what I wanted to work on and he was happy to oblige. Our task [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://coreyhaines.com/">Corey Haines</a> has been staying here in South France with me for the last few days and we had been meaning to pair up on some coding tasks, but hadn&#8217;t been able to until today. I had in my mind already what I wanted to work on and he was happy to oblige. Our task was to set up some cucumber features that would describe the <a href="https://dnsimple.com/documentation/api">DNSimple REST API</a> properly, allowing all of the available end points to be tested. I had worked on this in the past trying to use Webrat, but since moving the DNSimple code to Rails 3 I&#8217;ve switched to Capybara none of the old code worked. Additionally the old code was only able to handle GET requests and never properly handled POST, PUT and DELETE, nor did it handle the various content types supported by the API.</p>
<p>This evening Corey and I sat down and started looking into how we could make the tests live again. First we attempted to use Capybara directly, but ran into issues when trying to set HTTP headers. The DNSimple API uses Basic HTTP Authentication and thus we needed to set the header for that. We also need to set the Content-Type and Accept headers to ensure that Rails handles the input and output correctly. After peeling back some layers of the Capybara onion we landed upon Rack::Test. When using Rack, Capybara delegates request and response handling down to <a href="http://github.com/brynary/rack-test">Rack::Test</a>. At this point we decided to see if we could use Rack::Test directly in our step definitions, and it worked like a charm.</p>
<p>Rack::Test has a module called Rack::Test::Methods that can be mixed into a class to provide it with methods for get, post, put, delete as well as last_request, last_response, header and more. We mixed Rack::Test::Methods into the Cucumber world at the top of our API steps file like so:</p>
<p><script src="http://gist.github.com/660319.js?file=gistfile1.rb"></script></p>
<p>Then our steps could simply call the Rack::Test methods directly. For example, here&#8217;s how to send the HTTP Basic Auth header:</p>
<p><script src="http://gist.github.com/660321.js?file=gistfile1.rb"></script></p>
<p>And to set content type and accept headers:</p>
<p><script src="http://gist.github.com/660323.js?file=gistfile1.rb"></script></p>
<p>And finally to actually send requests and test the responses. The entire api_steps.rb as it is right now looks like this:</p>
<p><script src="http://gist.github.com/660331.js?file=api_steps.rb"></script></p>
<p>And here is an example of a Cucumber feature that uses the API steps:</p>
<p><script src="http://gist.github.com/660337.js?file=list_domains.feature"></script></p>
<p>I doubt we&#8217;ve ended up with the ultimate final set of steps that can be used repeatedly for testing RESTful APIs, however I think it is an excellent start. I&#8217;m still on the fence about how to check the response body, specifically whether it is better to match the response body as a string or to actually parse it and write custom steps for each of the different types of objects, but time will tell.</p>
<p>As usual pairing with Corey resulted in some good code, a usable solution and something that I think others will benefit from as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2010/11/testing-rest-apis-with-cucumber-and-rack-test/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Stubbing Before Everything with RSpec</title>
		<link>http://www.anthonyeden.com/2010/04/stubbing-before-everything-with-rspe/</link>
		<comments>http://www.anthonyeden.com/2010/04/stubbing-before-everything-with-rspe/#comments</comments>
		<pubDate>Sat, 03 Apr 2010 09:13:15 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[RSpec]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[mock]]></category>
		<category><![CDATA[stub]]></category>

		<guid isPermaLink="false">http://www.anthonyeden.com/?p=132</guid>
		<description><![CDATA[Let&#8217;s say I want to always stub some external service client before every model and controller spec. For example, if I want to stub RSpreedly (a nice client interface to the Spreedly recurring payment processor), I put the following in spec/support/stubs.rb: Now RSpreedly::Subscriber instances will always be stubbed. Simple and sweet.]]></description>
			<content:encoded><![CDATA[<p>Let&#8217;s say I want to always stub some external service client before every model and controller spec. For example, if I want to stub RSpreedly (a nice client interface to the Spreedly recurring payment processor), I put the following in spec/support/stubs.rb:</p>
<p><script src="http://gist.github.com/354294.js?file=stubs.rb"></script></p>
<p>Now RSpreedly::Subscriber instances will always be stubbed. Simple and sweet.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2010/04/stubbing-before-everything-with-rspe/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XSS and Building HTML in JavaScript</title>
		<link>http://www.anthonyeden.com/2010/02/xss-and-building-html-in-javascript/</link>
		<comments>http://www.anthonyeden.com/2010/02/xss-and-building-html-in-javascript/#comments</comments>
		<pubDate>Tue, 16 Feb 2010 22:04:31 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[ujs]]></category>

		<guid isPermaLink="false">http://www.anthonyeden.com/?p=123</guid>
		<description><![CDATA[In my recent article on Rails, JQuery, Unobtrusive JS and Graceful Degradation I implemented the Ajax logic for adding a new entry using JSON returned from the server to build the HTML in JavaScript. An attentive reader brought to my attention the cross-site scripting vulnerability that is possible with this implementation and I think this [...]]]></description>
			<content:encoded><![CDATA[<p>In my recent article on <a href="http://www.anthonyeden.com/2010/02/rails-jquery-unobtrusive-js-and-graceful-degradation/">Rails, JQuery, Unobtrusive JS and Graceful Degradation</a> I implemented the Ajax logic for adding a new entry using JSON returned from the server to build the HTML in JavaScript. An attentive reader brought to my attention the cross-site scripting vulnerability that is possible with this implementation and I think this would be a good time to address the issue and open the comments to other options.</p>
<p>First of all let&#8217;s look at the most obvious attack vector, which is pretty simple: a malicious user would enter a script into the person name field and save that and then it would execute the script when the person is rendered in the person list. First I verified that this attack vector worked, and yes it did work, so then I considered where the value entered by the user needed to be sanitized. It&#8217;s pretty straightforward to sanitize the rendering when Rails is involved, just add the <code>h()</code> helper before the name output in the listing, so line 4 of index.html.erb becomes:</p>
<p><script src="http://gist.github.com/305978.js?file=gistfile1.rhtml"></script></p>
<p>This is a fairly standard idiom in Rails (not necessarily the best way to sanitize user input, but the most common way to do it). This fix only fixes the problem when the page is rendered by Rails, but it does not address the issue for items that are added via Ajax, and here is where things get a bit tricky.</p>
<p>You&#8217;d think that sanitizing user input in JavaScript would be fairly easy, and to be clear you can do it with the JavaScript <code>escape()</code> function, however this results in some pretty ugly percent-encoded content (which may or may not matter to you. I was curious though whether there was something similar to the <code>h()</code> helper in Rails available in JavaScript. There is but finding it proved to be a bit of a challenge.</p>
<p>What I ended up doing what searching <a href="http://stackoverflow.com/">Stack Overflow</a> for solutions that others had come up with and eventually landed upon this bit of code: <a href="http://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/plugin/html-sanitizer.js">http://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/plugin/html-sanitizer.js</a>. Unfortunately this bit of code by itself doesn&#8217;t work unless you have another JS library (html4) and that library requires building with Ant. Fortunately additional searching led me to a minified version with everything already compiled. I&#8217;ve included this minified library as html-sanitizer-minified.js and added a call to html_santize before rendering the person name in the JavaScript as such:</p>
<p><script src="http://gist.github.com/305989.js?file=gistfile1.js"></script></p>
<p>..and it works. I&#8217;ve deployed this fix to <a href="http://rails-jquery-unobtrusive.heroku.com/">http://rails-jquery-unobtrusive.heroku.com/</a> and have updated the <a href="http://github.com/aeden/unobtrusive-jquery-example">github repo</a> so you can see the changes in action.</p>
<p>So is this the best solution for handling user input and avoiding XSS when you want to build HTML in JavaScript? I&#8217;m not sure. It&#8217;s probably not the only solution so feel free to add yours in the comments below. Also, consider this a warning if you are developing JavaScript code that builds and renders HTML: tainted user input is a threat and you need to deal with it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2010/02/xss-and-building-html-in-javascript/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Rails, JQuery, Unobtrusive JS and Graceful Degradation</title>
		<link>http://www.anthonyeden.com/2010/02/rails-jquery-unobtrusive-js-and-graceful-degradation/</link>
		<comments>http://www.anthonyeden.com/2010/02/rails-jquery-unobtrusive-js-and-graceful-degradation/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 21:50:24 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[ujs]]></category>

		<guid isPermaLink="false">http://www.anthonyeden.com/?p=115</guid>
		<description><![CDATA[I&#8217;m always on the lookout for ways to improve my web applications. To that end I wanted to see if I could come up with a way to marry jQuery and Rails in a way that was both unobtrusive and a way that would degrade gracefully in a Rails 2.3.5 application. I&#8217;m looking forward to [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m always on the lookout for ways to improve my web applications. To that end I wanted to see if I could come up with a way to marry jQuery and Rails in a way that was both unobtrusive and a way that would degrade gracefully in a Rails 2.3.5 application. I&#8217;m looking forward to seeing how UJS with jQuery in Rails looks as of Rails 3.0, however in the meantime the method I describe below may prove to be useful.</p>
<p>If you want to go straight to the code it is available on Github: <a href="http://github.com/aeden/unobtrusive-jquery-example">http://github.com/aeden/unobtrusive-jquery-example</a>. I have also put a live demo on this up on Heroku: <a href="http://rails-jquery-unobtrusive.heroku.com">http://rails-jquery-unobtrusive.heroku.com</a>.</p>
<p>Rather than going through all of the steps needed to set up a Rails app, the best thing to do is to follow along in the code from the example above.</p>
<p>First let&#8217;s take a look at the PeopleController (app/controllers/people_controller.rb):</p>
<p><script src="http://gist.github.com/296266.js?file=gistfile1.rb"></script></p>
<p>This looks like a fairly normal RESTful controller. The one exception is the delete method, which will be used by browsers that have JavaScript turned off to provide a page that 1.) confirms that the record should be deleted and 2.) has a form that can post to the destroy method.</p>
<p>Next, let&#8217;s take a look at the index view:</p>
<p><script src="http://gist.github.com/296269.js?file=gistfile1.rhtml"></script></p>
<p>There is a list of people with each person having a delete link next to their name. The delete link points to /person/:id/delete which will execute the delete action that I mentioned above (I&#8217;ll show you how to remove the &#8220;/delete&#8221; part of that link with JavaScript later). There is also a form for adding a new person. Note that there is no JavaScript in this page, just normal HTML elements with classes.</p>
<p>While we&#8217;re looking at views, let&#8217;s look at the only other view, the delete view:</p>
<p><script src="http://gist.github.com/296270.js?file=gistfile1.rhtml"></script></p>
<p>This is just a simple form that confirms that they want to delete the user and provides a cancel link back to the people_url if they don&#8217;t. Note that the form tag uses the REST-ful URL for accessing the resource and sets &#8216;_method&#8217; to &#8216;delete&#8217; in the hidden field tag.</p>
<p>Finally, let&#8217;s take a look at the most complicated bit, the jQuery JavaScript. To make things easier to follow I&#8217;ll go through it piece by piece, starting with the document ready handler:</p>
<p><script src="http://gist.github.com/296271.js?file=gistfile1.js"></script></p>
<p>This is the jQuery way for executing code when the document has finished loading. All it does is call two methods, one for connecting up the add form and one for connecting up the delete links. To keep things organized and namespaced a bit I placed these two methods onto a JS object called &#8216;Actions&#8217;. First, the connectAddForm implementation:</p>
<p><script src="http://gist.github.com/296272.js?file=gistfile1.js"></script></p>
<p>This function finds the form element with the class &#8220;people&#8221; and attaches an event handler to the submit event. When the form is submitted an AJAX POST is made. The data type is JSON, which will call the &#8216;create&#8217; action in the people controller with the accepts type set to a value that triggers Rails to render JSON as the response. The form is serialized and passed as data and when a successful response is received a bit of HTML is appended to the people list and the person name field is cleared.</p>
<p>Now for the connect delete links JavaScript:</p>
<p><script src="http://gist.github.com/296273.js?file=gistfile1.js"></script></p>
<p>Here each element that is in the people list that matches the selector a.delete and adds a click handler to it. Notice that I used the jQuery live method here, the benefit being that as new records are added, and new elements that match the selector expression are added automatically get the click handler that I define here. This saves me from the trouble of having to add the handler each time that a record is added to the page. The click handler first finds the li that it may eventually delete, displays a confirmation message to the viewer and if they confirm that they want to delete the record it will post via AJAX to the /person/:id URL with the method &#8216;delete&#8217;. The URL is pulled from the anchor&#8217;s href attribute and the &#8216;/delete&#8217; is removed using a simple regular expression replace. Upon a successful delete the li that was found earlier is hidden using the slideToggle() function.</p>
<p>That&#8217;s it. You can try this in a browser either with JavaScript turned on, in which case it&#8217;ll use all of the JavaScript goodness, or you can turn of JavaScript and see the magic of graceful degradation. I hope you&#8217;ve enjoyed reading this little tutorial and if you have any suggestions on how to improve the code in the project please feel free to fork the github project, make your changes and send me a pull request. I&#8217;ll add any cool mods into the tutorial as I can.</p>
<p><b>Update:</b> I&#8217;ve <a href="http://www.anthonyeden.com/2010/02/xss-and-building-html-in-javascript/">published a follow-on article</a> that talks about changes to the code for this tutorial to handle sanitizing user input both in Rails and in JavaScript. I suggest reading it to understand XSS vulnerabilities that you need to deal with when accepting user input.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2010/02/rails-jquery-unobtrusive-js-and-graceful-degradation/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Aloha on Rails &#8211; Technical Debt Slides</title>
		<link>http://www.anthonyeden.com/2009/10/aloha-on-rails-technical-debt-slides/</link>
		<comments>http://www.anthonyeden.com/2009/10/aloha-on-rails-technical-debt-slides/#comments</comments>
		<pubDate>Wed, 07 Oct 2009 07:55:42 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[alohaonrails]]></category>
		<category><![CDATA[presentation]]></category>
		<category><![CDATA[refactoring]]></category>
		<category><![CDATA[technical debt]]></category>

		<guid isPermaLink="false">http://www.anthonyeden.com/?p=111</guid>
		<description><![CDATA[Thanks to everyone who came out to Aloha on Rails and a huge mahalo to Seth for putting so much into it. It was awesome. Here are the slides for my talk: Technical Debt . I&#8217;ve left the presenter notes in so you can see what I was thinking when I put the slide together [...]]]></description>
			<content:encoded><![CDATA[<p>Thanks to everyone who came out to <a href="http://alohaonrails.com">Aloha on Rails</a> and a huge mahalo to <a href="http://blog.semergence.com/">Seth</a> for putting so much into it. It was awesome.</p>
<p>Here are the slides for my talk: <a href="http://www.anthonyeden.com/wp-content/uploads/2009/10/Technical-Debt.pdf">Technical Debt</a> . I&#8217;ve left the presenter notes in so you can see what I was thinking when I put the slide together (since most of the slides are just pictures anyhow.) Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2009/10/aloha-on-rails-technical-debt-slides/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

