mirror of
https://github.com/samsonjs/grape-active_model_serializers.git
synced 2026-04-27 14:57:43 +00:00
add custom error formatter (#76)
This commit is contained in:
parent
fab476772e
commit
b2654190c1
6 changed files with 185 additions and 10 deletions
|
|
@ -1,20 +1,48 @@
|
||||||
# This configuration was generated by `rubocop --auto-gen-config`
|
# This configuration was generated by
|
||||||
# on 2015-01-13 18:47:14 -0500 using RuboCop version 0.28.0.
|
# `rubocop --auto-gen-config`
|
||||||
|
# on 2017-10-09 10:22:52 -0500 using RuboCop version 0.41.2.
|
||||||
# The point is for the user to remove these configuration records
|
# The point is for the user to remove these configuration records
|
||||||
# one by one as the offenses are removed from the code base.
|
# one by one as the offenses are removed from the code base.
|
||||||
# Note that changes in the inspected code, or installation of new
|
# Note that changes in the inspected code, or installation of new
|
||||||
# versions of RuboCop, may require this file to be generated again.
|
# versions of RuboCop, may require this file to be generated again.
|
||||||
|
|
||||||
# Offense count: 25
|
# Offense count: 1
|
||||||
# Configuration parameters: AllowURI, URISchemes.
|
|
||||||
Metrics/AbcSize:
|
Metrics/AbcSize:
|
||||||
Max: 20
|
Max: 18
|
||||||
|
|
||||||
# Offense count: 7
|
# Offense count: 1
|
||||||
|
Metrics/CyclomaticComplexity:
|
||||||
|
Max: 9
|
||||||
|
|
||||||
|
# Offense count: 1
|
||||||
|
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes.
|
||||||
|
# URISchemes: http, https
|
||||||
|
Metrics/LineLength:
|
||||||
|
Max: 87
|
||||||
|
|
||||||
|
# Offense count: 1
|
||||||
|
# Configuration parameters: CountComments.
|
||||||
|
Metrics/MethodLength:
|
||||||
|
Max: 18
|
||||||
|
|
||||||
|
# Offense count: 1
|
||||||
|
Metrics/PerceivedComplexity:
|
||||||
|
Max: 11
|
||||||
|
|
||||||
|
# Offense count: 5
|
||||||
Style/Documentation:
|
Style/Documentation:
|
||||||
Enabled: false
|
Exclude:
|
||||||
|
- 'spec/**/*'
|
||||||
|
- 'test/**/*'
|
||||||
|
- 'lib/grape-active_model_serializers/endpoint_extension.rb'
|
||||||
|
- 'lib/grape-active_model_serializers/error_formatter.rb'
|
||||||
|
- 'lib/grape-active_model_serializers/formatter.rb'
|
||||||
|
- 'lib/grape-active_model_serializers/options_builder.rb'
|
||||||
|
- 'lib/grape-active_model_serializers/serializer_resolver.rb'
|
||||||
|
|
||||||
# Offense count: 2
|
# Offense count: 2
|
||||||
# Configuration parameters: Exclude.
|
# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts.
|
||||||
Style/FileName:
|
Style/FileName:
|
||||||
Enabled: false
|
Exclude:
|
||||||
|
- 'lib/grape-active_model_serializers.rb'
|
||||||
|
- 'spec/grape-active_model_serializers_spec.rb'
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
### 1.5.2 (Next)
|
### 1.5.2 (Next)
|
||||||
|
|
||||||
|
* [#76](https://github.com/ruby-grape/grape-active_model_serializers/pull/76): Add custom error formatter - [@xn](https://github.com/xn).
|
||||||
* Your contribution here.
|
* Your contribution here.
|
||||||
|
|
||||||
### 1.5.1 (April 25, 2017)
|
### 1.5.1 (April 25, 2017)
|
||||||
|
|
|
||||||
2
Gemfile
2
Gemfile
|
|
@ -2,7 +2,7 @@ source 'https://rubygems.org'
|
||||||
|
|
||||||
gemspec
|
gemspec
|
||||||
|
|
||||||
case version = ENV['GRAPE_VERSION'] || '~> 0.10.0'
|
case version = ENV['GRAPE_VERSION'] || '~> 1.0.0'
|
||||||
when 'HEAD'
|
when 'HEAD'
|
||||||
gem 'grape', github: 'intridea/grape'
|
gem 'grape', github: 'intridea/grape'
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
require 'active_model_serializers'
|
require 'active_model_serializers'
|
||||||
require 'grape'
|
require 'grape'
|
||||||
require 'grape-active_model_serializers/endpoint_extension'
|
require 'grape-active_model_serializers/endpoint_extension'
|
||||||
|
require 'grape-active_model_serializers/error_formatter'
|
||||||
require 'grape-active_model_serializers/formatter'
|
require 'grape-active_model_serializers/formatter'
|
||||||
require 'grape-active_model_serializers/serializer_resolver'
|
require 'grape-active_model_serializers/serializer_resolver'
|
||||||
require 'grape-active_model_serializers/options_builder'
|
require 'grape-active_model_serializers/options_builder'
|
||||||
|
|
|
||||||
53
lib/grape-active_model_serializers/error_formatter.rb
Normal file
53
lib/grape-active_model_serializers/error_formatter.rb
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
module Grape
|
||||||
|
module ErrorFormatter
|
||||||
|
module ActiveModelSerializers
|
||||||
|
extend Base
|
||||||
|
|
||||||
|
class << self
|
||||||
|
def call(message, backtrace, options = {}, env = nil, original_exception = nil)
|
||||||
|
message = present(message, env) if respond_to?(:present)
|
||||||
|
message = wrap_message(message)
|
||||||
|
|
||||||
|
rescue_options = options[:rescue_options] || {}
|
||||||
|
if rescue_options[:backtrace] && backtrace && !backtrace.empty?
|
||||||
|
message = message.merge(backtrace: backtrace)
|
||||||
|
end
|
||||||
|
if rescue_options[:original_exception] && original_exception
|
||||||
|
message = message
|
||||||
|
.merge(original_exception: original_exception.inspect)
|
||||||
|
end
|
||||||
|
if ::Grape.const_defined? :Json
|
||||||
|
::Grape::Json.dump(message)
|
||||||
|
else
|
||||||
|
::MultiJson.dump(message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def wrap_message(message)
|
||||||
|
if active_model?(message)
|
||||||
|
::ActiveModelSerializers::SerializableResource.new(
|
||||||
|
message,
|
||||||
|
serializer: ActiveModel::Serializer::ErrorSerializer
|
||||||
|
).as_json
|
||||||
|
elsif ok_to_pass_through?(message)
|
||||||
|
message
|
||||||
|
else
|
||||||
|
{ error: message }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def active_model?(message)
|
||||||
|
message.respond_to?(:errors) &&
|
||||||
|
message.errors.is_a?(ActiveModel::Errors)
|
||||||
|
end
|
||||||
|
|
||||||
|
def ok_to_pass_through?(message)
|
||||||
|
message.is_a?(Exceptions::ValidationErrors) ||
|
||||||
|
message.is_a?(Hash)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
92
spec/grape-active_model_serializers/error_formatter_spec.rb
Normal file
92
spec/grape-active_model_serializers/error_formatter_spec.rb
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
require 'grape-active_model_serializers/error_formatter'
|
||||||
|
|
||||||
|
describe Grape::ErrorFormatter::ActiveModelSerializers do
|
||||||
|
subject { Grape::ErrorFormatter::ActiveModelSerializers }
|
||||||
|
let(:backtrace) { ['Line:1'] }
|
||||||
|
let(:options) { Hash.new }
|
||||||
|
let(:env) { { 'api.endpoint' => app.endpoints.first } }
|
||||||
|
let(:original_exception) { StandardError.new('oh noes!') }
|
||||||
|
|
||||||
|
let(:app) {
|
||||||
|
Class.new(Grape::API) do |app|
|
||||||
|
app.format :json
|
||||||
|
app.formatter :jsonapi, Grape::Formatter::ActiveModelSerializers
|
||||||
|
app.error_formatter :jsonapi, Grape::ErrorFormatter::ActiveModelSerializers
|
||||||
|
|
||||||
|
app.namespace('space') do |ns|
|
||||||
|
ns.get('/', root: false) do
|
||||||
|
error!(message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
let(:foo) {
|
||||||
|
Class.new {
|
||||||
|
include ActiveModel::Model
|
||||||
|
|
||||||
|
attr_accessor :name
|
||||||
|
|
||||||
|
def initialize(attributes = {})
|
||||||
|
super
|
||||||
|
errors.add(:name, 'We don\'t like bears')
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
before do
|
||||||
|
ActiveModel::Serializer.config.adapter = :json_api
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
ActiveModel::Serializer.config.adapter = :json
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#call' do
|
||||||
|
context 'message is an activemodel' do
|
||||||
|
let(:message) {
|
||||||
|
foo.new(name: 'bar')
|
||||||
|
}
|
||||||
|
it 'formats the error' do
|
||||||
|
result = subject
|
||||||
|
.call(message, backtrace, options, env, original_exception)
|
||||||
|
json_hash = JSON.parse(result)
|
||||||
|
|
||||||
|
expected_result = {
|
||||||
|
'errors' => [
|
||||||
|
{
|
||||||
|
'source' => {
|
||||||
|
'pointer' => '/data/attributes/name'
|
||||||
|
},
|
||||||
|
'detail' => 'We don\'t like bears'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(json_hash == expected_result).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'message is hash like' do
|
||||||
|
let(:message) { { 'errors' => ['error'] } }
|
||||||
|
it 'passes the message through' do
|
||||||
|
result = subject
|
||||||
|
.call(message, backtrace, options, env, original_exception)
|
||||||
|
json_hash = JSON.parse(result)
|
||||||
|
|
||||||
|
expect(json_hash == message).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'message is text' do
|
||||||
|
let(:message) { 'error' }
|
||||||
|
it 'wraps the error' do
|
||||||
|
result = subject
|
||||||
|
.call(message, backtrace, options, env, original_exception)
|
||||||
|
json_hash = JSON.parse(result)
|
||||||
|
|
||||||
|
expect(json_hash == { 'error' => message }).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Reference in a new issue