Frozen Bytes

liquescent frozen bytes of code to manageable puddles

How to YAML

It is no secret, I’m enjoying Octopress! I’ve been tweaking Octopress to better suite my needs and make my process even simpler. In my effort to build a couple custom rake tasks for my Octopress fork I required the ability to read a few properties from the _config.yaml file. Before we dive into the code, what is YAML anyway? YAML stands for YAML Ain’t Markup Language and it is a versatile human friendly data serialization format. Some people believe YAML is easier to use and understand than JSON. That might be true, but I believe they serve two different purposes.

YAML is a simple human readable store of name/value pairs. You could compare it to an INI file, some also compare it to a Java properties file. Comparing YAML to JSON, you can, they both store name/value pairs or collections of but JSON is the accepted data transport for the web. When you think of RESTful services or even AJAX calls, I do not think of YAML for data transport, I think of JSON. Why? Because JavaScript understands JSON natively, not YAML. There are JavaScript YAML parsers available, like this js-yaml and checkout js-yaml online. In the same respect, dealing with configuration files, I think of YAML, XML or INI files not JSON.

Here is a simple YAML file to store values for root, url_base, and disqus_developer. In the Octopress world this file is called _config.yml, you name it anything you’d like just ensure it has .yml extension.

root: /
url_base: http://i-m-code.com/blog/
disqus_developer: 0

Open your favorite editor, mine is Sublime Text 2, create a new file, save it as Rakefile. Now add the below code to create your first Rake task to output the values in your YAML file. Open a terminal, navigate to the directory, run bundle exec rake burst to execute the task.

Rakefile burst
1
2
3
4
5
6
7
8
9
10
require "rubygems"
require "bundler/setup"

desc "My first Rake task to read and output a YAML file."
task :burst do
  yml = YAML::load(File.open('_config.yml'))
  puts yml['root'] # /
  puts yml['url_base'] # http://i-m-code.com/blog/
  puts yml['disqus_developer'] # 0
end

Well, that is really not too useful. Instead, to output all the name/value pairs in a YAML file update the Rake task to take in a parameter ( yamlfile ). Then loop through the yml name/value collection using each_pair using puts to output the key and value. Open a terminal, navigate to the directory, run bundle exec rake burst_loop[“_config.yml”] to execute the task.

Rakefile burst_loop[“_config.yml”]
1
2
3
4
5
6
7
8
desc "My first Rake task to read and output a YAML file."
task :burst_loop, :yamlfile do |t,args|
  raise "### You must specify a YAML file name." unless args[:yamlfile]
  yml = YAML::load(File.open(args.yamlfile))
  yml.each_pair { |key, value|
    puts "#{key} = #{value}"
  }
end

Use the code below to write to the YAML file. Open a terminal, navigate to the directory, run bundle exec rake burst_write[“_config-write.yml”,”mykey:myvalue”] to execute the task. You can also do it like this bundle exec rake burst_write[“_config-write.yml”,”{‘mykey’ => ‘myvalue’}”]. Of course you can send in more complex data like a class or a stream.

Rakefile burst_write[“yaml_file”,”yamldata”]
1
2
3
4
5
6
7
8
desc "Rake task to write YAML to a new YAML file."
task :burst_write, :yamlfile, :yamldata do |t,args|
  raise "### You must specify a YAML file name." unless args[:yamlfile]
  raise "### You must specify a YAML data." unless args[:yamldata]
  File.open(args.yamlile, 'w') do |out|
    YAML::dump(args.yamldata, out)
  end
end

What about merging two configuration files using YAML. First, create a new config-default.yml and config-dev.yml file in the directory root of the Rakefile you are working with. Next open each in editor of choice, add a few name/value pairs in config-default.yml and config-dev.yml as seen below then save.

_config-default.yml

team: 49ners
winner: no
root: /blog
url_base: http://i-m-code.com/blog/

_config-dev.yml

root: /
url_base: http://localhost:4000/blog/
disqus_developer: 0

Now you are ready to test the the Rake task below. Open a terminal, navigate to the directory, run bundle exec rake burst_merge[”config-default.yml”, ”config-dev.yml”] to execute the task.

Rakefile burst_merge[“yaml_file1” “yaml_file2”]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
desc "Rake task to merge two YAML files into one output YAML file."
task :burst_merge, :yamlfile1, :yamlfile2 do |t,args|
  raise "### You must specify a YAML file 1 name." unless args[:yamlfile1]
  raise "### You must specify a YAML file 2 name." unless args[:yamlfile2]
  outputfile = '_config-test.yml'
  puts "## Generating #{outputfile} from #{args.yamlfile1} and #{args.yamlfile2}"

  config = YAML::load( File.open(args.yamlfile1) )
  config_mode = YAML::load( File.open(args.yamlfile2) )
  config.merge!( config_mode )
    File.open( outputfile, 'w') do |f|
    f.puts("# Generated file. Do not edit")
    f.write(config.to_yaml)
  end
end

After merging the two YAML files _config-test.yml output will look like this.

team: 49ners
winner: no
root: /
url_base: http://localhost:4000/blog/
disqus_developer: 0

A more detailed tutorial.

Comments