From 23078698b3e1ac2066331e9c8fd4d51077be6866 Mon Sep 17 00:00:00 2001 From: Chris Kampmeier Date: Sat, 29 Nov 2008 05:20:31 -0800 Subject: [PATCH] Add #hash and #eql? to ActiveSupport::Multibyte::Chars so you can use multibyte strings as hash keys without Ruby 1.9 --- .../lib/active_support/multibyte/chars.rb | 21 ++++++++++++++++ activesupport/test/multibyte_chars_test.rb | 25 ++++++++++++++++---- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb index be9c6d3..38d2e9d 100644 --- a/activesupport/lib/active_support/multibyte/chars.rb +++ b/activesupport/lib/active_support/multibyte/chars.rb @@ -165,6 +165,27 @@ module ActiveSupport #:nodoc: translate_offset(@wrapped_string =~ other) end + if RUBY_VERSION < '1.9' + # Returns a Fixnum unique to the string's length and content. This is + # used during hash insertion and comparison. + # + # Example: + # 'Café périferôl'.mb_chars.hash # => 62351556 + def hash + @wrapped_string.hash + end + + # Returns +true+ if the Chars object has the same length and content as + # _other_, or +false+ otherwise. It accepts any object that implements +to_s+. + # + # Example: + # 'Café'.mb_chars.eql?('Café'.mb_chars) # => true + # 'Café'.mb_chars.eql?('Cafe'.mb_chars) # => false + def eql?(other) + @wrapped_string.eql?(other.to_s) + end + end + # Works just like String#split, with the exception that the items in the resulting list are Chars # instances instead of String. This makes chaining methods easier. # diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb index ca2af9b..0ce58c0 100644 --- a/activesupport/test/multibyte_chars_test.rb +++ b/activesupport/test/multibyte_chars_test.rb @@ -152,11 +152,26 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase def test_identity assert_equal @chars, @chars assert @chars.eql?(@chars) - if RUBY_VERSION <= '1.9' - assert !@chars.eql?(UNICODE_STRING) - else - assert @chars.eql?(UNICODE_STRING) - end + assert @chars.eql?(UNICODE_STRING) + assert !@chars.eql?('other'.mb_chars) + assert !@chars.eql?('other') + end + + def test_should_be_usable_as_hash_keys + @same_chars = UNICODE_STRING.dup.mb_chars + assert_equal({@chars => true}, {@same_chars => true}) + assert_not_equal({@chars => true}, {'other'.mb_chars => true}) + assert_equal({@chars => true}.merge(@same_chars => false), {@chars => false}) + assert_equal({@chars => true}[@same_chars], true) + end + + def test_hash_is_deferred_to_the_wrapped_string + assert_equal @chars.hash, UNICODE_STRING.hash + end + + def test_hash_equality + assert_equal @chars.hash, UNICODE_STRING.mb_chars.hash + assert_not_equal @chars.hash, 'other'.mb_chars.hash end def test_string_methods_are_chainable -- 1.6.0.4