You wish to consume a JSON REST API implemented in your Rails application.
Using the $resource
service is a great start and can be tweaked to feel more natural to a Rails developer by configuring the methods in accordance with the Rails actions.
app.factory("Contact", function($resource) {
return $resource("/api/contacts/:id", { id: "@id" },
{
'create': { method: 'POST' },
'index': { method: 'GET', isArray: true },
'show': { method: 'GET', isArray: false },
'update': { method: 'PUT' },
'destroy': { method: 'DELETE' }
}
);
});
We can now fetch a list of contacts using Contact.index()
and a single contact with Contact.show(id)
. These actions can be directly mapped to the ContactsController
actions in your Rails backend.
class ContactsController < ApplicationController
respond_to :json
def index
@contacts = Contact.all
respond_with @contacts
end
def show
@contact = Contact.find(params[:id])
respond_with @contact
end
...
end
The Rails action controller uses a Contact
ActiveRecord model with the usual contact attributes like firstname, lastname, age, etc. By specifying respond_to :json
the controller only responds to the JSON resource format and we can use respond_with
to automatically transform the Contact
model to a JSON response.
The route definition uses the Rails default resource routing and an api
scope to separate the API requests from other requests.
Contacts::Application.routes.draw do
scope "api" do
resources :contacts
end
end
This will generate paths like for example api/contacts
and api/contacts/:id
for the HTTP GET method.
You can find the complete example on github.
If you want to get up to speed with Ruby on Rails, I suggest that you look into the Rails Guides which will help you understand how all the pieces fit together.
The example code above works nicely until we use the HTTP methods POST
, PUT
and DELETE
with the resource. As a security mechanism, Rails expects an authenticity token to prevent a CSRF (Cross Site Request Forgery) attack. We need to submit an additional HTTP header X-CSRF-Token
with the token. It is conveniently rendered in the HTML meta
tag csrf-token
by Rails. Using jQuery we can fetch that meta tag definition and configure the $httpProvider
appropriately.
var app = angular.module("Contacts", ["ngResource"]);
app.config(function($httpProvider) {
$httpProvider.defaults.headers.common['X-CSRF-Token'] =
$('meta[name=csrf-token]').attr('content');
});
If you are using a Rails version prior 3.1, you’ll notice that the JSON response will use a contact
namespace for the model attributes which breaks your Angular.js code. To disable this behavior you can configure your Rails app accordingly.
ActiveRecord::Base.include_root_in_json = false
There are still inconsistencies between the Ruby and Javascript world. For example, in Ruby we use underscored attribute names (display_name) whereas in Javascript we use camelCase (displayName).
There is a custom $resource
implementation angularjs-rails-resource available to streamline consuming Rails resources. It uses transformers and inceptors to rename the attribute fields and handles the root wrapping behavior for you.