3

I'm developing a RESTful API using Sinatra and DataMapper. When my models fail validation, I want to return JSON to indicate what fields were in error. DataMapper adds an 'errors' attribute to my model of type DataMapper::Validations::ValidationErrors. I want to return a JSON representation of this attribute.

Here's a single file example (gotta love Ruby/Sinatra/DataMapper!):

require 'sinatra'
require 'data_mapper'
require 'json'


class Person
    include DataMapper::Resource

    property :id, Serial
    property :first_name, String, :required => true
    property :middle_name, String
    property :last_name, String, :required => true
end


DataMapper.setup :default, 'sqlite::memory:'
DataMapper.auto_migrate!


get '/person' do
    person = Person.new :first_name => 'Dave'
    if person.save
        person.to_json
    else
        # person.errors - what to do with this?
        { :errors => [:last_name => ['Last name must not be blank']] }.to_json
    end
end


Sinatra::Application.run!

In my actual app, I'm handling a POST or PUT, but to make the problem easy to reproduce, I'm using GET so you can use curl http://example.com:4567/person or your browser.

So, what I have is person.errors and the JSON output I'm looking for is like what's produced by the hash:

{"errors":{"last_name":["Last name must not be blank"]}}

What do I have to do to get the DataMapper::Validations::ValidationErrors into the JSON format I want?

AnyWareFx
  • 131
  • 1
  • 6

2 Answers2

5

So, as I was typing this up, the answer came to me (of course!). I've burned several hours trying to figure this out, and I hope this will save others the pain and frustration I've experienced.

To get the JSON I'm looking for, I just had to create a hash like this:

{ :errors => person.errors.to_h }.to_json

So, now my Sinatra route looks like this:

get '/person' do
    person = Person.new :first_name => 'Dave'
    if person.save
        person.to_json
    else
        { :errors => person.errors.to_h }.to_json
    end
end

Hope this helps others looking to solve this problem.

AnyWareFx
  • 131
  • 1
  • 6
  • Yes that's one way of doing, for me requirement was a bit different. In case you are looking just for the error messages in response `JSON` check my answer. – ch4nd4n Dec 06 '12 at 06:43
  • Interesting... thanks for the info. For me, I need to associate the error message with the input field on my form on the client. The name is required to make that association. – AnyWareFx Dec 17 '12 at 02:12
0

I know, I am answering this late, but, in case you are just looking for just validation error messages, you can use object.errors.full_messages.to_json. For example

person.errors.full_messages.to_json

will result in something like

"[\"Name must not be blank\",\"Code must not be blank\",
   \"Code must be a number\",\"Jobtype must not be blank\"]"

This will rescue on client side from iterating over key value pair.

ch4nd4n
  • 4,110
  • 2
  • 21
  • 43