Sha256: 3b389fd4ebab28cda6b794002c316d36a7292c2dfc9eae34cca459444ae1b7fd

Contents?: true

Size: 1.67 KB

Versions: 1

Compression:

Stored size: 1.67 KB

Contents

module InheritedClassVar
  class Variable
    attr_reader :name, :klass, :options

    def initialize(name, klass, options={})
      @name = name
      @klass = klass
      @options = options
    end

    def object_method_name
      self.class.object_method_name(name)
    end

    def default_value
      raise NotImplementedError
    end

    def raw_value
      @raw_value ||= default_value
    end

    def value
      @value ||= klass.inherited_ancestors
        .map { |ancestor| ancestor.try(object_method_name).try(:raw_value) }
        .compact
        .reverse
        .reduce(default_value, &method(:reduce))
    end

    def change(other_value)
      notify_change
      _change(raw_value, other_value)
    end

    def _change(value1, value2)
      raise NotImplementedError
    end
    def reduce(*args); _change(*args) end

    def notify_change
      ([klass] + klass.descendants).each do |descendant|
        descendant.try(object_method_name).try(:clear_memoized_value)
      end
    end

    def clear_memoized_value
      @value = nil if @value
    end

    class << self
      def object_method_name(name)
        :"#{name}_object"
      end

      def define_methods(name, klass, options={})
        variable_class = self
        object_method_name = object_method_name(name)

        klass.send :define_singleton_method, object_method_name do
          instance_variable_name = :"@#{object_method_name}"
          instance_variable_get(instance_variable_name) || instance_variable_set(instance_variable_name, variable_class.new(name, self, options))
        end
        klass.send(:define_singleton_method, name) { public_send(object_method_name).value }
      end
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
inherited_class_var-1.0.0.beta1 lib/inherited_class_var/variable.rb