diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cc4c01c..ad8ad929 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,8 @@ Features: - [#1050](https://github.com/rails-api/active_model_serializers/pull/1050) Add support for toplevel jsonapi member (@beauby, @bf4) - [#1251](https://github.com/rails-api/active_model_serializers/pull/1251) Rename ArraySerializer to CollectionSerializer for clarity, add ActiveModelSerializers.config.collection_serializer (@bf4) +- [#1295](https://github.com/rails-api/active_model_serializers/pull/1295) Add config `serializer_lookup_enabled` that, + when disabled, requires serializers to explicitly specified. (@trek) Fixes: - [#1239](https://github.com/rails-api/active_model_serializers/pull/1239) Fix duplicates in JSON API compound documents (@beauby) diff --git a/docs/general/configuration_options.md b/docs/general/configuration_options.md index 46465f06..1632324d 100644 --- a/docs/general/configuration_options.md +++ b/docs/general/configuration_options.md @@ -5,6 +5,7 @@ The following configuration options can be set on `ActiveModel::Serializer.confi ## General - `adapter`: The [adapter](adapters.md) to use. Possible values: `:attributes, :json, :json_api`. Default: `:attributes`. +- `serializer_lookup_enabled`: When `false`, serializers must be explicitly specified. Default: `true` ## JSON API diff --git a/lib/action_controller/serialization.rb b/lib/action_controller/serialization.rb index 5fefaedf..fb5a03a3 100644 --- a/lib/action_controller/serialization.rb +++ b/lib/action_controller/serialization.rb @@ -10,6 +10,12 @@ module ActionController # Deprecated ADAPTER_OPTION_KEYS = ActiveModel::SerializableResource::ADAPTER_OPTION_KEYS + module ClassMethods + def serialization_scope(scope) + self._serialization_scope = scope + end + end + included do class_attribute :_serialization_scope self._serialization_scope = :current_user @@ -55,11 +61,5 @@ module ActionController super(serializable_resource, options) end end - - module ClassMethods - def serialization_scope(scope) - self._serialization_scope = scope - end - end end end diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index eadcb32e..48f57edc 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -172,6 +172,7 @@ module ActiveModel # 2. try again with superclass, if present # 3. nil def self.get_serializer_for(klass) + return nil unless config.serializer_lookup_enabled serializers_cache.fetch_or_store(klass) do # NOTE(beauby): When we drop 1.9.3 support we can lazify the map for perfs. serializer_class = serializer_lookup_chain_for(klass).map(&:safe_constantize).find { |x| x && x < ActiveModel::Serializer } diff --git a/lib/active_model/serializer/configuration.rb b/lib/active_model/serializer/configuration.rb index 9e33633e..520f76f2 100644 --- a/lib/active_model/serializer/configuration.rb +++ b/lib/active_model/serializer/configuration.rb @@ -9,6 +9,7 @@ module ActiveModel included do |base| config = base.config config.collection_serializer = ActiveModel::Serializer::CollectionSerializer + config.serializer_lookup_enabled = true def config.array_serializer=(collection_serializer) self.collection_serializer = collection_serializer diff --git a/test/serializers/serializer_for_test.rb b/test/serializers/serializer_for_test.rb index 53b2f07d..89cbd199 100644 --- a/test/serializers/serializer_for_test.rb +++ b/test/serializers/serializer_for_test.rb @@ -57,7 +57,7 @@ module ActiveModel def test_serializer_for_non_ams_serializer serializer = ActiveModel::Serializer.serializer_for(@tweet) - assert_nil(serializer) + assert_equal nil, serializer end def test_serializer_for_existing_serializer @@ -65,6 +65,13 @@ module ActiveModel assert_equal ProfileSerializer, serializer end + def test_serializer_for_existing_serializer_with_lookup_disabled + serializer = with_serializer_lookup_disabled do + ActiveModel::Serializer.serializer_for(@profile) + end + assert_equal nil, serializer + end + def test_serializer_for_not_existing_serializer serializer = ActiveModel::Serializer.serializer_for(@model) assert_equal nil, serializer @@ -75,21 +82,51 @@ module ActiveModel assert_equal ProfileSerializer, serializer end + def test_serializer_inherited_serializer_with_lookup_disabled + serializer = with_serializer_lookup_disabled do + ActiveModel::Serializer.serializer_for(@my_profile) + end + assert_equal nil, serializer + end + def test_serializer_custom_serializer serializer = ActiveModel::Serializer.serializer_for(@custom_profile) assert_equal ProfileSerializer, serializer end + def test_serializer_custom_serializer_with_lookup_disabled + serializer = with_serializer_lookup_disabled do + ActiveModel::Serializer.serializer_for(@custom_profile) + end + assert_equal ProfileSerializer, serializer + end + def test_serializer_for_namespaced_resource post = ResourceNamespace::Post.new serializer = ActiveModel::Serializer.serializer_for(post) - assert_equal(ResourceNamespace::PostSerializer, serializer) + assert_equal ResourceNamespace::PostSerializer, serializer + end + + def test_serializer_for_namespaced_resource_with_lookup_disabled + post = ResourceNamespace::Post.new + serializer = with_serializer_lookup_disabled do + ActiveModel::Serializer.serializer_for(post) + end + assert_equal nil, serializer end def test_serializer_for_nested_resource comment = ResourceNamespace::Comment.new serializer = ResourceNamespace::PostSerializer.serializer_for(comment) - assert_equal(ResourceNamespace::PostSerializer::CommentSerializer, serializer) + assert_equal ResourceNamespace::PostSerializer::CommentSerializer, serializer + end + + def test_serializer_for_nested_resource_with_lookup_disabled + comment = ResourceNamespace::Comment.new + serializer = with_serializer_lookup_disabled do + ResourceNamespace::PostSerializer.serializer_for(comment) + end + assert_equal nil, serializer end end end diff --git a/test/support/serialization_testing.rb b/test/support/serialization_testing.rb index e1272097..84853e2b 100644 --- a/test/support/serialization_testing.rb +++ b/test/support/serialization_testing.rb @@ -31,6 +31,14 @@ module SerializationTesting ActiveModel::Serializer.config.replace(old_config) end + def with_serializer_lookup_disabled + original_serializer_lookup = ActiveModelSerializers.config.serializer_lookup_enabled + ActiveModelSerializers.config.serializer_lookup_enabled = false + yield + ensure + ActiveModelSerializers.config.serializer_lookup_enabled = original_serializer_lookup + end + def serializable(resource, options = {}) ActiveModel::SerializableResource.new(resource, options) end