File: active_support/ordered_hash.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: ActiveSupport#8
  class: OrderedHash#9
inherits from
  Hash ( Builtin-Module )
has properties
method: to_yaml_type #10
method: to_yaml / 1 #14
method: initialize / 2 #26
class method: [] / 1 #31
method: initialize_copy / 1 #55
method: []= / 2 #61
method: delete / 1 #66
method: delete_if #74
method: reject! #80
method: reject / 1 #86
method: keys #90
method: values #94
method: to_hash #98
method: to_a #102
method: each_key #106
method: each_value #110
method: each #114
method: clear #120
method: shift #126
method: merge! / 1 #132
method: merge / 2 #143
method: replace / 1 #148
method: invert #154
method: inspect #158
method: sync_keys! #163

Class Hierarchy

Code

   1  require 'yaml'
   2 
   3  YAML.add_builtin_type("omap") do |type, val|
   4    ActiveSupport::OrderedHash[val.map(&:to_a).map(&:first)]
   5  end
   6 
   7  # OrderedHash is namespaced to prevent conflicts with other implementations
   8  module ActiveSupport
   9    class OrderedHash < ::Hash #:nodoc:
  10      def to_yaml_type
  11        "!tag:yaml.org,2002:omap"
  12      end
  13 
  14      def to_yaml(opts = {})
  15        YAML.quick_emit(self, opts) do |out|
  16          out.seq(taguri, to_yaml_style) do |seq|
  17            each do |k, v|
  18              seq.add(k => v)
  19            end
  20          end
  21        end
  22      end
  23 
  24      # Hash is ordered in Ruby 1.9!
  25      if RUBY_VERSION < '1.9'
  26        def initialize(*args, &block)
  27          super
  28          @keys = []
  29        end
  30 
  31        def self.[](*args)
  32          ordered_hash = new
  33 
  34          if (args.length == 1 && args.first.is_a?(Array))
  35            args.first.each do |key_value_pair|
  36              next unless (key_value_pair.is_a?(Array))
  37              ordered_hash[key_value_pair[0]] = key_value_pair[1]
  38            end
  39 
  40            return ordered_hash
  41          end
  42 
  43          unless (args.size % 2 == 0)
  44            raise ArgumentError.new("odd number of arguments for Hash")
  45          end
  46 
  47          args.each_with_index do |val, ind|
  48            next if (ind % 2 != 0)
  49            ordered_hash[val] = args[ind + 1]
  50          end
  51 
  52          ordered_hash
  53        end
  54 
  55        def initialize_copy(other)
  56          super
  57          # make a deep copy of keys
  58          @keys = other.keys
  59        end
  60 
  61        def []=(key, value)
  62          @keys << key if !has_key?(key)
  63          super
  64        end
  65 
  66        def delete(key)
  67          if has_key? key
  68            index = @keys.index(key)
  69            @keys.delete_at index
  70          end
  71          super
  72        end
  73 
  74        def delete_if
  75          super
  76          sync_keys!
  77          self
  78        end
  79 
  80        def reject!
  81          super
  82          sync_keys!
  83          self
  84        end
  85 
  86        def reject(&block)
  87          dup.reject!(&block)
  88        end
  89 
  90        def keys
  91          @keys.dup
  92        end
  93 
  94        def values
  95          @keys.collect { |key| self[key] }
  96        end
  97 
  98        def to_hash
  99          self
 100        end
 101 
 102        def to_a
 103          @keys.map { |key| [ key, self[key] ] }
 104        end
 105 
 106        def each_key
 107          @keys.each { |key| yield key }
 108        end
 109 
 110        def each_value
 111          @keys.each { |key| yield self[key]}
 112        end
 113 
 114        def each
 115          @keys.each {|key| yield [key, self[key]]}
 116        end
 117 
 118        alias_method :each_pair, :each
 119 
 120        def clear
 121          super
 122          @keys.clear
 123          self
 124        end
 125 
 126        def shift
 127          k = @keys.first
 128          v = delete(k)
 129          [k, v]
 130        end
 131 
 132        def merge!(other_hash)
 133          if block_given?
 134            other_hash.each { |k, v| self[k] = key?(k) ? yield(k, self[k], v) : v }
 135          else
 136            other_hash.each { |k, v| self[k] = v }
 137          end
 138          self
 139        end
 140 
 141        alias_method :update, :merge!
 142 
 143        def merge(other_hash, &block)
 144          dup.merge!(other_hash, &block)
 145        end
 146 
 147        # When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not.
 148        def replace(other)
 149          super
 150          @keys = other.keys
 151          self
 152        end
 153 
 154        def invert
 155          OrderedHash[self.to_a.map!{|key_value_pair| key_value_pair.reverse}]
 156        end
 157 
 158        def inspect
 159          "#<OrderedHash #{super}>"
 160        end
 161 
 162        private
 163          def sync_keys!
 164            @keys.delete_if {|k| !has_key?(k)}
 165          end
 166      end
 167    end
 168  end