Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse included array from request body #13

Merged
merged 7 commits into from
Feb 28, 2017

Conversation

nilsding
Copy link
Contributor

This is a possible solution for #10.

It extends the body options with an included block, where you can set the schema for each type.

A simplified example for the definition:

options do
  body do
    # Schema definition for the main resource
    schema(Dry::Validation.JSON { ... })

    included do
      # Schema definition for `media' type
      media(Dry::Validation.JSON { ... })
      # Schema definition for `other_types' type
      other_types(Dry::Validation.JSON { ... })
    end
  end
end

The resulting body_params then becomes an array if the included block was given with a few definitions. This array contains the main resource as the first element.

@codecov-io
Copy link

codecov-io commented Feb 22, 2017

Codecov Report

Merging #13 into master will not change coverage.
The diff coverage is 100%.

@@          Coverage Diff          @@
##           master    #13   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files          14     14           
  Lines         382    400   +18     
=====================================
+ Hits          382    400   +18
Impacted Files Coverage Δ
lib/request_handler/base.rb 100% <100%> (ø)
lib/request_handler/body_parser.rb 100% <100%> (ø)
lib/request_handler/schema_parser.rb 100% <100%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 79a08a0...747b76e. Read the comment docs.

Copy link
Member

@andreaseger andreaseger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generally nice just a couple small things

schema_options: execute_options(lookup('body.options')),
included_schemas: lookup('body.included')
).run
return defaults.merge(parsed_body) unless parsed_body.is_a? Array
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm I think I'd rather drop the support for default body then this - Not sure why we added this in the first place and if it even makes sense to have a default for that.

end

def run
validate_schema(flattened_request_body)
flattened_body = flattened_request_body
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could do here already

body, *included = flattened_request_body

if flattened_request_body returns only a hash that will end up in body otherwise the multiple return values will be split up correctly

def request_body
b = request.body
b.rewind
b = b.read
b.empty? ? {} : MultiJson.load(b)
end

attr_reader :request
def included_schemas?
!included_schemas.nil? && !included_schemas.empty?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small thing but I prefer

!( included_schemas.nil? || included_schemas.empty?)

body.merge!(body.delete('attributes') { {} })
relationships = flatten_relationship_resource_linkages(body.delete('relationships') { {} })
body.merge!(relationships)
flatten_resource!(body)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could always return

[flatten_resource!(body), *parsed_included]

and do the included_schemas? check only in the parse_included

@@ -14,18 +14,19 @@ def initialize(schema:, schema_options: {})

private

def validate_schema(data)
def validate_schema(data, with: nil)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about defining this method as

def validate_schema(data, with: schema)

testhandler = testclass.new(request: request)
expect(testhandler.to_dto)
.to eq(OpenStruct.new(body: [{ name: 'About naming stuff and cache invalidation' }, { view_count: 1337 }]))
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is missing the case where the schema defines some included schemas but the body doesn't have any (which is fine as the relationship entities could already be present)

{
'type' => 'people',
'id' => '9',
'first-name' => 'Dan',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please change the example to snake_case attributes. We probably need to add some extra handling for dashed attributes. #14

end
shared_examples 'flattens the body as expected' do
it 'returns the flattend body' do
expect(handler).to receive(:validate_schema).with(wanted_result)
it 'returns the flattened body' do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer if we either have a separate shared_example for the case with included schemas or - as it's only a single example right now - move this handling directly there

README.md Outdated
# The first object is the main resource object, i.e. the one that is about to
# be created
{
:id => '1',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use the new hash syntax in the example

@@ -90,17 +90,17 @@ class DemoHandler < RequestHandler::Base
options(->(_handler, _request) { { foo: "bar" } })
# options({foo: "bar"}) # also works for hash options instead of procs
end
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@runtasticBot
Copy link

runtasticBot commented Feb 22, 2017

1 Warning
⚠️ Please limit commit subject line to 50 characters.
63c5e9f

Generated by 🚫 Danger

validation_failure?(validator)
validator.output
end

def validate(data)
def validate(data, with:)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think naming wise it would be more clear if we call the with parameter schema or validation_schema. Especially the else case below read weird with.with

end
it 'flattens the body as expected' do
expect(handler).to receive(:validate_schema).with(wanted_result.shift)
wanted_result.each { |result| expect(handler).to receive(:validate_schema).with(result, with: anything) }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a do/end block would read nicer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants