Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looking for paradigm to use for generic error handling in Angular from a JSON response from Rails

I'm building an app which is architected as a Rails server app providing RESTful api's to the client. The Rails server uses RABL. The client is an Angular JS client performing standard $http calls (gets, puts, etc).

Occasionally my Rails server will produce an error (let's say validation error attached to the object) or even no error in which case I would want to display something to the user - either the errror e.g., "The record did not save because..." or "The record was updated successfully".

I'm trying to map out a pattern on both the Rails side and the Angular/client side to handle this.

As for Rails:

  • I can certainly pass back a node in each of my RABL files to contain error arrays
  • I can also return different RABL by checking in the controller before returning
  • Most suggest using http codes (which makes sense) as per here (although there doesn't seem to be a consistent usages of the codes for something like a validation error).

As for Angular:

  • I suppose I can write a response interceptor but not sure how that would fully get flushed out.

I guess I'm hoping that I don't have to reinvent the wheel here and someone can point me to a pattern that's currently used and suggested (and localized).

like image 526
Arthur Frankel Avatar asked Apr 10 '13 20:04

Arthur Frankel


1 Answers

I went ahead and implemented what I thought needed to be done. Thanks for digger69 for some help with this.

On the Rails side, I went with using an http status code. As per here I agreed with using a 400 http status code for error validation.

In my controllers I now have something like the following:

def create
  my_obj = MyObj.build_with_params(params)
  if my_obj.save
    respond_with(my_obj) # regular RABL response
  else
    respond_with_errors(my_obj.errors)
  end
end

In my application_controller.rb I defined a common method respond_with_errors

# respond back to the client an http 400 status plus the errors array
def respond_with_errors(errors)
  render :json => {:errors => errors}, :status => :bad_request
end

Note that the :bad_request symbol is already defined for Rails as per here

On the client side I needed to intercept http calls (not only for validation but for authentication failures too (and probably more). Here is an example of my code in Angular (thanks to this post for the help with that):

var interceptor = ['$rootScope', '$q', function (scope, $q) {
  function success(response) {
    return response;
  }
  function error(response) {
    var status = response.status;

    if (status == 401) { // unauthorized - redirect to login again
      window.location = "/";
    } else if (status == 400) { // validation error display errors
      alert(JSON.stringify(response.data.errors)); // here really we need to format this but just showing as alert.
    } else {
      // otherwise reject other status codes
      return $q.reject(response);
    }
  }
  return function (promise) {
    return promise.then(success, error);
  }
}];
$httpProvider.responseInterceptors.push(interceptor);

I now can be consistent with my rails code and deal with success returns from http calls on the client. I'm sure I have some more to do, but I think this gives a localized solution.

like image 169
Arthur Frankel Avatar answered Oct 15 '22 13:10

Arthur Frankel