Skip to content

Commit 502b691

Browse files
committed
begin playing with using JSON API for deserialization
extract key_transfor chaneg to case_transform gem fix tests pass
1 parent 6c6e45b commit 502b691

File tree

9 files changed

+38
-443
lines changed

9 files changed

+38
-443
lines changed

Gemfile

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ eval_gemfile local_gemfile if File.readable?(local_gemfile)
77
# Specify your gem's dependencies in active_model_serializers.gemspec
88
gemspec
99

10+
# TODO: remove when @beauby re-publishes this gem
11+
gem 'jsonapi', github: 'beauby/jsonapi'
12+
1013
version = ENV['RAILS_VERSION'] || '4.2'
1114

1215
if version == 'master'

active_model_serializers.gemspec

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Gem::Specification.new do |spec|
4343
# 'thread_safe'
4444

4545
spec.add_runtime_dependency 'jsonapi', '~> 0.1.1.beta2'
46+
spec.add_runtime_dependency 'case_transform', '>= 0.2'
4647

4748
spec.add_development_dependency 'activerecord', rails_versions
4849
# arel

lib/active_model_serializers/adapter/base.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
require 'active_model_serializers/key_transform'
1+
require 'case_transform'
22

33
module ActiveModelSerializers
44
module Adapter
@@ -31,7 +31,7 @@ def self.transform(options)
3131
# @param options [Object] serializable resource options
3232
# @return [Symbol] the default transform for the adapter
3333
def self.transform_key_casing!(value, options)
34-
KeyTransform.send(transform(options), value)
34+
CaseTransform.send(transform(options), value)
3535
end
3636

3737
def self.cache_key

lib/active_model_serializers/adapter/json_api/deserialization.rb

+13-45
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1+
require 'jsonapi'
2+
13
module ActiveModelSerializers
24
module Adapter
35
class JsonApi
46
# NOTE(Experimental):
57
# This is an experimental feature. Both the interface and internals could be subject
68
# to changes.
79
module Deserialization
8-
InvalidDocument = Class.new(ArgumentError)
9-
1010
module_function
1111

1212
# Transform a JSON API document, containing a single data object,
@@ -74,21 +74,21 @@ module Deserialization
7474
#
7575
def parse!(document, options = {})
7676
parse(document, options) do |invalid_payload, reason|
77-
fail InvalidDocument, "Invalid payload (#{reason}): #{invalid_payload}"
77+
fail JSONAPI::Parser::InvalidDocument, "Invalid payload (#{reason}): #{invalid_payload}"
7878
end
7979
end
8080

8181
# Same as parse!, but returns an empty hash instead of raising InvalidDocument
8282
# on invalid payloads.
8383
def parse(document, options = {})
84-
document = document.dup.permit!.to_h if document.is_a?(ActionController::Parameters)
85-
86-
validate_payload(document) do |invalid_document, reason|
87-
yield invalid_document, reason if block_given?
88-
return {}
89-
end
84+
document = JSONAPI.parse(document, options)
85+
document = document.to_hash
9086

9187
primary_data = document['data']
88+
89+
# null data is allowed, as per the JSON API Schema
90+
return {} unless primary_data
91+
9292
attributes = primary_data['attributes'] || {}
9393
attributes['id'] = primary_data['id'] if primary_data['id']
9494
relationships = primary_data['relationships'] || {}
@@ -101,43 +101,11 @@ def parse(document, options = {})
101101
hash.merge!(parse_relationships(relationships, options))
102102

103103
hash
104-
end
105-
106-
# Checks whether a payload is compliant with the JSON API spec.
107-
#
108-
# @api private
109-
# rubocop:disable Metrics/CyclomaticComplexity
110-
def validate_payload(payload)
111-
unless payload.is_a?(Hash)
112-
yield payload, 'Expected hash'
113-
return
114-
end
115104

116-
primary_data = payload['data']
117-
unless primary_data.is_a?(Hash)
118-
yield payload, { data: 'Expected hash' }
119-
return
120-
end
121-
122-
attributes = primary_data['attributes'] || {}
123-
unless attributes.is_a?(Hash)
124-
yield payload, { data: { attributes: 'Expected hash or nil' } }
125-
return
126-
end
127-
128-
relationships = primary_data['relationships'] || {}
129-
unless relationships.is_a?(Hash)
130-
yield payload, { data: { relationships: 'Expected hash or nil' } }
131-
return
132-
end
133-
134-
relationships.each do |(key, value)|
135-
unless value.is_a?(Hash) && value.key?('data')
136-
yield payload, { data: { relationships: { key => 'Expected hash with :data key' } } }
137-
end
138-
end
105+
rescue JSONAPI::Parser::InvalidDocument
106+
return {} unless block_given?
107+
yield
139108
end
140-
# rubocop:enable Metrics/CyclomaticComplexity
141109

142110
# @api private
143111
def filter_fields(fields, options)
@@ -205,7 +173,7 @@ def parse_relationships(relationships, options)
205173
# @api private
206174
def transform_keys(hash, options)
207175
transform = options[:key_transform] || :underscore
208-
KeyTransform.send(transform, hash)
176+
CaseTransform.send(transform, hash)
209177
end
210178
end
211179
end

lib/active_model_serializers/key_transform.rb

-74
This file was deleted.

test/action_controller/json_api/transform_test.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
module ActionController
44
module Serialization
55
class JsonApi
6-
class KeyTransformTest < ActionController::TestCase
7-
class KeyTransformTestController < ActionController::Base
6+
class CaseTransformTest < ActionController::TestCase
7+
class CaseTransformTestController < ActionController::Base
88
class Post < ::Model; end
99
class Author < ::Model; end
1010
class TopComment < ::Model; end
@@ -69,7 +69,7 @@ def render_resource_with_transform_with_global_config
6969
end
7070
end
7171

72-
tests KeyTransformTestController
72+
tests CaseTransformTestController
7373

7474
def test_render_resource_with_transform
7575
get :render_resource_with_transform

0 commit comments

Comments
 (0)