hashie 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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