lib/active_model/serializer/adapter.rb in cheap_ams-0.10.8 vs lib/active_model/serializer/adapter.rb in cheap_ams-0.10.10

- old
+ new

@@ -1,23 +1,84 @@ module ActiveModel class Serializer class Adapter + UnknownAdapterError = Class.new(ArgumentError) + ADAPTER_MAP = {} + private_constant :ADAPTER_MAP if defined?(private_constant) extend ActiveSupport::Autoload - require 'active_model/serializer/adapter/json' - require 'active_model/serializer/adapter/json_api' - autoload :FlattenJson - autoload :Null autoload :FragmentCache + autoload :Json + autoload :JsonApi + autoload :Null + autoload :FlattenJson def self.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 self.adapter_class(adapter) - adapter_name = adapter.to_s.classify.sub('API', 'Api') - "ActiveModel::Serializer::Adapter::#{adapter_name}".safe_constantize + 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<adapter_name, adapter_class> + def adapter_map + ADAPTER_MAP + end + + # @return [Array<Symbol>] list of adapter names + def adapters + adapter_map.keys.sort + end + + # Adds an adapter 'klass' with 'name' to the 'adapter_map' + # Names are stringified and underscored + # @param [Symbol, String] name of the registered adapter + # @param [Class] klass - adapter class itself + # @example + # AMS::Adapter.register(:my_adapter, MyAdapter) + def register(name, klass) + adapter_map.update(name.to_s.underscore => klass) + self + end + + # @param adapter [String, Symbol, Class] name to fetch adapter by + # @return [ActiveModel::Serializer::Adapter] subclass of Adapter + # @raise [UnknownAdapterError] + def lookup(adapter) + # 1. return if is a class + return adapter if adapter.is_a?(Class) + adapter_name = adapter.to_s.underscore + # 2. return if registered + adapter_map.fetch(adapter_name) { + # 3. try to find adapter class from environment + adapter_class = find_by_name(adapter_name) + register(adapter_name, adapter_class) + adapter_class + } + rescue NameError, ArgumentError => e + failure_message = + "NameError: #{e.message}. Unknown adapter: #{adapter.inspect}. Valid adapters are: #{adapters}" + raise UnknownAdapterError, failure_message, e.backtrace + end + + # @api private + def find_by_name(adapter_name) + adapter_name = adapter_name.to_s.classify.tr('API', 'Api') + ActiveModel::Serializer::Adapter.const_get(adapter_name.to_sym) or # rubocop:disable Style/AndOr + fail UnknownAdapterError + end + private :find_by_name + end + + # Automatically register adapters when subclassing + def self.inherited(subclass) + ActiveModel::Serializer::Adapter.register(subclass.to_s.demodulize, subclass) end attr_reader :serializer def initialize(serializer, options = {})