Gem Version

Summary

Toast is an extension to Ruby on Rails to build web services with low programming effort in a coherent way. Toast extends ActiveRecord such that each model can be declared to be a web resource, exposing defined attributes for reading and writing using HTTP.

Its main features are:

  • declaration of web resources based on ActiveRecord models
  • generic controller handles all actions
  • automated routing
  • exposing data values with JSON maps
  • exposing associations by links (URLs)

Toast works with

  • Ruby on Rails >= 3.1.0 (currently tested up to 3.2.16)
  • Ruby 1.8.7, 1.9.3, 2.0.0

See the User Manual for a detailed description.

Status

Toast is ready for production and is being used in productive applications since 2012. However, misconfigurations can have undesired effects.

WARNING

A soon the gem is loaded a controller with ready routing is enabled serving the annotated model's data records at least for reading for everybody.

You need to implement authorization yourself.

Example

Let the table bananas have the following schema:

 create_table "bananas", :force => true do |t|
   t.string   "name"
   t.integer  "number"
   t.string   "color"
   t.integer  "apple_id"
 end

and let a corresponding model class have a acts_as_resource annotation:

 class Banana < ActiveRecord::Base
   belongs_to :apple
   has_many :coconuts

   scope :less_than_100, where("number < 100")

   acts_as_resource do
     # exposed attributes or association names
     readables :coconuts, :apple
     writables :name, :number

     # exposed class methods of Banana returning an Array of Banana records
     collections :less_than_100, :all
   end
 end

The above definition inside the acts_as_resource block exposes the records of the model Banana automatically via a generic controller to the outside world, accepting and delivering JSON representations of the records. Let the associated models Apple and Coconut be exposed as a resource, too:

Get a collection

GET /bananas
--> 200,  '[{"self":     "http://www.example.com/bananas/23",
             "name":     "Fred",
             "number":   33,
             "coconuts": "http://www.example.com/bananas/23/coconuts",
             "apple":    "http://www.example.com/bananas/23/apple,
            {"self":     "http://www.example.com/bananas/24",
              ... }, ... ]

Get a customized collection (filtered, paging, etc.)

GET /bananas/less_than_100
--> 200, '[{BANANA}, {BANANA}, ...]'

Get a single resource representation:

GET /bananas/23
--> 200,  '{"self":     "http://www.example.com/bananas/23"
            "name":     "Fred",
            "number":   33,
            "coconuts": "http://www.example.com/bananas/23/coconuts",
            "apple":    "http://www.example.com/bananas/23/apple" }'

Get an associated collection

"GET" /bananas/23/coconuts
--> 200, '[{COCNUT},{COCONUT},...]',

Update a single resource:

PUT /bananas/23, '{"self":   "http://www.example.com/bananas/23"
                   "name":   "Barney",
                   "number": 44}'
--> 200,  '{"self":     "http://www.example.com/bananas/23"
            "name":     "Barney",
            "number":   44,
            "coconuts": "http://www.example.com/bananas/23/coconuts",
            "apple":    "http://www.example.com/bananas/23/apple"}'

Create a new record

"POST" /bananas,  '{"name": "Johnny",
                    "number": 888}'
--> 201,  {"self":     "http://www.example.com/bananas/102"
           "name":     "Johnny",
           "number":   888,
           "coconuts": "http://www.example.com/bananas/102/coconuts" ,
           "apple":    "http://www.example.com/bananas/102/apple }

Create an associated record

"POST" /bananas/23/coconuts, '{COCONUT}'
--> 201,  {"self":"http://www.example.com/coconuts/432,
           ...}

Delete records

DELETE /bananas/23
--> 200

More details and configuration options are documented in the manual.

Installation

With bundler from (rubygems.org)

gem "toast"

the latest Git:

gem "toast", :git => "https://github.com/robokopp/toast.git"

Remarks

REST is more than some pretty URIs, the use of the HTTP verbs and response codes. It's on the Toast user to invent meaningful media types that control the application's state and introduce semantics. With toast you can build REST services or tightly coupled server-client applications, which ever suits the task best. That's why TOAST stands for:

TOast Ain't reST