fun_with_json_api 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +28 -0
  4. data/config/locales/fun_with_json_api.en.yml +13 -0
  5. data/lib/fun_with_json_api/attribute.rb +38 -0
  6. data/lib/fun_with_json_api/attributes/boolean_attribute.rb +24 -0
  7. data/lib/fun_with_json_api/attributes/date_attribute.rb +22 -0
  8. data/lib/fun_with_json_api/attributes/datetime_attribute.rb +20 -0
  9. data/lib/fun_with_json_api/attributes/decimal_attribute.rb +23 -0
  10. data/lib/fun_with_json_api/attributes/float_attribute.rb +20 -0
  11. data/lib/fun_with_json_api/attributes/integer_attribute.rb +20 -0
  12. data/lib/fun_with_json_api/attributes/relationship.rb +73 -0
  13. data/lib/fun_with_json_api/attributes/relationship_collection.rb +99 -0
  14. data/lib/fun_with_json_api/attributes/string_attribute.rb +9 -0
  15. data/lib/fun_with_json_api/controller_methods.rb +12 -0
  16. data/lib/fun_with_json_api/deserializer.rb +70 -0
  17. data/lib/fun_with_json_api/deserializer_class_methods.rb +83 -0
  18. data/lib/fun_with_json_api/deserializer_config_builder.rb +48 -0
  19. data/lib/fun_with_json_api/exception.rb +27 -0
  20. data/lib/fun_with_json_api/exception_payload.rb +29 -0
  21. data/lib/fun_with_json_api/exception_payload_serializer.rb +17 -0
  22. data/lib/fun_with_json_api/exception_serializer.rb +15 -0
  23. data/lib/fun_with_json_api/exceptions/invalid_attribute.rb +13 -0
  24. data/lib/fun_with_json_api/exceptions/invalid_document.rb +12 -0
  25. data/lib/fun_with_json_api/exceptions/invalid_relationship.rb +13 -0
  26. data/lib/fun_with_json_api/exceptions/missing_relationship.rb +15 -0
  27. data/lib/fun_with_json_api/pre_deserializer.rb +61 -0
  28. data/lib/fun_with_json_api/railtie.rb +11 -0
  29. data/lib/fun_with_json_api/version.rb +3 -0
  30. data/lib/fun_with_json_api.rb +24 -0
  31. data/lib/tasks/fun_with_json_api_tasks.rake +4 -0
  32. data/spec/dummy/README.rdoc +28 -0
  33. data/spec/dummy/Rakefile +6 -0
  34. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  35. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  36. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  37. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  38. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  39. data/spec/dummy/bin/bundle +3 -0
  40. data/spec/dummy/bin/rails +4 -0
  41. data/spec/dummy/bin/rake +4 -0
  42. data/spec/dummy/bin/setup +29 -0
  43. data/spec/dummy/config/application.rb +25 -0
  44. data/spec/dummy/config/boot.rb +5 -0
  45. data/spec/dummy/config/database.yml +25 -0
  46. data/spec/dummy/config/environment.rb +5 -0
  47. data/spec/dummy/config/environments/development.rb +41 -0
  48. data/spec/dummy/config/environments/production.rb +80 -0
  49. data/spec/dummy/config/environments/test.rb +42 -0
  50. data/spec/dummy/config/initializers/assets.rb +11 -0
  51. data/spec/dummy/config/initializers/backtrace_silencers.rb +9 -0
  52. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  53. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  54. data/spec/dummy/config/initializers/inflections.rb +16 -0
  55. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  56. data/spec/dummy/config/initializers/session_store.rb +3 -0
  57. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  58. data/spec/dummy/config/locales/en.yml +23 -0
  59. data/spec/dummy/config/routes.rb +56 -0
  60. data/spec/dummy/config/secrets.yml +22 -0
  61. data/spec/dummy/config.ru +4 -0
  62. data/spec/dummy/log/test.log +37839 -0
  63. data/spec/dummy/public/404.html +67 -0
  64. data/spec/dummy/public/422.html +67 -0
  65. data/spec/dummy/public/500.html +66 -0
  66. data/spec/dummy/public/favicon.ico +0 -0
  67. data/spec/example_spec.rb +64 -0
  68. data/spec/fixtures/active_record.rb +65 -0
  69. data/spec/fun_with_json_api/controller_methods_spec.rb +123 -0
  70. data/spec/fun_with_json_api/deserializer_class_methods_spec.rb +52 -0
  71. data/spec/fun_with_json_api/deserializer_spec.rb +450 -0
  72. data/spec/fun_with_json_api/exception_spec.rb +77 -0
  73. data/spec/fun_with_json_api/pre_deserializer_spec.rb +287 -0
  74. data/spec/fun_with_json_api_spec.rb +55 -0
  75. data/spec/spec_helper.rb +33 -0
  76. metadata +275 -0
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe FunWithJsonApi::DeserializerClassMethods do
4
+ describe '.belongs_to' do
5
+ it 'should add a Relationship attribute' do
6
+ foos_deserializer_class = Class.new(FunWithJsonApi::Deserializer) do
7
+ attribute :blargh
8
+ end
9
+ deserializer_class = Class.new(FunWithJsonApi::Deserializer) do
10
+ belongs_to :foo, -> { foos_deserializer_class }
11
+ end
12
+ relationship = deserializer_class.relationships.last
13
+ expect(relationship).to be_kind_of(FunWithJsonApi::Attributes::Relationship)
14
+
15
+ expect(relationship.name).to eq :foo
16
+ expect(relationship.as).to eq :foo
17
+ expect(relationship.deserializer).to be_kind_of(foos_deserializer_class)
18
+
19
+ expect(relationship.deserializer.attributes).to eq []
20
+ expect(relationship.deserializer.relationships).to eq []
21
+ end
22
+ end
23
+
24
+ describe '.has_many' do
25
+ it 'should add a RelationshipCollection attribute' do
26
+ foos_deserializer_class = Class.new(FunWithJsonApi::Deserializer) do
27
+ attribute :blargh
28
+ end
29
+ deserializer_class = Class.new(FunWithJsonApi::Deserializer) do
30
+ has_many :foos, -> { foos_deserializer_class }
31
+ end
32
+ relationship = deserializer_class.relationships.last
33
+ expect(relationship).to be_kind_of(FunWithJsonApi::Attributes::RelationshipCollection)
34
+
35
+ expect(relationship.name).to eq :foos
36
+ expect(relationship.as).to eq :foo
37
+ expect(relationship.deserializer).to be_kind_of(foos_deserializer_class)
38
+
39
+ expect(relationship.deserializer.attributes).to eq []
40
+ expect(relationship.deserializer.relationships).to eq []
41
+ end
42
+
43
+ it 'should not allow pluralized as values' do
44
+ foos_deserializer_class = Class.new(FunWithJsonApi::Deserializer)
45
+ expect do
46
+ Class.new(FunWithJsonApi::Deserializer) do
47
+ has_many :foos, -> { foos_deserializer_class }, as: 'foos'
48
+ end
49
+ end.to raise_error(ArgumentError, 'Use a singular relationship as value: {as: :foo}')
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,450 @@
1
+ require 'spec_helper'
2
+
3
+ # Returns a FunWithJsonApi::Deserializer class with an attribute
4
+ #
5
+ # Equivalent of:
6
+ # ```
7
+ # class ExampleDeserializer < FunWithJsonApi::Deserializer
8
+ # attribute #{attribute}, #{attribute_options}
9
+ # end
10
+ def deserializer_class_with_attribute(attribute, attribute_options = {})
11
+ Class.new(FunWithJsonApi::Deserializer) do
12
+ attribute attribute, attribute_options
13
+ end
14
+ end
15
+
16
+ def deserializer_class_with_relationship(relationship, relationship_type, relationship_options = {})
17
+ relationship_deserializer = Class.new(FunWithJsonApi::Deserializer) do
18
+ type(relationship_type)
19
+ end
20
+
21
+ Class.new(FunWithJsonApi::Deserializer) do
22
+ belongs_to relationship, relationship_deserializer, relationship_options
23
+ end
24
+ end
25
+
26
+ # Returns an instance of a FunWithJsonApi::Deserializer with an attribute with an assigned value
27
+ #
28
+ # Equivalent of:
29
+ # ```
30
+ # class ExampleDeserializer < FunWithJsonApi::Deserializer
31
+ # attribute #{attribute}, #{attribute_options}
32
+ # end
33
+ # ExampleDeserializer.create
34
+ # ~~~
35
+ def deserializer_with_attribute(attribute, attribute_options = {})
36
+ deserializer_class_with_attribute(attribute, attribute_options).create
37
+ end
38
+
39
+ describe FunWithJsonApi::Deserializer do
40
+ describe '#parse_{attribute}' do
41
+ context 'with an alias value' do
42
+ it 'should generated an attribute from the alias value' do
43
+ deserializer = deserializer_with_attribute(:original_key, as: :assigned_key)
44
+ expect(deserializer.parse_assigned_key('Foo Bar')).to eq 'Foo Bar'
45
+ expect(deserializer).to_not respond_to(:original_key)
46
+ end
47
+ end
48
+
49
+ context 'with no format argument (string)' do
50
+ it 'should allow a String value' do
51
+ deserializer = deserializer_with_attribute(:example)
52
+ expect(deserializer.parse_example('Foo Bar')).to eq 'Foo Bar'
53
+ end
54
+ it 'should allow a nil value' do
55
+ deserializer = deserializer_with_attribute(:example)
56
+ expect(deserializer.parse_example(nil)).to be nil
57
+ end
58
+ end
59
+
60
+ context 'with a boolean format' do
61
+ it 'should allow a Boolean.TRUE value' do
62
+ deserializer = deserializer_with_attribute(:example, format: :boolean)
63
+ expect(deserializer.parse_example(true)).to eq true
64
+ end
65
+ it 'should allow a Boolean.FALSE value' do
66
+ deserializer = deserializer_with_attribute(:example, format: :boolean)
67
+ expect(deserializer.parse_example(false)).to eq false
68
+ end
69
+ it 'should allow a nil value' do
70
+ deserializer = deserializer_with_attribute(:example, format: :boolean)
71
+ expect(deserializer.parse_example(nil)).to be nil
72
+ end
73
+ it 'should raise an InvalidAttribute for invalid boolean values' do
74
+ deserializer = deserializer_with_attribute(:example, format: :boolean)
75
+ ['true', 'True', 'TRUE', 1, 'false', 'False', 'FALSE', 0].each do |value|
76
+ expect do
77
+ deserializer.parse_example(value)
78
+ end.to raise_error(FunWithJsonApi::Exceptions::InvalidAttribute) do |e|
79
+ expect(e.payload.size).to eq 1
80
+
81
+ payload = e.payload.first
82
+ expect(payload.status).to eq '400'
83
+ expect(payload.code).to eq 'invalid_attribute'
84
+ expect(payload.title).to eq(
85
+ I18n.t('fun_with_json_api.exceptions.invalid_attribute')
86
+ )
87
+ expect(payload.detail).to eq(
88
+ I18n.t('fun_with_json_api.exceptions.invalid_boolean_attribute')
89
+ )
90
+ expect(payload.pointer).to eq '/data/attributes/example'
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ context 'with a date format' do
97
+ it 'should allow a "YYYY-MM-DD" formatted value' do
98
+ deserializer = deserializer_with_attribute(:example, format: :date)
99
+ expect(deserializer.parse_example('2016-03-12')).to eq Date.new(2016, 03, 12)
100
+ end
101
+ it 'should allow a nil value' do
102
+ deserializer = deserializer_with_attribute(:example, format: :date)
103
+ expect(deserializer.parse_example(nil)).to be nil
104
+ end
105
+ it 'should raise an InvalidAttribute for invalid date value' do
106
+ deserializer = deserializer_with_attribute(:example, format: :date)
107
+ ['2016-12', 'Last Wednesday', 'April'].each do |value|
108
+ expect do
109
+ deserializer.parse_example(value)
110
+ end.to raise_error(FunWithJsonApi::Exceptions::InvalidAttribute) do |e|
111
+ expect(e.payload.size).to eq 1
112
+
113
+ payload = e.payload.first
114
+ expect(payload.status).to eq '400'
115
+ expect(payload.code).to eq 'invalid_attribute'
116
+ expect(payload.title).to eq(
117
+ I18n.t('fun_with_json_api.exceptions.invalid_attribute')
118
+ )
119
+ expect(payload.detail).to eq(
120
+ I18n.t('fun_with_json_api.exceptions.invalid_date_attribute')
121
+ )
122
+ expect(payload.pointer).to eq '/data/attributes/example'
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ context 'with a datetime format' do
129
+ it 'should allow a ISO 8601 formatted values' do
130
+ deserializer = deserializer_with_attribute(:example, format: :datetime)
131
+ [
132
+ '2016-03-11T03:45:40+00:00',
133
+ '2016-03-11T13:45:40+10:00',
134
+ '2016-03-11T03:45:40Z',
135
+ '20160311T034540Z'
136
+ ].each do |timestamp|
137
+ expect(deserializer.parse_example(timestamp)).to eq(
138
+ DateTime.new(2016, 03, 11, 3, 45, 40, 0)
139
+ )
140
+ end
141
+ end
142
+ it 'should allow a nil value' do
143
+ deserializer = deserializer_with_attribute(:example, format: :datetime)
144
+ expect(deserializer.parse_example(nil)).to be nil
145
+ end
146
+ it 'should raise an InvalidAttribute for invalid date value' do
147
+ deserializer = deserializer_with_attribute(:example, format: :datetime)
148
+ [
149
+ 'Last Wednesday',
150
+ 'April'
151
+ ].each do |value|
152
+ expect do
153
+ deserializer.parse_example(value)
154
+ end.to raise_error(FunWithJsonApi::Exceptions::InvalidAttribute) do |e|
155
+ expect(e.payload.size).to eq 1
156
+
157
+ payload = e.payload.first
158
+ expect(payload.status).to eq '400'
159
+ expect(payload.code).to eq 'invalid_attribute'
160
+ expect(payload.title).to eq(
161
+ I18n.t('fun_with_json_api.exceptions.invalid_attribute')
162
+ )
163
+ expect(payload.detail).to eq(
164
+ I18n.t('fun_with_json_api.exceptions.invalid_datetime_attribute')
165
+ )
166
+ expect(payload.pointer).to eq '/data/attributes/example'
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ context 'with a decimal format' do
173
+ it 'should allow integers' do
174
+ deserializer = deserializer_with_attribute(:example, format: :decimal)
175
+ expect(deserializer.parse_example(12)).to eq BigDecimal.new('12')
176
+ end
177
+ it 'should allow floats' do
178
+ deserializer = deserializer_with_attribute(:example, format: :decimal)
179
+ expect(deserializer.parse_example(12.34)).to eq BigDecimal.new('12.34')
180
+ end
181
+ it 'should allow integer numbers as strings' do
182
+ deserializer = deserializer_with_attribute(:example, format: :decimal)
183
+ expect(deserializer.parse_example('12')).to eq BigDecimal.new('12')
184
+ end
185
+ it 'should allow floating point numbers as strings' do
186
+ deserializer = deserializer_with_attribute(:example, format: :decimal)
187
+ expect(deserializer.parse_example('12.30')).to eq BigDecimal.new('12.30')
188
+ end
189
+ it 'should allow a nil value' do
190
+ deserializer = deserializer_with_attribute(:example, format: :decimal)
191
+ expect(deserializer.parse_example(nil)).to be nil
192
+ end
193
+ it 'should raise an InvalidAttribute for invalid decimal value' do
194
+ deserializer = deserializer_with_attribute(:example, format: :decimal)
195
+ [
196
+ 'twelve',
197
+ '-',
198
+ 'abc'
199
+ ].each do |value|
200
+ expect do
201
+ deserializer.parse_example(value)
202
+ end.to raise_error(FunWithJsonApi::Exceptions::InvalidAttribute) do |e|
203
+ expect(e.payload.size).to eq 1
204
+
205
+ payload = e.payload.first
206
+ expect(payload.status).to eq '400'
207
+ expect(payload.code).to eq 'invalid_attribute'
208
+ expect(payload.title).to eq(
209
+ I18n.t('fun_with_json_api.exceptions.invalid_attribute')
210
+ )
211
+ expect(payload.detail).to eq(
212
+ I18n.t('fun_with_json_api.exceptions.invalid_decimal_attribute')
213
+ )
214
+ expect(payload.pointer).to eq '/data/attributes/example'
215
+ end
216
+ end
217
+ end
218
+ end
219
+
220
+ context 'with a float format' do
221
+ it 'should allow floats' do
222
+ deserializer = deserializer_with_attribute(:example, format: :float)
223
+ expect(deserializer.parse_example(12.34)).to eq 12.34
224
+ end
225
+ it 'should allow float numbers as strings' do
226
+ deserializer = deserializer_with_attribute(:example, format: :float)
227
+ expect(deserializer.parse_example('12.34')).to eq 12.34
228
+ end
229
+ it 'should allow integer numbers as strings' do
230
+ deserializer = deserializer_with_attribute(:example, format: :float)
231
+ expect(deserializer.parse_example('12')).to eq 12.0
232
+ end
233
+ it 'should allow a nil value' do
234
+ deserializer = deserializer_with_attribute(:example, format: :float)
235
+ expect(deserializer.parse_example(nil)).to be nil
236
+ end
237
+ it 'should raise an InvalidAttribute for invalid float value' do
238
+ deserializer = deserializer_with_attribute(:example, format: :float)
239
+ [
240
+ 'twelve',
241
+ '-',
242
+ 'abc'
243
+ ].each do |value|
244
+ expect do
245
+ deserializer.parse_example(value)
246
+ end.to raise_error(FunWithJsonApi::Exceptions::InvalidAttribute) do |e|
247
+ expect(e.payload.size).to eq 1
248
+
249
+ payload = e.payload.first
250
+ expect(payload.status).to eq '400'
251
+ expect(payload.code).to eq 'invalid_attribute'
252
+ expect(payload.title).to eq(
253
+ I18n.t('fun_with_json_api.exceptions.invalid_attribute')
254
+ )
255
+ expect(payload.detail).to eq(
256
+ I18n.t('fun_with_json_api.exceptions.invalid_float_attribute')
257
+ )
258
+ expect(payload.pointer).to eq '/data/attributes/example'
259
+ end
260
+ end
261
+ end
262
+ end
263
+
264
+ context 'with a integer format' do
265
+ it 'should allow integer numbers as strings' do
266
+ deserializer = deserializer_with_attribute(:example, format: :integer)
267
+ expect(deserializer.parse_example('12')).to eq BigDecimal.new('12')
268
+ end
269
+ it 'should allow a nil value' do
270
+ deserializer = deserializer_with_attribute(:example, format: :integer)
271
+ expect(deserializer.parse_example(nil)).to be nil
272
+ end
273
+ it 'should raise an InvalidAttribute for invalid integer value' do
274
+ deserializer = deserializer_with_attribute(:example, format: :integer)
275
+ [
276
+ 12.0,
277
+ '12.0',
278
+ 'twelve',
279
+ '-',
280
+ 'abc'
281
+ ].each do |value|
282
+ expect do
283
+ deserializer.parse_example(value)
284
+ end.to raise_error(FunWithJsonApi::Exceptions::InvalidAttribute) do |e|
285
+ expect(e.payload.size).to eq 1
286
+
287
+ payload = e.payload.first
288
+ expect(payload.status).to eq '400'
289
+ expect(payload.code).to eq 'invalid_attribute'
290
+ expect(payload.title).to eq(
291
+ I18n.t('fun_with_json_api.exceptions.invalid_attribute')
292
+ )
293
+ expect(payload.detail).to eq(
294
+ I18n.t('fun_with_json_api.exceptions.invalid_integer_attribute')
295
+ )
296
+ expect(payload.pointer).to eq '/data/attributes/example'
297
+ end
298
+ end
299
+ end
300
+ end
301
+
302
+ it 'raises an ArgumentError with an unknown format' do
303
+ expect do
304
+ deserializer_class_with_attribute(:example, format: :blarg)
305
+ end.to raise_error(ArgumentError)
306
+ end
307
+
308
+ it 'raises an ArgumentError with a blank attribute name' do
309
+ expect do
310
+ deserializer_class_with_attribute('', format: :string)
311
+ end.to raise_error(ArgumentError)
312
+ end
313
+ end
314
+
315
+ describe '#parse_{relationship}_id' do
316
+ context 'with a ARModels::Author relationship with a "code" id param' do
317
+ let(:deserializer) do
318
+ author_deserializer_class = Class.new(FunWithJsonApi::Deserializer) do
319
+ id_param 'code'
320
+ type 'persons'
321
+ resource_class ARModels::Author
322
+ end
323
+
324
+ # Build the Deserializer
325
+ Class.new(FunWithJsonApi::Deserializer) do
326
+ belongs_to :example, author_deserializer_class
327
+ end.create
328
+ end
329
+
330
+ it 'finds a resource by the defined id_param and returns the resource id' do
331
+ author = ARModels::Author.create(id: 1, code: 'foobar')
332
+ expect(deserializer.parse_example_id('foobar')).to eq author.id
333
+ end
334
+
335
+ it 'raises a MissingRelationship when unable to find the resource' do
336
+ expect do
337
+ deserializer.parse_example_id 'foobar'
338
+ end.to raise_error(FunWithJsonApi::Exceptions::MissingRelationship) do |e|
339
+ expect(e.message).to start_with "Couldn't find ARModels::Author where code = \"foobar\": "
340
+ expect(e.payload.size).to eq 1
341
+
342
+ payload = e.payload.first
343
+ expect(payload.status).to eq '404'
344
+ expect(payload.code).to eq 'missing_relationship'
345
+ expect(payload.title).to eq I18n.t('fun_with_json_api.exceptions.missing_relationship')
346
+ expect(payload.pointer).to eq '/data/relationships/example/id'
347
+ expect(payload.detail).to eq "Unable to find 'persons' with matching id: \"foobar\""
348
+ end
349
+ end
350
+
351
+ it 'raises a InvalidRelationship when given an array value' do
352
+ expect do
353
+ deserializer.parse_example_id %w(1 2)
354
+ end.to raise_error(FunWithJsonApi::Exceptions::InvalidRelationship) do |e|
355
+ expect(e.payload.size).to eq 1
356
+
357
+ payload = e.payload.first
358
+ expect(payload.status).to eq '400'
359
+ expect(payload.code).to eq 'invalid_relationship'
360
+ expect(payload.title).to eq I18n.t('fun_with_json_api.exceptions.invalid_relationship')
361
+ expect(payload.pointer).to eq '/data/relationships/example'
362
+ expect(payload.detail).to be_kind_of(String)
363
+ end
364
+ end
365
+ end
366
+ end
367
+
368
+ describe '#parse_{relationship}_ids' do
369
+ context 'with a ARModels::Author relationship with a "code" id param' do
370
+ let(:deserializer) do
371
+ author_deserializer_class = Class.new(FunWithJsonApi::Deserializer) do
372
+ id_param 'code'
373
+ type 'persons'
374
+ resource_class ARModels::Author
375
+ end
376
+
377
+ # Build the Deserializer
378
+ Class.new(FunWithJsonApi::Deserializer) do
379
+ has_many :examples, author_deserializer_class
380
+ end.create
381
+ end
382
+
383
+ it 'finds a resource by the defined id_param and returns the resource id' do
384
+ author_a = ARModels::Author.create(id: 1, code: 'foobar')
385
+ author_b = ARModels::Author.create(id: 2, code: 'blargh')
386
+ expect(deserializer.parse_example_ids(%w(foobar blargh))).to eq(
387
+ [author_a.id, author_b.id]
388
+ )
389
+ end
390
+
391
+ it 'raises a MissingRelationship when unable to find a single resource' do
392
+ ARModels::Author.create(id: 1, code: 'foobar')
393
+
394
+ expect do
395
+ deserializer.parse_example_ids %w(foobar blargh)
396
+ end.to raise_error(FunWithJsonApi::Exceptions::MissingRelationship) do |e|
397
+ expect(e.message).to eq "Couldn't find ARModels::Author items with code in [\"blargh\"]"
398
+ expect(e.payload.size).to eq 1
399
+
400
+ payload = e.payload.first
401
+ expect(payload.status).to eq '404'
402
+ expect(payload.code).to eq 'missing_relationship'
403
+ expect(payload.title).to eq I18n.t('fun_with_json_api.exceptions.missing_relationship')
404
+ expect(payload.pointer).to eq '/data/relationships/examples/id'
405
+ expect(payload.detail).to eq "Unable to find 'persons' with matching id: \"blargh\""
406
+ end
407
+ end
408
+
409
+ it 'raises a MissingRelationship with a payload for all missing resources' do
410
+ expect do
411
+ deserializer.parse_example_ids %w(foobar blargh)
412
+ end.to raise_error(FunWithJsonApi::Exceptions::MissingRelationship) do |e|
413
+ expect(e.message).to eq(
414
+ "Couldn't find ARModels::Author items with code in [\"foobar\", \"blargh\"]"
415
+ )
416
+ expect(e.payload.size).to eq 2
417
+
418
+ payload_a = e.payload.first
419
+ expect(payload_a.status).to eq '404'
420
+ expect(payload_a.code).to eq 'missing_relationship'
421
+ expect(payload_a.title).to eq I18n.t('fun_with_json_api.exceptions.missing_relationship')
422
+ expect(payload_a.pointer).to eq '/data/relationships/examples/id'
423
+ expect(payload_a.detail).to eq "Unable to find 'persons' with matching id: \"foobar\""
424
+
425
+ payload_b = e.payload.last
426
+ expect(payload_b.status).to eq '404'
427
+ expect(payload_b.code).to eq 'missing_relationship'
428
+ expect(payload_b.title).to eq I18n.t('fun_with_json_api.exceptions.missing_relationship')
429
+ expect(payload_b.pointer).to eq '/data/relationships/examples/id'
430
+ expect(payload_b.detail).to eq "Unable to find 'persons' with matching id: \"blargh\""
431
+ end
432
+ end
433
+
434
+ it 'raises a InvalidRelationship when given a non-array value' do
435
+ expect do
436
+ deserializer.parse_example_ids '1'
437
+ end.to raise_error(FunWithJsonApi::Exceptions::InvalidRelationship) do |e|
438
+ expect(e.payload.size).to eq 1
439
+
440
+ payload = e.payload.first
441
+ expect(payload.status).to eq '400'
442
+ expect(payload.code).to eq 'invalid_relationship'
443
+ expect(payload.title).to eq I18n.t('fun_with_json_api.exceptions.invalid_relationship')
444
+ expect(payload.pointer).to eq '/data/relationships/examples'
445
+ expect(payload.detail).to be_kind_of(String)
446
+ end
447
+ end
448
+ end
449
+ end
450
+ end