Class: ActiveSupport::OrderedHash

Inherits:
Hash show all
Defined in:
activesupport/lib/active_support/ordered_hash.rb

Overview

The order of iteration over hashes in Ruby 1.8 is undefined. For example, you do not know the order in which keys will return keys, or each yield pairs. ActiveSupport::OrderedHash implements a hash that preserves insertion order, as in Ruby 1.9:

oh = ActiveSupport::OrderedHash.new
oh[:a] = 1
oh[:b] = 2
oh.keys # => [:a, :b], this order is guaranteed

ActiveSupport::OrderedHash is namespaced to prevent conflicts with other implementations.

Direct Known Subclasses

OrderedOptions

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Hash

#as_json, #assert_valid_keys, #deep_dup, #deep_merge, #deep_merge!, #diff, #encode_json, #except, #except!, #extract!, from_xml, #reverse_merge, #reverse_merge!, #slice, #slice!, #stringify_keys, #stringify_keys!, #symbolize_keys, #symbolize_keys!, #to_param, #to_xml, #with_indifferent_access

Constructor Details

#initialize(*args, &block) ⇒ OrderedHash

Returns a new instance of OrderedHash.


68
69
70
71
# File 'activesupport/lib/active_support/ordered_hash.rb', line 68

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

Class Method Details

.[](*args) ⇒ Object


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'activesupport/lib/active_support/ordered_hash.rb', line 73

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 % 2 == 0)
    raise ArgumentError.new("odd number of arguments for Hash")
  end

  args.each_with_index do |val, ind|
    next if (ind % 2 != 0)
    ordered_hash[val] = args[ind + 1]
  end

  ordered_hash
end

Instance Method Details

#[]=(key, value) ⇒ Object


103
104
105
106
# File 'activesupport/lib/active_support/ordered_hash.rb', line 103

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

#clearObject


174
175
176
177
178
# File 'activesupport/lib/active_support/ordered_hash.rb', line 174

def clear
  super
  @keys.clear
  self
end

#delete(key) ⇒ Object


108
109
110
111
112
113
114
# File 'activesupport/lib/active_support/ordered_hash.rb', line 108

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

#delete_ifObject


116
117
118
119
120
# File 'activesupport/lib/active_support/ordered_hash.rb', line 116

def delete_if
  super
  sync_keys!
  self
end

#eachObject


160
161
162
163
164
# File 'activesupport/lib/active_support/ordered_hash.rb', line 160

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

#each_keyObject


148
149
150
151
152
# File 'activesupport/lib/active_support/ordered_hash.rb', line 148

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

#each_pairObject


166
167
168
169
170
# File 'activesupport/lib/active_support/ordered_hash.rb', line 166

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

#each_valueObject


154
155
156
157
158
# File 'activesupport/lib/active_support/ordered_hash.rb', line 154

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

#encode_with(coder) ⇒ Object


28
29
30
# File 'activesupport/lib/active_support/ordered_hash.rb', line 28

def encode_with(coder)
  coder.represent_seq '!omap', map { |k,v| { k => v } }
end

#extractable_options?Boolean

Returns true to make sure that this hash is extractable via Array#extract_options!

Returns:

  • (Boolean)

51
52
53
# File 'activesupport/lib/active_support/ordered_hash.rb', line 51

def extractable_options?
  true
end

#initialize_copy(other) ⇒ Object


97
98
99
100
101
# File 'activesupport/lib/active_support/ordered_hash.rb', line 97

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

#inspectObject


212
213
214
# File 'activesupport/lib/active_support/ordered_hash.rb', line 212

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

#invertObject


208
209
210
# File 'activesupport/lib/active_support/ordered_hash.rb', line 208

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

#keysObject


132
133
134
# File 'activesupport/lib/active_support/ordered_hash.rb', line 132

def keys
  @keys.dup
end

#merge(other_hash, &block) ⇒ Object


197
198
199
# File 'activesupport/lib/active_support/ordered_hash.rb', line 197

def merge(other_hash, &block)
  dup.merge!(other_hash, &block)
end

#merge!(other_hash) ⇒ Object Also known as: update


186
187
188
189
190
191
192
193
# File 'activesupport/lib/active_support/ordered_hash.rb', line 186

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

#nested_under_indifferent_accessObject


46
47
48
# File 'activesupport/lib/active_support/ordered_hash.rb', line 46

def nested_under_indifferent_access
  self
end

#reject(&block) ⇒ Object


128
129
130
# File 'activesupport/lib/active_support/ordered_hash.rb', line 128

def reject(&block)
  dup.reject!(&block)
end

#reject!Object


122
123
124
125
126
# File 'activesupport/lib/active_support/ordered_hash.rb', line 122

def reject!
  super
  sync_keys!
  self
end

#replace(other) ⇒ Object

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


202
203
204
205
206
# File 'activesupport/lib/active_support/ordered_hash.rb', line 202

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

#shiftObject


180
181
182
183
184
# File 'activesupport/lib/active_support/ordered_hash.rb', line 180

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

#to_aObject


144
145
146
# File 'activesupport/lib/active_support/ordered_hash.rb', line 144

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

#to_hashObject


140
141
142
# File 'activesupport/lib/active_support/ordered_hash.rb', line 140

def to_hash
  self
end

#to_yaml(opts = {}) ⇒ Object


32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'activesupport/lib/active_support/ordered_hash.rb', line 32

def to_yaml(opts = {})
  if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck?
    return super
  end

  YAML.quick_emit(self, opts) do |out|
    out.seq(taguri) do |seq|
      each do |k, v|
        seq.add(k => v)
      end
    end
  end
end

#to_yaml_typeObject


24
25
26
# File 'activesupport/lib/active_support/ordered_hash.rb', line 24

def to_yaml_type
  "!tag:yaml.org,2002:omap"
end

#valuesObject


136
137
138
# File 'activesupport/lib/active_support/ordered_hash.rb', line 136

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