fun_with_json_api 0.0.2 → 0.0.3

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.
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