Skip to content

Commit 1309f22

Browse files
author
Fletcher91
committed
Introduces per-request adapter switching based on the request mime.
1 parent dff621e commit 1309f22

File tree

6 files changed

+35
-1
lines changed

6 files changed

+35
-1
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Breaking changes:
66

77
Features:
88

9+
- [#?](https://github.com/rails-api/active_model_serializers/pull/?) Introduces per-request adapter switching based on the request mime. (@fletcher91)
10+
911
Fixes:
1012

1113
Misc:

docs/general/adapters.md

+14
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,20 @@ The `Attributes` adapter does not include a root key. It is just the serialized
3636

3737
Use either the `JSON` or `JSON API` adapters if you want the response document to have a root key.
3838

39+
To automatically switch between adapters based on the request, set the adapter to `:mime`
40+
41+
```ruby
42+
# In configuration
43+
ActiveModelSerializers.config.adapter = :mime
44+
45+
# In controller action
46+
respond_to do |format|
47+
format.json { render json: Model.first } # Uses the JSON adapter
48+
format.json_api { render json: Model.first } # Users the JSON:API adapter
49+
format.bug { render json: Model.first } # Will raise `UnknownAdapterError`
50+
end
51+
```
52+
3953
## Built in Adapters
4054

4155
### Attributes - Default

lib/active_model_serializers/adapter.rb

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ def configured_adapter
1919

2020
def create(resource, options = {})
2121
override = options.delete(:adapter)
22+
context = options[:serialization_context]
23+
format = context && context.format
24+
if format && (override || ActiveModelSerializers.config.adapter) == :mime
25+
override = lookup(format)
26+
end
2227
klass = override ? adapter_class(override) : configured_adapter
2328
klass.new(resource, options)
2429
end

lib/active_model_serializers/serialization_context.rb

+3-1
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,17 @@ def default_url_options
2121
end
2222
end
2323

24-
attr_reader :request_url, :query_parameters, :key_transform
24+
attr_reader :request_url, :query_parameters, :key_transform, :format
2525

2626
def initialize(*args)
2727
options = args.extract_options!
2828
if args.size == 1
2929
request = args.pop
30+
options[:format] = request.format.to_sym
3031
options[:request_url] = request.original_url[/\A[^?]+/]
3132
options[:query_parameters] = request.query_parameters
3233
end
34+
@format = options.delete(:format)
3335
@request_url = options.delete(:request_url)
3436
@query_parameters = options.delete(:query_parameters)
3537
@url_helpers = options.delete(:url_helpers) || self.class.url_helpers

test/adapter/json_api/pagination_links_test.rb

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def mock_request(query_parameters = {}, original_url = URI)
2626
context.expect(:request_url, original_url)
2727
context.expect(:query_parameters, query_parameters)
2828
context.expect(:key_transform, nil)
29+
context.expect(:format, nil)
2930
end
3031

3132
def load_adapter(paginated_collection, mock_request = nil)

test/adapter_test.rb

+10
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@ def test_create_adapter_with_override
5555
assert_equal ActiveModelSerializers::Adapter::JsonApi, adapter.class
5656
end
5757

58+
def test_create_adapter_with_mime
59+
json_context = ActiveModelSerializers::SerializationContext.new(format: :json)
60+
adapter = ActiveModelSerializers::Adapter.create(@serializer, adapter: :mime, serialization_context: json_context)
61+
assert_equal ActiveModelSerializers::Adapter::Json, adapter.class
62+
63+
json_api_context = ActiveModelSerializers::SerializationContext.new(format: :json_api)
64+
adapter = ActiveModelSerializers::Adapter.create(@serializer, adapter: :mime, serialization_context: json_api_context)
65+
assert_equal ActiveModelSerializers::Adapter::JsonApi, adapter.class
66+
end
67+
5868
def test_inflected_adapter_class_for_known_adapter
5969
ActiveSupport::Inflector.inflections(:en) { |inflect| inflect.acronym 'API' }
6070
klass = ActiveModelSerializers::Adapter.adapter_class(:json_api)

0 commit comments

Comments
 (0)