Reading and Writing Configuration Files






Reading and Writing Configuration Files

Problem

You want to store your application's 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' => 'blue',
	                  'font' => 'Septimus',
	                  'font-size' => 7 }
	open('text.cfg', 'w') { |f| YAML.dump(configuration, f) }

	open('text.cfg') { |f| puts f.read }
	# --
	# font-size: 7
	# color: blue
	# font: Septimus

	open('text.cfg') { |f| YAML.load(f) }
	# => {"font-size"=>7, "color"=>"blue", "font"=>"Septimus"}

It's easy for a user to edit this: it's 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 there's no reason why the data structures can't be modified by other programs while they're 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 = [ { 'name' => 'Alice', 'donation' => 50 },
	                  { 'name' => '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

  • Recipe 13.1, "Serializing Data with YAML"



 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows