From dd7cd151312dec6129d4232acdefd7304bee3e7f Mon Sep 17 00:00:00 2001 From: Frederick Cheung Date: Tue, 9 Dec 2008 20:36:24 +0000 Subject: [PATCH] Rework ActiveSupport::OrderedHash to make lookups faster --- activerecord/test/cases/calculations_test.rb | 5 +- activesupport/lib/active_support/ordered_hash.rb | 59 ++++++++------------- activesupport/test/ordered_hash_test.rb | 10 ++++ 3 files changed, 36 insertions(+), 38 deletions(-) diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index 8bd0dd0..080f6a7 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -171,8 +171,9 @@ class CalculationsTest < ActiveRecord::TestCase Account.expects(:columns).at_least_once.returns([column]) c = Account.count(:all, :group => :firm) - assert_equal Firm, c.first.first.class - assert_equal 1, c.first.last + first_key = c.keys.first + assert_equal Firm, first_key.class + assert_equal 1, c[first_key] end end diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb index 5de94c6..b4a51c5 100644 --- a/activesupport/lib/active_support/ordered_hash.rb +++ b/activesupport/lib/active_support/ordered_hash.rb @@ -4,62 +4,49 @@ module ActiveSupport if RUBY_VERSION >= '1.9' OrderedHash = ::Hash else - class OrderedHash < Array #:nodoc: + class OrderedHash < Hash #:nodoc: + def initialize(*args, &block) + super + @keys = [] + end + def []=(key, value) - if pair = assoc(key) - pair.pop - pair << value - else - self << [key, value] + if !has_key?(key) + @keys << key end - value - end - - def [](key) - pair = assoc(key) - pair ? pair.last : nil + super end def delete(key) - pair = assoc(key) - pair ? array_index = index(pair) : nil - array_index ? delete_at(array_index).last : nil + array_index = has_key?(key) && index(key) + if array_index + @keys.delete_at(array_index) + end + super end def keys - collect { |key, value| key } + @keys end def values - collect { |key, value| value } + @keys.collect { |key| self[key] } end def to_hash - returning({}) do |hash| - each { |array| hash[array[0]] = array[1] } - end - end - - def has_key?(k) - !assoc(k).nil? - end - - alias_method :key?, :has_key? - alias_method :include?, :has_key? - alias_method :member?, :has_key? - - def has_value?(v) - any? { |key, value| value == v } + Hash.new(self) end - alias_method :value?, :has_value? - def each_key - each { |key, value| yield key } + @keys.each { |key| yield key } end def each_value - each { |key, value| yield value } + @keys.each { |key| yield self[key]} + end + + def each + keys.each {|key| yield [key, self[key]]} end end end diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb index 17dffbd..3225b13 100644 --- a/activesupport/test/ordered_hash_test.rb +++ b/activesupport/test/ordered_hash_test.rb @@ -73,4 +73,14 @@ class OrderedHashTest < Test::Unit::TestCase @ordered_hash.each_value { |v| values << v } assert_equal @values, values end + + def test_each + values = [] + @ordered_hash.each {|key, value| values << value} + assert_equal @values, values + end + + def test_each_with_index + @ordered_hash.each_with_index { |pair, index| assert_equal [@keys[index], @values[index]], pair} + end end -- 1.6.0.1