hash_digest 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in hash_digest.gemspec
4
+ gemspec
data/README.markdown ADDED
@@ -0,0 +1,40 @@
1
+ = HashHash
2
+
3
+ Generates MD5 digests of Hashes (and Arrays) indifferent to key type and ordering.
4
+
5
+ Useful for hashing rows in a 2-dimensional table.
6
+
7
+ Used by the [remote_table](https://github.com/seamusabshere/remote_table) gem.
8
+
9
+ == Example
10
+
11
+ === Indifferent to key type
12
+
13
+ HashDigest.hexdigest(:a => 1) #=> '3872c9ae3f427af0be0ead09d07ae2cf'
14
+ HashDigest.hexdigest('a' => 1) #=> '3872c9ae3f427af0be0ead09d07ae2cf'
15
+
16
+ === Indifferent to key order
17
+
18
+ HashDigest.hexdigest(:a => 1, 'b' => 2) == HashDigest.hexdigest('a' => 1, :b => 2) # true
19
+ HashDigest.hexdigest(:a => 1, 'b' => 2) == HashDigest.hexdigest(:b => 2, 'a' => 1) # true
20
+
21
+ == Algorithm
22
+
23
+ Basically represent the hash as a URL querystring, ordered by key, and MD5 that.
24
+
25
+ 1. Stringify keys
26
+ 2. Create an array of strings like "url_encode(key)=url_encode(value)" by going through each key in alphabetical order
27
+ 3. Join the array together with "&"
28
+ 4. MD5 hexdigest the joined string
29
+
30
+ To digest an array, just pretend it's a hash with keys like 1, 2, 3, etc.
31
+
32
+ == Potential issues
33
+
34
+ * Uses MD5 (not cryptographically awesome)
35
+ * Uses ActiveSupport's <tt>#to_query</tt> method to create a digestible string like "foo=bar&baz=bam" (slow)
36
+ * Meant for flat hashes, e.g. { :a => 1, :b => 2 } and not { :x => { :y => :z } }
37
+
38
+ == Copyright
39
+
40
+ Copyright 2011 Seamus Abshere
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake'
4
+ require 'rake/testtask'
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/test_*.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "hash_digest/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "hash_digest"
7
+ s.version = HashDigest::VERSION
8
+ s.authors = ["Seamus Abshere"]
9
+ s.email = ["seamus@abshere.net"]
10
+ s.homepage = "https://github.com/seamusabshere/hash_digest"
11
+ s.summary = %q{Make consistent hashcodes from flat Hashes, regardless of key ordering}
12
+ s.description = %q{Make consistent hashcodes from flat Hashes, regardless of key ordering. Useful for hashing rows in a table.}
13
+
14
+ s.rubyforge_project = "hash_digest"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ # s.add_development_dependency "rspec"
23
+ # s.add_runtime_dependency "rest-client"
24
+ s.add_runtime_dependency 'activesupport'
25
+
26
+ s.add_development_dependency 'minitest'
27
+ s.add_development_dependency 'rake'
28
+ end
@@ -0,0 +1,27 @@
1
+ require 'digest/md5'
2
+ require 'active_support'
3
+ require 'active_support/version'
4
+ %w{
5
+ active_support/core_ext/hash/keys
6
+ active_support/core_ext/object/to_query
7
+ }.each do |active_support_3_requirement|
8
+ require active_support_3_requirement
9
+ end if ::ActiveSupport::VERSION::MAJOR >= 3
10
+
11
+ require "hash_digest/version"
12
+
13
+ module HashDigest
14
+ def self.hexdigest(hsh)
15
+ ordered_list = if hsh.is_a?(::Hash)
16
+ hsh = hsh.stringify_keys
17
+ hsh.keys.sort.map { |k| hsh[k].to_query k }
18
+ elsif hsh.is_a?(::Array)
19
+ ary = []
20
+ hsh.each_with_index { |v, i| ary.push v.to_query(i.to_s) }
21
+ ary
22
+ else
23
+ raise ::ArgumentError, "[hash_digest gem] Can only digest Hashes and Arrays, not #{hsh.class}"
24
+ end
25
+ ::Digest::MD5.hexdigest ordered_list.join('&')
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module HashDigest
2
+ VERSION = "1.0.0"
3
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/setup'
2
+ require 'minitest/spec'
3
+ require 'minitest/autorun'
4
+
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ require 'hash_digest'
8
+
9
+ class MiniTest::Unit::TestCase
10
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'helper'
3
+
4
+ describe HashDigest do
5
+ it 'generates a hash of a hash' do
6
+ HashDigest.hexdigest(:a => 1).must_equal '3872c9ae3f427af0be0ead09d07ae2cf'
7
+ end
8
+
9
+ it 'is indifferent to key type' do
10
+ HashDigest.hexdigest(:a => 1, 'b' => 2).must_equal(HashDigest.hexdigest('a' => 1, :b => 2))
11
+ end
12
+
13
+ it 'is indifferent to key order' do
14
+ HashDigest.hexdigest(:a => 1, 'b' => 2).must_equal(HashDigest.hexdigest(:b => 2, 'a' => 1))
15
+ end
16
+
17
+ it 'just as a bonus, works on arrays' do
18
+ HashDigest.hexdigest([:a, 1]).must_equal '8ce19b95077ec34a4fd06b089f368678'
19
+ end
20
+
21
+ it "raises an exception if you try to digest something it doesn't handle" do
22
+ lambda { HashDigest.hexdigest('foobar') }.must_raise(::ArgumentError)
23
+ end
24
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hash_digest
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Seamus Abshere
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-09-23 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: &2154254960 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2154254960
25
+ - !ruby/object:Gem::Dependency
26
+ name: minitest
27
+ requirement: &2154254540 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *2154254540
36
+ - !ruby/object:Gem::Dependency
37
+ name: rake
38
+ requirement: &2154254120 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *2154254120
47
+ description: Make consistent hashcodes from flat Hashes, regardless of key ordering.
48
+ Useful for hashing rows in a table.
49
+ email:
50
+ - seamus@abshere.net
51
+ executables: []
52
+ extensions: []
53
+ extra_rdoc_files: []
54
+ files:
55
+ - .gitignore
56
+ - Gemfile
57
+ - README.markdown
58
+ - Rakefile
59
+ - hash_digest.gemspec
60
+ - lib/hash_digest.rb
61
+ - lib/hash_digest/version.rb
62
+ - test/helper.rb
63
+ - test/test_hash_digest.rb
64
+ homepage: https://github.com/seamusabshere/hash_digest
65
+ licenses: []
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubyforge_project: hash_digest
84
+ rubygems_version: 1.8.6
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: Make consistent hashcodes from flat Hashes, regardless of key ordering
88
+ test_files:
89
+ - test/helper.rb
90
+ - test/test_hash_digest.rb