roda-contrib 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +3 -0
- data/README.md +2 -1
- data/doc/release_notes/0_3_0.rdoc +6 -0
- data/lib/roda/contrib/plugins/json_api.rb +177 -0
- data/lib/roda/contrib/version.rb +1 -1
- data/lib/roda/plugins/contrib_json_api.rb +3 -0
- data/roda-contrib.gemspec +2 -0
- metadata +32 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 98460898008a6d9fa6213b1d5b77f524a9eac86c
|
4
|
+
data.tar.gz: d58b7165a2d2ba77371768f928ac5acfea445f26
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c879c14dc8f0856ab6b088fd61bae9bd57e51a8704e052f1c8123e1f580b8d934462e3542cfd4ad2641fccff8c187d49701d0040264761312c07e366fb501da
|
7
|
+
data.tar.gz: ec7b4e96e1e8fecf2ad83e4916033083d71d61f98c28fb71ee46ce194169e000efdbbcef898c38d0caf819f4ff79bb157b3bf275ef83ae71fe268de94cc84c93
|
data/CHANGELOG
CHANGED
data/README.md
CHANGED
@@ -21,11 +21,12 @@ Or install it yourself as:
|
|
21
21
|
|
22
22
|
## Usage
|
23
23
|
|
24
|
-
Currently, the roda-contrib gem ships
|
24
|
+
Currently, the roda-contrib gem ships 4 plugins:
|
25
25
|
|
26
26
|
* load\_all
|
27
27
|
* multi\_dispatch
|
28
28
|
* csrf
|
29
|
+
* json\_api
|
29
30
|
|
30
31
|
When loading plugins from this gem, you should append the 'contrib' to the
|
31
32
|
symbol to load it. For example, if you want to use the multi\_dispatch plugin:
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'rack/parser'
|
2
|
+
require 'jsonapi/serializable'
|
3
|
+
require 'jsonapi/deserializable'
|
4
|
+
|
5
|
+
module RodaContrib
|
6
|
+
module Plugins
|
7
|
+
# This plugin intergrate Roda with the jsonapi-rb gem. It offers a simple
|
8
|
+
# interface to users, but a bit opinioned.
|
9
|
+
#
|
10
|
+
# === Prerequest
|
11
|
+
# To use this plugin, you should install the +rack-parser+ and the
|
12
|
+
# +jsonapi-rb+ gem first.
|
13
|
+
#
|
14
|
+
# === Configuration
|
15
|
+
# The +contrib_json_api+ plugin will not complain if you offer nothing to
|
16
|
+
# configure the boring middleware.
|
17
|
+
#
|
18
|
+
# App.plugin :contrib_json_api
|
19
|
+
#
|
20
|
+
# You can use options pass to this plugin to configure the +Rack::Parser+.
|
21
|
+
#
|
22
|
+
# App.plugin :contrib_json_api, {
|
23
|
+
# :parser => { 'application/json' => proc { |data| MultiJSON.parse(data) } },
|
24
|
+
# :handler => { 'application/json' => proc { |e, t| [400, {'Content-Type' => t}, ["broke"]] }
|
25
|
+
# }
|
26
|
+
#
|
27
|
+
# Check the rack-parser documentation for more information
|
28
|
+
#
|
29
|
+
# Optionally, if you already have the rack-parser middleware and don't want
|
30
|
+
# to setup the middleware again, you can use +:skip_middleware+ option to
|
31
|
+
# do so:
|
32
|
+
#
|
33
|
+
# App.plugin :contrib_json_api, skip_middleware: true
|
34
|
+
#
|
35
|
+
# === Usage
|
36
|
+
# The +contrib_json_api+ plugin only expose three methods to use.
|
37
|
+
#
|
38
|
+
# the +represent+ method is used for rendering the resources
|
39
|
+
# represent rc, with: SerializableRc
|
40
|
+
#
|
41
|
+
# the +represent_err+ method is used for rendering the errors, if you don't
|
42
|
+
# offer a title, 'model field validation error' will be used as title. the
|
43
|
+
# status is default to 400.
|
44
|
+
#
|
45
|
+
# represent rc.errors, title: 'gateway not reachable', status: 500
|
46
|
+
#
|
47
|
+
# the +json_params+ method is used to get the parsed data from the request
|
48
|
+
# body.
|
49
|
+
#
|
50
|
+
# a lot of options could be applied to customize the +represent+ and
|
51
|
+
# +represent_err+ method. Checkout the official jsonapi-rb documentation:
|
52
|
+
# https://jsonapi-rb.org/guides
|
53
|
+
#
|
54
|
+
# === Exmaple
|
55
|
+
# class App < Roda
|
56
|
+
# plugin :contrib_json_api
|
57
|
+
#
|
58
|
+
# route do |r|
|
59
|
+
# r.on 'product' do
|
60
|
+
# r.is :id do |id|
|
61
|
+
# @rc = Product.with_pk(id.to_i)
|
62
|
+
#
|
63
|
+
# r.get do
|
64
|
+
# represent @rc, with: SerializableProduct
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# r.post do
|
68
|
+
# @rc.set_fields(json_params)
|
69
|
+
# if @rc.valid?
|
70
|
+
# @rc.save_changes
|
71
|
+
# represent @rc, with: SerializableProduct
|
72
|
+
# else
|
73
|
+
# represent_err @rc.errors
|
74
|
+
# end
|
75
|
+
# end
|
76
|
+
# end
|
77
|
+
# end
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
module JsonApi
|
81
|
+
CONTENT_TYPE = 'Content-Type'.freeze
|
82
|
+
|
83
|
+
JSONAPI_MEDIA_TYPE = 'application/vnd.api+json'.freeze
|
84
|
+
|
85
|
+
RACK_PASER_PARAMS = 'rack.parser.result'.freeze
|
86
|
+
|
87
|
+
DEFAULT_JSON_PARSER = proc { |data| JSON.parse(data) }
|
88
|
+
|
89
|
+
DEFAULT_ERROR_HANDLER = proc { |err, type|
|
90
|
+
e = [SerializableError.new(title: 'invalid JSON doc', err: err, status: 400)]
|
91
|
+
msg = JSONAPI::Serializable::ErrorRenderer.render(e, {})
|
92
|
+
[400, { CONTENT_TYPE => JSONAPI_MEDIA_TYPE }, [msg]]
|
93
|
+
}
|
94
|
+
|
95
|
+
DEFAULT_RACK_PARSER_OPTS = {
|
96
|
+
parsers: { JSONAPI_MEDIA_TYPE => DEFAULT_JSON_PARSER },
|
97
|
+
handlers: { JSONAPI_MEDIA_TYPE => DEFAULT_ERROR_HANDLER }
|
98
|
+
}.freeze
|
99
|
+
|
100
|
+
class SerializableError < JSONAPI::Serializable::Error
|
101
|
+
title { @title }
|
102
|
+
status { @status }
|
103
|
+
detail { @err.is_a?(Exception) ? @err.message : @err }
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.configure(app, opts={})
|
107
|
+
return if opts[:skip_middleware]
|
108
|
+
|
109
|
+
app.instance_exec do
|
110
|
+
@middleware.each do |(mid, *rest), _|
|
111
|
+
if mid.equal?(::Rack::Parser)
|
112
|
+
rest[0].merge!(opts)
|
113
|
+
build_rack_app
|
114
|
+
return
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
if opts.empty?
|
119
|
+
use ::Rack::Parser, DEFAULT_RACK_PARSER_OPTS.dup
|
120
|
+
return
|
121
|
+
elsif opts[:parsers].nil? || opts[:pasers][JSONAPI_MEDIA_TYPE].nil?
|
122
|
+
opts[:parsers] = { JSONAPI_MEDIA_TYPE => DEFAULT_JSON_PARSER }
|
123
|
+
use ::Rack::Parser, opts
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
module InstanceMethods
|
129
|
+
def represent(rc, options={})
|
130
|
+
options[:class] = options.delete(:with) unless options[:class]
|
131
|
+
rendered = JSONAPI::Serializable::Renderer.render(rc, options)
|
132
|
+
|
133
|
+
response[CONTENT_TYPE] = JSONAPI_MEDIA_TYPE
|
134
|
+
response.write(rendered)
|
135
|
+
request.halt
|
136
|
+
end
|
137
|
+
|
138
|
+
def represent_err(errs, options={})
|
139
|
+
t = options.delete(:title) || 'model field validation failed'
|
140
|
+
s = options.delete[:status] || 400
|
141
|
+
e = if errs.resond_to? :full_messages
|
142
|
+
errs.full_messages.map { |err| SerializableError.new(title: t, err: err, status: s) }
|
143
|
+
else
|
144
|
+
[SerializableError.new(title: t, err: errs, status: s)]
|
145
|
+
end
|
146
|
+
rendered = JSONAPI::Serializable::ErrorRenderer.render(e, options)
|
147
|
+
|
148
|
+
response.status = s
|
149
|
+
response[CONTENT_TYPE] = JSONAPI_MEDIA_TYPE
|
150
|
+
response.write(rendered)
|
151
|
+
request.halt
|
152
|
+
end
|
153
|
+
|
154
|
+
def json_params
|
155
|
+
parse_jsonapi env[RACK_PASER_PARAMS]
|
156
|
+
end
|
157
|
+
|
158
|
+
private
|
159
|
+
def parse_jsonapi(rc, options={})
|
160
|
+
klass = options[:with] || JSONAPI::Deserializable::Resource
|
161
|
+
begin
|
162
|
+
result = klass.call(rc)
|
163
|
+
rescue JSONAPI::Parser::InvalidDocument => e
|
164
|
+
errs = [SerializableError.new(title: 'Invalid JSONAPI doc', error: e, status: 400)]
|
165
|
+
rendered = JSONAPI::Serializable::ErrorRenderer.render(errs, {})
|
166
|
+
|
167
|
+
response.status = 400
|
168
|
+
response[CONTENT_TYPE] = JSONAPI_MEDIA_TYPE
|
169
|
+
response.write(rendered)
|
170
|
+
request.halt
|
171
|
+
end
|
172
|
+
result
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
data/lib/roda/contrib/version.rb
CHANGED
data/roda-contrib.gemspec
CHANGED
@@ -29,6 +29,8 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_development_dependency 'yard'
|
30
30
|
spec.add_development_dependency 'rack-test'
|
31
31
|
spec.add_development_dependency 'rack_csrf'
|
32
|
+
spec.add_development_dependency 'rack-parser'
|
33
|
+
spec.add_development_dependency 'jsonapi-rb'
|
32
34
|
|
33
35
|
spec.add_dependency 'roda', '~> 2.0'
|
34
36
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roda-contrib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- luciusgone
|
@@ -94,6 +94,34 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rack-parser
|
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
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: jsonapi-rb
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
97
125
|
- !ruby/object:Gem::Dependency
|
98
126
|
name: roda
|
99
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -126,14 +154,17 @@ files:
|
|
126
154
|
- Rakefile
|
127
155
|
- doc/release_notes/0_1_0.rdoc
|
128
156
|
- doc/release_notes/0_2_0.rdoc
|
157
|
+
- doc/release_notes/0_3_0.rdoc
|
129
158
|
- lib/roda/contrib.rb
|
130
159
|
- lib/roda/contrib/action.rb
|
131
160
|
- lib/roda/contrib/action/dispatchable.rb
|
132
161
|
- lib/roda/contrib/plugins/csrf.rb
|
162
|
+
- lib/roda/contrib/plugins/json_api.rb
|
133
163
|
- lib/roda/contrib/plugins/load_all.rb
|
134
164
|
- lib/roda/contrib/plugins/multi_dispatch.rb
|
135
165
|
- lib/roda/contrib/version.rb
|
136
166
|
- lib/roda/plugins/contrib_csrf.rb
|
167
|
+
- lib/roda/plugins/contrib_json_api.rb
|
137
168
|
- lib/roda/plugins/contrib_load_all.rb
|
138
169
|
- lib/roda/plugins/contrib_multi_dispatch.rb
|
139
170
|
- roda-contrib.gemspec
|