<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>caboose - blog.caboo.se Home</title>
  <id>tag:caboose.org,2008:mephisto/</id>
  <generator version="0.7.3" uri="http://mephistoblog.com">Mephisto Noh-Varr</generator>
  <link href="http://caboose.org/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://caboose.org/" rel="alternate" type="text/html"/>
  <updated>2008-11-15T01:50:43Z</updated>
  <entry xml:base="http://caboose.org/">
    <author>
      <name>Courtenay</name>
    </author>
    <id>tag:caboose.org,2008-11-15:15531</id>
    <published>2008-11-15T00:00:00Z</published>
    <updated>2008-11-15T01:50:43Z</updated>
    <category term="rails"/>
    <category term="ruby"/>
    <category term="git"/>
    <link href="http://caboose.org/articles/2008/11/15/new-plugin-acts_as_git" rel="alternate" type="text/html"/>
    <title>new plugin: acts_as_git</title>
<content type="html">
            &lt;p&gt;With the help of Jamie van Dyke at &lt;a href=&quot;http://parfa.it/&quot;&gt;Parfait&lt;/a&gt; and Scott Chacon at &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;, I'm pleased to announce Acts As Git (no, I don't like the name either).  It's a simple plugin which stores all changes you make to a text field in a git repository.  This is ideal for something like a git-backed wiki.&lt;/p&gt;

&lt;p&gt;Look at it here: &lt;a href=&quot;http://github.com/courtenay/acts_like_git/tree/master&quot;&gt;github&lt;/a&gt; or check it out from&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git://github.com/courtenay/acts_like_git.git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;From the README:&lt;/p&gt;

&lt;p&gt;ALG automagically saves the history of a given text or string field.  It sits over the top of
an ActiveRecord model; after a value is committed to the database, the plugin writes the
new value to a text file and commits it to a git repository.  This way you get all the advantages
of using Git as version-control.&lt;/p&gt;

&lt;p&gt;Usage:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Post &amp;lt; ActiveRecord::Base
  versioning(:title) do |version|
    version.repository = '/home/git/repositories/postal.git'
    version.message = lambda { |post| &quot;Committed by #{post.author.name}&quot; }
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To view the complete list of changes:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; @post = Post.find 15
&amp;lt;Post:15&amp;gt;
&amp;gt;&amp;gt; @post.title
=&amp;gt; 'Freddy'
&amp;gt;&amp;gt; @post.history(:title)
=&amp;gt; ['Joe', 'Frank', 'Freddy]
&amp;gt;&amp;gt; @post.log
=&amp;gt; ['bfec2f69e270d2d02de4e8c7a4eb2bd0f132bdbb', '643deb45c12982dde75ba71657792a2dbdda83e6', 
'1ce6c7368219db7698f4acc3417e656510b4138d']
&amp;gt;&amp;gt; @post.revert_to '1ce6c7368219db7698f4acc3417e656510b4138d'
&amp;gt;&amp;gt; @post.title
=&amp;gt; 'Joe'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It uses the excellent Grit library, and doesn't actually have a checked-out repository.  The latest version of your data is still stored in the database.  You can actually clone this repo and view the changes; pushing back to it won't do anything useful.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://caboose.org/">
    <author>
      <name>Courtenay</name>
    </author>
    <id>tag:caboose.org,2008-11-11:15520</id>
    <published>2008-11-11T01:41:00Z</published>
    <updated>2008-11-11T01:56:24Z</updated>
    <category term="rails"/>
    <category term="ruby"/>
    <link href="http://caboose.org/articles/2008/11/11/plugin-configuration-style" rel="alternate" type="text/html"/>
    <title>Plugin configuration style?</title>
<content type="html">
            &lt;p&gt;I&#8217;m putting the final touches on a super-sweet versioning plugin, and I&#8217;ve discovered that we&#8217;re using several different metaphors for configuring the plugin options.  I&#8217;d like to get some opinions/feedback on your preferred style.&lt;/p&gt;


	&lt;h2&gt;The &lt;span class=&quot;caps&quot;&gt;DSL&lt;/span&gt;&lt;/h2&gt;


	&lt;p&gt;Using a &lt;span class=&quot;caps&quot;&gt;DSL&lt;/span&gt; and passing blocks in which get instance evalled.  I&#8217;m normally very scathing of DSLs; I think that they&#8217;re Yet Another Language for people to learn to use &#8211; it&#8217;s usually your very own write-only syntax &#8211; but it&#8217;s been super-fun implementing the backend to this.&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;class Monkey &amp;lt; ActiveRecord::Base
  versioning do
    author do
      name { user.current.name }
      message { &quot;Commited via #{name}&quot; }
    end
    repository &quot;Joe's DataStore&quot; 
  end&lt;/code&gt;&lt;/pre&gt;


	&lt;h2&gt;Hashes&lt;/h2&gt;


	&lt;p&gt;This seems to be the Rails plugin default:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;class Monkey &amp;lt; ActiveRecord::Base
  versioning :author =&amp;gt; { :name =&amp;gt; lambda{ |u| user.current.name } }, :repository =&amp;gt; &quot;Joe's DataStore&quot; 
end&lt;/code&gt;&lt;/pre&gt;


	&lt;h2&gt;Class vars / methods&lt;/h2&gt;


	&lt;p&gt;Easy to monkeypatch later&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;class Monkey &amp;lt; ActiveRecord::Base
   will_version
   @@version_repository = &quot;Joe's DataStory&quot; 
   def version_author
     current_name
   end
end&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;Are there others? Which do you prefer? Currently I&#8217;m using all three in this one plugin, and it&#8217;s very un-awesome.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://caboose.org/">
    <author>
      <name>Courtenay</name>
    </author>
    <id>tag:caboose.org,2008-11-06:15508</id>
    <published>2008-11-06T20:18:00Z</published>
    <updated>2008-11-06T20:23:29Z</updated>
    <category term="rails"/>
    <category term="ruby"/>
    <category term="testing"/>
    <link href="http://caboose.org/articles/2008/11/6/ripping-out-your-mocks" rel="alternate" type="text/html"/>
    <title>Ripping out your mocks</title>
<content type="html">
            &lt;p&gt;I sat down with David Chelimsky at Rubyconf today to talk about rSpec and an interesting topic came up.&lt;/p&gt;

&lt;p&gt;In my mind, there are two reasons to use a mock object:  first, when you&#8217;re developing TDD style, you physically don&#8217;t have the objects yet; and second, so that you can tightly focus your unit tests.  Maybe, these two different purposes should use a different mechanism.&lt;/p&gt;

&lt;p&gt;His question to me then was, &#8220;Do you replace your mocks with the real objects after you&#8217;ve implemented those objects?&#8221;. I guess I hadn&#8217;t thought about that before.  Do you?  If so, how do you handle the extra complexity, maintaining sane associations and valid data?&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://caboose.org/">
    <author>
      <name>Courtenay</name>
    </author>
    <id>tag:caboose.org,2008-11-04:15454</id>
    <published>2008-11-04T18:33:00Z</published>
    <updated>2008-11-04T07:52:50Z</updated>
    <category term="rails"/>
    <category term="ruby"/>
    <category term="testing"/>
    <link href="http://caboose.org/articles/2008/11/4/on-hiring-rubyists-and-railsers" rel="alternate" type="text/html"/>
    <title>On hiring Rubyists and Railsers</title>
<content type="html">
            &lt;p&gt;We&#8217;re launching a new service &lt;a href=&quot;http://entp.com&quot;&gt;at work&lt;/a&gt; in the next week or so that involves me looking through a lot of job applications: resumes and sample code.  &lt;/p&gt;

&lt;p&gt;I&#8217;d like to tell people right now, upfront, if you&#8217;re applying for a Ruby or Rails job, for anyone, there are a few ways of ensuring you get called back.  They&#8217;re probably fairly simple.&lt;/p&gt;

&lt;p&gt;Send some sample code, maybe a link to a project on &lt;a href=&quot;http://github.com&quot;&gt;Github&lt;/a&gt;, or a snippet of work you&#8217;ve done.  Make sure you send the tests for the code.   Any tests would be good, and you get bonus points for good tests.  If you don&#8217;t have any tests, write them.&lt;/p&gt;

&lt;p&gt;Don&#8217;t worry too much about sending some crazy complex code.  Maybe some polymorphic associations (models), some ajax (views), a knowledge of the whole stack (simple controllers), some nested resources.  Write a simple todo list application.&lt;/p&gt;

&lt;p&gt;It&#8217;s not just a silly philosophy.  Writing tests &#8211; hell, submitting tests with your job application&#8217;s code &#8211; shows that you&#8217;ve actually thought about the code, and that it actually works.  You&#8217;ve permutated and permeated through the logic, actually think about the various ramifications of the design decisions in the code itself.   &lt;/p&gt;

&lt;p&gt;Just the pure act of sending tests with your sample code will put you above 90% of applicants, I promise.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://caboose.org/">
    <author>
      <name>Courtenay</name>
    </author>
    <id>tag:caboose.org,2008-11-04:15453</id>
    <published>2008-11-04T07:32:00Z</published>
    <updated>2008-11-04T07:33:08Z</updated>
    <category term="rails"/>
    <category term="ruby"/>
    <category term="testing"/>
    <link href="http://caboose.org/articles/2008/11/4/we-ve-stopped-using-rspec" rel="alternate" type="text/html"/>
    <title>We've stopped using rSpec ...</title>
<content type="html">
            &lt;p&gt;...for new projects.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/blog.caboo.se/2008/11/4/Picture_12_bigthumb_1.png&quot; alt=&quot;fail&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We upgraded the gems for one of our client projects, and the auto-loading / config.gems managed to completely break all our other projects, requiring upgrades, which caused weird breakages in weird places in some of the specs.  &lt;/p&gt;

&lt;p&gt;The app would refuse to deploy (rake tmp:create failed, because lib/tasks/rspec.rake was being loaded, and spec wasn't installed on the server).  The annoying thing was that just having whatever.11 installed (I don't know the exact version) broke older apps on whatever.4 or whatever.0.2.  .. so those had to be upgraded too.  We wasted a day or two (three, maybe four developers) which equates to several thousand dollars in wasteage.  It was also really infuriating -- the culmination of a few years of frustration of rSpec's weirdnesses.&lt;/p&gt;

&lt;p&gt;After that, I found that some of the specs had never run (who knows why).  It stopped reading spec.opts and started doing some weirdness with pending options.  Finally, Rick just snapped, threw out rSpec and his Model Stubbing library, and now we're playing with a combination of rr, context, and matchy, trying to get a feel for a decent workflow again.  It's sad and maybe a bit exciting to be on the edge.&lt;/p&gt;

&lt;p&gt;What are you testing with?&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://caboose.org/">
    <author>
      <name>Courtenay</name>
    </author>
    <id>tag:caboose.org,2008-09-29:15447</id>
    <published>2008-09-29T21:56:00Z</published>
    <updated>2008-09-29T22:01:32Z</updated>
    <category term="rails"/>
    <category term="sql"/>
    <link href="http://caboose.org/articles/2008/9/29/a-simple-rails-slow-query-logger" rel="alternate" type="text/html"/>
    <title>A simple Rails slow-query logger</title>
<content type="html">
            &lt;p&gt;A few years ago I wrote a simple addition to ActiveRecord that does two things: it chops out the eager loading &quot;t1_t2 AS foo&quot;, and it shows the number of records returned for every query you run against the database.  You can view the file &lt;a href=&quot;http://sample.caboo.se/empty_with_ssl/trunk/lib/ar_extensions.rb&quot;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today I was profiling a site and wanted to quickly find the slow database queries, but didn't have access to mysql's config directly, so I patched that file above to record all queries over 500ms and save it to a log file. I'll warn you now, it ain't pretty, but it works pretty well.&lt;/p&gt;

&lt;p&gt;Here's how it works: First, throw this in  a file in config/initializers.  I open up the rails abstract adapter&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;module ActiveRecord
  module ConnectionAdapters
    class AbstractAdapter
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And add in a new logger.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        def slow_query; 0.5; end # number of seconds
        def slow_query_logger
          @slow_query_logger ||= Logger.new(&quot;log/slow_queries.log&quot;)
        end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ideally of course this would all be configurable.&lt;/p&gt;

&lt;p&gt;Next, I copy the logging code out of the latest ActiveRecord, and patch it to return the number of records.  This is a bit of a hack, too, but we can either look at &quot;num_rows&quot; from the resultset or the actual size of an array.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;              s = result &amp;amp;&amp;amp; (result.respond_to?(:num_rows) ? result.num_rows : \
                 (result.respond_to?(:size) ? result.size : 0)) || 0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, I rewrite the actual log method so that it checks the benchmark against our threshold&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        def log_info(sql, name, runtime, result_size = 0)
          if runtime &amp;gt; slow_query &amp;amp;&amp;amp; slow_query_logger
            slow_query_logger.debug &quot;Slow query: (#{runtime}) [#{result_size}] #{sql}&quot;
          end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And add the number of results to the regular rails log, while snipping out the annoying eager-loading code.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;          if @logger &amp;amp;&amp;amp; @logger.debug?
            if name =~ /Load Including Associations$/
              sql = sql.scan(/SELECT /).to_s + ' ...&amp;lt;snip&amp;gt;... ' + sql.scan(/(FROM .*)$/).to_s
            end

            name = &quot;#{name.nil? ? &quot;SQL&quot; : name} (#{sprintf(&quot;%f&quot;, runtime)}) [#{result_size.to_i}]&quot;
            @logger.debug format_log_entry(name, sql.squeeze(' '))
          end
        end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here's the full file.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;module ActiveRecord
  module ConnectionAdapters # :nodoc:
    class AbstractAdapter
      protected
        # todo: config this
        def slow_query; 0.5; end
        def slow_query_logger
          @slow_query_logger ||= Logger.new(&quot;log/slow_queries.log&quot;)
        end

        alias_method :old_log, :log

        def log(sql, name, &amp;amp;block)
          if block_given?
            #if @logger and @logger.level &amp;lt;= Logger::INFO
              result = nil
              seconds = Benchmark.realtime { result = yield }
              @runtime += seconds
              s = result &amp;amp;&amp;amp; (result.respond_to?(:num_rows) ? result.num_rows : \
                 (result.respond_to?(:size) ? result.size : 0)) || 0 
              log_info(sql, name, seconds, s)
              return result
            #end
          else
            log_info(sql, name, 0, 0)
            nil
          end
          # old_log(sql, name) { yield }
        rescue Exception =&amp;gt; e
          @last_verification = 0
          message = &quot;#{e.class.name}: #{e.message}: #{sql}&quot;
          log_info(message, name, 0)
          raise ActiveRecord::StatementInvalid, message
        end

        alias_method :old_log_info, :log_info
        def log_info(sql, name, runtime, result_size = 0)
          if runtime &amp;gt; slow_query &amp;amp;&amp;amp; slow_query_logger
            slow_query_logger.debug &quot;Slow query: (#{runtime}) [#{result_size}] #{sql}&quot;
          end
          if @logger &amp;amp;&amp;amp; @logger.debug?
            if name =~ /Load Including Associations$/
              sql = sql.scan(/SELECT /).to_s + ' ...&amp;lt;snip&amp;gt;... ' + sql.scan(/(FROM .*)$/).to_s
            end

            name = &quot;#{name.nil? ? &quot;SQL&quot; : name} (#{sprintf(&quot;%f&quot;, runtime)}) [#{result_size.to_i}]&quot;
            @logger.debug format_log_entry(name, sql.squeeze(' '))
          end
        end
      end
    end
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Would this work as a plugin? As a patch to Rails itself?  Or did somebody else already implement a cross-platform slow query logger?&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://caboose.org/">
    <author>
      <name>Courtenay</name>
    </author>
    <id>tag:caboose.org,2008-08-26:15430</id>
    <published>2008-08-26T21:00:00Z</published>
    <updated>2008-08-27T17:51:30Z</updated>
    <category term="rails"/>
    <category term="ruby"/>
    <category term="sql"/>
    <link href="http://caboose.org/articles/2008/8/26/the-awesomest-filter-and-sort-ever" rel="alternate" type="text/html"/>
    <title>The awesomest filter and sort ever</title>
<content type="html">
            &lt;p&gt;Update 2: seems like only one or two people knew about what can_search does :)  I hope we&#8217;re all a little better educated.&lt;/p&gt;

&lt;p&gt;Update: yes, I&#8217;m using these named scopes throughout the app in other places &#8211; they aren&#8217;t used only in this one controller.&lt;/p&gt;

&lt;p&gt;Often you have an index action where you want to sort records, filter by a parameter, and maybe join on some other tables to get a result.
Let&#8217;s say you&#8217;re looking at a videos controller (where videos are &lt;code&gt;acts_as_taggable&lt;/code&gt;) and you want to filter by &lt;code&gt;user_id&lt;/code&gt;, filter by tag name, order by video title, or rating.
Maybe later, you&#8217;ll add a roles (hm:t) association and need to only show videos viewable by a certain user.  How complex!&lt;/p&gt;

&lt;p&gt;To solve this, we&#8217;re going to play with some things you may know, and finish up with a bam! pow! that&#8217;ll take your breath away.&lt;/p&gt;

&lt;p&gt;Rather than build up some form of frankenquery with all sorts of conditionals and cases, joins, and other messing about, let&#8217;s use a brand-new bleeding edge feature of Rails: named scopes.&lt;/p&gt;

&lt;p&gt;First, build up individual named scopes for each axis on which you wish to filter.  Make sure and put the table name in that query.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;

    named_scope :by_user, lambda { |user_id| 
      { :conditions =&gt; ['videos.user_id = ?', user_id] }
    }

    named_scope :tag_name, lambda { |tag_name|
      { :joins =&gt; { :taggable =&gt; :tag },
      { :conditions =&gt; ['tags.name = ?', tag] }
    }

    named_scope :rating, lambda { |rating| 
      { :conditions =&gt; ['ratings_count &gt; ?', rating] }
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;OK, I cheated on the last one, but let&#8217;s assume you have a counter_cache on ratings count.&lt;/p&gt;

&lt;p&gt;Now, if you have more than one scope with joins in it, you&#8217;ll need to apply &lt;a href=&quot;http://rails.lighthouseapp.com/projects/8994/tickets/46-named_scope-should-support-joins&quot;&gt;this patch&lt;/a&gt; to your rails installation, or upgrade past 2.1.1.  This will allow you to have as many joins as you like in your scopes.&lt;/p&gt;

&lt;p&gt;Now, here&#8217;s where the magic happens: in the controller.  Big shout out to protocool for this method.
Let&#8217;s build up a set of all the possible scopes that we might want to use, in an array form like &lt;code&gt;[ named_scope, argument ]&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def index
  scopes = []
  scopes &amp;lt;&amp;lt; [ :by_user, params[:user_id] ] if params[:user_id]
  scopes &amp;lt;&amp;lt; [ :tag_name, params[:tag_name] ] if params[:tag_name]
  scopes &amp;lt;&amp;lt; [ :rating, params[:rating] ] if params[:rating]
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Easy, right?  Very readable.&lt;/p&gt;

&lt;p&gt;How about some ordering?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  order = { 'name' : 'videos.name ASC' }[params[:order]] || 'videos.id DESC'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, as you know, you can chain named scopes.  So you could say &lt;code&gt;Video.by_user(2).tag_name('monkeys')&lt;/code&gt;  Let's take advantage of this, building up a chain of scopes dynamically using 'inject', starting from Video, and adding each scope we added to the array above.  This is really fun magic, because it doesn't run any of the queries until the whole thing is built.  I don't even know how this works, but it does.  Swimmingly.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  @videos = scopes.inject(Video) {|m,v| m.scopes[v[0]].call(m, v[1]) }.paginate(:all, :order =&amp;gt; order)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The final method looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def index
  scopes = []
  scopes &amp;lt;&amp;lt; [ :by_user, params[:user_id] ] if params[:user_id]
  scopes &amp;lt;&amp;lt; [ :tag_name, params[:tag_name] ] if params[:tag_name]
  scopes &amp;lt;&amp;lt; [ :rating, params[:rating] ] if params[:rating]

  order = { 'name' : 'videos.name ASC' }[params[:order]] || 'videos.id DESC'

  @videos = scopes.inject(Video) {|m,v| m.scopes[v[0]].call(m, v[1]) }.paginate(:all, :order =&amp;gt; order, :page =&amp;gt; params[:page])
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;One final caveat. Sometimes :joins doesn&#8217;t know where to get the video id from, so if you&#8217;re using &lt;code&gt;id&lt;/code&gt; in your app, you&#8217;ll need a slight workaround involving manually getting the pagination count, and forcing &lt;code&gt;:select =&amp;gt; &amp;amp;#8216;distinct videos.*&amp;amp;#8217;&lt;/code&gt; in the &lt;code&gt;paginate&lt;/code&gt; call.&lt;/p&gt;

&lt;p&gt;If this works for you, it&#8217;s really easy to add new filtering, ordering, or even scoping to your query. For example, you can add some form of role hackery to your video&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
    named_scope :viewable_by, lambda { |user| 
      { :joins =&gt; { :permissions =&gt; :roles },
        :conditions =&gt; [ &quot;roles.user_id = ? AND permissions.role = ?&quot;, user.id, &quot;view&quot;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Controller, you replace the first scope definition with this&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;scopes = [ :viewable_by, current_user ]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or, you modify the scope inject statement&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
    @videos = scopes.inject(Video.viewable_by(current_user)) { |m,v| ... }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you consider this a giant hack, you&#8217;re probably at least partly right.  However, the alternative in building up a complex query with many possible moving parts is just hideous.  And consider this: you can unit test each part of the query on its own, in the model specs.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://caboose.org/">
    <author>
      <name>Courtenay</name>
    </author>
    <id>tag:caboose.org,2008-08-25:15422</id>
    <published>2008-08-25T11:27:00Z</published>
    <updated>2008-08-25T11:32:09Z</updated>
    <category term="rails"/>
    <category term="ruby"/>
    <link href="http://caboose.org/articles/2008/8/25/sanitize-your-users-html-input" rel="alternate" type="text/html"/>
    <title>Sanitize your users' HTML input</title>
<content type="html">
            &lt;p&gt;The default Rails sanitize helper is actually quite powerful. You can see some of its usage here:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;%= sanitize @article.body, :tags =&amp;gt; %w(table tr td), :attributes =&amp;gt; %w(id class style) %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;However, as the docs say, &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Please note that sanitizing user-provided text does not 
guarantee that the resulting markup is valid.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We were having an issue with users providing bad markup and leaving their tags unclosed.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;This is &amp;lt;a href=&quot;http://foo.com&quot;&amp;gt;my dog&amp;lt;a/&amp;gt; and he&amp;amp;#8217;s super cool!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We solved it by running Hpricot over their input.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;before_save :clean_html
def clean_html
  self.body = Hpricot(body).to_html
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For performance reasons, you should probably run the hpricot and sanitize methods on the way into the database, rather than rendering it in the views, because it&#8217;s somewhat slow, and is a calculation that you only need to perform once.&lt;/p&gt;

&lt;p&gt;In fact, instead of saving it in a callback, you could overload the accessor like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def body=(new_body)
  write_attribute :body, Hpricot(new_body).to_html
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You&#8217;ll want to include the ActionView methods from ActionView::Helpers::SanitizeHelper to get &#8216;sanitize&#8217; available in your model.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://caboose.org/">
    <author>
      <name>Courtenay</name>
    </author>
    <id>tag:caboose.org,2008-08-20:15417</id>
    <published>2008-08-20T20:44:00Z</published>
    <updated>2008-08-20T20:45:39Z</updated>
    <link href="http://caboose.org/articles/2008/8/20/data-migration-tip" rel="alternate" type="text/html"/>
    <title>data migration tip</title>
<content type="html">
            &lt;p&gt;I&#8217;m tracking all the failures that occur in a model, so the users can easily track and resolve them.  The data looks something like this:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
 Failures table

  id | video_id | description
 ----+----------+------------------------
  1  | 5        | Transcoding error
  2  | 23       | Bad file type

 Videos table

  id | name     | creator_id
 ----+----------+------------------------
  5  | Kitten   | 23
  6  | Monkey   | 12
  23 | Elephant | 23    

 &lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;If we want to search for all failures by creator, we have to do a join on Failures and Video.
To make this a little faster, I will denormalize the data a little, by adding a creator_id to failures table, and a callback to the Failure model to set the creator_id field.  This is one of the scaling tradeoffs you need to make: slower writes, slower updates, larger table disk size, faster reads and counts (with grouping).&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;class Failure &amp;lt; ActiveRecord::Base
  before_update :denormalize_creator  
  def denormalize_creator
    self.creator_id = video &#38;&#38; video.creator_id
  end
end&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;This might have some issues depending on if you&#8217;re using #build to generate your Failure object. Regardless..&lt;/p&gt;


	&lt;p&gt;The temptation (for me, anyways) is to create a migration that looks something like this:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;class AddCreatorIdToFailure  ActiveRecord::Migration
  def self.up
    add_column :failures, :creator_id, :integer
    Failure.each do |fail|
      fail.update_attribute :creator_id, fail.video.creator_id
    end
  end
  def self.down
    remove_column :failures, :creator_id
  end
end&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;There are a few things bad with this method.&lt;/p&gt;


	&lt;p&gt;1. You&#8217;re loading all failure objects into memory, then performing a query on each one.
2. If you have thousands of failures, it&#8217;s going to take some time to run. If it gets stopped partway through, you&#8217;ll have to comment out that &#8220;add_column&#8221; line to get it to re-run.&lt;/p&gt;


	&lt;p&gt;So. Step one, move the update to its own migration.  Then, you can re-run it as often as you like.&lt;/p&gt;


	&lt;p&gt;Step two, make the migration a bit smarter. You can do this either by rewriting it in &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt;, or by using something like paginated_each (jfgi).&lt;/p&gt;


	&lt;p&gt;When you do that, it&#8217;s worth throwing some conditions and an include in there. For example,&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;Failure.paginated_each(:order =&amp;gt; &quot;id desc&quot;, :conditions =&amp;gt; &quot;creator_id IS NULL&quot;, :include =&amp;gt; :video) do |fail|
  fail.update_attribute :creator_id, fail.video.creator_id
end&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;You can run this migration as many times as you like (it will only query the records it hasn&#8217;t updated).  Ultimately, though, unless you&#8217;re doing polymorphic associations (which makes the join nigh on impossible), it&#8217;s going to be 10 &#8211; 100x faster (wild guess) doing the update in raw sql.  Any takers on the best &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; for this situation?&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://caboose.org/">
    <author>
      <name>Courtenay</name>
    </author>
    <id>tag:caboose.org,2008-08-15:15415</id>
    <published>2008-08-15T20:35:00Z</published>
    <updated>2008-08-15T20:35:30Z</updated>
    <link href="http://caboose.org/articles/2008/8/15/since-i-don-t-have-anything-of-value-to-post" rel="alternate" type="text/html"/>
    <title>Since I don't have anything of value to post,</title>
<content type="html">
            &lt;p&gt;Here&#8217;s a video of my cat.&lt;/p&gt;

&lt;p&gt;&amp;lt;object height=&quot;344&quot; width=&quot;425&quot;&gt;&amp;lt;param&gt;&amp;lt;/param&gt;&amp;lt;param&gt;&amp;lt;/param&gt;&amp;lt;embed src=&quot;http://www.youtube.com/v/0ssftiRjLaE&amp;amp;amp;hl=en&amp;amp;amp;fs=1&quot; height=&quot;344&quot; width=&quot;425&quot;&gt;&amp;lt;/embed&gt;&amp;lt;/object&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://caboose.org/">
    <author>
      <name>Courtenay</name>
    </author>
    <id>tag:caboose.org,2008-07-19:15404</id>
    <published>2008-07-19T00:39:00Z</published>
    <updated>2008-07-19T01:00:55Z</updated>
    <category term="rails"/>
    <category term="ruby"/>
    <category term="sso"/>
    <link href="http://caboose.org/articles/2008/7/19/authenticate-like-sso-with-activeresource" rel="alternate" type="text/html"/>
    <title>Authenticate like SSO with ActiveResource</title>
<content type="html">
            &lt;p&gt;When you have multiple Rails applications that don&#8217;t share a common database and you want to share the user authentication information &#8211; or rather, use one app to provide authentication for another &#8211; there are a few options. Here&#8217;s how I solved it recently.  This is the simplest way I could think of to get this working.  I couldn&#8217;t find a plugin to do this, so here&#8217;s the result of my pdi.&lt;/p&gt;

&lt;p&gt;Effectively what we&#8217;re doing is separating the user&#8217;s data - their profile info, if you like - from the credentials, and moving the latter to ActiveResource. This is something you should do in your own apps.  Too frequently we stuff a bunch of data (like full name, phone number) into the user model, because it&#8217;s there. A more advanced version of this code might use the &#8216;profile&#8217; as the resource name, updating the local profile with data from remote, and keeping User as a pure credential model.&lt;/p&gt;

&lt;p&gt;Let&#8217;s assume we have App A which will act as the authenticator master.  Our other application, App B, will still hold a User record, but we&#8217;ll override the authenticate method to use ActiveResource.  We&#8217;ll also store some other fields like username and email, and will grab those each time the user logs in.  That way, they can set an auth token in App A and they can login from cookies in app B (provided the cookie domain is shared).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
class User &amp;lt; ActiveRecord::Base

  class Auth &amp;lt; ActiveResource::Base
    self.site = &quot;http://app-a.com&quot;
    self.format = :json
    self.element_name = 'user' # this is the name of the resource in your app
  end

  def self.authenticate(login, password)
    Auth.user = login
    Auth.password = password

    # Authenticating against the app will actually 'prove' the login/pass details.
    # We also want the user's details so we can cache them here.
    authed = Auth.find :first, :params =&gt; { :login =&gt; login }
    return false unless authed

    # Now, pull the data from remote and store it locally.
    user = User.find_or_initialize_by_login(login)
    user.attributes = authed.attributes
    user.save!
    user.activate!
    user

  rescue ActiveResource::ClientError # 406 error -- bad username/password.
    false
  end

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Interestingly enough, find first actually runs the &#8216;index&#8217; action, and returns the first record. &lt;em&gt;sigh&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now, in your App A: users_controller, you want to set up a filter in the index like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
  def index
    if params[:login]
      # for single-sign-on.
      @users = User.find(:all, :conditions =&gt; { :login =&gt; params[:login] })
    else
      @users = User.paginate(:all, :page =&gt; params[:page]) #... 
    end

    respond_to do |format|
      format.html
      format.json { render :json =&gt; @users }
    end
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Do you have a better way of doing this?  &lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://caboose.org/">
    <author>
      <name>Courtenay</name>
    </author>
    <id>tag:caboose.org,2008-07-01:15391</id>
    <published>2008-07-01T00:53:00Z</published>
    <updated>2008-07-01T00:56:42Z</updated>
    <category term="meta"/>
    <link href="http://caboose.org/articles/2008/7/1/all-quiet-on-the-western-front" rel="alternate" type="text/html"/>
    <title>All quiet on the Western Front</title>
<content type="html">
            &lt;p&gt;It&#8217;s been a while since I blogged here.  Mainly, I think it&#8217;s because as I get deep into the daily grind of building other people&#8217;s social apps, I no longer feel like any of the code I&#8217;m writing is worthy of a post. This is not to say that I don&#8217;t love my work, just that maybe the techniques we&#8217;re using aren&#8217;t that special.  (Maybe I&#8217;m wrong. Lots of people at Rails Conf came up to me and said they love reading this blog.)&lt;/p&gt;

&lt;p&gt;So, readers, what content do you want to see on the Caboose blog moving forward?&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://caboose.org/">
    <author>
      <name>Courtenay</name>
    </author>
    <id>tag:caboose.org,2008-05-16:15384</id>
    <published>2008-05-16T19:40:00Z</published>
    <updated>2008-05-16T19:41:22Z</updated>
    <link href="http://caboose.org/articles/2008/5/16/still-got-rooms-at-the-jupiter-for-conference" rel="alternate" type="text/html"/>
    <title>Still got rooms at the Jupiter for conference</title>
<content type="html">
            &lt;p&gt;If you want a discounted room, contact me &lt;em&gt;today&lt;/em&gt;, preferably on irc.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://caboose.org/">
    <author>
      <name>Courtenay</name>
    </author>
    <id>tag:caboose.org,2008-05-07:15379</id>
    <published>2008-05-07T00:23:00Z</published>
    <updated>2008-05-07T00:25:24Z</updated>
    <link href="http://caboose.org/articles/2008/5/7/coming-to-caboose-conf-you-need-to-register" rel="alternate" type="text/html"/>
    <title>Coming to caboose conf? You need to register</title>
<content type="html">
            &lt;p&gt;Your name needs to be on the list, otherwise you won&#8217;t get in.&lt;/p&gt;

&lt;p&gt;&lt;p&gt;Also, you&#8217;ll need to prove your worth, by &lt;a href=&quot;http://rails.lighthouseapp.com/&quot;&gt;submitting&lt;/a&gt; a &lt;a href=&quot;http://github.com/lifo/docrails/tree/master&quot;&gt;documentation patch&lt;/a&gt; to Rails core.  Do that, then sign up here: &lt;a href=&quot;http://register.caboose.org&quot;&gt;http://register.caboose.org&lt;/a&gt;.&lt;p&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://caboose.org/">
    <author>
      <name>Courtenay</name>
    </author>
    <id>tag:caboose.org,2008-05-03:15374</id>
    <published>2008-05-03T19:17:00Z</published>
    <updated>2008-05-03T19:18:51Z</updated>
    <link href="http://caboose.org/articles/2008/5/3/moving-everything-to-github" rel="alternate" type="text/html"/>
    <title>Moving everything to github</title>
<content type="html">
            &lt;p&gt;This is a quick note to inform you that any plugins or code hosted on *.caboo.se will be moving to GitHub very soon.  If I&#8217;m hosting your project, you have about a week to move your code repository, if you haven&#8217;t already.&lt;/p&gt;
          </content>  </entry>
</feed>
