Tracking Changes in Git

I've always heard people refer to creating 'tracking branches' but never really knew how to set one up. I think I've figured it out - here's my current workflow:

  $ git clone my_git_repo
  $ git remote add other_source other_git_repo
  $ git fetch other_source
  $ git branch --track other_source_master other_source/master

Once I have that set up, I can integrate others' changes:

  $ git checkout master
  $ git checkout -b merge_area
  $ git merge other_source_master

Any time I want to pull upstream changes from the other remote source:

  $ git checkout other_source_master
  $ git pull

Unit Testing Your ApplicationController

Do it!

class ApplicationControllerTest < ActiveSupport::TestCase
  context "An instance of ApplicationController" do

    setup { @controller = ApplicationController.new }

    should "return nil when there is no :user_id in session" do
      @controller.stubs(:session).returns({})
      assert_nil @controller.current_user
    end

    should "retrieve the current user when there is a :user_id in session" do
      user = Factory(:user)
      @controller.stubs(:session).returns({:user_id => user.id})

      assert_equal user, @controller.current_user
    end

    should "return nil when the :user_id in session can't be found in the database" do
      @controller.stubs(:session).returns(:user_id => 1)

      assert_nil @controller.current_user
    end

  end
end

Setting Session Data the Old-School Way

Rails provides an easy way to send session data in functional tests when accessing an action (the 3rd parameter is session data):

  get :index, {}, {:user_id => 1}

As you add to your functional test suite, this becomes quite tedious and doesn't play well with tools like Shoulda. Here's where doing it the old-school way helps:

context "A GET to :index" do
  context "as a logged-in user" do
    setup do
      @request.session[:user_id] = Factory(:user)
      get :index
    end

    should_assign_to :messages      
    should_render_template 'index'
  end
end

Thanks to Matt for giving me a hand with this today.

Overwriting "Constants"

In Ruby, constants aren't the same as in other languages since you can change them at runtime. This code:

ENDPOINT_URL = 'http://mysubdomain.unfuddle.com/api/v1/'
ENDPOINT_URL = 'http://othersubdomain.unfuddle.com/api/v1/'
puts ENDPOINT_URL

produces this output (including the warning):

warning: already initialized constant ENDPOINT_URL
http://othersubdomain.unfuddle.com/api/v1/

If you need to override a constant and don't want to trigger a warning (in a test environment, for example) you can use the replace method:

ENDPOINT_URL = 'http://mysubdomain.unfuddle.com/api/v1/'
ENDPOINT_URL.replace 'http://othersubdomain.unfuddle.com/api/v1/'
puts ENDPOINT_URL

This will only work with those objects that have a replace method defined (e.g. Array, Hash, and String) and the new value must have the same datatype.

The Inevitable MySQL Gem Install

Got your new box all set up? Let's do some Rails:

$ rake db:create
!!! The bundled mysql.rb driver has been removed from Rails 2.2. Please 
install the mysql gem and try again: gem install mysql.

rake aborted!
no such file to load -- mysql

If you're on Ubuntu, do this:

$ sudo apt-get install libmysqlclient15-dev 
$ which mysql_config
/usr/bin/mysql_config

$ sudo gem install mysql -- --with-mysql-config=/usr/bin/mysql_config
Building native extensions.  This could take a while...
Successfully installed mysql-2.7
1 gem installed

If you're running on OSX and have installed mysql from MacPorts, mysql_config is already installed:

$ sudo gem install mysql -- --with-mysql-config=/opt/local/bin/mysql_config5

Done.

Fun With Association Proxies

Not only are tags great, they're a requirement of Web 2.0 (read the handbook). Here's a quick way to pull out those tags in a meaningful way:

class Post < ActiveRecord::Base
  has_many :taggings
  has_many :tags, :through => :taggings do
    def to_s
      self.map(&:name).join(', ')
    end
  end
end

Now, calling @post.tags.to_s will return the list of tag names separated by commas. The real magic is when you do this:

puts "#{@post.tags}"

Dot-Underscore Hell

A frustrating situation courtesy of OSX and mounted drives (over SMB in this case):

linux-host$ svn status
?      site/actions/._contact.php
M      site/actions/contact.php
?      site/conf/._controller-config.ini
?      site/conf/._nav-config.php
M      site/conf/nav-config.php
?      site/templates/._contact.php
M      site/templates/contact.php

Luckily, there's a command for that (OSX Leopard):

mac$ dot_clean .
linux-host$ svn status
M      site/actions/contact.php
M      site/conf/nav-config.php
M      site/templates/contact.php

See man dot_clean for more information. Credit to MacWorld for this tip.

Update: Since posting this, Brian pointed out that this is most likely a setting inside of TextMate. To disable, just run this command from a terminal:

defaults write com.macromates.textmate OakDocumentDisableFSMetaData 1

Do not run this using sudo if you want it to work (I found out the hard way).

Freezing Just a Single Gem

Sometimes you don't want them all frozen (maybe you want to build Hpricot on your target system instead):

  $ rake gems:unpack GEM=coderay
  (in /Users/preagan/Projects/sneaq)
  Unpacked gem: '/Users/preagan/Projects/sneaq/vendor/gems/coderay-0.7.4.215'

Hello, World

I'm pretty terrible with the whole blogging thing, so this is my attempt to bridge the gap between the verbosity of 140 characters and a full-fledged blog post. To make this whole thing easier, I wrote my own custom blogging software - we'll see how it goes...