Sha256: ec6a9b50b09332b82679aab1465a0bd45dc0d1fb43150c0ae1faed7ee91dada1

Contents?: true

Size: 1.58 KB

Versions: 2

Compression:

Stored size: 1.58 KB

Contents

# frozen_string_literal: true

module Structure
  module ClassMethods
    attr_reader :attribute_names

    def self.extended(base)
      base.instance_variable_set :@attribute_names, []
    end

    def attribute(name, &block)
      name = name.to_s

      if name.chomp!('?')
        module_eval <<-CODE, __FILE__, __LINE__ + 1
          def #{name}?
            #{name}
          end
        CODE
      end

      module_eval <<-CODE, __FILE__, __LINE__ + 1
        def #{name}
          @__mutex__.synchronize {
            return @#{name} if defined?(@#{name})

            @#{name} = __#{name}__
            @#{name}.freeze unless @#{name}.is_a?(Structure)

            @#{name}
          }
        end
      CODE

      define_method "__#{name}__", block
      private "__#{name}__"

      @attribute_names << name

      name.to_sym
    end

    def __overwrite_initialize__
      class_eval do
        unless method_defined?(:__custom_initialize__)
          define_method :__custom_initialize__ do |*args|
            @__mutex__ = ::Thread::Mutex.new
            __original_initialize__(*args)
          end
        end

        return if instance_method(:initialize) ==
                  instance_method(:__custom_initialize__)

        alias_method :__original_initialize__, :initialize
        alias_method :initialize, :__custom_initialize__
      end
    end

    private

    def method_added(name)
      return if name != :initialize

      __overwrite_initialize__
    end

    def inherited(subclass)
      subclass.instance_variable_set :@attribute_names, @attribute_names.dup
    end
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
structure-1.1.1 lib/structure/class_methods.rb
structure-1.1.0 lib/structure/class_methods.rb