Makes using Roar's representers in your Rails app fun.
Roar is a framework for parsing and rendering REST documents. For a better overview about representers please check the roar repository.
- Rendering with responders
- Parsing incoming documents
- URL helpers in representers
- Better tests
- Autoloading
This gem works with all Rails >= 3.x.
roar-rails provides a number of baked-in rendering methods.
Easily render resources using representers with the built-in responder.
class SingersController < ApplicationController
include Roar::Rails::ControllerAdditions
respond_to :json
def show
singer = Singer.find_by_id(params[:id])
respond_with singer
end
end
The representer name will be infered from the passed model class (e.g. a Singer
instance gets the SingerRepresenter
). If the passed model is a collection it will be extended using a representer. The representer name will be computed from the controller name (e.g. a SingersController
uses the SingersRepresenter
).
Need to use a representer with a different name than your model? You may always pass it in using the :represent_with
option:
respond_with singers, :represent_with => MusicianCollectionRepresenter
end
If you don't want to use conventions or pass representers you can configure them on the class level using ::represents
. This will also call respond_to
for you.
class SingersController < ApplicationController
represents :json, Musician
This will use the MusicianRepresenter
for models and MusiciansRepresenter
for representing collections.
Note that ::represents
also allows fine-tuning.
class SingersController < ApplicationController
represents :json, :entity => MusicianRepresenter, :collection => MusicianCollectionRepresenter
You might pass strings as representer names to ::represents
, they will be constantized at run-time when needed.
If you don't want to write a dedicated representer for a collection of items (highly recommended, thou) but rather use a representer for each item, use the :represent_items_with
option.
class SingersController < ApplicationController
def index
singers = Musician.find(:all)
respond_with singers, :represent_items_with => SingerRepresenter
end
end
In #create
and #update
actions it is often necessary to parse the incoming representation and map it to a model instance. Use the #consume!
method for this.
class SingersController < ApplicationController
respond_to :json
def create
singer = Singer.new
consume!(singer)
respond_with singer
end
end
The consume!
call will roughly do the following.
singer.
extend(SingerRepresenter)
from_json(request.body)
So, #consume!
helps you figuring out the representer module and reading the incoming document.
Note that it respects settings from #represents
. It uses the same mechanics known from #respond_with
to choose a representer.
consume!(singer, :represent_with => MusicianRepresenter)
If you prefer roar's decorator approach over extend, just go for it. roar-rails will figure out automatically which represent strategy to use. Be sure to use roar >= 0.11.17.
class SingerRepresenter < Roar::Decorator
include Roar::Representer::JSON
property :name
link :self do
singer_url(represented)
end
end
In decorators' link blocks you currently have to use represented
to get the actual represented model (this is self
in module representers).
Both rendering and consuming support passing user options to the representer.
With #respond_with
, any additional options will be passed to to_json
(or whatever format you're using).
respond_with @singer, :current_user => current_user
Same goes with #consume!
, passing options to from_json
.
consume! Singer.new, :current_user => current_user
Note: If you pass in options to a representer, you must process them youself. For rendering, use :getter
in the representer.
property :username, getter: lambda { |args| args[:current_user].name }
That'll render the current_user
's name as the username
property.
More docs about passing and processing option can be found here.
Any URL helpers from the Rails app are automatically available in representers.
module FruitRepresenter
include Roar::Representer::JSON
include Roar::Representer::Feature::Hypermedia
link :self do
fruit_url self
end
end
To get the hyperlinks up and running, please make sure to set the right host name in your environment files (config/environments):
config.representer.default_url_options = {:host => "127.0.0.1:3000"}
Attention: If you are using representers from a gem your Rails URL helpers might not work in these modules. This is due to a loading order problem in Rails. As a workaround, don't require the representers in the gem but load them as lately as possible, usually it works when you require in the controller. We are working on fixing that problem.
By default, roar-rails will extend/decorate any model passed to respond_with
for any request format. When adding roar-rails to a legacy project, you might want to restrict roar-rails' representing and fall back to the old behavior for certain formats. This can be configured both globally and on a per action basis.
To restrict representing globally to a particular format you can set the config.representer.represented_formats
in your environment's configuration to an array of formats. For example the following will only represent hal and json requests.
config.representer.represented_formats = [:hal, :json]
The global configuration (or lack thereof) can be overridden by supplying the :represented_formats
array when calling respond_with
. The following will only represent @resource
for the hal format in the show
action. For any other format, it will expose the resource using Rails' old behavior.
class MyController < ApplicationController
def show
...
respond_with @resource, :represented_formats => [:hal]
end
end
You can entirely suppress roar-rails in respond_with
by passing in an empty array.
class MyController < ApplicationController
def show
...
respond_with @resource, :represented_formats => []
end
end
Put your representers in app/representers
and they will be autoloaded by Rails. Also, frequently used modules as media representers and features don't need to be required manually.
- Railslove and especially Michael Bumann [bumi] have heavily supported development of roar-rails ("resource :singers").
Roar-rails is released under the MIT License.