Skip to content

Instantly share code, notes, and snippets.

@jasonayre
Created January 7, 2016 21:52
Show Gist options
  • Save jasonayre/5e344c50a01d06feaa46 to your computer and use it in GitHub Desktop.
Save jasonayre/5e344c50a01d06feaa46 to your computer and use it in GitHub Desktop.
serializer
module Serializer
module Sti
extend ::ActiveSupport::Concern
included do
class_attribute(:serializer_for_type_map, {})
class_attribute(:_resolve_serializer_for_type_block)
class << self
alias :__new__ :new
end
def self.new(object, options={})
type_specific_serializer = type_specific_serializer_for(object)
if type_specific_serializer
type_specific_serializer.new(object, options)
else
super(object, options)
end
end
end
module ClassMethods
def inherited(subclass)
super(subclass)
class << subclass
alias :new :__new__
end
end
def look_for_type_specific_serializer?(object)
object.class.inheritance_column && object[object.class.inheritance_column.to_sym]
end
def try_mapping_type?(type_name)
self._resolve_serializer_for_type_block || serializer_for_type_map.key?(type_name) || serializer_for_type_map.key?(type_name.safe_constantize)
end
def resolve_serializer_for_type_with(&block)
self._resolve_serializer_for_type_block = block
end
def type_specific_serializer_for(object)
return nil unless look_for_type_specific_serializer?(object)
type_name = object[object.class.inheritance_column]
if try_mapping_type?(type_name)
result = if self._resolve_serializer_for_type_block
self._resolve_serializer_for_type_block.call(type_name)
else
self.serializer_for_type_map.fetch(type_name) {
self.serializer_for_type_map.fetch(type_name.safe_constantize)
}
end
else
nil
end
end
end
end
end
class WidgetSerializer < ::BaseSerializer
include ::Serializer::Sti
def json_key
'widget'
end
resolve_serializer_for_type_with do |type_name|
"#{type_name.demodulize}Serializer".safe_constantize
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment