Class: Ure

Inherits:
BasicObject
Includes:
Enumerable
Defined in:
lib/ure.rb,
lib/ure/version.rb

Overview

Immutable alternative to Struct that requires keyword arguments

Constant Summary collapse

VERSION =
"0.1.4"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(fields = {}) ⇒ Ure

Returns a new instance of Ure.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/ure.rb', line 50

def initialize(fields = {})
  ::Kernel.fail ::ArgumentError, "'fields' must be a 'Hash'" unless fields.is_a?(::Hash)

  members.freeze

  members.each do |member|
    ::Kernel.fail ::ArgumentError, "missing keyword: #{member}" unless fields.include?(member)
  end

  unless (extra = fields.keys - members).empty?  
    ::Kernel.fail ::ArgumentError, "unknown keyword#{'s' if extra.size > 1}: #{extra.join(', ')}"
  end

  @fields = fields.freeze
end

Instance Attribute Details

#fieldsObject (readonly)

Returns the value of attribute fields.



66
67
68
# File 'lib/ure.rb', line 66

def fields
  @fields
end

Class Method Details

.membersObject

Returns the ure members as an array of symbols.



10
11
12
# File 'lib/ure.rb', line 10

def self.members
  @members.freeze
end

.new(*members, &body) ⇒ Object

Create an ure named by its constant.



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/ure.rb', line 16

def self.new(*members, &body)
  ::Class.new(self) do
    instance_variable_set(:@members, members)

    def self.new(*args, &block)
      object = allocate
      object.__send__(:initialize, *args, &block) if respond_to?(:initialize, true)
      object
    end 

    define_method(:members) do
      @members ||= members
    end

    members.each do |member|
      define_method member.to_sym do
        fields[member.to_sym]
      end

      define_method :"#{member}=" do |_|
        ::Kernel.fail "can't modify frozen #{self}"
      end
    end

    parent_class = self

    define_method(:class) do
      parent_class
    end

    class_eval(&body) if body
  end
end

Instance Method Details

#==(arg) ⇒ Object

Equality—Returns true if other has the same ure subclass and has equal member values.



70
71
72
73
74
75
76
77
78
# File 'lib/ure.rb', line 70

def ==(arg)
  if self.class == arg.class
    fields == arg.fields
  else
    false
  end
rescue ::NoMethodError
  false
end

#[](key) ⇒ Object

Because Ure doesn’t care about indexing, this allows users to treat instances of Ure as a hash.



82
83
84
# File 'lib/ure.rb', line 82

def [](key)
  fields[key]
end

#each(&block) ⇒ Object

Converts the fields into a hash and calls each on them.



88
89
90
# File 'lib/ure.rb', line 88

def each(&block)
  to_h.each(&block)
end

#inspectObject

Returns a string describing the object and its fields



100
101
102
# File 'lib/ure.rb', line 100

def inspect
  "#<#{::Ure} #{self.class} #{fields.to_s}"
end

#to_aObject

Alias for #values



106
107
108
# File 'lib/ure.rb', line 106

def to_a
  fields.values
end

#to_hObject

Alias for #fields



112
113
114
# File 'lib/ure.rb', line 112

def to_h
  fields.to_h
end

#to_jsonObject

Returns a JSON string of members and values.



130
131
132
# File 'lib/ure.rb', line 130

def to_json
  fields.to_json
end

#to_sObject

Returns a string describing the object and its fields



94
95
96
# File 'lib/ure.rb', line 94

def to_s
  "#<#{::Ure} #{self.class} #{fields.to_s}"
end

#valuesObject

Returns an array of the values in the fields



118
119
120
# File 'lib/ure.rb', line 118

def values
  fields.values
end

#values_at(name, *args) ⇒ Object

Takes one or more keys as arguments, and returns an array of the corresponding values.



124
125
126
# File 'lib/ure.rb', line 124

def values_at(name, *args)
  [fields[name]] + args.map { |arg| fields[arg] }
end