Using Rabl with Grape

nesquena edited this page Feb 19, 2013 · 10 revisions

Recent versions

grape-rabl is the best way to integrate RABL into your Grape APIs. Simply follow the basic instructions for setup on that gem's README.

For extends and partial, be sure to configure your grape templates path as a default view path:

Rabl.configure do |c|
  c.view_paths = [
    Rails.root.join("app/api/templates"), 
    Rails.root.join("app/views") 
  ]
end

Then just use grape-rabl as shown in their readme:

# Setup in config.ru or in application.rb
use Rack::Config do |env|
  env['api.tilt.root'] = '/path/to/view/root/directory'
end

require 'grape/rabl'
class API < Grape::API
  format :json
  formatter :json, Grape::Formatter::Rabl

  get "/user/:id", :rabl => "user.rabl" do
    @user = User.find(params[:id])
  end
end

Older versions

Version (~> 0.6.8) of Rabl breaks compatibility with older versions of grape-rabl, luckily there is a workaround using Grape's presenter support. You can also upgrade to latest rabl and grape-rabl versions (see above).

Here's an example:

posts_api.rb

resource :posts do
    get '/' do
      @posts = current_user.posts
      present @posts, :with => RablPresenter, :source => 'api/posts'
    end
end

The only attribute you need to pass in is :source to tell Rabl::Renderer which template to use.

Your RablPresenter could look something like this:

class RablPresenter
  def self.represent(object, options)
    render_options = {
      :format => options[:env]['api.format'],
      :view_path => Rails.root.join('app/views')
    }
    Rabl::Renderer.new(options[:source], object, render_options).render
  end
end

You can take this one step further and declare the presenter within your API class:

class PostsAPI < Grape::API
  represent Post, :with => RablPresenter

  resource :posts do
    get '/' do
      @posts = current_user.posts
      present @posts, :source => 'api/posts'
    end
  end
end

These examples are based around using Grape mounted within a Rails application, you might need to tweak the :view_path attribute to suit your stack.

Rabl::Renderer was added in version 0.6.9 and is required for this example.

Rails Path Helpers

In order to have path helpers available in grape methods and rabl views, add the following code to an initializer (config/initializers/rabl_grape.rb):

module Grape
  class Endpoint
    include Rails.application.routes.url_helpers
    default_url_options[:host] = ::Rails.application.routes.default_url_options[:host]
  end
end

module Rabl
  class Engine
    include Rails.application.routes.url_helpers
    default_url_options[:host] = ::Rails.application.routes.default_url_options[:host]
  end
end

and under config/environments/development.rb and all other environment files, add

routes.default_url_options = { host: "local.dev.com", port: 3000 }