ActiveResource Removed from Rails. What about Roar?

Due to the removal of ActiveResource (Ares) from Rails I want to analyze how we use it, how we can replace it, and present a new promising gem.

ActiveResource was introduced in Rails 2.0:

Active Resource (ARes) connects business objects and Representational State Transfer (REST) web services. It implements object-relational mapping for REST webservices to provide transparent proxying capabilities between a client (ActiveResource) and a RESTful service (which is provided by Simply RESTful routing in ActionController::Resources).
Active Resource attempts to provide a coherent wrapper object-relational mapping for REST web services.
Model classes are mapped to remote REST resources by Active Resource much the same way Active Record maps model classes to database tables. When a request is made to a remote resource, a REST XML request is generated, transmitted, and the result received and serialized into a usable Ruby object.

What’s wrong with this?

From the image below, we can assume that we will map our product model directly to our resource and that ActiveResource will do the work nicely.

What about this?

Are all the representations of our resources mapping directly to our ActiveRecord models?

We are tempted to create a dashboard model in our application and have it represent the state of several objects in our system. But is ActiveResource the best way to represent our REST documents? How easy is it to compose a representation with several objects mixing ActiveRecord, Mongodb, Riak, etc?

Based on REST we are consuming documents representing the state of some part of our application.

Using ActiveResource, we still have to compute hyperlinks to get the ActiveRecord mapped objects into our front end. But what if the document provides the hypermedia links to the other associated representations?

ActiveResource is not web oriented. The missing feature: Hypermedia

Hypermedia is used as a logical extension of the term hypertext in which graphics, audio, video, plain text and hyperlinks intertwine to create a generally non-linear medium of information.

To represent hypermedia Roar provides HAL. It’s not mandatory to use it, but I suggest you consider it if you want to use hypermedia documents.

HAL is a lean, domain-agnostic hypermedia type in both JSON and XML, and is designed specifically for exposing RESTful hypermedia APIs.

HAL has two main components: resources and links. Resources have their own state, links, and embedded resources (which are resources in their own right)

Roar to the Rescue

Resource-Oriented Architectures in Ruby. “Lets make documents suit our models and not models fit to documents.”
Please note that Roar is still in conception, the API might change as well as concepts do.

Central to Roar are representers – object-oriented documents suitable for parsing and rendering, extendable at run time and with hypermedia support. The representer concept is the answer to the missing REST abstraction layer in most frameworks.

Features:

  • OOP access to documents
  • Parsing and rendering of representations in one place
  • Declaratively define document syntax and semantics
  • Hypermedia support
  • ActiveResource-like client support
  • Useable in both client and server
  • Framework agnostic, runs with sinatra, Rails, webmachine and friends

Considering that we have a REST API back end for our application, this is how it would look without Roar:

By adding Roar:

And here’s how it will look in code:

# dashboard.rb in the backend
# Dashboard is not ActiveRecord, is a Ruby object.
#
class Dashboard

  include DashboardRepresenter
  attr_reader :user

  def initialize(id)
    @user = User.find(id)
  end

  def user_id
    @user.id
  end

  def galleries(limit = 5)
    @user.galleries.limit(limit)
  end

end

# dashboard_client.rb in the client
# we use dashboard_client to have the representation of the Dashboard
# remote object.
#
require 'roar/representer/feature/client'

class DashboardClient
  include ::Roar::Representer::Feature::HttpVerbs

  def initialize
    extend(DashboardRepresenter)
    extend ::Roar::Representer::Feature::Client
  end

end

# dashboard_representer.rb shared between backend and client
# this code can be shared between client and server to get
# the same representation and share some behavior.
# I think is a good idea to put them on a gem and include the
# gem in both applications
#
require 'roar/representer/json/hal'

module DashboardRepresenter
  include ::Roar::Representer::JSON
  include ::Roar::Representer::JSON::HAL::Links
  include ::Roar::Representer::Feature::Hypermedia

  property :user_id

  collection :galleries,  extend: GalleryRepresenter

  link :self do
    'http://self'
  end

end

# gallery_representer.rb shared between backend and client

module GalleryRepresenter
  include ::Roar::Representer::JSON

  property :id
  property :name

end

# users_controller.rb on the backend responding to dashboard
# the controller will know how to respond to the request as
# the Json representation.
#
class UsersController < ApplicationController
  respond_to :json

  responders Roar::Rails::Responder

  def dashboard
    dashboard = Dashboard.new(params[:user_id])
    respond_with(dashboard)
  end
end

We share the representers in client and server as mixins.

Is not required to use Roar on both sides, but the fact you can gives it an advantage over ActiveResource. The representers also can be seen as a contract between the client as server or interfaces in Java.

Conclusion

Web development is a lot more distributed than it’s ever been, so we need to design distributed systems more often. Distributed systems are more complex and include more variables. The removal of ActiveResource as a default integrator forces us to start looking for alternatives. Roar is more than a replacement: It provides a missing layer to get pure Ruby object representations of our resources.

How about you? Any tips? Tell me by posting a comment below.

Post a Comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>