hashie 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Intridea, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,76 @@
1
+ = Hashie
2
+
3
+ Hashie is a growing collection of tools that extend Hashes and make
4
+ them more useful.
5
+
6
+ == Installation
7
+
8
+ Hashie is a gem and is available on Gemcutter. If you don't have Gemcutter,
9
+ install it:
10
+
11
+ gem install gemcutter
12
+ gem tumble
13
+
14
+ Then you can install Hashie:
15
+
16
+ gem install hashie
17
+
18
+ == Mash
19
+
20
+ Mash is an extended Hash that gives simple pseudo-object functionality
21
+ that can be built from hashes and easily extended. It is designed to
22
+ be used in RESTful API libraries to provide easy object-like access
23
+ to JSON and XML parsed hashes.
24
+
25
+ === Example:
26
+
27
+ mash = Hashie::Mash.new
28
+ mash.name? # => false
29
+ mash.name # => nil
30
+ mash.name = "My Mash"
31
+ mash.name # => "My Mash"
32
+ mash.name? # => true
33
+ mash.inspect # => <Hashie::Mash name="My Mash">
34
+
35
+ mash = Mash.new
36
+ # use bang methods for multi-level assignment
37
+ mash.author!.name = "Michael Bleigh"
38
+ mash.author # => <Hashie::Mash name="Michael Bleigh">
39
+
40
+ == Dash
41
+
42
+ Dash is an extended Hash that has a discrete set of defined properties
43
+ and only those properties may be set on the hash. Additionally, you
44
+ can set defaults for each property.
45
+
46
+ === Example:
47
+
48
+ class Person < Hashie::Dash
49
+ property :name
50
+ property :email
51
+ property :occupation, :default => 'Rubyist'
52
+ end
53
+
54
+ p = Person.new
55
+ p.name # => nil
56
+ p.occupation # => 'Rubyist'
57
+ p.email = 'abc@def.com'
58
+ p.email # => 'abc@def.com'
59
+ p['awesome'] # => NoMethodError
60
+
61
+
62
+ == Note on Patches/Pull Requests
63
+
64
+ * Fork the project.
65
+ * Make your feature addition or bug fix.
66
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
67
+ * Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
68
+ * Send me a pull request. Bonus points for topic branches.
69
+
70
+ == Authors
71
+
72
+ * Michael Bleigh
73
+
74
+ == Copyright
75
+
76
+ Copyright (c) 2009 Intridea, Inc (http://intridea.com/). See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "hashie"
8
+ gem.summary = %Q{Your friendly neighborhood hash toolkit.}
9
+ gem.description = %Q{Hashie is a small collection of tools that make hashes more powerful. Currently includes Mash (Mocking Hash) and Dash (Discrete Hash).}
10
+ gem.email = "michael@intridea.com"
11
+ gem.homepage = "http://github.com/intridea/hashie"
12
+ gem.authors = ["Michael Bleigh"]
13
+ gem.add_development_dependency "rspec"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
19
+ end
20
+
21
+ require 'spec/rake/spectask'
22
+ Spec::Rake::SpecTask.new(:spec) do |spec|
23
+ spec.libs << 'lib' << 'spec'
24
+ spec.spec_files = FileList['spec/**/*_spec.rb']
25
+ end
26
+
27
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.pattern = 'spec/**/*_spec.rb'
30
+ spec.rcov = true
31
+ end
32
+
33
+ task :spec => :check_dependencies
34
+
35
+ task :default => :spec
36
+
37
+ require 'rake/rdoctask'
38
+ Rake::RDocTask.new do |rdoc|
39
+ if File.exist?('VERSION')
40
+ version = File.read('VERSION')
41
+ else
42
+ version = ""
43
+ end
44
+
45
+ rdoc.rdoc_dir = 'rdoc'
46
+ rdoc.title = "hashie #{version}"
47
+ rdoc.rdoc_files.include('README*')
48
+ rdoc.rdoc_files.include('lib/**/*.rb')
49
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/hashie.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'hashie/hash_extensions'
2
+ require 'hashie/hash'
3
+ require 'hashie/mash'
4
+ require 'hashie/dash'
@@ -0,0 +1,72 @@
1
+ require 'hashie/hash'
2
+
3
+ module Hashie
4
+ # A Dash is a 'defined' or 'discrete' Hash, that is, a Hash
5
+ # that has a set of defined keys that are accessible (with
6
+ # optional defaults) and only those keys may be set or read.
7
+ #
8
+ # Dashes are useful when you need to create a very simple
9
+ # lightweight data object that needs even fewer options and
10
+ # resources than something like a DataMapper resource.
11
+ #
12
+ # It is preferrable to a Struct because of the in-class
13
+ # API for defining properties as well as per-property defaults.
14
+ class Dash < Hashie::Hash
15
+ # Defines a property on the Dash. Options are
16
+ # as follows:
17
+ #
18
+ # * <tt>:default</tt> - Specify a default value for this property,
19
+ # to be returned before a value is set on the property in a new
20
+ # Dash.
21
+ #
22
+ def self.property(property_name, options = {})
23
+ property_name = property_name.to_sym
24
+
25
+ (@properties ||= []) << property_name
26
+ (@defaults ||= {})[property_name] = options.delete(:default)
27
+
28
+ class_eval <<-RUBY
29
+ def #{property_name}
30
+ self['#{property_name}']
31
+ end
32
+
33
+ def #{property_name}=(val)
34
+ self['#{property_name}'] = val
35
+ end
36
+ RUBY
37
+ end
38
+
39
+ # Get a String array of the currently defined
40
+ # properties on this Dash.
41
+ def self.properties
42
+ @properties.collect{|p| p.to_s}
43
+ end
44
+
45
+ # Check to see if the specified property has already been
46
+ # defined.
47
+ def self.property?(prop)
48
+ properties.include?(prop.to_s)
49
+ end
50
+
51
+ # The default values that have been set for this Dash
52
+ def self.defaults
53
+ @defaults
54
+ end
55
+
56
+ # Retrieve a value from the Dash (will return the
57
+ # property's default value if it hasn't been set).
58
+ def [](property_name)
59
+ super || self.class.defaults[property_name.to_sym]
60
+ end
61
+
62
+ # Set a value on the Dash in a Hash-like way. Only works
63
+ # on pre-existing properties.
64
+ def []=(property, value)
65
+ if self.class.property?(property)
66
+ super
67
+ else
68
+ raise NoMethodError, 'You may only set pre-defined properties.'
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,8 @@
1
+ module Hashie
2
+ # A Hashie Hash is simply a Hash that has convenience
3
+ # functions baked in such as stringify_keys that may
4
+ # not be available in all libraries.
5
+ class Hash < Hash
6
+ include Hashie::HashExtensions
7
+ end
8
+ end
@@ -0,0 +1,31 @@
1
+ module Hashie
2
+ module HashExtensions
3
+ def self.included(base)
4
+ # Don't tread on existing extensions of Hash by
5
+ # adding methods that are likely to exist.
6
+ %w(stringify_keys stringify_keys!).each do |hashie_method|
7
+ base.send :alias_method, hashie_method, "hashie_#{hashie_method}" unless base.instance_methods.include?(hashie_method)
8
+ end
9
+ end
10
+
11
+ # Destructively convert all of the keys of a Hash
12
+ # to their string representations.
13
+ def hashie_stringify_keys!
14
+ self.keys.each do |k|
15
+ self[k.to_s] = self.delete(k)
16
+ end
17
+ self
18
+ end
19
+
20
+ # Convert all of the keys of a Hash
21
+ # to their string representations.
22
+ def hashie_stringify_keys
23
+ self.dup.stringify_keys!
24
+ end
25
+
26
+ # Convert this hash into a Mash
27
+ def to_mash
28
+ Hashie::Mash.new(self)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,208 @@
1
+ module Hashie
2
+ # Mash allows you to create pseudo-objects that have method-like
3
+ # accessors for hash keys. This is useful for such implementations
4
+ # as an API-accessing library that wants to fake robust objects
5
+ # without the overhead of actually doing so. Think of it as OpenStruct
6
+ # with some additional goodies.
7
+ #
8
+ # A Mash will look at the methods you pass it and perform operations
9
+ # based on the following rules:
10
+ #
11
+ # * No punctuation: Returns the value of the hash for that key, or nil if none exists.
12
+ # * Assignment (<tt>=</tt>): Sets the attribute of the given method name.
13
+ # * Existence (<tt>?</tt>): Returns true or false depending on whether that key has been set.
14
+ # * Bang (<tt>!</tt>): Forces the existence of this key, used for deep Mashes. Think of it as "touch" for mashes.
15
+ #
16
+ # == Basic Example
17
+ #
18
+ # mash = Mash.new
19
+ # mash.name? # => false
20
+ # mash.name = "Bob"
21
+ # mash.name # => "Bob"
22
+ # mash.name? # => true
23
+ #
24
+ # == Hash Conversion Example
25
+ #
26
+ # hash = {:a => {:b => 23, :d => {:e => "abc"}}, :f => [{:g => 44, :h => 29}, 12]}
27
+ # mash = Mash.new(hash)
28
+ # mash.a.b # => 23
29
+ # mash.a.d.e # => "abc"
30
+ # mash.f.first.g # => 44
31
+ # mash.f.last # => 12
32
+ #
33
+ # == Bang Example
34
+ #
35
+ # mash = Mash.new
36
+ # mash.author # => nil
37
+ # mash.author! # => <Mash>
38
+ #
39
+ # mash = Mash.new
40
+ # mash.author!.name = "Michael Bleigh"
41
+ # mash.author # => <Mash name="Michael Bleigh">
42
+ #
43
+ class Mash < Hashie::Hash
44
+ # If you pass in an existing hash, it will
45
+ # convert it to a Mash including recursively
46
+ # descending into arrays and hashes, converting
47
+ # them as well.
48
+ def initialize(source_hash = nil, default = nil, &blk)
49
+ deep_update(source_hash) if source_hash
50
+ super default if default
51
+ super &blk if blk
52
+ end
53
+
54
+ class << self; alias [] new; end
55
+
56
+ def id #:nodoc:
57
+ self["id"] ? self["id"] : super
58
+ end
59
+
60
+ # Borrowed from Merb's Mash object.
61
+ #
62
+ # ==== Parameters
63
+ # key<Object>:: The default value for the mash. Defaults to nil.
64
+ #
65
+ # ==== Alternatives
66
+ # If key is a Symbol and it is a key in the mash, then the default value will
67
+ # be set to the value matching the key.
68
+ def default(key = nil)
69
+ if key.is_a?(Symbol) && key?(key.to_s)
70
+ self[key]
71
+ else
72
+ key ? super : super()
73
+ end
74
+ end
75
+
76
+ alias_method :regular_reader, :[]
77
+ alias_method :regular_writer, :[]=
78
+
79
+ # Retrieves an attribute set in the Mash. Will convert
80
+ # any key passed in to a string before retrieving.
81
+ def [](key)
82
+ key = convert_key(key)
83
+ regular_reader(key)
84
+ end
85
+
86
+ # Sets an attribute in the Mash. Key will be converted to
87
+ # a string before it is set, and Hashes will be converted
88
+ # into Mashes for nesting purposes.
89
+ def []=(key,value) #:nodoc:
90
+ key = convert_key(key)
91
+ regular_writer(key, convert_value(value))
92
+ end
93
+
94
+ # This is the bang method reader, it will return a new Mash
95
+ # if there isn't a value already assigned to the key requested.
96
+ def initializing_reader(key)
97
+ self[key] = Hashie::Mash.new unless key?(key)
98
+ self[key]
99
+ end
100
+
101
+ alias_method :regular_dup, :dup
102
+ # Duplicates the current mash as a new mash.
103
+ def dup
104
+ Mash.new(self, self.default)
105
+ end
106
+
107
+ alias_method :picky_key?, :key?
108
+ def key?(key)
109
+ picky_key?(convert_key(key))
110
+ end
111
+
112
+ alias_method :regular_inspect, :inspect
113
+ # Prints out a pretty object-like string of the
114
+ # defined attributes.
115
+ def inspect
116
+ ret = "<#{self.class.to_s}"
117
+ keys.sort.each do |key|
118
+ ret << " #{key}=#{self[key].inspect}"
119
+ end
120
+ ret << ">"
121
+ ret
122
+ end
123
+ alias_method :to_s, :inspect
124
+
125
+ # Performs a deep_update on a duplicate of the
126
+ # current mash.
127
+ def deep_merge(other_hash)
128
+ dup.deep_merge!(other_hash)
129
+ end
130
+
131
+ # Recursively merges this mash with the passed
132
+ # in hash, merging each hash in the hierarchy.
133
+ def deep_update(other_hash)
134
+ other_hash = Hashie::Hash[other_hash].stringify_keys!
135
+
136
+ other_hash.each_pair do |k,v|
137
+ k = convert_key(k)
138
+ self[k] = Hashie::Mash.new(self[k]).to_mash if self[k].is_a?(Hash) unless self[k].is_a?(Hashie::Mash)
139
+ if self[k].is_a?(Hashie::Mash) && other_hash[k].is_a?(Hash)
140
+ self[k] = self[k].deep_merge(other_hash[k])
141
+ else
142
+ self[k] = convert_value(other_hash[k],true)
143
+ end
144
+ end
145
+
146
+ self
147
+ end
148
+ alias_method :deep_merge!, :deep_update
149
+
150
+ # ==== Parameters
151
+ # other_hash<Hash>::
152
+ # A hash to update values in the mash with. Keys will be
153
+ # stringified and Hashes will be converted to Mashes.
154
+ #
155
+ # ==== Returns
156
+ # Mash:: The updated mash.
157
+ def update(other_hash)
158
+ other_hash.each_pair do |key, value|
159
+ if respond_to?(convert_key(key) + "=")
160
+ self.send(convert_key(key) + "=", convert_value(value))
161
+ else
162
+ regular_writer(convert_key(key), convert_value(value))
163
+ end
164
+ end
165
+ self
166
+ end
167
+ alias_method :merge!, :update
168
+
169
+ # Converts a mash back to a hash (with stringified keys)
170
+ def to_hash
171
+ Hash.new(default).merge(self)
172
+ end
173
+
174
+ def method_missing(method_name, *args) #:nodoc:
175
+ if (match = method_name.to_s.match(/(.*)=$/)) && args.size == 1
176
+ self[match[1]] = args.first
177
+ elsif (match = method_name.to_s.match(/(.*)\?$/)) && args.size == 0
178
+ key?(match[1])
179
+ elsif (match = method_name.to_s.match(/(.*)!$/)) && args.size == 0
180
+ initializing_reader(match[1])
181
+ elsif key?(method_name)
182
+ self[method_name]
183
+ elsif match = method_name.to_s.match(/^([a-z][a-z0-9A-Z_]+)$/)
184
+ default(method_name)
185
+ else
186
+ super
187
+ end
188
+ end
189
+
190
+ protected
191
+
192
+ def convert_key(key) #:nodoc:
193
+ key.to_s
194
+ end
195
+
196
+ def convert_value(val, duping=false) #:nodoc:
197
+ case val
198
+ when ::Hash
199
+ val = val.dup if duping
200
+ Hashie::Mash.new(val)
201
+ when Array
202
+ val.collect{ |e| convert_value(e) }
203
+ else
204
+ val
205
+ end
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,58 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ class DashTest < Hashie::Dash
4
+ property :first_name
5
+ property :email
6
+ property :count, :default => 0
7
+ end
8
+
9
+ describe Hashie::Dash do
10
+ it 'should be a subclass of Hashie::Hash' do
11
+ (Hashie::Dash < Hash).should be_true
12
+ end
13
+
14
+ describe ' creating properties' do
15
+ it 'should add the property to the list' do
16
+ DashTest.property :not_an_att
17
+ DashTest.properties.include?('not_an_att').should be_true
18
+ end
19
+
20
+ it 'should create a method for reading the property' do
21
+ DashTest.new.respond_to?(:first_name).should be_true
22
+ end
23
+
24
+ it 'should create a method for writing the property' do
25
+ DashTest.new.respond_to?(:first_name=).should be_true
26
+ end
27
+ end
28
+
29
+ describe ' writing to properties' do
30
+ before do
31
+ @dash = DashTest.new
32
+ end
33
+
34
+ it 'should not be able to write to a non-existent property using []=' do
35
+ lambda{@dash['abc'] = 123}.should raise_error(NoMethodError)
36
+ end
37
+
38
+ it 'should be able to write to an existing property using []=' do
39
+ lambda{@dash['first_name'] = 'Bob'}.should_not raise_error
40
+ end
41
+
42
+ it 'should be able to read/write to an existing property using a method call' do
43
+ @dash.first_name = 'Franklin'
44
+ @dash.first_name.should == 'Franklin'
45
+ end
46
+ end
47
+
48
+ describe ' defaults' do
49
+ before do
50
+ @dash = DashTest.new
51
+ end
52
+
53
+ it 'should return the default value for defaulted' do
54
+ DashTest.property :defaulted, :default => 'abc'
55
+ DashTest.new.defaulted.should == 'abc'
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,22 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Hash do
4
+ it "should be convertible to a Hashie::Mash" do
5
+ mash = Hashie::Hash[:some => "hash"].to_mash
6
+ mash.is_a?(Hashie::Mash).should be_true
7
+ mash.some.should == "hash"
8
+ end
9
+
10
+ it "#stringify_keys! should turn all keys into strings" do
11
+ hash = Hashie::Hash[:a => "hey", 123 => "bob"]
12
+ hash.stringify_keys!
13
+ hash.should == Hashie::Hash["a" => "hey", "123" => "bob"]
14
+ end
15
+
16
+ it "#stringify_keys should return a hash with stringified keys" do
17
+ hash = Hashie::Hash[:a => "hey", 123 => "bob"]
18
+ stringified_hash = hash.stringify_keys
19
+ hash.should == Hashie::Hash[:a => "hey", 123 => "bob"]
20
+ stringified_hash.should == Hashie::Hash["a" => "hey", "123" => "bob"]
21
+ end
22
+ end
@@ -0,0 +1,116 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Hashie::Mash do
4
+ before(:each) do
5
+ @mash = Hashie::Mash.new
6
+ end
7
+
8
+ it "should inherit from hash" do
9
+ @mash.is_a?(Hash).should be_true
10
+ end
11
+
12
+ it "should be able to set hash values through method= calls" do
13
+ @mash.test = "abc"
14
+ @mash["test"].should == "abc"
15
+ end
16
+
17
+ it "should be able to retrieve set values through method calls" do
18
+ @mash["test"] = "abc"
19
+ @mash.test.should == "abc"
20
+ end
21
+
22
+ it "should test for already set values when passed a ? method" do
23
+ @mash.test?.should be_false
24
+ @mash.test = "abc"
25
+ @mash.test?.should be_true
26
+ end
27
+
28
+ it "should make all [] and []= into strings for consistency" do
29
+ @mash["abc"] = 123
30
+ @mash.key?('abc').should be_true
31
+ @mash["abc"].should == 123
32
+ end
33
+
34
+ it "should have a to_s that is identical to its inspect" do
35
+ @mash.abc = 123
36
+ @mash.to_s.should == @mash.inspect
37
+ end
38
+
39
+ it "should return nil instead of raising an error for attribute-esque method calls" do
40
+ @mash.abc.should be_nil
41
+ end
42
+
43
+ it "should return a Hashie::Mash when passed a bang method to a non-existenct key" do
44
+ @mash.abc!.is_a?(Hashie::Mash).should be_true
45
+ end
46
+
47
+ it "should return the existing value when passed a bang method for an existing key" do
48
+ @mash.name = "Bob"
49
+ @mash.name!.should == "Bob"
50
+ end
51
+
52
+ it "#initializing_reader should return a Hashie::Mash when passed a non-existent key" do
53
+ @mash.initializing_reader(:abc).is_a?(Hashie::Mash).should be_true
54
+ end
55
+
56
+ it "should allow for multi-level assignment through bang methods" do
57
+ @mash.author!.name = "Michael Bleigh"
58
+ @mash.author.should == Hashie::Mash.new(:name => "Michael Bleigh")
59
+ @mash.author!.website!.url = "http://www.mbleigh.com/"
60
+ @mash.author.website.should == Hashie::Mash.new(:url => "http://www.mbleigh.com/")
61
+ end
62
+
63
+ it "#deep_update should recursively Hashie::Mash Hashie::Mashes and hashes together" do
64
+ @mash.first_name = "Michael"
65
+ @mash.last_name = "Bleigh"
66
+ @mash.details = Hashie::Hash[:email => "michael@asf.com"].to_mash
67
+ @mash.deep_update({:details => {:email => "michael@intridea.com"}})
68
+ @mash.details.email.should == "michael@intridea.com"
69
+ end
70
+
71
+ it "should convert hash assignments into Hashie::Mashes" do
72
+ @mash.details = {:email => 'randy@asf.com', :address => {:state => 'TX'} }
73
+ @mash.details.email.should == 'randy@asf.com'
74
+ @mash.details.address.state.should == 'TX'
75
+ end
76
+
77
+ context "#initialize" do
78
+ it "should convert an existing hash to a Hashie::Mash" do
79
+ converted = Hashie::Mash.new({:abc => 123, :name => "Bob"})
80
+ converted.abc.should == 123
81
+ converted.name.should == "Bob"
82
+ end
83
+
84
+ it "should convert hashes recursively into Hashie::Mashes" do
85
+ converted = Hashie::Mash.new({:a => {:b => 1, :c => {:d => 23}}})
86
+ converted.a.is_a?(Hashie::Mash).should be_true
87
+ converted.a.b.should == 1
88
+ converted.a.c.d.should == 23
89
+ end
90
+
91
+ it "should convert hashes in arrays into Hashie::Mashes" do
92
+ converted = Hashie::Mash.new({:a => [{:b => 12}, 23]})
93
+ converted.a.first.b.should == 12
94
+ converted.a.last.should == 23
95
+ end
96
+
97
+ it "should convert an existing Hashie::Mash into a Hashie::Mash" do
98
+ initial = Hashie::Mash.new(:name => 'randy', :address => {:state => 'TX'})
99
+ copy = Hashie::Mash.new(initial)
100
+ initial.name.should == copy.name
101
+ initial.object_id.should_not == copy.object_id
102
+ copy.address.state.should == 'TX'
103
+ copy.address.state = 'MI'
104
+ initial.address.state.should == 'TX'
105
+ copy.address.object_id.should_not == initial.address.object_id
106
+ end
107
+
108
+ it "should accept a default block" do
109
+ initial = Hashie::Mash.new { |h,i| h[i] = []}
110
+ initial.default_proc.should_not be_nil
111
+ initial.default.should be_nil
112
+ initial.test.should == []
113
+ initial.test?.should be_true
114
+ end
115
+ end
116
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format progress
@@ -0,0 +1,10 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+
4
+ require 'hashie'
5
+ require 'spec'
6
+ require 'spec/autorun'
7
+
8
+ Spec::Runner.configure do |config|
9
+
10
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hashie
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Michael Bleigh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-12 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: Hashie is a small collection of tools that make hashes more powerful. Currently includes Mash (Mocking Hash) and Dash (Discrete Hash).
26
+ email: michael@intridea.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.rdoc
34
+ files:
35
+ - .document
36
+ - .gitignore
37
+ - LICENSE
38
+ - README.rdoc
39
+ - Rakefile
40
+ - VERSION
41
+ - lib/hashie.rb
42
+ - lib/hashie/dash.rb
43
+ - lib/hashie/hash.rb
44
+ - lib/hashie/hash_extensions.rb
45
+ - lib/hashie/mash.rb
46
+ - spec/hashie/dash_spec.rb
47
+ - spec/hashie/hash_spec.rb
48
+ - spec/hashie/mash_spec.rb
49
+ - spec/spec.opts
50
+ - spec/spec_helper.rb
51
+ has_rdoc: true
52
+ homepage: http://github.com/intridea/hashie
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --charset=UTF-8
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ requirements: []
73
+
74
+ rubyforge_project:
75
+ rubygems_version: 1.3.5
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: Your friendly neighborhood hash toolkit.
79
+ test_files:
80
+ - spec/hashie/dash_spec.rb
81
+ - spec/hashie/hash_spec.rb
82
+ - spec/hashie/mash_spec.rb
83
+ - spec/spec_helper.rb