<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US"><title type="text">techno weenie - Home</title><link rel="alternate" type="text/html" href="http://weblog.techno-weenie.net/" /><updated>2008-10-06T04:31:29+00:00</updated><generator uri="http://mephistoblog.com">Mephisto Noh-Varr</generator><id>tag:weblog.techno-weenie.net,2008:mephisto/</id><link rel="self" href="http://feeds.feedburner.com/TechnoWeenie" type="application/atom+xml" /><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><title type="text">Calendar About Nothing</title><link rel="alternate" type="text/html" href="http://weblog.techno-weenie.net/2008/10/6/calendar-about-nothing" /><author><name>rick</name></author><updated>2008-10-05T23:31:29-05:00</updated><id>tag:weblog.techno-weenie.net,2008-10-06:15068</id><content type="html">
            &lt;p&gt;Several months ago, I was listening to one of the &lt;a href='http://odeo.com/channels/2116099-Gitsplosion'&gt;Gitsplosion!&lt;/a&gt; podcasts.  PJ was talking about ant juice, and Chris suggested starting a &lt;a href='http://lifehacker.com/software/motivation/jerry-seinfelds-productivity-secret-281626.php'&gt;seinfeld calendar&lt;/a&gt; to mark your progress on wearing your Github t-shirts every day for a month.  I’d been looking for a cool &lt;a href='http://metaatem.net/2008/05/30/my-railsconf-talk'&gt;microapp&lt;/a&gt; to build for awhile, and thought I could use this calendar idea. However, I have no idea how to confirm if someone is actually wearing a Github shirt, so I decided to scan public &lt;a href='http://github.com'&gt;Github&lt;/a&gt; feeds.&lt;/p&gt;


	&lt;p&gt;After I let my microapp sit around unfinished for several months, &lt;a href='http://warpspire.com'&gt;Kyle&lt;/a&gt; whipped up a basic layout, and I launched the &lt;a href='http://calendaraboutnothing.com/'&gt;Calendar About Nothing&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;I also decided to use various frameworks that are unfamiliar to me: Sinatra, Datamapper, and &lt;span class='caps'&gt;HAML&lt;/span&gt;.  The code itself &lt;a href='http://github.com/entp/seinfeld/tree/master'&gt;isn’t anything special&lt;/a&gt;.  It’s a big hack that’ll hopefully get refactored as time goes on, and more sources get added.  Let me know if you have any ideas of other sources I can check (&lt;a href='http://gitorious.org/'&gt;Gitorious&lt;/a&gt; and &lt;a href='http://www.bitbucket.org/'&gt;bitbucket&lt;/a&gt; spring to mind).  Ideally, you’d be able to take the mythical calendar source &lt;span class='caps'&gt;API&lt;/span&gt; and implement your own private hooks that read private repositories on your own hosted calendars.&lt;/p&gt;
          </content></entry><entry><title type="text">Rails Migrations in Git Branches</title><link rel="alternate" type="text/html" href="http://weblog.techno-weenie.net/2008/3/25/rails-migrations-in-git-branches" /><author><name>rick</name></author><updated>2008-03-24T23:40:26-05:00</updated><id>tag:weblog.techno-weenie.net,2008-03-25:13337</id><content type="html">
            &lt;p&gt;For those of you that don’t &lt;del&gt;stalk&lt;/del&gt; follow my other streams:&lt;/p&gt;


	&lt;h4&gt;&lt;a href='http://github.com/technoweenie/rails_migration_buddy/tree/master'&gt;Migration Buddy&lt;/a&gt;&lt;/h4&gt;


	&lt;p&gt;Or, “the inevitable renumbering and conflict-resolution of miggy tardust”&lt;/p&gt;


	&lt;p&gt;This is a tool to help merge rails branches with conflicting migrations.  The basic
idea goes like this:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;First you migrate down to the migration you were at when you branched.&lt;/li&gt;
		&lt;li&gt;Renumber any new migrations you created that conflict with any new migrations in
  the target branch.&lt;/li&gt;
		&lt;li&gt;Commit the renames.&lt;/li&gt;
		&lt;li&gt;Merge to the target branch (usually ‘master’).&lt;/li&gt;
		&lt;li&gt;Migrate back up.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Wow, what a pain, right?  (Apologies to &lt;a href='http://niggytardust.com/'&gt;Saul Williams&lt;/a&gt;, &lt;a href='http://flickr.com/photos/technoweenie/2358883164/'&gt;you rock&lt;/a&gt;).&lt;/p&gt;


	&lt;p&gt;I keep threatening, but I may have to replace this blog with a combination &lt;a href='http://twitter.com/technoweenie'&gt;twitter&lt;/a&gt; / &lt;a href='http://technoweenie.tumblr.com'&gt;tumblr&lt;/a&gt; / &lt;a href='http://github.com/technoweenie'&gt;github&lt;/a&gt; stream.&lt;/p&gt;
          </content></entry><entry><title type="text">moving to github</title><link rel="alternate" type="text/html" href="http://weblog.techno-weenie.net/2008/3/4/my-gushing-github-love-letter" /><author><name>rick</name></author><updated>2008-03-04T10:37:48-06:00</updated><id>tag:weblog.techno-weenie.net,2008-03-04:13098</id><content type="html">
            &lt;p&gt;I’ve been using git for several months now, waiting for a reason to keep my svn habits around.  So far, it’s been pretty smooth sailing.  There were some squalls along the way as I unlearned some habits from svn though.  I even moved active development of my various open source projects to git.  Well, today I’ve moved most of my “active” (and I say that in the loosest of terms) projects to &lt;a href='http://github.com/technoweenie'&gt;github&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Github is fantastic, but why?.  The core repository browser stuff looks and works great, but is nothing revolutionary, to be honest.  What’s amazing about Github is how it really brings the social aspect into play.  Chris and Tom are showing us all &lt;em&gt;visually&lt;/em&gt; how git development is supposed to work.  I know I personally had some &lt;strong&gt;bing&lt;/strong&gt; moments once I started pulling in commits from external git repos.&lt;/p&gt;


	&lt;p&gt;For what it’s worth, &lt;a href='http://gitorious.org'&gt;Gitorious&lt;/a&gt; is another great community of git hackers.  They’ve also added merge requests to the mix since the last time I looked at it.  The differences with Gitorious are that it’s exclusively geared for open source projects, and that &lt;a href='http://gitorious.org/projects/gitorious'&gt;Gitorious itself is open source&lt;/a&gt;.  That’s wild.&lt;/p&gt;


	&lt;p&gt;The great thing about git is that it doesn’t matter which you choose.  You can easily add a git remote for both, and keep your origin on your own server.  I hope we can see some collaboration between the two in the future.  I know Github has some neat web hooks powering some backend processing functions.  It’d be interesting to be able to initiate fork requests to your git[hub/orious] account by POSTing a public fetch url, or to send a user a pull/merge request by POSTing to a public end point (or emailing a git mailbox).&lt;/p&gt;


	&lt;p&gt;Naturally, as the author of &lt;a href='http://warehouseapp.com'&gt;Warehouse&lt;/a&gt;, I have &lt;em&gt;other&lt;/em&gt; reasons for wanting to see this happen.  I’d like to be able to collaborate with other git hacker networks and keep my data on my own server.  The only way this is possible is if there’s a simple &lt;span class='caps'&gt;API&lt;/span&gt; we can all agree on.&lt;/p&gt;


	&lt;p&gt;At any rate, I firmly believe that fantastic tools like Github and Gitorious will do a lot to drive git adoption.  Having clean, visual tools will go a long way in simplifying git for new users.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt;  Oh yea, I have a couple github invites if anyone wants them.&lt;/p&gt;
          </content></entry><entry><title type="text">Giles is Proud Not to Understand has_many :through</title><link rel="alternate" type="text/html" href="http://weblog.techno-weenie.net/2008/2/13/giles-is-proud-not-to-understand-has_many-through" /><author><name>rick</name></author><updated>2008-02-13T03:43:35-06:00</updated><id>tag:weblog.techno-weenie.net,2008-02-13:12921</id><content type="html">
            &lt;p&gt;Apparently, the number of exception classes related to has_many :through (HM:T) &lt;a href='http://gilesbowkett.blogspot.com/2008/02/im-proud-not-to-understand-hasmany.html'&gt;scared Giles away&lt;/a&gt;.  I think most of them are there because I put the original ones there.  Course, looking at them highlighted does make it seem a bit ridiculous.&lt;/p&gt;


	&lt;p&gt;HM:T associations are the only associations that actually look at other associations to figure out how to query the database.  There aren’t a simple set of conventions to go by that raise simple errors like “couldn’t find the `suspended_users` table”.  If you actually look at the associations, they’re not much more than simple ActiveRecordError subclasses with a custom message.  It gives you nice, helpful messages like this:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
class Post &amp;lt; ActiveRecord::Base
end
class User &amp;lt; ActiveRecord::Base
end
class Topic &amp;lt; ActiveRecord::Base
  has_many :posts
  belongs_to :user
end
class Forum &amp;lt; ActiveRecord::Base
  # commented out bits are things
  # i conveniently 'forgot' in this contrived example.
  #
  # has_many :topics 
  has_many :posts, :through =&amp;gt; :topics
  has_many :creators, :through =&amp;gt; :topics# , :source =&amp;gt; :user
end

Forum.find(:first).posts
# =&amp;gt; ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the association :topics in model Forum

Forum.find(:first).creators
# =&amp;gt; ActiveRecord::HasManyThroughSourceAssociationNotFoundError: Could not find the source association(s) :creator or :creators in model Topic.  Try 'has_many :creators, :through =&amp;gt; :topics, :source =&amp;gt; &amp;lt;name&amp;gt;'.  Is it one of :posts or :user?
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Are the error messages helpful?  I sure think so.  But, do we really need all those exception classes?  Sure, it’ll keep the error messages &lt;span class='caps'&gt;DRY&lt;/span&gt;.&lt;/p&gt;


&lt;div class='thumbnail'&gt;&lt;a href='http://skitch.com/technoweenie/gg1s/associations.rb-lib'&gt;&lt;img src='http://img.skitch.com/20080213-d54pqtibt6t94u8qh7f1yfxhhq.preview.jpg' alt='associations.rb 2014 lib' /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span&gt;Uploaded with &lt;a href='http://plasq.com/'&gt;plasq&lt;/a&gt;’s &lt;a href='http://skitch.com'&gt;Skitch&lt;/a&gt;!&lt;/span&gt;&lt;/div&gt;

	&lt;p&gt;Okay, maybe not.  Is it sufficient to have a single ActiveRecordError class (or even a more specific ActiveRecord::AssociationsError)?  I could definitely do something like this:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
raise ActiveRecord::AssociationsError.new(:has_many, :through_association_not_found, model, reflection)
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Whichever way’s the best, I really don’t think it’s good enough validation to miss out on the feature.  I can point to a few other more complex areas of the associations code (the crazy eager joins code is why I personally haven’t used :include in any of my apps in over a year).&lt;/p&gt;
          </content></entry><entry><title type="text">Timezone awareness in Rails</title><link rel="alternate" type="text/html" href="http://weblog.techno-weenie.net/2008/2/6/timezone-awareness-in-rails" /><author><name>rick</name></author><updated>2008-02-06T12:42:36-06:00</updated><id>tag:weblog.techno-weenie.net,2008-02-06:12805</id><content type="html">
            &lt;p&gt;I just committed &lt;a href='http://dev.rubyonrails.org/changeset/8806'&gt;another piece of the puzzle&lt;/a&gt; to &lt;a href='http://ryandaigle.com/articles/2008/1/25/what-s-new-in-edge-rails-easier-timezones'&gt;Rails’ new time zone support&lt;/a&gt;, coming in Rails 2.1.  This takes a different approach than my &lt;a href='http://svn.rubyonrails.org/rails/plugins/tztime/'&gt;previous attempt&lt;/a&gt; at timezone-aware activerecord attributes. The whole idea behind this approach, is that times appear in the local time zone while you work with them, but are persisted to the database in &lt;span class='caps'&gt;UTC&lt;/span&gt;.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
&amp;gt;&amp;gt; Time.zone = "Pacific Time (US &amp; Canada)" 
&amp;gt;&amp;gt; @status = Status.find :first
&amp;gt;&amp;gt; @status.created_at
=&amp;gt; Tue, 29 Jan 2008 15:30:09 PST -08:00
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;If you set the time, it makes any necessary conversions to your current time zone.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
&amp;gt;&amp;gt; @status.created_at = Time.utc 2008, 1, 1
&amp;gt;&amp;gt; @status.created_at
=&amp;gt; Mon, 31 Dec 2007 16:00:00 PST -08:00
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Multiparameter attributes (say, from a time select box) are changed to the current time zone properly.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
&amp;gt;&amp;gt; @status.attributes = {
?&amp;gt;   "created_at(1i)" =&amp;gt; "2008", "created_at(2i)" =&amp;gt; "1", "created_at(3i)" =&amp;gt; "1", 
?&amp;gt;   "created_at(4i)" =&amp;gt; "0", "created_at(5i)" =&amp;gt; "0", "created_at(6i)" =&amp;gt; "0" }
&amp;gt;&amp;gt; @status.created_at
=&amp;gt; Tue, 01 Jan 2008 00:00:00 PST -08:00
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now in our particular app, it’s very important that each user sets up their own timezone.  The easiest way, we’ve found, is to take the offset from the browser.  This way, the user can move around, hop on a business flight, or play with their system clock, and our app will still function correctly.  First, we set a cookie with the timezone offset:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
Cookie.set({tzoffset: (new Date()).getTimezoneOffset()});
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Then, I wrote a before filter to process this automatically and set the Time.zone value appropriately.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
  # The browsers give the # of minutes that a local time needs to add to
  # make it UTC, while TimeZone expects offsets in seconds to add to 
  # a UTC to make it local.
  def browser_timezone
    return nil if cookies[:tzoffset].blank?
    @browser_timezone ||= begin
      min = cookies[:tzoffset].to_i
      TimeZone[-min.minutes]
    end
  end

  def set_timezone
    if logged_in? &amp;&amp; browser_timezone \
        &amp;&amp; browser_timezone.name != current_user.time_zone
      current_user.update_attribute(:time_zone, browser_timezone.name)
    end
    Time.zone = logged_in? ? current_user.time_zone : browser_timezone
  end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Keep in mind, this does only set the current offset.  The offset doesn’t account for things like &lt;acronym title='Daylight Savings Time'&gt;DST&lt;/acronym&gt;.  However, since this will update on each request, it’ll correct itself once the &lt;span class='caps'&gt;DST&lt;/span&gt; status changes.&lt;/p&gt;


	&lt;p&gt;Huge thanks to &lt;a href='http://mad.ly'&gt;Geoff Buesing&lt;/a&gt;, the mastermind behind this new TimeWithZone implementation.&lt;/p&gt;
          </content></entry><entry><title type="text">Random Rails Tidbits</title><link rel="alternate" type="text/html" href="http://weblog.techno-weenie.net/2008/1/21/random-rails-tidbits" /><author><name>rick</name></author><updated>2008-01-20T23:46:38-06:00</updated><id>tag:weblog.techno-weenie.net,2008-01-21:12638</id><content type="html">
            &lt;p&gt;With &lt;a href='http://dev.rubyonrails.org/changeset/8664'&gt;ActiveSupport::Callbacks being extracted out of ActiveRecord&lt;/a&gt; and &lt;a href='http://dev.rubyonrails.org/ticket/10876'&gt;ActiveSupport::Validations on the way&lt;/a&gt;, it looks like Josh and lifo both did a large chunk of the work I was going to do for ActiveModel.&lt;/p&gt;


	&lt;p&gt;Apparently the &lt;a href='http://www.novemberain.com/2008/1/20/russian-mafia-saves-the-world'&gt;Russian Mafia&lt;/a&gt; is spreading git propaganda and &lt;a href='http://www.novemberain.com/2008/1/17/routes-recognition'&gt;speeding up the Rails routing implementation&lt;/a&gt;.  Bravo!&lt;/p&gt;


	&lt;p&gt;The QuarkRuby folks succeeded in &lt;a href='http://www.quarkruby.com/2008/1/15/activeresource-and-youtube'&gt;hacking ActiveResource to access Youtube videos&lt;/a&gt;.  I think there may be an opportunity to tweak ActiveResource under the hood to make these sorts of plugins easier.&lt;/p&gt;
          </content></entry><entry><title type="text">Benchmarking ActiveDocument vs ActiveRecord</title><link rel="alternate" type="text/html" href="http://weblog.techno-weenie.net/2008/1/14/benchmarking-activedocument-vs-activerecord" /><author><name>rick</name></author><updated>2008-01-14T10:11:14-06:00</updated><id>tag:weblog.techno-weenie.net,2008-01-14:12608</id><content type="html">
            &lt;p&gt;I created a reference rails app with a single controller to benchmark the difference between ActiveRecord and ActiveDocument.&lt;/p&gt;


	&lt;p&gt;First, let’s create some posts to populate the database.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
# ActiveRecord
&amp;gt; script/performance/benchmarker 100 'Importer.run'
            user     system      total        real
#1      2.080000   1.060000   3.140000 (  4.655729)

# ActiveDocument
&amp;gt; script/performance/benchmarker 100 'Importer.run'
            user     system      total        real
#1      2.060000   0.150000   2.210000 ( 28.470869)

# ActiveDocument (json branch)
&amp;gt; script/performance/benchmarker 100 'Importer.run'
            user     system      total        real
#1      2.020000   0.140000   2.160000 ( 27.215934)
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now, let’s retrieve some posts:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
# ActiveRecord
&amp;gt; script/performance/benchmarker 1000 'Post.find(55)'
            user     system      total        real
#1      0.640000   0.050000   0.690000 (  0.685781)

&amp;gt; script/performance/benchmarker 100 'Post.find(:all)'
            user     system      total        real
#1     16.840000   0.080000  16.920000 ( 17.107640)

# ActiveDocument
&amp;gt; script/performance/benchmarker 1000 'Post.find("76d77998-7721-48c6-9ffd-8925efeb8b7e")'
            user     system      total        real
#1      0.490000   0.030000   0.520000 (  0.891832)

&amp;gt; script/performance/benchmarker 100 'Post.find(:all)'
            user     system      total        real
#1      4.860000   0.070000   4.930000 (  8.574478)

# ActiveDocument (json branch)
&amp;gt; script/performance/benchmarker 1000 'Post.find("1b3033bb-7d04-44ff-a1d3-1727d06c603e")'
            user     system      total        real
#1      0.400000   0.030000   0.430000 (  0.820451)

&amp;gt; script/performance/benchmarker 100 'Post.find(:all)'
            user     system      total        real
#1      3.110000   0.060000   3.170000 (  7.097080)
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;It’s still a bit messy since ActiveDocument is still incomplete.  But, you can grab the Battle Royale app I used to test it at:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
git://activereload.net/battleroyale.git
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Oh, and it turns out that I was not the first or second, but fourth or fifth to start this project.  &lt;a href='http://notsostupid.com/'&gt;Sebastian&lt;/a&gt; started a &lt;a href='http://groups.google.com/group/activedocument'&gt;Google group&lt;/a&gt; for all of us.&lt;/p&gt;
          </content></entry><entry><title type="text">ActiveDocument</title><link rel="alternate" type="text/html" href="http://weblog.techno-weenie.net/2008/1/12/activedocument" /><author><name>rick</name></author><updated>2008-01-14T02:12:20-06:00</updated><id>tag:weblog.techno-weenie.net,2008-01-12:12605</id><content type="html">
            &lt;p&gt;This is just a quick post, but I’ve started playing around with &lt;a href='http://code.google.com/p/thrudb/'&gt;thrudb&lt;/a&gt;, and naturally, writing a ruby library for it.  It’s still incredibly rough.  The indexing code is busted since I started testing with a mock manager class instead of the actual thing, so about all it does is saves and fetches records at the moment.&lt;/p&gt;


	&lt;p&gt;You can get the code from:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
git://git.caboo.se/activedocument.git.
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Note:  I have an experimental json branch and a sample app to &lt;a href='http://weblog.techno-weenie.net/2008/1/14/benchmarking-activedocument-vs-activerecord'&gt;pit the 2 data stores against each other&lt;/a&gt;.&lt;/p&gt;
          </content></entry><entry><title type="text">More on Controller Specs, or Fun with Ruby2Ruby</title><link rel="alternate" type="text/html" href="http://weblog.techno-weenie.net/2008/1/10/more-on-controller-specs-or-fun-with-ruby2ruby" /><author><name>rick</name></author><updated>2008-01-10T13:04:15-06:00</updated><id>tag:weblog.techno-weenie.net,2008-01-10:12596</id><content type="html">
            &lt;p&gt;One of the problems with the rspec_on_rails_on_crack (git://activereload.net/rspec_on_rails_on_crack.git) was that the redirection examples had horrible descriptions.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;describe FooController, "GET /index" do
  it_redirects_to { foo_path }
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The route goes in a ruby proc because routes aren’t available from the context of the example group.  They’re only available from inside a running example.  But this is what the description looks like when running &lt;code&gt;rake spec:doc&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;FooController GET #index
  - redirects to #&amp;lt;Proc:0x0224e7d8@./spec/controllers/foo_controller_spec.rb:68&amp;gt;&lt;/pre&gt;

	&lt;p&gt;Solution?  Install the ParseTree and ruby2ruby gems and add this to #it_redirects_to:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;route.to_ruby.gsub(/(^proc \{)|(\}$)/, '').strip&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;FooController GET #edit
- redirects to "foo_path(1)"&lt;/pre&gt;
          </content></entry><entry><title type="text">Controller specs are a drag</title><link rel="alternate" type="text/html" href="http://weblog.techno-weenie.net/2007/12/26/controller-specs-are-a-drag" /><author><name>rick</name></author><updated>2007-12-26T11:30:30-06:00</updated><id>tag:weblog.techno-weenie.net,2007-12-26:12529</id><content type="html">
            &lt;p&gt;Ever since Jamis &lt;a href='http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model'&gt;taught us about fat models and skinny controllers&lt;/a&gt;, the controller’s importance has dipped a bit (for the best).  Controllers should only be testing the basic things, such as the fact that it’s using the params correctly to retrieve and create records, and returning the right response.  Any more details about the model are usually exercised in model specs.  This can make the examples incredibly repetitive:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
it "should set @records when accessing GET /index" do
  get :index
  assigns[:records].should_not be_nil
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;ul&gt;
	&lt;li&gt;For those not using rspec, you can pretty much replace ‘spec’ with ‘test case’ and ‘example’ with ‘test’.  It’s all the same, really.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Rspec tends to encourage that the controller examples be broken up into finer contexts, such as by action.  (You can do this with test/unit of course, but it’s not nearly as common).  You’re also encouraged to keep to a “single assertion per example” discipline.  This way if one assertion fails, the other assertions are still run in other examples.  Good practice to follow, but it results in a lot of extra time spent writing more spec examples.  Here’s what I came up with: &lt;a href='http://git.caboo.se/?p=altered_beast.git;a=blob;f=spec/controllers/forums_controller_spec.rb;h=6d92e80600049f511005a87675a4dad173d4651b;hb=923a33cbc82235b1f1e0c05637f68f9746bda842'&gt;(old and busted)&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;While soliciting for comments, &lt;a href='http://yehudakatz.com/'&gt;Yehuda Katz&lt;/a&gt; scoffed at all the repetition.  Not that I blamed him, it seemed rather silly to write 560 lines of spec code for a &lt;a href='http://git.caboo.se/?p=altered_beast.git;a=blob;f=app/controllers/forums_controller.rb;h=8746a2e93de361101209c21e9cb9fffff2ddb6cb;hb=HEAD'&gt;90 &lt;span class='caps'&gt;LOC&lt;/span&gt; controller&lt;/a&gt;. We swapped ideas back and forth and wondered if there was some way to define meta spec examples to ease the controller speccing process.  Here’s the basic outline we came up with:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
it.assigns :forum, :flash =&amp;gt; {:notice =&amp;gt; :not_nil}
it.redirects_to { forum_path(@forum) }
it.renders :template, :index
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;As you can see, I managed to cut the &lt;a href='http://git.caboo.se/?p=altered_beast.git;a=blob;f=spec/controllers/forums_controller_spec.rb;h=6d93c71e6d95f2b0883f7d2e6994784babfe92fa;hb=HEAD'&gt;controller spec&lt;/a&gt; &lt;em&gt;in half&lt;/em&gt;, with this &lt;a href='http://git.caboo.se/?p=altered_beast.git;a=tree;f=vendor/plugins/rspec_on_rails_on_crack/lib;h=62b5fe1ccad8186a989f5d72dd218f3678fae518;hb=HEAD'&gt;new hotness&lt;/a&gt;.  There are a few minor things there to contribute to back to rails and rspec.  Yehuda mentioned he was going go implement the same &lt;span class='caps'&gt;API&lt;/span&gt; for the merb testing harness.  Any thoughts on this approach?&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: fixed a textile error around the “90 &lt;span class='caps'&gt;LOC&lt;/span&gt;…” link.  Also, moved this to its own git repository: git://activereload.net/rspec_on_rails_on_crack.git.  I also made a quick custom_scaffold generator in git://activereload.net/custom_scaffold.git.&lt;/p&gt;
          </content></entry><entry><title type="text">Moving to git</title><link rel="alternate" type="text/html" href="http://weblog.techno-weenie.net/2007/12/25/moving-to-git" /><author><name>rick</name></author><updated>2007-12-26T11:24:52-06:00</updated><id>tag:weblog.techno-weenie.net,2007-12-25:12522</id><content type="html">
            &lt;p&gt;Ever since starting my latest client project a few months ago, I’ve started using git.  I had the fortune to be trained by a couple &lt;a href='http://eagain.net/blog/'&gt;git&lt;/a&gt; &lt;a href='http://scie.nti.st'&gt;badasses&lt;/a&gt;, so it was a pretty smooth transition.  At some point, I figured it was time to start porting my own open source projects to git, while keeping the svn repositories current.  Here’s a rakefile I worked up to move my own plugins in one command:&lt;/p&gt;


&lt;table class='CodeRay'&gt;&lt;tr&gt;
  &lt;td title='click to toggle' class='line_numbers'&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class='code'&gt;&lt;pre&gt;&lt;span class='c'&gt;# imports all dirs in given SVN dir as a separate git repo in the current directory&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class='c'&gt;# pass SERVER= to specify a remote git server.  it'll add it as a remote for origin and push master:refs/heads/master&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;task &lt;span class='sy'&gt;:fetch_plugins&lt;/span&gt; &lt;span class='r'&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  raise &lt;span class='s'&gt;&lt;span class='dl'&gt;&amp;quot;&lt;/span&gt;&lt;span class='k'&gt;need svn repo in SVN env var&lt;/span&gt;&lt;span class='dl'&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class='r'&gt;if&lt;/span&gt; &lt;span class='co'&gt;ENV&lt;/span&gt;[&lt;span class='s'&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;span class='k'&gt;SVN&lt;/span&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;/span&gt;].nil?&lt;tt&gt;
&lt;/tt&gt;  &lt;span class='co'&gt;ENV&lt;/span&gt;[&lt;span class='s'&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;span class='k'&gt;GIT&lt;/span&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;/span&gt;] ||= &lt;span class='s'&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;span class='k'&gt;git&lt;/span&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  repos = &lt;span class='sh'&gt;&lt;span class='dl'&gt;%x{&lt;/span&gt;&lt;span class='k'&gt;svn ls &lt;/span&gt;&lt;span class='il'&gt;&lt;span class='dl'&gt;#{&lt;/span&gt;&lt;span class='co'&gt;ENV&lt;/span&gt;[&lt;span class='s'&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;span class='k'&gt;SVN&lt;/span&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class='dl'&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class='dl'&gt;}&lt;/span&gt;&lt;/span&gt;.split&lt;tt&gt;
&lt;/tt&gt;  repos.each &lt;span class='r'&gt;do&lt;/span&gt; |repo|&lt;tt&gt;
&lt;/tt&gt;    &lt;span class='r'&gt;next&lt;/span&gt; &lt;span class='r'&gt;unless&lt;/span&gt; repo =~ &lt;span class='rx'&gt;&lt;span class='dl'&gt;/&lt;/span&gt;&lt;span class='ch'&gt;\/&lt;/span&gt;&lt;span class='k'&gt;$&lt;/span&gt;&lt;span class='dl'&gt;/&lt;/span&gt;&lt;/span&gt; &amp;amp;&amp;amp; !&lt;span class='co'&gt;File&lt;/span&gt;.exist?(repo)&lt;tt&gt;
&lt;/tt&gt;    repo.gsub! &lt;span class='rx'&gt;&lt;span class='dl'&gt;/&lt;/span&gt;&lt;span class='ch'&gt;\/&lt;/span&gt;&lt;span class='k'&gt;$&lt;/span&gt;&lt;span class='dl'&gt;/&lt;/span&gt;&lt;/span&gt;, &lt;span class='s'&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class='co'&gt;FileUtils&lt;/span&gt;.mkdir_p repo&lt;tt&gt;
&lt;/tt&gt;    error = &lt;span class='pc'&gt;false&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class='co'&gt;Dir&lt;/span&gt;.chdir repo &lt;span class='r'&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class='r'&gt;begin&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        puts &lt;span class='s'&gt;&lt;span class='dl'&gt;&amp;quot;&lt;/span&gt;&lt;span class='k'&gt;initializing &lt;/span&gt;&lt;span class='il'&gt;&lt;span class='dl'&gt;#{&lt;/span&gt;repo&lt;span class='dl'&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class='k'&gt;...&lt;/span&gt;&lt;span class='dl'&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class='sh'&gt;&lt;span class='dl'&gt;%x{&lt;/span&gt;&lt;span class='k'&gt;git svn init &lt;/span&gt;&lt;span class='il'&gt;&lt;span class='dl'&gt;#{&lt;/span&gt;&lt;span class='co'&gt;ENV&lt;/span&gt;[&lt;span class='s'&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;span class='k'&gt;SVN&lt;/span&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class='dl'&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class='k'&gt;/&lt;/span&gt;&lt;span class='il'&gt;&lt;span class='dl'&gt;#{&lt;/span&gt;repo&lt;span class='dl'&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class='dl'&gt;}&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        puts &lt;span class='sh'&gt;&lt;span class='dl'&gt;%x{&lt;/span&gt;&lt;span class='k'&gt;git svn fetch&lt;/span&gt;&lt;span class='dl'&gt;}&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class='r'&gt;if&lt;/span&gt; &lt;span class='co'&gt;ENV&lt;/span&gt;[&lt;span class='s'&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;span class='k'&gt;SERVER&lt;/span&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;          puts &lt;span class='sh'&gt;&lt;span class='dl'&gt;%x{&lt;/span&gt;&lt;span class='k'&gt;git remote add origin &lt;/span&gt;&lt;span class='il'&gt;&lt;span class='dl'&gt;#{&lt;/span&gt;&lt;span class='co'&gt;ENV&lt;/span&gt;[&lt;span class='s'&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;span class='k'&gt;GIT&lt;/span&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class='dl'&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class='k'&gt;@&lt;/span&gt;&lt;span class='il'&gt;&lt;span class='dl'&gt;#{&lt;/span&gt;&lt;span class='co'&gt;ENV&lt;/span&gt;[&lt;span class='s'&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;span class='k'&gt;SERVER&lt;/span&gt;&lt;span class='dl'&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class='dl'&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='il'&gt;&lt;span class='dl'&gt;#{&lt;/span&gt;repo&lt;span class='dl'&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class='k'&gt;.git&lt;/span&gt;&lt;span class='dl'&gt;}&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;          puts &lt;span class='sh'&gt;&lt;span class='dl'&gt;%x{&lt;/span&gt;&lt;span class='k'&gt;git push origin master:refs/heads/master&lt;/span&gt;&lt;span class='dl'&gt;}&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;          puts &lt;span class='sh'&gt;&lt;span class='dl'&gt;%x{&lt;/span&gt;&lt;span class='k'&gt;git config branch.master.remote 'origin'&lt;/span&gt;&lt;span class='dl'&gt;}&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;          puts &lt;span class='sh'&gt;&lt;span class='dl'&gt;%x{&lt;/span&gt;&lt;span class='k'&gt;git config branch.master.merge 'refs/heads/master'&lt;/span&gt;&lt;span class='dl'&gt;}&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class='r'&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class='r'&gt;rescue&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        error = &lt;span class='gv'&gt;$!&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class='r'&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class='r'&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class='r'&gt;if&lt;/span&gt; error&lt;tt&gt;
&lt;/tt&gt;      &lt;span class='co'&gt;FileUtils&lt;/span&gt;.rm_rf repo&lt;tt&gt;
&lt;/tt&gt;      puts &lt;span class='s'&gt;&lt;span class='dl'&gt;&amp;quot;&lt;/span&gt;&lt;span class='k'&gt;removing &lt;/span&gt;&lt;span class='il'&gt;&lt;span class='dl'&gt;#{&lt;/span&gt;repo&lt;span class='dl'&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class='k'&gt;: &lt;/span&gt;&lt;span class='il'&gt;&lt;span class='dl'&gt;#{&lt;/span&gt;error.inspect&lt;span class='dl'&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class='dl'&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class='r'&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class='r'&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class='r'&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;If you read through, it does these basic commands:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
mkdir pluginname
cd pluginname
git svn init http://pluginurl
git svn fetch
# get some coffee
git remote add origin git@server:pluginname.git
git config branch.master.remote 'origin'
git config branch.master.merge 'refs/heads/master'
git push origin master:refs/heads/master
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The last command pushes the local master branch to a master branch on the remote git server.  Once that’s done,  you should be able to git push/pull without issues.  However, there’s something missing from the .git/config file, and in my git newbieness, I have no idea how else to fix:  &lt;strong&gt;Update&lt;/strong&gt; – I know how to fix this now.  See the git config commands in the rake task.  No more need to modify .git/config manually.&lt;/p&gt;


&lt;pre&gt;[branch "master"]
        remote = origin
        merge = refs/heads/master&lt;/pre&gt;

	&lt;p&gt;You can setup &lt;a href='http://scie.nti.st/2007/11/14/hosting-git-repositories-the-easy-and-secure-way'&gt;gitosis&lt;/a&gt; on the server to manage the repos.  It’s a brilliant piece of software that uses a single ‘git’ user account and public keys to manage access to various repos.  The only issue I had with the config file though, was that it required a [repo] entry for every plugin to enable git daemon access.  Here’s what I mean:&lt;/p&gt;


&lt;pre&gt;[group activereload]
writable = gitosis-admin lighthouse warehouse darkroom
members = caged rick

[group mephisto]
writable = mephisto
members = imajes psq svenfuchs caged rick

# enable gitweb 
[repo mephisto]
daemon = yes
&lt;/pre&gt;

	&lt;p&gt;You now clone mephisto and the &lt;a href='http://activereload.net/plugins/'&gt;rest of my open source projects&lt;/a&gt; with a command like “git clone git://activereload.net/mephisto.git”.&lt;/p&gt;


	&lt;p&gt;Oh, and merry christmas and all that.  I didn’t really intend for this to be “one of those” posts.  I’m just having some problems going back to sleep after playing santa (putting out presents, eating the cookies, etc).&lt;/p&gt;
          </content></entry><entry><title type="text">Adventures in Rails Debugging</title><link rel="alternate" type="text/html" href="http://weblog.techno-weenie.net/2007/12/19/adventures-in-rails-debugging" /><author><name>rick</name></author><updated>2007-12-18T19:45:08-06:00</updated><id>tag:weblog.techno-weenie.net,2007-12-19:12204</id><content type="html">
            &lt;p&gt;After upgrading my app to Rails 2.0, I started getting an error, but &lt;em&gt;only&lt;/em&gt; when running a rake task (such as rake db:migrate).&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
$ rake db:migrate --trace
(in /Users/rick/p/lighthouse/trunk)
** Invoke db:migrate (first_time)
** Invoke environment (first_time)
** Execute environment
rake aborted!
uninitialized constant Technoweenie::ActiveRecordContext
/Users/rick/p/lighthouse/trunk/vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:266:in `load_missing_constant'
/Users/rick/p/lighthouse/trunk/vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:453:in `const_missing'
/Users/rick/p/lighthouse/trunk/vendor/plugins/active_record_context/init.rb:1:in `evaluate_init_rb'
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;So, it’s failing on the first line of my active_record_context’s init.rb file:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;ActiveRecord::Base.send :include, Technoweenie::ActiveRecordContext&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Where’s the require?  I leave it out, relying on ActiveSupport::Dependencies to auto-load the module for me.  But, it seems to be failing me in my rake tasks.  The fact that it’s working when I run script/server or script/console makes me think it’s some wacky &lt;span class='caps'&gt;LOAD&lt;/span&gt;_PATH issue.  So, I try this in the init.rb file:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;puts $LOAD_PATH.inspect
puts Dependencies.load_paths.inspect
ActiveRecord::Base.send :include, Technoweenie::ActiveRecordContext&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Running both my rake task and script/console don’t show any differences, so that’s a dead end.  Next, I turn my attention to Dependencies.  The first stack trace showed it failing on line 266 in Dependencies.load_missing_constant.  Above the &lt;a href='http://dev.rubyonrails.org/browser/trunk/activesupport/lib/active_support/dependencies.rb#L242'&gt;large if statement&lt;/a&gt; seems like a good spot for some debugging.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;$ rdebug `which rake` db:migrate -n -- --trace&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Here are some interesting variables:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;qualified_name – “Technoweenie::ActiveRecordContext” &lt;/li&gt;
		&lt;li&gt;path_suffix – “technoweenie::active_record_context”&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;That doesn’t look like a normal path, String#underscore should be converting :: to /.   Next, I run this in script/server (script/console has no switch to enable the debugger).&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;$ script/server -u&lt;/code&gt;&lt;/pre&gt;

	&lt;ul&gt;
	&lt;li&gt;qualified_name – “Technoweenie::ActiveRecordContext” &lt;/li&gt;
		&lt;li&gt;path_suffix – “technoweenie/active_record_context”&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;So, something is messing with String#underscore, but only when rake runs.  Interesting…  I then do a grep of my vendor directory, looking for ‘def underscore’ and find 3 locations:  ActiveSupport, &lt;a href='http://rubyforge.org/forum/forum.php?forum_id=19781'&gt;bj&lt;/a&gt;, and &lt;a href='http://amazon.rubyforge.org'&gt;&lt;span class='caps'&gt;AWS&lt;/span&gt;::S3&lt;/a&gt;.  bj managed to copy ActiveSupport’s version of the method exactly, but S3 left out the part that converts :: to /:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
  # ActiveSupport adds an underscore method to String so let's just use that one if
  # we find that the method is already defined
  def underscore
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    downcase
  end unless public_method_defined? :underscore
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;So, &lt;span class='caps'&gt;AWS&lt;/span&gt;::S3 only adds that method if ActiveSupport isn’t available.  Looking at ‘String.included_modules’ while debugging does list ‘ActiveSupport::CoreExtensions::String::Inflections’, so it’s looking like &lt;span class='caps'&gt;AWS&lt;/span&gt;::S3 is loading before ActiveSupport somehow.&lt;/p&gt;


	&lt;p&gt;Then it hits me, I’m loading it in a rake task!  Doh…&lt;/p&gt;
          </content></entry><entry><title type="text">Go Daddy Assumes 850,000 RegisterFly Domains</title><link rel="alternate" type="text/html" href="http://weblog.techno-weenie.net/2007/5/29/go-daddy-assumes-850-000-registerfly-domains" /><author><name>rick</name></author><updated>2007-05-29T14:19:36-05:00</updated><id>tag:weblog.techno-weenie.net,2007-05-29:8014</id><content type="html">
            &lt;p&gt;&lt;a href='http://news.netcraft.com/archives/2007/05/29/go_daddy_assumes_850000_registerfly_domains.html'&gt;Yay&lt;/a&gt;.&lt;/p&gt;
          </content></entry><entry><title type="text">High profile Beast usage, and Joyent Slingshot ports</title><link rel="alternate" type="text/html" href="http://weblog.techno-weenie.net/2007/5/5/high-profile-beast-usage-and-joyent-slingshot-ports" /><author><name>rick</name></author><updated>2007-05-04T19:27:59-05:00</updated><id>tag:weblog.techno-weenie.net,2007-05-05:7914</id><content type="html">
            &lt;p&gt;Joyent made their &lt;a href='http://joyeur.com/2007/05/01/slingshot-public-release'&gt;public release of Slingshot&lt;/a&gt; recently, along with a &lt;a href='http://developers.joyent.com/wiki/SlingshotPortContest'&gt;Slingshot Port contest&lt;/a&gt; to go with it.  Two of the listed entries include &lt;a href='http://developers.joyent.com/wiki/ProjectInferno'&gt;Inferno&lt;/a&gt;, a Mephisto port, and &lt;a href='http://developers.joyent.com/wiki/ProjectBrute'&gt;Brute&lt;/a&gt;, a Beast port.  Good luck to both entrants!&lt;/p&gt;


	&lt;p&gt;Today, Matt at 37signals posted a &lt;a href='http://www.37signals.com/svn/posts/392-design-decisions-new-forums-at-basecamp-and-highrise'&gt;Design Decisions article&lt;/a&gt; about the move from punBB to Beast.  I love seeing Beast in action.&lt;/p&gt;
          </content></entry><entry><title type="text">Where did rick go?</title><link rel="alternate" type="text/html" href="http://weblog.techno-weenie.net/2007/5/1/where-did-rick-go" /><author><name>rick</name></author><updated>2007-05-01T12:22:11-05:00</updated><id>tag:weblog.techno-weenie.net,2007-05-01:7885</id><content type="html">
            &lt;p&gt;I’m finding it difficult to come up with a use for this blog.  Most of my work is spent on client work or Lighthouse, so therefore my rails based blogging is at the &lt;a href='http://activereload.net/blog'&gt;Active Reload blog&lt;/a&gt;.  Mephisto has its &lt;a href='http://mephistoblog.com/'&gt;own blog&lt;/a&gt; of course, but a fair amount of you still can’t access it (Registerfly has my domains locked and untransferrable, I may have to bite the bullet and buy a new name.).&lt;/p&gt;


	&lt;p&gt;I’m also having a lot of fun with &lt;a href='http://technoweenie.tumblr.com/'&gt;my tumblr&lt;/a&gt;.  Even though I can technically do everything there in Mephisto, Tumblr provides a nice, focused interface for tumbling.  I’ve pretty much ceased my twitter activity lately, I can’t imagine it was anything exciting to read.  I’d like to turn this blog into more of a dashboard with various feeds for my &lt;span class='caps'&gt;OSS&lt;/span&gt; projects and blogs.  It’d give me a chance to beef up that aspect of Mephisto as well…&lt;/p&gt;


	&lt;p&gt;As for offline activities, I’m teaching my son to be a Guitar Hero and getting him prepped for kindergarten graduation (don’t ask).&lt;/p&gt;
          </content></entry></feed>
