Permalink
Browse files

Fixed that mash doesn't hash stuff consistently and thus makes it har…

…d to use mashed objects with set and such. (technomancy)
  • Loading branch information...
1 parent de57b1c commit 2da491308766e82c797c7801bdc3a440b7f8d719 @jnunemaker jnunemaker committed Apr 9, 2009
Showing with 17 additions and 2 deletions.
  1. +11 −2 lib/twitter/request.rb
  2. +6 −0 test/twitter/base_test.rb
View
@@ -74,13 +74,22 @@ def parse(response)
def mash(obj)
if obj.is_a?(Array)
- obj.map { |item| Mash.new(item) }
+ obj.map { |item| make_mash_with_consistent_hash(item) }
elsif obj.is_a?(Hash)
- Mash.new(obj)
+ make_mash_with_consistent_hash(obj)
else
obj
end
end
+
+ # Lame workaround for the fact that mash doesn't hash correctly
+ def make_mash_with_consistent_hash(obj)
+ m = Mash.new(obj)
+ def m.hash
+ inspect.hash
+ end
+ return m
+ end
def to_query(options)
options.inject([]) do |collection, opt|
@@ -69,6 +69,12 @@ class BaseTest < Test::Unit::TestCase
first.user.name.should == '-oAk-'
first.text.should == '@jnunemaker cold out today. cold yesterday. even colder today.'
end
+
+ should "correctly hash statuses" do
+ stub_get('/statuses/friends_timeline.json', 'friends_timeline.json')
+ hashes = @twitter.friends_timeline.map{ |s| s.hash }
+ hashes.should == @twitter.friends_timeline.map{ |s| s.hash }
+ end
end
end
end

7 comments on commit 2da4913

Actually I did some digging and found out that it’s Ruby’s core Hash#hash that’s at fault; Mash only manifests this problem since it inherits from Hash.

The workaround to hash the inspect string works here, but unfortunately isn’t a good general-case fix because it honors insertion order, which should be irrelevant to the final hashed value.

Also: I’m curious what advantage Mash provides over OpenStruct, since that’s included in the standard library. It wouldn’t fix the #hash problem unfortunately, but it’d be one fewer dependency.

Collaborator

jnunemaker replied Apr 9, 2009

I started with openstruct and I think the problem was that a hash of hashes doesn’t allow dot notation. Does that make sense? I’m open to other solutions if you come up with something.

Actually using separate Twitter::Status classes made the most sense to me because it was most explicit. I suppose you’ve moved away from that because you’d rather let the API responses determine all the set of methods so you don’t have to update your code if the API changes?

Collaborator

jnunemaker replied Apr 10, 2009

You are correct sir. I got tired of updating and pull in changes for every little tweak in the api.

It’s too bad you can’t lock to a specific version of the REST API and only upgrade when you need a new piece of functionality.

Collaborator

jnunemaker replied Apr 10, 2009

Yeah, I would imagine eventually that twitter will no longer update the api so much. Right now it is still forming which makes changes more of an issue.

Please sign in to comment.