jsonapi_errorable 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 73ec568ac9bdcef2b3216712107e7baea1a64fdb
4
+ data.tar.gz: 83d98f0633575e7f885c9eaf4b608988f9fa5218
5
+ SHA512:
6
+ metadata.gz: 4e305fdbf489ffdeead744bc6b9bd451ed882fc110b617ddfff62b539047c8c91fcc7a4700ab7fdb4b33a195ea8332acb230aafa483117a7257dba69ee1af370
7
+ data.tar.gz: 74dfcb7ee472baeb352e47facd63a8d930719bc10af1398e258c1c603758571f2a1e7401d11a04db1431b2a629c8b9993305ffce09d748fb3ce52d1bc35ab24e
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.3
4
+ before_install: gem install bundler -v 1.11.2
data/Appraisals ADDED
@@ -0,0 +1,7 @@
1
+ appraise "rails-4" do
2
+ gem "rails", "~> 4.1"
3
+ end
4
+
5
+ appraise "rails-5" do
6
+ gem "rails", "~> 5.0"
7
+ end
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in jsonapi_errorable.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'appraisal'
8
+ gem 'pry'
9
+ gem 'pry-byebug'
10
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Lee Richmond
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # JsonapiErrorable
2
+
3
+ [![Build Status](https://travis-ci.org/jsonapi-suite/jsonapi_errorable.svg?branch=master)](https://travis-ci.org/jsonapi-suite/jsonapi_errorable)
4
+
5
+ Error handling patterns for jsonapi.org-compatible APIs.
6
+
7
+ [View official documentation](http://jsonapi-suite.github.io/jsonapi_errorable)
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/appraisal ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # This file was generated by Bundler.
5
+ #
6
+ # The application 'appraisal' is installed as part of a gem, and
7
+ # this file is here to facilitate running it.
8
+ #
9
+
10
+ require "pathname"
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
+ Pathname.new(__FILE__).realpath)
13
+
14
+ require "rubygems"
15
+ require "bundler/setup"
16
+
17
+ load Gem.bin_path("appraisal", "appraisal")
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "jsonapi_errorable"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/rspec ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # This file was generated by Bundler.
5
+ #
6
+ # The application 'rspec' is installed as part of a gem, and
7
+ # this file is here to facilitate running it.
8
+ #
9
+
10
+ require "pathname"
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
+ Pathname.new(__FILE__).realpath)
13
+
14
+ require "rubygems"
15
+ require "bundler/setup"
16
+
17
+ load Gem.bin_path("rspec-core", "rspec")
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,13 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 4.1"
6
+
7
+ group :test do
8
+ gem "appraisal"
9
+ gem "pry"
10
+ gem "pry-byebug"
11
+ end
12
+
13
+ gemspec :path => "../"
@@ -0,0 +1,165 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ jsonapi_errorable (0.1.1)
5
+ active_model_serializers (~> 0.10)
6
+ rails (>= 4.1, < 6)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ actionmailer (4.2.6)
12
+ actionpack (= 4.2.6)
13
+ actionview (= 4.2.6)
14
+ activejob (= 4.2.6)
15
+ mail (~> 2.5, >= 2.5.4)
16
+ rails-dom-testing (~> 1.0, >= 1.0.5)
17
+ actionpack (4.2.6)
18
+ actionview (= 4.2.6)
19
+ activesupport (= 4.2.6)
20
+ rack (~> 1.6)
21
+ rack-test (~> 0.6.2)
22
+ rails-dom-testing (~> 1.0, >= 1.0.5)
23
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
24
+ actionview (4.2.6)
25
+ activesupport (= 4.2.6)
26
+ builder (~> 3.1)
27
+ erubis (~> 2.7.0)
28
+ rails-dom-testing (~> 1.0, >= 1.0.5)
29
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
30
+ active_model_serializers (0.10.2)
31
+ actionpack (>= 4.1, < 6)
32
+ activemodel (>= 4.1, < 6)
33
+ jsonapi (~> 0.1.1.beta2)
34
+ railties (>= 4.1, < 6)
35
+ activejob (4.2.6)
36
+ activesupport (= 4.2.6)
37
+ globalid (>= 0.3.0)
38
+ activemodel (4.2.6)
39
+ activesupport (= 4.2.6)
40
+ builder (~> 3.1)
41
+ activerecord (4.2.6)
42
+ activemodel (= 4.2.6)
43
+ activesupport (= 4.2.6)
44
+ arel (~> 6.0)
45
+ activesupport (4.2.6)
46
+ i18n (~> 0.7)
47
+ json (~> 1.7, >= 1.7.7)
48
+ minitest (~> 5.1)
49
+ thread_safe (~> 0.3, >= 0.3.4)
50
+ tzinfo (~> 1.1)
51
+ appraisal (2.1.0)
52
+ bundler
53
+ rake
54
+ thor (>= 0.14.0)
55
+ arel (6.0.3)
56
+ builder (3.2.2)
57
+ byebug (9.0.5)
58
+ coderay (1.1.1)
59
+ concurrent-ruby (1.0.2)
60
+ diff-lcs (1.2.5)
61
+ erubis (2.7.0)
62
+ globalid (0.3.7)
63
+ activesupport (>= 4.1.0)
64
+ i18n (0.7.0)
65
+ json (1.8.3)
66
+ jsonapi (0.1.1.beta2)
67
+ json (~> 1.8)
68
+ jsonapi_spec_helpers (0.2.0)
69
+ loofah (2.0.3)
70
+ nokogiri (>= 1.5.9)
71
+ mail (2.6.4)
72
+ mime-types (>= 1.16, < 4)
73
+ method_source (0.8.2)
74
+ mime-types (3.1)
75
+ mime-types-data (~> 3.2015)
76
+ mime-types-data (3.2016.0521)
77
+ mini_portile2 (2.1.0)
78
+ minitest (5.9.0)
79
+ nokogiri (1.6.8)
80
+ mini_portile2 (~> 2.1.0)
81
+ pkg-config (~> 1.1.7)
82
+ pkg-config (1.1.7)
83
+ pry (0.10.4)
84
+ coderay (~> 1.1.0)
85
+ method_source (~> 0.8.1)
86
+ slop (~> 3.4)
87
+ pry-byebug (3.4.0)
88
+ byebug (~> 9.0)
89
+ pry (~> 0.10)
90
+ rack (1.6.4)
91
+ rack-test (0.6.3)
92
+ rack (>= 1.0)
93
+ rails (4.2.6)
94
+ actionmailer (= 4.2.6)
95
+ actionpack (= 4.2.6)
96
+ actionview (= 4.2.6)
97
+ activejob (= 4.2.6)
98
+ activemodel (= 4.2.6)
99
+ activerecord (= 4.2.6)
100
+ activesupport (= 4.2.6)
101
+ bundler (>= 1.3.0, < 2.0)
102
+ railties (= 4.2.6)
103
+ sprockets-rails
104
+ rails-deprecated_sanitizer (1.0.3)
105
+ activesupport (>= 4.2.0.alpha)
106
+ rails-dom-testing (1.0.7)
107
+ activesupport (>= 4.2.0.beta, < 5.0)
108
+ nokogiri (~> 1.6.0)
109
+ rails-deprecated_sanitizer (>= 1.0.1)
110
+ rails-html-sanitizer (1.0.3)
111
+ loofah (~> 2.0)
112
+ railties (4.2.6)
113
+ actionpack (= 4.2.6)
114
+ activesupport (= 4.2.6)
115
+ rake (>= 0.8.7)
116
+ thor (>= 0.18.1, < 2.0)
117
+ rake (10.5.0)
118
+ rspec-core (3.5.3)
119
+ rspec-support (~> 3.5.0)
120
+ rspec-expectations (3.5.0)
121
+ diff-lcs (>= 1.2.0, < 2.0)
122
+ rspec-support (~> 3.5.0)
123
+ rspec-mocks (3.5.0)
124
+ diff-lcs (>= 1.2.0, < 2.0)
125
+ rspec-support (~> 3.5.0)
126
+ rspec-rails (3.5.1)
127
+ actionpack (>= 3.0)
128
+ activesupport (>= 3.0)
129
+ railties (>= 3.0)
130
+ rspec-core (~> 3.5.0)
131
+ rspec-expectations (~> 3.5.0)
132
+ rspec-mocks (~> 3.5.0)
133
+ rspec-support (~> 3.5.0)
134
+ rspec-support (3.5.0)
135
+ slop (3.6.0)
136
+ sprockets (3.7.0)
137
+ concurrent-ruby (~> 1.0)
138
+ rack (> 1, < 3)
139
+ sprockets-rails (3.2.0)
140
+ actionpack (>= 4.0)
141
+ activesupport (>= 4.0)
142
+ sprockets (>= 3.0.0)
143
+ sqlite3 (1.3.11)
144
+ thor (0.19.1)
145
+ thread_safe (0.3.5)
146
+ tzinfo (1.2.2)
147
+ thread_safe (~> 0.1)
148
+
149
+ PLATFORMS
150
+ ruby
151
+
152
+ DEPENDENCIES
153
+ appraisal
154
+ bundler (~> 1.11)
155
+ jsonapi_errorable!
156
+ jsonapi_spec_helpers
157
+ pry
158
+ pry-byebug
159
+ rails (~> 4.1)
160
+ rake (~> 10.0)
161
+ rspec-rails (~> 3.0)
162
+ sqlite3
163
+
164
+ BUNDLED WITH
165
+ 1.12.5
@@ -0,0 +1,13 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 5.0"
6
+
7
+ group :test do
8
+ gem "appraisal"
9
+ gem "pry"
10
+ gem "pry-byebug"
11
+ end
12
+
13
+ gemspec :path => "../"
@@ -0,0 +1,170 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ jsonapi_errorable (0.1.1)
5
+ active_model_serializers (~> 0.10)
6
+ rails (>= 4.1, < 6)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ actioncable (5.0.0.1)
12
+ actionpack (= 5.0.0.1)
13
+ nio4r (~> 1.2)
14
+ websocket-driver (~> 0.6.1)
15
+ actionmailer (5.0.0.1)
16
+ actionpack (= 5.0.0.1)
17
+ actionview (= 5.0.0.1)
18
+ activejob (= 5.0.0.1)
19
+ mail (~> 2.5, >= 2.5.4)
20
+ rails-dom-testing (~> 2.0)
21
+ actionpack (5.0.0.1)
22
+ actionview (= 5.0.0.1)
23
+ activesupport (= 5.0.0.1)
24
+ rack (~> 2.0)
25
+ rack-test (~> 0.6.3)
26
+ rails-dom-testing (~> 2.0)
27
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
28
+ actionview (5.0.0.1)
29
+ activesupport (= 5.0.0.1)
30
+ builder (~> 3.1)
31
+ erubis (~> 2.7.0)
32
+ rails-dom-testing (~> 2.0)
33
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
34
+ active_model_serializers (0.10.2)
35
+ actionpack (>= 4.1, < 6)
36
+ activemodel (>= 4.1, < 6)
37
+ jsonapi (~> 0.1.1.beta2)
38
+ railties (>= 4.1, < 6)
39
+ activejob (5.0.0.1)
40
+ activesupport (= 5.0.0.1)
41
+ globalid (>= 0.3.6)
42
+ activemodel (5.0.0.1)
43
+ activesupport (= 5.0.0.1)
44
+ activerecord (5.0.0.1)
45
+ activemodel (= 5.0.0.1)
46
+ activesupport (= 5.0.0.1)
47
+ arel (~> 7.0)
48
+ activesupport (5.0.0.1)
49
+ concurrent-ruby (~> 1.0, >= 1.0.2)
50
+ i18n (~> 0.7)
51
+ minitest (~> 5.1)
52
+ tzinfo (~> 1.1)
53
+ appraisal (2.1.0)
54
+ bundler
55
+ rake
56
+ thor (>= 0.14.0)
57
+ arel (7.1.1)
58
+ builder (3.2.2)
59
+ byebug (9.0.5)
60
+ coderay (1.1.1)
61
+ concurrent-ruby (1.0.2)
62
+ diff-lcs (1.2.5)
63
+ erubis (2.7.0)
64
+ globalid (0.3.7)
65
+ activesupport (>= 4.1.0)
66
+ i18n (0.7.0)
67
+ json (1.8.3)
68
+ jsonapi (0.1.1.beta2)
69
+ json (~> 1.8)
70
+ jsonapi_spec_helpers (0.2.0)
71
+ loofah (2.0.3)
72
+ nokogiri (>= 1.5.9)
73
+ mail (2.6.4)
74
+ mime-types (>= 1.16, < 4)
75
+ method_source (0.8.2)
76
+ mime-types (3.1)
77
+ mime-types-data (~> 3.2015)
78
+ mime-types-data (3.2016.0521)
79
+ mini_portile2 (2.1.0)
80
+ minitest (5.9.0)
81
+ nio4r (1.2.1)
82
+ nokogiri (1.6.8)
83
+ mini_portile2 (~> 2.1.0)
84
+ pkg-config (~> 1.1.7)
85
+ pkg-config (1.1.7)
86
+ pry (0.10.4)
87
+ coderay (~> 1.1.0)
88
+ method_source (~> 0.8.1)
89
+ slop (~> 3.4)
90
+ pry-byebug (3.4.0)
91
+ byebug (~> 9.0)
92
+ pry (~> 0.10)
93
+ rack (2.0.1)
94
+ rack-test (0.6.3)
95
+ rack (>= 1.0)
96
+ rails (5.0.0.1)
97
+ actioncable (= 5.0.0.1)
98
+ actionmailer (= 5.0.0.1)
99
+ actionpack (= 5.0.0.1)
100
+ actionview (= 5.0.0.1)
101
+ activejob (= 5.0.0.1)
102
+ activemodel (= 5.0.0.1)
103
+ activerecord (= 5.0.0.1)
104
+ activesupport (= 5.0.0.1)
105
+ bundler (>= 1.3.0, < 2.0)
106
+ railties (= 5.0.0.1)
107
+ sprockets-rails (>= 2.0.0)
108
+ rails-dom-testing (2.0.1)
109
+ activesupport (>= 4.2.0, < 6.0)
110
+ nokogiri (~> 1.6.0)
111
+ rails-html-sanitizer (1.0.3)
112
+ loofah (~> 2.0)
113
+ railties (5.0.0.1)
114
+ actionpack (= 5.0.0.1)
115
+ activesupport (= 5.0.0.1)
116
+ method_source
117
+ rake (>= 0.8.7)
118
+ thor (>= 0.18.1, < 2.0)
119
+ rake (10.5.0)
120
+ rspec-core (3.5.3)
121
+ rspec-support (~> 3.5.0)
122
+ rspec-expectations (3.5.0)
123
+ diff-lcs (>= 1.2.0, < 2.0)
124
+ rspec-support (~> 3.5.0)
125
+ rspec-mocks (3.5.0)
126
+ diff-lcs (>= 1.2.0, < 2.0)
127
+ rspec-support (~> 3.5.0)
128
+ rspec-rails (3.5.1)
129
+ actionpack (>= 3.0)
130
+ activesupport (>= 3.0)
131
+ railties (>= 3.0)
132
+ rspec-core (~> 3.5.0)
133
+ rspec-expectations (~> 3.5.0)
134
+ rspec-mocks (~> 3.5.0)
135
+ rspec-support (~> 3.5.0)
136
+ rspec-support (3.5.0)
137
+ slop (3.6.0)
138
+ sprockets (3.7.0)
139
+ concurrent-ruby (~> 1.0)
140
+ rack (> 1, < 3)
141
+ sprockets-rails (3.2.0)
142
+ actionpack (>= 4.0)
143
+ activesupport (>= 4.0)
144
+ sprockets (>= 3.0.0)
145
+ sqlite3 (1.3.11)
146
+ thor (0.19.1)
147
+ thread_safe (0.3.5)
148
+ tzinfo (1.2.2)
149
+ thread_safe (~> 0.1)
150
+ websocket-driver (0.6.4)
151
+ websocket-extensions (>= 0.1.0)
152
+ websocket-extensions (0.1.2)
153
+
154
+ PLATFORMS
155
+ ruby
156
+
157
+ DEPENDENCIES
158
+ appraisal
159
+ bundler (~> 1.11)
160
+ jsonapi_errorable!
161
+ jsonapi_spec_helpers
162
+ pry
163
+ pry-byebug
164
+ rails (~> 5.0)
165
+ rake (~> 10.0)
166
+ rspec-rails (~> 3.0)
167
+ sqlite3
168
+
169
+ BUNDLED WITH
170
+ 1.12.5
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'jsonapi_errorable/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "jsonapi_errorable"
8
+ spec.version = JsonapiErrorable::VERSION
9
+ spec.authors = ["Lee Richmond"]
10
+ spec.email = ["lrichmond1@bloomberg.net"]
11
+
12
+ spec.summary = %q{jsonapi.org compatible error handling}
13
+ spec.description = %q{Handles application errors and model validations}
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'rails', [">= 4.1", "< 6"]
22
+ spec.add_dependency 'active_model_serializers', '~> 0.10'
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.11"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec-rails", "~> 3.0"
27
+ spec.add_development_dependency "sqlite3"
28
+ spec.add_development_dependency "jsonapi_spec_helpers"
29
+ end
@@ -0,0 +1,67 @@
1
+ require 'active_model_serializers'
2
+ require 'jsonapi_errorable/version'
3
+ require 'jsonapi_errorable/exception_handler'
4
+ require 'jsonapi_errorable/validatable'
5
+ require 'jsonapi_errorable/serializers/validation_serializer'
6
+
7
+ module JsonapiErrorable
8
+ def self.included(klass)
9
+ klass.class_eval do
10
+ class << self
11
+ attr_accessor :_errorable_registry
12
+ end
13
+
14
+ def self.inherited(subklass)
15
+ subklass._errorable_registry = self._errorable_registry.dup
16
+ end
17
+ end
18
+ klass._errorable_registry = {}
19
+ klass.send(:include, Validatable)
20
+ klass.extend ClassMethods
21
+ end
22
+
23
+ def self.disable!
24
+ @enabled = false
25
+ end
26
+
27
+ def self.enable!
28
+ @enabled = true
29
+ end
30
+
31
+ def self.disabled?
32
+ @enabled == false
33
+ end
34
+
35
+ def self.logger
36
+ @logger ||= defined?(Rails) ? Rails.logger : Logger.new($stdout)
37
+ end
38
+
39
+ def self.logger=(logger)
40
+ @logger = logger
41
+ end
42
+
43
+ def handle_exception(e)
44
+ raise e if JsonapiErrorable.disabled?
45
+
46
+ exception_klass = self.class._errorable_registry[e.class] || default_exception_handler.new
47
+ exception_klass.log(e)
48
+ json = exception_klass.error_payload(e)
49
+ status = exception_klass.status_code(e)
50
+ render json: json, status: status
51
+ end
52
+
53
+ def default_exception_handler
54
+ self.class.default_exception_handler
55
+ end
56
+
57
+ module ClassMethods
58
+ def register_exception(klass, options = {})
59
+ exception_klass = options[:handler] || default_exception_handler
60
+ self._errorable_registry[klass] = exception_klass.new(options)
61
+ end
62
+
63
+ def default_exception_handler
64
+ JsonapiErrorable::ExceptionHandler
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,81 @@
1
+ module JsonapiErrorable
2
+ class ExceptionHandler
3
+ def initialize(options = {})
4
+ @status = options[:status]
5
+ @title = options[:title]
6
+ @message = options[:message]
7
+ @log = options[:log]
8
+ end
9
+
10
+ def status_code(error)
11
+ @status || 500
12
+ end
13
+
14
+ def error_code(error)
15
+ status_code = status_code(error)
16
+ Rack::Utils::SYMBOL_TO_STATUS_CODE.invert[status_code]
17
+ end
18
+
19
+ def backtrace_cleaner
20
+ defined?(Rails) ? Rails.backtrace_cleaner : nil
21
+ end
22
+
23
+ def title
24
+ @title || 'Error'
25
+ end
26
+
27
+ def detail(error)
28
+ if @message == true
29
+ error.message
30
+ else
31
+ @message ? @message.call(error) : default_detail
32
+ end
33
+ end
34
+
35
+ def meta(error)
36
+ {}
37
+ end
38
+
39
+ def error_payload(error)
40
+ {
41
+ errors: [
42
+ code: error_code(error),
43
+ status: status_code(error).to_s,
44
+ title: title,
45
+ detail: detail(error),
46
+ meta: meta(error)
47
+ ]
48
+ }
49
+ end
50
+
51
+ def log?
52
+ @log != false
53
+ end
54
+
55
+ def log(error)
56
+ return unless log?
57
+ backtrace = error.backtrace
58
+
59
+ if cleaner = backtrace_cleaner
60
+ backtrace = cleaner.clean(backtrace)
61
+ end
62
+
63
+ log_error(error, backtrace)
64
+ end
65
+
66
+ private
67
+
68
+ def log_error(e, backtrace)
69
+ logger.error "\033[31mERROR: #{e.class}: #{e.message}\033[0m"
70
+ logger.error "\033[31m#{backtrace.join("\n")}\033[0m"
71
+ end
72
+
73
+ def logger
74
+ JsonapiErrorable.logger
75
+ end
76
+
77
+ def default_detail
78
+ "We've notified our engineers and hope to address this issue shortly."
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,50 @@
1
+ module JsonapiErrorable
2
+ module Serializers
3
+ class ValidationSerializer < ActiveModel::Serializer
4
+ attribute :errors
5
+
6
+ def errors
7
+ object.errors.to_hash.map do |attribute, messages|
8
+ messages.map do |message|
9
+ {
10
+ code: 'unprocessable_entity',
11
+ status: '422',
12
+ title: 'Validation Error',
13
+ detail: "#{attribute.capitalize} #{message}",
14
+ source: { pointer: pointer_for(object, attribute) },
15
+ meta: { attribute: attribute, message: message }
16
+ }
17
+ end
18
+ end.flatten
19
+ end
20
+
21
+ def activerecord?
22
+ object.is_a?(ActiveRecord::Base)
23
+ end
24
+
25
+ def relationship?(name)
26
+ return false unless activerecord?
27
+
28
+ relation_names = object.class.reflect_on_all_associations.map(&:name)
29
+ relation_names.include?(name)
30
+ end
31
+
32
+ def attribute?(name)
33
+ object.respond_to?(name)
34
+ end
35
+
36
+ private
37
+
38
+ def pointer_for(object, name)
39
+ if relationship?(name)
40
+ "/data/relationships/#{name}"
41
+ elsif attribute?(name)
42
+ "/data/attributes/#{name}"
43
+ else
44
+ # Probably a nested relation, like post.comments
45
+ "/data/relationships/#{name}"
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,11 @@
1
+ module JsonapiErrorable
2
+ module Validatable
3
+ def render_errors_for(record)
4
+ render \
5
+ json: record,
6
+ status: :unprocessable_entity,
7
+ serializer: Serializers::ValidationSerializer,
8
+ adapter: :attributes
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module JsonapiErrorable
2
+ VERSION = "0.1.1"
3
+ end
metadata ADDED
@@ -0,0 +1,171 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jsonapi_errorable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Lee Richmond
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-09-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.1'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '6'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '4.1'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '6'
33
+ - !ruby/object:Gem::Dependency
34
+ name: active_model_serializers
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.10'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '0.10'
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.11'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.11'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rake
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '10.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '10.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec-rails
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '3.0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '3.0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: sqlite3
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: jsonapi_spec_helpers
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ description: Handles application errors and model validations
118
+ email:
119
+ - lrichmond1@bloomberg.net
120
+ executables: []
121
+ extensions: []
122
+ extra_rdoc_files: []
123
+ files:
124
+ - ".gitignore"
125
+ - ".rspec"
126
+ - ".travis.yml"
127
+ - Appraisals
128
+ - Gemfile
129
+ - LICENSE.txt
130
+ - README.md
131
+ - Rakefile
132
+ - bin/appraisal
133
+ - bin/console
134
+ - bin/rspec
135
+ - bin/setup
136
+ - gemfiles/rails_4.gemfile
137
+ - gemfiles/rails_4.gemfile.lock
138
+ - gemfiles/rails_5.gemfile
139
+ - gemfiles/rails_5.gemfile.lock
140
+ - jsonapi_errorable.gemspec
141
+ - lib/jsonapi_errorable.rb
142
+ - lib/jsonapi_errorable/exception_handler.rb
143
+ - lib/jsonapi_errorable/serializers/validation_serializer.rb
144
+ - lib/jsonapi_errorable/validatable.rb
145
+ - lib/jsonapi_errorable/version.rb
146
+ homepage:
147
+ licenses:
148
+ - MIT
149
+ metadata: {}
150
+ post_install_message:
151
+ rdoc_options: []
152
+ require_paths:
153
+ - lib
154
+ required_ruby_version: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ required_rubygems_version: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
164
+ requirements: []
165
+ rubyforge_project:
166
+ rubygems_version: 2.4.5.1
167
+ signing_key:
168
+ specification_version: 4
169
+ summary: jsonapi.org compatible error handling
170
+ test_files: []
171
+ has_rdoc: