magoosh/motion_record

View on GitHub
lib/motion_record/serialization.rb

Summary

Maintainability
A
0 mins
Test Coverage
module MotionRecord
  module Serialization
    module ClassMethods
      # Register a new attribute serializer
      #
      # attribute               - Symbol name of the attribute
      # serializer_class_or_sym - One of :time, :boolean, :json, :date or a custom
      #                           subclass of Serialization::BaseSerializer
      def serialize(attribute, serializer_class_or_sym)
        if serializer_class_or_sym.is_a?(Symbol)
          self.serializer_classes[attribute] = case serializer_class_or_sym
          when :time
            Serialization::TimeSerializer
          when :date
            Serialization::DateSerializer
          when :boolean
            Serialization::BooleanSerializer
          when :json
            Serialization::JSONSerializer
          else
            raise "Unknown serializer #{serializer_class_or_sym.inspect}"
          end
        else
          self.serializer_classes[attribute] = serializer_class_or_sym
        end
      end

      # Deserialize a Hash of attributes from their database representation
      #
      # params - a Hash of Symbol column names to SQLite values
      #
      # Returns a Hash with all values replaced by their deserialized versions
      def deserialize_table_params(params)
        params.each_with_object({}) do |name_and_value, attributes|
          name, value = name_and_value
          attributes[name.to_sym] = serializer(name.to_sym).deserialize(value)
        end
      end

      # Serialize a Hash of attributes to their database representation
      #
      # params - a Hash of Symbol column names to their attribute values
      #
      # Returns a Hash with all values replaced by their serialized versions
      def serialize_table_params(hash)
        hash.each_with_object({}) do |attribute_and_value, params|
          attribute, value = attribute_and_value
          params[attribute] = serializer(attribute).serialize(value)
        end
      end

      protected

      # Internal: Get the serializer object for an attribute
      #
      # attribute - Symbol name of the attribute
      def serializer(attribute)
        @serializers ||= {}
        unless @serializers[attribute]
          @serializers[attribute] = build_serializer(attribute)
        end
        @serializers[attribute]
      end

      # Internal: Registry of serializer classes 
      def serializer_classes
        @serializer_classes ||= Hash.new(Serialization::DefaultSerializer)
      end

      def build_serializer(attribute)
        serializer_classes[attribute].new(table_columns[attribute])
      end
    end

    def self.included(base)
      base.extend(ClassMethods)
    end
  end
end