YAML Support and Hash Representer In representable-1.2.7!

{{{
The tiny “representable gem”:https://github.com/apotonick/representable/ got some improvements recently. Not only did we refactor the internals to make it easier adding new representation engines, we also used that to give you a new format: YAML!

h3. YAML, Who Needs YAML?

I use YAML very rarely. But sometimes clients happen to require it, or an API might be based on this format. Let’s make the world a better place and support it in representable!

Consider the following domain class.

require 'ostruct'
class Song  "Scarified", :track => 4)

To render this into YAML a simple representer is needed.

module SongRepresenter
  include Representable::YAML

  property :title
  property :track
end

Note the usage of the @Representable::YAML@ module. After injecting, the domain object is fully equipped with @#to_yaml@ and @#from_yaml@.

puts song.extend(SongRepresenter).to_yaml

# => "
---
title: Scarified
track: 4"

As always, this works also with parsing.

song = Song.new.extend(SongRepresenter)
song.from_yaml("---
title: Jackhammer
track: 5
")

puts song.inspect

#=> #

h3. Nested Models? Not A Big Deal.

Often you may want to represent nested setups – where models contain models. This has always been a key feature in representable.

class Album  SongRepresenter, 
                      :class  => Song
end

Since an @Album@ contains a list of @Song@s we wanna represent those embedded objects with the @SongRepresenter@ we already wrote.

Seting up a demo album, first.

album = Album.new(:songs => [
  Song.new(:title => "Scarified",  :track => 4),
  Song.new(:title => "Jackhammer", :track => 5)
])

The YAML representer will now create a proper YAML document for the nested objects.

album.extend(AlbumRepresenter).to_yaml
#=>
"---
songs:
- title: Scarified
  track: 4
- title: Jackhammer
  track: 5"

See how easy that is?

h3. And Finally: Flow-Style Lists.

Another cool feature is the ability to declare collections as “flow-style”:http://www.yaml.org/spec/1.2/spec.html#id2790088 which is an official part of the YAML specification but only very poorly implemented in available YAML gems.

Usually, lists are rendered in the block style.

class HotBands < OpenStruct
end

module HotBandsRepresenter
  include Representable::YAML

  property :for
  collection :names
end

After creating and rendering one of those @HotBand@s, the @names@ list is rendered in block style – the default in all YAML gems.

HotBands.new(:for => "Nick", :names => [
  "Bad Religion", 
  "Van Halen", 
  "Mozart"
]).extend(HotBandsRepresenter).to_yaml

#=> 
"---
for: Nick
names:
- Bad Religion
- Van Halen
- Mozart"

Now, if you don’t like that style where one list item is displayed per line, you might want to switch to the oh-so-flowing flow style.

module HotBandsRepresenter
  include Representable::YAML

  property :for
  collection :names, :style => :flow
end

By using the @:style => :flow@ option in the collection you can achieve just that!

hotties.to_yaml
#=> 
"---
for: Nick
names: [Bad Religion, Van Halen, Mozart]"

Check how it flows. That is just awesome.

h3. Introducing The Hash Representer.

We did a little bit of internal refactorings cleaning up representable. What came out is the new hash representer which gives basic functionality to most of the other representer engines. It can also be helpful if you want to parse incoming form data or use the @params@ hash from Rails or Sinatra to fill your objects.

Consider this representer.

require 'representable/hash'
module BandRepresenter
  include Representable::Hash

  property :name
  property :label
end

This representer can read and write plain Ruby hashes. Sounds stupid? It is! However, what if you wanna use Rails’ @params@ hash to update a model?

params = {"band" => 
  {"name" => "Paul Gilbert", "label" => "n/a"}}

This could be a form Rails (or Sinatra) automatically parsed for you. Now let’s use that on a new @Band@ instance.

band = Band.new.extend(BandRepresenter).
  from_hash(params["band"])

Note that this could be an existing @Band@ instance, too, as from @Band.find(params[:id])@.

Inspecting the result of our “parsing” we see that it actually works.

band.inspect
#=> #

This new hash representer is especially helpful for using representers with forms.

h3. One Module, Multiple Representers

Another nice little cleanup lets you include different representer engines into a single module, so you can transform to and from different media types.

module BandRepresenter
  include Representable::JSON
  include Representable::XML

This would give your objects the power of both XML and JSON.

h3. More To Come.

In the next release we’re planning readable/writeable policy support, polymorphic collections, letting you pass arguments to the represented accessors if you need that and more stuff I already forgot. Let us know if you need anything more, and *¡Salud!*
}}}

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s