Caius Theory

Now with even more cowbell…

Create a blank rails app including plugins

When I create a rails app from scratch I like to include certain plugins to help me write the app, such as the Rspec testing framework instead of the built-in Test::Unit and jQuery instead of prototype.

And here are the commands in the order I run them to create the blank app.

# Create the rails app
cd ~/Sites/apps/
rails myapp
cd myapp

# Setup a git repo
git init
# Add all files and make the initial import
git add .
git commit -m "Initial Import"

# Add the plugins as git submodules
git submodule add git:// vendor/plugins/rspec
git submodule add git:// vendor/plugins/rspec-rails
git submodule add git:// vendor/plugins/cucumber
git submodule add git:// vendor/plugins/webrat
git submodule add git:// vendor/plugins/demeters_revenge

# Commit the changes
git ci -am "Adding all needed submodules"

# Replace TestUnit with rspec
git rm -r test/
ruby script/generate rspec
# Replace stories with cucumber features
rm -rf stories/
ruby script/generate cucumber

# Add the changes to git
git add .
git ci -m "Committing initial rspec/cucumber files"

# Install jRails, we have to install it using script/plugin
# Remove existing javascript files
git rm public/javascripts/*
mkdir public/javascripts
# Add jrails
ruby script/plugin install
git add vendor/plugins/jrails/ public/javascripts
git ci -m "Adding jRails to replace Prototype"

And now you have a blank app waiting for you to write using features for full stack testing, and rspec for testing model and controller code.

Updated 2008-11-04

Added demeters revenge and jRails plugins.

Update 2008-11-05

I've also blogged the .gitignore file I use with rails apps as well. Usually add it into my apps before running git init

Spanning Sync

So for work I have to subscribe to a shared google calendar the company uses. Annoyingly this can't be through my Google Apps account though, it has to be through my normal google account.

Also annoying is the fact google doesn't let me subscribe to my shared calendars without making them 100% public. Which means the shared private calendar work uses would have to be a public shared calendar, which is obviously not going to happen. (Can't have everyone knowing when the secret drinking parties are!)

Thankfully, there is already a solution out there to this problem, and it comes in the form of a Preference Pane called SpanningSync that syncs iCal to Google Calendar. All you need to do is install the prefpane and enter your google email/password (which is then safely secured in your keychain I believe.)

What it does is stick an icon in the menubar, and then at a pre-defined (and customisable) interval, sync any new changes between the local iCal calendar and the remote shared calendar in your google acccount.

Spanning Sync is only $25 to register for the year, but you can save yourself $5 by entering 6EMQAC as the spanning sync coupon code, or clicking here

Setting up git with rails apps

When I create a new rails app, I'm constantly going back to another project and stealing the .gitignore file from it to make sure that git doesn't know about certain files rails either updates frequently, or stores machine-specific data in. The latter is generally just config/database.yml, because I develop alongside my colleagues at Brightbox and we deploy via capistrano, we always put the database.yml file in the shared directory on the server, so we each have our own version with our local credentials in it locally. And thus we don't want it to be tracked by git.

Here's what I've collated from various sources over the few weeks I've been using git + rails everyday.



# OS X only

Then to make sure log/ and tmp/ are tracked, convention is to add a blank .gitkeep file in them.

touch log/.gitkeep
touch tmp/.gitkeep

Removing non-existent source from rubygems

I just came to move some ruby scripts onto my mac mini, and to do so I needed to install a couple of gems. Now I realised I hadn't installed or updated rubygems on the machine for a while, so I figured it was best to update gem before installing the gems I wanted. Easier said than done.

At some point in the past I had added as a source to rubygems. Since then the datamapper project has discontinued using this gem source to serve up gems, so I was getting the following output:

mm:daemons caius$ sudo gem update --system
Updating installed gems
Bulk updating Gem source index for:
ERROR:  While executing gem ... (Gem::RemoteSourceException)
    HTTP Response 404 fetching

Eeek! I can't update because the source no longer exists. So I figured I'd remove the source before updating, that should work right? Wrong. It updates the sources before removing the source from the config it would appear.

mm:daemons caius$ sudo gem sources

mm:daemons caius$ sudo gem sources -r
Bulk updating Gem source index for:
ERROR:  While executing gem ... (Gem::RemoteSourceException)
    HTTP Response 404 fetching

Oh balls. So how do I remove the source without updating it first. I need to update it to remove it, but to remove it I need to update from it. Gotta love catch 22s!

I remembered that gem install has an option not to update sources, --no-update-sources. So I figured thats gotta work when removing a source as well, but it doesn't.

mm:daemons caius$ sudo gem sources -r --no-update-sources
ERROR:  While executing gem ... (OptionParser::InvalidOption)
    invalid option: --no-update-sources

Oh crap. Now what do I do? Take my usual tactic and google for a hint of course! I'd considered trying to find where the gem config was and remove the source by hand, but I figured that wouldn't be that simple. After hitting a couple of sites that weren't relevant I ended up on the edge of complexity where he mentions the command nano ~/.gemrc. Which made me wonder if that file contains the sources.

mm:daemons caius$ cat ~/.gemrc
:update_sources: true
:verbose: true
:bulk_threshold: 1000
:backtrace: false
:benchmark: false

All I needed to do was remove the - line and poof, gem was working again. One quick gem update --system later and I was upgraded from gem 1.1.1 to 1.3.1 and installing the gems I needed.

Adding a remote to existing git repo

Usually for me this happens when I have an existing project and I setup a github repo for it. As part of the setup for the github project, it gives you the commands to run to add the github repo as a remote to my local git repo.

cd existing_git_repo
git remote add origin
git push origin master

The problem then is you've added the remote account, but the local master branch isn't tracking the remote master branch, so when you try and just git pull it will fail with a message telling you to set the remote refs up.

$ git pull  
You asked me to pull without telling me which branch you  
want to merge with, and 'branch.master.merge' in  
your configuration file does not tell me either.  Please  
name which branch you want to merge on the command line and  
try again (e.g. 'git pull <repository> <refspec>').  
See git-pull(1) for details on the refspec.  

If you often merge with the same branch, you may want to  
configure the following variables in your configuration  

    branch.master.remote = <nickname>
    branch.master.merge = <remote-ref>
    remote.<nickname>.url = <url>
    remote.<nickname>.fetch = <refspec>

See git-config(1) for details.

The answer is to do what it says funnily enough, and add the remote refs tracking to the config file. The easiest way I've found of doing this is to edit .git/config and add the following at the bottom of it.

[branch "master"]
    remote = origin
    merge = refs/heads/master

Remember to change the branch or remote names if you need to.

Once you've added that to the config you can run git pull on the master branch and it'll do the usual automagical thing and pull the remote master branch changes into the local one!

Updated 2008-11-09

See Ciarán's comment below for an all-inclusive command to do the above.

When work just feels right

Much like Rahoul's post on knowing you're on the right path, I had that moment this morning whilst we were discussing a future feature for our control panel.

john: will I be able to superpoke our customers?
john: is that in the spec?
Jeremy: "John made server10 a zombie"
Caius: "server10 zombified server9"
Jeremy: "David has poked server19 19234 times"
john: server16 messaged David "My disk is filling up and I have files I need to put somewhere, please help!"
Caius: "Rahoul ended his friendship with server15"
David: "server02 is now married to server05"
Rahoul: server10 has sent you 12 videos of a fat man eating a cake
David: server11 joined the group "KVM ftw"
Caius: "server16 threw a sheep at server15"
john: server03 joined the group "Centos sucks!"
Caius: "server15 sent an emergency broadcast: physical movement detected"
john: storage03 has logged off
Caius: "x13 flew to the moon 0 times"
john: disk5 in storage02 is now a zombie
Jeremy: disk4 in storage02 is now a zombie
Jeremy: disk3 in storage02 is now a zombie
Jeremy: disk2 in storage02 is now a zombie
john: storage02 was sold on ebay by Jeremy
Caius: "john was sold on brightbox marketplace by storage5"

(In case you don't know, I work for Brightbox.)