tags:

views:

821

answers:

3

I'm trying to pick up ruby by porting a medium-sized (non-OO) perl program. One of my personal idioms is to set options like this:

use Getopt::Std;
our $opt_v;  # be verbose
getopts('v');
# and later ...
$opt_v && print "something interesting\n";

In perl, I kind of grit my teeth and let $opt_v be (effectively) a global.

In ruby,the more-or-less exact equivalent would be

require 'optparse'
    opts.on("-v", "--[no-]verbose", TrueClass, "Run verbosely") {
        |$opt_verbose|
    }
    opts.parse!
end

where $opt_verbose is a global that classes could access. Having classes know about global flags like that seems ... er ... wrong. What's the OO-idiomatic way of doing this?

  • Let the main routine take care of all option-related stuff and have the classes just return things to it that it decides how to deal with?
  • Have classes implement optional behaviour (e.g., know how to be verbose) and set a mode via an attr_writer sort of thing?

updated: Thanks for the answers suggesting optparse, but I should have been clearer that it's not how to process command-line options I'm asking about, but more the relationship between command-line options that effectively set a global program state and classes that should ideally be independent of that sort of thing.

+1  A: 

The first hit on google for "processing command line options in ruby" is an article about Trollop which seems to be a good tool for this job.

John
A: 

The optparse library is part of the standard distribution, so you'll be able to use it without requiring any third party stuff.

I haven't used it personally, but rails seems to use it extensively and so does rspec, which I guess is a pretty solid vote of confidence

This example from rails' script/console seems to show how to use it pretty easily and nicely

Orion Edwards
+3  A: 

A while back I ran across this blog post (by Todd Werth) which presented a rather lengthy skeleton for command-line scripts in Ruby. His skeleton uses a hybrid approach in which the application code is encapsulated in an application class which is instantiated, then executed by calling a "run" method on the application object. This allowed the options to be stored in a class-wide instance variable so that all methods in the application object can access them without exposing them to any other objects that might be used in the script.

I would lean toward using this technique, where the options are contained in one object and use either attr_writers or option parameters on method calls to pass relevant options to any additional objects. This way, any code contained in external classes can be isolated from the options themselves -- no need to worry about the naming of the variables in the main routine from within the thingy class if your options are set with a thingy.verbose=true attr_writer or thingy.process(true) call.

Nathan Fritz