diff --git a/CHANGELOG.md b/CHANGELOG.md index a550a964..bc99a7c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ ### 0.10.0 +Breaking changes: + * Adapters now inherit Adapter::Base. 'Adapter' is now a module, no longer a class. [@bf4], #1138 + * using a class as a namespace that you also inherit from is complicated and circular at time i.e. + buggy (see https://github.com/rails-api/active_model_serializers/pull/1177) + * The class methods on Adapter aren't necessarily related to the instance methods, they're more + Adapter functions + * named `Base` because it's a Rails-ism + * It helps to isolate and highlight what the Adapter interface actually is + +Features: * adds adapters pattern * adds support for `meta` and `meta_key` [@kurko] * adds method to override association [@kurko] @@ -12,3 +22,7 @@ * adds FlattenJSON as default adapter [@joaomdmoura] * adds support for `pagination links` at top level of JsonApi adapter [@bacarini] * adds extended format for `include` option to JsonApi adapter [@beauby] + +Fixes: + +Misc: diff --git a/lib/active_model/serializer/adapter.rb b/lib/active_model/serializer/adapter.rb index 20b21a79..832fe3f4 100644 --- a/lib/active_model/serializer/adapter.rb +++ b/lib/active_model/serializer/adapter.rb @@ -1,26 +1,30 @@ module ActiveModel class Serializer - class Adapter + module Adapter UnknownAdapterError = Class.new(ArgumentError) ADAPTER_MAP = {} private_constant :ADAPTER_MAP if defined?(private_constant) require 'active_model/serializer/adapter/fragment_cache' require 'active_model/serializer/adapter/cached_serializer' - def self.create(resource, options = {}) - override = options.delete(:adapter) - klass = override ? adapter_class(override) : ActiveModel::Serializer.adapter - klass.new(resource, options) - end + class << self # All methods are class functions + def new(*args) + fail ArgumentError, 'Adapters inherit from Adapter::Base.' \ + "Adapter.new called with args: '#{args.inspect}', from" \ + "'caller[0]'." + end - # @see ActiveModel::Serializer::Adapter.lookup - def self.adapter_class(adapter) - ActiveModel::Serializer::Adapter.lookup(adapter) - end + def create(resource, options = {}) + override = options.delete(:adapter) + klass = override ? adapter_class(override) : ActiveModel::Serializer.adapter + klass.new(resource, options) + end + + # @see ActiveModel::Serializer::Adapter.lookup + def adapter_class(adapter) + ActiveModel::Serializer::Adapter.lookup(adapter) + end - # Only the Adapter class has these methods. - # None of the sublasses have them. - class << ActiveModel::Serializer::Adapter # @return Hash def adapter_map ADAPTER_MAP @@ -76,58 +80,8 @@ module ActiveModel private :find_by_name end - # Automatically register adapters when subclassing - def self.inherited(subclass) - ActiveModel::Serializer::Adapter.register(subclass) - end - - attr_reader :serializer, :instance_options - - def initialize(serializer, options = {}) - @serializer = serializer - @instance_options = options - end - - def serializable_hash(options = nil) - raise NotImplementedError, 'This is an abstract method. Should be implemented at the concrete adapter.' - end - - def as_json(options = nil) - hash = serializable_hash(options) - include_meta(hash) - hash - end - - def fragment_cache(*args) - raise NotImplementedError, 'This is an abstract method. Should be implemented at the concrete adapter.' - end - - def cache_check(serializer) - CachedSerializer.new(serializer).cache_check(self) do - yield - end - end - - private - - def meta - serializer.meta if serializer.respond_to?(:meta) - end - - def meta_key - serializer.meta_key || 'meta'.freeze - end - - def root - serializer.json_key.to_sym if serializer.json_key - end - - def include_meta(json) - json[meta_key] = meta if meta - json - end - # Gotta be at the bottom to use the code above it :( + require 'active_model/serializer/adapter/base' require 'active_model/serializer/adapter/null' require 'active_model/serializer/adapter/attributes' require 'active_model/serializer/adapter/json' diff --git a/lib/active_model/serializer/adapter/attributes.rb b/lib/active_model/serializer/adapter/attributes.rb index 7ebe76ba..09761a4a 100644 --- a/lib/active_model/serializer/adapter/attributes.rb +++ b/lib/active_model/serializer/adapter/attributes.rb @@ -1,7 +1,7 @@ module ActiveModel class Serializer - class Adapter - class Attributes < Adapter + module Adapter + class Attributes < Base def serializable_hash(options = nil) options ||= {} if serializer.respond_to?(:each) diff --git a/lib/active_model/serializer/adapter/base.rb b/lib/active_model/serializer/adapter/base.rb new file mode 100644 index 00000000..2496236f --- /dev/null +++ b/lib/active_model/serializer/adapter/base.rb @@ -0,0 +1,58 @@ +module ActiveModel + class Serializer + module Adapter + class Base + # Automatically register adapters when subclassing + def self.inherited(subclass) + ActiveModel::Serializer::Adapter.register(subclass) + end + + attr_reader :serializer, :instance_options + + def initialize(serializer, options = {}) + @serializer = serializer + @instance_options = options + end + + def serializable_hash(_options = nil) + fail NotImplementedError, 'This is an abstract method. Should be implemented at the concrete adapter.' + end + + def as_json(options = nil) + hash = serializable_hash(options) + include_meta(hash) + hash + end + + def fragment_cache(*_args) + fail NotImplementedError, 'This is an abstract method. Should be implemented at the concrete adapter.' + end + + def cache_check(serializer) + CachedSerializer.new(serializer).cache_check(self) do + yield + end + end + + private + + def meta + serializer.meta if serializer.respond_to?(:meta) + end + + def meta_key + serializer.meta_key || 'meta'.freeze + end + + def root + serializer.json_key.to_sym if serializer.json_key + end + + def include_meta(json) + json[meta_key] = meta if meta + json + end + end + end + end +end diff --git a/lib/active_model/serializer/adapter/cached_serializer.rb b/lib/active_model/serializer/adapter/cached_serializer.rb index 86bf65ac..35b10168 100644 --- a/lib/active_model/serializer/adapter/cached_serializer.rb +++ b/lib/active_model/serializer/adapter/cached_serializer.rb @@ -1,6 +1,6 @@ module ActiveModel class Serializer - class Adapter + module Adapter class CachedSerializer def initialize(serializer) @cached_serializer = serializer diff --git a/lib/active_model/serializer/adapter/fragment_cache.rb b/lib/active_model/serializer/adapter/fragment_cache.rb index 7b47c1d4..6a326996 100644 --- a/lib/active_model/serializer/adapter/fragment_cache.rb +++ b/lib/active_model/serializer/adapter/fragment_cache.rb @@ -1,6 +1,6 @@ module ActiveModel class Serializer - class Adapter + module Adapter class FragmentCache attr_reader :serializer diff --git a/lib/active_model/serializer/adapter/json.rb b/lib/active_model/serializer/adapter/json.rb index 1bebe8e8..4e5fd29f 100644 --- a/lib/active_model/serializer/adapter/json.rb +++ b/lib/active_model/serializer/adapter/json.rb @@ -1,7 +1,7 @@ module ActiveModel class Serializer - class Adapter - class Json < Adapter + module Adapter + class Json < Base extend ActiveSupport::Autoload autoload :FragmentCache diff --git a/lib/active_model/serializer/adapter/json/fragment_cache.rb b/lib/active_model/serializer/adapter/json/fragment_cache.rb index 76ba1ee6..ff312cd9 100644 --- a/lib/active_model/serializer/adapter/json/fragment_cache.rb +++ b/lib/active_model/serializer/adapter/json/fragment_cache.rb @@ -1,6 +1,6 @@ module ActiveModel class Serializer - class Adapter + module Adapter class Json class FragmentCache def fragment_cache(cached_hash, non_cached_hash) diff --git a/lib/active_model/serializer/adapter/json_api.rb b/lib/active_model/serializer/adapter/json_api.rb index 87b40999..7a028717 100644 --- a/lib/active_model/serializer/adapter/json_api.rb +++ b/lib/active_model/serializer/adapter/json_api.rb @@ -1,7 +1,7 @@ module ActiveModel class Serializer - class Adapter - class JsonApi < Adapter + module Adapter + class JsonApi < Base extend ActiveSupport::Autoload autoload :PaginationLinks autoload :FragmentCache diff --git a/lib/active_model/serializer/adapter/json_api/fragment_cache.rb b/lib/active_model/serializer/adapter/json_api/fragment_cache.rb index edadb4ec..7dbc1179 100644 --- a/lib/active_model/serializer/adapter/json_api/fragment_cache.rb +++ b/lib/active_model/serializer/adapter/json_api/fragment_cache.rb @@ -1,6 +1,6 @@ module ActiveModel class Serializer - class Adapter + module Adapter class JsonApi class FragmentCache def fragment_cache(root, cached_hash, non_cached_hash) diff --git a/lib/active_model/serializer/adapter/json_api/pagination_links.rb b/lib/active_model/serializer/adapter/json_api/pagination_links.rb index 55e3280b..368d4795 100644 --- a/lib/active_model/serializer/adapter/json_api/pagination_links.rb +++ b/lib/active_model/serializer/adapter/json_api/pagination_links.rb @@ -1,7 +1,7 @@ module ActiveModel class Serializer - class Adapter - class JsonApi < Adapter + module Adapter + class JsonApi < Base class PaginationLinks FIRST_PAGE = 1 diff --git a/lib/active_model/serializer/adapter/null.rb b/lib/active_model/serializer/adapter/null.rb index 1728f88e..f398380f 100644 --- a/lib/active_model/serializer/adapter/null.rb +++ b/lib/active_model/serializer/adapter/null.rb @@ -1,7 +1,7 @@ module ActiveModel class Serializer - class Adapter - class Null < Adapter + module Adapter + class Null < Base def serializable_hash(options = nil) {} end diff --git a/test/adapter/fragment_cache_test.rb b/test/adapter/fragment_cache_test.rb index 6442156d..fc6c3feb 100644 --- a/test/adapter/fragment_cache_test.rb +++ b/test/adapter/fragment_cache_test.rb @@ -1,7 +1,7 @@ require 'test_helper' module ActiveModel class Serializer - class Adapter + module Adapter class FragmentCacheTest < Minitest::Test def setup @spam = Spam::UnrelatedLink.new(id: 'spam-id-1') diff --git a/test/adapter/json/belongs_to_test.rb b/test/adapter/json/belongs_to_test.rb index 217f920c..9f3fa4fb 100644 --- a/test/adapter/json/belongs_to_test.rb +++ b/test/adapter/json/belongs_to_test.rb @@ -2,7 +2,7 @@ require 'test_helper' module ActiveModel class Serializer - class Adapter + module Adapter class Json class BelongsToTest < Minitest::Test def setup diff --git a/test/adapter/json/collection_test.rb b/test/adapter/json/collection_test.rb index 8ebc0aa8..f627dd84 100644 --- a/test/adapter/json/collection_test.rb +++ b/test/adapter/json/collection_test.rb @@ -2,7 +2,7 @@ require 'test_helper' module ActiveModel class Serializer - class Adapter + module Adapter class Json class Collection < Minitest::Test def setup diff --git a/test/adapter/json/has_many_test.rb b/test/adapter/json/has_many_test.rb index 2a0a96c6..34d69048 100644 --- a/test/adapter/json/has_many_test.rb +++ b/test/adapter/json/has_many_test.rb @@ -2,7 +2,7 @@ require 'test_helper' module ActiveModel class Serializer - class Adapter + module Adapter class Json class HasManyTestTest < Minitest::Test def setup diff --git a/test/adapter/json_api/belongs_to_test.rb b/test/adapter/json_api/belongs_to_test.rb index 5bfdc52b..acf98f4f 100644 --- a/test/adapter/json_api/belongs_to_test.rb +++ b/test/adapter/json_api/belongs_to_test.rb @@ -2,7 +2,7 @@ require 'test_helper' module ActiveModel class Serializer - class Adapter + module Adapter class JsonApi class BelongsToTest < Minitest::Test def setup diff --git a/test/adapter/json_api/collection_test.rb b/test/adapter/json_api/collection_test.rb index c17c8aad..7f42719e 100644 --- a/test/adapter/json_api/collection_test.rb +++ b/test/adapter/json_api/collection_test.rb @@ -2,7 +2,7 @@ require 'test_helper' module ActiveModel class Serializer - class Adapter + module Adapter class JsonApi class CollectionTest < Minitest::Test def setup diff --git a/test/adapter/json_api/has_many_embed_ids_test.rb b/test/adapter/json_api/has_many_embed_ids_test.rb index 15243c7a..d00c906b 100644 --- a/test/adapter/json_api/has_many_embed_ids_test.rb +++ b/test/adapter/json_api/has_many_embed_ids_test.rb @@ -2,7 +2,7 @@ require 'test_helper' module ActiveModel class Serializer - class Adapter + module Adapter class JsonApi class HasManyEmbedIdsTest < Minitest::Test def setup diff --git a/test/adapter/json_api/has_many_explicit_serializer_test.rb b/test/adapter/json_api/has_many_explicit_serializer_test.rb index 5c53fa01..9872665c 100644 --- a/test/adapter/json_api/has_many_explicit_serializer_test.rb +++ b/test/adapter/json_api/has_many_explicit_serializer_test.rb @@ -2,7 +2,7 @@ require 'test_helper' module ActiveModel class Serializer - class Adapter + module Adapter class JsonApi # Test 'has_many :assocs, serializer: AssocXSerializer' class HasManyExplicitSerializerTest < Minitest::Test diff --git a/test/adapter/json_api/has_many_test.rb b/test/adapter/json_api/has_many_test.rb index 699126c2..07453681 100644 --- a/test/adapter/json_api/has_many_test.rb +++ b/test/adapter/json_api/has_many_test.rb @@ -2,7 +2,7 @@ require 'test_helper' module ActiveModel class Serializer - class Adapter + module Adapter class JsonApi class HasManyTest < Minitest::Test def setup diff --git a/test/adapter/json_api/has_one_test.rb b/test/adapter/json_api/has_one_test.rb index 29582ddf..42f319b0 100644 --- a/test/adapter/json_api/has_one_test.rb +++ b/test/adapter/json_api/has_one_test.rb @@ -2,7 +2,7 @@ require 'test_helper' module ActiveModel class Serializer - class Adapter + module Adapter class JsonApi class HasOneTest < Minitest::Test def setup diff --git a/test/adapter/json_api/json_api_test.rb b/test/adapter/json_api/json_api_test.rb index 16d1f93d..6aef2021 100644 --- a/test/adapter/json_api/json_api_test.rb +++ b/test/adapter/json_api/json_api_test.rb @@ -2,7 +2,7 @@ require 'test_helper' module ActiveModel class Serializer - class Adapter + module Adapter class JsonApiTest < Minitest::Test def setup ActionController::Base.cache_store.clear diff --git a/test/adapter/json_api/linked_test.rb b/test/adapter/json_api/linked_test.rb index 7b4b43f1..32b835b4 100644 --- a/test/adapter/json_api/linked_test.rb +++ b/test/adapter/json_api/linked_test.rb @@ -1,7 +1,7 @@ require 'test_helper' module ActiveModel class Serializer - class Adapter + module Adapter class JsonApi class LinkedTest < Minitest::Test def setup diff --git a/test/adapter/json_api/pagination_links_test.rb b/test/adapter/json_api/pagination_links_test.rb index 52fdfd7b..d9fd2bec 100644 --- a/test/adapter/json_api/pagination_links_test.rb +++ b/test/adapter/json_api/pagination_links_test.rb @@ -6,7 +6,7 @@ require 'kaminari/hooks' module ActiveModel class Serializer - class Adapter + module Adapter class JsonApi class PaginationLinksTest < Minitest::Test URI = 'http://example.com' diff --git a/test/adapter/json_api/resource_type_config_test.rb b/test/adapter/json_api/resource_type_config_test.rb index 1f2f534d..859ea7a7 100644 --- a/test/adapter/json_api/resource_type_config_test.rb +++ b/test/adapter/json_api/resource_type_config_test.rb @@ -2,7 +2,7 @@ require 'test_helper' module ActiveModel class Serializer - class Adapter + module Adapter class JsonApi class ResourceTypeConfigTest < Minitest::Test def setup diff --git a/test/adapter/json_test.rb b/test/adapter/json_test.rb index dac6b140..51dcb057 100644 --- a/test/adapter/json_test.rb +++ b/test/adapter/json_test.rb @@ -2,7 +2,7 @@ require 'test_helper' module ActiveModel class Serializer - class Adapter + module Adapter class JsonTest < Minitest::Test def setup ActionController::Base.cache_store.clear diff --git a/test/adapter/null_test.rb b/test/adapter/null_test.rb index 9f23b778..fbfaeb6c 100644 --- a/test/adapter/null_test.rb +++ b/test/adapter/null_test.rb @@ -2,7 +2,7 @@ require 'test_helper' module ActiveModel class Serializer - class Adapter + module Adapter class NullTest < Minitest::Test def setup profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }) diff --git a/test/adapter_test.rb b/test/adapter_test.rb index 8296fb34..b9259a8a 100644 --- a/test/adapter_test.rb +++ b/test/adapter_test.rb @@ -6,7 +6,7 @@ module ActiveModel def setup profile = Profile.new @serializer = ProfileSerializer.new(profile) - @adapter = ActiveModel::Serializer::Adapter.new(@serializer) + @adapter = ActiveModel::Serializer::Adapter::Base.new(@serializer) end def test_serializable_hash_is_abstract_method diff --git a/test/serializers/adapter_for_test.rb b/test/serializers/adapter_for_test.rb index 63f2e01e..ecb83777 100644 --- a/test/serializers/adapter_for_test.rb +++ b/test/serializers/adapter_for_test.rb @@ -127,7 +127,7 @@ module ActiveModel def test_inherited_adapter_hooks_register_adapter Object.const_set(:MyAdapter, Class.new) my_adapter = MyAdapter - ActiveModel::Serializer::Adapter.inherited(my_adapter) + ActiveModel::Serializer::Adapter::Base.inherited(my_adapter) assert_equal ActiveModel::Serializer::Adapter.lookup(:my_adapter), my_adapter ensure ActiveModel::Serializer::Adapter.adapter_map.delete('my_adapter'.freeze) @@ -138,7 +138,7 @@ module ActiveModel Object.const_set(:MyNamespace, Module.new) MyNamespace.const_set(:MyAdapter, Class.new) my_adapter = MyNamespace::MyAdapter - ActiveModel::Serializer::Adapter.inherited(my_adapter) + ActiveModel::Serializer::Adapter::Base.inherited(my_adapter) assert_equal ActiveModel::Serializer::Adapter.lookup(:'my_namespace/my_adapter'), my_adapter ensure ActiveModel::Serializer::Adapter.adapter_map.delete('my_namespace/my_adapter'.freeze) @@ -151,8 +151,8 @@ module ActiveModel my_adapter = MyAdapter Object.const_set(:MySubclassedAdapter, Class.new(MyAdapter)) my_subclassed_adapter = MySubclassedAdapter - ActiveModel::Serializer::Adapter.inherited(my_adapter) - ActiveModel::Serializer::Adapter.inherited(my_subclassed_adapter) + ActiveModel::Serializer::Adapter::Base.inherited(my_adapter) + ActiveModel::Serializer::Adapter::Base.inherited(my_subclassed_adapter) assert_equal ActiveModel::Serializer::Adapter.lookup(:my_adapter), my_adapter assert_equal ActiveModel::Serializer::Adapter.lookup(:my_subclassed_adapter), my_subclassed_adapter ensure