keso 0.1.3
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 +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +23 -0
- data/Rakefile +44 -0
- data/VERSION +1 -0
- data/keso.gemspec +72 -0
- data/lib/keso.rb +8 -0
- data/lib/realvar.rb +12 -0
- data/lib/values/attribute.rb +44 -0
- data/lib/values/heading.rb +125 -0
- data/lib/values/immutable_hash.rb +112 -0
- data/lib/values/immutable_set.rb +151 -0
- data/lib/values/relation.rb +455 -0
- data/lib/values/tuple.rb +149 -0
- data/spec/attribute_spec.rb +61 -0
- data/spec/heading_spec.rb +125 -0
- data/spec/immutable_hash_spec.rb +200 -0
- data/spec/immutable_set_spec.rb +163 -0
- data/spec/relation_spec.rb +358 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/tuple_spec.rb +155 -0
- metadata +107 -0
data/lib/values/tuple.rb
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
class Tuple
|
4
|
+
|
5
|
+
@hash = nil
|
6
|
+
|
7
|
+
def initialize *args
|
8
|
+
hash = ImmutableHash.new *args
|
9
|
+
@hash = ImmutableHash.new
|
10
|
+
@heading = Heading.new
|
11
|
+
hash.each do |name_or_attribute,value|
|
12
|
+
if name_or_attribute.is_a? Attribute
|
13
|
+
|
14
|
+
if value.is_a? Relation
|
15
|
+
throw "#{value} is not the same as #{name_or_attribute.type}" if value.heading != name_or_attribute.type
|
16
|
+
else
|
17
|
+
throw "#{value} is not the same as #{name_or_attribute.type}" if value.class != name_or_attribute.type
|
18
|
+
end
|
19
|
+
|
20
|
+
@heading = @heading.add(name_or_attribute)
|
21
|
+
@hash = @hash.add(name_or_attribute,value)
|
22
|
+
else
|
23
|
+
if value.is_a? Relation
|
24
|
+
@heading = @heading.add(Attribute.new(name_or_attribute,value.heading))
|
25
|
+
@hash = @hash.add(Attribute.new(name_or_attribute,value.heading),value)
|
26
|
+
else
|
27
|
+
@heading = @heading.add(Attribute.new(name_or_attribute,value.class))
|
28
|
+
@hash = @hash.add(Attribute.new(name_or_attribute,value.class),value)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def count
|
35
|
+
@hash.count
|
36
|
+
end
|
37
|
+
|
38
|
+
def heading
|
39
|
+
@heading
|
40
|
+
end
|
41
|
+
|
42
|
+
def [] attribute_name
|
43
|
+
if attribute_name.is_a? String
|
44
|
+
@hash[self.heading[attribute_name]]
|
45
|
+
elsif attribute_name.is_a? Attribute
|
46
|
+
@hash[attribute_name]
|
47
|
+
elsif attribute_name.is_a? Symbol
|
48
|
+
@hash[self.heading[attribute_name.to_s]]
|
49
|
+
else
|
50
|
+
throw "What should i do with this ? attribute_name=\"#{attribute_name.inspect}\""
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def each &block
|
56
|
+
@hash.each do |key,value|
|
57
|
+
block.call key,value
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def add *values
|
62
|
+
|
63
|
+
if values.length == 1 and values[0].is_a? Tuple
|
64
|
+
to_return = self
|
65
|
+
values[0].each do |attribute,value|
|
66
|
+
to_return = to_return.add(attribute,value)
|
67
|
+
end
|
68
|
+
|
69
|
+
to_return
|
70
|
+
else
|
71
|
+
if values[0].is_a? Attribute
|
72
|
+
throw "already exists with this name" unless self.heading[values[0].name].nil?
|
73
|
+
elsif values[0].is_a? String
|
74
|
+
throw "already exists with this name" unless self.heading[values[0]].nil?
|
75
|
+
end
|
76
|
+
Tuple.new(@hash.add(*values))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def hash
|
81
|
+
@hash.hash
|
82
|
+
end
|
83
|
+
|
84
|
+
def rename from,to
|
85
|
+
throw "Missing from" if self[from].nil?
|
86
|
+
throw "to already exists" unless self[to].nil?
|
87
|
+
|
88
|
+
to_return = Tuple.new()
|
89
|
+
to_return._heading = @heading.rename(from,to)
|
90
|
+
to_return._inner_hash = @hash.delete(self.heading[from]).add(Attribute.new(to,self.heading[from].type) ,self[from])
|
91
|
+
|
92
|
+
to_return
|
93
|
+
end
|
94
|
+
|
95
|
+
def remove *values
|
96
|
+
|
97
|
+
to_return = @hash
|
98
|
+
|
99
|
+
values.each do |attribute_or_name|
|
100
|
+
if attribute_or_name.is_a? Attribute
|
101
|
+
to_return = to_return.delete(attribute_or_name)
|
102
|
+
elsif attribute_or_name.is_a? Hash
|
103
|
+
attribute_or_name.each do |key,value|
|
104
|
+
to_return = to_return.delete(heading[key.to_s])
|
105
|
+
end
|
106
|
+
elsif attribute_or_name.is_a? Array
|
107
|
+
attribute_or_name.each do |name|
|
108
|
+
to_return = to_return.delete(heading[name.to_s])
|
109
|
+
end
|
110
|
+
else
|
111
|
+
to_return = to_return.delete(heading[attribute_or_name.to_s])
|
112
|
+
end
|
113
|
+
end
|
114
|
+
Tuple.new to_return
|
115
|
+
end
|
116
|
+
|
117
|
+
def eql? object
|
118
|
+
self == object
|
119
|
+
end
|
120
|
+
|
121
|
+
def == object
|
122
|
+
if object.equal?(self)
|
123
|
+
true
|
124
|
+
elsif !self.class.equal?(object.class)
|
125
|
+
false
|
126
|
+
else
|
127
|
+
self.inner_hash.eql?(object.inner_hash)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def method_missing name,&args
|
132
|
+
self[name.to_sym]
|
133
|
+
end
|
134
|
+
|
135
|
+
protected
|
136
|
+
|
137
|
+
def inner_hash
|
138
|
+
@hash
|
139
|
+
end
|
140
|
+
|
141
|
+
def _heading= value
|
142
|
+
@heading = value
|
143
|
+
end
|
144
|
+
|
145
|
+
def _inner_hash= value
|
146
|
+
@hash = value
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Attribute do
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
describe :new do
|
8
|
+
it 'creates a new attrbute with given name and class' do
|
9
|
+
Attribute.new(:name => :age, :type => Fixnum).type.should eql(Fixnum)
|
10
|
+
Attribute.new(:name => :age, :type => Fixnum).name.should eql('age')
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'creates a new attribute when given a symal as name and a value as type' do
|
14
|
+
Attribute.new(:name => :age, :type => 1).type.should eql(Fixnum)
|
15
|
+
Attribute.new(:name => :age, :type => "ueoau").type.should eql(String)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe :== do
|
20
|
+
it 'should return true when to attributes with the same name and type is compared' do
|
21
|
+
(Attribute.new(:name => :age, :type => Fixnum) == Attribute.new(:name => 'age', :type => Fixnum)).should be_true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe :eql? do
|
26
|
+
it 'should return true when to attributes with the same name and type is compared' do
|
27
|
+
(Attribute.new(:name => :age, :type => Fixnum).eql?(Attribute.new(:name => 'age', :type => Fixnum))).should be_true
|
28
|
+
|
29
|
+
person = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
30
|
+
Attribute.new(:name => :persons, :type => person.heading).should eql(Attribute.new(:name => :persons, :type => person.heading))
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'two diffrent heading types should not be equal' do
|
34
|
+
|
35
|
+
person = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29})).add(Tuple.new({:name => 'Emma',:age => 30}))
|
36
|
+
person_with_length = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29,:length => 155})).add(Tuple.new({:name => 'Emma',:age => 30, :length => 135}))
|
37
|
+
|
38
|
+
Attribute.new(:name => :persons, :type => person.heading).should_not eql(Attribute.new(:name => :persons, :type => person_with_length.heading))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe :hash do
|
43
|
+
it 'should return the same value for attributes that are equal' do
|
44
|
+
Attribute.new(:name => :age, :type => Fixnum).hash.should eql(Attribute.new(:name => 'age', :type => Fixnum).hash)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe :type do
|
49
|
+
it 'is a accesor to the type of the attribute' do
|
50
|
+
Attribute.new(:name => :age, :type => Fixnum).type.should eql(Fixnum)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe :name do
|
55
|
+
it 'is a accesor to the type of the attribute' do
|
56
|
+
Attribute.new(:name => :age, :type => Fixnum).name.should eql('age')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Heading do
|
4
|
+
|
5
|
+
describe :new do
|
6
|
+
it 'creates a new instance of heading with given attribute' do
|
7
|
+
Heading.new(Attribute.new(:name => 'a', :type => 1)).first.type.should eql(Fixnum)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'creates a new instance of heading with given name and class' do
|
11
|
+
Heading.new(:name => 'a', :type => Fixnum).first.type.should eql(Fixnum)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'creates a new instance of heading with given name and value' do
|
15
|
+
Heading.new(:name => 'a', :type => 1).first.type.should eql(Fixnum)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'throws an exception if given just a symbol' do
|
19
|
+
lambda{ Heading.new(:bla) }.should raise_error
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'creates a new empty heading' do
|
23
|
+
Heading.new.first.should be_nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe :eql? do
|
28
|
+
it 'returns true if two headings has the same attributes' do
|
29
|
+
Heading.new(:name => 'a', :type => 1).eql?(Heading.new(:name => 'a', :type => 1)).should be_true
|
30
|
+
Heading.new(:name => 'a', :type => 1).eql?(Heading.new(:name => 'b', :type => 1)).should be_false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe :hash do
|
35
|
+
it 'should return an integer related to this hash' do
|
36
|
+
Heading.new(:name => 'a', :type => 1).hash.should eql Heading.new(:name => 'a', :type => 1).hash
|
37
|
+
Heading.new(:name => 'a', :type => 1).hash.should_not eql Heading.new(:name => 'b', :type => 1).hash
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe :names do
|
42
|
+
it 'should return the names of the attributes in the heading' do
|
43
|
+
Heading.new(Attribute.new(:name => 'a', :type => Fixnum)).add(Attribute.new(:name => 'b', :type => Fixnum)).names.should eql(['a','b'])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe :add do
|
48
|
+
it 'accepts attributes or name value pares' do
|
49
|
+
Heading.new.add( Attribute.new(:name => 'a', :type => Fixnum)).first.type.should eql(Fixnum)
|
50
|
+
Heading.new.add(:name => 'a', :type => Fixnum).first.type.should eql(Fixnum)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should add return a heading with all the attributes of the supplied heading' do
|
54
|
+
Heading.new.add( Attribute.new(:name => 'a', :type => Fixnum)).add(Heading.new(:name => 'b', :type => Fixnum)).should eql(Heading.new(:name => 'a', :type => 1).add(Attribute.new(:name => 'b', :type => Fixnum)))
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
it 'only accepts attributes or name value pares' do
|
59
|
+
lambda{ Heading.new.add(:test,:test) }.should raise_error
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'returns a new instance' do
|
63
|
+
h = Heading.new
|
64
|
+
h.add(:name => 'a', :type => Fixnum).should_not eql(h)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'it should accept a heading as a type' do
|
68
|
+
heading_type = Heading.new(:name => 'name', :type => String)
|
69
|
+
|
70
|
+
Heading.new(:name => 'a', :type => 1).add(:name => 'Names', :type => heading_type)
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe :[] do
|
76
|
+
it 'returns the attribute for the given attribute name' do
|
77
|
+
Heading.new.add(:name => 'a', :type => Fixnum)[:a].should eql(Attribute.new(:name => 'a', :type => Fixnum))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe :rename do
|
82
|
+
it 'changes the name of a current attribute' do
|
83
|
+
Heading.new.add(:name => 'name', :type => String).rename(:name ,:title).should eql(Heading.new.add(:name => :title,:type => String))
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should throw an exception' do
|
87
|
+
lambda { Heading.new.add(:name => :name,:type => String).add(:name => :age,:type => Fixnum).rename(:age ,:name) }.should raise_error(ArgumentError)
|
88
|
+
lambda { Heading.new.add(:name => :age,:type => Fixnum).rename(:year ,:some_other_year) }.should raise_error(ArgumentError)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
describe :remove do
|
94
|
+
it 'removes given attribute' do
|
95
|
+
Heading.new(Attribute.new(:name => 'a', :type => 1)).remove(Attribute.new(:name => 'a', :type => 1)).count.should eql(0)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'removes given attribute name' do
|
99
|
+
Heading.new(Attribute.new(:name => 'a', :type => 1)).remove(:a).count.should eql(0)
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'returns a new instance' do
|
103
|
+
h = Heading.new Attribute.new(:name => 'a', :type => 1)
|
104
|
+
h.remove(Attribute.new(:name => 'a', :type => 1)).should_not eql(h)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
describe :each do
|
110
|
+
it 'iterates over all the attributes in the heading' do
|
111
|
+
|
112
|
+
|
113
|
+
count = 0
|
114
|
+
Heading.new.add(Attribute.new(:name => 'a', :type => Fixnum)).add(Heading.new(:name => 'b', :type => Fixnum)).each do |attribute|
|
115
|
+
count += 1
|
116
|
+
end
|
117
|
+
|
118
|
+
count.should eql(2)
|
119
|
+
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe ImmutableHash do
|
4
|
+
|
5
|
+
describe :new do
|
6
|
+
it 'takes a ruby hash as argument and returns a ImmutableHash with entries from the supplied hash' do
|
7
|
+
ih = ImmutableHash.new({:a => :b})
|
8
|
+
ih.should be_an_instance_of ImmutableHash
|
9
|
+
ih[:a].should eql(:b)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns a ImmutableHash' do
|
13
|
+
ImmutableHash.new.should be_an_instance_of ImmutableHash
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
describe :keys do
|
19
|
+
it 'returns an array of all keys' do
|
20
|
+
ImmutableHash.new({:a => :b}).keys.should eql([:a])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe :values do
|
25
|
+
it 'returns an array of all values' do
|
26
|
+
ImmutableHash.new({:a => :b}).values.should eql([:b])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe :size do
|
31
|
+
it 'should return the amount of entries in the hash' do
|
32
|
+
ImmutableHash.new({:a => :b}).size.should eql(1)
|
33
|
+
ImmutableHash.new({:a => :b,:c => :b}).size.should eql(2)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe :count do
|
38
|
+
it 'should return the amount of entries in the hash' do
|
39
|
+
ImmutableHash.new({:a => :b}).size.should eql(1)
|
40
|
+
ImmutableHash.new({:a => :b,:c => :b}).size.should eql(2)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe :[] do
|
45
|
+
it 'returns nil or the value pointed to by the key' do
|
46
|
+
ImmutableHash.new({:a => :b})[:a].should eql(:b)
|
47
|
+
ImmutableHash.new({:a => :b})[:c].should be_nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe :add do
|
52
|
+
it 'creates a new hash with all the entries plus a new of from the key and value parameters' do
|
53
|
+
ih1 = ImmutableHash.new({:a => :b})
|
54
|
+
ih2 = ih1.add :c,:d
|
55
|
+
ih2.should_not eql(ih1)
|
56
|
+
ih2[:c].should eql(:d)
|
57
|
+
ih1[:c].should be_nil
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'can take a hash and returns a new imutable instance with all the current entries plus the ones from the hash' do
|
61
|
+
ih1 = ImmutableHash.new({:a => :b})
|
62
|
+
ih2 = ih1.add({:e => :f,:c => :d})
|
63
|
+
ih2.count.should eql(3)
|
64
|
+
ih2.should_not eql(ih1)
|
65
|
+
ih2[:c].should eql(:d)
|
66
|
+
ih1[:c].should be_nil
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'can take another imutable hash and returns a new instance with the entries of both' do
|
70
|
+
ih1 = ImmutableHash.new({:a => :b})
|
71
|
+
ih2 = ih1.add ImmutableHash.new({:e => :f,:c => :d})
|
72
|
+
ih2.count.should eql(3)
|
73
|
+
ih2.should_not eql(ih1)
|
74
|
+
ih2[:c].should eql(:d)
|
75
|
+
ih1[:c].should be_nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe :set do
|
80
|
+
it 'creates a new hash with all the entries plus a new of from the key and value parameters' do
|
81
|
+
ih1 = ImmutableHash.new({:a => :b})
|
82
|
+
ih2 = ih1.set :c,:d
|
83
|
+
ih2.should_not eql(ih1)
|
84
|
+
ih2[:c].should eql(:d)
|
85
|
+
ih1[:c].should be_nil
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'can take a hash and returns a new imutable instance with all the current entries plus the ones from the hash' do
|
89
|
+
ih1 = ImmutableHash.new({:a => :b})
|
90
|
+
ih2 = ih1.set({:e => :f,:c => :d})
|
91
|
+
ih2.count.should eql(3)
|
92
|
+
ih2.should_not eql(ih1)
|
93
|
+
ih2[:c].should eql(:d)
|
94
|
+
ih1[:c].should be_nil
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'can take another imutable hash and returns a new instance with the entries of both' do
|
98
|
+
ih1 = ImmutableHash.new({:a => :b})
|
99
|
+
ih2 = ih1.set ImmutableHash.new({:e => :f,:c => :d})
|
100
|
+
ih2.count.should eql(3)
|
101
|
+
ih2.should_not eql(ih1)
|
102
|
+
ih2[:c].should eql(:d)
|
103
|
+
ih1[:c].should be_nil
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe :+ do
|
108
|
+
it 'creates a new hash with all the entries plus a new of from the key and value parameters' do
|
109
|
+
ih1 = ImmutableHash.new({:a => :b})
|
110
|
+
ih2 = ih1.add :c,:d
|
111
|
+
ih2.should_not eql(ih1)
|
112
|
+
ih2[:c].should eql(:d)
|
113
|
+
ih1[:c].should be_nil
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'can take a hash and returns a new imutable instance with all the current entries plus the ones from the hash' do
|
117
|
+
ih1 = ImmutableHash.new({:a => :b})
|
118
|
+
ih2 = ih1.add({:e => :f,:c => :d})
|
119
|
+
ih2.count.should eql(3)
|
120
|
+
ih2.should_not eql(ih1)
|
121
|
+
ih2[:c].should eql(:d)
|
122
|
+
ih1[:c].should be_nil
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'can take another imutable hash and returns a new instance with the entries of both' do
|
126
|
+
ih1 = ImmutableHash.new({:a => :b})
|
127
|
+
ih2 = ih1.add ImmutableHash.new({:e => :f,:c => :d})
|
128
|
+
ih2.count.should eql(3)
|
129
|
+
ih2.should_not eql(ih1)
|
130
|
+
ih2[:c].should eql(:d)
|
131
|
+
ih1[:c].should be_nil
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe :delete do
|
136
|
+
it 'returns a new instance of ImmutableHash without the supplied key' do
|
137
|
+
ImmutableHash.new({:a => :b}).delete(:a).count.should eql(0)
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'returns a new instance of ImmutableHash without the supplied keys' do
|
141
|
+
ImmutableHash.new({:a => :b,:b => :c}).delete([:a,:b]).count.should eql(0)
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'returns a new instance of ImmutableHash without the entries from the supplied hash' do
|
145
|
+
ImmutableHash.new({:a => :b,:b => :c}).delete({:b => :b,:a => :b}).count.should eql(1)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'returns a new instance of ImmutableHash without the entries from the supplied imutable hash' do
|
149
|
+
ImmutableHash.new({:a => :b,:b => :c}).delete(ImmutableHash.new({:b => :b,:a => :b})).count.should eql(1)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe :== do
|
154
|
+
it 'retuns true if both instances are equal' do
|
155
|
+
(ImmutableHash.new({:a => :b,:b => :c}) == ImmutableHash.new({:a => :b,:b => :c})).should be_true
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe :eql? do
|
160
|
+
it 'returns true if the supplied value is eql to this one' do
|
161
|
+
(ImmutableHash.new({:a => :b,:b => :c}).eql?(ImmutableHash.new({:a => :b,:b => :c}))).should be_true
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe :hash do
|
166
|
+
it 'always returns the same integer for the same value' do
|
167
|
+
ImmutableHash.new({:a => :b,:b => :c}).hash.should eql(ImmutableHash.new({:a => :b,:b => :c}).hash)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
describe :- do
|
172
|
+
it 'returns a new instance of ImmutableHash without the supplied key' do
|
173
|
+
(ImmutableHash.new({:a => :b}) - :a).count.should eql(0)
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'returns a new instance of ImmutableHash without the supplied keys' do
|
177
|
+
(ImmutableHash.new({:a => :b,:b => :c}) - [:a,:b]).count.should eql(0)
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'returns a new instance of ImmutableHash without the entries from the supplied hash' do
|
181
|
+
(ImmutableHash.new({:a => :b,:b => :c}) - {:b => :b,:a => :b}).count.should eql(1)
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'returns a new instance of ImmutableHash without the entries from the supplied imutable hash' do
|
185
|
+
(ImmutableHash.new({:a => :b,:b => :c}) - ImmutableHash.new({:b => :b,:a => :b})).count.should eql(1)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe :each do
|
190
|
+
it 'takes a code block that and for each key => value it yiels' do
|
191
|
+
hash = {}
|
192
|
+
ImmutableHash.new({:a => :b,:b => :c}).each do |key,value|
|
193
|
+
hash[key] = value;
|
194
|
+
end
|
195
|
+
|
196
|
+
hash.should eql({:a => :b,:b => :c})
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|