Sha256: 14c1688019ca6173a9cdf2e2e41ca5fb75ac7ce57e4f96bcd5d20b0ba4ea55d7

Contents?: true

Size: 1.57 KB

Versions: 1

Compression:

Stored size: 1.57 KB

Contents

class KWAttr < Module
  VERSION = "0.4.0"

  def initialize
    @required = []
    @defaults = {}
  end

  def initializer(attrs, opts)
    required_attrs = @required
    defaults = @defaults
    required_attrs.concat(attrs).uniq!
    defaults.merge!(opts)
    iv_cache = Hash.new { |h, k| h[k] = :"@#{k}" }

    verbose, $VERBOSE = $VERBOSE, false
    define_method :initialize do |*args, **kwargs|
      required = required_attrs.dup

      defaults.merge(kwargs).each_pair do |key, value|
        next unless required.delete(key) || defaults.key?(key)
        kwargs.delete(key)
        instance_variable_set iv_cache[key], value
      end

      unless required.empty?
        method(:initialize).super_method.parameters.each do |type, name|
          required << name if type == :keyreq && !kwargs.key?(name)
        end
        raise ArgumentError,
          "missing keyword#{'s' if required.size > 1}: #{required.join(', ')}"
      end
      unless kwargs.empty?
        arity = method(:initialize).super_method.arity
        if arity != -1 && arity == args.size
          raise ArgumentError,
            "unknown keyword#{'s' if kwargs.size > 1}: #{kwargs.keys.join(', ')}"
        end
        args << kwargs
      end

      super(*args)
    end
    $VERBOSE = verbose
  end

  def inspect
    "<KWAttr:#{'%#016x'%(object_id<<1)} @required=#{@required.inspect}, @defaults=#{@defaults.inspect}>"
  end
end

class Module
  def kwattr(*attrs, **opts)
    names = [*attrs, *opts.keys]
    attr_reader(*names)
    prepend @kwattrs ||= KWAttr.new
    @kwattrs.initializer(attrs, opts)
    names
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
kwattr-0.4.0 lib/kwattr.rb