trailblazer / roar-rails

Use Roar's representers in Rails.
http://roar.apotomo.de
MIT License
235 stars 65 forks source link

Handle validation errors #49

Open jbbarth opened 11 years ago

jbbarth commented 11 years ago

It seems for now roar-rails' responder doesn't handle validation errors transparently (correct me if I'm wrong) like rails' builtin responder does, see ActionController::Responder docs. Today I write this:

def create
  singer = Singer.new(params[:singer])
  if singer.save
    respond_with singer
  else
    render json: { message: "Validation Failed", errors: singer.errors }.to_json
  end
end

but I'd like this to automatically happen (depending if resource has_errors?..) so we can write this:

def create
  respond_with Singer.create(params[:singer])
end

Could you :

If it sounds good I can work on that and submit a pull request in a few weeks.

fltiago commented 10 years ago

@apotonick +1. Seems like it doesn't look for a Representer when there is a validation error. That's right?

apotonick commented 10 years ago

That would be an ActiveModel-related extension of Roar. How would the output of the errors property look like?

cutalion commented 10 years ago

FYI, I've solved this with redefined render method in base controller class. I needed one-level errors hash in my API, instead of 2-level ActiveModel::Errors hash.

{"errors" => ["full error message"]} instead of {"errors" => { "base" => ["error message"]}}

  def render(*args)
    options = args.dup.extract_options!

    if options[:json] && options[:json].is_a?(Hash) &&
      options[:json][:errors].is_a?(ActiveModel::Errors)

      options[:json][:errors] = options[:json][:errors].full_messages

      super options
    else
      super
    end
  end
apotonick commented 10 years ago

If you want to return a generic errors document, there should be a generic Representer::JSON::Errors that kicks in when respond_with (or whatever renders) detects an error.

Introducing that, you wouldn't have to override render but could simply provide an optional errors representer.

cutalion commented 10 years ago

I guess it won't work with current implementation of roar-rails. The main issue with Roar::Rails::Responder is that it gets control only on rendering model (overrides display).

Rails won't render resource if it has errors (https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/responder.rb#L179). It will explicitly call resource.errors, which are not decorated.

I think that we can try to decorate resource earlier to take control over errors method.