[Best practices] YAML usage in Ruby on Rails
YAML
Welcome to the Yaml Cookbook for Ruby. This version of the Yaml Cookbook focuses on the Ruby implementation of Yaml by comparing Yaml documents with their Ruby counterparts.
YAML™ is a readable text format for data structures. As you’ll see below, YAML can handle many common data types and structures. And what YAML can’t handle natively can be supported through flexible type families. For example, YAML for Ruby uses type families to support storage of regular expressions, ranges and object instances.
Collections
Nested Sequences
You can include a sequence within another sequence by giving the sequence an empty dash, followed by an indented list.
1 | - |
Ruby code:
1 | [['foo', 'bar', 'baz']] |
Inline Collections
Simple Inline Array
Sequences can be contained on a single line, using the inline syntax. Separate each entry with commas and enclose in square brackets.
1 | seq: [ a, b, c ] |
Ruby code:
1 | { 'seq' => [ 'a', 'b', 'c' ] } |
Simple Inline Hash
Mapping can also be contained on a single line, using the inline syntax. Each key-value pair is separated by a colon, with a comma between each entry in the mapping. Enclose with curly braces.
1 | hash: { name: Steve, foo: bar } |
Ruby code:
1 | { 'hash' => { 'name' => 'Steve', 'foo' => 'bar' } } |
Multi-line Inline Collections
Both inline sequences and inline mappings can span multiple lines, provided that you indent the additional lines.
1 | languages: [ Ruby, |
Ruby code:
1 | { 'languages' => [ 'Ruby', 'Perl', 'Python' ], |
Basic Types
Strings
Forcing Strings
Any YAML type can be forced into a string using the explicit !str method.
1 | date string: !str 2001-08-01 |
Ruby code:
1 | { |
Single-quoted Strings
You can also enclose your strings within single quotes, which allows use of slashes, colons, and other indicators freely. Inside single quotes, you can represent a single quote in your string by using two single quotes next to each other.
1 | all my favorite symbols: '#:!/%.)' |
Ruby code:
1 | { |
Double-quoted Strings
Enclosing strings in double quotes allows you to use escapings to represent ASCII and Unicode characters.
1 | i know where i want my line breaks: "one here\nand another here\n" |
Ruby code:
1 | { |
Null
You can use the tilde ‘~’ character for a null value.
1 | name: Mr. Show |
Ruby code:
1 | { |
YAML For Ruby
Symbols
Ruby Symbols can be simply serialized using the !ruby/symbol transfer method, or the abbreviated !ruby/sym.
1 | simple symbol: !ruby/symbol Simple |
Ruby code:
1 | { 'simple symbol' => :Simple, |
Ranges
Ranges are serialized with the !ruby/range type family.
1 | normal range: !ruby/range 10..20 |
Ruby code:
1 | { 'normal range' => (10..20), |
Ruby code:
1 | { 'simple' => /a.b/, 'complex' => /\A"((?:[^"]|\")+)"/, |
Perl Regexps
Regexps may also be imported from serialized Perl.
1 | --- !perl/regexp: |
Ruby code:
1 | /R[Uu][Bb][Yy]$/i |
Struct class
The Ruby Struct class is registered as a YAML builtin type through Ruby, so it can safely be serialized. To use it, first make sure you define your Struct with Struct::new. Then, you are able to serialize with Struct#to_yaml and unserialize from a YAML stream.
1 | --- !ruby/struct:BookStruct |
Ruby code:
1 | book_struct = Struct::new( "BookStruct", :author, :title, :year, :isbn ) |
Nested Structs
As with other YAML builtins, you may nest the Struct inside of other Structs or other data types.
1 | - !ruby/struct:FoodStruct |
Ruby code:
1 | food_struct = Struct::new( "FoodStruct", :name, :ingredients, :taste ) |
Objects
YAML has generic support for serializing objects from any class available in Ruby. If using the generic object serialization, no extra code is needed.
1 | --- !ruby/object:YAML::Zoolander |
Ruby code:
1 | class Zoolander |
Extending Kernel::Array
When extending the Array class, your instances of such a class will dump as YAML sequences, tagged with a class name.
1 | --- !ruby/array:YAML::MyArray |
Ruby code:
1 | class MyArray < Kernel::Array; end |
Extending Kernel::Hash
When extending the Hash class, your instances of such a class will dump as YAML maps, tagged with a class name.
1 | --- !ruby/hash:YAML::MyHash |
Ruby code:
1 | # Note that the @me attribute isn't dumped |
Reuse config when possible
extends
extends
is a great way to reuse some YAML config in multiple places, for example:
1 | .image_template: |
Dynamic Code
1 |
|
References
[1] YAML.rb is YAML for Ruby | Cookbook - https://yaml.org/YAML_for_ruby.html
[5] YAML Ain’t Markup Language (YAML™) Version 1.2 - https://yaml.org/spec/1.2/spec.html