File: base.rb

package info (click to toggle)
ruby-enumerize 2.8.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 432 kB
  • sloc: ruby: 3,712; makefile: 6
file content (116 lines) | stat: -rw-r--r-- 3,033 bytes parent folder | download
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