1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
# frozen_string_literal: true
module Enumerize
module Base
def self.included(base)
base.extend ClassMethods
base.singleton_class.prepend ClassMethods::Hook
if base.respond_to?(:validate)
base.validate :_validate_enumerized_attributes
end
end
module ClassMethods
def enumerize(name, options={})
attr = Attribute.new(self, name, options)
enumerized_attributes << attr
unless methods.include?(attr.name)
_enumerize_module._class_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{attr.name}
enumerized_attributes[:#{attr.name}]
end
RUBY
end
attr.define_methods!(_enumerize_module)
end
def enumerized_attributes
@enumerized_attributes ||= AttributeMap.new
end
module Hook
def inherited(subclass)
enumerized_attributes.add_dependant subclass.enumerized_attributes
super subclass
end
end
private
def _enumerize_module
@_enumerize_module ||= begin
mod = Module.new
include mod
mod
end
end
end
def initialize(...)
super
_set_default_value_for_enumerized_attributes
end
def read_attribute_for_validation(key)
key = key.to_s
if _enumerized_values_for_validation.has_key?(key)
_enumerized_values_for_validation[key]
elsif defined?(super)
super
else
send(key)
end
end
private
def _enumerized_values_for_validation
@_enumerized_values_for_validation ||= {}
end
def _validate_enumerized_attributes
self.class.enumerized_attributes.each do |attr|
skip_validations = Utils.call_if_callable(attr.skip_validations_value, self)
next if skip_validations
value = read_attribute_for_validation(attr.name)
next if value.blank?
if attr.kind_of? Multiple
errors.add attr.name unless value.respond_to?(:all?) && value.all? { |v| v.blank? || attr.find_value(v) }
else
errors.add attr.name, :inclusion unless attr.find_value(value)
end
end
end
def _set_default_value_for_enumerized_attributes
self.class.enumerized_attributes.each do |attr|
_set_default_value_for_enumerized_attribute(attr)
end
end
def _set_default_value_for_enumerized_attribute(attr)
return if attr.default_value.nil?
begin
if respond_to?(attr.name)
attr_value = public_send(attr.name)
else
return
end
value_for_validation = _enumerized_values_for_validation[attr.name.to_s]
if (!attr_value || attr_value.empty?) && (!value_for_validation || value_for_validation.empty?)
value = Utils.call_if_callable(attr.default_value, self)
public_send("#{attr.name}=", value)
end
rescue ActiveModel::MissingAttributeError
end
end
end
end
|