json_error 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 710945ff34e88690adf8b1287c718d8a1452fd22
4
+ data.tar.gz: b99fed58240fc196859f26225809d5095d22a119
5
+ SHA512:
6
+ metadata.gz: 05856bbb8024a62a2733bc783ecc06cbd312cffcada7e4e0caf4935845d2b80b8a4c1d6c9150100fde8673a88aeccc15a52c3e3b2ce2ccbcf81a11d0882f7e47
7
+ data.tar.gz: 791ffbea2fa34ac4aaa4a4241eeb8ab14d25000c6c6d8e50201b1e05a3f8ca124bd6dd3423e285294ffe993d87f7aae4f512b6e882911390ef0a0ed36c49ca95
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/.rubocop.yml ADDED
@@ -0,0 +1,2 @@
1
+ Style/Documentation:
2
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.0
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Krzysztof Buszewicz
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,165 @@
1
+ # JSONError
2
+
3
+ [![Code Climate](https://codeclimate.com/github/buszu/json_error/badges/gpa.svg)](https://codeclimate.com/github/buszu/json_error)
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'json_error', github: 'buszu/json_error'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ ## Usage
18
+
19
+ ### Defining JSONErrors
20
+
21
+ ```ruby
22
+ module Errors
23
+ class ResourceNotFound < JSONError.base
24
+ def initialize(options = {})
25
+ # Add required :key option
26
+ options.merge!(key: :resource_not_found)
27
+ super(options)
28
+ end
29
+ end
30
+
31
+ class OtherError < JSONError.base
32
+ # Slice response JSON properties
33
+ def self.properties
34
+ super - %i(href description)
35
+ end
36
+
37
+ options.merge!(key: :other_error)
38
+ super(options)
39
+ end
40
+ end
41
+ ```
42
+
43
+ ### Defining JSONError Properties
44
+
45
+ Add entries below to your locale.
46
+
47
+ ```yml
48
+ en:
49
+ errors:
50
+ resource_not_found:
51
+ status: 404
52
+ message: 'Resource %{name} (%{id}) was not found.'
53
+ description: 'Blah blah blah.'
54
+ href: 'https://developers.api.pl/doc/errors/resource_not_found'
55
+ ```
56
+
57
+ ### Rendering JSONError
58
+
59
+ #### Rails
60
+
61
+ ```ruby
62
+ # app/controllers/batmans_controller.rb
63
+ class BatmansController < ApplicationController
64
+ def index
65
+ error = Errors::ResourceNotFound.new(name: :Batman, id: 2)
66
+ render json: error, status: error.status
67
+ end
68
+ end
69
+
70
+ # or
71
+
72
+ class BatmansController < ApplicationController
73
+ def index
74
+ raise Errors::ResourceNotFound, name: :Batman, id: 2
75
+ rescue JSONError.base => e
76
+ render json: e, status: e.status
77
+ end
78
+ end
79
+ ```
80
+
81
+ #### Sinatra
82
+
83
+ ```ruby
84
+ # Remember to load dependencies
85
+
86
+ class Application < Sinatra::Base
87
+ before { content_type :json }
88
+
89
+ get '/batmans' do
90
+ error = Errors::ResourceNotFound.new(name: :Batman, id: 2)
91
+ halt error.status, json(error)
92
+ end
93
+ end
94
+ ```
95
+
96
+ ### Responses
97
+
98
+ #### For ResourceNotFound
99
+
100
+ ```js
101
+ {
102
+ "status": 404,
103
+ "key": "resource_not_found",
104
+ "message": "Resource Batman (2) was not found.",
105
+ "description": "Blah blah blah.",
106
+ "href": "https://developers.api.pl/doc/errors/resource_not_found"
107
+ }
108
+ ```
109
+
110
+ #### For OtherError
111
+ ```js
112
+ {
113
+ "status": 500,
114
+ "key": "other_error",
115
+ "message": null
116
+ }
117
+ ```
118
+
119
+ ### Using Contexts
120
+
121
+ You can specify different contexts for the same error key.
122
+
123
+ ```yml
124
+ # In locale
125
+
126
+ en:
127
+ errors:
128
+ resource_not_found:
129
+ status: 404
130
+ message: 'Resource %{name} (%{id}) was not found.'
131
+ description: 'Blah blah blah.'
132
+ href: 'https://developers.api.pl/doc/errors/resource_not_found'
133
+ batmans:
134
+ resource_not_found:
135
+ status: 404
136
+ message: 'Resource Batman (%{id}) was not found.'
137
+ description: "Cuz I'm Batman"
138
+ ```
139
+
140
+ ```ruby
141
+ # In constructor
142
+
143
+ Errors::ResourceNotFound.new(context: 'batmans', id: 2)
144
+ ```
145
+
146
+ ```js
147
+ // And then response will look like below
148
+
149
+ {
150
+ "status": 404,
151
+ "key": "resource_not_found",
152
+ "message": "Resource Batman (2) was not found.",
153
+ "description": "Cuz I'm Batman",
154
+ "href": null
155
+ }
156
+ ```
157
+
158
+ ## Contributing
159
+
160
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/json_error.
161
+
162
+
163
+ ## License
164
+
165
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
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/console ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'json_error'
5
+
6
+ require 'irb'
7
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,5 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
3
+
4
+ require 'json_error/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'json_error'
8
+ s.version = JSONError::VERSION
9
+ s.summary = 'JSON errors base for APIs.'
10
+ s.homepage = 'https://github.com/buszu/json_error'
11
+ s.license = 'MIT'
12
+
13
+ s.authors = ['Krzysztof Buszewicz']
14
+ s.email = ['krzysztof.buszewicz@gmail.com']
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- spec/*`.split("\n")
18
+ s.require_paths = ['lib']
19
+
20
+ s.add_dependency 'json'
21
+ s.add_dependency 'i18n'
22
+
23
+ s.add_development_dependency 'bundler', '~> 1.10'
24
+ s.add_development_dependency 'rake', '~> 10.0'
25
+ s.add_development_dependency 'rspec'
26
+ end
data/lib/json_error.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'i18n'
2
+ require 'json'
3
+ require 'json_error/version'
4
+ require 'json_error/base'
5
+
6
+ module JSONError
7
+ def self.base
8
+ Base
9
+ end
10
+ end
@@ -0,0 +1,59 @@
1
+ module JSONError
2
+ class Base < StandardError
3
+ NULL_TOKEN = '~'
4
+
5
+ attr_reader :context, :key, :options
6
+
7
+ def initialize(attrs = {})
8
+ @context = attrs[:context]
9
+ @key = attrs.fetch(:key)
10
+ @options = attrs.delete_if { |k, _v| %i(key context).include?(k) }
11
+ options.merge!(default: NULL_TOKEN)
12
+ super(message)
13
+ end
14
+
15
+ def self.properties
16
+ %i(status key message description href)
17
+ end
18
+
19
+ def message
20
+ translate(:message)
21
+ end
22
+
23
+ def description
24
+ translate(:description)
25
+ end
26
+
27
+ def href
28
+ translate(:href)
29
+ end
30
+
31
+ def status
32
+ translate(:status, default: 500)
33
+ end
34
+
35
+ def to_json(*args)
36
+ properties.to_json(*args)
37
+ end
38
+
39
+ private
40
+
41
+ def translate(node, translation_options = {})
42
+ translation_options = options.merge(translation_options)
43
+ translation = I18n.t("#{translation_path}.#{node}", translation_options)
44
+ translation unless translation == NULL_TOKEN
45
+ end
46
+
47
+ def translation_path
48
+ context.nil? ? "errors.#{key}" : "errors.#{context}.#{key}"
49
+ end
50
+
51
+ def properties
52
+ { status: status,
53
+ key: key,
54
+ message: message,
55
+ description: description,
56
+ href: href }.delete_if { |k, _v| !self.class.properties.include?(k) }
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,3 @@
1
+ module JSONError
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,7 @@
1
+ en:
2
+ errors:
3
+ resource_not_found:
4
+ status: 404
5
+ message: 'Resource %{name} (%{id}) was not found.'
6
+ description: 'Blah blah blah.'
7
+ href: 'https://developers.api.pl/doc/errors/resource_not_found'
@@ -0,0 +1,142 @@
1
+ require 'spec_helper'
2
+
3
+ describe JSONError::Base do
4
+ describe 'NULL_TOKEN' do
5
+ subject { described_class::NULL_TOKEN }
6
+ it { is_expected.to eq('~') }
7
+ end
8
+
9
+ describe '.superclass' do
10
+ subject { described_class.superclass }
11
+ it { is_expected.to be(StandardError) }
12
+ end
13
+
14
+ describe '.new' do
15
+ context 'called without :key option' do
16
+ subject { -> { described_class.new } }
17
+ it { is_expected.to raise_error(KeyError) }
18
+ end
19
+
20
+ context 'called with :key option' do
21
+ subject { described_class.new(key: :resource_not_found) }
22
+ it { is_expected.to be_a(described_class) }
23
+ end
24
+ end
25
+
26
+ describe '#status' do
27
+ subject { error.status }
28
+
29
+ context 'when not defined in locale' do
30
+ let(:error) { described_class.new(key: :other_error) }
31
+ it { is_expected.to eq(500) }
32
+ end
33
+
34
+ context 'when defined in locale' do
35
+ let(:error) { described_class.new(key: :resource_not_found) }
36
+ it { is_expected.to eq(404) }
37
+ end
38
+ end
39
+
40
+ describe '#key' do
41
+ let(:error) { described_class.new(key: :resource_not_found) }
42
+ subject { error.key }
43
+ it { is_expected.to eq(:resource_not_found) }
44
+ end
45
+
46
+ describe '#message' do
47
+ subject { error.message }
48
+
49
+ context 'when not defined in locale' do
50
+ let(:error) { described_class.new(key: :other_error) }
51
+ it { is_expected.to be_nil }
52
+ end
53
+
54
+ context 'when defined in locale' do
55
+ let(:name) { 'stick' }
56
+ let(:id) { 1 }
57
+ let(:error) do
58
+ described_class.new(key: :resource_not_found, name: name, id: id)
59
+ end
60
+ it { is_expected.to eq("Resource #{name} (#{id}) was not found.") }
61
+ end
62
+ end
63
+
64
+ describe '#description' do
65
+ subject { error.description }
66
+
67
+ context 'when not defined in locale' do
68
+ let(:error) { described_class.new(key: :other_error) }
69
+ it { is_expected.to be_nil }
70
+ end
71
+
72
+ context 'when defined in locale' do
73
+ let(:error) { described_class.new(key: :resource_not_found) }
74
+ it { is_expected.to eq('Blah blah blah.') }
75
+ end
76
+ end
77
+
78
+ describe '#href' do
79
+ subject { error.href }
80
+
81
+ context 'when not defined in locale' do
82
+ let(:error) { described_class.new(key: :other_error) }
83
+ it { is_expected.to be_nil }
84
+ end
85
+
86
+ context 'when defined in locale' do
87
+ let(:error) { described_class.new(key: :resource_not_found) }
88
+ it do
89
+ is_expected.to eq(
90
+ 'https://developers.api.pl/doc/errors/resource_not_found'
91
+ )
92
+ end
93
+ end
94
+ end
95
+
96
+ describe '#to_json' do
97
+ let(:parse) { -> (s) { JSON.parse(s) } }
98
+ subject { error.to_json }
99
+
100
+ context 'when not defined in locale' do
101
+ let(:error) { described_class.new(key: :other_error) }
102
+ it { is_expected.to be_a(String) }
103
+ describe 'status property' do
104
+ it { expect(parse.call(subject)['status']).to eq(500) }
105
+ end
106
+ describe 'key property' do
107
+ it { expect(parse.call(subject)['key']).to eq(error.key.to_s) }
108
+ end
109
+ describe 'message property' do
110
+ it { expect(parse.call(subject)['message']).to be_nil }
111
+ end
112
+ describe 'description property' do
113
+ it { expect(parse.call(subject)['description']).to be_nil }
114
+ end
115
+ describe 'href property' do
116
+ it { expect(parse.call(subject)['href']).to be_nil }
117
+ end
118
+ end
119
+
120
+ context 'when defined in locale' do
121
+ let(:error) { described_class.new(key: :resource_not_found) }
122
+ it { is_expected.to be_a(String) }
123
+ describe 'status property' do
124
+ it { expect(parse.call(subject)['status']).to eq(error.status) }
125
+ end
126
+ describe 'key property' do
127
+ it { expect(parse.call(subject)['key']).to eq(error.key.to_s) }
128
+ end
129
+ describe 'message property' do
130
+ it { expect(parse.call(subject)['message']).to eq(error.message) }
131
+ end
132
+ describe 'description property' do
133
+ it do
134
+ expect(parse.call(subject)['description']).to eq(error.description)
135
+ end
136
+ end
137
+ describe 'href property' do
138
+ it { expect(parse.call(subject)['href']).to eq(error.href) }
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe JSONError do
4
+ describe 'VERSION' do
5
+ subject { described_class::VERSION }
6
+ it { is_expected.not_to be_nil }
7
+ end
8
+
9
+ describe '.base' do
10
+ subject { described_class.base }
11
+ it { is_expected.to be(described_class::Base) }
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'i18n'
4
+
5
+ I18n.load_path = Dir['./spec/fixtures/locales/*.yml']
6
+ require 'json_error'
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: json_error
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Krzysztof Buszewicz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-10-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: i18n
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.10'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description:
84
+ email:
85
+ - krzysztof.buszewicz@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - ".rubocop.yml"
93
+ - ".travis.yml"
94
+ - Gemfile
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - bin/console
99
+ - bin/setup
100
+ - json_error.gemspec
101
+ - lib/json_error.rb
102
+ - lib/json_error/base.rb
103
+ - lib/json_error/version.rb
104
+ - spec/fixtures/locales/en.yml
105
+ - spec/json_error/base_spec.rb
106
+ - spec/json_error_spec.rb
107
+ - spec/spec_helper.rb
108
+ homepage: https://github.com/buszu/json_error
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 2.4.5
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: JSON errors base for APIs.
132
+ test_files:
133
+ - spec/fixtures/locales/en.yml
134
+ - spec/json_error/base_spec.rb
135
+ - spec/json_error_spec.rb
136
+ - spec/spec_helper.rb
137
+ has_rdoc: