Class: OrderedHash

Inherits:
Hash
  • Object
show all
Defined in:
/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb

Overview

This class was copied from an old version of ActiveSupport.

Class Method Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (OrderedHash) initialize(*args)

In MRI the Hash class is core and written in C. In particular, methods are programmed with explicit C function calls and polymorphism is not honored.

For example, []= is crucial in this implementation to maintain the @keys array but hash.c invokes rb_hash_aset() originally. This prevents method reuse through inheritance and forces us to reimplement stuff.

For instance, we cannot use the inherited #merge! because albeit the algorithm itself would work, our []= is not being called at all by the C code.



34
35
36
37
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 34

def initialize(*args)
  super
  @keys = []
end

Class Method Details

+ [](*args)



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 39

def self.[](*args)
  ordered_hash = new

  if args.length == 1 && args.first.is_a?(Array)
    args.first.each do |key_value_pair|
      next unless key_value_pair.is_a?(Array)
      ordered_hash[key_value_pair[0]] = key_value_pair[1]
    end

    return ordered_hash
  end

  unless args.size.even?
    raise ArgumentError.new("odd number of arguments for Hash")
  end

  args.each_with_index do |val, ind|
    next if ind.odd?
    ordered_hash[val] = args[ind + 1]
  end

  ordered_hash
end

Instance Method Details

- []=(key, value)



69
70
71
72
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 69

def []=(key, value)
  @keys << key unless has_key?(key)
  super
end

- clear



140
141
142
143
144
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 140

def clear
  super
  @keys.clear
  self
end

- delete(key)



74
75
76
77
78
79
80
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 74

def delete(key)
  if has_key? key
    index = @keys.index(key)
    @keys.delete_at index
  end
  super
end

- delete_if



82
83
84
85
86
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 82

def delete_if
  super
  sync_keys!
  self
end

- each



126
127
128
129
130
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 126

def each
  return to_enum(:each) unless block_given?
  @keys.each {|key| yield [key, self[key]]}
  self
end

- each_key



114
115
116
117
118
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 114

def each_key
  return to_enum(:each_key) unless block_given?
  @keys.each {|key| yield key}
  self
end

- each_pair



132
133
134
135
136
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 132

def each_pair
  return to_enum(:each_pair) unless block_given?
  @keys.each {|key| yield key, self[key]}
  self
end

- each_value



120
121
122
123
124
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 120

def each_value
  return to_enum(:each_value) unless block_given?
  @keys.each {|key| yield self[key]}
  self
end

- initialize_copy(other)



63
64
65
66
67
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 63

def initialize_copy(other)
  super
  # make a deep copy of keys
  @keys = other.keys
end

- inspect



183
184
185
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 183

def inspect
  "#<OrderedHash #{super}>"
end

- invert



179
180
181
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 179

def invert
  OrderedHash[to_a.map! {|key_value_pair| key_value_pair.reverse}]
end

- keys



98
99
100
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 98

def keys
  @keys.dup
end

- merge(other_hash)



163
164
165
166
167
168
169
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 163

def merge(other_hash)
  if block_given?
    dup.merge!(other_hash) {|k, v1, v2| yield k, v1, v2}
  else
    dup.merge!(other_hash)
  end
end

- merge!(other_hash) Also known as: update



152
153
154
155
156
157
158
159
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 152

def merge!(other_hash)
  if block_given?
    other_hash.each {|k, v| self[k] = key?(k) ? yield(k, self[k], v) : v}
  else
    other_hash.each {|k, v| self[k] = v}
  end
  self
end

- reject



94
95
96
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 94

def reject
  dup.reject! {|h, k| yield h, k}
end

- reject!



88
89
90
91
92
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 88

def reject!
  super
  sync_keys!
  self
end

- replace(other)

When replacing with another hash, the initial order of our keys must come from the other hash – ordered or not.



173
174
175
176
177
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 173

def replace(other)
  super
  @keys = other.keys
  self
end

- shift



146
147
148
149
150
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 146

def shift
  k = @keys.first
  v = delete(k)
  [k, v]
end

- to_a



110
111
112
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 110

def to_a
  @keys.map {|key| [key, self[key]]}
end

- to_hash



106
107
108
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 106

def to_hash
  self
end

- values



102
103
104
# File '/Users/ceppstei/Projects/sass-lang/.sass/lib/sass/util/ordered_hash.rb', line 102

def values
  @keys.map {|key| self[key]}
end