Skip to content

Commit

Permalink
Introduces per-request adapter switching based on the request mime.
Browse files Browse the repository at this point in the history
  • Loading branch information
Fletcher91 committed May 2, 2017
1 parent dff621e commit c7bf9aa
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Breaking changes:

Features:

- [#2122](https://github.com/rails-api/active_model_serializers/pull/2122) Introduces per-request adapter switching based on the request mime. (@fletcher91)

Fixes:

Misc:
Expand Down
14 changes: 14 additions & 0 deletions docs/general/adapters.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@ The `Attributes` adapter does not include a root key. It is just the serialized

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

To automatically switch between adapters based on the request, set the adapter to `:mime`

```ruby
# In configuration
ActiveModelSerializers.config.adapter = :mime

# In controller action
respond_to do |format|
format.json { render json: Model.first } # Uses the JSON adapter
format.json_api { render json: Model.first } # Users the JSON:API adapter
format.bug { render json: Model.first } # Will raise `UnknownAdapterError`
end
```

## Built in Adapters

### Attributes - Default
Expand Down
5 changes: 5 additions & 0 deletions lib/active_model_serializers/adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ def configured_adapter

def create(resource, options = {})
override = options.delete(:adapter)
context = options[:serialization_context]
format = context && context.format
if format && (override || ActiveModelSerializers.config.adapter) == :mime
override = lookup(format)
end
klass = override ? adapter_class(override) : configured_adapter
klass.new(resource, options)
end
Expand Down
4 changes: 3 additions & 1 deletion lib/active_model_serializers/serialization_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@ def default_url_options
end
end

attr_reader :request_url, :query_parameters, :key_transform
attr_reader :request_url, :query_parameters, :key_transform, :format

def initialize(*args)
options = args.extract_options!
if args.size == 1
request = args.pop
options[:format] = request.format.to_sym
options[:request_url] = request.original_url[/\A[^?]+/]
options[:query_parameters] = request.query_parameters
end
@format = options.delete(:format)
@request_url = options.delete(:request_url)
@query_parameters = options.delete(:query_parameters)
@url_helpers = options.delete(:url_helpers) || self.class.url_helpers
Expand Down
1 change: 1 addition & 0 deletions test/adapter/json_api/pagination_links_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def mock_request(query_parameters = {}, original_url = URI)
context.expect(:request_url, original_url)
context.expect(:query_parameters, query_parameters)
context.expect(:key_transform, nil)
context.expect(:format, nil)
end

def load_adapter(paginated_collection, mock_request = nil)
Expand Down
10 changes: 10 additions & 0 deletions test/adapter_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ def test_create_adapter_with_override
assert_equal ActiveModelSerializers::Adapter::JsonApi, adapter.class
end

def test_create_adapter_with_mime
json_context = ActiveModelSerializers::SerializationContext.new(format: :json)
adapter = ActiveModelSerializers::Adapter.create(@serializer, adapter: :mime, serialization_context: json_context)
assert_equal ActiveModelSerializers::Adapter::Json, adapter.class

json_api_context = ActiveModelSerializers::SerializationContext.new(format: :json_api)
adapter = ActiveModelSerializers::Adapter.create(@serializer, adapter: :mime, serialization_context: json_api_context)
assert_equal ActiveModelSerializers::Adapter::JsonApi, adapter.class
end

def test_inflected_adapter_class_for_known_adapter
ActiveSupport::Inflector.inflections(:en) { |inflect| inflect.acronym 'API' }
klass = ActiveModelSerializers::Adapter.adapter_class(:json_api)
Expand Down

0 comments on commit c7bf9aa

Please sign in to comment.