<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
  <title>chrisblunt.com</title>
  
  <link href="http://chrisblunt.com/blog" />
  <updated>2010-03-06T14:55:45+00:00</updated>
  <id>http://chrisblunt.com/blog</id>
  <author>
    <name>Chris Blunt</name>
    <uri>http://chrisblunt.com/</uri>
    <email>chris@chrisblunt.com</email>
  </author>
  
  
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/chrisblunt" /><feedburner:info uri="chrisblunt" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/chrisblunt" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://www.plusmo.com/add?url=http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare href="http://www.thefreedictionary.com/_/hp/AddRSS.aspx?http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://img.tfd.com/hp/addToTheFreeDictionary.gif">Subscribe with The Free Dictionary</feedburner:feedFlare><feedburner:feedFlare href="http://www.bitty.com/manual/?contenttype=rssfeed&amp;contentvalue=http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://www.bitty.com/img/bittychicklet_91x17.gif">Subscribe with Bitty Browser</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsalloy.com/?rss=http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://www.newsalloy.com/subrss3.gif">Subscribe with NewsAlloy</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare href="http://mix.excite.eu/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><feedburner:feedFlare href="http://download.attensa.com/app/get_attensa.html?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://www.attensa.com/blogs/attensa/WindowsLiveWriter/BadgeredintoBadges_10C02/attensa_feed_button5.gif">Subscribe with Attensa for Outlook</feedburner:feedFlare><feedburner:feedFlare href="http://www.webwag.com/wwgthis.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://www.webwag.com/images/wwgthis.gif">Subscribe with Webwag</feedburner:feedFlare><feedburner:feedFlare href="http://www.podcastready.com/oneclick_bookmark.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://www.podcastready.com/images/podcastready_button.gif">Subscribe with Podcast Ready</feedburner:feedFlare><feedburner:feedFlare href="http://www.flurry.com/pushRssFeed.do?r=fb&amp;url=http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://www.flurry.com/images/flurry_rss_logo2.gif">Subscribe with Flurry</feedburner:feedFlare><feedburner:feedFlare href="http://www.wikio.com/subscribe?url=http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://www.wikio.com/shared/img/add2wikio.gif">Subscribe with Wikio</feedburner:feedFlare><feedburner:feedFlare href="http://www.dailyrotation.com/index.php?feed=http%3A%2F%2Ffeeds.feedburner.com%2Fchrisblunt" src="http://www.dailyrotation.com/rss-dr2.gif">Subscribe with Daily Rotation</feedburner:feedFlare><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site.</feedburner:browserFriendly><entry>
    <author><name>Chris</name></author>
    <title>Run Rails 3 Apps on Passenger</title>
    <id>http://chrisblunt.com/blog/2010/03/05/run-rails-3-apps-on-passenger</id>
    <link href="http://feedproxy.google.com/~r/chrisblunt/~3/0J-12ZrVfr4/" />
    <published>2010-03-05T00:00:00+00:00</published>
    <updated>2010-03-05T00:00:00+00:00</updated>
    <content type="html">

&lt;p class="notice"&gt;
  &lt;strong&gt;Update&lt;/strong&gt;: Make sure you update Rubygems using &lt;em&gt;sudo gem update --system&lt;/em&gt;.
&lt;/p&gt;


&lt;p&gt;Whilst I've been &lt;a href="http://chrisblunt.com/2010/03/03/building-apps-with-rails-3-rspec-factorygirl-and-mocha/"&gt;learning more about Rails 3&lt;/a&gt;, I've been using the built in &lt;span class="code"&gt;rails server&lt;/span&gt; to run my code. Today I tried to run my Rails 3 app through &lt;a href="http://modrails.com"&gt;Passenger&lt;/a&gt; on Apache, and immediately hit an error page:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;uninitialized constant Rack::Runtime
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;It &lt;a href="http://cakebaker.42dh.com/2010/01/17/rails-3-and-passenger/"&gt;turns out&lt;/a&gt; that Passenger notices Rails' new &lt;em&gt;config.ru&lt;/em&gt; file, causing it to run as a &lt;em&gt;Rack&lt;/em&gt; application. This requires a slight change in the app's &lt;em&gt;VirtualHost&lt;/em&gt; entry. The &lt;span class="code"&gt;RailsEnv&lt;/span&gt; setting now becomes &lt;span class="code"&gt;RackEnv&lt;/span&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# /etc/apache2/apache2.conf&lt;/span&gt;
&lt;span class="c"&gt;# RailsEnv development&lt;/span&gt;
&lt;span class="nb"&gt;RackEnv&lt;/span&gt; development
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;But that wasn't all. My development machine was still running Passenger 2.2.7, which wouldn't support Rails 3. To ensure a clean slate, I removed the old versions of Passenger and installed the latest build (2.2.11 at the time of writing). Once installed, I ran the standard Passenger installation script and updated &lt;em&gt;apache2.conf&lt;/em&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;sudo gem update --system
&lt;span class="nv"&gt;$ &lt;/span&gt;sudo gem uninstall passenger
  &lt;span class="c"&gt;# Remove all versions of Passenger&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;sudo gem install passenger
&lt;span class="nv"&gt;$ &lt;/span&gt;sudo passenger-install-apache2-module
&lt;/pre&gt;
&lt;/div&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# /etc/apache2/apache2.conf&lt;/span&gt;
&lt;span class="c"&gt;# Passenger mod_rails &lt;/span&gt;
&lt;span class="c"&gt;# NOTE: Your paths may be different. Use the config generated by Passenger&amp;#39;s install script)&lt;/span&gt;
&lt;span class="nb"&gt;LoadModule&lt;/span&gt; passenger_module &lt;span class="sx"&gt;/usr/lib/ruby/gems/1.8/gems/passenger-2.2.11/ext/apache2/mod_passenger.so&lt;/span&gt;
&lt;span class="nb"&gt;PassengerRoot&lt;/span&gt; &lt;span class="sx"&gt;/usr/lib/ruby/gems/1.8/gems/passenger-2.2.11&lt;/span&gt;
&lt;span class="nb"&gt;PassengerRuby&lt;/span&gt; &lt;span class="sx"&gt;/usr/bin/ruby1.8&lt;/span&gt;

&lt;span class="nb"&gt;RailsEnv&lt;/span&gt; development
&lt;span class="nb"&gt;RackEnv&lt;/span&gt; development
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;After a quick restart of Apache, Passenger kicked in and my new Rails 3 app was up and running!&lt;/p&gt;

&lt;h3&gt;References&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://cakebaker.42dh.com/2010/01/17/rails-3-and-passenger/"&gt;Rails 3 and Passenger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rails.lighthouseapp.com/projects/8994/tickets/3917-uninitialized-constant-rackruntime-error"&gt;Rails Lighthouse Ticket&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=0J-12ZrVfr4:Gg4Qyv6EJEw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=0J-12ZrVfr4:Gg4Qyv6EJEw:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=0J-12ZrVfr4:Gg4Qyv6EJEw:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=0J-12ZrVfr4:Gg4Qyv6EJEw:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://chrisblunt.com/blog/2010/03/05/run-rails-3-apps-on-passenger/</feedburner:origLink></entry>
  
  <entry>
    <author><name>Chris</name></author>
    <title>Building apps with Rails 3, RSpec, FactoryGirl and Mocha.</title>
    <id>http://chrisblunt.com/blog/2010/03/03/building-apps-with-rails-3-rspec-factorygirl-and-mocha</id>
    <link href="http://feedproxy.google.com/~r/chrisblunt/~3/21NjSp9zHl0/" />
    <published>2010-03-03T00:00:00+00:00</published>
    <updated>2010-03-03T00:00:00+00:00</updated>
    <content type="html">

&lt;p class="sourcecode_notice"&gt;
&lt;a href="http://github.com/cblunt/rails3_project_template"&gt;Clone the source code&lt;/a&gt; from &lt;a href="http://github.com/cblunt"&gt;github&lt;/a&gt;.
&lt;/p&gt;


&lt;p&gt;It's no secret that &lt;a href="http://weblog.rubyonrails.org/2010/2/5/rails-3-0-beta-release"&gt;Rails 3 has been released in beta&lt;/a&gt; for a little while now. Like most Rails developers, I was keen to try out some of the new functionality, not least the redesigned &lt;a href="http://m.onkey.org/2010/1/22/active-record-query-interface"&gt;Active Record API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Some heavy duty googling turned up little information on how to get an app started and configured with all the associated goodies we've come to expect: &lt;a href="http://github.com/rspec/rspec"&gt;rspec&lt;/a&gt;, &lt;a href="http://mocha.rubyforge.org/"&gt;mocha&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/factory_girl/tree/rails3"&gt;factory_girl&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is probably because most of these plugins are in a state of development to bring full compatability with Rails 3. So until that happens, I thought I'd document how I've got a skeleton app up and running on Ubuntu using the current development branches.&lt;/p&gt;

&lt;p&gt;You can find the latest versions of the code behind on my &lt;a href="http://github.com/cblunt/rails3_project_template"&gt;github&lt;/a&gt;. I'll continue to revise this template as I figure out more about Rails 3, and the plugins.&lt;/p&gt;

&lt;h3&gt;Installing Rails 3&lt;/h3&gt;

&lt;p&gt;There's plenty of posts detailing how to get Rails 3 on your machine. Favouring gems, I followed the &lt;a href="http://weblog.rubyonrails.org/2010/2/5/rails-3-0-beta-release/"&gt;official advice&lt;/a&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gem install tzinfo builder memcache-client rack rack-test rack-mount 
&lt;span class="nv"&gt;$ &lt;/span&gt;gem install erubis mail text-format thor bundler i18n
&lt;span class="nv"&gt;$ &lt;/span&gt;gem install rails --pre
&lt;span class="nv"&gt;$ &lt;/span&gt;rails -v
Rails 3.0.0.beta 
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;With everything set, we can spin a new app using:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rails myapp
&lt;span class="c"&gt;# Lots of output&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;myapp
&lt;/pre&gt;
&lt;/div&gt;


&lt;h3&gt;Bundling Gems&lt;/h3&gt;

&lt;p&gt;Rails 3 uses the &lt;a href="http://github.com/carlhuda/bundler"&gt;Bundler&lt;/a&gt; gem to configure its environment. Bundler brings a lot of benefits, including dependency resolution and ensures that an app's gem requirements are met.&lt;/p&gt;

&lt;p&gt;Your app's required gems are declared in a &lt;em&gt;Gemfile&lt;/em&gt; in your project root. A default Gemfile is provided to load Rails 3 and SQLite. For our project, we'll update it to require some additional gems:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# Gemfile&lt;/span&gt;
&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;http://gemcutter.org&amp;#39;&lt;/span&gt;

&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rails&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;3.0.0.beta&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;sqlite3-ruby&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:require&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;sqlite3&amp;quot;&lt;/span&gt;

&lt;span class="c1"&gt;# Require the haml gem for rendering HAML templates and SASS stylesheets&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;haml&amp;quot;&lt;/span&gt;

&lt;span class="c1"&gt;# FactoryGirl and Shoulda Rails 3 development branches from github&lt;/span&gt;
&lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="ss"&gt;:thoughtbot&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# I&amp;#39;ve included shoulda here in case you use TestUnit. Shoulda macros for RSpec 2 don&amp;#39;t &lt;/span&gt;
  &lt;span class="c1"&gt;# work yet though.&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;shoulda&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:git&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;git://github.com/sinefunc/shoulda.git&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="ss"&gt;:branch&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rails3&amp;quot;&lt;/span&gt;

  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;factory_girl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:git&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;git://github.com/thoughtbot/factory_girl.git&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="ss"&gt;:branch&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rails3&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="ss"&gt;:require&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;factory_girl&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="ss"&gt;:test&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# Install development release of rspec (includes rspec-rails)&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rspec-rails&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;gt;= 2.0.0.a9&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;webrat&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;mocha&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now you can install the bundled gems with:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;bundle install
&lt;/pre&gt;
&lt;/div&gt;


&lt;h3&gt;Configuring RSpec and FactoryGirl&lt;/h3&gt;

&lt;p&gt;One of the first tools I felt lost without in Rails 3 was RSpec. Although I tried going back &lt;em&gt;TestUnit&lt;/em&gt;, I missed the clarity of RSpec. With RSpec 2 installed by Bundler, the app can be prepared for specs with:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rails generate rspec:install 
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This creates the appropriate &lt;em&gt;spec&lt;/em&gt; folder and configuration files. I configured RSpec to use FactoryGirl and Mocha. Notice that in the &lt;em&gt;Gemfile&lt;/em&gt; above, Shoulda and FactoryGirl are declared in a group &lt;span class="code"&gt;:thoughtbot&lt;/span&gt;. Bundler loads the default gems before Rails has initialised environment constants such as &lt;span class="code"&gt;Rails.root&lt;/span&gt;. By declaring these gems within a group, they can be defered until Rails has setup the environment (&lt;a href="http://www.pipetodevnull.com/past/2010/2/22/our_first_app_in_rails_3/"&gt;Reference&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;For RSpec to use FactoryGirl, we ask Bundler to load the &lt;em&gt;:thoughtbot&lt;/em&gt; gems in &lt;em&gt;spec_helper.rb&lt;/em&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# specs/spec_helper.rb&lt;/span&gt;
&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;RAILS_ENV&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;test&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/../config/environment&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;defined?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;RAILS_ROOT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rspec/rails&amp;#39;&lt;/span&gt;

&lt;span class="c1"&gt;# Load in RSpec and Shoulda&lt;/span&gt;
&lt;span class="c1"&gt;# Shoulda macros don&amp;#39;t seem to work with RSpec 2. When they do, this is where to require them.&lt;/span&gt;
&lt;span class="c1"&gt;# require &amp;#39;shoulda&amp;#39;&lt;/span&gt;
&lt;span class="c1"&gt;# require &amp;#39;shoulda/rspec&amp;#39;&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;factory_girl&amp;#39;&lt;/span&gt;

&lt;span class="c1"&gt;# Autoloading of Factories seems to be broken, so manually require the &amp;lt;tt&amp;gt;factories.rb&amp;lt;/tt&amp;gt; file&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/../spec/factories.rb&amp;quot;&lt;/span&gt;

&lt;span class="c1"&gt;# Requires supporting files with custom matchers and macros, etc,&lt;/span&gt;
&lt;span class="c1"&gt;# in ./support/ and its subdirectories.&lt;/span&gt;
&lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/support/**/*.rb&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;For now I've left &lt;em&gt;shoulda&lt;/em&gt; out of the configuration as the Shoulda macros don't yet work with RSpec 2. I also manually required &lt;em&gt;spec/factories.rb&lt;/em&gt; as FactoryGirl's autoloader also seemed not to be working yet. Before running a spec, you'll need to declare your factories in &lt;em&gt;spec/factories.rb&lt;/em&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;touch spec/factories.rb
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Finally, switch RSpec to use &lt;em&gt;mocha&lt;/em&gt; for mocking objects:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# spec/spec_helper.rb&lt;/span&gt;
&lt;span class="c1"&gt;# == Mock Framework&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mock_with&lt;/span&gt; &lt;span class="ss"&gt;:mocha&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;h3&gt;Writing specs&lt;/h3&gt;

&lt;p&gt;With everything setup, it's time to write the first spec. As a simple example, I'll create a &lt;span class="code"&gt;User&lt;/span&gt; model and its associated spec. With RSpec installed, the standard rails model generator will automatically create an associated spec file:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rails generate model user email_address:string password_hash:string password_salt:string
&lt;span class="nv"&gt;$ &lt;/span&gt;rake db:migrate
&lt;span class="o"&gt;==&lt;/span&gt;  CreateUsers: &lt;span class="nv"&gt;migrating&lt;/span&gt; &lt;span class="o"&gt;====================================================&lt;/span&gt;
-- create_table&lt;span class="o"&gt;(&lt;/span&gt;:users&lt;span class="o"&gt;)&lt;/span&gt;
   -&amp;gt; 0.0041s
&lt;span class="o"&gt;==&lt;/span&gt;  CreateUsers: migrated &lt;span class="o"&gt;(&lt;/span&gt;0.0043s&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===========================================&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The spec for the &lt;span class="code"&gt;User&lt;/span&gt; model can now be written using the familiar RSpec dialect:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# spec/models/user_spec.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;spec_helper&amp;#39;&lt;/span&gt;

&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;should be valid&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Factory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;be_valid&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I've also used &lt;span class="code"&gt;Factory.create&lt;/span&gt; to build a user, so as before, you'll need to declare your user factory in &lt;em&gt;spec/factories.rb&lt;/em&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# spec/factories.rb&lt;/span&gt;
&lt;span class="no"&gt;Factory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;define&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email_address&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;joe.user@example.com&amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;secret&amp;#39;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Finally, to run your specs, you use &lt;em&gt;rake&lt;/em&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rake spec
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;All being well, RSpec should now load up and run your specs. In this example, the spec fails trying to set &lt;span class="code"&gt;User#password&lt;/span&gt;. To fix this, we'll add a virtual attribute, &lt;span class="code"&gt;password&lt;/span&gt;, to the &lt;span class="code"&gt;User&lt;/span&gt; model that sets a salted, hashed password:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# app/models/user.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;digest/sha2&amp;#39;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="n"&gt;pass&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@password&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blank?&lt;/span&gt; 

    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password_salt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Digest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SHA2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password_hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Digest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SHA2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@password&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password_salt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="kp"&gt;protected&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;password&lt;/span&gt;
    &lt;span class="vi"&gt;@password&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;With that, another call to &lt;em&gt;rake&lt;/em&gt; should report your passing spec:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rake spec
.
Finished in 0.062692 seconds
1 example, 0 failures
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;With this, you can now start to build your Rails 3 app, complete with specs and factories. I'll continue to update the &lt;a href="http://github.com/cblunt/rails3_project_template"&gt;code on github&lt;/a&gt; as I figure out more, and as more plugins become compatible with Rails 3.&lt;/p&gt;

&lt;h3&gt;References&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.railsplugins.org"&gt;railsplugins.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.pipetodevnull.com/past/2010/2/22/our_first_app_in_rails_3/"&gt;pipetodevnull.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/rspec/rspec"&gt;rspec&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/thoughtbot/factory_girl/tree/rails3"&gt;thoughtbot's factory_girl for rails3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/thoughtbot/shoulda/tree/rails3"&gt;thoughtbot's shoulda for rails3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=21NjSp9zHl0:GD_vNTnaqO0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=21NjSp9zHl0:GD_vNTnaqO0:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=21NjSp9zHl0:GD_vNTnaqO0:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=21NjSp9zHl0:GD_vNTnaqO0:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://chrisblunt.com/blog/2010/03/03/building-apps-with-rails-3-rspec-factorygirl-and-mocha/</feedburner:origLink></entry>
  
  <entry>
    <author><name>Chris</name></author>
    <title>Changed Permalinks and More Blog Tweaks</title>
    <id>http://chrisblunt.com/blog/2010/02/16/changed-permalinks-and-more-blog-tweaks</id>
    <link href="http://feedproxy.google.com/~r/chrisblunt/~3/pweKpjXmcfU/" />
    <published>2010-02-16T00:00:00+00:00</published>
    <updated>2010-02-16T00:00:00+00:00</updated>
    <content type="html">&lt;p&gt;I'm really liking Jekyll as a blog engine, and have been tweaking a few things on the site. One big change is permalinks. To follow Jekyll's preferred convention, I've switched my post's permalinks from &lt;span class="filename"&gt;/blog/YYYY/MM/DD&lt;/span&gt; to just &lt;span class="filename"&gt;/YYYY/MM/DD&lt;/span&gt;. Thanks to Apache's mod_rewrite, old links will still work, but I find mod_rewrite rules a bit of a dark art. So, for convenience and future reference, here are the rules I've used:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# .htaccess&lt;/span&gt;
&lt;span class="nb"&gt;RewriteBase&lt;/span&gt; /
&lt;span class="c"&gt;# Don&amp;#39;t redirect if URL is a real file&lt;/span&gt;
&lt;span class="nb"&gt;RewriteCond&lt;/span&gt; %{REQUEST_URI} !-f
&lt;span class="c"&gt;# Redirect requests for /blog/some/page.html to /some/page.html&lt;/span&gt;
&lt;span class="nb"&gt;RewriteCond&lt;/span&gt; %{REQUEST_URI}% ^/blog(.*)
&lt;span class="nb"&gt;RewriteRule&lt;/span&gt; blog/(.*) http://chrisblunt.com/$1 [R=301,NC,L]

&lt;span class="c"&gt;# Redirect requests for /feed to Feedburner&lt;/span&gt;
&lt;span class="nb"&gt;RewriteCond&lt;/span&gt; %{REQUEST_URI}% ^/feed/?(.*)
&lt;span class="nb"&gt;RewriteRule&lt;/span&gt; ^(.*) http://feeds.feedburner.com/chrisblunt [R=301,NC,L]
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;For now, the changed permalink structure means that &lt;a href="(http://disqus.com/"&gt;Disqus&lt;/a&gt; comments are not available. I've contacted &lt;a href="http://disqus.com/overview/"&gt;Disqus&lt;/a&gt; about this though, and hope to move those comments to the new format soon.&lt;/p&gt;

&lt;p&gt;In the meantime, everything else seems to be running smoothly on Jekyll. I've tweaked my site's design back to a fairly minimal theme - &lt;a href="http://tom.preston-werner.com/"&gt;influenced&lt;/a&gt; by &lt;a href="http://alexyoung.org/"&gt;other&lt;/a&gt; Jekyll &lt;a href="http://wiki.github.com/mojombo/jekyll/sites"&gt;sites&lt;/a&gt; that I've seen.&lt;/p&gt;

&lt;p&gt;I've kept deployments simple too; rather than using git hooks, I use a Rakefile and rsync combination based on &lt;a href="http://tatey.com/2009/10/29/simpler-deployment-for-jekyll-using-a-rakefile-and-rsync/"&gt;this post&lt;/a&gt;. The Rakefile lets me use &lt;a href="http://github.com/cblunt/jekyll"&gt;a fork of Jekyll&lt;/a&gt; to compile and upload the site with a simple call to &lt;span class="code"&gt;rake deploy&lt;/span&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# /Rakefile&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;jekyll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;../jekyll/bin/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rm -rf _site&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;jekyll &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
  
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
  &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;:domain&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;servername&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="ss"&gt;:deploy_to&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;filesystem path&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;:port&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ssh_port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;:user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ssh_username&amp;#39;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rsync -rtz -e &amp;#39;ssh -p &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:port&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39; _site/ &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;@&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:domain&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:deploy_to&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Perform a jekyll rebuild of the site&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:build&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;jekyll&lt;/span&gt; 
  &lt;span class="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;sitemap:build&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;invoke&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Serve on Localhost with port 4000&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:local&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;jekyll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;--server --auto --limit-posts 5&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Rebuild and Deploy to Live&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:deploy&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:build&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;rsync&lt;/span&gt;
  &lt;span class="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;sitemap:ping&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;invoke&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Deploy the currently cached build to Live&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:cached&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;rsync&lt;/span&gt;
  &lt;span class="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;sitemap:ping&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;invoke&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:sitemap&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Rebuild the sitemap.xml using gen_sitemap.rb&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:build&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;generate_sitemap_bin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/_tools/gen_sitemap.rb&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;cd _site &amp;amp;&amp;amp; ruby &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;generate_sitemap_bin&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &amp;#39;.&amp;#39; &amp;gt; sitemap.xml&amp;quot;&lt;/span&gt;
    &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Notify Google of the new sitemap&amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:ping&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;net/http&amp;#39;&lt;/span&gt;
    &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;uri&amp;#39;&lt;/span&gt;
    &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;&amp;#39;www.google.com&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;&amp;#39;/webmasters/tools/ping?sitemap=&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;escape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://chrisblunt.com/sitemap.xml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Overall everything feels a lot lighter and easier to manage, and vim now sits at the heart of my blog workflow. This is great as I find it hard work to use any other text editor since learning vim. Static HTML means the site is served quickly as well, and I feel safe in the knowledge that my data is stored in a &lt;span class="filename"&gt;git&lt;/span&gt; repository rather than a single database.&lt;/p&gt;

&lt;p&gt;One caveat is that the site can't include external dynamic content; at least not without some Javascript. I figure, though, that there are plenty of ways to follow &lt;a href="http://twitter.com/cblunt"&gt;my Twitter ramblings&lt;/a&gt; or &lt;a href="http://flickr.com/photos/cbl2001"&gt;photostreams&lt;/a&gt; and so on without adding distraction to the site.&lt;/p&gt;

&lt;p&gt;So hopefully the transition is complete. Once the Disqus comments are linked, I'll be able to get back to writing some content to fill the blog! There's plenty to write about, with the recent release of &lt;a href="http://weblog.rubyonrails.org/2010/2/5/rails-3-0-beta-release/"&gt;Rails 3 beta&lt;/a&gt;, and my upcoming travels. I'll also document more about &lt;a href="http://bit.ly/5C5iL9" title="Amberleaf"&gt;Amberleaf&lt;/a&gt;'s development, post more Rails tips as I learn, and discuss a new mobile app for Android I'm starting.&lt;/p&gt;

&lt;p&gt;Are you using &lt;a href="http://github.com/mojombo/jekyll"&gt;Jekyll&lt;/a&gt; or something similar to power your site? How have you found the transition if you've switched from bigger engines like Wordpress or Mephisto?&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=pweKpjXmcfU:WzjKAlLs8HU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=pweKpjXmcfU:WzjKAlLs8HU:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=pweKpjXmcfU:WzjKAlLs8HU:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=pweKpjXmcfU:WzjKAlLs8HU:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://chrisblunt.com/blog/2010/02/16/changed-permalinks-and-more-blog-tweaks/</feedburner:origLink></entry>
  
  <entry>
    <author><name>Chris</name></author>
    <title>Switching to Jekyll</title>
    <id>http://chrisblunt.com/blog/2010/02/07/switching-to-jekyll</id>
    <link href="http://feedproxy.google.com/~r/chrisblunt/~3/kS3qt_BIWAU/" />
    <published>2010-02-07T00:00:00+00:00</published>
    <updated>2010-02-07T00:00:00+00:00</updated>
    <content type="html">&lt;p&gt;For several years now, I've used Wordpress to power this site. As I've learned to use new tools for coding (&lt;a href="http://vim.org"&gt;vim&lt;/a&gt;, &lt;a href="http://git-scm.com"&gt;git&lt;/a&gt; and so on), Wordpress has started to seem a little too heavy, especially for just writing posts. A &amp;lt;textarea&amp;gt; editor just can't cut it when you've been using vim for a couple of years.&lt;/p&gt;

&lt;p&gt;So I started looking for alternative blogging engines. After trying out a few Rails-powered engines, I eventually stumbled across &lt;a href="http://github.com/mojombo/jekyll"&gt;Jekyll&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Jekyll is described as a "blog-aware static site generator", and I set about giving it a try. After a few minutes, I knew that Jekyll was what I'd been looking for. It lets me edit my site in a text editor of my choosing, generates static HTML files (no more heavy server-side tech), and sits perfectly in a Rails-esque &lt;span class="code"&gt;git push; rake deploy&lt;/span&gt; workflow.&lt;/p&gt;

&lt;p&gt;So after a few days migrating from Wordpress, this site is now 100% Jekyll powered: there is no back-end PHP; no database connection to worry about; and everything is versioned and backed-up through git. I've used a &lt;a href="http://github.com/henrik/jekyll"&gt;fork of Jekyll&lt;/a&gt; that lets me write templates in &lt;a href="http://haml-lang.com"&gt;Haml&lt;/a&gt; rather than stock HTML.&lt;/p&gt;

&lt;p&gt;There have been a few bumps along the way, but thanks to the growing Jekyll community and &lt;a href="http://wiki.github.com/mojombo/jekyll/"&gt;wiki&lt;/a&gt;, there are plenty of helpful guides and tricks available to solve any problems I've had. Here's a quick overview of how I've switched to Jekyll.&lt;/p&gt;

&lt;h3&gt;Pure Text&lt;/h3&gt;

&lt;p&gt;Jekyll uses plain text for everything. Plain text is great - it's small and portable; can be edited using your editor of choice, and is easily versionable using tools like &lt;a href="http://git-scm.com"&gt;git&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Deploying&lt;/h3&gt;

&lt;p&gt;With a suitable &lt;a href="http://github.com/tatey/tatey.com/blob/master/Rakefile"&gt;Rakefile&lt;/a&gt;, managing my site is as simple as writing a post and running &lt;span class="code"&gt;rake deploy&lt;/span&gt;. Rather that git post-commit hooks, I've used rsync (as described in &lt;a href="http://tatey.com/2009/10/29/simpler-deployment-for-jekyll-using-a-rakefile-and-rsync/"&gt;this post&lt;/a&gt;) to push files into my server's blog directory.&lt;/p&gt;

&lt;h3&gt;Comments&lt;/h3&gt;

&lt;p&gt;Having no server-side scripting means that Jekyll sites have no way to submit and process comments. The Jekyll sites I've seen either don't use comments, or implement them through a hosted service such as &lt;a href="http://www.disqus.com"&gt;Disqus&lt;/a&gt; or &lt;a href="http://intensedebate.com"&gt;IntenseDebate&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I like the conversation that comments bring, so I went with Disqus to manage this site's comments. The process was fairly simple, and just involved adding a couple of &amp;lt;script&amp;gt; tags to my &lt;span class="code"&gt;_layouts/post.haml&lt;/span&gt; file.&lt;/p&gt;

&lt;p&gt;As an added bonus, using a hosted service lets you keep track of your conversations across the web, and listen for replies across a number of sites more easily.&lt;/p&gt;

&lt;h3&gt;Migrating Posts&lt;/h3&gt;

&lt;p&gt;Jekyll comes with a set of converters for getting your posts out of other blog engines. You can find them in the &lt;span class="filename"&gt;lib/jekyll/converters/&lt;/span&gt; folder of the Jekyll repository.&lt;/p&gt;

&lt;p&gt;I had 6 years worth of posts stored in Wordpress, and used the built-in converter to extract them. This was fine, but I found the default converter didn't migrate tags and categories.&lt;/p&gt;

&lt;p&gt;After taking a quick look at the Wordpress database structure, I &lt;a href="http://github.com/cblunt/jekyll"&gt;forked Jekyll&lt;/a&gt; and added a snippet of code to pull out each posts' tags and categories. The tags and categories are inserted into each post's YAML front matter.&lt;/p&gt;

&lt;p&gt;You can find my fork of Jekyll on &lt;a href="http://github.com/cblunt/jekyll"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Code highlighting&lt;/h3&gt;

&lt;p&gt;Jekyll uses &lt;a href="http://pygments.org/"&gt;pygments&lt;/a&gt; to as its source highlighting engine. As a lot of my posts include code snippets, I've come to rely heavily on the wp-syntax plugin. Jekyll uses a different markup delimiter though, so I've not yet managed to migrate highlighted source code. I'm hoping to find some way to patch this, probably using regex. I'll update my fork of Jekyll with any changes.&lt;/p&gt;

&lt;p&gt;An alternative approach that I'm thinking of is to use &lt;a href="http://gist.github.com"&gt;github gists&lt;/a&gt;. This would allow code to be embedded into each post, and would keep all my code in one place.&lt;/p&gt;

&lt;h3&gt;Google Sitemaps and Pings&lt;/h3&gt;

&lt;p&gt;My Wordpress site used a plugin to generate a &lt;span class="filename"&gt;sitemap.xml&lt;/span&gt; file every time a post was published. Again, the Jekyll community had already developed a script to replicate this functionality, and my &lt;span class="filename"&gt;sitemap.xml&lt;/span&gt; is now built and submitted to Google every time with every update.&lt;/p&gt;

&lt;h3&gt;RSS/Atom Feeds&lt;/h3&gt;

&lt;p&gt;My site's feed is handled through &lt;a href="http://feeds.feedburner.com/chrisblunt"&gt;Feedburner&lt;/a&gt;. For the few users that were directly subscribed to my site's raw XML feed (&lt;span class="filename"&gt;http://chrisblunt.com/blog/feed&lt;/span&gt;), I've used Apache mod_rewrite to redirect requests to &lt;a href="http://feeds.feedburner.com/chrisblunt"&gt;Feedburner&lt;/a&gt;. This should be transparent to those subscribers, but please let me know if you find otherwise.&lt;/p&gt;

&lt;p&gt;So that's my site switched over to Jekyll, and I'm glad to say that everything seems to have gone smoothly. Thanks to the magic of &lt;span class="code"&gt;mod_rewrite&lt;/span&gt; all previous links should still work.&lt;/p&gt;

&lt;p&gt;The only problem so far is that code snippets haven't migrated properly, so you'll find that they aren't syntax highlighted. I'll work on switching those manually once I decide whether to go with gist or pygments.&lt;/p&gt;

&lt;p&gt;There are likely to be a few more tweaks to the site's layout and theme. I'll also be posting more as I get to grips with Rails 3 and Android, and Claire and I start on our travels in March...&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=kS3qt_BIWAU:hlwb2k7QSqQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=kS3qt_BIWAU:hlwb2k7QSqQ:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=kS3qt_BIWAU:hlwb2k7QSqQ:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=kS3qt_BIWAU:hlwb2k7QSqQ:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://chrisblunt.com/blog/2010/02/07/switching-to-jekyll/</feedburner:origLink></entry>
  
  <entry>
    <author><name>Chris</name></author>
    <title>Amberleaf: Manage Your Domains &amp; Hosting - Public Beta Now Open.</title>
    <id>http://chrisblunt.com/blog/2010/01/04/amberleaf-manage-your-domains-hosting-public-beta-now-open</id>
    <link href="http://feedproxy.google.com/~r/chrisblunt/~3/37xSI5VT154/" />
    <published>2010-01-04T00:00:00+00:00</published>
    <updated>2010-01-04T00:00:00+00:00</updated>
    <content type="html">&lt;p&gt;&lt;a href="http://bit.ly/5C5iL9" title="Amberleaf"&gt;&lt;img src="/images/2010/01/Screenshot-1.png" title="Amberleaf Front Page" alt="Amberleaf Front Page" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After several months of evening development and jumping into Rails at the deep-end, I'm happy to jump into 2010 by opening public beta accounts for &lt;a href="http://bit.ly/5C5iL9" title="Amberleaf"&gt;Amberleaf&lt;/a&gt; - and every account is &lt;strong&gt;free for the duration of the beta&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Amberleaf is built to remind you of upcoming renewals for domains and SSL certificate expiries, and hosting account renewals, and simply to remind you when to bill your customers. It is the evolution of HostManager, an OS X app I wrote back in my university days.&lt;/p&gt;

&lt;h3&gt;Who uses Amberleaf?&lt;/h3&gt;

&lt;p&gt;Anybody who has a domain! Whether you own or manage a single domain, or several hundred hosting accounts on behalf of your clients, Amberleaf is designed to make your life easier, by providing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatic WHOIS lookup for domains, with more TLDs being added.&lt;/li&gt;
&lt;li&gt;Email notification of upcoming expiries and renewals.&lt;/li&gt;
&lt;li&gt;Private RSS feed of your upcoming notifications.&lt;/li&gt;
&lt;li&gt;Simple client management, with the ability to import your existing clients' vCards.&lt;/li&gt;
&lt;li&gt;Keep a history of notes for your domains and clients, such as when special discounts are due to end.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;What do you think?&lt;/h3&gt;

&lt;p&gt;Amberleaf is completely free for the duration of the beta, and signup only takes a couple of minutes; I'd love to hear your feedback and comments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="http://bit.ly/6rfiOQ" title="Sign up for Amberleaf"&gt;Sign up for Amberleaf now&lt;/a&gt;&lt;/strong&gt; or &lt;a href="http://bit.ly/5C5iL9" title="Amberleaf"&gt;find out more&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you've already signed up, you can email comments to &lt;strong&gt;chris&lt;/strong&gt; at &lt;strong&gt;chrisblunt&lt;/strong&gt; dot &lt;strong&gt;com&lt;/strong&gt;; ping me on &lt;a href="http://twitter.com/cblunt" title="Twitter @cblunt"&gt;twitter&lt;/a&gt; (@cblunt), or send feedback directly from Amberleaf using the feedback tab at the bottom of every page.&lt;/p&gt;

&lt;p&gt;If you'd like to see what's coming in future releases, and get involved in Amberleaf's development, check out the public tracker at &lt;a href="http://trac.chrisblunt.com"&gt;trac.chrisblunt.com&lt;/a&gt;.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=37xSI5VT154:Zyt2Mxbnwnw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=37xSI5VT154:Zyt2Mxbnwnw:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=37xSI5VT154:Zyt2Mxbnwnw:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=37xSI5VT154:Zyt2Mxbnwnw:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://chrisblunt.com/blog/2010/01/04/amberleaf-manage-your-domains-hosting-public-beta-now-open/</feedburner:origLink></entry>
  
  <entry>
    <author><name>Chris</name></author>
    <title>Just Married</title>
    <id>http://chrisblunt.com/blog/2010/01/03/just-married</id>
    <link href="http://feedproxy.google.com/~r/chrisblunt/~3/-PJx62k7NEc/" />
    <published>2010-01-03T00:00:00+00:00</published>
    <updated>2010-01-03T00:00:00+00:00</updated>
    <content type="html">&lt;p&gt;Over Christmas, Claire and I travelled to Las Vegas to finally tie the knot. After a few relatively easy months of planning, several hours delay in London and very little sleep; the wedding day was perfect.&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/2010/01/DSC_0153.jpg" title="Treasure Island" alt="Treasure Island" /&gt;
&lt;img src="/images/2010/01/DSC_0373.jpg" title="Venetian" alt="Venetian" /&gt;&lt;/p&gt;

&lt;p&gt;We were married at the Treasure Island, and had a small reception meal across the road in the Venetian hotel, before taking a tour of the strip, and obligatory photos at 'the sign', in a stretch.&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/2010/01/PC280118.jpg" title="Flight over Grand Canyon" alt="Flight over Grand Canyon" /&gt;&lt;/p&gt;

&lt;p&gt;The trip was complete with a helicopter tour of the strip and neighbouring Grand Canyon valleys.&lt;/p&gt;

&lt;p&gt;Needless to say it was one of the most exciting and unusual Christmas' I've ever experienced, and a great start to married life in 2010!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://bit.ly/5dbPkN" title="Photostream on Flickr"&gt;More photos on Flickr...&lt;/a&gt;&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=-PJx62k7NEc:clodu1RT8CI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=-PJx62k7NEc:clodu1RT8CI:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=-PJx62k7NEc:clodu1RT8CI:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=-PJx62k7NEc:clodu1RT8CI:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://chrisblunt.com/blog/2010/01/03/just-married/</feedburner:origLink></entry>
  
  <entry>
    <author><name>Chris</name></author>
    <title>Introducing Molehill: Simple Issue Tracking</title>
    <id>http://chrisblunt.com/blog/2009/12/15/introducing-molehill-simple-issue-tracking</id>
    <link href="http://feedproxy.google.com/~r/chrisblunt/~3/DSKwWa7UaTc/" />
    <published>2009-12-15T00:00:00+00:00</published>
    <updated>2009-12-15T00:00:00+00:00</updated>
    <content type="html">&lt;p&gt;&lt;img src="/images/2009/12/molehill-01.jpg" title="Molehill Homepage" alt="Molehill Homepage Screenshot" /&gt;&lt;/p&gt;

&lt;p&gt;In my &lt;a href="http://chrisblunt.com/blog/2009/12/11/rails-first-steps-with-cucumber/" title="Rails: First Steps with Cucumber"&gt;previous post&lt;/a&gt;, I wrote how I've recently been getting to grips with &lt;a href="http://cukes.info/" title="Cucumber"&gt;Cucumber&lt;/a&gt; and &lt;a href="http://github.com/ianwhite/pickle" title="Pickle"&gt;Pickle&lt;/a&gt;. To do this, rather than trying to retro-fit Cucumber stories into another app, I decided to start with a fresh new Rails app: &lt;a href="http://molehill.chrisblunt.com/" title="Molehill"&gt;Molehill&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://molehill.chrisblunt.com/" title="Molehill"&gt;Molehill&lt;/a&gt; is an experiment, both in learning behaviour driven design (BDD), and also trying out some ideas for a simplified issue tracker.&lt;/p&gt;

&lt;p&gt;Molehill is open-source, and can be downloaded from &lt;a href="http://github.com/cblunt/molehill" title="Molehill"&gt;github&lt;/a&gt;. See the end of this post for more details.&lt;/p&gt;

&lt;h3&gt;Post. Fix. Close.&lt;/h3&gt;

&lt;p&gt;Molehill is designed to avoid the problem I've found with other issue trackers I've used - they do too much. They require so much overhead setting up and managing versions, milestones, time estimates, shipping forecasts, gantt charts, and so on - that it's as much work posting a case as actually fixing it.&lt;/p&gt;

&lt;p&gt;Molehill takes a much simpler approach, purposefully avoiding all that which makes other issue trackers so heavy. Instead, Molehill is based on the idea that tracking bugs and features should be as simple as &lt;strong&gt;post, fix, close.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;Posting and Promoting Cases&lt;/h3&gt;

&lt;p&gt;Taking cues from Twitter and the micro-blog format, cases are written as simple posts which are dropped into a timeline.&lt;/p&gt;

&lt;p&gt;If a case is posted that you think is important, you can promote it. The more promotions a case has, the higher it appears in the timeline.&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/2009/12/molehill-02.jpg" title="Molehill Promoting Posts" alt="Molehill Promoting Posts Screenshot" /&gt;&lt;/p&gt;

&lt;p&gt;For developers, this means that your users' most desired bugfixes or features are always sitting at the top of the timeline. Instead of spending hours building roadmaps, and scheduling cases for release in 6 weeks (if you're lucky), just work on whatever case is next at the top of the list and release it.&lt;/p&gt;

&lt;h3&gt;Closing Cases&lt;/h3&gt;

&lt;p&gt;Once a case has been fixed or implemented, the original author can mark it as such; or - if it's not going to be implemented - it can be marked declined.&lt;/p&gt;

&lt;p&gt;At the moment, only the original author can close a cace - I've intentionally avoided roles (such as Developers and Reporter) in Molehill, although I may have to make an exception so that developer's can mark any case as completed or declined.&lt;/p&gt;

&lt;p&gt;An alternative approach might be to allow any other use to &lt;em&gt;suggest&lt;/em&gt; a case is complete, or indicate that it won't be implemented. This might be better achieved through a reply system though, like Twitter's &lt;span class="code"&gt;@reply&lt;/span&gt; tag.&lt;/p&gt;

&lt;h3&gt;Categories and Projects&lt;/h3&gt;

&lt;p&gt;Molehill doesn't have a concept of projects, but does allow &lt;span class="code"&gt;#hashtags&lt;/span&gt; within a case. This means cases can easily be tagged and categorised to a project or feature, for example:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;There should be a way for #molehill to categorise or tag #cases. 
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;A quick search from the homepage, or click on the #hashtag, reveals any other cases tagged with the same words.&lt;/p&gt;

&lt;h3&gt;Cucumbers Everywhere&lt;/h3&gt;

&lt;p&gt;I built Molehill primarily to learn Cucumber, and doing so has got me hooked on writing feature-first code. The majority of Molehill was built without once launching Firefox or Chrome; everything was instead written as a feature, and run through Cucumber and Webrat until that feature passed.&lt;/p&gt;

&lt;p&gt;Good Cucumber coverage allows far more confidence when deploying your code that everything works together. Too often I've seen a minor fix in one part of an app have a completely unforeseen effect on some screen assumed to be unrelated. With Cucumber, and a good test suite, these worries can be all but forgotten. Now that it's in public beta, I'm working to retrospectively cover &lt;a href="https://amberleafapp.com" title="Amberleaf"&gt;Amberleaf&lt;/a&gt; in Cucumber stories&lt;/p&gt;

&lt;h3&gt;Getting Molehill&lt;/h3&gt;

&lt;p&gt;Molehill is open sourced under the MIT licence (the same as Rails). You can grab a copy of the code from &lt;a href="http://githuib.com/cblunt/molehill" title="Molehill on Github"&gt;github&lt;/a&gt;, and setup your own local Molehill server using the following steps:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git clone git://github.com/cblunt/molehill.git
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;molehill

&lt;span class="nv"&gt;$ &lt;/span&gt;cp config/database.yml.sample config/database.yml
&lt;span class="c"&gt;# You&amp;#39;ll need to configure your local database in config/database.yml&lt;/span&gt;

&lt;span class="c"&gt;# Molehill has a number of gem dependencies, including Cucumber and Pickle&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;rake gems:install

&lt;span class="nv"&gt;$ &lt;/span&gt;rake db:migrate
&lt;span class="nv"&gt;$ &lt;/span&gt;rake db:migrate &lt;span class="nv"&gt;RAILS_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cucumber

&lt;span class="nv"&gt;$ &lt;/span&gt;rake cucumber
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;You can also generate an RCov coverage report (saved in &lt;span class="filename"&gt;features_coverage&lt;/span&gt;) using:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rake cucumber:rcov
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;There is a live demo of Molehill running at &lt;a href="http://molehill.chrisblunt.com" title="Molehill"&gt;http://molehill.chrisblunt.com&lt;/a&gt;. To begin with, I'll use Molehill to track its own development. However, if it proves to be a workable concept (and requires less management than a full redmine setup), I'll probably use it for Amberleaf's issue tracking as well.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=DSKwWa7UaTc:NUQmvMf72no:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=DSKwWa7UaTc:NUQmvMf72no:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=DSKwWa7UaTc:NUQmvMf72no:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=DSKwWa7UaTc:NUQmvMf72no:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://chrisblunt.com/blog/2009/12/15/introducing-molehill-simple-issue-tracking/</feedburner:origLink></entry>
  
  <entry>
    <author><name>Chris</name></author>
    <title>Rails: Building Apps with Cucumber and Pickle</title>
    <id>http://chrisblunt.com/blog/2009/12/11/rails-first-steps-with-cucumber</id>
    <link href="http://feedproxy.google.com/~r/chrisblunt/~3/Z9UBkUlRsLc/" />
    <published>2009-12-11T00:00:00+00:00</published>
    <updated>2009-12-11T00:00:00+00:00</updated>
    <content type="html">&lt;p&gt;I'd often read about &lt;a href="http://cukes.info/" title="Cucumber"&gt;Cucumber&lt;/a&gt;, but had always been put off by the task of learning another abstract domain language to distract me from actually writing code. But as I kept reading more and more about it, curiosity got the better of me and I had to give it a try.&lt;/p&gt;

&lt;p&gt;After a couple of weeks of learning to use Cucumber, I'm completely hooked.&lt;/p&gt;

&lt;h3&gt;What is Cucumber?&lt;/h3&gt;

&lt;p&gt;Cucumber grew out of &lt;a href="http://rspec.info/" title="RSpec"&gt;RSpec&lt;/a&gt; as a language for describing user stories in behaviour driven design (BDD). Cucumber avoids the abstract and often incorrect, functional and technical documenting of the software process, instead encouraging you to write short, specific &lt;em&gt;stories&lt;/em&gt; about an should do.&lt;/p&gt;

&lt;p&gt;In Cucumber, these stories are described through number of individual &lt;em&gt;steps&lt;/em&gt; that describe a situation, set of actions, and conditions to be met. For example, a Cucumber story to test logging out of an application might look something like:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# features/logging_in_and_out.feature&lt;/span&gt;
&lt;span class="no"&gt;Scenario&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="n"&gt;logged&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;wants&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;
  &lt;span class="no"&gt;Given&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt; &lt;span class="n"&gt;am&lt;/span&gt; &lt;span class="n"&gt;logged&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
  &lt;span class="no"&gt;And&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt; &lt;span class="n"&gt;click&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Log out&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;link&lt;/span&gt;
  &lt;span class="no"&gt;Then&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;logged&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
  &lt;span class="no"&gt;And&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;home&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;
  &lt;span class="no"&gt;And&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;see&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;You have been logged out&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Stories are designed to be written and read by people, not machines. When you run your story through Cucumber, it applies some funky logic and regular expression matching to run your application code against the story's steps. Each step creates or checks the situation being described.&lt;/p&gt;

&lt;p&gt;For example, the steps for the logging out feature above might be:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# features/step_definitions/authentication_steps.rb&lt;/span&gt;
&lt;span class="no"&gt;Given&lt;/span&gt;&lt;span class="sr"&gt; /^I am logged in$/&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# I&amp;#39;ve used FactoryGirl to create fixtures here&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;Then&lt;/span&gt;&lt;span class="sr"&gt; /^I should not be logged in$/&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;be_nil&lt;/span&gt;
  &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;be_nil&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Thankfully, Cucumber comes with a collection of pre-defined steps that cover common situations, such as the  &lt;span class="code"&gt;Then I should see "{something}"&lt;/span&gt; and &lt;span class="code"&gt;When I click "{some link}"&lt;/span&gt; steps in the previous example.&lt;/p&gt;

&lt;h3&gt;Cucumber with Pickle&lt;/h3&gt;

&lt;p&gt;Cucumber works well with a number of other gems, but one that you'll definitely want to use is &lt;a href="http://github.com/ianwhite/pickle" title="Pickle"&gt;pickle&lt;/a&gt;. Once installed, pickle gives you a collection of handy step definitions for creating a referring to new models in your stories.&lt;/p&gt;

&lt;p&gt;In the example below, a new Post model is created and assigned the label "the post". The remaining steps can then refer to "the post" directly:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# features/publishing_posts.rb&lt;/span&gt;
&lt;span class="no"&gt;Given&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;the post&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;published&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;span class="no"&gt;And&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;the post&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;belongs&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;me&lt;/span&gt;
&lt;span class="no"&gt;When&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt; &lt;span class="n"&gt;am&lt;/span&gt; &lt;span class="n"&gt;editing&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;the post&amp;quot;&lt;/span&gt;
&lt;span class="no"&gt;And&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt; &lt;span class="n"&gt;click&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Publish Post&amp;quot;&lt;/span&gt;
&lt;span class="no"&gt;Then&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;the post&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;published&lt;/span&gt;
&lt;span class="no"&gt;And&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;see&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Post Published&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;h3&gt;Why You Should Be Using Cucumber&lt;/h3&gt;

&lt;h4&gt;Confidence&lt;/h4&gt;

&lt;p&gt;The greatest benefit of Cucumber (and most test-driven methodologies) is that you gain an incredible amount of confidence in your code. Before any release, you can quickly and automatically check that your whole application is doing what you'd expect it to do. This makes releases a far less daunting experience.&lt;/p&gt;

&lt;h4&gt;It tests your entire application, from top to bottom&lt;/h4&gt;

&lt;p&gt;I'd always found testing the high-level functionality of a web app tricky with other test tools, including RSpec. Although they were great at checking very specific, model conditions, when it came to testing the working app as a whole, they never seemed to quite cut it.&lt;/p&gt;

&lt;p&gt;Cucumber lets you write tests that drive through every layer of your application: views, controllers, models and other utility classes (such as email handling, see this &lt;a href="http://drnicwilliams.com/2009/03/26/testing-outbound-emails-with-cucumber/" title="Testing Outbound Emails"&gt;great post&lt;/a&gt; on &lt;a href="http://github.com/bmabey/email-spec" title="email_spec at Github"&gt;email_spec&lt;/a&gt;) can all be tested in a much more natural manner.&lt;/p&gt;

&lt;h4&gt;Stories are reusable&lt;/h4&gt;

&lt;p&gt;As you write more stories, you'll quickly build up a library of handy step definitions. You can use more advanced regular expressions to DRY those step definitions, and then re-use them in other parts of your project, or in other projects.&lt;/p&gt;

&lt;h4&gt;Your code is self documenting&lt;/h4&gt;

&lt;p&gt;One of the greatest benefits of Cucumber stories is that they act as effective documentation for your app. Cucumber can output its running descriptions in a number of formats, including HTML. Having this documentation automatically generated can give you even more assurance that your code is doing what you'd expect, and lets you answer those "what's supposed to happen if...?" questions with certainty.&lt;/p&gt;

&lt;h3&gt;Get Started&lt;/h3&gt;

&lt;p&gt;If you haven't tried Cucumber yet, I really recommend you take an hour to follow some of the &lt;a href="http://wiki.github.com/aslakhellesoy/cucumber/tutorials-and-related-blog-posts" title="Cucumber tutorials"&gt;tutorials&lt;/a&gt;. You definitely won't regret it. There's loads more tips and information available on the &lt;a href="http://cukes.info" title="Cucumber"&gt;Cucumber website&lt;/a&gt;, as well as the official &lt;a href="http://pragprog.com/titles/achbd/the-rspec-book" title="RSpec Book"&gt;RSpec Book&lt;/a&gt; from The Pragmatic Bookshelf.&lt;/p&gt;

&lt;p&gt;In the next post, I'll introduce &lt;a href="http://molehill.chrisblunt.com" title="Molehill"&gt;Molehill&lt;/a&gt;, my first attempt at building an app the BDD way. In the meantime, if you'd like to check out the code and take a look at the Cucumber stories, you can find &lt;a href="http://github.com/cblunt/molehill" title="Molehill at Github"&gt;Molehill&lt;/a&gt; on github.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=Z9UBkUlRsLc:ZDVW4ouAAdc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=Z9UBkUlRsLc:ZDVW4ouAAdc:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=Z9UBkUlRsLc:ZDVW4ouAAdc:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=Z9UBkUlRsLc:ZDVW4ouAAdc:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://chrisblunt.com/blog/2009/12/11/rails-first-steps-with-cucumber/</feedburner:origLink></entry>
  
  <entry>
    <author><name>Chris</name></author>
    <title>Rails: Multiple default scopes for ActiveRecord</title>
    <id>http://chrisblunt.com/blog/2009/10/22/rails-multiple-default-scopes-for-activerecord</id>
    <link href="http://feedproxy.google.com/~r/chrisblunt/~3/zlicpizeClA/" />
    <published>2009-10-22T00:00:00+01:00</published>
    <updated>2009-10-22T00:00:00+01:00</updated>
    <content type="html">&lt;p&gt;Default scopes were introduced in Rails 2.3 to allow a default set of options to be applied to any find methods. The common example is to always order a set of results by a given column, e.g:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="c1"&gt;# Any calls to Post.find will automatically have the default :order option merged into them&lt;/span&gt;
  &lt;span class="c1"&gt;# Post.find(:all)&lt;/span&gt;
  &lt;span class="c1"&gt;# =&amp;gt; SELECT * FROM &amp;quot;posts&amp;quot; ORDER BY &amp;quot;created_at DESC&amp;quot;;&lt;/span&gt;
  &lt;span class="n"&gt;default_scope&lt;/span&gt; &lt;span class="ss"&gt;:order&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;created_at DESC&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Unlike &lt;a href="http://chrisblunt.com/blog/2009/10/06/rails-complex-queries-with-named-scopes/"&gt;named_scopes&lt;/a&gt; (which I am finding more and more useful every day), I found that default scopes cannot  be combined when I tried to use the &lt;a href="http://github.com/rich/acts_as_revisable/"&gt;acts_as_revisable&lt;/a&gt; and &lt;a href="http://github.com/semanticart/is_paranoid"&gt;is_paranoid&lt;/a&gt; plugins together:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;acts_as_revisable&lt;/span&gt;
  &lt;span class="n"&gt;is_paranoid&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;It seems the default scope declared in &lt;span class="code"&gt;is_paranoid&lt;/span&gt; overrides that of &lt;span class="code"&gt;acts_as_revisable&lt;/span&gt;. &lt;span class="code"&gt;Post.find(:all)&lt;/span&gt; will therefore return every revision of &lt;span class="code"&gt;Post&lt;/span&gt; rather than just the current revision. You can check this out by reversing the plugin order:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;is_paranoid&lt;/span&gt;
  &lt;span class="n"&gt;acts_as_revisable&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now, &lt;span class="code"&gt;Post.find(:all)&lt;/span&gt; will return only current revisions, but will include any destroyed posts as the &lt;span class="code"&gt;acts_as_revisable&lt;/span&gt; default scope overrides &lt;span class="code"&gt;is_paranoid&lt;/span&gt;!&lt;/p&gt;

&lt;h3&gt;A Solution&lt;/h3&gt;


&lt;p&gt;&lt;a href="http://joshuaclayton.github.com/code/default_scope/activerecord/is_paranoid/multiple-default-scopes.html"&gt;This post and code snippet&lt;/a&gt; shows a method for declaring multiple default scopes on a model. I've not yet tried out the code, though, as one of the commenter's was kind enough to fork&lt;span class="code"&gt;is_paranoid&lt;/span&gt; and modify it to merge any existing default scopes. With this forked plugin, &lt;span class="code"&gt;Post&lt;/span&gt; can be scoped correctly by both plugins.&lt;/p&gt;

&lt;p&gt;The fork is available at &lt;a href="http://github.com/grioja/is_paranoid/tree/master"&gt;http://github.com/grioja/is_paranoid/tree/master&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;But... is_paranoid is depracated&lt;/h3&gt;


&lt;p&gt;I noticed that the original &lt;a href="http://github.com/semanticart/is_paranoid"&gt;is_paranoid&lt;/a&gt; plugin has ceased development, so I'm not sure if I'll continue to use it, although It's a neat little plugin, and has several forks.&lt;/p&gt;

&lt;p&gt;The underlying problem, though, of ActiveRecord allowing only one &lt;span class="code"&gt;default_scope&lt;/span&gt; to be declared, is something that I'm bound to come up against in the future, so it's handy to know there is a workaround at least until Rails includes the functionality.&lt;/p&gt;

&lt;p&gt;As an aside, &lt;a href="http://withoutscope.com/"&gt;Rich Cavanaugh&lt;/a&gt;, the developer of acts_as_revisable, has pointed out that the plugin includes some basic is_paranoid functionality already (see &lt;a href="http://github.com/rich/acts_as_revisable/issues/#issue/8/comment/63289"&gt;Rich's reply&lt;/a&gt; to my &lt;a href="http://github.com/rich/acts_as_revisable/issues#issue/8"&gt;original ramblings&lt;/a&gt;):&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;acts_as_revisable&lt;/span&gt; &lt;span class="ss"&gt;:on_delete&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:revise&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Do you use default_scope? Do you find the single scope a limitation, or do you rely on named scopes? Feel free to discuss in the comments.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=zlicpizeClA:W3K3-b1v3LQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=zlicpizeClA:W3K3-b1v3LQ:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=zlicpizeClA:W3K3-b1v3LQ:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=zlicpizeClA:W3K3-b1v3LQ:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://chrisblunt.com/blog/2009/10/22/rails-multiple-default-scopes-for-activerecord/</feedburner:origLink></entry>
  
  <entry>
    <author><name>Chris</name></author>
    <title>Rails: Getting the id of form fields inside a fields_for block </title>
    <id>http://chrisblunt.com/blog/2009/10/12/rails-getting-the-id-of-form-fields-inside-a-fields_for-block</id>
    <link href="http://feedproxy.google.com/~r/chrisblunt/~3/vMi3Hj5rUeI/" />
    <published>2009-10-12T00:00:00+01:00</published>
    <updated>2009-10-12T00:00:00+01:00</updated>
    <content type="html">&lt;p&gt;Something that seems to crop up a lot when working with nested forms is the need to access the id of an input field generated inside a fields_for loop. The problem is that the FormBuilder object doesn't expose its &lt;span class="code"&gt;index&lt;/span&gt; attribute, so you can't specify the full id of the field. For example:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# app/views/people/_form.html.erb&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;% person_form,fields_for &lt;/span&gt;&lt;span class="ss"&gt;:attributes&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;attributes_form&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="sx"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="sx"&gt;  # This text field&amp;#39;s id will be in the format person_attributes_[index]_name&lt;/span&gt;
&lt;span class="sx"&gt;  &amp;lt;%= f.text_field :name %&amp;gt;&lt;/span&gt;

   &lt;span class="c1"&gt;# No way to know what [index] should be&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;observe_field&lt;/span&gt; &lt;span class="ss"&gt;:person_attributes_&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="n"&gt;_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="sx"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="sx"&gt;&amp;lt;% end -%&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I hit this problem a few days ago when I wanted to setup autocompleters on a dynamically generated field. I ended up posting a solution to &lt;a href="http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/fbaffb284d7e504c/d1e2047bd214ed1b#d1e2047bd214ed1b"&gt;Google Groups&lt;/a&gt;. For completeness, I'm reposting the code with all my typos removed.&lt;/p&gt;

&lt;h3&gt;Where does the index come from?&lt;/h3&gt;


&lt;p&gt;To find out how the FormBuilder generates its field ids, I delved into the Rails source code and found a couple of helper methods in the &lt;span class="code"&gt;InstanceTagMethods&lt;/span&gt; module (&lt;a href="http://github.com/rails/rails/blob/master/"&gt;source&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The methods of interest are &lt;span class="code"&gt;sanitized_object_name&lt;/span&gt; and &lt;span class="code"&gt;sanitized_method_name&lt;/span&gt;. They take the name of the FormBuilder's model object (which is publicly accessible) and return the generated form element id (e.g. &lt;span class="code"&gt;person[attributes][0][name]&lt;/span&gt; becomes &lt;span class="code"&gt;person_attributes_0_name&lt;/span&gt;).&lt;/p&gt;

&lt;p&gt;However, the methods that work this magic are private to the &lt;span class="code"&gt;InstanceTagMethods&lt;/span&gt; module, so you can't get at them from within your &lt;span class="code"&gt;fields_for&lt;/span&gt; block.&lt;/p&gt;

&lt;h3&gt;Exposing the generated form field ids&lt;/h3&gt;


&lt;p&gt;I decided to duplicate these methods in my &lt;span class="filename"&gt;application_helper.rb&lt;/span&gt;, making them available to my fields_for block. Whilst not DRY, this is so far the only solution I've found for exposing the FormBuilder's index:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# app/helpers/application_helper.rb&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sanitized_object_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;object_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;object_name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/\]\[|[^-a-zA-Z0-9:.]/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;_&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/_$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sanitized_method_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;method_name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/\?$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;form_tag_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;object_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;sanitized_object_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;object_name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;sanitized_method_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method_name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# app/views/people/_person_attributes.rb&lt;/span&gt;
&lt;span class="c1"&gt;# wrapped in person_form,fields_for :attributes do |attributes_form|&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= f.text_field :name %&amp;gt;&lt;/span&gt;
&lt;span class="sx"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;observe_field&lt;/span&gt; &lt;span class="n"&gt;form_tag_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;object_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This code works for indexed partials (i.e. those with indexes based on their model id), and those generated with timestamp indexes such as in Ryan Bates' latest nested form code for Rails 2.3 -
&lt;a href="http://github.com/ryanb/complex-form-examples"&gt;http://github.com/ryanb/complex-form-examples&lt;/a&gt;.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=vMi3Hj5rUeI:iyt-DpWkVMc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=vMi3Hj5rUeI:iyt-DpWkVMc:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=vMi3Hj5rUeI:iyt-DpWkVMc:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=vMi3Hj5rUeI:iyt-DpWkVMc:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://chrisblunt.com/blog/2009/10/12/rails-getting-the-id-of-form-fields-inside-a-fields_for-block/</feedburner:origLink></entry>
  
  <entry>
    <author><name>Chris</name></author>
    <title>Rails: Complex Queries with Named Scopes</title>
    <id>http://chrisblunt.com/blog/2009/10/06/rails-complex-queries-with-named-scopes</id>
    <link href="http://feedproxy.google.com/~r/chrisblunt/~3/GjKqDFy_mhc/" />
    <published>2009-10-06T00:00:00+01:00</published>
    <updated>2009-10-06T00:00:00+01:00</updated>
    <content type="html">&lt;p&gt;I've recently come to realise the massive power of ActiveRecord's &lt;span class="code"&gt;named_scopes&lt;/span&gt;. The revelation came whilst I was researching how to scope, by their permissions, the records  a &lt;span class="class"&gt;@current_user&lt;/span&gt; can view or edit.&lt;/p&gt;

&lt;p&gt;I'd looked at all sorts of plugins and complex authorization configurations, before realising that named scopes have almost limitless potential for building such complex queries.&lt;/p&gt;

&lt;h3&gt;What are named scopes?&lt;/h3&gt;


&lt;p&gt;As demonstrated by &lt;a href="http://railscasts.com/episodes/108-named-scope"&gt;Ryan Bates' screencast&lt;/a&gt;, named scopes let you declare finder conditions as methods on your model object.&lt;/p&gt;

&lt;p&gt;For example, you could get all active users using&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# app/models/user.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;named_scope&lt;/span&gt; &lt;span class="ss"&gt;:active&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:conditions&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:active&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# To select all active users&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt; 
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The real power of named scopes, though, lies in their ability to be chained. As they are just methods on your model class, they can be combined, and ActiveRecord will take care of building the relevant conditions and joins:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# app/models/user.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;named_scope&lt;/span&gt; &lt;span class="ss"&gt;:active&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:conditions&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:active&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;named_scope&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:conditions&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;named_scope&lt;/span&gt; &lt;span class="ss"&gt;:recently_logged_in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
              &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:conditions&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;logged_in_at &amp;gt;= ?&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ago&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# To get all active users who have recently logged in:&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recently_logged_in&lt;/span&gt;

&lt;span class="c1"&gt;# To get all active admin users who have recently logged in&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recently_logged_in&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;




&lt;h3&gt;Using Named Scopes to Build Complex Queries&lt;/h3&gt;


&lt;p&gt;With chaining, you can build some pretty complex queries with ease. However, it would be great if we were able to declare some conditions at run-time, rather than when the model class is loaded.&lt;/p&gt;

&lt;p&gt;The &lt;span class="code"&gt;lambda&lt;/span&gt; function lets you do just that, taking a set of arguments and inserting them into your query:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# app/models/user.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;named_scope&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:conditions&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;named_scope&lt;/span&gt; &lt;span class="ss"&gt;:last_logged_in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;time_ago&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; 
    &lt;span class="n"&gt;time_ago&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ago&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:conditions&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;logged_in_at &amp;gt;= ?&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_ago&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# By default, we&amp;#39;ll get users who have logged in in the last 7 days:&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_logged_in&lt;/span&gt;

&lt;span class="c1"&gt;# To get users who have logged in during the past 4 weeks:&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_logged_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weeks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ago&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# To get admin users who have logged in in the past 6 months&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_logged_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;months&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ago&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Combining &lt;span class="code"&gt;lambda&lt;/span&gt; with &lt;span class="code"&gt;named_scope&lt;/span&gt; lets you build complex attribute queries with runtime arguments. As an example, I've reworked my the code from my &lt;a href="http://chrisblunt.com/blog/2009/05/12/rails-building-complex-search-filters-with-activerecord-and-ez_where/"&gt;previous posts&lt;/a&gt; to make use of named_scope:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# app/models/user.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;named_scope&lt;/span&gt; &lt;span class="ss"&gt;:name_like&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;terms&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; 
    &lt;span class="c1"&gt;# ensure terms is an array&lt;/span&gt;
    &lt;span class="n"&gt;terms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[*&lt;/span&gt;&lt;span class="n"&gt;terms&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;composed_conditions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;EZ&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Caboose&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Condition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="ss"&gt;:users&lt;/span&gt;

    &lt;span class="n"&gt;terms&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;term&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;%&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;%&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;

      &lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;EZ&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Caboose&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Condition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="ss"&gt;:users&lt;/span&gt;
      &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;first_name ILIKE ?&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:or&lt;/span&gt;
      &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;last_name ILIKE ?&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:or&lt;/span&gt;

      &lt;span class="n"&gt;composed_conditions&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:conditions&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;composed_conditions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_sql&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;With this small chunk of code (and a helping hand from the &lt;a href="http://brainspl.at/articles/2006/06/30/new-release-of-ez_where-plugin"&gt;Caboose EZ Condition&lt;/a&gt; plugin), you can now search for Users by matching their first or last names with the supplied terms, e.g:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# To search for users with a first or last name like &amp;quot;joe&amp;quot;&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name_like&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;joe&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# To search for users with a first or last name like &amp;quot;joe&amp;quot; and a first or last name like &amp;quot;bloggs&amp;quot;:&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name_like&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;joe&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;bloggs&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;As we saw above, the greatest advantage of using named_scopes for this type of functionality is their ability to chain. With this in mind, I was able to solve my problem of scoping results within the permissions of &lt;span class="code"&gt;@current_user&lt;/span&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# app/models/user.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="n"&gt;named_scope&lt;/span&gt; &lt;span class="ss"&gt;:visible_to&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:conditions&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;department_id IN ?&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;managed_department_ids&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_logged_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weeks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ago&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name_like&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;joe&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;bloggs&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;visible_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@current_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ordered_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Named scopes are undoubtedly one of the most powerful tools available to ActiveRecord. I can't help but think I'm still just scratching the surface of their potential, but already I've been able to refactor pages of code and build powerful, Rails-friendly custom queries.&lt;/p&gt;

&lt;p&gt;Are you using named scopes in your code? Feel free to discuss in the comments!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=GjKqDFy_mhc:t2TRZn2xKHA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=GjKqDFy_mhc:t2TRZn2xKHA:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=GjKqDFy_mhc:t2TRZn2xKHA:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=GjKqDFy_mhc:t2TRZn2xKHA:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://chrisblunt.com/blog/2009/10/06/rails-complex-queries-with-named-scopes/</feedburner:origLink></entry>
  
  <entry>
    <author><name>Chris</name></author>
    <title>Rails: Writing library code</title>
    <id>http://chrisblunt.com/blog/2009/09/17/rails-writing-library-code</id>
    <link href="http://feedproxy.google.com/~r/chrisblunt/~3/-rzW66B6--k/" />
    <published>2009-09-17T00:00:00+01:00</published>
    <updated>2009-09-17T00:00:00+01:00</updated>
    <content type="html">&lt;p&gt;Plugins are great in Rails, but sometimes they seem a bit much for certain tasks, such as writing a quick utility mixin. In a previous post on &lt;a href="http://chrisblunt.com/blog/2009/04/18/rails-writing-dry-custom-validators/"&gt;writing DRY validators&lt;/a&gt;, I discussed putting the validation mixin code inside Rails' &lt;span class="filename"&gt;config/initializers&lt;/span&gt; directory.&lt;/p&gt;

&lt;p&gt;Although this worked, it didn't feel clean: Rails apps come with a default &lt;span class="filename"&gt;lib&lt;/span&gt; folder that seems much better suited to the task.&lt;/p&gt;

&lt;p&gt;Since reading &lt;a href="http://www.strictlyuntyped.com/2008/06/rails-where-to-put-other-files.html"&gt;this post&lt;/a&gt; on Rails' &lt;em&gt;other files&lt;/em/&gt;. I've used the following setup in projects such as &lt;a href="http://amberleafapp.com"&gt;Amberleaf&lt;/a&gt; to load all the mixins and utility code that doesn't warrant its own plugin:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# config/initializers/application.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;lib/application.rb&amp;#39;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The &lt;span class="filename"&gt;lib/application.rb&lt;/span&gt; acts as a start point for loading in any of your other library code. In the following example, I've mixed some methods into the &lt;span class="code"&gt;String&lt;/span&gt; class and written a small extension to &lt;span class="code"&gt;ActiveRecord::Base&lt;/span&gt;.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# lib/application.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;core_ext/string.rb&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;core_ext/array.rb&amp;#39;&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;active_record/auditing.rb&amp;#39;&lt;/span&gt;

&lt;span class="c1"&gt;# lib/core_ext/string.rb&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;CoreExt&lt;/span&gt;
  &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;class_eval&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrap&lt;/span&gt;
      &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;%&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# lib/active_record/auditing.rb&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;ActiveRecord&lt;/span&gt;
  &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Auditing&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;included&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;ClassMethods&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;ClassMethods&lt;/span&gt;
      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;acts_as_auditable&lt;/span&gt;
        &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;InstanceMethods&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;InstanceMethods&lt;/span&gt;
      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;auditable_name&lt;/span&gt;
        &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt; &lt;span class="ss"&gt;:include&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Auditing&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This is a lot neater than putting everything in the &lt;span class="filename"&gt;initializers&lt;/span&gt; folder, and allows you to correctly namespace your files. It also prevents your model, controller and view folders from becoming cluttered with utility code.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=-rzW66B6--k:tLG87l2lDXI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=-rzW66B6--k:tLG87l2lDXI:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=-rzW66B6--k:tLG87l2lDXI:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=-rzW66B6--k:tLG87l2lDXI:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://chrisblunt.com/blog/2009/09/17/rails-writing-library-code/</feedburner:origLink></entry>
  
  <entry>
    <author><name>Chris</name></author>
    <title>Rails: Configuring RSpec for Spork</title>
    <id>http://chrisblunt.com/blog/2009/08/28/rails-configuring-rspec-for-spork</id>
    <link href="http://feedproxy.google.com/~r/chrisblunt/~3/gVsiHcuwBLA/" />
    <published>2009-08-28T00:00:00+01:00</published>
    <updated>2009-08-28T00:00:00+01:00</updated>
    <content type="html">&lt;p&gt;&lt;a href="http://rspec.info/"&gt;RSpec&lt;/a&gt; is great for behaviour driven development in Rails. However, as the amount of code you test increases, so too does the time taken to run the tests.&lt;/p&gt;

&lt;p&gt;To help speed things up, I've been using &lt;a href="http://github.com/timcharper/spork/tree/master"&gt;Spork&lt;/a&gt;; a small server that preloads all your library code and sits waiting for specs to run. Installing and setting up your project to use Spork is quick to do:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# Spork relies on cucumber&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;gem install cucumber spork

&lt;span class="c"&gt;# Prepares your project for Spork&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;railsap
&lt;span class="nv"&gt;$ &lt;/span&gt;spork --bootstrap
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Once your project is bootstrapped, you'll need to move all your RSpec initialisation code into the &lt;span class="code"&gt;prefork&lt;/span&gt; block that Spork has added to your &lt;span class="filename"&gt;spec_helper.rb&lt;/span&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# spec/spec_helper.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;spork&amp;#39;&lt;/span&gt;

&lt;span class="no"&gt;Spork&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefork&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# All the default RSpec stuff goes here, e.g:&lt;/span&gt;
  &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;RAILS_ENV&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;test&amp;#39;&lt;/span&gt;
  &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/../config/environment&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;spec/autorun&amp;#39;&lt;/span&gt;
  &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;spec/rails&amp;#39;&lt;/span&gt;
  &lt;span class="no"&gt;Spec&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Runner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;configure&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;#...&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now you can run a Spork server instance with:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;spork
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;For me, though, Spork refused to run. It just kept throwing the following exception:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;Preloading Rails environment
Loading Spork.prefork block...
uninitialized constant MissingSourceFile (NameError)
&lt;/pre&gt;
&lt;/div&gt;




&lt;h3&gt;Fixing the configuration for Spork&lt;/h3&gt;


&lt;p&gt;For a short while, I skipped Spork and continued running my specs as normal. Eventually the number of specs I was testing took several seconds for each run, which soon added up to a lot of waiting.&lt;/p&gt;

&lt;p&gt;So, after some searching and thanks to &lt;a href="http://groups.google.com/group/rspec/browse_thread/thread/4b36ecc09ac6f2e1/abc45ae2bf7dcd3a?q=rspec+spork#abc45ae2bf7dcd3a"&gt;this post on Google Groups&lt;/a&gt;, I learned the exception is caused by a condition included as part of the default RSpec initialisation code.&lt;/p&gt;

&lt;p&gt;The solution is to remove the condition from your &lt;span class="filename"&gt;spec_helper.rb&lt;/span&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# spec/spec_helper.rb&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="c1"&gt;# before:&lt;/span&gt;
&lt;span class="c1"&gt;# require File.dirname(__FILE__) + &amp;quot;/../config/environment&amp;quot; unless defined?(RAILS_ROOT)&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/../config/environment&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now you should be able to run Spork with:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;spork
Using RSpec
Preloading Rails environment
Loading Spork.prefork block...
Spork is ready and listening on 8989!
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Finally, you can tell RSpec to connect to and use Spork if it is running. Just add &lt;span class="code"&gt;--drb&lt;/span&gt; to your &lt;span class="filename"&gt;spec.opts&lt;/span&gt; file:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;# spec/spec.opts
--colour
--format progress
--loadby mtime
--reverse
--drb
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Note that these options are only used if you run RSpec through the rake spec: tasks. If you run specs manually, remember to add the --drb option, for example:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;script/spec --colour --drb spec/controllers/users_controller_spec.rb
&lt;/pre&gt;
&lt;/div&gt; 


&lt;p&gt;Changing your spec setup code by removing the condition is obviously far from ideal, and it may break compatability with cucumber (see &lt;a href="https://rspec.lighthouseapp.com/projects/5645/tickets/839"&gt;this lighthouse ticket&lt;/a&gt; for more information). However, it at least means you can take advantage of Spork until a proper fix is implemented.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=gVsiHcuwBLA:zISipyru6XE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=gVsiHcuwBLA:zISipyru6XE:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=gVsiHcuwBLA:zISipyru6XE:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=gVsiHcuwBLA:zISipyru6XE:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://chrisblunt.com/blog/2009/08/28/rails-configuring-rspec-for-spork/</feedburner:origLink></entry>
  
  <entry>
    <author><name>Chris</name></author>
    <title>Rails: Validating Unique Attributes with acts_as_revisable</title>
    <id>http://chrisblunt.com/blog/2009/08/06/rails-validating-unique-attributes-with-acts_as_revisable</id>
    <link href="http://feedproxy.google.com/~r/chrisblunt/~3/ifvMjJ9TF48/" />
    <published>2009-08-06T00:00:00+01:00</published>
    <updated>2009-08-06T00:00:00+01:00</updated>
    <content type="html">&lt;p&gt;I've been using the &lt;a href="http://github.com/rich/acts_as_revisable/tree/master"&gt;acts_as_revisable&lt;/a&gt; plugin in my &lt;a href="http://staging.chrisblunt.com/"&gt;Rails apps&lt;/a&gt; to store a revision history of ActiveRecord models. The plugin automatically versions your models, and allows you to navigate revisions; branch and merge changes, and perform bulk changesets.&lt;/p&gt;

&lt;p&gt;During some tests of my code, I found a conflict between the plugin and &lt;span class="code"&gt;ActiveRecord.validates_uniqueness_of&lt;/span&gt;. It seems the conflict occurs because acts_as_revisable stores all revisions in the same database table. For example, when trying to save a record whose &lt;span class="code"&gt;:name&lt;/span&gt; attribute should be unique, the validator will see all previous versions of the record with identical names, and prevent the save.&lt;/p&gt;

&lt;p&gt;The fix I put in for this was to use the &lt;span class="code"&gt;:scope&lt;/span&gt; to scope &lt;span class="code"&gt;validates_uniqueness_of&lt;/span&gt; by the &lt;span class="code"&gt;revisable_is_current&lt;/span&gt; attribute:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;validates_as_unique&lt;/span&gt; &lt;span class="ss"&gt;:username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:scope&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:revisable_is_current&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Scoping the attribute causes the validator to only consider records whose &lt;span class="code"&gt;:revisable_is_current&lt;/span&gt; attribute matches that of the record being edited. This works for my app, as only the current revision (&lt;span class="code"&gt;User#revisable_is_current= true&lt;/span&gt;) will ever be edited.&lt;/p&gt;

&lt;p&gt;Are you using acts_as_revisable and come across this problem? Spotted a better solution? Feel free to discuss ideas in the comments.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=ifvMjJ9TF48:DhlgMn5fCyw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=ifvMjJ9TF48:DhlgMn5fCyw:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=ifvMjJ9TF48:DhlgMn5fCyw:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=ifvMjJ9TF48:DhlgMn5fCyw:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://chrisblunt.com/blog/2009/08/06/rails-validating-unique-attributes-with-acts_as_revisable/</feedburner:origLink></entry>
  
  <entry>
    <author><name>Chris</name></author>
    <title>Rails: Upgrade Passenger for Rails 2.3.3</title>
    <id>http://chrisblunt.com/blog/2009/07/31/rails-upgrade-passenger-for-rails-2-3-3</id>
    <link href="http://feedproxy.google.com/~r/chrisblunt/~3/1LnPNJ5KdZU/" />
    <published>2009-07-31T00:00:00+01:00</published>
    <updated>2009-07-31T00:00:00+01:00</updated>
    <content type="html">&lt;p&gt;I recently upgraded a project from Rails 2.3.2 to 2.3.3, after which I started getting strange the following error from &lt;a href="http://www.modrails.com"&gt;Passenger&lt;/a&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;undefined method &amp;#39;rewind&amp;#39; for #&amp;lt;UNIXSocket:0xf6206c18&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;After a little Googling, I discovered that I also needed to upgrade passenger from 2.1.2 to the current version 2.2.4. If you're using RubyGems, this is a quick and easy:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;gem update passenger
passenger-install-apache2-module
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Once the Passenger installation has finished, be sure to update your &lt;span class="code"&gt;apache&lt;/span&gt; config to point to the new version of Passenger:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# apache2.conf&lt;/span&gt;
&lt;span class="nb"&gt;LoadModule&lt;/span&gt; passenger_module &lt;span class="sx"&gt;/usr/lib/ruby/gems/1.8/gems/passenger-2.2.4/ext/apache2/mod_passenger.so&lt;/span&gt;
&lt;span class="nb"&gt;PassengerRoot&lt;/span&gt; &lt;span class="sx"&gt;/usr/lib/ruby/gems/1.8/gems/passenger-2.2.4&lt;/span&gt;
&lt;span class="nb"&gt;PassengerRuby&lt;/span&gt; &lt;span class="sx"&gt;/usr/bin/ruby1.8&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=1LnPNJ5KdZU:myPRZg1EDBI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=1LnPNJ5KdZU:myPRZg1EDBI:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=1LnPNJ5KdZU:myPRZg1EDBI:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/chrisblunt?a=1LnPNJ5KdZU:myPRZg1EDBI:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/chrisblunt?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  <feedburner:origLink>http://chrisblunt.com/blog/2009/07/31/rails-upgrade-passenger-for-rails-2-3-3/</feedburner:origLink></entry>
  
</feed>
