media_types-serialization 1.0.3 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +7 -3
- data/.gitignore +12 -12
- data/.idea/.rakeTasks +5 -5
- data/.idea/inspectionProfiles/Project_Default.xml +5 -5
- data/.idea/runConfigurations/test.xml +19 -19
- data/.prettierrc +1 -0
- data/CHANGELOG.md +21 -9
- data/CODE_OF_CONDUCT.md +11 -11
- data/Gemfile +4 -4
- data/Gemfile.lock +63 -69
- data/LICENSE.txt +21 -21
- data/README.md +94 -47
- data/Rakefile +10 -10
- data/bin/console +14 -14
- data/bin/setup +8 -8
- data/lib/media_types/serialization.rb +61 -10
- data/lib/media_types/serialization/base.rb +8 -4
- data/lib/media_types/serialization/error.rb +11 -3
- data/lib/media_types/serialization/serialization_registration.rb +19 -9
- data/lib/media_types/serialization/serializers/problem_serializer.rb +23 -10
- data/lib/media_types/serialization/utils/accept_header.rb +77 -0
- data/lib/media_types/serialization/utils/accept_language_header.rb +82 -0
- data/lib/media_types/serialization/utils/header_list.rb +89 -0
- data/lib/media_types/serialization/version.rb +1 -1
- data/media_types-serialization.gemspec +0 -2
- metadata +11 -41
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
[![Gem Version](https://badge.fury.io/rb/media_types-serialization.svg)](https://badge.fury.io/rb/media_types-serialization)
|
5
5
|
[![MIT license](http://img.shields.io/badge/license-MIT-brightgreen.svg)](http://opensource.org/licenses/MIT)
|
6
6
|
|
7
|
-
`respond_to` on steroids. Add
|
7
|
+
`respond_to` on steroids. Add [HATEOAS](https://docs.delftsolutions.nl/wiki/HATEOAS_API) compatible serialization and deserialization to your Rails projects.
|
8
8
|
|
9
9
|
## Installation
|
10
10
|
|
@@ -57,6 +57,60 @@ BookSerializer.serialize(book, 'vnd.acme.book.v1+json', context: nil)
|
|
57
57
|
# => { "book": { "title": "Everything, abridged" } }
|
58
58
|
```
|
59
59
|
|
60
|
+
### Controller integration
|
61
|
+
|
62
|
+
You can integrate the serialization system in rails, giving you automatic [Content-Type negotiation](https://en.wikipedia.org/wiki/Content_negotiation) using the `Accept` header:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
require 'media_types/serialization'
|
66
|
+
|
67
|
+
class BookController < ActionController::API
|
68
|
+
include MediaTypes::Serialization
|
69
|
+
|
70
|
+
allow_output_serializer(BookSerializer, only: %i[show])
|
71
|
+
freeze_io!
|
72
|
+
|
73
|
+
def show
|
74
|
+
book = Book.new
|
75
|
+
book.title = 'Everything, abridged'
|
76
|
+
|
77
|
+
render_media book
|
78
|
+
end
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
82
|
+
While using the controller integration the context will always be set to the current controller. This allows you to construct urls.
|
83
|
+
|
84
|
+
### Adding HATEOAS responses to existing routes
|
85
|
+
|
86
|
+
When creating a mobile application it's often useful to allow the app to request a non-html representation of a specific url. If you have an existing route:
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
class BookController < ApplicationController
|
90
|
+
def show
|
91
|
+
@book = Book.new
|
92
|
+
|
93
|
+
# Use view corresponding to the controller
|
94
|
+
end
|
95
|
+
end
|
96
|
+
```
|
97
|
+
|
98
|
+
You can add a json representation as follows:
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
class BookController < ApplicationController
|
102
|
+
allow_output_serializer(BookSerializer, only: %i[show])
|
103
|
+
allow_output_html
|
104
|
+
freeze_io!
|
105
|
+
|
106
|
+
def show
|
107
|
+
@book = Book.new
|
108
|
+
|
109
|
+
render_media @book
|
110
|
+
end
|
111
|
+
end
|
112
|
+
```
|
113
|
+
|
60
114
|
### Validations
|
61
115
|
|
62
116
|
Right now the serializer does not validate incoming or outgoing information. This can cause issues when you accidentally emit non-conforming data that people start to depend on. To make sure you don't do that you can specify a [Media Type validator](https://github.com/SleeplessByte/media-types-ruby):
|
@@ -98,30 +152,6 @@ end
|
|
98
152
|
|
99
153
|
For more information, see the [Media Types docs](https://github.com/SleeplessByte/media-types-ruby).
|
100
154
|
|
101
|
-
### Controller integration
|
102
|
-
|
103
|
-
You can integrate the serialization system in rails, giving you automatic [Content-Type negotiation](https://en.wikipedia.org/wiki/Content_negotiation) using the `Accept` header:
|
104
|
-
|
105
|
-
```ruby
|
106
|
-
require 'media_types/serialization'
|
107
|
-
|
108
|
-
class BookController < ActionController::API
|
109
|
-
include MediaTypes::Serialization
|
110
|
-
|
111
|
-
allow_output_serializer(BookSerializer, only: %i[show])
|
112
|
-
freeze_io!
|
113
|
-
|
114
|
-
def show
|
115
|
-
book = Book.new
|
116
|
-
book.title = 'Everything, abridged'
|
117
|
-
|
118
|
-
render_media book
|
119
|
-
end
|
120
|
-
end
|
121
|
-
```
|
122
|
-
|
123
|
-
While using the controller integration the context will always be set to the current controller. This allows you to construct urls.
|
124
|
-
|
125
155
|
### Versioning
|
126
156
|
|
127
157
|
To help with supporting older versions, serializers have a [DSL](https://en.wikipedia.org/wiki/Domain-specific_language) to construct json objects:
|
@@ -149,7 +179,7 @@ BookSerializer.serialize(book, BookValidator.version(2), context: nil)
|
|
149
179
|
|
150
180
|
### Links
|
151
181
|
|
152
|
-
When making [HATEOAS](https://
|
182
|
+
When making [HATEOAS](https://docs.delftsolutions.nl/wiki/HATEOAS_API) compliant applications it's very useful to include `Link` headers in your response so clients can use a `HEAD` request instead of having to fetch the entire resource. Serializers have convenience methods to help with this:
|
153
183
|
|
154
184
|
```ruby
|
155
185
|
class BookSerializer < MediaTypes::Serialization::Base
|
@@ -206,7 +236,7 @@ class BookSerializer < MediaTypes::Serialization::Base
|
|
206
236
|
output view: :index, version: 3 do |arr, version, context|
|
207
237
|
attribute :books do
|
208
238
|
link :self, href: context.book_index_url
|
209
|
-
|
239
|
+
|
210
240
|
index arr, version: version
|
211
241
|
end
|
212
242
|
end
|
@@ -248,15 +278,15 @@ class BookSerializer < MediaTypes::Serialization::Base
|
|
248
278
|
output view: :index, version: 3 do |arr, version, context|
|
249
279
|
attribute :books do
|
250
280
|
link :self, href: context.book_index_url
|
251
|
-
|
281
|
+
|
252
282
|
index arr, version: version
|
253
283
|
end
|
254
284
|
end
|
255
|
-
|
285
|
+
|
256
286
|
output view: :collection, version: 3 do |arr, version, context|
|
257
287
|
attribute :books do
|
258
288
|
link :self, href: context.book_collection_url
|
259
|
-
|
289
|
+
|
260
290
|
collection arr, version: version
|
261
291
|
end
|
262
292
|
end
|
@@ -309,8 +339,8 @@ class BookController < ActionController::API
|
|
309
339
|
allow_output_serializer(BookSerializer, only: %i[show])
|
310
340
|
allow_input_serializer(BookSerializer, only: %i[create])
|
311
341
|
freeze_io!
|
312
|
-
|
313
|
-
def show
|
342
|
+
|
343
|
+
def show
|
314
344
|
book = Book.new
|
315
345
|
book.title = 'Everything, abridged'
|
316
346
|
|
@@ -355,8 +385,8 @@ class BookController < ActionController::API
|
|
355
385
|
allow_output_serializer(BookSerializer, only: %i[show])
|
356
386
|
allow_input_serializer(BookSerializer, only: %i[create])
|
357
387
|
freeze_io!
|
358
|
-
|
359
|
-
def show
|
388
|
+
|
389
|
+
def show
|
360
390
|
book = Book.new
|
361
391
|
book.title = 'Everything, abridged'
|
362
392
|
|
@@ -385,7 +415,7 @@ class BookSerializer < MediaTypes::Serialization::Base
|
|
385
415
|
output_raw view: :raw, version: 3 do |obj, version, context|
|
386
416
|
hidden do
|
387
417
|
# Make sure links are only set in the headers, not in the body.
|
388
|
-
|
418
|
+
|
389
419
|
link :self, href: context.book_url(obj)
|
390
420
|
end
|
391
421
|
|
@@ -454,14 +484,12 @@ class BookController < ActionController::API
|
|
454
484
|
include MediaTypes::Serialization
|
455
485
|
|
456
486
|
allow_api_viewer
|
457
|
-
|
458
|
-
allow_output_serializer(MediaTypes::ApiViewer)
|
459
487
|
|
460
488
|
allow_output_serializer(BookSerializer, only: %i[show])
|
461
489
|
allow_input_serializer(BookSerializer, only: %i[create])
|
462
490
|
freeze_io!
|
463
|
-
|
464
|
-
def show
|
491
|
+
|
492
|
+
def show
|
465
493
|
book = Book.new
|
466
494
|
book.title = 'Everything, abridged'
|
467
495
|
|
@@ -489,14 +517,14 @@ class BookSerializer < MediaTypes::Serialization::Base
|
|
489
517
|
attribute :description, obj.description if version >= 2
|
490
518
|
end
|
491
519
|
end
|
492
|
-
|
520
|
+
|
493
521
|
output_raw view: :html do |obj, context|
|
494
522
|
render_view 'book/show', context: context, assigns: {
|
495
523
|
title: obj.title,
|
496
524
|
description: obj.description
|
497
525
|
}
|
498
526
|
end
|
499
|
-
|
527
|
+
|
500
528
|
output_alias 'text/html', view: :html
|
501
529
|
end
|
502
530
|
```
|
@@ -518,11 +546,11 @@ class BookController < ActionController::API
|
|
518
546
|
|
519
547
|
freeze_io!
|
520
548
|
|
521
|
-
# ...
|
549
|
+
# ...
|
522
550
|
end
|
523
551
|
```
|
524
552
|
|
525
|
-
The exception you specified will be rescued by the controller and will be displayed to the user along with a link to the shared wiki page for that error type. Feel free to add instructions there on how clients should solve this problem. You can find more information at:
|
553
|
+
The exception you specified will be rescued by the controller and will be displayed to the user along with a link to the shared wiki page for that error type. Feel free to add instructions there on how clients should solve this problem. You can find more information at: [https://docs.delftsolutions.nl/wiki/Error](https://docs.delftsolutions.nl/wiki/Error)
|
526
554
|
If you want to override this url you can use the `p.url(href)` function.
|
527
555
|
|
528
556
|
By default the `message` property of the error is used to fill the `details` field. You can override this by using the `p.override_details(description, lang:)` function.
|
@@ -563,14 +591,18 @@ The block should return an object to convert into JSON.
|
|
563
591
|
|
564
592
|
This has the same behavior as `output` but should return a string instead of an object. Output is not validated.
|
565
593
|
|
566
|
-
#### `output_alias( media_type_identifier, view: )`
|
594
|
+
#### `output_alias( media_type_identifier, view:, hide_variant: false )`
|
567
595
|
|
568
|
-
Defines a legacy mapping. This will make the deserializer parse the media type `media_type_identifier` as if it was version
|
596
|
+
Defines a legacy mapping. This will make the deserializer parse the media type `media_type_identifier` as if it was version `nil` of the specified view. If view is undefined it will use the output serializer without a view defined.
|
569
597
|
|
570
|
-
|
598
|
+
Response will have a content type equal to `[media_type_identifier]; variant=[mapped_media_type_identifier]`. If `hide_variant:` is true, the content type emitted will only be `[media_type_identifier]`.
|
599
|
+
|
600
|
+
#### `output_alias_optional( media_type_identifier, view:, hide_variant: false )`
|
571
601
|
|
572
602
|
Has the same behavior as `output_alias` but can be used by multiple serializers. The serializer that is loaded last in the controller 'wins' control over this media type identifier. If any of the serializers have an `output_alias` defined with the same media type identifier that one will win instead.
|
573
603
|
|
604
|
+
Response will have a content type equal to `[media_type_identifier]; variant=[mapped_media_type_identifier]`. If `hide_variant:` is true, the content type emitted will only be `[media_type_identifier]`.
|
605
|
+
|
574
606
|
#### `input( view:, version:, versions: ) do |obj, version, context|`
|
575
607
|
|
576
608
|
Defines a deserialization block. Either version or versions can be set. View should be a symbol or unset.
|
@@ -656,6 +688,20 @@ Configure the controller to allow the client to request responses emitted by the
|
|
656
688
|
|
657
689
|
Accepts the same filters as `before_action`.
|
658
690
|
|
691
|
+
#### `allow_output_html( as: nil, layout: nil, **filters )`
|
692
|
+
|
693
|
+
Allows falling back to the default Rails view rendering when the client asks for the media type in the `as:` parameter or `text/html` if `as:` is unset.
|
694
|
+
|
695
|
+
The `Content-Type` of the response will be `text/html` if the `as:` parameter is unset. If the `as:` parameter is set, it will include it in the variant parameter: `text/html; variant=application/vnd.xpbytes.borderless`.
|
696
|
+
|
697
|
+
Accepts the same filters as `before_action`.
|
698
|
+
|
699
|
+
#### `allow_output_docs( description, **filters )`
|
700
|
+
|
701
|
+
Outputs the specified description as help information.
|
702
|
+
|
703
|
+
Accepts the same filters as `before_action`.
|
704
|
+
|
659
705
|
#### `allow_input_serializer( serializer, views: nil, **filters )`
|
660
706
|
|
661
707
|
Configure the controller to allow the client to send bodies with a `Content-Type` that can be deserialized using the specified serializer. Optionally allows you to specify which views to allow by passing an array in the views parameter.
|
@@ -690,7 +736,7 @@ Clears the list of serializers used to render the error when the client supplies
|
|
690
736
|
|
691
737
|
Enables rendering the api viewer when adding the `api_viewer=last` query parameter to the url.
|
692
738
|
|
693
|
-
#### `freeze_io
|
739
|
+
#### `freeze_io!(**filter_opts)`
|
694
740
|
|
695
741
|
Registers serialization and deserialization in the controller. This function must be called before using the controller.
|
696
742
|
|
@@ -740,6 +786,7 @@ Does the same as `deserialize( request )` but gives the client an error page if
|
|
740
786
|
Returns the serializer class that will handle the given request.
|
741
787
|
|
742
788
|
## Customization
|
789
|
+
|
743
790
|
The easiest way to customize the look and feel of the built in pages is to provide your own logo and background in an initializer:
|
744
791
|
|
745
792
|
```ruby
|
data/Rakefile
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
require "bundler/gem_tasks"
|
2
|
-
require "rake/testtask"
|
3
|
-
|
4
|
-
Rake::TestTask.new(:test) do |t|
|
5
|
-
t.libs << "test"
|
6
|
-
t.libs << "lib"
|
7
|
-
t.test_files = FileList["test/**/*_test.rb"]
|
8
|
-
end
|
9
|
-
|
10
|
-
task :default => :test
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
3
|
+
|
4
|
+
Rake::TestTask.new(:test) do |t|
|
5
|
+
t.libs << "test"
|
6
|
+
t.libs << "lib"
|
7
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
8
|
+
end
|
9
|
+
|
10
|
+
task :default => :test
|
data/bin/console
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
require "media_types/serialization"
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start(__FILE__)
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "media_types/serialization"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
#!/usr/bin/env bash
|
2
|
-
set -euo pipefail
|
3
|
-
IFS=$'\n\t'
|
4
|
-
set -vx
|
5
|
-
|
6
|
-
bundle install
|
7
|
-
|
8
|
-
# Do any other automated setup that you need to do here
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
set -euo pipefail
|
3
|
+
IFS=$'\n\t'
|
4
|
+
set -vx
|
5
|
+
|
6
|
+
bundle install
|
7
|
+
|
8
|
+
# Do any other automated setup that you need to do here
|
@@ -15,8 +15,7 @@ require 'active_support/concern'
|
|
15
15
|
require 'active_support/core_ext/module/attribute_accessors'
|
16
16
|
require 'active_support/core_ext/object/blank'
|
17
17
|
|
18
|
-
require '
|
19
|
-
|
18
|
+
require 'media_types/serialization/utils/accept_header'
|
20
19
|
require 'media_types/serialization/base'
|
21
20
|
require 'media_types/serialization/error'
|
22
21
|
require 'media_types/serialization/serialization_dsl'
|
@@ -44,7 +43,8 @@ end
|
|
44
43
|
module MediaTypes
|
45
44
|
module Serialization
|
46
45
|
|
47
|
-
HEADER_ACCEPT = 'HTTP_ACCEPT'
|
46
|
+
HEADER_ACCEPT = 'HTTP_ACCEPT'.freeze
|
47
|
+
HEADER_ACCEPT_LANGUAGE = 'HTTP_ACCEPT_LANGUAGE'.freeze
|
48
48
|
|
49
49
|
mattr_accessor :json_encoder, :json_decoder
|
50
50
|
if defined?(::Oj)
|
@@ -183,7 +183,58 @@ module MediaTypes
|
|
183
183
|
@serialization_output_registrations = @serialization_output_registrations.merge(mergeable_outputs)
|
184
184
|
end
|
185
185
|
end
|
186
|
-
|
186
|
+
|
187
|
+
def allow_output_html(as: nil, layout: nil, **filter_opts)
|
188
|
+
before_action(**filter_opts) do
|
189
|
+
raise SerializersAlreadyFrozenError if defined? @serialization_frozen
|
190
|
+
|
191
|
+
@serialization_output_registrations ||= SerializationRegistration.new(:output)
|
192
|
+
|
193
|
+
html_registration = SerializationRegistration.new(:output)
|
194
|
+
output_identifier = 'text/html'
|
195
|
+
output_identifier += "; variant=#{as}" unless as.nil?
|
196
|
+
|
197
|
+
validator = FakeValidator.new(as.nil? ? 'text/html' : as)
|
198
|
+
|
199
|
+
block = lambda { |_, _, controller|
|
200
|
+
if layout.nil?
|
201
|
+
controller.render_to_string
|
202
|
+
else
|
203
|
+
controller.render_to_string(layout: layout)
|
204
|
+
end
|
205
|
+
}
|
206
|
+
|
207
|
+
html_registration.register_block(nil, validator, nil, block, true, wildcards: true)
|
208
|
+
html_registration.registrations[validator.identifier].display_identifier = output_identifier
|
209
|
+
html_registration.registrations["#{validator.identifier.split('/')[0]}/*"].display_identifier = output_identifier
|
210
|
+
html_registration.registrations['*/*'].display_identifier = output_identifier
|
211
|
+
|
212
|
+
@serialization_output_registrations = @serialization_output_registrations.merge(html_registration)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def allow_output_docs(description, **filter_opts)
|
217
|
+
before_action(**filter_opts) do
|
218
|
+
raise SerializersAlreadyFrozenError if defined? @serialization_frozen
|
219
|
+
|
220
|
+
@serialization_output_registrations ||= SerializationRegistration.new(:output)
|
221
|
+
|
222
|
+
docs_registration = SerializationRegistration.new(:output)
|
223
|
+
validator = FakeValidator.new('text/vnd.delftsolutions.docs')
|
224
|
+
|
225
|
+
block = lambda { |_, _, _|
|
226
|
+
description
|
227
|
+
}
|
228
|
+
|
229
|
+
docs_registration.register_block(nil, validator, nil, block, true, wildcards: true)
|
230
|
+
docs_registration.registrations['text/vnd.delftsolutions.docs'].display_identifier = 'text/plain; charset=utf-8'
|
231
|
+
docs_registration.registrations['text/*'].display_identifier = 'text/plain; charset=utf-8'
|
232
|
+
docs_registration.registrations['*/*'].display_identifier = 'text/plain; charset=utf-8'
|
233
|
+
|
234
|
+
@serialization_output_registrations = @serialization_output_registrations.merge(docs_registration)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
187
238
|
def allow_api_viewer(serializer: MediaTypes::Serialization::Serializers::ApiViewer, **filter_opts)
|
188
239
|
before_action do
|
189
240
|
@serialization_api_viewer_enabled ||= {}
|
@@ -216,7 +267,7 @@ module MediaTypes
|
|
216
267
|
raise ArrayInViewParameterError, :allow_input_serializer if view.is_a? Array
|
217
268
|
views = [view] if views.nil?
|
218
269
|
raise ViewsNotAnArrayError unless views.is_a? Array
|
219
|
-
|
270
|
+
|
220
271
|
before_action do
|
221
272
|
@serialization_available_serializers ||= {}
|
222
273
|
@serialization_available_serializers[:input] ||= {}
|
@@ -259,8 +310,8 @@ module MediaTypes
|
|
259
310
|
##
|
260
311
|
# Freezes additions to the serializes and notifies the controller what it will be able to respond to.
|
261
312
|
#
|
262
|
-
def freeze_io!
|
263
|
-
before_action :serializer_freeze_io_internal
|
313
|
+
def freeze_io!(**filter_opts)
|
314
|
+
before_action :serializer_freeze_io_internal, **filter_opts
|
264
315
|
|
265
316
|
output_error MediaTypes::Serialization::NoInputReceivedError do |p, error|
|
266
317
|
p.title 'Providing input is mandatory. Please set a Content-Type', lang: 'en'
|
@@ -366,7 +417,7 @@ module MediaTypes
|
|
366
417
|
return nil if identifier.nil?
|
367
418
|
|
368
419
|
registration = registration.registrations[identifier]
|
369
|
-
|
420
|
+
|
370
421
|
raise 'Assertion failed, inconsistent answer from resolve_media_type' if registration.nil?
|
371
422
|
registration.serializer
|
372
423
|
end
|
@@ -386,7 +437,7 @@ module MediaTypes
|
|
386
437
|
#
|
387
438
|
#
|
388
439
|
|
389
|
-
accept_header =
|
440
|
+
accept_header = Utils::AcceptHeader.new(request.get_header(HEADER_ACCEPT)) || ''
|
390
441
|
accept_header.each do |mime_type|
|
391
442
|
stripped = mime_type.to_s.split(';')[0]
|
392
443
|
next unless registration.has? stripped
|
@@ -403,7 +454,7 @@ module MediaTypes
|
|
403
454
|
identifier = serializer.validator.identifier
|
404
455
|
obj = { request: request, registrations: registrations }
|
405
456
|
new_registrations = serializer.outputs_for(views: [nil])
|
406
|
-
|
457
|
+
|
407
458
|
serialization_render_resolved(obj: obj, serializer: serializer, identifier: identifier, registrations: new_registrations, options: {})
|
408
459
|
response.status = :not_acceptable
|
409
460
|
end
|