<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>opensoul.org - Code</title>
  <id>tag:opensoul.org,2010:mephisto/code</id>
  <generator version="0.8.0" uri="http://mephistoblog.com">Mephisto Drax</generator>
  
  <link href="http://opensoul.org/code" rel="alternate" type="text/html" />
  <updated>2010-02-17T18:48:52Z</updated>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/opensoul/code" /><feedburner:info uri="opensoul/code" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:browserFriendly></feedburner:browserFriendly><entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2010-02-17:20923</id>
    <published>2010-02-17T18:40:00Z</published>
    <updated>2010-02-17T18:48:52Z</updated>
    <category term="Code" />
    <category term="conference" />
    <category term="local" />
    <category term="ruby" />
    <link href="http://opensoul.org/2010/2/17/great-lakes-ruby-bash" rel="alternate" type="text/html" />
    <title>Great Lakes Ruby Bash</title>
<content type="html">
            &lt;p&gt;The &lt;a href="http://greatlakesrubybash.com/"&gt;Great Lakes Ruby Bash&lt;/a&gt; is now accepting talk proposals.  The conference will be held on Michigan State University’s campus in East Lansing, Michigan on Saturday, April 17th.&lt;/p&gt;


	&lt;p&gt;We’re looking for passionate speakers to give 25 and 40 minute presentations about their experiences with Ruby and related technologies. Our goal is to engage attendees and inspire them to create great software, empower users, and continue learning with others.&lt;/p&gt;


	&lt;p&gt;Proposals are due &lt;strong&gt;Feb 28th, 2010 at 12:59pm &lt;span class="caps"&gt;EST&lt;/span&gt;&lt;/strong&gt;. We hope to have all proposals reviewed and speakers chosen by March 8th, 2010. &lt;a href="http://greatlakesrubybash.com/"&gt;Visit the website&lt;/a&gt; for more info.&lt;/p&gt;


	&lt;h3&gt;Sponsors&lt;/h3&gt;


	&lt;p&gt;We are also looking for companies and freelancers to sponsor the event. This year’s conference will be the third Ruby conference in this region.  The previous two conferences attracted 60-70 attendees each. As a result of more interest, greater community involvement, and a more aggressive marketing campaign, we are anticipating 100-150 attendees this year.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://greatlakesrubybash.com/sponsors.html"&gt;Visit the sponsorship page&lt;/a&gt; to become a sponsor or find additional information about available sponsorship packages.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2010-02-16:20903</id>
    <published>2010-02-16T14:36:00Z</published>
    <updated>2010-02-16T14:38:56Z</updated>
    <category term="Code" />
    <category term="activeresource" />
    <category term="rails" />
    <link href="http://opensoul.org/2010/2/16/active-resource-in-practice" rel="alternate" type="text/html" />
    <title>Active Resource in practice</title>
<content type="html">
            &lt;p&gt;I’m working on app to integrate &lt;a href="http://pivotaltracker.com"&gt;Pivotal Tracker&lt;/a&gt; and &lt;a href="http://getharvest.com"&gt;Harvest&lt;/a&gt;. There’s a great &lt;a href="http://github.com/aiaio/harvest"&gt;ruby wrapper around Harvest’s &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt;, but there isn’t a decent Ruby wrapper for &lt;a href="http://www.pivotaltracker.com/help/api?version=v3"&gt;Tracker’s v3 &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt;, so I thought I would just build one as I needed it.&lt;/p&gt;


	&lt;p&gt;If this app were read only, I would probably use HTTParty and HappyMapper, but since I also want to be able to update timers and stories,  &lt;a href="http://api.rubyonrails.org/classes/ActiveResource/Base.htm"&gt;Active Resource&lt;/a&gt; seemed like the right tool for the job.  Active Resource in theory is great. Active Resource in practice is not so great. I’ve toyed around with it in the past, but using it for something real I found it…lacking.&lt;/p&gt;


	&lt;p&gt;Fortunately the Harvest gem had solved a lot of these problems.  I write about them here in hopes that they will be useful to you.&lt;/p&gt;


	&lt;h3&gt;Challenge 1: Headers don’t inherit&lt;/h3&gt;


	&lt;p&gt;Pivotal Tracker uses a token for authentication and looks for it in a header called “X-TrackerToken”. It would be nice if you could just set this once, and all Active Resource classes would use it. But unfortunately, headers don’t inherit.&lt;/p&gt;


	&lt;p&gt;So the trick is to define a base class for all of your models to inherit from, and in that override how Active Resource treats headers.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;module PivotalTracker
  class Resource &amp;lt; ActiveResource::Base
    Resource.site = &amp;quot;https://www.pivotaltracker.com/services/v3&amp;quot;

    class &amp;lt;&amp;lt; self
      # If headers are not defined in a given subclass, then obtain
      # headers from the superclass.
      def headers
        if defined?(@headers)
          @headers
        elsif superclass != Object &amp;amp;&amp;amp; superclass.headers
          superclass.headers
        else
          @headers ||= {}
        end
      end
  end

  class Project &amp;lt; Resource
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now we can set our token once and subclasses will inherit it:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;PivotalTracker::Resource.headers['X-TrackerToken'] = &amp;quot;mytoken&amp;quot;
projects = PivotalTracker::Project.find(:all)&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;Challenge 2: “Associations”&lt;/h3&gt;


	&lt;p&gt;I find it strange that Active Resource doesn’t support associations. Rails has a standard way of defining embedded resources, so you would think that Active Resource would have a standard way of consuming them (I know, I should get off my lazy duff and contribute a patch, but it’s so much easier to just complain about it).&lt;/p&gt;


	&lt;p&gt;So for APIs that have nested resources like Pivotal Tracker’s, Active Resource forces you to hard code the parent resource id.  If you want to get the iterations for a project, then you have to set the project_id on the Iteration resource.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;PROJECT_ID = 1738

module PivotalTracker
  class Iteration &amp;lt; Resource
    self.prefix = &amp;quot;/services/v3/projects/#{PROJECT_ID}&amp;quot;
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This is just not a scalable solution.  I’m going to need to be able to access multiple projects in the app that I’m working on. So the Harvest gem had a really clever (and evil) solution, which I’ve modified a bit here.&lt;/p&gt;


	&lt;p&gt;It basically involves creating an anonymous subclass of our resource, and setting the prefix just for that subclass.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;module PivotalTracker
  class Project &amp;lt; Resource
    def iterations
      Iteration.build_subclass.tap do |iteration|
        iteration.prefix = &amp;quot;/services/v3/projects/#{self.id}&amp;quot;
      end
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now we can access iterations for any project.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;iterations = Project.find(x).iterations.find(:all)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The #build_subclass method is &lt;a href="http://github.com/collectiveidea/pivotal_tracker/blob/master/lib/pivotal_tracker/resource.rb#L18"&gt;defined on the base resource&lt;/a&gt; and just creates an anonymous subclass and copies some settings that don’t inherit.&lt;/p&gt;


	&lt;h3&gt;Onward Ho!&lt;/h3&gt;


	&lt;p&gt;I don’t have a lot built out yet for the new Pivotal Tracker wrapper, but you can check out the &lt;a href="http://github.com/collectiveidea/pivotal_tracker"&gt;latest progress on GitHub&lt;/a&gt;.  I feel like I’ve overcome most of the bit barriers, so it shouldn’t take much to finish it up.&lt;/p&gt;


	&lt;p&gt;Do you have any other tips or tricks for working with Active Resource?&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2010-02-09:20829</id>
    <published>2010-02-09T04:33:00Z</published>
    <updated>2010-02-09T04:39:07Z</updated>
    <category term="Code" />
    <category term="passenger" />
    <category term="rails" />
    <category term="vmware" />
    <category term="windows" />
    <link href="http://opensoul.org/2010/2/9/passenger-and-browser-testing-in-virtual-machines" rel="alternate" type="text/html" />
    <title>Passenger and browser testing in virtual machines</title>
<content type="html">
            &lt;p&gt;If you’re running Passenger in development, here is how to make Windows running in a virtual machine connect to your app in Passenger.&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Boot up the VM and open up the Windows command prompt (go to “Start-&amp;gt;Run…”, enter “cmd” and press enter)&lt;/li&gt;
		&lt;li&gt;Type &lt;code&gt;ipconfig&lt;/code&gt; to see the network configuration.  Take note of the “Default Gateway” address. &lt;/li&gt;
		&lt;li&gt;Navigate to C:\WINDOWS\system32\drivers\etc and edit the &lt;code&gt;hosts&lt;/code&gt; file.  Add a line with the gateway address pointing to your app’s domain (you can even list multiple on the same line).
  &lt;pre&gt;172.16.248.2    awesomeapp.local otherawesomeapp.local&lt;/pre&gt;&lt;/li&gt;
		&lt;li&gt;Open up a browser in the VM and type in the address.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Tada! Now you can test out your app in those other browsers.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2010-01-05:20190</id>
    <published>2010-01-05T02:31:00Z</published>
    <updated>2010-01-05T02:32:04Z</updated>
    <category term="Code" />
    <category term="collectiveidea" />
    <link href="http://opensoul.org/2010/1/5/things-that-will-rock-the-world-in-2010" rel="alternate" type="text/html" />
    <title>Things that will rock the (my) world in 2010</title>
<content type="html">
            &lt;p&gt;Here are a few things that I’m really looking forward to using and abusing this year:&lt;/p&gt;


	&lt;h3&gt;&lt;a href="http://mongodb.org/"&gt;MongoDB&lt;/a&gt;&lt;/h3&gt;


	&lt;p&gt;We’ve all been trying to shoehorn our Web 2.x applications into a 20 year old technology with an antiquated query language. If you haven’t looked into MongoDB, you need to, and you also need to check out &lt;a href="http://github.com/jnunemaker/mongomapper"&gt;MongoMapper&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;I went out on a limb back in October and stated that &lt;a href="http://twitter.com/bkeepers/status/4709484780"&gt;a year from now, we’ll be using MongoDB for most new web apps&lt;/a&gt;. I think Mongo will be one of those things like Git that catches on like wildfire.&lt;/p&gt;


	&lt;p&gt;I have worked on a couple apps now with MongoDB, and it is a lot of fun. It blows my mind just how much our understanding of data modeling is tied to relational databases.&lt;/p&gt;


	&lt;h3&gt;&lt;a href="http://code.quirkey.com/sammy/"&gt;Sammy&lt;/a&gt;&lt;/h3&gt;


	&lt;p&gt;Sammy is an awesome little Javascript framework for building RESTful and evented web applications.  I’ve only build one little toy app with it so far, but I really enjoyed it and plan to update a couple existing apps an use it on some new ones this year.&lt;/p&gt;


	&lt;h3&gt;&lt;a href="http://outoftime.github.com/"&gt;Sunspot&lt;/a&gt;&lt;/h3&gt;


	&lt;p&gt;If you need to do full-text searching, then &lt;a href="http://outoftime.github.com/"&gt;Sunspot&lt;/a&gt; is your man. I have tried and given up on almost every single solution for doing real full-text searching in applications. I have a reputation around the office for enthusiastically touting several different search solutions as “the one”, only to watch all of them fall on their face in production.&lt;/p&gt;


	&lt;p&gt;But Sunspot has not let me down yet, and I have one app that has been using it in production for a few months with zero problems.  I look forward to abusing it this year.&lt;/p&gt;


	&lt;h3&gt;&lt;a href="http://rubyonrails.org"&gt;Rails 3&lt;/a&gt;&lt;/h3&gt;


	&lt;p&gt;Two weeks ago, Rails 3 would not have made it on this list. In fact, it would have probably made it on my “things that are totally going to suck” list. I was afraid I was becoming a curmudgeon.&lt;/p&gt;


	&lt;p&gt;But the Rails core team has kicked it into high gear the past couple weeks. I spent some time playing with Rails (setting up a new app was no easy feat, although &lt;a href="http://yehudakatz.com/2009/12/31/spinning-up-a-new-rails-app"&gt;now there’s a guide&lt;/a&gt;) and digging through the internals and I can now say that I am officially excited.&lt;/p&gt;


	&lt;p&gt;What are you looking forward to?&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2009-10-29:18483</id>
    <published>2009-10-29T15:52:00Z</published>
    <updated>2009-10-29T15:55:51Z</updated>
    <category term="Code" />
    <category term="acts_as_audited" />
    <category term="authlogic" />
    <category term="collectiveidea" />
    <category term="plugin" />
    <link href="http://opensoul.org/2009/10/29/acts_as_audited-and-authlogic" rel="alternate" type="text/html" />
    <title>acts_as_audited and authlogic</title>
<content type="html">
            &lt;p&gt;For those using authlogic that have had issues with auditing your User model, version 1.0.2 of &lt;a href="github.com/collectiveidea/acts_as_audited"&gt;acts_as_audited&lt;/a&gt; should cure your woes.&lt;/p&gt;


	&lt;p&gt;All you need to do is exclude the &lt;code&gt;last_request_at&lt;/code&gt; and &lt;code&gt;perisable_token&lt;/code&gt; fields from being audited.  We also excluded a few other fields that don’t need to be audited:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class User &amp;lt; ActiveRecord::Base
  acts_as_audited :except =&amp;gt; [
    :crypted_password, 
    :persistence_token,
    :single_access_token,
    :perishable_token,
    :last_request_at,
  ]
end&lt;/code&gt;&lt;/pre&gt;
          </content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2009-10-05:17997</id>
    <published>2009-10-05T17:33:00Z</published>
    <updated>2009-10-05T19:50:15Z</updated>
    <category term="Code" />
    <link href="http://opensoul.org/2009/10/5/how-to-gemify-your-rails-plugins" rel="alternate" type="text/html" />
    <title>How to Gemify your Rails Plugins</title>
<content type="html">
            &lt;p&gt;Ever since &lt;a href="http://ryandaigle.com/articles/2008/4/1/what-s-new-in-edge-rails-gem-dependencies"&gt;Rails added support for declaring gem dependencies&lt;/a&gt;, there is really no (good) reason to use plain ol’ plugins. We’ve been slowly gemifying &lt;a href="http://github.com/collectiveidea"&gt;all of our plugins&lt;/a&gt; as we need them. There’s a few hoops you have to jump through to get Rake tasks and Capistrano recipes working, but it’s fairly straight forward.&lt;/p&gt;


	&lt;p&gt;First, you need something that will help you generate the gemspec and build the gem. You can do this by hand, but there’s several great plugins out there that make it easy. We recommend &lt;a href="http://github.com/technicalpickles/jeweler"&gt;Jeweler&lt;/a&gt;. Follow the directions in the Jeweler &lt;span class="caps"&gt;README&lt;/span&gt; for “Using in an existing project”.&lt;/p&gt;


	&lt;h3&gt;1. Move &lt;code&gt;init.rb&lt;/code&gt; to &lt;code&gt;rails/init.rb&lt;/code&gt;&lt;/h3&gt;


	&lt;p&gt;Rails plugins have the magical &lt;code&gt;init.rb&lt;/code&gt; that gets loaded when the plugin is initialized. To make this work in a gem, all you have to do is move it to &lt;code&gt;rails/init.rb&lt;/code&gt;. Recent versions of Rails will look there whether you install it as a plugin or a gem, so you can just move it to the new location if you don’t care about ancient versions of Rails.&lt;/p&gt;


	&lt;h3&gt;2. Move rake tasks to &lt;code&gt;lib/&lt;/code&gt;&lt;/h3&gt;


	&lt;p&gt;Rails will load &lt;code&gt;tasks/*.rake&lt;/code&gt; defined in any plugins. Unfortunately, these don’t get loaded from Gems.  To make your rake tasks work from a plugin, you will need to move them into the lib directory, and explicitly require them from your app’s &lt;code&gt;Rakefile&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;require 'mygem/tasks'&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;If you want your tasks to still be available when your code is installed as a plugin, you can just explicitly require the task from &lt;code&gt;task/mygem.rake&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'mygem', 'tasks'))&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;3. Move Capistrano tasks to &lt;code&gt;lib/&lt;/code&gt;&lt;/h3&gt;


	&lt;p&gt;Capistrano recipes defined at &lt;code&gt;recipes/*.rb&lt;/code&gt; in your plugin are also automatically loaded by Rails. Unfortunately, they suffer the same fate as Rake tasks and have to be move to the lib directory and be explicitly required from &lt;code&gt;config/deploy.rb&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;When moving the recipes to the lib directory, we have to jump through a hoop to get Capistrano to load it properly.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;Capistrano::Configuration.instance.load do
  # put cap recipes here
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;And in your &lt;code&gt;config/deploy.rb&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;require 'mygem/recipes'&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;As with Rake tasks, if you want your recipes to still work when installed as a plugin, add the following to a file in the &lt;code&gt;recipes/&lt;/code&gt; directory of your plugin:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'mygem', 'recipes'))&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;4. Generators&lt;/h3&gt;


	&lt;p&gt;You don’t have to do anything, they just work.&lt;/p&gt;


	&lt;h3&gt;That’s it&lt;/h3&gt;


	&lt;p&gt;Publish your gem and go buy yourself a drink. Check out &lt;a href="http://github.com/collectiveidea/awesome_nested_set"&gt;one&lt;/a&gt; of &lt;a href="http://github.com/collectiveidea/delayed_job"&gt;our&lt;/a&gt; &lt;a href="http://github.com/collectiveidea/deploy_and_deliver"&gt;gems&lt;/a&gt; if you need &lt;a href="http://github.com/collectiveidea/acts_as_audited"&gt;more&lt;/a&gt; &lt;a href="http://github.com/collectiveidea/no-peeping-toms"&gt;examples&lt;/a&gt;.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2009-06-24:15269</id>
    <published>2009-06-24T00:45:00Z</published>
    <updated>2009-06-25T16:15:13Z</updated>
    <category term="Code" />
    <category term="capistrano" />
    <category term="deployment" />
    <category term="git" />
    <category term="rails" />
    <category term="ssh" />
    <link href="http://opensoul.org/2009/6/24/capistrano-git-and-ssh-keys" rel="alternate" type="text/html" />
    <title>Capistrano, Git and SSH keys</title>
<content type="html">
            &lt;p&gt;This trick has been around for a while, but I’ve talked with several people that didn’t know about it.&lt;/p&gt;


	&lt;p&gt;When deploying apps with Capistrano, your server needs to have access to the Git repository. Generating an &lt;span class="caps"&gt;SSH&lt;/span&gt; key for each server is a bit of a pain, but there’s an easier way: &lt;span class="caps"&gt;SSH&lt;/span&gt; agent forwarding enables you to use any of your local &lt;span class="caps"&gt;SSH&lt;/span&gt; keys on the server. It’s really easy to set up.&lt;/p&gt;


	&lt;p&gt;Enable &lt;span class="caps"&gt;SSH&lt;/span&gt; forwarding in &lt;code&gt;deploy.rb&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;set :ssh_options, {:forward_agent =&amp;gt; true}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The only other thing you need to do is tell the &lt;span class="caps"&gt;SSH&lt;/span&gt; agent about your key.&lt;/p&gt;


&lt;pre&gt;&lt;code class="bash"&gt;$ ssh-add -K&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The &lt;code&gt;-K&lt;/code&gt; option only works on &lt;span class="caps"&gt;OS X&lt;/span&gt; and it adds your key to your keychain so you don’t have to run &lt;code&gt;ssh-add&lt;/code&gt; after you reboot (and if you have a passphrase set, you don’t have to type it every time). You can also pass it the path to an &lt;span class="caps"&gt;SSH&lt;/span&gt; private key in a different location.&lt;/p&gt;


	&lt;p&gt;Now the server can pull from any Git repository that you have access to.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2009-06-01:14492</id>
    <published>2009-06-01T13:18:00Z</published>
    <updated>2009-06-25T13:15:03Z</updated>
    <category term="Code" />
    <category term="bdd" />
    <category term="cucumber" />
    <category term="rails" />
    <category term="search" />
    <category term="sphinx" />
    <link href="http://opensoul.org/2009/6/1/cucumber-scenarios-that-depend-on-sphinx" rel="alternate" type="text/html" />
    <title>Cucumber scenarios that depend on Sphinx</title>
<content type="html">
            &lt;p&gt;I love writing apps that make heavy use of search indexes, but testing them can be a bit of a pain.  Here is how I got &lt;a href="http://freelancing-god.github.com/ts/en/"&gt;ThinkingSphinx&lt;/a&gt; to play nice with &lt;a href="http://cukes.info"&gt;Cucumber&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Here is the relevant part of what I put in &lt;code&gt;features/support/env.rb&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;# Cucumber::Rails.use_transactional_fixtures

# http://github.com/bmabey/database_cleaner
require 'database_cleaner'
DatabaseCleaner.strategy = :truncation
Before do
  DatabaseCleaner.clean
end

ts = ThinkingSphinx::Configuration.instance
ts.build
FileUtils.mkdir_p ts.searchd_file_path
ts.controller.index
ts.controller.start
at_exit do
  ts.controller.stop
end
ThinkingSphinx.deltas_enabled = true
ThinkingSphinx.updates_enabled = true
ThinkingSphinx.suppress_delta_output = true

# Re-generate the index before each Scenario
Before do
  ts.controller.index
end&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;What’s going on here?&lt;/h3&gt;


	&lt;p&gt;Start by commenting out the line about using transactional fixtures in &lt;code&gt;env.rb&lt;/code&gt;. Using transactional fixtures will run each scenario inside of a transaction and roll it back at the end of the scenario to revert the database state. Thinking Sphinx uses an &lt;code&gt;after_commit&lt;/code&gt; callback for kicking off the delta indexing, but the callback never gets run when transactional fixtures are enabled because the entire scenario is run inside of a big transaction.&lt;/p&gt;


	&lt;p&gt;Once we’ve disabled transactional fixtures, our test database will start to fill up, likely causing some problems. So we need to add a &lt;code&gt;Before&lt;/code&gt; block that clears out the database before each scenario. I’m using &lt;a href="http://github.com/bmabey/database_cleaner/tree/master"&gt;database_cleaner&lt;/a&gt;, which gives you some different strategies for cleaning the database. Alternatively, the brute-force solution is just to reload the schema before each scenario, but this is slower than truncating the data.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;Before do
  ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])
  ActiveRecord::Schema.verbose = false
  load &amp;quot;#{RAILS_ROOT}/db/schema.rb&amp;quot;
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Next, we start Sphinx when &lt;code&gt;env.rb&lt;/code&gt; is loaded, and shut it down when the Ruby process exists.  We also enable deltas and updates, which are disabled by default in test mode.  Finally, we define a &lt;code&gt;Before&lt;/code&gt; block that updates the index before each scenario so we don’t end up with a stale index.&lt;/p&gt;


	&lt;h3&gt;Putting it all together&lt;/h3&gt;


	&lt;p&gt;I’m using Sphinx’s &lt;a href="http://opensoul.org/2009/4/30/keepin-sphinx-indexes-fresh-2"&gt;delayed delta support&lt;/a&gt;, so whenever I update records, I need to have delayed_job process jobs. Instead of trying to get delayed_job to run in the background, I took the easy way out and defined a step: “When the system processes jobs”.&lt;/p&gt;


&lt;pre&gt;
Scenario: Posting a new listing
  Given I am logged in as "MovinMan" 
  When I create a new listing titled "Lots of Boxes" near "49423" 
  And the system processes jobs
  And I browse listings near "49423" 
  Then I can see a listing titled "Lots of Boxes" 
&lt;/pre&gt;

	&lt;p&gt;Which is just implemented as:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;When 'the system processes jobs' do
  Delayed::Job.work_off
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;If you’re just using the default deltas, and not delayed deltas, then you can update the index like this:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;When /^the system updates the index$/ do
  MyModel.sphinx_indexes.first.delta_object.index(MyModel)
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I hope that helps.  Post your suggestions in the comments for improving this.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2009-05-06:13317</id>
    <published>2009-05-06T02:57:00Z</published>
    <updated>2009-05-06T17:02:01Z</updated>
    <category term="Code" />
    <category term="api" />
    <category term="docs" />
    <category term="mac" />
    <category term="rails" />
    <link href="http://opensoul.org/2009/5/6/site-specific-app-for-rails-docs" rel="alternate" type="text/html" />
    <title>Site-specific app for Rails docs</title>
<content type="html">
            &lt;p&gt;Unless you’re a Rails genius, you probably need to frequently reference the Rails &lt;span class="caps"&gt;API&lt;/span&gt; docs. And if you haven’t discovered it yet, &lt;a href="http://railsapi.com"&gt;railsapi.com&lt;/a&gt; is awesome.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://railstips.org"&gt;John Nunemaker&lt;/a&gt; suggested that I create a site-specific browser and point it to a local copy of the docs from &lt;a href="http://railsapi.com"&gt;railsapi.com&lt;/a&gt;.  I did and have been loving it, so I’m suggesting that you do it too.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://fluidapp.com/"&gt;Download Fluid&lt;/a&gt; (or the comparable app for your platform if you’re not on a Mac).  Then download a copy of the docs from &lt;a href="http://railsapi.com"&gt;railsapi.com&lt;/a&gt; and create a new app pointing to that local copy.&lt;/p&gt;


	&lt;p&gt;&lt;/p&gt;


	&lt;p&gt;Better yet, head over to &lt;a href="http://railslogo.com"&gt;railslogo.com&lt;/a&gt; and grab the Creative Commons licensed logo to use as the icon.&lt;/p&gt;


	&lt;p&gt;&lt;/p&gt;


	&lt;p&gt;Now my only complaint is that I don’t have docs for Ruby and other gems in this app, but I have a hunch that it won’t be long until that changes.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2009-04-30:13060</id>
    <published>2009-04-30T01:33:00Z</published>
    <updated>2009-04-30T02:40:53Z</updated>
    <category term="Code" />
    <category term="rails" />
    <category term="search" />
    <category term="sphinx" />
    <link href="http://opensoul.org/2009/4/30/keepin-sphinx-indexes-fresh-2" rel="alternate" type="text/html" />
    <title>Keepin' Sphinx Indexes Fresh</title>
<content type="html">
            &lt;p&gt;&amp;lt;infomercial-voice&amp;gt;Stale indexes got you down? Embarrassed that your users’ searches are coming up empty? Act now and you can avoid stale indexes with &lt;span class="caps"&gt;NEW&lt;/span&gt; and &lt;span class="caps"&gt;IMPROVED&lt;/span&gt; delayed delta indexing!!&amp;lt;/infomercial-voice&amp;gt;&lt;/p&gt;


	&lt;p&gt;Ok, maybe it’s not new and improved. It’s actually &lt;a href="http://groups.google.com/group/thinking-sphinx/browse_thread/thread/af6723f764329a41"&gt;been around since January&lt;/a&gt;, but it’s still awesome. &lt;a href="http://ts.freelancing-gods.com/"&gt;Thinking Sphinx&lt;/a&gt; can use &lt;a href="http://github.com/tobi/delayed_job/tree/master"&gt;delayed_job&lt;/a&gt; to keep indexes fresh.&lt;/p&gt;


	&lt;p&gt;I was slow at jumping on the Sphinx bandwagon for one reason: the index has to be rebuilt to incorporate new data. Delta indexing alleviated some of this by storing frequent changes in a small separate index, but it still had to be occasionally reindexed. It also seemed to only index existing records in my trials with it. New records didn’t ever seem to show up until I rebuilt the whole index.&lt;/p&gt;


	&lt;p&gt;From what I can tell, delayed delta indexing makes everything Just Work™, and here’s how to use it…&lt;/p&gt;


	&lt;p&gt;After you’ve setup &lt;a&gt;ThinkingSphinx&lt;/a&gt;, set the &lt;code&gt;:delayed&lt;/code&gt; property to &lt;code&gt;:delta&lt;/code&gt; in your index:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class Listing &amp;lt; ActiveRecord::Base
  define_index do
    indexes title
    indexes description
    indexes user.login, :as =&amp;gt; :user

    set_property :delta =&amp;gt; :delayed
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The delayed delta support depends on delayed_job, but if you’re using the gem version, it’s already bundled in. I’m using delayed job for some other things in my project, so I still have it installed separately and that seems to be working just fine.&lt;/p&gt;


	&lt;p&gt;delayed_job uses a table to keep track of the jobs that need run, so create a migration containing:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;create_table :delayed_jobs, :force =&amp;gt; true do |table| 
   table.integer  :priority, :default =&amp;gt; 0 
   table.integer  :attempts, :default =&amp;gt; 0 
   table.text     :handler 
   table.string   :last_error 
   table.datetime :run_at 
   table.datetime :locked_at 
   table.datetime :failed_at 
   table.string   :locked_by 
   table.timestamps 
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;And lastly, all you need to do is fire up the worker process:&lt;/p&gt;


&lt;pre&gt;
$ rake thinking_sphinx:delayed_delta
&lt;/pre&gt;

	&lt;p&gt;Now whenever changes are made to your models, the index will be updated moments later. And that’s how you keep it fresh!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2009-04-15:12498</id>
    <published>2009-04-15T00:48:00Z</published>
    <updated>2009-04-15T00:52:42Z</updated>
    <category term="Code" />
    <category term="acts_as_geocodable" />
    <category term="graticule" />
    <category term="rails" />
    <category term="ruby" />
    <category term="search" />
    <category term="sphinx" />
    <link href="http://opensoul.org/2009/4/15/location-based-search-with-sphinx-and-acts_as_geocodable" rel="alternate" type="text/html" />
    <title>Location-based search with Sphinx and acts_as_geocodable</title>
<content type="html">
            &lt;p&gt;&lt;a href="http://www.sphinxsearch.com/"&gt;Sphinx&lt;/a&gt;, everybody’s favorite search engine, has support for location-based search, giving you geo-aware, full-text searching. So now you can find all of the garage sales on Saturday within 20 miles that have LPs and a reel mower.&lt;/p&gt;


	&lt;p&gt;All you need to do is add latitude and longitude (in radians) to the index, allowing you to limit the results to records within a distance of a point. The hardest part is getting the coordinates, but &lt;a href="http://github.com/collectiveidea/acts_as_geocodable"&gt;acts_as_geocodable&lt;/a&gt; makes that really easy.&lt;/p&gt;


	&lt;p&gt;To start, install &lt;a href="http://github.com/collectiveidea/acts_as_geocodable"&gt;acts_as_geocodable&lt;/a&gt;. Once you have that configured properly, install &lt;a href="http://ts.freelancing-gods.com/"&gt;ThinkingSphinx&lt;/a&gt;, define an index on your geocodable model and add the coordinates to the index:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class Listing &amp;lt; ActiveRecord::Base
  acts_as_geocodable

  define_index do
    indexes title
    indexes description

    has geocoding.geocode(:id), :as =&amp;gt; :geocode_id
    has 'RADIANS(geocodes.latitude)', :as =&amp;gt; :latitude, :type =&amp;gt; :float
    has 'RADIANS(geocodes.longitude)', :as =&amp;gt; :longitude, :type =&amp;gt; :float
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The three lines that start with &lt;code&gt;has&lt;/code&gt; add the geocode id, and the latitude and longitude in radians to the index. Our index doesn’t need the geocode id, but we have to add it so that ThinkingSphinx properly joins the geocodes table.&lt;/p&gt;


	&lt;p&gt;After you rebuild the index and start the daemon, you can search for records by location. Here’s an example of taking a zip code from a user and finding all records with in 20 miles. (&lt;strong&gt;Note:&lt;/strong&gt; you will need to grab the latest version, 0.2.9, of Graticule for this next bit of code to work)&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;def search
  location = Geocode.geocoder.locate(params[:zip]).coordinates.map(&amp;amp;:to_radians)
  @listings = Listing.search(params[:q], :geo =&amp;gt; location,
    :with =&amp;gt; {'@geodist' =&amp;gt; 0.0..(20 * 1610.0)})
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;After looking up the coordinates of the zip code that the user entered, we do a search with the &lt;code&gt;:geo&lt;/code&gt; parameter, limiting the results using the special &lt;code&gt;@geodist&lt;/code&gt; condition. We have to pass in a range of floats that represent the distance of the points in meters
(and since the US is in the stone age, I’m converting from miles).&lt;/p&gt;


	&lt;p&gt;That’s all there is to it. Now go write some cool location-based search and comment here about it.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2009-03-06:11438</id>
    <published>2009-03-06T02:57:00Z</published>
    <updated>2009-03-06T02:58:47Z</updated>
    <category term="Code" />
    <category term="cucumber" />
    <category term="facebook" />
    <category term="rails" />
    <category term="testing" />
    <link href="http://opensoul.org/2009/3/6/testing-facebook-with-cucumber" rel="alternate" type="text/html" />
    <title>Testing Facebook with Cucumber</title>
<content type="html">
            &lt;p&gt;For those that haven’t heard: &lt;a href="http://cukes.info"&gt;Cucumber&lt;/a&gt; is pretty much the greatest thing since sliced bread. It dramatically improved the quality and stability of our applications, and the &lt;a href="http://dannorth.net/whats-in-a-story"&gt;outside-in&lt;/a&gt; approach that it encourages forces you to stay focused on what’s important.&lt;/p&gt;


	&lt;p&gt;When we started working on a Facebook application a few months ago, we couldn’t fathom not using Cucumber. So we had to figure out a way to test it.  It took us a few months to evolve it to a point where we could extract it, but this week we &lt;a href="http://github.com/mmangino/facebooker/commit/cad4ef415f297bfd0ed6ab67bf9d11f4d7ce5150"&gt;pushed a change to Facebooker&lt;/a&gt; to make life a little easier. So grab the latest version of Facebooker and keep on reading…&lt;/p&gt;


	&lt;p&gt;First, in &lt;code&gt;features/support/env.rb&lt;/code&gt;, replace the default Rails world with the one in Facebooker:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;# require 'cucumber/rails/world'
require 'facebooker/rails/cucumber'&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;Given I am logged in as a Facebook user&lt;/h3&gt;


	&lt;p&gt;Most of our Facebook application requires that a user be logged in. So most of our scenarios started with “Given I am logged in as a Facebook user”.&lt;/p&gt;


&lt;pre&gt;
Scenario: Uploading a video
  Given I am logged in as a Facebook user
  When I upload a video
  Then I can see a video on my blog
&lt;/pre&gt;

	&lt;p&gt;And here is our implementation for that step:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;Given &amp;quot;I am logged in as a Facebook user&amp;quot; do
  @current_user = User.create! :facebook_id =&amp;gt; 1
  @current_user.facebook_user.friends = [
    Facebooker::User.new(:id =&amp;gt; 2, :name =&amp;gt; 'Bob'),
    Facebooker::User.new(:id =&amp;gt; 3, :name =&amp;gt; 'Sam')
  ]
  @integration_session.default_request_params.merge!(
    :fb_sig_user =&amp;gt; @current_user.facebook_id,
    :fb_sig_friends =&amp;gt; @current_user.facebook_user.friends.map(&amp;amp;:id).join(',')
  )
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Our application has a &lt;code&gt;User&lt;/code&gt; model with a &lt;code&gt;facebook_id&lt;/code&gt; attribute and a &lt;code&gt;#facebook_user&lt;/code&gt; method which returned an instance of &lt;code&gt;Facebooker::User&lt;/code&gt;. Due to how the Facebook session is being mocked, it is important that we set our fake user’s id to 1 for now (I’ll try to figure out a way around this). We also manually add some friends for our application to use.  Lastly, we merge in our user’s id and friend ids into the default request params so that any requests we make include those parameters.&lt;/p&gt;


	&lt;h3&gt;Drop your…canvas&lt;/h3&gt;


	&lt;p&gt;There were some places in our app where requests don’t go through the canvas. For example, we have a few multipart forms, which have to submit directly to your application. To mimic this, wrap webrat calls in &lt;code&gt;#without_canvas&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;When &amp;quot;I upload a video&amp;quot; do
  visit root_path

  without_canvas do
    fill_in 'Title', :with =&amp;gt; 'A video'
    fill_in 'Description', :with =&amp;gt; 'Caption for video'
    attach_file 'Video', &amp;quot;#{RAILS_ROOT}/features/support/sample.mpg&amp;quot;, &amp;quot;video/mpeg&amp;quot;
    click_button 'Upload Video'
  end
  follow_redirect!
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Note that if your action redirects to a &lt;span class="caps"&gt;URL&lt;/span&gt; with &lt;code&gt;:canvas =&amp;gt; true&lt;/code&gt;, webrat will see that as an “external” redirect and won’t follow it. Just call &lt;code&gt;#follow_redirect!&lt;/code&gt; and it’ll go on it’s merry way.&lt;/p&gt;


	&lt;h3&gt;Accessing the Facebook &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/h3&gt;


	&lt;p&gt;Instead of making requests to the Facebook &lt;span class="caps"&gt;API&lt;/span&gt; in your tests, Facebooker will try to read a canned response fixture from &lt;code&gt;features/support/facebook/&lt;/code&gt;. It will give you a friendly error whenever this happens, so just follow the directions and you should be on your way.&lt;/p&gt;


	&lt;h3&gt;Feedback &amp; Patches&lt;/h3&gt;


	&lt;p&gt;I’m sure there are things that don’t work right, so let me know if you run into any troubles. If you have any ideas for making the Cucumber support better, please share them here or on the Facebooker mailing list.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2009-03-04:11375</id>
    <published>2009-03-04T12:00:00Z</published>
    <updated>2009-03-04T01:45:44Z</updated>
    <category term="Code" />
    <category term="ajax" />
    <category term="css" />
    <category term="CSS" />
    <category term="javascript" />
    <link href="http://opensoul.org/2009/3/4/showing-ajax-activity-with-css" rel="alternate" type="text/html" />
    <title>Showing Ajax activity with CSS</title>
<content type="html">
            &lt;p&gt;You know when you have a form that submits with Ajax, and you want to show some type of activity on the form?  There’s several ways to do this, like including a hidden image that you show and hide while there is activity, or inserting and removing an image with javascript.  These all just feel too dirty to me.  I don’t want to have to change the markup just because the form is submitting via Ajax.&lt;/p&gt;


	&lt;p&gt;As usual, there’s a cleaner way to do it with just &lt;span class="caps"&gt;CSS&lt;/span&gt;. I’ve used this simple but effective trick on a couple projects now, so I thought I would share.&lt;/p&gt;


	&lt;p&gt;First, here is a demo of what it looks like: (sorry, you’ll have to leave your feed reader.)&lt;/p&gt;




  &lt;p&gt;&lt;strong&gt;Click the save button.&lt;/strong&gt;&lt;/p&gt;
  &lt;div class="buttons"&gt;
    
    or &lt;a href="#"&gt;Cancel&lt;/a&gt;
  &lt;/div&gt;



  #loading_example {
    margin: 1em 3em;
    padding: 1em;
    border: 4px solid #CCC;
    border-radius: 10px;
    -moz-border-radius: 10px;
    -webkit-border-radius: 10px;
  }
  form.example .buttons { text-align: center; }
  form.example.loading .buttons {
    text-indent: -2000px;
    overflow: hidden;
    background: url(/assets/2009/3/4/loading.gif) no-repeat center center;
  }
  form.example.loading .buttons * { visibility: hidden; }





	&lt;p&gt;This technique is very simple. It adds a class on the form with Javascript while it is loading, and then removes it once it’s done.  The loading class hides the submit button and replaces it with a background image, usually an animated gif.&lt;/p&gt;


	&lt;p&gt;First, with Javascript, add a class to the form while the Ajax request is loading. It would look something like this in Prototype:&lt;/p&gt;


&lt;pre&gt;&lt;code class="javascript"&gt;$('my_form').observe('submit', function(event) {
  event.stop();
  this.request({
    evalScripts: true,
    onLoading:  function() { this.addClassName('loading'); }.bind(this),
    onComplete: function() { this.removeClassName('loading'); }.bind(this)
  });
});&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Next, wrap an element around your buttons or whatever you want to hide.&lt;/p&gt;


&lt;pre&gt;&lt;code class="html"&gt;&amp;lt;form&amp;gt;
  &amp;lt;div class=&amp;quot;buttons&amp;quot;&amp;gt;…&amp;lt;/div&amp;gt;
&amp;lt;/form&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Lastly, there’s just a little &lt;span class="caps"&gt;CSS&lt;/span&gt; to hide buttons and any elements inside them, and set the background image:&lt;/p&gt;


&lt;pre&gt;&lt;code class="css"&gt;form .buttons { text-align: center; }
form.loading .buttons {
  text-indent: -2000px;
  overflow: hidden;
  background: url(../images/loading.gif) no-repeat center center;
}
form.loading .buttons * { visibility: hidden; }&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;There you have it.  It’s really simple, but it’s worked well.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2009-03-03:11371</id>
    <published>2009-03-03T13:33:00Z</published>
    <updated>2009-03-03T13:35:10Z</updated>
    <category term="Code" />
    <category term="rack" />
    <category term="rails" />
    <category term="ruby" />
    <link href="http://opensoul.org/2009/3/3/plugging-rack-into-rails" rel="alternate" type="text/html" />
    <title>Plugging Rack into Rails</title>
<content type="html">
            &lt;p&gt;The interwebs are all a’buzz about &lt;a href="http://rack.rubyforge.org/"&gt;Rack&lt;/a&gt;. For those that haven’t been following along, Rack is a &lt;em&gt;specification&lt;/em&gt; and a &lt;em&gt;library&lt;/em&gt; for connecting web servers to Ruby libraries (a.k.a. “Middleware”). It’s basically the Web 2.0 version of &lt;span class="caps"&gt;CGI&lt;/span&gt;, except that it doesn’t suck and it’s just for Ruby.&lt;/p&gt;


	&lt;p&gt;Rails 2.3 has Rack baked in. It uses Rack for things like sessions and parameter parsing. But what if you want to add your own middleware to a Rails app?&lt;/p&gt;


	&lt;p&gt;It’s really easy! In the &lt;code&gt;init.rb&lt;/code&gt; of a plugin, or just in a Rails initializer:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;ActionController::Dispatcher.middleware.use MyMiddleware&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This will append your middleware to the end of the “stack”, so it will be executed after all of Rails’ middleware, but before anything else in the Rails framework.&lt;/p&gt;


	&lt;p&gt;But what if you need to massage request parameters before Rails parses them? All you need to do is insert your middleware in the stack before Rails parses the params. You can find the current list of middleware by inspecting &lt;code&gt;ActionController::Dispatcher.middleware&lt;/code&gt;.  In there you’ll find &lt;code&gt;ActionController::ParamsParser&lt;/code&gt;, which is what we want to insert our middleware before. Unfortunately, there’s not an &lt;code&gt;insert_before&lt;/code&gt; method (yet), so we’ll need to use &lt;code&gt;insert_after&lt;/code&gt;, giving it a middleware earlier in the stack:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;ActionController::Dispatcher.middleware.insert_after 'ActionController::Failsafe', MyMiddleware&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;If you don’t like the way that one of the existing pieces of middleware handles things, you can swap it out for your own version:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;ActionController::Dispatcher.middleware.swap 'Rails::Rack::Metal', HeavyMetal&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;So there you have it. Eat, drink, and go write middleware.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2009-02-21:11201</id>
    <published>2009-02-21T05:03:00Z</published>
    <updated>2009-02-21T05:06:47Z</updated>
    <category term="Code" />
    <category term="facebook" />
    <category term="rails" />
    <category term="routing" />
    <link href="http://opensoul.org/2009/2/21/force-absolute-urls" rel="alternate" type="text/html" />
    <title>Force Absolute URLs</title>
<content type="html">
            &lt;p&gt;Need to force all URLs in a controller or action to be absolute URLs, but don’t want to use the &lt;code&gt;*_url&lt;/code&gt; named routes or, even worse, &lt;code&gt;:only_path =&amp;gt; false&lt;/code&gt; everywhere?&lt;/p&gt;


	&lt;h3&gt;Background&lt;/h3&gt;


	&lt;p&gt;As we were putting the finishing touches on an awesome Facebook app today (yes I said “awesome” in the same sentence as “facebook app”…you’ll see), we needed to make it so that users can add the app as a tab in their profile. Facebook makes this very easy, but there’s an interesting &lt;del&gt;quirk&lt;/del&gt; &lt;ins&gt;feature&lt;/ins&gt;. From the &lt;a href="http://wiki.developers.facebook.com/index.php/New_Design_Tabbed_Profile"&gt;developer’s wiki&lt;/a&gt;:&lt;/p&gt;


&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Absolute URLs on a tab take the user to your application’s canvas page.&lt;/li&gt;
&lt;li&gt;Relative URLs are treated as if they are relative to your home canvas page and &lt;span class="caps"&gt;AJAX&lt;/span&gt;-loads in the tab.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

	&lt;p&gt;We needed all of the URLs on the page to be absolute so that they would take the user out of the tab and into our application. So we were faced with two options:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Change all of our named routes from &lt;code&gt;*_path&lt;/code&gt; to &lt;code&gt;*_url&lt;/code&gt; and use explicit paths instead of polymorphic urls (you know, that thing that lets you do &lt;code&gt;form_for @model&lt;/code&gt;, or &lt;code&gt;link_to h(@model.name), @model&lt;/code&gt;)&lt;/li&gt;
		&lt;li&gt;Figure out some quick hack that forced Rails to generate absolute URLs on this one page and go on about our lives&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;The page reused a lot of components from all over the site, so we weren’t excited about option 1. And, like all good developers, we were just adverse to that much work.&lt;/p&gt;


	&lt;p&gt;So we started looking for a good fit for option 2. We needed to force &lt;code&gt;:only_path&lt;/code&gt; to be false on any &lt;span class="caps"&gt;URL&lt;/span&gt; generation.  There’s a way to specify &lt;code&gt;default_url_options&lt;/code&gt;, but as the name implies, those are only defaults.  Using the &lt;code&gt;*_path&lt;/code&gt; named routes forces &lt;code&gt;:only_path&lt;/code&gt; to true.&lt;/p&gt;


	&lt;h3&gt;Solution&lt;/h3&gt;


	&lt;p&gt;It turns out, Rails passes all &lt;span class="caps"&gt;URL&lt;/span&gt; generation through a method on your controller called &lt;code&gt;#rewrite_options&lt;/code&gt;. So we just overrode that method to force &lt;code&gt;:only_path&lt;/code&gt; to false on our one action.  Here’s the code we used:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class ContentController &amp;lt; ApplicationController
  # …

  def profile
    # profile action
  end

private
  # Force absolute URLs on the profile tab.
  def rewrite_options(options)
    super(action_name == 'profile' ? options.merge(:only_path =&amp;gt; false) : options)
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;It’s slightly evil, but it worked beautifully.&lt;/p&gt;
          </content>  </entry>
</feed>
