keso 0.1.3

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