request_handler 0.12.0 → 0.13.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 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