json_api_responders 1.2.2 → 2.0.0
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 +4 -4
- data/.codeclimate.yml +25 -0
- data/.rubocop.yml +1156 -0
- data/README.md +38 -11
- data/json_api_responders.gemspec +7 -2
- data/lib/json_api_responders/errors.rb +7 -1
- data/lib/json_api_responders/responder/actions.rb +2 -26
- data/lib/json_api_responders/responder/sanitizers.rb +1 -1
- data/lib/json_api_responders/responder.rb +39 -52
- data/lib/json_api_responders/version.rb +3 -3
- data/lib/json_api_responders.rb +14 -42
- metadata +64 -7
data/README.md
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
# JsonApiResponders
|
2
2
|
|
3
|
-
|
3
|
+
[](https://badge.fury.io/rb/json_api_responders)
|
4
|
+
[](https://semaphoreci.com/infinum/json_api_responders)
|
5
|
+
[](https://codeclimate.com/github/infinum/json_api_responders)
|
6
|
+
[](https://codeclimate.com/github/infinum/json_api_responders/coverage)
|
4
7
|
|
5
|
-
|
8
|
+
This gem gives a few convinient methods for working with JSONAPI. It is inspired by responders gem.
|
6
9
|
|
7
10
|
## Installation
|
8
11
|
|
@@ -16,21 +19,45 @@ And then execute:
|
|
16
19
|
|
17
20
|
$ bundle
|
18
21
|
|
19
|
-
|
22
|
+
## Usage
|
20
23
|
|
21
|
-
|
24
|
+
user = User.first
|
25
|
+
respond_with user
|
26
|
+
respond_with user, on_error: { status: :unauthorized, detail: 'Invalid user or password' }
|
27
|
+
respond_with_error, status: 401, detail: 'Bad credentials'
|
22
28
|
|
23
|
-
|
29
|
+
whatever can be passed to controller.render can be passed here:
|
24
30
|
|
25
|
-
|
31
|
+
respond_with user, serializer: UserSerializer
|
26
32
|
|
27
|
-
##
|
33
|
+
## Responses
|
28
34
|
|
29
|
-
|
35
|
+
### index
|
30
36
|
|
31
|
-
|
37
|
+
render json: resource, status: 200
|
32
38
|
|
33
|
-
|
39
|
+
### show
|
40
|
+
|
41
|
+
render json: resource, status: 200
|
42
|
+
|
43
|
+
### create
|
44
|
+
|
45
|
+
if resource.valid?
|
46
|
+
render json: resource, status: 201
|
47
|
+
else
|
48
|
+
render error: errors, status: 409
|
34
49
|
|
35
|
-
|
50
|
+
### update
|
51
|
+
|
52
|
+
if resource.valid?
|
53
|
+
render json: resource, status: 200
|
54
|
+
else
|
55
|
+
render error: errors, status: 409
|
56
|
+
|
57
|
+
### destroy
|
58
|
+
|
59
|
+
head status: 204
|
60
|
+
|
61
|
+
## Contributing
|
36
62
|
|
63
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/infinum/json_api_responders.
|
data/json_api_responders.gemspec
CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
|
|
16
16
|
if spec.respond_to?(:metadata)
|
17
17
|
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
18
18
|
else
|
19
|
-
|
19
|
+
raise('RubyGems 2.0 or newer is required to protect against public gem pushes.')
|
20
20
|
end
|
21
21
|
|
22
22
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
@@ -28,5 +28,10 @@ Gem::Specification.new do |spec|
|
|
28
28
|
|
29
29
|
spec.add_development_dependency 'bundler', '~> 1.11'
|
30
30
|
spec.add_development_dependency 'rake', '~> 10.0'
|
31
|
-
spec.add_development_dependency 'rspec'
|
31
|
+
# spec.add_development_dependency 'rspec-rails'
|
32
|
+
spec.add_development_dependency 'rspec'
|
33
|
+
spec.add_development_dependency 'rack'
|
34
|
+
spec.add_development_dependency 'pry-byebug'
|
35
|
+
spec.add_development_dependency 'simplecov'
|
36
|
+
spec.add_development_dependency 'codeclimate-test-reporter'
|
32
37
|
end
|
@@ -30,7 +30,13 @@ module JsonApiResponders
|
|
30
30
|
|
31
31
|
def message
|
32
32
|
"Unknown controller action '#{action}'.\n"\
|
33
|
-
"Accepted actions are #{
|
33
|
+
"Accepted actions are #{JsonApiResponders::Responder::ACTIONS.join(', ')}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class StatusNotDefined < StandardError
|
38
|
+
def message
|
39
|
+
'Status is not defined'
|
34
40
|
end
|
35
41
|
end
|
36
42
|
end
|
@@ -14,7 +14,7 @@ module JsonApiResponders
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def respond_to_create_action
|
17
|
-
if resource.
|
17
|
+
if resource.valid?
|
18
18
|
self.status ||= :created
|
19
19
|
render_resource
|
20
20
|
else
|
@@ -43,31 +43,7 @@ module JsonApiResponders
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def resource_render_options
|
46
|
-
|
47
|
-
|
48
|
-
render_options.merge(
|
49
|
-
json: resource,
|
50
|
-
serializer_key => serializer_class,
|
51
|
-
include: options[:include],
|
52
|
-
meta: options[:meta]
|
53
|
-
)
|
54
|
-
end
|
55
|
-
|
56
|
-
def serializer_class
|
57
|
-
(relation? ? options[:each_serializer] : options[:serializer]) ||
|
58
|
-
[
|
59
|
-
namespace,
|
60
|
-
"#{resource_class}Serializer"
|
61
|
-
].compact.join('::').constantize
|
62
|
-
end
|
63
|
-
|
64
|
-
def resource_class
|
65
|
-
return resource.model if relation?
|
66
|
-
resource.class
|
67
|
-
end
|
68
|
-
|
69
|
-
def relation?
|
70
|
-
resource.is_a?(ActiveRecord::Relation) || resource.is_a?(Array)
|
46
|
+
render_options.merge(json: resource, **options)
|
71
47
|
end
|
72
48
|
end
|
73
49
|
end
|
@@ -5,68 +5,52 @@ module JsonApiResponders
|
|
5
5
|
class Responder
|
6
6
|
include Actions
|
7
7
|
|
8
|
-
attr_accessor :
|
9
|
-
attr_accessor :status
|
8
|
+
attr_accessor :options
|
10
9
|
attr_reader :resource
|
11
|
-
attr_reader :options
|
12
|
-
attr_reader :params
|
13
10
|
attr_reader :controller
|
14
|
-
attr_reader :namespace
|
15
11
|
|
16
|
-
def initialize(resource, options = {})
|
12
|
+
def initialize(controller, resource = nil, options = {})
|
13
|
+
@controller = controller
|
17
14
|
@resource = resource
|
18
15
|
@options = options
|
19
|
-
self.status = @options[:status] if @options[:status]
|
20
|
-
@params = @options[:params]
|
21
|
-
@controller = @options[:controller]
|
22
|
-
@namespace = @options[:namespace]
|
23
16
|
end
|
24
17
|
|
25
18
|
def respond!
|
26
|
-
|
19
|
+
return send("respond_to_#{action}_action") if ACTIONS.include?(action)
|
20
|
+
raise JsonApiResponders::Errors::UnknownAction, action
|
27
21
|
end
|
28
22
|
|
29
|
-
def
|
30
|
-
self.errors = {
|
31
|
-
errors: [
|
32
|
-
{
|
33
|
-
title: I18n.t("json_api.errors.#{status}.title"),
|
34
|
-
detail: @options[:error_detail] || I18n.t("json_api.errors.#{status}.detail"),
|
35
|
-
status: status_code
|
36
|
-
}
|
37
|
-
]
|
38
|
-
}
|
39
|
-
|
23
|
+
def respond_error
|
40
24
|
render_error
|
41
25
|
end
|
42
26
|
|
43
|
-
|
27
|
+
def status
|
28
|
+
return nil if @options[:status].nil?
|
29
|
+
Sanitizers.status(@options[:status])
|
30
|
+
end
|
44
31
|
|
45
32
|
def status=(status)
|
46
|
-
@status =
|
33
|
+
@options[:status] = status
|
47
34
|
end
|
48
35
|
|
49
|
-
|
50
|
-
Rack::Utils::SYMBOL_TO_STATUS_CODE[status]
|
51
|
-
end
|
36
|
+
private
|
52
37
|
|
53
38
|
def render_error
|
54
|
-
controller.render(
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
39
|
+
controller.render(
|
40
|
+
render_options.merge(
|
41
|
+
json: error_render_options,
|
42
|
+
status: error_status
|
43
|
+
)
|
44
|
+
)
|
59
45
|
end
|
60
46
|
|
61
|
-
def
|
62
|
-
return
|
63
|
-
|
47
|
+
def error_status
|
48
|
+
return Sanitizers.status(on_error(:status)) if on_error(:status)
|
49
|
+
status
|
64
50
|
end
|
65
51
|
|
66
|
-
def
|
67
|
-
|
68
|
-
json: error_response
|
69
|
-
)
|
52
|
+
def action
|
53
|
+
@options[:params][:action]
|
70
54
|
end
|
71
55
|
|
72
56
|
def render_options
|
@@ -76,25 +60,28 @@ module JsonApiResponders
|
|
76
60
|
}
|
77
61
|
end
|
78
62
|
|
79
|
-
def
|
80
|
-
|
63
|
+
def error_render_options
|
64
|
+
errors = { errors: [] }
|
81
65
|
|
82
|
-
errors
|
83
|
-
errors[:errors] ||= []
|
66
|
+
errors[:errors] << { detail: on_error(:detail) } if on_error(:detail)
|
84
67
|
|
85
68
|
resource.errors.each do |attribute, message|
|
86
|
-
errors[:errors] <<
|
87
|
-
title: I18n.t("json_api.errors.#{status}.title"),
|
88
|
-
detail: resource.errors.full_message(attribute, message),
|
89
|
-
status: status_code.to_s,
|
90
|
-
source: {
|
91
|
-
parameter: attribute,
|
92
|
-
pointer: "data/attributes/#{attribute}"
|
93
|
-
}
|
94
|
-
}
|
69
|
+
errors[:errors] << error_response(attribute, message)
|
95
70
|
end
|
96
71
|
|
97
72
|
errors
|
98
73
|
end
|
74
|
+
|
75
|
+
def error_response(attribute, message)
|
76
|
+
{
|
77
|
+
title: I18n.t("json_api.errors.#{status}.title"),
|
78
|
+
detail: resource.errors.full_message(attribute, message),
|
79
|
+
source: { parameter: attribute, pointer: "data/attributes/#{attribute}" }
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
def on_error(key)
|
84
|
+
@options.fetch(:on_error, {}).fetch(key, nil)
|
85
|
+
end
|
99
86
|
end
|
100
87
|
end
|
data/lib/json_api_responders.rb
CHANGED
@@ -6,53 +6,15 @@ module JsonApiResponders
|
|
6
6
|
def self.included(base)
|
7
7
|
base.rescue_from ActiveRecord::RecordNotFound, with: :record_not_found!
|
8
8
|
base.rescue_from ActionController::ParameterMissing, with: :parameter_missing!
|
9
|
-
redefine_authorization(base)
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.redefine_authorization(base)
|
13
|
-
return unless base.instance_methods.include?(:authenticate_user_from_token!)
|
14
|
-
|
15
|
-
base.class_eval do
|
16
|
-
alias_method(:_authenticate_from_token!, :authenticate_user_from_token!)
|
17
|
-
|
18
|
-
define_method :authenticate_user_from_token! do
|
19
|
-
result = catch(:warden) { _authenticate_from_token! }
|
20
|
-
|
21
|
-
return unless result
|
22
|
-
respond_with_error(:unauthorized)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def respond_with_error(error_type, error_detail = nil)
|
30
|
-
case error_type
|
31
|
-
when :unauthorized
|
32
|
-
Responder.new(nil, controller: self, status: :forbidden, error_detail: error_detail).error
|
33
|
-
when :not_found
|
34
|
-
Responder.new(nil, controller: self, status: :not_found).error
|
35
|
-
when :parameter_missing
|
36
|
-
Responder.new(nil, controller: self, status: :unprocessable_entity, error_detail: error_detail).error
|
37
|
-
end
|
38
9
|
end
|
39
10
|
|
40
11
|
def respond_with(resource, options = {})
|
41
|
-
options = {
|
42
|
-
|
43
|
-
params: params,
|
44
|
-
controller: self
|
45
|
-
}.merge(options)
|
46
|
-
|
47
|
-
Responder.new(resource, options).respond!
|
48
|
-
end
|
49
|
-
|
50
|
-
def record_not_found!
|
51
|
-
respond_with_error(:not_found)
|
12
|
+
options = { params: params }.merge(options)
|
13
|
+
Responder.new(self, resource, options).respond!
|
52
14
|
end
|
53
15
|
|
54
|
-
def
|
55
|
-
|
16
|
+
def respond_with_error(status, detail = nil)
|
17
|
+
Responder.new(self, on_error: { status: status, error: detail }).respond_error
|
56
18
|
end
|
57
19
|
|
58
20
|
def deserialized_params
|
@@ -64,6 +26,16 @@ module JsonApiResponders
|
|
64
26
|
)
|
65
27
|
end
|
66
28
|
|
29
|
+
private
|
30
|
+
|
31
|
+
def record_not_found!
|
32
|
+
respond_with_error(:not_found)
|
33
|
+
end
|
34
|
+
|
35
|
+
def parameter_missing!(reason)
|
36
|
+
respond_with_error(:parameter_missing, reason.message)
|
37
|
+
end
|
38
|
+
|
67
39
|
def json_api_parse_options
|
68
40
|
{}
|
69
41
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json_api_responders
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stanko Krtalić Rusendić
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-10-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -42,16 +42,72 @@ dependencies:
|
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rack
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry-byebug
|
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
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: codeclimate-test-reporter
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
53
109
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
110
|
+
version: '0'
|
55
111
|
description: Automatically respond to JSON::API requests
|
56
112
|
email:
|
57
113
|
- stanko.krtalic@gmail.com
|
@@ -59,8 +115,10 @@ executables: []
|
|
59
115
|
extensions: []
|
60
116
|
extra_rdoc_files: []
|
61
117
|
files:
|
118
|
+
- ".codeclimate.yml"
|
62
119
|
- ".gitignore"
|
63
120
|
- ".rspec"
|
121
|
+
- ".rubocop.yml"
|
64
122
|
- ".travis.yml"
|
65
123
|
- Gemfile
|
66
124
|
- README.md
|
@@ -99,4 +157,3 @@ signing_key:
|
|
99
157
|
specification_version: 4
|
100
158
|
summary: Automatically respond to JSON::API requests
|
101
159
|
test_files: []
|
102
|
-
has_rdoc:
|