<?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>andy goundry &#187; Ruby</title>
	<atom:link href="http://www.andygoundry.com/category/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.andygoundry.com</link>
	<description>web developer</description>
	<lastBuildDate>Wed, 01 Feb 2012 16:01:06 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Debugging cucumber scenarios in Rubymine</title>
		<link>http://www.andygoundry.com/2012/02/01/debugging-cucumber-scenarios-in-rubymine/</link>
		<comments>http://www.andygoundry.com/2012/02/01/debugging-cucumber-scenarios-in-rubymine/#comments</comments>
		<pubDate>Wed, 01 Feb 2012 15:52:10 +0000</pubDate>
		<dc:creator>andy</dc:creator>
				<category><![CDATA[Cucumber]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Rubymine]]></category>
		<category><![CDATA[bdd]]></category>

		<guid isPermaLink="false">http://www.andygoundry.com/?p=645</guid>
		<description><![CDATA[Debugging cucumber scenarios in Rubymine is wonderfully simple. Here&#8217;s how i do it:
Create a cucumber step that puts the app into debug mode and pops open the current page that&#8217;s being debugged

I use Rubymine&#8217;s gutter breakpoints, and I add the breakpoint after the save_and_open_page method call, so the page pops open before entering the debugger.
Insert [...]]]></description>
			<content:encoded><![CDATA[<p>Debugging cucumber scenarios in Rubymine is wonderfully simple. Here&#8217;s how i do it:</p>
<h3><span style="font-weight: normal;">Create a cucumber step that puts the app into debug mode and pops open the current page that&#8217;s being debugged</span></h3>
<p><img class="alignnone size-full wp-image-658" title="Screen Shot 2012-02-01 at 16.00.42" src="http://www.andygoundry.com/wp-content/uploads/2012/02/Screen-Shot-2012-02-01-at-16.00.42.png" alt="Screen Shot 2012-02-01 at 16.00.42" width="258" height="62" /></p>
<p>I use Rubymine&#8217;s gutter breakpoints, and I add the breakpoint after the save_and_open_page method call, so the page pops open before entering the debugger.</p>
<h3><span style="font-weight: normal;">Insert the step into whichever scenario i wish to debug</span></h3>
<p><img class="alignnone size-full wp-image-647" title="Screen Shot 2012-02-01 at 15.43.25" src="http://www.andygoundry.com/wp-content/uploads/2012/02/Screen-Shot-2012-02-01-at-15.43.25.png" alt="Screen Shot 2012-02-01 at 15.43.25" width="569" height="71" /></p>
<h3><span style="font-weight: normal;">Run the scenario in debug mode</span></h3>
<p><img class="alignnone size-full wp-image-649" title="Screen Shot 2012-02-01 at 15.48.36" src="http://www.andygoundry.com/wp-content/uploads/2012/02/Screen-Shot-2012-02-01-at-15.48.36.png" alt="Screen Shot 2012-02-01 at 15.48.36" width="355" height="528" /></p>
<h3><span style="font-weight: normal;">Inspect the app&#8217;s objects in Rubymine&#8217;s Watches</span></h3>
<p><img class="alignnone size-full wp-image-648" title="Screen Shot 2012-02-01 at 15.36.27" src="http://www.andygoundry.com/wp-content/uploads/2012/02/Screen-Shot-2012-02-01-at-15.36.27.png" alt="Screen Shot 2012-02-01 at 15.36.27" width="637" height="152" /></p>
<p>Pretty sweet! Super easy and extremely useful.</p>
<p>Rubymine&#8217;s a great app, and i&#8217;m just starting to scratch the surface.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.andygoundry.com/2012/02/01/debugging-cucumber-scenarios-in-rubymine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ensuring postgres gem is installed on heroku when using Rails 3.1</title>
		<link>http://www.andygoundry.com/2012/01/07/ensuring-postgres-gem-is-installed-on-heroku-when-using-rails-3-1/</link>
		<comments>http://www.andygoundry.com/2012/01/07/ensuring-postgres-gem-is-installed-on-heroku-when-using-rails-3-1/#comments</comments>
		<pubDate>Sun, 08 Jan 2012 00:54:43 +0000</pubDate>
		<dc:creator>andy</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[bundler]]></category>
		<category><![CDATA[heroku]]></category>

		<guid isPermaLink="false">http://www.andygoundry.com/?p=636</guid>
		<description><![CDATA[It turns out that Rails 3.1 doesn&#8217;t come with a database adapter. So, when deploying to heroku, the app will blow up unless you add the require postgres gem to your gem file:
group :production do
gem &#8220;pg&#8221;
end
group :production do
gem &#8220;pg&#8221;
end
This resolves the heroku error
/app/.bundle/gems/ruby/1.9.1/gems/activerecord-3.1.0/lib/active_record/connection_adapters/abstract/connection_specification.rb:71:in `rescue in establish_connection&#8217;: Please install the postgresql adapter: `gem install activerecord-postgresql-adapter` (pg is [...]]]></description>
			<content:encoded><![CDATA[<p>It turns out that Rails 3.1 doesn&#8217;t come with a database adapter. So, when deploying to heroku, the app will blow up unless you add the require postgres gem to your gem file:</p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">group :production do</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">gem &#8220;pg&#8221;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">end</div>
<blockquote><p>group :production do</p>
<p>gem &#8220;pg&#8221;</p>
<p>end</p></blockquote>
<p>This resolves the heroku error</p>
<blockquote><p>/app/.bundle/gems/ruby/1.9.1/gems/activerecord-3.1.0/lib/active_record/connection_adapters/abstract/connection_specification.rb:71:in `rescue in establish_connection&#8217;: Please install the postgresql adapter: `gem install activerecord-postgresql-adapter` (pg is not part of the bundle. Add it to Gemfile.)</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.andygoundry.com/2012/01/07/ensuring-postgres-gem-is-installed-on-heroku-when-using-rails-3-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ensuring that Heroku does not install gems within the Bundler :development group</title>
		<link>http://www.andygoundry.com/2012/01/07/ensuring-that-heroku-does-not-install-gems-within-the-bundler-development-group/</link>
		<comments>http://www.andygoundry.com/2012/01/07/ensuring-that-heroku-does-not-install-gems-within-the-bundler-development-group/#comments</comments>
		<pubDate>Sun, 08 Jan 2012 00:38:06 +0000</pubDate>
		<dc:creator>andy</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[bundler]]></category>
		<category><![CDATA[heroku]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.andygoundry.com/?p=634</guid>
		<description><![CDATA[Tonight, i ran into an issue with Heroku, where is was failing when installing a gem that i have within my :development bundler group:
group :development, :test, :cucumber do
gem &#8216;ruby-debug19&#8242;
end
As the clear solution was to prevent heroku installing gems that it didn&#8217;t need, i found this handy heroku command:
heroku config:add BUNDLE_WITHOUT=&#8221;development:test:cucumber&#8221;
Running this has told heroku to [...]]]></description>
			<content:encoded><![CDATA[<p>Tonight, i ran into an issue with Heroku, where is was failing when installing a gem that i have within my :development bundler group:</p>
<blockquote><p>group :development, :test, :cucumber do</p>
<p>gem &#8216;ruby-debug19&#8242;</p>
<p>end</p></blockquote>
<p>As the clear solution was to prevent heroku installing gems that it didn&#8217;t need, i found this handy heroku command:</p>
<blockquote><p>heroku config:add BUNDLE_WITHOUT=&#8221;development:test:cucumber&#8221;</p></blockquote>
<p>Running this has told heroku to ignore gems that it doesn&#8217;t need, meaning the deploy worked fine. Further details: http://devcenter.heroku.com/articles/bundler</p>
<p>This resolves the heroku error:</p>
<blockquote><p>Installing linecache19 (0.5.12) with native extensions /usr/ruby1.9.2/lib/ruby/1.9.1/rubygems/installer.rb:483:in `rescue in block in build_extensions&#8217;: ERROR: Failed to build gem native extension. (Gem::Installer::ExtensionBuildError)</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.andygoundry.com/2012/01/07/ensuring-that-heroku-does-not-install-gems-within-the-bundler-development-group/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Testing Paperclip generated expiring S3 urls with RSpec, Cucumber and Timecop</title>
		<link>http://www.andygoundry.com/2011/12/21/using-cucumber-to-test-s3-expiring-urls/</link>
		<comments>http://www.andygoundry.com/2011/12/21/using-cucumber-to-test-s3-expiring-urls/#comments</comments>
		<pubDate>Wed, 21 Dec 2011 07:07:15 +0000</pubDate>
		<dc:creator>andy</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[bdd]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[rspec]]></category>

		<guid isPermaLink="false">http://www.andygoundry.com/?p=529</guid>
		<description><![CDATA[The need
I have a Rails app that is using Paperclip to generate expiring urls for files stored in S3. The urls are set to expire after 1 minute. As much as i trust Paperclip and Amazon, I need tests that prove that these generated urls do in fact expire on time, and that visitors to [...]]]></description>
			<content:encoded><![CDATA[<h2>The need</h2>
<p>I have a Rails app that is using Paperclip to generate expiring urls for files stored in S3. The urls are set to expire after 1 minute. As much as i trust Paperclip and Amazon, I need tests that prove that these generated urls do in fact expire on time, and that visitors to those files after they&#8217;ve expired are prevented from accessing the file.</p>
<h2 style="font-size: 1.5em;">Disclaimer</h2>
<p>This has been a bit of a rush, so no doubt i&#8217;ll refactor and tidy the code and this post laster today / in the week.</p>
<h2 style="font-size: 1.5em;">The solution</h2>
<p>I&#8217;ve used RSpec and Cucumber to check expiring urls that the system generates to ensure they expire successfully. RSpec simply checks that a generated url includes the Expires parameter and it&#8217;s value is set exactly to 60 seconds from now. Cucumber goes further than this by uploading files and checking if they are accessible before and after expiration.</p>
<h3><span style="color: #333399;"> RSpec to simply test that the expiration time generated for a link is correctly set to 1 minute<br />
</span></h3>
<p>This test simply asks the model containing the attachment (in this case an &#8220;Asset&#8221; model), how many seconds from now remain before the attachment expires.</p>
<p><strong>Spec</strong></p>
<blockquote><p>describe Asset do</p>
<p style="padding-left: 30px; "><strong> it &#8220;should return an attachment link that expires within 1 minute&#8221; do</strong></p>
<p style="padding-left: 60px;">asset = Factory.build(:asset)<br />
asset.seconds_until_attachment_expires.should == 60</p>
<p style="padding-left: 30px; ">end</p>
<p>end</p></blockquote>
<p>This depends on a few new methods in the Asset model class, which take care of extracting the Expires param from the expiring url, and comparing to Time.now.</p>
<p><strong>Asset Model Class</strong></p>
<p>First, we create an instance helper method that returns the number of seconds an object&#8217;s url has left before it expires</p>
<blockquote><p>def seconds_until_attachment_expires</p>
<p style="padding-left: 30px;">Asset.seconds_until_attachment_expires(expiring_attachment_url)</p>
<p>end</p></blockquote>
<p>I decided to pass the responsibility of calculating this number to a class method. I did this because the Cucumber tests need to request the same calculation for urls that were generated in the past. If they interacted with an instance of the Asset class, by default it would return a new url each time it was asked. So, rather than clutter up the instance method with a decision about whether to issue a new url or return an existing one, i simply passed the responsibility to the class. That seems to work for now, although I might refactor it later.</p>
<p>Next, we create the class level method that calculates time left until expiration. This accepts a url, meaning we can test urls generated now or in the past</p>
<blockquote><p>def self.seconds_until_attachment_expires(url)</p>
<p style="padding-left: 30px;">seconds = attachment_expiration_in_seconds_from_epoch(url) &#8211; Time.now.strftime(&#8221;%s&#8221;).to_i<br />
seconds.round</p>
<p>end</p></blockquote>
<p>This method simply strips the time from the generated url (via the attachment_expiration_in_seconds_from_epoch method) and rounds the value.</p>
<blockquote><p>def self.attachment_expiration_in_seconds_from_epoch(url)</p>
<p style="padding-left: 30px;">url.split(&#8221;&amp;&#8221;).second.split(&#8221;=&#8221;).last.to_i</p>
<p>end</p></blockquote>
<p>Clearly, this is tightly coupled to the format of the generated url string, so a cleaner way should be sought. However, for now, this method is only used in the tests and it does work, so it&#8217;ll do for the moment.</p>
<p>Finally, to ensure that Rspec, Cucumber and the app all interact with a url generated exactly 60 seconds from now, we create a model instance method that generates the link. All requests for the link call this method.</p>
<blockquote><p>def expiring_attachment_url</p>
<p style="padding-left: 30px;">attachment.expiring_url(60)</p>
<p>end</p></blockquote>
<h3 style="font-size: 1.17em;"><span style="color: #333399;">Cucumber to test actual file access via the browser</span></h3>
<p>Cucumber takes things 1 step further. It interacts with all the same methods that we created on the Asset model, but also goes off and uploads attachments and then tries to access them before and after they&#8217;ve expired. We use <a href="http://www.google.co.uk/url?sa=t&amp;rct=j&amp;q=timecop%20gem&amp;source=web&amp;cd=1&amp;ved=0CCEQFjAA&amp;url=https%3A%2F%2Fgithub.com%2Fjtrupiano%2Ftimecop&amp;ei=CarxTpfiJMLLswbLlM3mDw&amp;usg=AFQjCNHx9MgEnBzIw0ysdxhOMlxC40j_4Q">Timecop</a> to create expired urls, and a Cucumber <em>before</em> hook to ensure all scenarios run from the current time by default.</p>
<p><strong>Scenarios</strong></p>
<blockquote><p>@selenium<br />
<strong>Scenario: Viewing an active attachment on an object</strong></p>
<p style="padding-left: 30px;"><strong> </strong>Given some object has been created and a plain text file attached<br />
When I visit the object&#8217;s attachment url<br />
Then I should see the contents of the uploaded attachment<br />
And I should not see &#8220;Request has expired&#8221;</p>
<p>@selenium<br />
<strong>Scenario: Viewing an expired attachment on an object</strong></p>
<p style="padding-left: 30px;"><strong> </strong>Given some object has been created and a plain text file attached<br />
When I visit the object&#8217;s attachment url after it has expired<br />
Then I should not see the contents of the uploaded attachment<br />
And I should see &#8220;Request has expired&#8221;</p>
</blockquote>
<p><strong>features/support/hooks.rb</strong></p>
<blockquote><p>Before do</p>
<p style="padding-left: 30px;">Timecop.return</p>
<p>end</p></blockquote>
<p>NB: For the sake of completeness (even though we&#8217;re not calling Timecop from our Rspec specs), to be completely satisfied that Timecop isn&#8217;t affecting our specs in any unexpected way, we add the same to spec_helper.rb too:</p>
<p><strong>spec/spec_helper.rb</strong></p>
<p><strong><span style="font-weight: normal; "> </span></strong></p>
<blockquote><p>config.before do</p>
<p style="padding-left: 30px;">Timecop.return</p>
<p>end</p></blockquote>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 776px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">config.before do</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 776px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Timecop.return</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 776px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">end</div>
<p><strong>steps</strong></p>
<p>This is where Timecop offers a wonderfully simple way of generating expired urls.</p>
<blockquote><p><strong>And /^I visit the question&#8217;s attachment url after it has expired$/ do</strong></p>
<p style="padding-left: 30px;"><span style="color: #3366ff;"><span style="color: #008080;"><span style="color: #99ccff;"><span style="color: #ff9900;"><span style="color: #333399;"><strong>#First, go back in time 2 minutes and generate the expiring url, and make sure it&#8217;s set to expire in 1 minute</strong><br />
</span> </span> </span> </span> </span> Timecop.freeze(Time.now &#8211; 2.to_i.minutes) do</p>
<p style="padding-left: 60px;">@url = current_object.asset.expiring_attachment_url<br />
Asset.attachment_expires_in(@url).should == 60</p>
<p style="padding-left: 30px;">end</p>
<p style="padding-left: 30px;"><strong><span style="color: #3366ff;"><span style="color: #008080;"><span style="color: #99ccff;"><span style="color: #ff9900;"><span style="color: #333399;"> #Next, return to the current time and make sure the previously generated expiring url has now been expired for 1 minute<br />
</span> </span> </span> </span> </span></strong> Timecop.return<br />
Asset.attachment_expires_in(@url).should == -60</p>
<p style="padding-left: 30px;"><strong><span style="color: #3366ff;"><span style="color: #008080;"><span style="color: #99ccff;"><span style="color: #ff9900;"><span style="color: #333399;"> #Finally, go visit the expired url<br />
</span> </span> </span> </span> </span></strong> visit @url</p>
<p>end</p></blockquote>
<p>When run, cucumber correctly reports that expired urls result in the user seeing the message &#8220;Request has expired&#8221;, and non-expired urls correctly provide access to the uploaded file.</p>
<h2 style="font-size: 1.5em;">Summary</h2>
<p>Although a rough and ready solution, and most likely needing refactoring, it does provide us with a way to test expiration of uploads to S3.</p>
<p>I hope you found this useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.andygoundry.com/2011/12/21/using-cucumber-to-test-s3-expiring-urls/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Making S3 file uploads private yet accessible via your rails app using Paperclip</title>
		<link>http://www.andygoundry.com/2011/12/20/making-s3-file-uploads-private-yet-accessible-in-rails-with-paperclip/</link>
		<comments>http://www.andygoundry.com/2011/12/20/making-s3-file-uploads-private-yet-accessible-in-rails-with-paperclip/#comments</comments>
		<pubDate>Tue, 20 Dec 2011 17:33:49 +0000</pubDate>
		<dc:creator>andy</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.andygoundry.com/?p=521</guid>
		<description><![CDATA[The need
I needed to make file uploads to S3 secure. Files must be private in S3 (i.e. not accessible if someone guessed the url), yet accessible via the rails based web app.
The solution
Add this to the rails model:
has_attached_file :attachment,
:storage =&#62; :s3,
:s3_credentials =&#62; &#8216;config/amazon_s3.yml&#8217;,
:s3_permissions =&#62; :private
Replaced this in the view:
Replaced: asset.attachment.url
With: asset.attachment.expiring_url(60)
This keeps the files private, and the [...]]]></description>
			<content:encoded><![CDATA[<h2><strong>The need</strong></h2>
<p>I needed to make file uploads to S3 secure. Files must be private in S3 (i.e. not accessible if someone guessed the url), yet accessible via the rails based web app.</p>
<h2><strong>The solution</strong></h2>
<p>Add this to the rails model:</p>
<blockquote><p>has_attached_file :attachment,</p>
<p>:storage =&gt; :s3,</p>
<p>:s3_credentials =&gt; &#8216;config/amazon_s3.yml&#8217;,</p>
<p><strong>:s3_permissions =&gt; :private</strong></p></blockquote>
<p>Replaced this in the view:</p>
<blockquote><p>Replaced: asset.attachment.url</p>
<p>With: asset.attachment.<strong>expiring_url(60)</strong></p></blockquote>
<p>This keeps the files private, and the app creates expiring urls as users request them, which expire after a minute.</p>
<h2>What Amazon Say</h2>
<p><span style="font-family: verdana, arial, sans-serif; line-height: normal;"> </span></p>
<div class="titlepage" style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; padding: 0px; margin: 0px;">
<div style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; padding: 0px; margin: 0px;">
<div style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; padding: 0px; margin: 0px;">
<h2 id="RESTAuthenticationQueryStringAuth" class="title" style="color: #cc6600; font-size: 14px; font-weight: bold; clear: both;">Query String Request Authentication Alternative</h2>
</div>
</div>
</div>
<p style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; margin-bottom: 1em;">You can authenticate certain types of requests by passing the required information as query-string parameters instead of using the <code class="code" style="font-family: 'Courier New', Courier, mono; font-size: 12px;">Authorization</code> HTTP header. This is useful for enabling direct third-party browser access to your private Amazon S3 data, without proxying the request. The idea is to construct a &#8220;pre-signed&#8221; request and encode it as a URL that an end-user&#8217;s browser can retrieve. Additionally, you can limit a pre-signed request by specifying an expiration time.</p>
<div class="section" style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; padding: 0px; margin: 0px;" lang="en">
<div class="titlepage" style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; padding: 0px; margin: 0px;">
<div style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; padding: 0px; margin: 0px;">
<div style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; padding: 0px; margin: 0px;">
<h3 id="CreatingASignature" class="title" style="color: #006699; font-size: 12px; font-weight: bold; padding: 0px;">Creating a Signature</h3>
</div>
</div>
</div>
<p><a name="d0e4215"></a></p>
<p style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; margin-bottom: 1em;">Following is an example query string authenticated Amazon S3 REST request.</p>
<pre class="programlisting" style="font-family: 'Courier New', Courier, mono; font-size: 12px; color: #000066; background-color: #eeeeee; margin-top: 5px; margin-bottom: 5px; overflow-x: auto; overflow-y: auto; width: 1083px; padding: 1em; border: 1px dashed #333333;">GET /photos/puppy.jpg
?AWSAccessKeyId=0PN5J17HBGZHT7JJ3X82&amp;Expires=1141889120&amp;Signature=vjbyPxybdZaNmGa%2ByT272YEAiv4%3D HTTP/1.1
Host: johnsmith.s3.amazonaws.com
Date: Mon, 26 Mar 2007 19:37:58 +0000</pre>
<p style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; margin-bottom: 1em;">The query string request authentication method doesn&#8217;t require any special HTTP headers. Instead, the required authentication elements are specified as query string parameters:</p>
</div>
<table style="-webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; border: 1px solid #cccccc;" border="0" cellspacing="0">
<colgroup>
<col></col>
<col></col>
<col></col>
</colgroup>
<thead>
<tr>
<th style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #333333; vertical-align: top; background-color: #eeeeee; font-weight: bold; text-align: left; padding: 5px; margin: 0px; border: 1px solid #cccccc;">Query String Parameter Name</th>
<th style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #333333; vertical-align: top; background-color: #eeeeee; font-weight: bold; text-align: left; padding: 5px; margin: 0px; border: 1px solid #cccccc;">Example Value</th>
<th style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #333333; vertical-align: top; background-color: #eeeeee; font-weight: bold; text-align: left; padding: 5px; margin: 0px; border: 1px solid #cccccc;">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; vertical-align: top; padding: 5px; margin: 0px; border: 1px solid #cccccc;"><em><code style="font-family: 'Courier New', Courier, mono; font-size: 12px;">AWSAccessKeyId</code></em></td>
<td style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; vertical-align: top; padding: 5px; margin: 0px; border: 1px solid #cccccc;"><code class="code" style="font-family: 'Courier New', Courier, mono; font-size: 12px;">0PN5J17HBGZHT7JJ3X82</code></td>
<td style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; vertical-align: top; padding: 5px; margin: 0px; border: 1px solid #cccccc;">Your AWS Access Key Id. Specifies the AWS Secret Access Key used to sign the request, and (indirectly) the identity of the developer making the request.</td>
</tr>
<tr>
<td style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; vertical-align: top; padding: 5px; margin: 0px; border: 1px solid #cccccc;"><em><code style="font-family: 'Courier New', Courier, mono; font-size: 12px;">Expires</code></em></td>
<td style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; vertical-align: top; padding: 5px; margin: 0px; border: 1px solid #cccccc;"><code class="code" style="font-family: 'Courier New', Courier, mono; font-size: 12px;">1141889120</code></td>
<td style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; vertical-align: top; padding: 5px; margin: 0px; border: 1px solid #cccccc;">The time when the signature expires, specified as the number of seconds since the epoch (00:00:00 UTC on January 1, 1970). A request received after this time (according to the server), will be rejected.</td>
</tr>
<tr>
<td style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; vertical-align: top; padding: 5px; margin: 0px; border: 1px solid #cccccc;"><em><code style="font-family: 'Courier New', Courier, mono; font-size: 12px;">Signature</code></em></td>
<td style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; vertical-align: top; padding: 5px; margin: 0px; border: 1px solid #cccccc;"><code class="code" style="font-family: 'Courier New', Courier, mono; font-size: 12px;">vjbyPxybdZaNmGa%2ByT272YEAiv4%3D</code></td>
<td style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; vertical-align: top; padding: 5px; margin: 0px; border: 1px solid #cccccc;">The URL encoding of the Base64 encoding of the HMAC-SHA1 of StringToSign.</td>
</tr>
</tbody>
</table>
<p><span style="font-family: verdana, arial, sans-serif; line-height: normal;"> </span></p>
<div class="section" style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; padding: 0px; margin: 0px;" lang="en">
<p style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; margin-bottom: 1em;">The query string request authentication method differs slightly from the ordinary method but only in the format of the <em><code style="font-family: 'Courier New', Courier, mono; font-size: 12px;">Signature</code></em> request parameter and the <em><code style="font-family: 'Courier New', Courier, mono; font-size: 12px;">StringToSign</code></em> element. Following is pseudo-grammar that illustrates the query string request authentication method.</p>
<pre class="programlisting" style="font-family: 'Courier New', Courier, mono; font-size: 12px; color: #000066; background-color: #eeeeee; margin-top: 5px; margin-bottom: 5px; overflow-x: auto; overflow-y: auto; width: 1083px; padding: 1em; border: 1px dashed #333333;">Signature = URL-Encode( Base64( HMAC-SHA1( YourSecretAccessKeyID, UTF-8-Encoding-Of( StringToSign ) ) ) );

StringToSign = HTTP-VERB + "\n" +
    Content-MD5 + "\n" +
    Content-Type + "\n" +
    Expires + "\n" +
    CanonicalizedAmzHeaders +
    CanonicalizedResource;</pre>
<p style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; margin-bottom: 1em;"><em><code style="font-family: 'Courier New', Courier, mono; font-size: 12px;">YourSecretAccessKeyID</code></em> is the AWS Secret Access Key ID Amazon assigns to you when you sign up to be an Amazon Web Service developer. Notice how the <em><code style="font-family: 'Courier New', Courier, mono; font-size: 12px;">Signature</code></em> is URL-Encoded to make it suitable for placement in the query-string. Also note that in <em><code style="font-family: 'Courier New', Courier, mono; font-size: 12px;">StringToSign</code></em>, the HTTP <code class="code" style="font-family: 'Courier New', Courier, mono; font-size: 12px;">Date</code> positional element has been replaced with <em><code style="font-family: 'Courier New', Courier, mono; font-size: 12px;">Expires</code></em>. The <em><code style="font-family: 'Courier New', Courier, mono; font-size: 12px;">CanonicalizedAmzHeaders</code></em> and<em><code style="font-family: 'Courier New', Courier, mono; font-size: 12px;">CanonicalizedResource</code></em> are the same.</p>
<div class="example" style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; padding: 0px; margin: 0px;"><a name="d0e4298"></a></p>
<p class="title" style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; margin-bottom: 1em;"><strong>Example Query String Request Authentication</strong></p>
</div>
</div>
<table style="-webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; border: 1px solid #cccccc;" border="0" cellspacing="0">
<colgroup>
<col></col>
<col></col>
</colgroup>
<thead>
<tr>
<th style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #333333; vertical-align: top; background-color: #eeeeee; font-weight: bold; text-align: left; padding: 5px; margin: 0px; border: 1px solid #cccccc;">Request</th>
<th style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #333333; vertical-align: top; background-color: #eeeeee; font-weight: bold; text-align: left; padding: 5px; margin: 0px; border: 1px solid #cccccc;">StringToSign</th>
</tr>
</thead>
<tbody>
<tr>
<td style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; vertical-align: top; padding: 5px; margin: 0px; border: 1px solid #cccccc;">
<pre class="programlisting" style="font-family: 'Courier New', Courier, mono; font-size: 12px; color: #000066; background-color: #eeeeee; margin-top: 5px; margin-bottom: 5px; overflow-x: auto; overflow-y: auto; width: 410px; padding: 1em; border: 1px dashed #333333;">GET /photos/puppy.jpg?AWSAccessKeyId=0PN5J17HBGZHT7JJ3X82&amp;
    Signature=rucSbH0yNEcP9oM2XNlouVI3BH4%3D&amp;
    Expires=1175139620 HTTP/1.1

Host: johnsmith.s3.amazonaws.com</pre>
</td>
<td style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; vertical-align: top; padding: 5px; margin: 0px; border: 1px solid #cccccc;">
<pre class="programlisting" style="font-family: 'Courier New', Courier, mono; font-size: 12px; color: #000066; background-color: #eeeeee; margin-top: 5px; margin-bottom: 5px; overflow-x: auto; overflow-y: auto; width: 204px; padding: 1em; border: 1px dashed #333333;">GET\n
\n
\n
1175139620\n

/johnsmith/photos/puppy.jpg</pre>
</td>
</tr>
</tbody>
</table>
<p><span style="font-family: verdana, arial, sans-serif; line-height: normal;"> </span></p>
<div class="section" style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; padding: 0px; margin: 0px;" lang="en">
<div class="example" style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; padding: 0px; margin: 0px;">
<div class="example-contents" style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; padding: 0px; margin: 0px;">
<p style="font-family: verdana, arial, sans-serif; font-size: 12px; color: #000000; margin-bottom: 1em;">We assume that when a browser makes the GET request, it won&#8217;t provide a Content-MD5 or a Content-Type header, nor will it set any x-amz- headers, so those parts of the <em><code style="font-family: 'Courier New', Courier, mono; font-size: 12px;">StringToSign</code></em></p>
</div>
</div>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 25px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">has_attached_file :attachment,</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 25px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">:storage =&gt; :s3,</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 25px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">:s3_credentials =&gt; &#8216;config/amazon_s3.yml&#8217;,</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 25px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">:s3_permissions =&gt; :private</div>
]]></content:encoded>
			<wfw:commentRss>http://www.andygoundry.com/2011/12/20/making-s3-file-uploads-private-yet-accessible-in-rails-with-paperclip/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using rvm in conjunction with bundler</title>
		<link>http://www.andygoundry.com/2011/11/16/using-rvm-in-conjunction-with-bundler/</link>
		<comments>http://www.andygoundry.com/2011/11/16/using-rvm-in-conjunction-with-bundler/#comments</comments>
		<pubDate>Wed, 16 Nov 2011 18:49:04 +0000</pubDate>
		<dc:creator>andy</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[bundler]]></category>
		<category><![CDATA[rvm]]></category>

		<guid isPermaLink="false">http://www.andygoundry.com/?p=515</guid>
		<description><![CDATA[I&#8217;m starting to use rvm with my rails projects and am wondering how to be use it in conjunction with bundler, as bundler already does a good job of managing the gems i need in my project.
To keep things simple for now, i&#8217;ve decided to keep bundler doing what it&#8217;s been doing (managing the project [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m starting to use rvm with my rails projects and am wondering how to be use it in conjunction with bundler, as bundler already does a good job of managing the gems i need in my project.</p>
<p>To keep things simple for now, i&#8217;ve decided to keep bundler doing what it&#8217;s been doing (managing the project gems), and use rvm to simply specify the versions of ruby and bundler to use within the project.</p>
<p>So, in my project folder, i have 2 files, 1 for rvm and 1 for bundler:</p>
<ul>
<li>.rvmrc<br />
This includes only the following:<br />
<em><span style="font-family: Helvetica; line-height: normal;"><span style="font-family: Helvetica;"><span style="line-height: normal;">rvm use 1.9.2@development &#8211;create</span></span></span><span style="font-family: Helvetica;"><span style="line-height: normal;"><br />
</span></span></em></li>
<li><span style="font-family: Helvetica;"><span style="line-height: normal;">Gemfile<br />
Includes all <em>gems need within the project</em></span></span></li>
</ul>
<p><span style="font-family: Helvetica;"><span style="line-height: normal;">The @development specifies that the app is using this rvm gemset, meaning that if i wish, i could have multiple gemsets and switch between them. As i&#8217;m currently handing off most of the gem management responsibility to bundler, this doesn&#8217;t makes sense at the moment, but could be useful later as i possibly migrate further responsibility over to rvm over time.</span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.andygoundry.com/2011/11/16/using-rvm-in-conjunction-with-bundler/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Making rvm gemsets work under OS X Lion with XCode 4.2</title>
		<link>http://www.andygoundry.com/2011/11/16/making-rvm-gemsets-work-under-os-x-lion-with-xcode-4-2/</link>
		<comments>http://www.andygoundry.com/2011/11/16/making-rvm-gemsets-work-under-os-x-lion-with-xcode-4-2/#comments</comments>
		<pubDate>Wed, 16 Nov 2011 18:39:05 +0000</pubDate>
		<dc:creator>andy</dc:creator>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[rvm]]></category>
		<category><![CDATA[xcode]]></category>

		<guid isPermaLink="false">http://www.andygoundry.com/?p=512</guid>
		<description><![CDATA[Running Xcode 4.2 on OS X will cause issues with RVM. Here are details of the issues and fix.The process takes no more than 5 minutes in total.
Issue
gem install bundler
/Users/me/.rvm/rubies/ruby-1.8.7-p352/lib/ruby/1.8/timeout.rb:60: [BUG] Bus Error
ruby 1.8.7 (2011-06-30 patchlevel 352) [i686-darwin11.1.0]
Abort trap: 6
Fix

Install Xcode 4.2
Install the gcc standalone compiler from https://github.com/kennethreitz/osx-gcc-installer (which replaces Xcode)
Add &#8220;export CC=gcc-4.2&#8243; to your [...]]]></description>
			<content:encoded><![CDATA[<p>Running Xcode 4.2 on OS X will cause issues with RVM. Here are details of the issues and fix.The process takes no more than 5 minutes in total.</p>
<p><strong>Issue</strong></p>
<p>gem install bundler<br />
/Users/me/.rvm/rubies/ruby-1.8.7-p352/lib/ruby/1.8/timeout.rb:60: [BUG] Bus Error<br />
ruby 1.8.7 (2011-06-30 patchlevel 352) [i686-darwin11.1.0]</p>
<p>Abort trap: 6</p>
<p><strong>Fix</strong></p>
<ol>
<li>Install Xcode 4.2</li>
<li>Install the gcc standalone compiler from https://github.com/kennethreitz/osx-gcc-installer (which replaces Xcode)</li>
<li>Add &#8220;export CC=gcc-4.2&#8243; to your ~/.bash_profile or equivalent (don&#8217;t forget to reload it)</li>
<li>Run &#8220;rvm implode&#8221; then re-install rvm http://beginrescueend.com/</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.andygoundry.com/2011/11/16/making-rvm-gemsets-work-under-os-x-lion-with-xcode-4-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Getting up and running with Git and Rails on EC2</title>
		<link>http://www.andygoundry.com/2011/11/06/getting-up-and-running-with-git-and-rails-on-ec2/</link>
		<comments>http://www.andygoundry.com/2011/11/06/getting-up-and-running-with-git-and-rails-on-ec2/#comments</comments>
		<pubDate>Sun, 06 Nov 2011 23:17:20 +0000</pubDate>
		<dc:creator>andy</dc:creator>
				<category><![CDATA[EC2]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[software development]]></category>

		<guid isPermaLink="false">http://www.andygoundry.com/?p=505</guid>
		<description><![CDATA[Here&#8217;s a short list of things to do to get Git and Rails running on EC2:
Install Git
 
sudo yum install -y git

sudo yum install -y git

Install Rails

sudo yum install -y rubygems ruby-devel gcc libxml2 libxml2-devel libxslt libxslt-devel mysql mysql-devel
sudo gem update &#8211;system
sudo gem install rails

]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a short list of things to do to get Git and Rails running on EC2:</p>
<p><strong>Install Git</strong></p>
<p><strong> </strong></p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">sudo yum install -y git</div>
<ul>
<li>sudo yum install -y git</li>
</ul>
<p><strong>Install Rails</strong></p>
<ul>
<li>sudo yum install -y rubygems ruby-devel gcc libxml2 libxml2-devel libxslt libxslt-devel mysql mysql-devel</li>
<li>sudo gem update &#8211;system</li>
<li>sudo gem install rails</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.andygoundry.com/2011/11/06/getting-up-and-running-with-git-and-rails-on-ec2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Merb Gem Cleanup</title>
		<link>http://www.andygoundry.com/2009/11/25/merb-gem-cleanup/</link>
		<comments>http://www.andygoundry.com/2009/11/25/merb-gem-cleanup/#comments</comments>
		<pubDate>Wed, 25 Nov 2009 18:33:31 +0000</pubDate>
		<dc:creator>andy</dc:creator>
				<category><![CDATA[DataMapper]]></category>
		<category><![CDATA[Merb]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.andygoundry.com/?p=461</guid>
		<description><![CDATA[It seems to be a common issue for us Merbists, who depend on multiple Gems for merb to play nicely to get into a bit of a mess as gems are updated.
So, at times a cleanup is in order. Here is what i&#8217;ve done to cleanup my merb setup:

$ sudo gem update --system
$ gem search [...]]]></description>
			<content:encoded><![CDATA[<p>It seems to be a common issue for us Merbists, who depend on multiple Gems for merb to play nicely to get into a bit of a mess as gems are updated.</p>
<p>So, at times a cleanup is in order. Here is what i&#8217;ve done to cleanup my merb setup:</p>
<blockquote>
<pre style="margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; font-size: 12px; color: #000000; overflow-x: auto; overflow-y: auto; background-color: #f3f3f3; padding: 1em;">$ <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">sudo</span> <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">gem</span> update --system
$ <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">gem</span> search --no-version merb | grep merb | xargs <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">sudo</span> <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">gem</span> un<span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">install</span> -a # NOTE: removes all old version of merb
$ <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">gem</span> search --no-version dm | grep dm | xargs <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">sudo</span> <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">gem</span> un<span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">install</span> -a # NOTE: removes all old version of data_mapper
$ <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">gem</span> search --no-version data_objects | grep data_objects | xargs <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">sudo</span> <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">gem</span> un<span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">install</span> -a # NOTE: removes all old version of data_objects
$ <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">sudo</span> <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">gem</span> sources -c
$ <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">sudo</span> rm PATH_TO_<span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">GEM</span>S/cache/merb* # PATH_TO_<span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">GEM</span>S is the path to your ruby<span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">gem</span>s <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">install</span>.  Mine is /usr/lib/ruby/<span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">gem</span>s/1.8
$ <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">sudo</span> rm PATH_TO_<span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">GEM</span>S/cache/dm*
$ <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">sudo</span> <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">gem</span> <span style="color: #000000; background-color: #ffff99; padding: 0px; margin: 0px;">install</span> -r merb</pre>
</blockquote>
<p>This was taken from the meb installation instructions at: <a href="http://wiki.merbivore.com/howto/installation/gems">http://wiki.merbivore.com/howto/installation/gems</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.andygoundry.com/2009/11/25/merb-gem-cleanup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Cucumber, Webrat and Selenium to test ajax form field validations</title>
		<link>http://www.andygoundry.com/2009/09/04/using-cucumber-webrat-and-selenium-to-test-ajax-form-field-validations/</link>
		<comments>http://www.andygoundry.com/2009/09/04/using-cucumber-webrat-and-selenium-to-test-ajax-form-field-validations/#comments</comments>
		<pubDate>Fri, 04 Sep 2009 18:11:09 +0000</pubDate>
		<dc:creator>andy</dc:creator>
				<category><![CDATA[Cucumber]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Merb]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Webrat]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.andygoundry.com/?p=439</guid>
		<description><![CDATA[I have an app that fires an ajax request on a form field to validate its contents when I take focus off the field.
I am also using Cucumber, Webrat and Selenium for my integration tests.
I needed my integration tests to test the Ajax responses and the tests weren&#8217;t receiving a response from the Ajax requests.
The [...]]]></description>
			<content:encoded><![CDATA[<p>I have an app that fires an ajax request on a form field to validate its contents when I take focus off the field.</p>
<p>I am also using Cucumber, Webrat and Selenium for my integration tests.</p>
<p>I needed my integration tests to test the Ajax responses and the tests weren&#8217;t receiving a response from the Ajax requests.</p>
<p><strong>The Problem</strong></p>
<p>I found that by simply completing the web form, the ajax request was not being fired and my test was therefore failing when i checked for the existance of the Ajax response. It soon became clear that selenium doesn&#8217;t really interact with the form in the sense of selecting fields and entering values; It simply enters values. As such, the Ajax request was not firing and my test was failing.</p>
<p><strong>The Solution</strong></p>
<p>The solution is Selenium&#8217;s fireEvent method, which you can pass a form field id and the blur method:</p>
<blockquote><p>selenium_session.fireEvent(&#8221;field&#8221;, &#8220;blur&#8221;);</p></blockquote>
<p>In Webrat, this is ever simpler:</p>
<blockquote><p>fire_event(&#8221;field&#8221;,&#8221;blur&#8221;)</p></blockquote>
<p>On using this in a Cucumber step, the ajax is fired as the blur command tells the browser to take focus off the field.</p>
<p>Lovely!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.andygoundry.com/2009/09/04/using-cucumber-webrat-and-selenium-to-test-ajax-form-field-validations/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

