Skip to content

Commit 5ce0f87

Browse files
Lee Richmondrichmolj
authored andcommitted
Add validation error when data/type missing
Addresses #339 A few other things came up - one is that all requests, even reads, go through the validator. Ideally the check is further upstream but I tried to change the least amount of code while making this explicit. The other is that I'm normalizing the params in the constructor, so we can always deal with something normalized instead of worrying about raw vs normalized. This has a downstream effect of changing the error message for a Rails4-specific test you can see in the diff (if anything, probably more correct now).
1 parent 054685c commit 5ce0f87

File tree

4 files changed

+42
-22
lines changed

4 files changed

+42
-22
lines changed

lib/graphiti/request_validators/update_validator.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,17 @@ def required_payload?
2626
[:data, :type],
2727
[:data, :id]
2828
].each do |required_attr|
29-
attribute_mismatch(required_attr) unless @raw_params.dig(*required_attr)
29+
attribute_mismatch(required_attr) unless @params.dig(*required_attr)
3030
end
3131
errors.blank?
3232
end
3333

3434
def payload_matches_endpoint?
35-
unless @raw_params.dig(:data, :id) == @raw_params.dig(:filter, :id)
35+
unless @params.dig(:data, :id) == @params.dig(:filter, :id)
3636
attribute_mismatch([:data, :id])
3737
end
3838

39-
meta_type = @raw_params.dig(:data, :type)
39+
meta_type = @params.dig(:data, :type)
4040

4141
# NOTE: calling #to_s and comparing 2 strings is slower than
4242
# calling #to_sym and comparing 2 symbols. But pre ruby-2.2

lib/graphiti/request_validators/validator.rb

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,31 @@ class Validator
55

66
def initialize(root_resource, raw_params, action)
77
@root_resource = root_resource
8-
@raw_params = raw_params
8+
@params = normalized_params(raw_params)
99
@errors = Graphiti::Util::SimpleErrors.new(raw_params)
1010
@action = action
1111
end
1212

1313
def validate
14+
# Right now, all requests - even reads - go through the validator
15+
# In the future these should have their own validation logic, but
16+
# for now we can just bypass
17+
return true unless @params.has_key?(:data)
18+
1419
resource = @root_resource
15-
if (meta_type = deserialized_payload.meta[:type].try(:to_sym))
16-
if @root_resource.type != meta_type && @root_resource.polymorphic?
17-
resource = @root_resource.class.resource_for_type(meta_type).new
20+
21+
if @params[:data].has_key?(:type)
22+
if (meta_type = deserialized_payload.meta[:type].try(:to_sym))
23+
if @root_resource.type != meta_type && @root_resource.polymorphic?
24+
resource = @root_resource.class.resource_for_type(meta_type).new
25+
end
1826
end
19-
end
2027

21-
typecast_attributes(resource, deserialized_payload.attributes, deserialized_payload.meta[:payload_path])
22-
process_relationships(resource, deserialized_payload.relationships, deserialized_payload.meta[:payload_path])
28+
typecast_attributes(resource, deserialized_payload.attributes, deserialized_payload.meta[:payload_path])
29+
process_relationships(resource, deserialized_payload.relationships, deserialized_payload.meta[:payload_path])
30+
else
31+
errors.add(:"data.type", :missing)
32+
end
2333

2434
errors.blank?
2535
end
@@ -33,14 +43,7 @@ def validate!
3343
end
3444

3545
def deserialized_payload
36-
@deserialized_payload ||= begin
37-
payload = normalized_params
38-
if payload[:data] && payload[:data][:type]
39-
Graphiti::Deserializer.new(payload)
40-
else
41-
Graphiti::Deserializer.new({})
42-
end
43-
end
46+
@deserialized_payload ||= Graphiti::Deserializer.new(@params)
4447
end
4548

4649
private
@@ -86,8 +89,8 @@ def typecast_attributes(resource, attributes, payload_path)
8689
end
8790
end
8891

89-
def normalized_params
90-
normalized = @raw_params
92+
def normalized_params(raw_params)
93+
normalized = raw_params
9194
if normalized.respond_to?(:to_unsafe_h)
9295
normalized = normalized.to_unsafe_h.deep_symbolize_keys
9396
end

spec/integration/rails/persistence_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -887,12 +887,12 @@ def self.model_name
887887
code: "unprocessable_entity",
888888
status: "422",
889889
title: "Validation Error",
890-
detail: "translation missing: en.could not be found",
890+
detail: "could not be found",
891891
source: {pointer: nil},
892892
meta: {
893893
relationship: {
894894
attribute: "base",
895-
message: "translation missing: en.could not be found",
895+
message: "could not be found",
896896
name: "classification",
897897
type: "classifications",
898898
id: "99999"

spec/request_validator_spec.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,23 @@ def self.name
5454
end
5555
end
5656

57+
context "when missing type" do
58+
let(:payload) do
59+
{
60+
data: {
61+
attributes: {
62+
first_name: "Jane"
63+
}
64+
}
65+
}
66+
end
67+
68+
it "adds corresponding error" do
69+
expect(validate).to eq(false)
70+
expect(instance.errors).to be_added(:'data.type', :missing)
71+
end
72+
end
73+
5774
context "when a single level resource payload" do
5875
let(:payload) do
5976
{

0 commit comments

Comments
 (0)