It has been a while since I blogged about Roar and it’s representers – beautiful South Africa kept me from doing my homework. Nevertheless, in the meantime, the new roar-rails gem emerged bringing together Rails and Roar in a very easy going way. I’d like to describe how this gem works by implementing a fruit and fruit bowl backend service following the examples from the last posts.
Oh, and before I forget mentioning, the Rails example app is available on github where I will keep adding examples from the Ruby On REST blog series.
Setting It Up…
To make things happen it is necessary adding the roar-rails gem to your Gemfile.
gem 'roar-rails'As we wanna use Rails’ URL helpers in our representers we have to add one line to the environment.
config.representer.default_url_options = {:host => "yum.my"}
Rendering Fruits, Done Right.
For simplicity let’s assume our Fruit model has the following underlying, highly complex database scheme.
create_table "fruits" do |t| t.string "title" end
Tough stuff, isn’t it?
Clients might want to retrieve fruit representations, that’s why we start with a functional test for handling GET requests on the FruitsController.
class FruitsControllerTest < ActionController::TestCase include Roar::Rails::TestCase test "GET returns fruit document" do get :show, :id => 1, :format => :json assert_body "{\"title\":\"Apple\",\"links\":[ {\"rel\":\"self\", \"href\":\"http://yum.my/fruits/Apple\"}]}" end
Including the Roar::Rails::TestCase module into the test gives us a couple of new or changed methods. One of those is assert_body and all it does it testing equality of the passed string and the last returned document. This test verifies our REST representations are rendered correctly.
Here’s the handling code in the FruitsController.
class FruitsController < ApplicationController include Roar::Rails::ControllerAdditions respond_to :json def show fruit = Fruit.find_by_id(params[:id]) respond_with fruit end
This is all very familiar code! But, wait… what happens here behind the scenes? The inclusion of the ControllerAdditions module activates a new responder which will take care of the JSON-rendering that is invoked inside respond_with. So, behind the curtain, the following is executed.
fruit. extend(FruitRepresenter). to_json
The roar-rails gem infers the representer name used for rendering.
The Fruit Representer
Now, where is that representer? It lives in the app/representers directory and its implementation is quite simple.
module FruitRepresenter include Roar::Representer::JSON property :title link :self do fruit_url(title) end end
All it does is defining the title property and the self link. Please note that we can simply use URL helpers here, making it pretty easy to include hypermedia in our representations.
Amazing! This is all the code needed for rendering fruit documents, including hot hypermedia and handling GET requests. Now, what do we need to consume incoming documents, in, let’s say a POST request?
Eat More Fruits!
To create new fruits in our backend service we’d need to accept POST requests. Test it.
class FruitsControllerTest < ActionController::TestCase # ... test "POST creates fruit" do post :create, "{\"title\":\"Orange\"}", :format => :json assert_body "{\"title\":\"Orange\",\"links\":[ {\"rel\":\"self\", \"href\":\"http://yum.my/fruits/Orange\"}]}" end
Again, we use assert_body to assure the resource returns the freshly created representation of the orange. Now, check the post: The second argument is the actual JSON document sent by the client. This is an API change. We no longer pass hashes to the “POST”, but use real documents to test our services.
The consuming controller action is hilariously simple as well.
class FruitsController < ApplicationController # ... def create fruit = Fruit.new. extend(FruitRepresenter). from_json(request.body.string). save respond_with fruit end
It creates a new Fruit instance, mixes in the respective representer, parses the incoming JSON document and updates the fruit’s attributes in the #from_json method and then renders the created model.
In the upcoming version of roar-rails, this code can also be written like:
class FruitsController < ApplicationController # ... def create fruit = consume(Fruit). save respond_with fruit end
The consume method provided by roar-rails is still under discussion – feel free to add comments to this post if you have a groundbreaking idea how to simplify the consumption steps!
Fruits On This Planet – Unite!
If that was to easy for you, and I bet it was, why not implement the fruit bowl as well. Consider this model class.
class Bowl < ActiveRecord::Base has_and_belongs_to_many :fruits end
Instead of wasting time with the rendering test and parsing code – which is identical to the fruit code – we jump directly into the parsing test.
class BowlsControllerTest < ActionController::TestCase include Roar::Rails::TestCase test "POST creates bowl with fruits" do post :create, "{\"fruits\":[{\"title\":\"Orange\"}]}", :format => :json bowl = Bowl.find(:last) assert_body "{\"fruits\":[ {\"title\":\"Orange\",\"links\":[ {\"rel\":\"self\", \"href\":\"http://yum.my/fruits/Orange\"}]}], \"links\":[ {\"rel\":\"self\", \"href\":\"http://bowls/#{bowl.id}\"}]}" end
Sometimes I wish my blog was less narrow.
In the test, an initial bowl document is POSTed to the resource. We expect a fresh bowl representation containing fruits as the response.
Let’s look at the controller action to understand how representers work in a nested setup. Speaking of nesting, here’s the representer responsible for rendering and parsing bowls.
module BowlRepresenter include Roar::Representer::JSON property :location collection :fruits, :class => Fruit, :extend => FruitRepresenter link :self do bowl_url(id) end end
In addition to the location property the collection defines a nesting fruits. The BowlRepresenter now knows that the collection contains Fruit instances that must be represented with the according FruitRepresenter. We already discussed that in one of the last posts.
Here’s the controller action using that representer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class BowlsController < ApplicationController # ... def create bowl = consume(Bowl) # puts bowl.fruits.inspect bowl.fruits = bowl.fruits.collect do |f| Fruit.find_by_title(f.title) end bowl.save respond_with bowl end |
I simply assume the consume call already works. Then, what is that loop? Well, when parsing the incoming document, the bowl representer creates a new Fruit instance for every fruit in the collection. If line 7 would be uncommented, it would output the following.
[#<Fruit id: nil, title: "Orange">]
That is, before we reset the collection manually. The representer doesn’t know anything about the database – it just maps a fruit representation in the document to a fresh Fruit instance. This is why there is no id set, yet. We have to do that ourselves (lines 8-10). What might look clumsy to you is simplicity – it’s up to you how to map objects to database records.
Conclusion – For Now?!
Come on, it is easy to use representers in your Rails backends using the roar-rails gem. It helps you rendering documents and makes it quite easy to have object-oriented access to a parsed incoming representation – under Rails-conditions.
And, as always, this is just a start. Open source lives from discussion and criticism, so feel free to use the comments form below. In the next post I’ll discuss writing paginated collections using representers. Have a nice day!

xeLL
awesome, thanks, write more!
Distributed Weekly 145 — Scott Banwart's Blog
[...] Ruby on REST 4: Using Representers in Rails [...]