Sleek CLI wrappers around Ruby libs

When using Ruby’s splat operator for method invocation, eg. my_method(*my_array), it takes the array and blows it out into the parameters required to fill the method’s signature. This makes it super easy to call methods from classes via the command line, by simply passing the arguments (ARGV) to a Ruby command line app and then directly down into a Ruby class API. The key to my approach is to do this in a very DRY way with as little code as possible. Here’s how I do it.

First we’ll create a file called seeker.rb with a class a API that looks like this:

class Seeker
  def work_file(infile, outfile, suffix, delimeter)
    p "parameter 1: infile = #{infile}"
    p "parameter 2: outfile = #{outfile}"
    p "parameter 3: suffix = #{suffix}"
    p "parameter 4: delimeter = #{delimeter}"
    #do important stuff, etc..
  end
end

Now, we can create a generic wrapper script to drive it like this by doing the following. Create a file called just seeker. Make sure to chmod +x seeker. Add the following text:

#!/usr/bin/env ruby

require File.expand_path('seeker.rb', __FILE__)
Seeker.new.send(ARGV.shift.to_sym, *ARGV)

With this generic message passing script in place, we can call the API like this:

$./seeker work_file foo.txt bar.txt .com ,

Running this command, we get the following output:

parameter 1: infile = foo.txt
parameter 2: outfile = bar.txt
parameter 3: suffix = .com
parameter 4: delimeter = ,

The ease with which we’re able to pass input from the cli straight into our class API comes from the splat operator’s ability to turn an ordered set of cli args into Ruby method params. Notice that we chewed off ARGV[0] as the name of the method we wanted to run. Using the builtin “send” method, which sends a generic message to an instance of a Ruby class, we can invoke any method by simply specifying it as the first cli arg followed by the parameters to be passed into the method, which are just the subsequent cli args.

With a general purpose wrapper like this we can invoke any method on any target class with no additional code. This is a testament to the sheer goodness of Ruby.

Leave a comment