rowtheboat - George Palmer

Just another WordPress weblog

Archive for June, 2008

Testing your rake tasks

This week I’ve been working on a client project where I needed to import a massive XML dataset into a database.  The XML was non-standard and broke its own rules in several places.  Consequently my rake task quickly become very complicated and I needed some tests to ensure I wasn’t breaking previous work.  This leads to a rather interesting question: how do you test rake tasks?  After a bit of googling I found a rather neat solution of simply pulling out the rake code to a class. For example, rather than:


desc "Import the XML"
task :import => :cleanup do
  File.open(XML_FILE) do |file|
    # Do importing here...
  end
end

do something more like


desc "Import the XML"
task :import => :cleanup do
  File.open(XML_FILE) do |file|
    XMLImporter.parse_lines(file)
  end
end

XMLImporter can then be tested in the normal way. Good ruby - clean and effective.

No comments

Capistrano 2.3, Git and frozen MERB

I had a few issues getting a Capistrano file to work with Git and frozen MERB the last few days. The script below is how I finally cracked it and also has starters and stoppers for Memcached and my forked backgroundrb for MERB.


# Basic deploy details
set :application, "myapp"
set :deploy_to, "/var/www/apps/#{application}"
set :mongrel_conf, "#{deploy_to}/current/config/mongrel_cluster.yml"

# Repository details
set :repository,  "git@ipaddress:reposname.git"
set :scm, "git"
set :scm_passphrase, ""
set :set_branch, "origin/master"
set :git_enable_submodules, 1

# Required to get git password prompt
default_run_options[:pty] = true

# Set the user account to use for deployment and running
set :user, "deploy"
set :use_sudo, false

# Server details
role :app, "mysite.com"
role :web, "mysite.com"
role :db,  "mysite.com", :primary => true

desc "Deploy to the production server"
task :production do
role :app, "mysite.com"
role :web, "mysite.com"
role :db,  "mysite.com", :primary => true
end

desc "Change the database configuration file"
task :after_update_code do
run "mv #{release_path}/config/database.yml.production #{release_path}/config/database.yml"

# Remove code we don’t want on the server
run "rm -rf #{release_path}/autotest"
run "rm #{release_path}/config/deploy.rb"
run "rm -rf #{release_path}/coverage"
run "rm -rf #{release_path}/spec"
run "rm -rf #{release_path}/stories"

# Make config directory just readable
run "chmod 700 #{release_path}/config"
run "chmod 400 #{release_path}/config/*"
run "chmod 700 #{release_path}/config/environments"
run "chmod 700 #{release_path}/config/initializers"
run "chmod 400 #{release_path}/config/environments/*"

# Make frozen-merb bin file executable
run "chmod 755 #{release_path}/framework/merb-more/merb-freezer/bin/frozen-merb"
end

# Override db:migrate as it calls rails specific stuff
namespace :deploy do
desc "Migrate the database"
task :migrate, :roles => :db do
run "cd #{release_path}; rake db:migrate MERB_ENV=production"
end
end

# Override the default deploy options to use backgroundrb, memcached and mongrel
namespace :deploy do
namespace :backgroundrb do
desc "Start backgroundrb"
task :start, :roles => :app do
invoke_command "cd /var/www/apps/bablo/current && script/backgroundrb start — -r production", :via => run_method
end
task :stop, :roles => :app do
invoke_command "cd /var/www/apps/bablo/current && script/backgroundrb stop", :via => run_method
end
end

namespace :memcached do
desc "Start memcached"
task :start, :roles => :app do
run "memcached -l 127.0.0.1 -d -m 96 -p 17898"
end
task :stop, :roles => :app do
run "killall -s TERM memcached"
end
end

namespace :mongrel do
desc "Start mongrel"
task :start, :roles => :app do
invoke_command "cd /var/www/apps/bablo/current && #{release_path}/framework/merb-more/merb-freezer/bin/frozen-merb -d -e production -c 5", :via => run_method
end
desc "Stop mongrel"
task :stop, :roles => :app do
invoke_command "cd /var/www/apps/bablo/current && #{release_path}/framework/merb-more/merb-freezer/bin/frozen-merb -K all", :via => run_method
end
end

desc "Custom restart task for mongrel cluster"
task :restart, :roles => :app, :except => { :no_release => true } do
deploy.backgroundrb.stop
deploy.memcached.stop
deploy.memcached.start
deploy.mongrel.stop
deploy.mongrel.start
deploy.backgroundrb.start # Doesn’t work if straight after the stop
end

desc "Custom start task for mongrel cluster"
task :start, :roles => :app do
deploy.backgroundrb.start
deploy.memcached.start
deploy.mongrel.start
end

desc "Custom stop task for mongrel cluster"
task :stop, :roles => :app do
deploy.backgroundrb.stop
deploy.memcached.stop
deploy.mongrel.stop
end
end

I’ve still not managed to get Git caching working with submodules, so any input on this would be appreciated (it seems to work fine without submodules).  Updated: Fixed in Capistrano 2.4

No comments

MERB: The new rails?

I presented on MERB last weekend at Barcamp London 4 I’ve been using the technology the last two months at Bablo so it was good to share my experience with other users. With it being quite a bleeding edge technology there was just a small gang of us there but there was plenty of good discussion. The talk I gave had a purposely provocative title but ended with a great quote by Ezra

more choices make the Ruby ecosystem a better place. So let’s just stop with the Rails VS Merb stuff. How about people choose what framework they want to use based on the frameworks merits and features rather then religious arguments about how my framework can beat up your framework.

I was then flicking through some slides from the recent RubyConf and was mightily impressed by a slide from the end of the MERB talk:

It’s consider a bug if:
* It’s not documented
* MERB gets slower
* There’s a public API change without prior deprecation in a timely manner

It seems the guys at EngineYard have a great attitude, not to mention a really well thought out framework. I’m looking forward to using it fulltime.

No comments