Using Command Line Parameters w/ Rake and Capistrano

Posted by ryan
at 10:40 PM on Thursday, June 21, 2007



Almost every project I work on requires a small set of both custom rake tasks and capistrano recipes. Since my models are as fat as they can be, these tasks and recipes are usually quite slim and really only involve delegation to the appropriate model method. Ok, so apparently Ryan thinks he’s great because he religiously believes in fat models – woohoo – that’s last year’s news. What I really want to talk about is that I am always needing to pass in parameters from the command line to these tasks, and everytime I struggle finding the documentation on how to properly do that.

So let’s try to figure this out once and for all.

Command line parameters in Rake

on Rake v0.7.2

This one’s easy. Options can be passed into rake by specifying key/value pairs on the rake command:


rake options:show opt1=value1

These command line options are then automatically set as environment variables which can be accessed within your rake task:

1
2
3
4
5
6
7
8
namespace :options do

  desc "Show how to read in command line options"
  task :show do
    p "option1 is #{ENV['opt1']}"
  end

end

I don’t love overloading the environment variables collection as a command line marshaller, but hey, it is what it is and it’s easy to use.

1
2
rake options:show opt1=value1
#=> option1 is value1

Ok, easy enough. Next.

Command line parameters in Capistrano

w/ Capistrano v1.4.1

Capistrano is a little different in that you need the -s command line switch for each key/value pair and you have a different way(s) of accessing these variables within your capistrano tasks. For instance, this is the capistrano version of the rake invocation example from earlier:


cap -a show_options -s opt1=value1

And you’ve got a couple of ways to get at these variables from within your capistrano task. The first is by referencing the variable name itself:

1
2
3
task :show_options do
  p "option1 is #{opt1}"
end

This is convenient, but you get a method_missing exception when you attempt to reference that variable when it hasn’t yet been set. The more reliable accessor method is by using the configuration object available to your capistrano tasks:

1
2
3
task :show_options do
  p "option1 is #{configuration[:opt1]}" if configuration[:opt1]
end

which will simply be nil if it doesn’t exist instead of choking like the previous, direct, access.

When you’re building a task library you’ll be wrapping your tasks in a Capistrano.configuration(:must_exist) block that yields the configuration object itself. So you can rename that lengthy configuration name to c if you’re the lazy type in that scenario:

1
2
3
4
5
6
7
Capistrano.configuration(:must_exist).load do |c|

  task :show_options do
    p "option1 is #{c[:opt1]}" if c[:opt1]
  end

end

So while this isn’t ground-breaking research here, I’ve had trouble finding concrete documentation on passing in values from the command line to Rake and Capistrano. So consider this a note to myself from the future… except that it’s from the past… to the future Ryan… which isn’t nearly as impressive.

tags: ruby, rubyonrails, rake, capistrano

What's New in Edge Rails: No More (conventional) Pagination

Posted by ryan
at 7:51 AM on Monday, June 11, 2007



For those of you luddites out there still grasping to the usage of standard pagination, your mind has been made up for you. Pagination has been removed from core Rails and future reliance on it will require the installation of the classic_pagination plugin. So what’s one to do now for your pagination needs? Why, will_paginate, of course.

What's New in Edge Rails: Nested Resource RESTful URL Builder

Posted by ryan
at 9:03 AM on Wednesday, June 06, 2007



Don’t go too overboard with this stuff – it’s meant primarily for internal (to Rails) usage…

The march to RESTful nirvana continues with a drop dead easy way to build nested resource URLs. Let’s review.

Assuming the following routing configuration:

1
2
3
map.resources :categories do |categories|
  categories.resources :articles
end

This automatically builds a category_url(category) and category_article_url(category, article) helper (among others) that will build the appropriate URLs:

1
2
category_url(@category) #=> /categories/1
category_article_url(@category, @article) #=> /categories/1/article/1

All right, that’s great. But why should we have to spell out these lengthy helper method calls when it’s clear that the first argument is a Category and the second is an Article? Can’t the appropriate helper method be implied by the types of these arguments? Yes – they can, and now they are with the new url_for update. Now you can pass in a collection of models to url_for, in order of nesting (root to child), and get the correct URL:

1
2
url_for(@category) #=> /categories/1
url_for([@category, @article]) #=> /categories/1/article/1

You can always fall back to the named routes provided for you by RESTful routing, but you now have an option to build URLs with an implied resource nesting.

tags: ruby, rubyonrails, REST

What's New in Edge Rails: Collection Fixtures

Posted by ryan
at 2:16 PM on Tuesday, June 05, 2007



For those of you tired of referencing the fixture method when building a collection of fixtures, your day has come

Gone are the days of unnecessary typing:

1
2
3
fixtures :states
..
assert_equal [states(:nc), states(:va)], State.find(:all)

and here are the days of a convenient syntax for retrieving more than one fixture at a time:

1
2
3
fixtures :states
..
assert_equal states(:nc, :va), State.find(:all)

Revolutionary? No. Useful? Yes.

tags: ruby, rubyonrails