zeisler/active_mocker

View on GitHub
lib/active_mocker/attribute_types/enum.rb

Summary

Maintainability
A
35 mins
Test Coverage
# frozen_string_literal: true
require "virtus"

module ActiveMocker
  module AttributeTypes
    class Enum < Virtus::Attribute
      class << self
        def build(db_value_type:, table_name:, attribute:, enums:, ignore_value: false)
          klass               = Class.new(ActiveMocker::AttributeTypes::Enum)
          klass.table_name    = table_name.to_sym
          klass.attribute     = attribute.to_sym
          klass.ignore_value  = ignore_value
          enums               = if enums.is_a?(Array)
                                  enums.each_with_object({}).with_index { |(k, h), i| h[k] = i }
                                else
                                  enums
                                end
          klass.key_type      = String
          klass.db_value_type = db_value_type
          klass.enums         = Hash[enums.map do |k, v|
            [Virtus::Attribute.build(klass.key_type).coerce(k),
             Virtus::Attribute.build(klass.db_value_type).coerce(v)]
          end]
          klass
        end

        def to_s
          "ActiveMocker::AttributeTypes::Enum.build(ignore_value: #{ignore_value}, db_value_type: #{db_value_type}, table_name: :#{table_name}, attribute: :#{attribute}, enums: #{enums.inspect})"
        end

        attr_accessor :enums, :table_name, :attribute, :db_value_type, :key_type, :ignore_value
      end

      def coerce(key)
        return if key.nil?
        coerced_key = key_type.coerce(key)
        if key && self.class.enums.key?(coerced_key)
          if self.class.ignore_value
            coerced_key
          else
            get_value(key)
          end
        else
          raise ArgumentError, "'#{coerced_key}' is not a valid #{self.class.attribute}"
        end
      end

      def get_key(value)
        self.class.enums.invert[db_value_type.coerce(value)]
      end

      def get_value(key)
        self.class.enums[key_type.coerce(key)]
      end

      def key_type
        Virtus::Attribute.build(self.class.key_type)
      end

      def db_value_type
        Virtus::Attribute.build(self.class.db_value_type)
      end
    end
  end
end