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.