Bruce P. Henry
Bruce P. Henry

Reputation: 432

External Configuration for Standalone Ruby Script

I have a standalone ruby script that is intended to be run from a commandline.

Currently I have a section to define stuff like paths to files and such.

    key_path = "C:\\OpenSSL-Win64\\keys\\"
    consumer_file = "henrb028.consumer"
    key_file = "henrb028.key"

I'd love to pull all of that out of the .rb file and into some external config file. Ideally it would be as lightweight as possible. For example, just copy-paste that into another ruby file and then cram it in at runtime.

I've tried both require and include and gotten varying errors. Without resorting to something like YAML, what's an easy and robust way to do this?

Upvotes: 0

Views: 168

Answers (1)

Masa Sakano
Masa Sakano

Reputation: 2267

There are a few standard ways to realize what you describe.

Read from environmental variables

Each of those environmental stores a particular parameter. Then users can control, if they want to change some or all of the parameters.

  • Pros: Standard and handy way for both developers and users, providing the parameters are seldom changed. The default parameters can be easily shared in the same environment (like the same account or even platform-wide), as well as with other programs.
  • Cons: Somewhat obscured. For example, if a user's work with the tool is logged in a file, other people (or even the user her/himself later) cannot tell what the exact set of the parameters used was from the logfile. Or, if a user wants to change a parameter frequently, it is awkward.

An example:

 key_file = ENV['KEY_FILE'] || "henrb028.key"

Read from a configuration file

Then either or both of each user and the system administrator can control and change it, when needed. How to determine the filename of the configuration file varies.

  • Pros: Suitable to store a large set of parameters.
  • Cons: Somewhat obscured. For example, if a user's work with the tool is logged in a file, other people (or even the user her/himself later) cannot tell what the exact set of the parameters used was. If a user wants to change a parameter frequently, it is very awkward.

A (crude!) example:

Suppose /etc/OUR_CONFIG.txt is as follows,

 CONSUMER_FILE: henrb028.consumer
 KEY_FILE: henrb028.key

Then, read them like,

 opts = { 'KEY_FILE' => 'default.key' }
 IO.readlines("/etc/OUR_CONFIG.txt").each do |ec|
   a = ec.strip.split(/\s*:\s*/)
   opts[a[0]] = a[1]
 end
 p opts

Specify with command-line options

If some (or all) options are not specified at the run time, it should fall back to the default value. OptionParser (as @tadaman suggested in his/her comment) is a powerful and versatile library to handle command-line options.

  • Pros: Standard and handy way for users, especially for a quick change at the run time. If you see the log file, you know what exactly the user did.
  • Cons: The default parameters cannot be shared with other tools on its own. To circumvent the problem, there are a few ways to make a fall-back routine:
    1. Simply hard-code the default value in the main code.
    2. Store the default value in an environmental variable.
    3. Store the default value in a configuration file. The developer must decide how to determine the filename of the configuration file (hard-coding, environmental variable, etc).

A crude example (without using OptionParser):

opts = { 'key_file' => 'default.key' }
%w(consumer_file key_file).each do |ec|
  cands = ARGV.grep(/^--#{Regexp.quote ec}=.+/)
  opts[ec] = cands[0].split('=')[1] unless cands.empty?
end
p opts

I think these are the most typical ways, though there are other ways!

Upvotes: 2

Related Questions