Sha256: 5acc4b859bd27d0197b0e3b3ec82f4e4bb993db2657b01021f461e683aee4031

Contents?: true

Size: 1.54 KB

Versions: 1

Compression:

Stored size: 1.54 KB

Contents

module KeyStruct

  def self.reader(*keys)
    define_key_struct(:attr_reader, keys)
  end

  def self.accessor(*keys)
    define_key_struct(:attr_accessor, keys)
  end

  instance_eval do
    alias :[] :accessor
  end

  private

  def self.define_key_struct(access, keys) 
    Class.new.class_eval do
      include Comparable
      keyvalues = Hash[*keys.map{|key| (Hash === key) ? key.to_a : [key, nil]}.flatten(2)]
      keys = keyvalues.keys
      send access, *keys
      define_method(:initialize) do |args={}|
        args = keyvalues.merge(args)
        keys.each do |key|
          instance_variable_set("@#{key}".to_sym, args.delete(key))
        end
        raise ArgumentError, "Invalid argument(s): #{args.keys.map(&:inspect).join(' ')}; KeyStruct accepts #{keys.map(&:inspect).join(' ')}" if args.any?
      end
      define_method(:==) do |other|
        keys.all?{|key| other.respond_to?(key) and self.send(key) == other.send(key)}
      end
      define_method(:<=>) do |other|
        keys.each do |key|
          cmp = (self.send(key) <=> other.send(key))
          return cmp unless cmp == 0
        end
        0
      end
      define_method(:to_hash) do
        Hash[*keys.map{ |key| [key, self.send(key)]}.flatten(2)]
      end
      define_method(:to_s) do
        "[#{self.class.name} #{keys.map{|key| "#{key}:#{self.send(key)}"}.join(' ')}]"
      end
      define_method(:inspect) do
        "<#{self.class.name}:0x#{self.object_id.to_s(16)} #{keys.map{|key| "#{key}:#{self.send(key).inspect}"}.join(' ')}>"
      end
      self
    end
  end

end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
key_struct-0.3.0 lib/key_struct/key_struct.rb