{{{
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!*
}}}