Reading and Writing Configuration Files

Problem

You want to store your applications configuration on disk, in a format parseable by Ruby but easily editable by someone with a text editor.

Solution

Put your configuration into a data structure, and write the data structure to disk as YAML. So long as you only use built-in Ruby data types (strings, numbers, arrays, hashes, and so on), the YAML file will be human-readable and -editable.

require yaml configuration = { color => lue, font => Septimus, font-size => 7 } open( ext.cfg, w) { |f| YAML.dump(configuration, f) } open( ext.cfg) { |f| puts f.read } # -- # font-size: 7 # color: blue # font: Septimus open( ext.cfg) { |f| YAML.load(f) } # => {"font-size"=>7, "color"=>"blue", "font"=>"Septimus"}

Its easy for a user to edit this: its just a colon-separated, line-delimited set of key names and values. Not a problem, even for a relatively unsophisticated user.

Discussion

YAML is a serialization format, designed to store data structures to disk and read them back later. But theres no reason why the data structures can be modified by other programs while they e on disk. Since simple YAML files are human-editable, they make good configuration files.

A YAML file typically contains a single data structure. The most common structures for configuration data are a hash (seen in the Solution) and an array of hashes.

configuration = [ { ame => Alice, donation => 50 }, { ame => Bob, donation => 15, currency => "EUR" } ] open(donors.cfg, w) { |f| YAML.dump(configuration, f) } open(donors.cfg) { |f| puts f.read } # --- # - name: Alice # donation: 50 # - name: Bob # donation: 15 # currency: EUR

In Recipe 5.1 we advise saving memory by using symbols as hash keys instead of strings. If your hash is going to be converted into human-editable YAML, you should always use strings. Otherwise, people editing the YAML may become confused. Compare the following two bits of YAML:

puts { measurements => metric }.to_yaml # --- # measurements: metric puts { :measurements => :metric }.to_yaml # --- # :measurements: :metric

Outside the context of a Ruby program, the symbol :measurements is too easy to confuse with the string ":measurements".

See Also

Категории