# 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