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.
@@ -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