Skip to content

Commit

Permalink
Replace fail/rescue CollectionSerializer::NoSerializerError with thro…
Browse files Browse the repository at this point in the history
…w/catch :no_serializer
  • Loading branch information
bf4 committed Jun 1, 2016
1 parent f2f747e commit 6373a4f
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Breaking changes:

Features:
- [#1426](https://github.com/rails-api/active_model_serializers/pull/1426) Add ActiveModelSerializers.config.default_includes (@empact)
- [TBD](TBD) Replace raising/rescuing `CollectionSerializer::NoSerializerError`, throw/catch `:no_serializer`. (@bf4)

Fixes:
- [#1710](https://github.com/rails-api/active_model_serializers/pull/1710) Prevent association loading when `include_data` option
Expand Down
13 changes: 6 additions & 7 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ It requires an adapter to transform its attributes into a JSON document; it cann
It may be useful to think of it as a
[presenter](http://blog.steveklabnik.com/posts/2011-09-09-better-ruby-presenters).

The **`ActiveModel::ArraySerializer`** represent a collection of resources as serializers
The **`ActiveModel::CollectionSerializer`** represent a collection of resources as serializers
and, if there is no serializer, primitives.

The **`ActiveModel::Adapter`** describes the structure of the JSON document generated from a
Expand All @@ -42,10 +42,9 @@ it is not modified.
Internally, if no serializer can be found in the controller, the resource is not decorated by
ActiveModelSerializers.

If the collection serializer (ArraySerializer) cannot
identify a serializer for a resource in its collection, it raises [`NoSerializerError`](https://github.com/rails-api/active_model_serializers/issues/1191#issuecomment-142327128)
which is rescued in `ActiveModel::Serializer::Reflection#build_association` which sets
the association value directly:
If the collection serializer (CollectionSerializer) cannot
identify a serializer for a resource in its collection, it throws [`:no_serializer`](https://github.com/rails-api/active_model_serializers/issues/1191#issuecomment-142327128).
For example, when caught by `Reflection#build_association`, the association value is set directly:

```ruby
reflection_options[:virtual_value] = association_value.try(:as_json) || association_value
Expand Down Expand Up @@ -85,8 +84,8 @@ Details:
1. The serializer and adapter are created as
1. `serializer_instance = serializer.new(resource, serializer_opts)`
2. `adapter_instance = ActiveModel::Serializer::Adapter.create(serializer_instance, adapter_opts)`
1. **ActiveModel::Serializer::ArraySerializer#new**
1. If the `serializer_instance` was a `ArraySerializer` and the `:serializer` serializer_opts
1. **ActiveModel::Serializer::CollectionSerializer#new**
1. If the `serializer_instance` was a `CollectionSerializer` and the `:serializer` serializer_opts
is present, then [that serializer is passed into each resource](https://github.com/rails-api/active_model_serializers/blob/a54d237e2828fe6bab1ea5dfe6360d4ecc8214cd/lib/active_model/serializer/array_serializer.rb#L14-L16).
1. **ActiveModel::Serializer#attributes** is used by the adapter to get the attributes for
resource as defined by the serializer.
Expand Down
6 changes: 3 additions & 3 deletions lib/active_model/serializer/collection_serializer.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
module ActiveModel
class Serializer
class CollectionSerializer
NoSerializerError = Class.new(StandardError)
include Enumerable
delegate :each, to: :@serializers

Expand All @@ -15,8 +14,9 @@ def initialize(resources, options = {})
@serializers = resources.map do |resource|
serializer_class = options.fetch(:serializer) { serializer_context_class.serializer_for(resource) }

if serializer_class.nil? # rubocop:disable Style/GuardClause
fail NoSerializerError, "No serializer found for resource: #{resource.inspect}"
if serializer_class.nil?
ActiveModelSerializers.logger.debug "No serializer found for resource: #{resource.inspect}"
throw :no_serializer
else
serializer_class.new(resource, options.except(:serializer))
end
Expand Down
7 changes: 4 additions & 3 deletions lib/active_model/serializer/reflection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,13 @@ def build_association(subject, parent_serializer_options)
reflection_options[:include_data] = @_include_data

if serializer_class
begin
serializer = serializer_class.new(
serializer = catch :no_serializer do
serializer_class.new(
association_value,
serializer_options(subject, parent_serializer_options, reflection_options)
)
rescue ActiveModel::Serializer::CollectionSerializer::NoSerializerError
end
if serializer.nil?
reflection_options[:virtual_value] = association_value.try(:as_json) || association_value
end
elsif !association_value.nil? && !association_value.instance_of?(Object)
Expand Down
7 changes: 4 additions & 3 deletions lib/active_model_serializers/serializable_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ def adapter

def find_adapter
return resource unless serializer?
ActiveModelSerializers::Adapter.create(serializer_instance, adapter_opts)
rescue ActiveModel::Serializer::CollectionSerializer::NoSerializerError
resource
adapter = catch :no_serializer do
ActiveModelSerializers::Adapter.create(serializer_instance, adapter_opts)
end
adapter || resource
end

def serializer_instance
Expand Down

0 comments on commit 6373a4f

Please sign in to comment.