zerobearing-hashie 0.1.9

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,6 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ *.gem
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,81 @@
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.email = 'abc@def.com'
57
+ p.occupation # => 'Rubyist'
58
+ p.email # => 'abc@def.com'
59
+ p[:awesome] # => NoMethodError
60
+ p[:occupation] # => 'Rubyist'
61
+
62
+ p = Person.new(:name => "Bob")
63
+ p.name # => 'Bob'
64
+ p.occupation # => 'Rubyist'
65
+
66
+
67
+ == Note on Patches/Pull Requests
68
+
69
+ * Fork the project.
70
+ * Make your feature addition or bug fix.
71
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
72
+ * 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)
73
+ * Send me a pull request. Bonus points for topic branches.
74
+
75
+ == Authors
76
+
77
+ * Michael Bleigh
78
+
79
+ == Copyright
80
+
81
+ 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.9
data/hashie.gemspec ADDED
@@ -0,0 +1,63 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{zerobearing-hashie}
8
+ s.version = "0.1.9"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Michael Bleigh"]
12
+ s.date = %q{2010-01-20}
13
+ s.description = %q{Hashie is a small collection of tools that make hashes more powerful. Currently includes Mash (Mocking Hash) and Dash (Discrete Hash).}
14
+ s.email = %q{michael@intridea.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "hashie.gemspec",
27
+ "lib/hashie.rb",
28
+ "lib/hashie/dash.rb",
29
+ "lib/hashie/hash.rb",
30
+ "lib/hashie/hash_extensions.rb",
31
+ "lib/hashie/mash.rb",
32
+ "spec/hashie/dash_spec.rb",
33
+ "spec/hashie/hash_spec.rb",
34
+ "spec/hashie/mash_spec.rb",
35
+ "spec/spec.opts",
36
+ "spec/spec_helper.rb"
37
+ ]
38
+ s.homepage = %q{http://github.com/intridea/hashie}
39
+ s.rdoc_options = ["--charset=UTF-8"]
40
+ s.require_paths = ["lib"]
41
+ s.rubygems_version = %q{1.3.5}
42
+ s.summary = %q{Your friendly neighborhood hash toolkit.}
43
+ s.test_files = [
44
+ "spec/hashie/dash_spec.rb",
45
+ "spec/hashie/hash_spec.rb",
46
+ "spec/hashie/mash_spec.rb",
47
+ "spec/spec_helper.rb"
48
+ ]
49
+
50
+ if s.respond_to? :specification_version then
51
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
52
+ s.specification_version = 3
53
+
54
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
55
+ s.add_development_dependency(%q<rspec>, [">= 0"])
56
+ else
57
+ s.add_dependency(%q<rspec>, [">= 0"])
58
+ end
59
+ else
60
+ s.add_dependency(%q<rspec>, [">= 0"])
61
+ end
62
+ end
63
+
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,108 @@
1
+ require 'hashie/hash'
2
+
3
+ module Hashie
4
+ include Hashie::PrettyInspect
5
+ # A Dash is a 'defined' or 'discrete' Hash, that is, a Hash
6
+ # that has a set of defined keys that are accessible (with
7
+ # optional defaults) and only those keys may be set or read.
8
+ #
9
+ # Dashes are useful when you need to create a very simple
10
+ # lightweight data object that needs even fewer options and
11
+ # resources than something like a DataMapper resource.
12
+ #
13
+ # It is preferrable to a Struct because of the in-class
14
+ # API for defining properties as well as per-property defaults.
15
+ class Dash < Hashie::Hash
16
+ include Hashie::PrettyInspect
17
+ alias_method :to_s, :inspect
18
+
19
+ # Defines a property on the Dash. Options are
20
+ # as follows:
21
+ #
22
+ # * <tt>:default</tt> - Specify a default value for this property,
23
+ # to be returned before a value is set on the property in a new
24
+ # Dash.
25
+ #
26
+ def self.property(property_name, options = {})
27
+ property_name = property_name.to_sym
28
+
29
+ (@properties ||= []) << property_name
30
+ (@defaults ||= {})[property_name] = options.delete(:default)
31
+
32
+ class_eval <<-RUBY
33
+ def #{property_name}
34
+ self[:#{property_name}]
35
+ end
36
+
37
+ def #{property_name}=(val)
38
+ self[:#{property_name}] = val
39
+ end
40
+ RUBY
41
+ end
42
+
43
+ # Get a String array of the currently defined
44
+ # properties on this Dash.
45
+ def self.properties
46
+ properties = []
47
+ ancestors.each do |elder|
48
+ if elder.instance_variable_defined?("@properties")
49
+ properties << elder.instance_variable_get("@properties")
50
+ end
51
+ end
52
+
53
+ properties.flatten.map{|p| p.to_s}
54
+ end
55
+
56
+ # Check to see if the specified property has already been
57
+ # defined.
58
+ def self.property?(prop)
59
+ properties.include?(prop.to_s)
60
+ end
61
+
62
+ # The default values that have been set for this Dash
63
+ def self.defaults
64
+ properties = {}
65
+ ancestors.each do |elder|
66
+ if elder.instance_variable_defined?("@defaults")
67
+ properties.merge! elder.instance_variable_get("@defaults")
68
+ end
69
+ end
70
+
71
+ properties
72
+ end
73
+
74
+ # You may initialize a Dash with an attributes hash
75
+ # just like you would many other kinds of data objects.
76
+ def initialize(attributes = {})
77
+ self.class.properties.each do |prop|
78
+ self.send("#{prop}=", self.class.defaults[prop.to_sym])
79
+ end
80
+
81
+ attributes.each_pair do |att, value|
82
+ self.send("#{att}=", value)
83
+ end
84
+ end
85
+
86
+ # Retrieve a value from the Dash (will return the
87
+ # property's default value if it hasn't been set).
88
+ def [](property)
89
+ super(property.to_sym) if property_exists? property
90
+ end
91
+
92
+ # Set a value on the Dash in a Hash-like way. Only works
93
+ # on pre-existing properties.
94
+ def []=(property, value)
95
+ super if property_exists? property
96
+ end
97
+
98
+ private
99
+ # Raises an NoMethodError if the property doesn't exist
100
+ #
101
+ def property_exists?(property)
102
+ unless self.class.property?(property.to_sym)
103
+ raise NoMethodError, "The property '#{property}' is not defined for this Dash."
104
+ end
105
+ true
106
+ end
107
+ end
108
+ 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,49 @@
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
+ unless String === k
16
+ self[k.to_s] = self.delete(k)
17
+ end
18
+ end
19
+ self
20
+ end
21
+
22
+ # Convert all of the keys of a Hash
23
+ # to their string representations.
24
+ def hashie_stringify_keys
25
+ self.dup.stringify_keys!
26
+ end
27
+
28
+ # Convert this hash into a Mash
29
+ def to_mash
30
+ Hashie::Mash.new(self)
31
+ end
32
+ end
33
+
34
+ module PrettyInspect
35
+ def self.included(base)
36
+ base.send :alias_method, :hash_inspect, :inspect
37
+ base.send :alias_method, :inspect, :hashie_inspect
38
+ end
39
+
40
+ def hashie_inspect
41
+ ret = "<##{self.class.to_s}"
42
+ stringify_keys.keys.sort.each do |key|
43
+ ret << " #{key}=#{self[key].inspect}"
44
+ end
45
+ ret << ">"
46
+ ret
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,166 @@
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
+ include Hashie::PrettyInspect
45
+ alias_method :to_s, :inspect
46
+
47
+ # If you pass in an existing hash, it will
48
+ # convert it to a Mash including recursively
49
+ # descending into arrays and hashes, converting
50
+ # them as well.
51
+ def initialize(source_hash = nil, default = nil, &blk)
52
+ deep_update(source_hash) if source_hash
53
+ default ? super(default) : super(&blk)
54
+ end
55
+
56
+ class << self; alias [] new; end
57
+
58
+ def id #:nodoc:
59
+ key?("id") ? self["id"] : super
60
+ end
61
+
62
+ alias_method :regular_reader, :[]
63
+ alias_method :regular_writer, :[]=
64
+
65
+ # Retrieves an attribute set in the Mash. Will convert
66
+ # any key passed in to a string before retrieving.
67
+ def [](key)
68
+ regular_reader(convert_key(key))
69
+ end
70
+
71
+ # Sets an attribute in the Mash. Key will be converted to
72
+ # a string before it is set, and Hashes will be converted
73
+ # into Mashes for nesting purposes.
74
+ def []=(key,value) #:nodoc:
75
+ regular_writer(convert_key(key), convert_value(value))
76
+ end
77
+
78
+ # This is the bang method reader, it will return a new Mash
79
+ # if there isn't a value already assigned to the key requested.
80
+ def initializing_reader(key)
81
+ ck = convert_key(key)
82
+ regular_writer(ck, Hashie::Mash.new) unless key?(ck)
83
+ regular_reader(ck)
84
+ end
85
+
86
+ alias_method :regular_dup, :dup
87
+ # Duplicates the current mash as a new mash.
88
+ def dup
89
+ Mash.new(self, self.default)
90
+ end
91
+
92
+ def key?(key)
93
+ super(convert_key(key))
94
+ end
95
+
96
+ # Performs a deep_update on a duplicate of the
97
+ # current mash.
98
+ def deep_merge(other_hash)
99
+ dup.deep_merge!(other_hash)
100
+ end
101
+
102
+ # Recursively merges this mash with the passed
103
+ # in hash, merging each hash in the hierarchy.
104
+ def deep_update(other_hash)
105
+ other_hash.each_pair do |k,v|
106
+ regular_writer(convert_key(k), convert_value(other_hash[k], true))
107
+ end
108
+ self
109
+ end
110
+ alias_method :deep_merge!, :deep_update
111
+ alias_method :update, :deep_update
112
+ alias_method :merge!, :update
113
+
114
+ # Converts a mash back to a hash (with stringified keys)
115
+ def to_hash
116
+ h = Hash.new(default).merge(self)
117
+ h.each {|key,val| h[key] = convert_value_to_hash(val)}
118
+ h
119
+ end
120
+
121
+ def method_missing(method_name, *args)
122
+ return self[method_name] if key?(method_name)
123
+ match = method_name.to_s.match(/(.*?)([?=!]?)$/)
124
+ case match[2]
125
+ when "="
126
+ self[match[1]] = args.first
127
+ when "?"
128
+ key?(match[1])
129
+ when "!"
130
+ initializing_reader(match[1])
131
+ else
132
+ default(method_name)
133
+ end
134
+ end
135
+
136
+ protected
137
+
138
+ def convert_key(key) #:nodoc:
139
+ key.to_s
140
+ end
141
+
142
+ #------------------
143
+ def convert_value_to_hash(val)
144
+ case val
145
+ when Mash
146
+ val.to_hash
147
+ when Array
148
+ val.collect(&:to_hash)
149
+ else
150
+ val
151
+ end
152
+ end
153
+
154
+ def convert_value(val, duping=false) #:nodoc:
155
+ case val
156
+ when ::Hash
157
+ val = val.dup if duping
158
+ self.class.new(val)
159
+ when Array
160
+ val.collect{ |e| convert_value(e) }
161
+ else
162
+ val
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,103 @@
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
+ class Subclassed < DashTest
10
+ property :last_name
11
+ end
12
+
13
+ describe Hashie::Dash do
14
+ it 'should be a subclass of Hashie::Hash' do
15
+ (Hashie::Dash < Hash).should be_true
16
+ end
17
+
18
+ it '#inspect should be ok!' do
19
+ dash = DashTest.new
20
+ dash.email = "abd@abc.com"
21
+ dash.inspect.should == "<#DashTest count=0 email=\"abd@abc.com\" first_name=nil>"
22
+ end
23
+
24
+ describe ' creating properties' do
25
+ it 'should add the property to the list' do
26
+ DashTest.property :not_an_att
27
+ DashTest.properties.include?('not_an_att').should be_true
28
+ end
29
+
30
+ it 'should create a method for reading the property' do
31
+ DashTest.new.respond_to?(:first_name).should be_true
32
+ end
33
+
34
+ it 'should create a method for writing the property' do
35
+ DashTest.new.respond_to?(:first_name=).should be_true
36
+ end
37
+ end
38
+
39
+ describe 'reading properties' do
40
+ it 'should raise an error when reading a non-existent property' do
41
+ lambda{@dash['abc']}.should raise_error(NoMethodError)
42
+ end
43
+ end
44
+
45
+ describe ' writing to properties' do
46
+ before do
47
+ @dash = DashTest.new
48
+ end
49
+
50
+ it 'should not be able to write to a non-existent property using []=' do
51
+ lambda{@dash['abc'] = 123}.should raise_error(NoMethodError)
52
+ end
53
+
54
+ it 'should be able to write to an existing property using []=' do
55
+ lambda{@dash['first_name'] = 'Bob'}.should_not raise_error
56
+ end
57
+
58
+ it 'should be able to read/write to an existing property using a method call' do
59
+ @dash.first_name = 'Franklin'
60
+ @dash.first_name.should == 'Franklin'
61
+ end
62
+ end
63
+
64
+ describe ' initializing with a Hash' do
65
+ it 'should not be able to initialize non-existent properties' do
66
+ lambda{DashTest.new(:bork => 'abc')}.should raise_error(NoMethodError)
67
+ end
68
+
69
+ it 'should set properties that it is able to' do
70
+ DashTest.new(:first_name => 'Michael').first_name.should == 'Michael'
71
+ end
72
+ end
73
+
74
+ describe ' defaults' do
75
+ before do
76
+ @dash = DashTest.new
77
+ end
78
+
79
+ it 'should return the default value for defaulted' do
80
+ DashTest.property :defaulted, :default => 'abc'
81
+ DashTest.new.defaulted.should == 'abc'
82
+ end
83
+ end
84
+ end
85
+
86
+ describe Subclassed do
87
+ it "should inherit all properties from DashTest" do
88
+ Subclassed.properties.size.should == 6
89
+ end
90
+
91
+ it "should inherit all defaults from DashTest" do
92
+ Subclassed.defaults.size.should == 6
93
+ end
94
+
95
+ it "should init without raising" do
96
+ lambda { Subclassed.new }.should_not raise_error
97
+ lambda { Subclassed.new(:first_name => 'Michael') }.should_not raise_error
98
+ end
99
+
100
+ it "should share defaults from DashTest" do
101
+ Subclassed.new.count.should == 0
102
+ end
103
+ 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,139 @@
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
+ it "should not convert the type of Hashie::Mashes childs to Hashie::Mash" do
78
+ class MyMash < Hashie::Mash
79
+ end
80
+
81
+ record = MyMash.new
82
+ record.son = MyMash.new
83
+ record.son.class.should == MyMash
84
+ end
85
+
86
+ context "#initialize" do
87
+ it "should convert an existing hash to a Hashie::Mash" do
88
+ converted = Hashie::Mash.new({:abc => 123, :name => "Bob"})
89
+ converted.abc.should == 123
90
+ converted.name.should == "Bob"
91
+ end
92
+
93
+ it "should convert hashes recursively into Hashie::Mashes" do
94
+ converted = Hashie::Mash.new({:a => {:b => 1, :c => {:d => 23}}})
95
+ converted.a.is_a?(Hashie::Mash).should be_true
96
+ converted.a.b.should == 1
97
+ converted.a.c.d.should == 23
98
+ end
99
+
100
+ it "should convert hashes in arrays into Hashie::Mashes" do
101
+ converted = Hashie::Mash.new({:a => [{:b => 12}, 23]})
102
+ converted.a.first.b.should == 12
103
+ converted.a.last.should == 23
104
+ end
105
+
106
+ it "should convert an existing Hashie::Mash into a Hashie::Mash" do
107
+ initial = Hashie::Mash.new(:name => 'randy', :address => {:state => 'TX'})
108
+ copy = Hashie::Mash.new(initial)
109
+ initial.name.should == copy.name
110
+ initial.object_id.should_not == copy.object_id
111
+ copy.address.state.should == 'TX'
112
+ copy.address.state = 'MI'
113
+ initial.address.state.should == 'TX'
114
+ copy.address.object_id.should_not == initial.address.object_id
115
+ end
116
+
117
+ it "should accept a default block" do
118
+ initial = Hashie::Mash.new { |h,i| h[i] = []}
119
+ initial.default_proc.should_not be_nil
120
+ initial.default.should be_nil
121
+ initial.test.should == []
122
+ initial.test?.should be_true
123
+ end
124
+ end
125
+
126
+ context "#to_hash" do
127
+ it "convert to hash (deeply)" do
128
+ @mash.test = 1
129
+ @mash.a = Hashie::Mash.new(:name => "testa")
130
+ @mash.b = [{:c => 1}, {:d => {:name => "hello"}}]
131
+ h = @mash.to_hash
132
+ h['test'].should == 1
133
+ h['a']['name'].should == "testa"
134
+ h['b'][0]['c'].should == 1
135
+ h['b'][1]['d']['name'].should == "hello"
136
+ end
137
+ end
138
+
139
+ 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,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zerobearing-hashie
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.9
5
+ platform: ruby
6
+ authors:
7
+ - Michael Bleigh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-20 00:00:00 -08: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
+ - hashie.gemspec
42
+ - lib/hashie.rb
43
+ - lib/hashie/dash.rb
44
+ - lib/hashie/hash.rb
45
+ - lib/hashie/hash_extensions.rb
46
+ - lib/hashie/mash.rb
47
+ - spec/hashie/dash_spec.rb
48
+ - spec/hashie/hash_spec.rb
49
+ - spec/hashie/mash_spec.rb
50
+ - spec/spec.opts
51
+ - spec/spec_helper.rb
52
+ has_rdoc: true
53
+ homepage: http://github.com/intridea/hashie
54
+ licenses: []
55
+
56
+ post_install_message:
57
+ rdoc_options:
58
+ - --charset=UTF-8
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ requirements: []
74
+
75
+ rubyforge_project:
76
+ rubygems_version: 1.3.5
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: Your friendly neighborhood hash toolkit.
80
+ test_files:
81
+ - spec/hashie/dash_spec.rb
82
+ - spec/hashie/hash_spec.rb
83
+ - spec/hashie/mash_spec.rb
84
+ - spec/spec_helper.rb