request_handler 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a6cf97cca0464ee4cd04d685441600aadfa55197
4
- data.tar.gz: dde5d38dac0cf15bb3103a78862219d0fcc26925
3
+ metadata.gz: f080519adc7f75f22de23333a3a0056538422d09
4
+ data.tar.gz: 12e57d56a1b7e384e76e868805db60fb1ec65771
5
5
  SHA512:
6
- metadata.gz: 9d0f9d84f1864af7c3ba99ae27d225ba3fcb6afc8e35c447916e5ef9d84eb7438cc861295429fd715f7667f5fc5689c27d4923b1c8cb185a12d53eea7f7fce11
7
- data.tar.gz: afdf18bfb0c580d0a63a4053a6717a5d78cd69f154e9d93de058e190461a6707d31c62abd30e8b6d84116a96b7b0d2dc3f172581581d74d9b039e03eeaa6894e
6
+ metadata.gz: d67dd542766a8792ab0c084c3d7f24a6867e7811497e3452378a31af61d6ecb502abc335bd135bbf368a0188e305c23f15b108f4916f658e5b8975554fd492f0
7
+ data.tar.gz: 18f1534788d306a99eeff74365bc5e779b09e2a40d827826fe171ac4e1e4487c1a623e1ae8de4a22b530ffc19db1cb2564a44c109f8504c6a49078fbd3ee0067
data/.travis.yml CHANGED
@@ -4,7 +4,7 @@ rvm:
4
4
  - 2.2.7
5
5
  - 2.3.4
6
6
  - 2.4.1
7
- - jruby-9.1.8.0
7
+ - jruby-9.1.12.0
8
8
  jdk:
9
9
  - oraclejdk8
10
10
  env:
@@ -22,11 +22,11 @@ matrix:
22
22
  jdk: oraclejdk8
23
23
  env: "JRUBY_OPTS='-Xcompile.invokedynamic=true --debug'"
24
24
  allow_failures:
25
- - rvm: jruby-9.1.8.0
25
+ - rvm: jruby-9.1.12.0
26
26
  jdk: oraclejdk8
27
27
  env: "JRUBY_OPTS='-Xcompile.invokedynamic=true --debug'"
28
28
  before_install:
29
29
  - gem update --system
30
- - gem install bundler -v 1.14.6
30
+ - gem install bundler -v 1.15.1
31
31
  before_script:
32
32
  - bundle exec danger
data/CHANGELOG.md CHANGED
@@ -3,6 +3,11 @@ Changelog
3
3
 
4
4
  ## master
5
5
 
6
+ ## 0.13.0
7
+
8
+ - sidecar resources for multipart requests can be labeled with required
9
+ - **remove** support for sidepushing via `included` array in request body.
10
+
6
11
  ## 0.12.0
7
12
 
8
13
  - support for multipart-requests
data/README.md CHANGED
@@ -146,136 +146,11 @@ include_options = [:posts__comments]
146
146
  sort_options = SortOption.new(:posts__published_on, :asc)
147
147
  ```
148
148
 
149
- ### Included relations
150
-
151
- Sometimes you want to create a single resource with its relations in a single
152
- request, ensuring that everything or nothing at all is created. However, the
153
- current JSON API specification does not mention anything about how to achieve
154
- this at all, it is expected that all associated resources already exist.
155
- `request_handler` attempts to solve this problem by allowing the request body
156
- to contain an `included` array with all the resources that have to be created.
157
-
158
- #### Example
159
-
160
- With this request handler:
161
-
162
- ```ruby
163
- class CreateQuestionHandler < RequestHandler::Base
164
- options do
165
- body do
166
- schema(
167
- Dry::Validation.JSON do
168
- required(:id).filled(:str?)
169
- required(:type).filled(:str?)
170
- required(:content).filled(:str?)
171
-
172
- optional(:media).schema do
173
- required(:id).filled(:str?)
174
- required(:type).filled(:str?)
175
- end
176
- end
177
- )
178
-
179
- included do
180
- media(
181
- Dry::Validation.JSON do
182
- required(:id).filled(:str?)
183
- required(:type).filled(:str?)
184
- required(:url).filled(:str?)
185
-
186
- optional(:categories).schema do
187
- required(:id).filled(:str?)
188
- required(:type).filled(:str?)
189
- end
190
- end
191
- )
192
- end
193
- end
194
- end
195
-
196
- def to_dto
197
- # see the resulting body_params below
198
- { body: body_params }
199
- end
200
- end
201
- ```
202
-
203
- The following JSON object including its included items is validated with the
204
- defined schema:
205
-
206
- ``` json
207
- {
208
- "data": {
209
- "id": "1",
210
- "type": "questions",
211
- "attributes": {
212
- "content": "How much is the fish?"
213
- },
214
- "relationships": {
215
- "media": {
216
- "data": {
217
- "id": "image-123456",
218
- "type": "media"
219
- }
220
- }
221
- }
222
- }
223
- },
224
- "included": [
225
- {
226
- "id": "image-123456",
227
- "type": "media",
228
- "attributes": {
229
- "url": "https://example.com/fish.jpg"
230
- },
231
- "relationships": {
232
- "categories": {
233
- "data": {
234
- "id": "123",
235
- "type": "categories"
236
- }
237
- }
238
- }
239
- }
240
- ]
241
- }
242
- ```
243
-
244
- The resulting `body_params` will be this:
245
-
246
- ``` ruby
247
- [
248
- # The first object is the main resource object, i.e. the one that is about to
249
- # be created
250
- {
251
- id: '1',
252
- type: 'questions',
253
- content: 'How much is the fish?'
254
- media: [
255
- {
256
- id: 'image-123456',
257
- type: 'media'
258
- }
259
- ]
260
- },
261
- # The remaining objects are every included object, validated with the schema
262
- # defined above
263
- {
264
- id: 'image-123456',
265
- type: 'media',
266
- url: 'https://example.com/fish.jpg',
267
- categories: {
268
- id: '123',
269
- type: 'categories'
270
- }
271
- }
272
- ]
273
- ```
274
-
275
149
  ### Multipart requests
276
150
  It is also possible to process and validate multipart requests, consisting of an arbitrary number of parts.
151
+ You can require specific resources, all the other listed resources are optional
277
152
 
278
- The following request handler accepts a question (which will be uploaded as a json-file) and an additional
153
+ The following request handler requires a question (which will be uploaded as a json-file) and accepts an additional
279
154
  file related to the question
280
155
 
281
156
  ```ruby
@@ -283,6 +158,7 @@ class CreateQuestionHandler < RequestHandler::Base
283
158
  options do
284
159
  multipart do
285
160
  question do
161
+ required true
286
162
  schema(
287
163
  Dry::Validation.JSON do
288
164
  required(:id).filled(:str?)
@@ -104,8 +104,7 @@ module RequestHandler
104
104
  BodyParser.new(
105
105
  request: request,
106
106
  schema: lookup!('body.schema'),
107
- schema_options: execute_options(lookup('body.options')),
108
- included_schemas: lookup('body.included')
107
+ schema_options: execute_options(lookup('body.options'))
109
108
  ).run
110
109
  end
111
110
 
@@ -5,20 +5,18 @@ require 'request_handler/error'
5
5
  require 'request_handler/json_api_document_parser'
6
6
  module RequestHandler
7
7
  class BodyParser
8
- def initialize(request:, schema:, schema_options: {}, included_schemas: {})
8
+ def initialize(request:, schema:, schema_options: {})
9
9
  raise MissingArgumentError, "request.body": 'is missing' if request.body.nil?
10
10
  @request = request
11
11
  @schema = schema
12
12
  @schema_options = schema_options
13
- @included_schemas = included_schemas
14
13
  end
15
14
 
16
15
  def run
17
16
  JsonApiDocumentParser.new(
18
17
  document: request_body,
19
18
  schema: schema,
20
- schema_options: schema_options,
21
- included_schemas: included_schemas
19
+ schema_options: schema_options
22
20
  ).run
23
21
  end
24
22
 
@@ -31,6 +29,6 @@ module RequestHandler
31
29
  b.empty? ? {} : MultiJson.load(b)
32
30
  end
33
31
 
34
- attr_reader :request, :schema, :schema_options, :included_schemas
32
+ attr_reader :request, :schema, :schema_options
35
33
  end
36
34
  end
@@ -4,21 +4,15 @@ require 'request_handler/schema_parser'
4
4
  require 'request_handler/error'
5
5
  module RequestHandler
6
6
  class JsonApiDocumentParser < SchemaParser
7
- def initialize(document:, schema:, schema_options: {}, included_schemas: {})
7
+ def initialize(document:, schema:, schema_options: {})
8
8
  raise MissingArgumentError, "data": 'is missing' if document.nil?
9
9
  super(schema: schema, schema_options: schema_options)
10
10
  @document = document
11
- @included_schemas = included_schemas
12
11
  end
13
12
 
14
13
  def run
15
- resource, *included = flattened_document
16
- unless included_schemas?
17
- raise SchemaValidationError, included: 'must be empty' unless included.empty?
18
- return validate_schema(resource)
19
- end
20
-
21
- validate_schemas(resource, included)
14
+ resource = flattened_document
15
+ validate_schema(resource)
22
16
  end
23
17
 
24
18
  private
@@ -27,7 +21,7 @@ module RequestHandler
27
21
  resource = document.fetch('data') do
28
22
  raise BodyParamsError, resource: 'must contain data'
29
23
  end
30
- [flatten_resource!(resource), *parse_included]
24
+ flatten_resource!(resource)
31
25
  end
32
26
 
33
27
  def flatten_resource!(resource)
@@ -44,27 +38,6 @@ module RequestHandler
44
38
  end
45
39
  end
46
40
 
47
- def parse_included
48
- included = document.fetch('included') { [] }
49
- included.each do |hsh|
50
- flatten_resource!(hsh)
51
- end
52
- end
53
-
54
- def included_schemas?
55
- !(included_schemas.nil? || included_schemas.empty?)
56
- end
57
-
58
- def validate_schemas(resource, included)
59
- schemas = [validate_schema(resource)]
60
- included_schemas.each do |type, schema|
61
- included.select { |inc| inc['type'] == type.to_s }.each do |inc|
62
- schemas << validate_schema(inc, with: schema)
63
- end
64
- end
65
- schemas
66
- end
67
-
68
- attr_reader :document, :included_schemas
41
+ attr_reader :document
69
42
  end
70
43
  end
@@ -16,20 +16,21 @@ module RequestHandler
16
16
  end
17
17
 
18
18
  def run
19
- multipart_config.keys.each_with_object({}) do |name, memo|
20
- params.fetch(name.to_s) { raise MultipartParamsError, multipart: 'missing' }
21
- memo[name] = parse_part(name)
19
+ multipart_config.each_with_object({}) do |(name, config), memo|
20
+ raise MultipartParamsError, multipart: "#{name} missing" if config[:required] && !params.key?(name.to_s)
21
+ next if params[name.to_s].nil?
22
+ memo[name] = parse_part(name.to_s)
22
23
  end
23
24
  end
24
25
 
25
26
  private
26
27
 
27
28
  def parse_part(name)
28
- params[name.to_s].fetch(:tempfile) { raise MultipartParamsError, multipart_file: 'missing' }
29
+ params[name].fetch(:tempfile) { raise MultipartParamsError, multipart_file: 'missing' }
29
30
  if lookup("#{name}.schema")
30
31
  parse_data(name)
31
32
  else
32
- params[name.to_s]
33
+ params[name]
33
34
  end
34
35
  end
35
36
 
@@ -37,19 +38,21 @@ module RequestHandler
37
38
  JsonApiDocumentParser.new(
38
39
  document: load_json(name),
39
40
  schema: lookup("#{name}.schema"),
40
- schema_options: execute_options(lookup("#{name}.options")),
41
- included_schemas: lookup("#{name}.included")
41
+ schema_options: execute_options(lookup("#{name}.options"))
42
42
  ).run
43
43
  end
44
44
 
45
45
  def load_json(name)
46
- MultiJson.load(multipart_file(name).read)
46
+ file = multipart_file(name)
47
+ file.rewind
48
+ file = file.read
49
+ MultiJson.load(file)
47
50
  rescue MultiJson::ParseError
48
- raise MultipartParamsError, multipart_file: 'invalid'
51
+ raise MultipartParamsError, multipart_file: 'invalid JSON'
49
52
  end
50
53
 
51
54
  def multipart_file(name)
52
- params[name.to_s][:tempfile]
55
+ params[name][:tempfile]
53
56
  end
54
57
 
55
58
  def lookup(key)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RequestHandler
4
- VERSION = '0.12.0'.freeze
4
+ VERSION = '0.13.0'.freeze
5
5
  end
@@ -23,7 +23,9 @@ Gem::Specification.new do |spec|
23
23
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
24
  spec.require_paths = ['lib']
25
25
 
26
- spec.add_dependency 'dry-validation', '~> 0.10.4'
26
+ spec.add_dependency 'dry-validation', '~> 0.11.0'
27
+ spec.add_dependency 'dry-types', '~> 0.11.0'
28
+
27
29
  spec.add_dependency 'confstruct', '~> 1.0.2'
28
30
  spec.add_dependency 'multi_json', '~> 1.12'
29
31
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: request_handler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andreas Eger
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2017-05-19 00:00:00.000000000 Z
12
+ date: 2017-07-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: dry-validation
@@ -17,14 +17,28 @@ dependencies:
17
17
  requirements:
18
18
  - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: 0.10.4
20
+ version: 0.11.0
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: 0.10.4
27
+ version: 0.11.0
28
+ - !ruby/object:Gem::Dependency
29
+ name: dry-types
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: 0.11.0
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: 0.11.0
28
42
  - !ruby/object:Gem::Dependency
29
43
  name: confstruct
30
44
  requirement: !ruby/object:Gem::Requirement
@@ -281,7 +295,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
281
295
  version: '0'
282
296
  requirements: []
283
297
  rubyforge_project:
284
- rubygems_version: 2.5.2
298
+ rubygems_version: 2.6.11
285
299
  signing_key:
286
300
  specification_version: 4
287
301
  summary: shared base for request_handler using dry-* gems