angus 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/angus +13 -0
- data/lib/angus.rb +6 -4
- data/lib/angus/base.rb +119 -0
- data/lib/angus/base_actions.rb +38 -0
- data/lib/angus/base_resource.rb +14 -0
- data/lib/angus/command.rb +27 -0
- data/lib/angus/generator.rb +141 -0
- data/lib/angus/generator/templates/Gemfile +5 -0
- data/lib/angus/generator/templates/README.md +0 -0
- data/lib/angus/generator/templates/config.ru.erb +10 -0
- data/lib/angus/generator/templates/definitions/messages.yml +0 -0
- data/lib/angus/generator/templates/definitions/operations.yml.erb +21 -0
- data/lib/angus/generator/templates/definitions/representations.yml +0 -0
- data/lib/angus/generator/templates/definitions/service.yml.erb +3 -0
- data/lib/angus/generator/templates/resources/resource.rb.erb +6 -0
- data/lib/angus/generator/templates/services/service.rb.erb +4 -0
- data/lib/angus/marshallings/base.rb +2 -0
- data/lib/angus/marshallings/marshalling.rb +136 -0
- data/lib/angus/marshallings/unmarshalling.rb +29 -0
- data/lib/angus/renders/base.rb +2 -0
- data/lib/angus/renders/html_render.rb +9 -0
- data/lib/angus/renders/json_render.rb +15 -0
- data/lib/angus/request_handler.rb +62 -0
- data/lib/angus/resource_definition.rb +78 -0
- data/lib/angus/response.rb +53 -0
- data/lib/angus/responses.rb +232 -0
- data/lib/angus/rspec/spec_helper.rb +3 -0
- data/lib/angus/rspec/support/examples.rb +64 -0
- data/lib/angus/rspec/support/examples/describe_errors.rb +36 -0
- data/lib/angus/rspec/support/matchers/operation_response_matchers.rb +117 -0
- data/lib/angus/rspec/support/operation_response.rb +57 -0
- data/lib/angus/utils.rb +2 -0
- data/lib/angus/utils/params.rb +24 -0
- data/lib/angus/utils/string.rb +27 -0
- data/lib/angus/version.rb +2 -2
- data/spec/angus/rspec/examples/describe_errors_spec.rb +64 -0
- data/spec/spec_helper.rb +27 -0
- metadata +181 -19
- data/.gitignore +0 -17
- data/Gemfile +0 -4
- data/LICENSE.txt +0 -22
- data/README.md +0 -29
- data/Rakefile +0 -1
- data/angus.gemspec +0 -23
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module Angus
|
5
|
+
module Marshalling
|
6
|
+
|
7
|
+
# Marshal an object
|
8
|
+
#
|
9
|
+
# This method is intended for scalar objects and arrays of scalar objects.
|
10
|
+
#
|
11
|
+
# For more complex objects:
|
12
|
+
# @see Angus::Marshalling.marshal_object
|
13
|
+
#
|
14
|
+
# @param object The object to be marshalled
|
15
|
+
# @return [Array] An object suitable for be converted easily to JSON notation
|
16
|
+
#
|
17
|
+
# If {object} is an array, this method returns an array with all the elements marshalled
|
18
|
+
# Else returns a marshalled representation of the object.
|
19
|
+
def self.marshal(object)
|
20
|
+
if object.is_a?(Array)
|
21
|
+
object.map { |element| marshal(element) }
|
22
|
+
else
|
23
|
+
marshal_scalar(object)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Marshal a complex object.
|
28
|
+
#
|
29
|
+
# @param object The object to be marshalled
|
30
|
+
# @param getters An array of getters / hashes that will be used to obtain the information
|
31
|
+
# from the object.
|
32
|
+
def self.marshal_object(object, getters)
|
33
|
+
result = {}
|
34
|
+
getters.each do |getter|
|
35
|
+
if getter.is_a?(Hash)
|
36
|
+
key = getter.keys[0]
|
37
|
+
value = get_value(object, key)
|
38
|
+
|
39
|
+
#TODO Consider adding ActiveRecord::Relation support
|
40
|
+
#ex: "if value.is_a?(Array) || value.is_a?(ActiveRecord::Relation)"
|
41
|
+
if value.is_a?(Array)
|
42
|
+
result[key] = value.map { |object| marshal_object(object, getter.values[0]) }
|
43
|
+
else
|
44
|
+
result[key] = value.nil? ? nil : marshal_object(value, getter.values[0])
|
45
|
+
end
|
46
|
+
else
|
47
|
+
value = get_value(object, getter)
|
48
|
+
result[getter] = marshal_scalar(value)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
return result
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
# Gets a value from a object for a given getter.
|
57
|
+
#
|
58
|
+
# @param [Object] object The object to get the value from
|
59
|
+
# @param [Symbol, String] getter to request from the object
|
60
|
+
# @raise [InvalidGetterError] when getter is not present
|
61
|
+
# in the object
|
62
|
+
# @return [Object] the requested value
|
63
|
+
def self.get_value(object, getter)
|
64
|
+
if object.is_a?(Hash)
|
65
|
+
get_value_from_hash(object, getter)
|
66
|
+
else
|
67
|
+
get_value_from_object(object, getter)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Gets a value from a object by invoking method.
|
72
|
+
#
|
73
|
+
# @param [Object] object The object to get the value from
|
74
|
+
# @param [Symbol, String] method the method to invoke in the object
|
75
|
+
# @raise [InvalidGetterError] when the object does not responds
|
76
|
+
# to method as public.
|
77
|
+
# @return [Object] the requested value
|
78
|
+
def self.get_value_from_object(object, method)
|
79
|
+
value = object.public_send method.to_sym
|
80
|
+
|
81
|
+
# HACK in order to fix the error:
|
82
|
+
# NoMethodError: undefined method `merge' for #<JSON::Ext::Generator::State:0x257fd086>
|
83
|
+
if value.is_a?(Array)
|
84
|
+
value.to_a
|
85
|
+
else
|
86
|
+
value
|
87
|
+
end
|
88
|
+
# TODO ver si tirar una exception especifica o que hacer?
|
89
|
+
#rescue NoMethodError => error
|
90
|
+
# raise InvalidGetterError.new(method, error.backtrace.first)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Gets a value from a hash for a given key.
|
94
|
+
#
|
95
|
+
# It accepts the key as a symbol or a string,
|
96
|
+
# it looks for the symbol key first.
|
97
|
+
#
|
98
|
+
# @param [Hash] hash The hash to get the value from
|
99
|
+
# @param [Symbol, String] key to get from the hash
|
100
|
+
# @raise [InvalidGetterError] when the key does not
|
101
|
+
# exists in the hash
|
102
|
+
# @return [Object] the requested value
|
103
|
+
def self.get_value_from_hash(hash, key)
|
104
|
+
if hash.has_key?(key.to_sym)
|
105
|
+
hash[key.to_sym]
|
106
|
+
elsif hash.has_key?(key.to_s)
|
107
|
+
hash[key.to_s]
|
108
|
+
else
|
109
|
+
#raise InvalidGetterError.new(key)
|
110
|
+
raise NoMethodError.new(key.to_s)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Marshal a scalar value
|
115
|
+
# @param scalar the scalar value to be marshalled
|
116
|
+
#
|
117
|
+
# If scalar is a Date or DateTime it return a iso8601 string
|
118
|
+
# If scalar is a Symbol it returns the symbol as string
|
119
|
+
# Everything else (string, integer, ...) returns the same object.
|
120
|
+
def self.marshal_scalar(scalar)
|
121
|
+
case scalar
|
122
|
+
when Time
|
123
|
+
scalar.iso8601
|
124
|
+
when DateTime
|
125
|
+
scalar.iso8601
|
126
|
+
when Date
|
127
|
+
scalar.iso8601
|
128
|
+
when Symbol
|
129
|
+
scalar.to_s
|
130
|
+
else
|
131
|
+
scalar
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module Angus
|
5
|
+
module Unmarshalling
|
6
|
+
|
7
|
+
def self.unmarshal_scalar(scalar, type)
|
8
|
+
return nil if scalar.nil?
|
9
|
+
|
10
|
+
case type
|
11
|
+
when :string
|
12
|
+
scalar
|
13
|
+
when :integer
|
14
|
+
scalar
|
15
|
+
when :boolean
|
16
|
+
scalar
|
17
|
+
when :date
|
18
|
+
Date.iso8601(scalar)
|
19
|
+
when :date_time
|
20
|
+
DateTime.iso8601(scalar)
|
21
|
+
when :decimal
|
22
|
+
BigDecimal.new(scalar.to_s)
|
23
|
+
else
|
24
|
+
raise ArgumentError, "Unknown type: #{type}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'angus-router'
|
2
|
+
|
3
|
+
require_relative 'response'
|
4
|
+
require_relative 'responses'
|
5
|
+
|
6
|
+
module Angus
|
7
|
+
class RequestHandler
|
8
|
+
|
9
|
+
include Responses
|
10
|
+
|
11
|
+
DEFAULT_RENDER = :json
|
12
|
+
|
13
|
+
attr_reader :env, :request, :response, :params
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@router = Angus::Router.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def router
|
20
|
+
@router
|
21
|
+
end
|
22
|
+
|
23
|
+
def call(env)
|
24
|
+
begin
|
25
|
+
@env = env
|
26
|
+
@response = Response.new
|
27
|
+
|
28
|
+
router.route(env)
|
29
|
+
rescue Angus::Router::NotImplementedError
|
30
|
+
@response.status = HTTP_STATUS_CODE_NOT_FOUND
|
31
|
+
|
32
|
+
render({ 'status' => 'error',
|
33
|
+
'messages' => [{ 'level' => 'error', 'key' => 'RouteNotFound',
|
34
|
+
'dsc' => 'Invalid route' }]
|
35
|
+
}, {format: :json})
|
36
|
+
end
|
37
|
+
|
38
|
+
@response.finish
|
39
|
+
end
|
40
|
+
|
41
|
+
# TODO ver multiples formatos en el futuro
|
42
|
+
def render(content, options = {})
|
43
|
+
format = options[:format] || DEFAULT_RENDER
|
44
|
+
case(format)
|
45
|
+
when :html
|
46
|
+
HtmlRender.render(@response, content)
|
47
|
+
when :json
|
48
|
+
JsonRender.render(@response, content)
|
49
|
+
else
|
50
|
+
raise 'Unknown render format'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# TODO ver esto en el futuro
|
55
|
+
# Use the specified Rack middleware
|
56
|
+
def use(middleware, *args, &block)
|
57
|
+
@prototype = nil
|
58
|
+
@middleware << [middleware, args, block]
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Angus
|
4
|
+
class ResourceDefinition
|
5
|
+
|
6
|
+
def initialize(resource_name, representations)
|
7
|
+
@resource_name = resource_name
|
8
|
+
@resource_class_name = classify_resource(resource_name)
|
9
|
+
@representations = representations || {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def operations
|
13
|
+
@representations.operations[@resource_name.to_s]
|
14
|
+
end
|
15
|
+
|
16
|
+
def canonical_name
|
17
|
+
Angus::String.underscore(@resource_class_name.to_s)
|
18
|
+
end
|
19
|
+
|
20
|
+
def resource_class
|
21
|
+
return @resource_class if @resource_class
|
22
|
+
require resource_path
|
23
|
+
|
24
|
+
@resource_class = Object.const_get(@resource_class_name)
|
25
|
+
end
|
26
|
+
|
27
|
+
def resource_path
|
28
|
+
File.join('resources', canonical_name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def build_response_metadata(response_representation)
|
32
|
+
return {} unless response_representation
|
33
|
+
|
34
|
+
case response_representation
|
35
|
+
when Angus::SDoc::Definitions::Representation
|
36
|
+
result = []
|
37
|
+
|
38
|
+
response_representation.fields.each do |field|
|
39
|
+
result << build_response_metadata(field)
|
40
|
+
end
|
41
|
+
|
42
|
+
result
|
43
|
+
when Array
|
44
|
+
result = []
|
45
|
+
|
46
|
+
response_representation.each do |field|
|
47
|
+
result << build_response_metadata(field)
|
48
|
+
end
|
49
|
+
|
50
|
+
result
|
51
|
+
else
|
52
|
+
field_name = response_representation.name
|
53
|
+
field_type = response_representation.type || response_representation.elements_type
|
54
|
+
|
55
|
+
# TODO fix this
|
56
|
+
representation = representation_by_name(field_type)
|
57
|
+
|
58
|
+
if representation.nil?
|
59
|
+
field_name.to_sym
|
60
|
+
else
|
61
|
+
{field_name.to_sym => build_response_metadata(representation)}
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# TODO improve this find
|
67
|
+
def representation_by_name(name)
|
68
|
+
@representations.representations.find { |representation| representation.name == name }
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def classify_resource(resource)
|
74
|
+
Angus::String.camelize(resource)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Angus
|
2
|
+
class Response < Rack::Response
|
3
|
+
def initialize(*)
|
4
|
+
super
|
5
|
+
headers['Content-Type'] ||= 'text/html'
|
6
|
+
end
|
7
|
+
|
8
|
+
def body=(value)
|
9
|
+
value = value.body while Rack::Response === value
|
10
|
+
@body = String === value ? [value.to_str] : value
|
11
|
+
end
|
12
|
+
|
13
|
+
def each
|
14
|
+
block_given? ? super : enum_for(:each)
|
15
|
+
end
|
16
|
+
|
17
|
+
def finish
|
18
|
+
result = body
|
19
|
+
|
20
|
+
if drop_content_info?
|
21
|
+
headers.delete "Content-Length"
|
22
|
+
headers.delete "Content-Type"
|
23
|
+
end
|
24
|
+
|
25
|
+
if drop_body?
|
26
|
+
close
|
27
|
+
result = []
|
28
|
+
end
|
29
|
+
|
30
|
+
if calculate_content_length?
|
31
|
+
# if some other code has already set Content-Length, don't muck with it
|
32
|
+
# currently, this would be the static file-handler
|
33
|
+
headers["Content-Length"] = body.inject(0) { |l, p| l + Rack::Utils.bytesize(p) }.to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
[status.to_i, headers, result]
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def calculate_content_length?
|
42
|
+
headers["Content-Type"] and not headers["Content-Length"] and Array === body
|
43
|
+
end
|
44
|
+
|
45
|
+
def drop_content_info?
|
46
|
+
status.to_i / 100 == 1 or drop_body?
|
47
|
+
end
|
48
|
+
|
49
|
+
def drop_body?
|
50
|
+
[204, 205, 304].include?(status.to_i)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
require 'angus/sdoc'
|
2
|
+
|
3
|
+
module Angus
|
4
|
+
module Responses
|
5
|
+
|
6
|
+
HTTP_STATUS_CODE_OK = 200
|
7
|
+
|
8
|
+
HTTP_STATUS_CODE_FORBIDDEN = 403
|
9
|
+
HTTP_STATUS_CODE_NOT_FOUND = 404
|
10
|
+
HTTP_STATUS_CODE_CONFLICT = 409
|
11
|
+
HTTP_STATUS_CODE_UNPROCESSABLE_ENTITY = 422
|
12
|
+
|
13
|
+
HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR = 500
|
14
|
+
|
15
|
+
# Returns a suitable HTTP status code for the given error
|
16
|
+
#
|
17
|
+
# If error param responds to #errors, then #{HTTP_STATUS_CODE_CONFLICT} will be returned.
|
18
|
+
#
|
19
|
+
# If error param responds to #error_key, then the status_code associated
|
20
|
+
# with the message will be returned.
|
21
|
+
#
|
22
|
+
# @param [#errors, #error_key] error An error object
|
23
|
+
#
|
24
|
+
# @return [Integer] HTTP status code
|
25
|
+
def get_error_status_code(error)
|
26
|
+
if error.respond_to?(:errors)
|
27
|
+
return HTTP_STATUS_CODE_CONFLICT
|
28
|
+
end
|
29
|
+
|
30
|
+
message = get_error_definition(error)
|
31
|
+
|
32
|
+
if message
|
33
|
+
message.status_code
|
34
|
+
else
|
35
|
+
HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns the error definition.
|
40
|
+
#
|
41
|
+
# If the error does not responds to error_key nil will be returned, see EvolutionError.
|
42
|
+
#
|
43
|
+
# @param [#error_key] error An error object
|
44
|
+
#
|
45
|
+
# @return [Hash]
|
46
|
+
def get_error_definition(error)
|
47
|
+
error_key = error.class.name
|
48
|
+
|
49
|
+
get_message_definition(error_key, Angus::SDoc::Definitions::Message::ERROR_LEVEL)
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_message_definition(key, level)
|
53
|
+
message = @definitions.messages.find { |name, definition|
|
54
|
+
name == key.to_s && definition.level.downcase == level.downcase
|
55
|
+
}
|
56
|
+
|
57
|
+
message.last if message
|
58
|
+
end
|
59
|
+
|
60
|
+
# Builds a service success response
|
61
|
+
#
|
62
|
+
# @param [Hash<Symbol, Object>] messages Elements to be sent in the response
|
63
|
+
# @param [Array<ResponseMessage] messages Messages to be sent in the response
|
64
|
+
#
|
65
|
+
# @return [String] JSON response
|
66
|
+
def build_success_response(elements = {}, messages = [])
|
67
|
+
elements = {
|
68
|
+
:status => :success,
|
69
|
+
}.merge(elements)
|
70
|
+
|
71
|
+
unless messages.empty?
|
72
|
+
elements[:messages] = messages
|
73
|
+
end
|
74
|
+
|
75
|
+
json(elements)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Builds a service error response
|
79
|
+
def build_error_response(error)
|
80
|
+
error_messages = messages_from_error(error)
|
81
|
+
build_response(:error, *error_messages)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Builds a ResponseMessage object
|
85
|
+
#
|
86
|
+
# @param [#to_s] key Message key
|
87
|
+
# @param [#to_s] level Message level
|
88
|
+
# @param [*Object] params Objects to be used when formatting the message description
|
89
|
+
#
|
90
|
+
# @raise [NameError] when there's no message for the given key and level
|
91
|
+
#
|
92
|
+
# @return [ResponseMessage]
|
93
|
+
def build_message(key, level, *params)
|
94
|
+
message_definition = get_message_definition(key, level)
|
95
|
+
|
96
|
+
unless message_definition
|
97
|
+
raise NameError.new("Could not found message with key: #{key}, level: #{level}")
|
98
|
+
end
|
99
|
+
|
100
|
+
description = if message_definition.text
|
101
|
+
message_definition.text % params
|
102
|
+
else
|
103
|
+
message_definition.description
|
104
|
+
end
|
105
|
+
|
106
|
+
Angus::SDoc::Definitions::Message
|
107
|
+
|
108
|
+
message = Angus::SDoc::Definitions::Message.new
|
109
|
+
message.key = key
|
110
|
+
message.level = level
|
111
|
+
message.description = description
|
112
|
+
|
113
|
+
message
|
114
|
+
end
|
115
|
+
|
116
|
+
# Builds a service success response
|
117
|
+
def build_warning_response(error)
|
118
|
+
error_messages = messages_from_error(error, :warning)
|
119
|
+
build_response(:success, *error_messages)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Builds a success response with the received data
|
123
|
+
#
|
124
|
+
# @param [Hash] data the hash to be returned in the response
|
125
|
+
# @param [Array] attributes the attributes that will be returned
|
126
|
+
# @param [Message, Symbol, String] messages A list of messages, or message keys
|
127
|
+
def build_data_response(data, attributes, messages = [])
|
128
|
+
marshalled_data = Angus::Marshalling.marshal_object(data, attributes)
|
129
|
+
|
130
|
+
messages = build_messages(Angus::SDoc::Definitions::Message::INFO_LEVEL, messages)
|
131
|
+
|
132
|
+
build_success_response(marshalled_data, messages)
|
133
|
+
end
|
134
|
+
|
135
|
+
# Builds a success response with no elements
|
136
|
+
#
|
137
|
+
# The response would include the following:
|
138
|
+
# - status
|
139
|
+
# - messages
|
140
|
+
#
|
141
|
+
# @param [Array<ResponseMessage>, Array<Symbol>] messages Message to be included in the response
|
142
|
+
#
|
143
|
+
# @return [String] JSON response
|
144
|
+
def build_no_data_response(messages = [])
|
145
|
+
messages = build_messages(Angus::SDoc::Definitions::Message::INFO_LEVEL, messages)
|
146
|
+
|
147
|
+
build_success_response({}, messages)
|
148
|
+
end
|
149
|
+
|
150
|
+
# Builds a list of messages with the following level
|
151
|
+
#
|
152
|
+
# ResponseMessage objects contained in messages param won't be modified, this method
|
153
|
+
# only creates ResponseMessage for each Symbol in messages array
|
154
|
+
#
|
155
|
+
# @param [#to_s] level Messages level
|
156
|
+
# @param [Array<ResponseMessage>, Array<Symbol>] messages
|
157
|
+
#
|
158
|
+
# @raise (see #build_message)
|
159
|
+
#
|
160
|
+
# @return [Array<ResponseMessage>]
|
161
|
+
def build_messages(level, messages)
|
162
|
+
(messages || []).map do |message|
|
163
|
+
if message.kind_of?(Angus::SDoc::Definitions::Message)
|
164
|
+
message
|
165
|
+
else
|
166
|
+
build_message(message, level)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# Sets the content_type to json and serialize +element+ as json
|
172
|
+
def json(element)
|
173
|
+
#content_type :json
|
174
|
+
JSON(element, :ascii_only => true)
|
175
|
+
end
|
176
|
+
|
177
|
+
private
|
178
|
+
# Returns an array of messages errors to be sent in an operation response
|
179
|
+
#
|
180
|
+
# If {error} respond_to? :errors then the method returns one error message
|
181
|
+
# for each one.
|
182
|
+
#
|
183
|
+
# Each message returned is a hash with:
|
184
|
+
# - level
|
185
|
+
# - key
|
186
|
+
# - description
|
187
|
+
#
|
188
|
+
# @param [Exception] error The error to be returned
|
189
|
+
#
|
190
|
+
# @return [Array] an array of messages
|
191
|
+
def messages_from_error(error, level = :error)
|
192
|
+
messages = []
|
193
|
+
|
194
|
+
if error.respond_to?(:errors)
|
195
|
+
error.errors.each do |key, description|
|
196
|
+
messages << {:level => level, :key => key, :dsc => description}
|
197
|
+
end
|
198
|
+
elsif error.respond_to?(:error_key)
|
199
|
+
messages << {:level => level, :key => error.error_key,
|
200
|
+
:dsc => error_message(error)}
|
201
|
+
else
|
202
|
+
messages << {:level => level, :key => error.class.name, :dsc => error.message}
|
203
|
+
end
|
204
|
+
|
205
|
+
messages
|
206
|
+
end
|
207
|
+
|
208
|
+
# Returns the message for an error.
|
209
|
+
#
|
210
|
+
# It first tries to get the message from text attribute of the error definition
|
211
|
+
# if no definition is found or if the text attribute is blank it the returns the error
|
212
|
+
# message attribute.
|
213
|
+
#
|
214
|
+
# @param [Exception] error The error to get the message for.
|
215
|
+
#
|
216
|
+
# @return [String] the error message.
|
217
|
+
def error_message(error)
|
218
|
+
error_definition = get_error_definition(error)
|
219
|
+
|
220
|
+
if error_definition && !error_definition.text.blank?
|
221
|
+
error_definition.text
|
222
|
+
else
|
223
|
+
error.message
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def build_response(status, *messages)
|
228
|
+
json(:status => status, :messages => messages)
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
232
|
+
end
|