media_types-serialization 1.0.3 → 1.1.0
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.
- 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
|
[](https://badge.fury.io/rb/media_types-serialization)
|
5
5
|
[](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
|