Sha256: 3da03185a54fc7634d0fa4bf2e717a7b1b2859c360f21323bb268bbaca0eabc5

Contents?: true

Size: 1.81 KB

Versions: 1

Compression:

Stored size: 1.81 KB

Contents

# frozen_string_literal: true

module Structure
  module ClassMethods
    # Returns an array of attribute names as strings
    attr_reader :attribute_names

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

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

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

      module_eval <<-CODE, __FILE__, __LINE__ + 1
        def #{name}
          @__mutex.synchronize {
            break if @__table.key?("#{name}")

            @__table["#{name}"] = __#{name}
            @__table["#{name}"].freeze

            @__table["#{name}"]
          }

          @__table["#{name}"]
        end
      CODE

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

      @attribute_names << name

      name.to_sym
    end

    private

    def __overwrite_initialize
      class_eval do
        unless method_defined?(:__custom_initialize)
          define_method :__custom_initialize do |*arguments, &block|
            @__mutex = ::Thread::Mutex.new
            @__table = {}
            __original_initialize(*arguments, &block)
            freeze
          end
        end

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

        alias_method :__original_initialize, :initialize
        alias_method :initialize, :__custom_initialize
        private :__custom_initialize, :__original_initialize
      end
    end

    def method_added(name)
      __overwrite_initialize if name == :initialize
    end

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

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
structure-1.2.0 lib/structure/class_methods.rb