Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Branch: master
Fetching contributors…

Cannot retrieve contributors at this time

138 lines (108 sloc) 4.707 kB

angrea

Automatically generate angular resource files from your Rails projects

AngularJS makes some assumptions about resources which don't map exactly to Rails, so I thought I would simply building this routing by generating it automatically from the definitive mapping, the routes object inside your rails application.

Add it to your Gemfile:

gem 'angrea', :git => 'git@github.com:xrd/Angrea.git'

Define the normal route in config/routes.rb

resources :tasks do
  collection do
    post :delegate_to_underling
  end

Define the normal thing in your controller

class TasksController << ApplicationController

  def index
    @tasks = Task.all
    render :json => @tasks
  end

  def delegate_to_underling
    render :json => [ { :underling_name => 'Dilbert' } ]
  end   
  ...
end                          

Then, use the method below like this inside service.js.coffee.erb files to automatically generate a service object for your angular controllers.

<%= Angrea::ViewHelpers::generate_angular_coffee_resource( { :model => 'Task', :robj => Rails.application.routes.routes } ) %>

This will generate an Angular service definition inside your output JS file which automatically maps out your Rails routes and can then be loaded into your angular controller.

You can then use it like this in a controller, like this: task.js.coffee

class TaskCtrl
        constructor: (Task) ->
                @Task = Task
                      @Task.index {}, (result) =>
                                      @tasks = result

        delegate: (task) ->
                response = @Task.delegate_to_underling({id : task.id, name: task.name})                                          
                message = response[0].underling_name

The neat thing is the Angular resource adapter transparently converts the JSON for you and you can just use the resulting object as a javascript object.
No heavy conversion code. And, it automatically sends the right parameters to your rails controllers. The rails controllers will get these requests:

/tasks  # First request

/tasks/delegate_to_underling?id=1234&name=Dilbert # second request.

IMPORTANT: The adapter assumes all routes with :id in the path are singular routes (meaning the object returned is not an array) while all routes without the :id in the path are collection routes (meaning the returned object is an array). So, if you want to pass something back in your controller that is not an array but the route is a collection route, then stuff it inside an array first.

class TasksController << ApplicationController

  def index
    @tasks = Task.all
    render :json => [ { :tasks => [1,2,3], :something => 'or another' } ]
  end
  ...
end                          

class TaskCtrl
        constructor: (Task) ->
                @Task = Task
                      @Task.index {}, (array) =>
                                      result = array[0]
                                      @stuff = result
                                      @stuff.tasks # [1,2,3]
                                      @stuff.something # 'or another'

You will need to add this to the bottom of your controller if you are using asset pipeline minimizing tools

this.TaskCtrl = TaskCtrl
TaskCtrl.$inject = [ 'Task' ]

This generates this JS after coming out of the coffeescript compiler:

(function() {
  angular.service('Task', function($resource) {
    return $resource('/tasks/:id/:action', {
      action: '@action',
      id: '@id'
    }, {
      index: {
        method: 'GET',
        action: 'index',
        isArray: true
      },
      create: {
        method: 'POST',
        action: 'create',
        isArray: true
      },
      "new": {
        method: 'GET',
        action: 'new',
        isArray: true
      },
      edit: {
        method: 'GET',
        action: 'edit',
        isArray: false
      },
      show: {
        method: 'GET',
        action: 'show',
        isArray: false
      },
      update: {
        method: 'PUT',
        action: 'update',
        isArray: false
      },
      destroy: {
        method: 'DELETE',
        action: 'destroy',
        isArray: false
      }
    });
  });
}).call(this);

License: This project rocks and uses MIT-LICENSE.

Jump to Line
Something went wrong with that request. Please try again.