Class: Tap::Support::Assignments

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/tap/support/assignments.rb

Overview

Assignments defines an array of [key, values] pairs that tracks which values are assigned to a particular key. A value may only be assigned to one key at a time.

Assignments tracks the order of key declaration, and the order in which values are assigned to a key. This behavior is used by ClassConfiguration to track the order of configurations

in a class; the order, in turn, is used in the formation of config files, command line documentation, etc.

a = Assignments.new
a.assign(:one, 'one')
a.assign(:two, 'two')
a.assign(:one, 'ONE')
a.to_a          # => [[:one, ['one', 'ONE']], [:two, ['two']]]

b = Assignments.new(a)
b.to_a          # => [[:one, ['one', 'ONE']], [:two, ['two']]]

b.unassign('one')
b.assign(:one, 1)
b.to_a          # => [[:one, ['ONE', 1]], [:two, ['two']]]
a.to_a          # => [[:one, ['one', 'ONE']], [:two, ['two']]]

– TODO:

Assignments may be optimizable... check if an alternate internal 
storage can be made faster or to take up less memory.  Not that
that much can be gained period...

Instance Method Summary collapse

Constructor Details

#initialize(parent = nil) ⇒ Assignments

Generates a new Assignments using the parent array of

key, values

pairs. Uses parent.array if parent is

an Assignments, or [] if parent is nil.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/tap/support/assignments.rb', line 39

def initialize(parent=nil)
  existing_array = case parent
  when Assignments then parent.array
  when Array then parent
  when nil then []
  else 
    raise ArgumentError.new("cannot convert #{parent.class} to Assignments, Array, or nil")
  end
  
  @array = []
  existing_array.each do |key, values|
    assign(key, *values)
  end
end

Instance Method Details

#assign(key, *values) ⇒ Object

Assigns the specified values to the key. The key will be declared, if necessary. Raises an error if the key is nil.

Raises:

  • (ArgumentError)


81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/tap/support/assignments.rb', line 81

def assign(key, *values)
  raise ArgumentError.new("nil keys are not allowed") if key == nil
  
  # partition the input values into existing and new
  # values, then check for conflicts.
  current_values = self.values
  existing_values, new_values = values.partition {|value| current_values.include?(value) }
  
  conflicts = []
  existing_values.collect do |value|
    current_key = key_for(value)
    if current_key != key 
      conflicts << "#{value} (#{key}) already assigned to #{current_key}"
    end
  end
  
  unless conflicts.empty?
    raise ArgumentError.new(conflicts.join("\n"))
  end
  
  declare(key)
  values_for(key).concat new_values
end

#assigned?(value) ⇒ Boolean

Returns true if the value has been assigned to a key.

Returns:

  • (Boolean)


113
114
115
116
117
118
# File 'lib/tap/support/assignments.rb', line 113

def assigned?(value)
  array.each do |key, values|
    return true if values.include?(value)
  end
  false
end

#declarationsObject

Returns an array of all the declared keys



74
75
76
# File 'lib/tap/support/assignments.rb', line 74

def declarations
  array.collect {|key, values| key }
end

#declare(key) ⇒ Object

Adds the key to the declarations.



55
56
57
# File 'lib/tap/support/assignments.rb', line 55

def declare(key)
  array << [key, []] unless declared?(key)
end

#declared?(key) ⇒ Boolean

Returns true if the key is declared.

Returns:

  • (Boolean)


66
67
68
69
70
71
# File 'lib/tap/support/assignments.rb', line 66

def declared?(key)
  array.each do |k, values|
    return true if k == key
  end
  false
end

#eachObject

Yields each [key, value] pair in the order in which the keys were declared. Keys with no values are skipped.



146
147
148
149
150
# File 'lib/tap/support/assignments.rb', line 146

def each
  array.each do |key, values|
    values.each {|value| yield(key, value) }
  end
end

#each_pairObject

Yields each [key, values] pair in the order in which the keys were declared.



154
155
156
157
158
# File 'lib/tap/support/assignments.rb', line 154

def each_pair
  array.each do |key, values|
    yield(key, values)
  end
end

#key_for(value) ⇒ Object

Returns the key for the specified value, or nil if the value is unassigned.



127
128
129
130
131
132
# File 'lib/tap/support/assignments.rb', line 127

def key_for(value)
  array.each do |key, values| 
    return key if values.include?(value)
  end
  nil
end

#to_aObject

Returns self as an array



161
162
163
# File 'lib/tap/support/assignments.rb', line 161

def to_a
  array.collect {|key, values| [key, values.dup] }
end

#unassign(value) ⇒ Object

Removes the specified value.



106
107
108
109
110
# File 'lib/tap/support/assignments.rb', line 106

def unassign(value)
  array.each do |key, values| 
    values.delete(value)
  end
end

#undeclare(key) ⇒ Object

Removes all values for the specified key and removes the key from declarations.



61
62
63
# File 'lib/tap/support/assignments.rb', line 61

def undeclare(key)
  array.delete_if {|k, values| k == key}
end

#valuesObject

Returns the ordered values as an array



121
122
123
# File 'lib/tap/support/assignments.rb', line 121

def values
  array.collect {|key, values| values}.flatten
end

#values_for(key) ⇒ Object

Returns the values for the specified key, or nil if the key cannot be found.



136
137
138
139
140
141
# File 'lib/tap/support/assignments.rb', line 136

def values_for(key)
  array.each do |k, values| 
    return values if k == key
  end
  nil
end