fun_with_json_api 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -1
  3. data/config/locales/fun_with_json_api.en.yml +29 -2
  4. data/lib/fun_with_json_api.rb +30 -2
  5. data/lib/fun_with_json_api/action_controller_extensions/serialization.rb +18 -0
  6. data/lib/fun_with_json_api/attribute.rb +3 -3
  7. data/lib/fun_with_json_api/attributes/relationship.rb +37 -23
  8. data/lib/fun_with_json_api/attributes/relationship_collection.rb +55 -38
  9. data/lib/fun_with_json_api/attributes/string_attribute.rb +12 -1
  10. data/lib/fun_with_json_api/attributes/uuid_v4_attribute.rb +27 -0
  11. data/lib/fun_with_json_api/controller_methods.rb +1 -1
  12. data/lib/fun_with_json_api/deserializer.rb +61 -8
  13. data/lib/fun_with_json_api/deserializer_class_methods.rb +37 -7
  14. data/lib/fun_with_json_api/exceptions/illegal_client_generated_identifier.rb +17 -0
  15. data/lib/fun_with_json_api/exceptions/invalid_client_generated_identifier.rb +17 -0
  16. data/lib/fun_with_json_api/exceptions/invalid_document_identifier.rb +17 -0
  17. data/lib/fun_with_json_api/exceptions/invalid_document_type.rb +20 -0
  18. data/lib/fun_with_json_api/exceptions/invalid_relationship.rb +5 -3
  19. data/lib/fun_with_json_api/exceptions/invalid_relationship_type.rb +17 -0
  20. data/lib/fun_with_json_api/exceptions/missing_resource.rb +15 -0
  21. data/lib/fun_with_json_api/exceptions/unknown_attribute.rb +15 -0
  22. data/lib/fun_with_json_api/exceptions/unknown_relationship.rb +15 -0
  23. data/lib/fun_with_json_api/find_collection_from_document.rb +124 -0
  24. data/lib/fun_with_json_api/find_resource_from_document.rb +112 -0
  25. data/lib/fun_with_json_api/pre_deserializer.rb +1 -0
  26. data/lib/fun_with_json_api/railtie.rb +30 -1
  27. data/lib/fun_with_json_api/schema_validator.rb +47 -0
  28. data/lib/fun_with_json_api/schema_validators/check_attributes.rb +52 -0
  29. data/lib/fun_with_json_api/schema_validators/check_document_id_matches_resource.rb +96 -0
  30. data/lib/fun_with_json_api/schema_validators/check_document_type_matches_resource.rb +40 -0
  31. data/lib/fun_with_json_api/schema_validators/check_relationships.rb +127 -0
  32. data/lib/fun_with_json_api/version.rb +1 -1
  33. data/spec/dummy/log/test.log +172695 -0
  34. data/spec/fixtures/active_record.rb +6 -0
  35. data/spec/fun_with_json_api/controller_methods_spec.rb +8 -3
  36. data/spec/fun_with_json_api/deserializer_class_methods_spec.rb +14 -6
  37. data/spec/fun_with_json_api/deserializer_spec.rb +155 -40
  38. data/spec/fun_with_json_api/exception_spec.rb +9 -9
  39. data/spec/fun_with_json_api/find_collection_from_document_spec.rb +203 -0
  40. data/spec/fun_with_json_api/find_resource_from_document_spec.rb +100 -0
  41. data/spec/fun_with_json_api/pre_deserializer_spec.rb +26 -26
  42. data/spec/fun_with_json_api/railtie_spec.rb +88 -0
  43. data/spec/fun_with_json_api/schema_validator_spec.rb +94 -0
  44. data/spec/fun_with_json_api/schema_validators/check_attributes_spec.rb +52 -0
  45. data/spec/fun_with_json_api/schema_validators/check_document_id_matches_resource_spec.rb +115 -0
  46. data/spec/fun_with_json_api/schema_validators/check_document_type_matches_resource_spec.rb +30 -0
  47. data/spec/fun_with_json_api/schema_validators/check_relationships_spec.rb +150 -0
  48. data/spec/fun_with_json_api_spec.rb +148 -4
  49. metadata +49 -4
  50. data/spec/example_spec.rb +0 -64
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe FunWithJsonApi do
4
- it 'should have a Semantic Versioning compatible VERSION' do
4
+ it 'has a semantic-versioning compatible VERSION' do
5
5
  # based on https://github.com/npm/node-semver/issues/32
6
6
  version_regex = /
7
7
  \A([0-9]+) # major
@@ -15,7 +15,42 @@ describe FunWithJsonApi do
15
15
 
16
16
  describe '.deserialize' do
17
17
  context 'with an PostDeserializer' do
18
- it 'should convert a json api to post params' do
18
+ it 'converts a json api document into create post params' do
19
+ ARModels::Author.create(id: 9)
20
+ ARModels::Comment.create(id: 5)
21
+ ARModels::Comment.create(id: 12)
22
+
23
+ post_json = {
24
+ 'data': {
25
+ 'type': 'posts',
26
+ 'attributes': {
27
+ 'title': 'Rails is Omakase',
28
+ 'body': 'This is my post body'
29
+ },
30
+ 'relationships': {
31
+ 'author': {
32
+ 'data': { 'type': 'person', 'id': '9' }
33
+ },
34
+ 'comments': {
35
+ 'data': [
36
+ { 'type': 'comments', 'id': '5' },
37
+ { 'type': 'comments', 'id': '12' }
38
+ ]
39
+ }
40
+ }
41
+ }
42
+ }
43
+
44
+ post_params = described_class.deserialize(post_json, ARModels::PostDeserializer)
45
+ expect(post_params).to eq(
46
+ title: 'Rails is Omakase',
47
+ body: 'This is my post body',
48
+ author_id: 9,
49
+ comment_ids: [5, 12]
50
+ )
51
+ end
52
+ it 'converts a json api document into update post params' do
53
+ post = ARModels::Post.create(id: 1)
19
54
  ARModels::Author.create(id: 9)
20
55
  ARModels::Comment.create(id: 5)
21
56
  ARModels::Comment.create(id: 12)
@@ -30,7 +65,7 @@ describe FunWithJsonApi do
30
65
  },
31
66
  'relationships': {
32
67
  'author': {
33
- 'data': { 'type': 'people', 'id': '9' }
68
+ 'data': { 'type': 'person', 'id': '9' }
34
69
  },
35
70
  'comments': {
36
71
  'data': [
@@ -42,7 +77,7 @@ describe FunWithJsonApi do
42
77
  }
43
78
  }
44
79
 
45
- post_params = FunWithJsonApi.deserialize(post_json, ARModels::PostDeserializer)
80
+ post_params = described_class.deserialize(post_json, ARModels::PostDeserializer, post)
46
81
  expect(post_params).to eq(
47
82
  title: 'Rails is Omakase',
48
83
  body: 'This is my post body',
@@ -50,6 +85,115 @@ describe FunWithJsonApi do
50
85
  comment_ids: [5, 12]
51
86
  )
52
87
  end
88
+ it 'allows for relationships to be scoped' do
89
+ post = ARModels::Post.create(id: 1)
90
+ ARModels::Author.create(id: 9, name: 'John', code: 'foo')
91
+ ARModels::Author.create(id: 10, name: 'John', code: 'bar')
92
+ ARModels::Comment.create(id: 5)
93
+ ARModels::Comment.create(id: 12)
94
+
95
+ post_json = {
96
+ 'data': {
97
+ 'type': 'posts',
98
+ 'id': '1',
99
+ 'attributes': {
100
+ 'title': 'Rails is Omakase',
101
+ 'body': 'This is my post body'
102
+ },
103
+ 'relationships': {
104
+ 'author': {
105
+ 'data': { 'type': 'person', 'id': 'John' }
106
+ },
107
+ 'comments': {
108
+ 'data': [
109
+ { 'type': 'comments', 'id': '5' },
110
+ { 'type': 'comments', 'id': '12' }
111
+ ]
112
+ }
113
+ }
114
+ }
115
+ }
116
+
117
+ post_params = described_class.deserialize(
118
+ post_json,
119
+ ARModels::PostDeserializer,
120
+ post,
121
+ author: { id_param: :name, resource_collection: ARModels::Author.where(code: 'foo') }
122
+ )
123
+ expect(post_params).to eq(
124
+ title: 'Rails is Omakase',
125
+ body: 'This is my post body',
126
+ author_id: 9,
127
+ comment_ids: [5, 12]
128
+ )
129
+ end
130
+ end
131
+ end
132
+
133
+ describe '.find_resource' do
134
+ context 'with a resource matching the document' do
135
+ let!(:resource) { ARModels::Author.create(id: 42) }
136
+ let(:document) { { data: { id: '42', type: 'person' } } }
137
+
138
+ it 'returns the matching resource' do
139
+ actual = described_class.find_resource(document, ARModels::AuthorDeserializer)
140
+ expect(actual).to eq(resource)
141
+ end
142
+ end
143
+
144
+ context 'with a resource_collection argument' do
145
+ let!(:resource_a) { ARModels::Author.create(id: 42, name: 'Jack', code: 'foo') }
146
+ let!(:resource_b) { ARModels::Author.create(id: 43, name: 'John', code: 'foo') }
147
+ let(:document) { { data: { id: 'foo', type: 'person' } } }
148
+
149
+ it 'returns the resource scoped to the resource_collection' do
150
+ actual = described_class.find_resource(
151
+ document,
152
+ ARModels::AuthorDeserializer,
153
+ id_param: 'code',
154
+ resource_collection: ARModels::Author.where(name: 'Jack')
155
+ )
156
+ expect(actual).to eq(resource_a)
157
+ end
158
+ end
159
+ end
160
+
161
+ describe '.find_collection' do
162
+ context 'with resources matching the document' do
163
+ let!(:resource_a) { ARModels::Author.create(id: 42) }
164
+ let!(:resource_b) { ARModels::Author.create(id: 43) }
165
+ let(:document) { { data: [{ id: '42', type: 'person' }, { id: '43', type: 'person' }] } }
166
+
167
+ it 'returns all matching resources' do
168
+ actual = described_class.find_collection(document, ARModels::AuthorDeserializer)
169
+ expect(actual).to eq([resource_a, resource_b])
170
+ end
171
+ end
172
+
173
+ context 'with a resource_collection argument' do
174
+ let!(:resource_a) { ARModels::Author.create(id: 42, name: 'Jack', code: 'foo') }
175
+ let!(:resource_b) { ARModels::Author.create(id: 43, name: 'John', code: 'foo') }
176
+ let!(:resource_c) { ARModels::Author.create(id: 44, name: 'Jack', code: 'bar') }
177
+ let(:document) { { data: [{ id: 'foo', type: 'person' }, { id: 'bar', type: 'person' }] } }
178
+
179
+ it 'returns the resource scoped to the resource_collection' do
180
+ actual = described_class.find_collection(
181
+ document,
182
+ ARModels::AuthorDeserializer,
183
+ id_param: 'code',
184
+ resource_collection: ARModels::Author.where(name: 'Jack')
185
+ )
186
+ expect(actual).to eq([resource_a, resource_c])
187
+ end
188
+ end
189
+
190
+ context 'with an empty array' do
191
+ let(:document) { { data: [] } }
192
+
193
+ it 'returns an empty array' do
194
+ actual = described_class.find_collection(document, ARModels::AuthorDeserializer)
195
+ expect(actual).to eq([])
196
+ end
53
197
  end
54
198
  end
55
199
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fun_with_json_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Morrall
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-24 00:00:00.000000000 Z
11
+ date: 2016-03-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: 0.38.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: simplecov
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -134,6 +148,7 @@ files:
134
148
  - Rakefile
135
149
  - config/locales/fun_with_json_api.en.yml
136
150
  - lib/fun_with_json_api.rb
151
+ - lib/fun_with_json_api/action_controller_extensions/serialization.rb
137
152
  - lib/fun_with_json_api/attribute.rb
138
153
  - lib/fun_with_json_api/attributes/boolean_attribute.rb
139
154
  - lib/fun_with_json_api/attributes/date_attribute.rb
@@ -144,6 +159,7 @@ files:
144
159
  - lib/fun_with_json_api/attributes/relationship.rb
145
160
  - lib/fun_with_json_api/attributes/relationship_collection.rb
146
161
  - lib/fun_with_json_api/attributes/string_attribute.rb
162
+ - lib/fun_with_json_api/attributes/uuid_v4_attribute.rb
147
163
  - lib/fun_with_json_api/controller_methods.rb
148
164
  - lib/fun_with_json_api/deserializer.rb
149
165
  - lib/fun_with_json_api/deserializer_class_methods.rb
@@ -152,12 +168,27 @@ files:
152
168
  - lib/fun_with_json_api/exception_payload.rb
153
169
  - lib/fun_with_json_api/exception_payload_serializer.rb
154
170
  - lib/fun_with_json_api/exception_serializer.rb
171
+ - lib/fun_with_json_api/exceptions/illegal_client_generated_identifier.rb
155
172
  - lib/fun_with_json_api/exceptions/invalid_attribute.rb
173
+ - lib/fun_with_json_api/exceptions/invalid_client_generated_identifier.rb
156
174
  - lib/fun_with_json_api/exceptions/invalid_document.rb
175
+ - lib/fun_with_json_api/exceptions/invalid_document_identifier.rb
176
+ - lib/fun_with_json_api/exceptions/invalid_document_type.rb
157
177
  - lib/fun_with_json_api/exceptions/invalid_relationship.rb
178
+ - lib/fun_with_json_api/exceptions/invalid_relationship_type.rb
158
179
  - lib/fun_with_json_api/exceptions/missing_relationship.rb
180
+ - lib/fun_with_json_api/exceptions/missing_resource.rb
181
+ - lib/fun_with_json_api/exceptions/unknown_attribute.rb
182
+ - lib/fun_with_json_api/exceptions/unknown_relationship.rb
183
+ - lib/fun_with_json_api/find_collection_from_document.rb
184
+ - lib/fun_with_json_api/find_resource_from_document.rb
159
185
  - lib/fun_with_json_api/pre_deserializer.rb
160
186
  - lib/fun_with_json_api/railtie.rb
187
+ - lib/fun_with_json_api/schema_validator.rb
188
+ - lib/fun_with_json_api/schema_validators/check_attributes.rb
189
+ - lib/fun_with_json_api/schema_validators/check_document_id_matches_resource.rb
190
+ - lib/fun_with_json_api/schema_validators/check_document_type_matches_resource.rb
191
+ - lib/fun_with_json_api/schema_validators/check_relationships.rb
161
192
  - lib/fun_with_json_api/version.rb
162
193
  - lib/tasks/fun_with_json_api_tasks.rake
163
194
  - spec/dummy/README.rdoc
@@ -195,13 +226,20 @@ files:
195
226
  - spec/dummy/public/422.html
196
227
  - spec/dummy/public/500.html
197
228
  - spec/dummy/public/favicon.ico
198
- - spec/example_spec.rb
199
229
  - spec/fixtures/active_record.rb
200
230
  - spec/fun_with_json_api/controller_methods_spec.rb
201
231
  - spec/fun_with_json_api/deserializer_class_methods_spec.rb
202
232
  - spec/fun_with_json_api/deserializer_spec.rb
203
233
  - spec/fun_with_json_api/exception_spec.rb
234
+ - spec/fun_with_json_api/find_collection_from_document_spec.rb
235
+ - spec/fun_with_json_api/find_resource_from_document_spec.rb
204
236
  - spec/fun_with_json_api/pre_deserializer_spec.rb
237
+ - spec/fun_with_json_api/railtie_spec.rb
238
+ - spec/fun_with_json_api/schema_validator_spec.rb
239
+ - spec/fun_with_json_api/schema_validators/check_attributes_spec.rb
240
+ - spec/fun_with_json_api/schema_validators/check_document_id_matches_resource_spec.rb
241
+ - spec/fun_with_json_api/schema_validators/check_document_type_matches_resource_spec.rb
242
+ - spec/fun_with_json_api/schema_validators/check_relationships_spec.rb
205
243
  - spec/fun_with_json_api_spec.rb
206
244
  - spec/spec_helper.rb
207
245
  homepage: https://github.com/bmorrall/fun_with_json_api
@@ -264,12 +302,19 @@ test_files:
264
302
  - spec/dummy/public/favicon.ico
265
303
  - spec/dummy/Rakefile
266
304
  - spec/dummy/README.rdoc
267
- - spec/example_spec.rb
268
305
  - spec/fixtures/active_record.rb
269
306
  - spec/fun_with_json_api/controller_methods_spec.rb
270
307
  - spec/fun_with_json_api/deserializer_class_methods_spec.rb
271
308
  - spec/fun_with_json_api/deserializer_spec.rb
272
309
  - spec/fun_with_json_api/exception_spec.rb
310
+ - spec/fun_with_json_api/find_collection_from_document_spec.rb
311
+ - spec/fun_with_json_api/find_resource_from_document_spec.rb
273
312
  - spec/fun_with_json_api/pre_deserializer_spec.rb
313
+ - spec/fun_with_json_api/railtie_spec.rb
314
+ - spec/fun_with_json_api/schema_validator_spec.rb
315
+ - spec/fun_with_json_api/schema_validators/check_attributes_spec.rb
316
+ - spec/fun_with_json_api/schema_validators/check_document_id_matches_resource_spec.rb
317
+ - spec/fun_with_json_api/schema_validators/check_document_type_matches_resource_spec.rb
318
+ - spec/fun_with_json_api/schema_validators/check_relationships_spec.rb
274
319
  - spec/fun_with_json_api_spec.rb
275
320
  - spec/spec_helper.rb
data/spec/example_spec.rb DELETED
@@ -1,64 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'Example' do
4
- xit 'prints out the thing' do
5
- params = {
6
- id: 'zorglub',
7
- title: 'Ember Hamster',
8
- published_at: '2016-03-12',
9
- enabled_at: '2016-03-12T17:19:28+11:00',
10
- promoted: false,
11
- times_read: '414',
12
- author_id: nil,
13
- editor_id: '9',
14
- comment_ids: %w(1 2)
15
- }
16
-
17
- puts "attributes: #{ArticleDeserializer.attributes.map(&:name).inspect}"
18
-
19
- deserializer = ArticleDeserializer.create
20
- deserialized_params = deserializer.sanitize_params(params)
21
- puts "title: #{deserialized_params[:title].inspect}"
22
- puts "published_at: #{deserialized_params[:published_at].inspect}"
23
- puts "enabled_at: #{deserialized_params[:enabled_at].inspect}"
24
- puts "times_read: #{deserialized_params[:times_read].inspect}"
25
- puts deserialized_params.inspect
26
-
27
- expect(deserializer.type).to eq 'articles'
28
- expect(deserializer.resource_class).to eq Article
29
- end
30
-
31
- xit 'deserializes params' do
32
- document_data = {
33
- # id: 'zorglub',
34
- type: 'articles',
35
- attributes: {
36
- title: 'Ember Hamster',
37
- date: '2016-03-12',
38
- enabled_at: '2016-03-12T13:45:40+09:30',
39
- promoted: false,
40
- times_read: '414'
41
- },
42
- relationships: {
43
- author: { data: nil },
44
- editor: { data: { id: 'demouser', type: 'persons' } },
45
- comments: { data: [{ id: '1', type: 'comments' }, { id: '2', type: 'comments' }] }
46
- }
47
- }
48
- document = { data: document_data }.as_json
49
-
50
- document_params = FunWithJsonApi.deserialize(document, ArticleDeserializer)
51
- expect(document_params).to eq(
52
- # id: Article.find(code: 'zorglub').id,
53
- title: 'Ember Hamster',
54
- published_at: Date.new(2016, 03, 12),
55
- enabled_at: DateTime.new(2016, 03, 12, 4, 15, 40, 0),
56
- promoted: false,
57
- times_read: 414,
58
- author_id: nil,
59
- editor_id: Person.find_by!(username: 'demouser').id,
60
- comment_ids: [1, 2]
61
- )
62
- puts "deserialized: #{document_params.inspect}"
63
- end
64
- end