alf 0.9.0
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/CHANGELOG.md +5 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +42 -0
- data/LICENCE.md +22 -0
- data/Manifest.txt +15 -0
- data/README.md +769 -0
- data/Rakefile +23 -0
- data/TODO.md +26 -0
- data/alf.gemspec +191 -0
- data/alf.noespec +30 -0
- data/bin/alf +31 -0
- data/examples/autonum.alf +6 -0
- data/examples/cities.rash +4 -0
- data/examples/clip.alf +3 -0
- data/examples/compact.alf +2 -0
- data/examples/database.alf +6 -0
- data/examples/defaults.alf +3 -0
- data/examples/extend.alf +3 -0
- data/examples/group.alf +3 -0
- data/examples/intersect.alf +4 -0
- data/examples/join.alf +2 -0
- data/examples/minus.alf +8 -0
- data/examples/nest.alf +2 -0
- data/examples/nulls.rash +3 -0
- data/examples/parts.rash +6 -0
- data/examples/project.alf +2 -0
- data/examples/quota.alf +4 -0
- data/examples/rename.alf +3 -0
- data/examples/restrict.alf +2 -0
- data/examples/runall.sh +26 -0
- data/examples/schema.yaml +28 -0
- data/examples/sort.alf +4 -0
- data/examples/summarize.alf +16 -0
- data/examples/suppliers.rash +5 -0
- data/examples/supplies.rash +12 -0
- data/examples/ungroup.alf +4 -0
- data/examples/union.alf +3 -0
- data/examples/unnest.alf +4 -0
- data/examples/with.alf +23 -0
- data/lib/alf.rb +2984 -0
- data/lib/alf/loader.rb +1 -0
- data/lib/alf/renderer/text.rb +153 -0
- data/lib/alf/renderer/yaml.rb +22 -0
- data/lib/alf/version.rb +14 -0
- data/spec/aggregator_spec.rb +62 -0
- data/spec/alf_spec.rb +47 -0
- data/spec/assumptions_spec.rb +15 -0
- data/spec/environment/explicit_spec.rb +15 -0
- data/spec/environment/folder_spec.rb +30 -0
- data/spec/examples_spec.rb +26 -0
- data/spec/lispy_spec.rb +23 -0
- data/spec/operator/command_methods_spec.rb +38 -0
- data/spec/operator/non_relational/autonum_spec.rb +61 -0
- data/spec/operator/non_relational/clip_spec.rb +49 -0
- data/spec/operator/non_relational/compact/buffer_based.rb +30 -0
- data/spec/operator/non_relational/compact/sort_based_spec.rb +30 -0
- data/spec/operator/non_relational/compact_spec.rb +38 -0
- data/spec/operator/non_relational/defaults_spec.rb +55 -0
- data/spec/operator/non_relational/sort_spec.rb +66 -0
- data/spec/operator/relational/extend_spec.rb +34 -0
- data/spec/operator/relational/group_spec.rb +54 -0
- data/spec/operator/relational/intersect_spec.rb +58 -0
- data/spec/operator/relational/join/hash_based_spec.rb +63 -0
- data/spec/operator/relational/minus_spec.rb +56 -0
- data/spec/operator/relational/nest_spec.rb +32 -0
- data/spec/operator/relational/project_spec.rb +65 -0
- data/spec/operator/relational/quota_spec.rb +44 -0
- data/spec/operator/relational/rename_spec.rb +32 -0
- data/spec/operator/relational/restrict_spec.rb +56 -0
- data/spec/operator/relational/summarize/sort_based_spec.rb +31 -0
- data/spec/operator/relational/summarize_spec.rb +41 -0
- data/spec/operator/relational/ungroup_spec.rb +35 -0
- data/spec/operator/relational/union_spec.rb +35 -0
- data/spec/operator/relational/unnest_spec.rb +32 -0
- data/spec/reader/alf_file_spec.rb +15 -0
- data/spec/reader/input.rb +2 -0
- data/spec/reader/rash_spec.rb +31 -0
- data/spec/reader_spec.rb +27 -0
- data/spec/renderer/text/cell_spec.rb +34 -0
- data/spec/renderer/text/row_spec.rb +30 -0
- data/spec/renderer/text/table_spec.rb +39 -0
- data/spec/renderer_spec.rb +42 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/tools/ordering_key_spec.rb +81 -0
- data/spec/tools/projection_key_spec.rb +83 -0
- data/spec/tools/tools_spec.rb +25 -0
- data/spec/tools/tuple_handle_spec.rb +78 -0
- data/tasks/debug_mail.rake +78 -0
- data/tasks/debug_mail.txt +13 -0
- data/tasks/gem.rake +68 -0
- data/tasks/spec_test.rake +79 -0
- data/tasks/unit_test.rake +77 -0
- data/tasks/yard.rake +51 -0
- metadata +282 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Operator::Relational
|
4
|
+
describe Union do
|
5
|
+
|
6
|
+
let(:operator_class){ Union }
|
7
|
+
it_should_behave_like("An operator class")
|
8
|
+
|
9
|
+
let(:left) {[
|
10
|
+
{:city => 'London'},
|
11
|
+
{:city => 'Paris'},
|
12
|
+
{:city => 'Paris'}
|
13
|
+
]}
|
14
|
+
|
15
|
+
let(:right) {[
|
16
|
+
{:city => 'Oslo'},
|
17
|
+
{:city => 'Paris'}
|
18
|
+
]}
|
19
|
+
|
20
|
+
let(:operator){ Union.run([]) }
|
21
|
+
subject{ operator.to_a }
|
22
|
+
|
23
|
+
describe "when applied on non disjoint sets" do
|
24
|
+
before{ operator.datasets = [left, right] }
|
25
|
+
let(:expected){[
|
26
|
+
{:city => 'London'},
|
27
|
+
{:city => 'Paris'},
|
28
|
+
{:city => 'Oslo'}
|
29
|
+
]}
|
30
|
+
it { should == expected }
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Operator::Relational
|
4
|
+
describe Unnest do
|
5
|
+
|
6
|
+
let(:operator_class){ Unnest }
|
7
|
+
it_should_behave_like("An operator class")
|
8
|
+
|
9
|
+
let(:input) {[
|
10
|
+
{:nested => {:a => "a", :b => "b"}, :c => "c"}
|
11
|
+
]}
|
12
|
+
|
13
|
+
let(:expected) {[
|
14
|
+
{:a => "a", :b => "b", :c => "c"},
|
15
|
+
]}
|
16
|
+
|
17
|
+
subject{ operator.to_a }
|
18
|
+
|
19
|
+
describe "when factored with commandline args" do
|
20
|
+
let(:operator){ Unnest.run(%w{-- nested}) }
|
21
|
+
before{ operator.pipe(input) }
|
22
|
+
it { should == expected }
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "when factored with Lispy" do
|
26
|
+
let(:operator){ Lispy.unnest(input, :nested) }
|
27
|
+
it { should == expected }
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
describe Reader::AlfFile do
|
4
|
+
|
5
|
+
let(:io){ StringIO.new "(restrict :suppliers, lambda{status > 20})" }
|
6
|
+
let(:reader){ Reader::AlfFile.new(io, self) }
|
7
|
+
def dataset(name)
|
8
|
+
[{:status => 10},{:status => 30}]
|
9
|
+
end
|
10
|
+
|
11
|
+
subject{ reader.to_a }
|
12
|
+
it{ should == [{:status => 30}]}
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
describe Reader::Rash do
|
4
|
+
|
5
|
+
let(:lines){ [{:id => 1},{:id => 2}] }
|
6
|
+
let(:str) { lines.collect{|s| s.inspect}.join("\n") }
|
7
|
+
let(:io) { StringIO.new(str) }
|
8
|
+
|
9
|
+
describe "when called on a StringIO" do
|
10
|
+
|
11
|
+
let(:reader){ Reader::Rash.new(io) }
|
12
|
+
|
13
|
+
it "should be enumerable" do
|
14
|
+
reader.to_a.should == lines
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "when called on a String" do
|
20
|
+
|
21
|
+
let(:file){ File.expand_path('../input.rb', __FILE__) }
|
22
|
+
let(:reader){ Reader::Rash.new(file) }
|
23
|
+
|
24
|
+
it "should be enumerable" do
|
25
|
+
reader.to_a.should == lines
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
data/spec/reader_spec.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
describe Reader do
|
4
|
+
|
5
|
+
subject{ Reader }
|
6
|
+
it { should respond_to(:rash) }
|
7
|
+
|
8
|
+
describe "rash" do
|
9
|
+
subject{ Reader.rash($stdin) }
|
10
|
+
it{ should be_a(Reader::Rash) }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "reader" do
|
14
|
+
|
15
|
+
specify "when associated" do
|
16
|
+
r = Reader.reader('suppliers.rash')
|
17
|
+
r.should be_a(Reader::Rash)
|
18
|
+
end
|
19
|
+
|
20
|
+
specify "when not associated" do
|
21
|
+
lambda{ Reader.reader('.noone') }.should raise_error
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
class Renderer::Text
|
4
|
+
describe Cell do
|
5
|
+
|
6
|
+
let(:f){ Cell.new }
|
7
|
+
|
8
|
+
specify "text_rendering" do
|
9
|
+
Cell.new(100).text_rendering.should == "100"
|
10
|
+
Cell.new(:hello).text_rendering.should == ":hello"
|
11
|
+
Cell.new("hello").text_rendering.should == "hello"
|
12
|
+
Cell.new(10.0).text_rendering.should == "10.0000000"
|
13
|
+
Cell.new(10/3.0).text_rendering.should == "3.3333333"
|
14
|
+
Cell.new([]).text_rendering.should == "[]"
|
15
|
+
Cell.new([10/3.0, true]).text_rendering.should == "[3.3333333, true]"
|
16
|
+
end
|
17
|
+
|
18
|
+
specify "min_width" do
|
19
|
+
Cell.new("").min_width.should == 0
|
20
|
+
Cell.new(10/3.0).min_width.should == 9
|
21
|
+
Cell.new("12\n5345").min_width.should == 4
|
22
|
+
end
|
23
|
+
|
24
|
+
specify "rendering_lines" do
|
25
|
+
Cell.new("").rendering_lines.should == []
|
26
|
+
Cell.new(10/3.0).rendering_lines.should == ["3.3333333"]
|
27
|
+
Cell.new([10/3.0,true]).rendering_lines.should == ["[3.3333333, true]"]
|
28
|
+
Cell.new("abc").rendering_lines(5).should == ["abc "]
|
29
|
+
Cell.new(12).rendering_lines(5).should == [" 12"]
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
class Renderer::Text
|
4
|
+
describe Row do
|
5
|
+
|
6
|
+
let(:row){ Row.new(values) }
|
7
|
+
|
8
|
+
describe "when single values are used only" do
|
9
|
+
|
10
|
+
let(:values){ [ 10/3.0, true ] }
|
11
|
+
specify "rendering_lines" do
|
12
|
+
row.rendering_lines.should == ["| 3.3333333 | true |"]
|
13
|
+
row.rendering_lines([10,5]).should == ["| 3.3333333 | true |"]
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "when multiple-line values are used" do
|
19
|
+
|
20
|
+
let(:values){ [ 10/3.0, [1, 2, 3] ] }
|
21
|
+
|
22
|
+
specify "rendering_lines" do
|
23
|
+
row.rendering_lines.should == ["| 3.3333333 | [1, 2, 3] |"]
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
class Renderer::Text
|
4
|
+
describe Table do
|
5
|
+
|
6
|
+
let(:columns){ [ :method, :total ] }
|
7
|
+
let(:table){ Table.new(records, columns) }
|
8
|
+
|
9
|
+
describe "on an empty table" do
|
10
|
+
|
11
|
+
let(:records){ [ ] }
|
12
|
+
|
13
|
+
specify "render" do
|
14
|
+
table.render.should == "+---------+--------+\n" +
|
15
|
+
"| :method | :total |\n" +
|
16
|
+
"+---------+--------+\n" +
|
17
|
+
"+---------+--------+\n"
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "when single values are used only" do
|
23
|
+
|
24
|
+
let(:records){ [ [:by_x, 10.0], [:by_y, 2.0] ] }
|
25
|
+
|
26
|
+
specify "render" do
|
27
|
+
table.render.should == "+---------+------------+\n" +
|
28
|
+
"| :method | :total |\n" +
|
29
|
+
"+---------+------------+\n" +
|
30
|
+
"| :by_x | 10.0000000 |\n" +
|
31
|
+
"| :by_y | 2.0000000 |\n" +
|
32
|
+
"+---------+------------+\n"
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
describe Renderer do
|
4
|
+
|
5
|
+
subject{ Renderer }
|
6
|
+
it { should respond_to(:rash) }
|
7
|
+
it { should respond_to(:text) }
|
8
|
+
|
9
|
+
describe 'renderer' do
|
10
|
+
subject{ Renderer.renderer(:rash) }
|
11
|
+
it{ should be_a(Renderer) }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'rash' do
|
15
|
+
subject{ Renderer.rash(input) }
|
16
|
+
let(:input){ [{:a => 1}] }
|
17
|
+
let(:output){ "" }
|
18
|
+
let(:expected){ "{:a=>1}\n" }
|
19
|
+
specify{
|
20
|
+
subject.should be_a(Renderer)
|
21
|
+
subject.execute(output).should == expected
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'text' do
|
26
|
+
subject{ Renderer.text(input) }
|
27
|
+
let(:input){ [{:a => 1}] }
|
28
|
+
let(:output){ "" }
|
29
|
+
let(:expected){ "+----+\n"\
|
30
|
+
"| :a |\n"\
|
31
|
+
"+----+\n"\
|
32
|
+
"| 1 |\n"\
|
33
|
+
"+----+\n"
|
34
|
+
}
|
35
|
+
specify{
|
36
|
+
subject.should be_a(Renderer)
|
37
|
+
subject.execute(output).should == expected
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
require 'alf'
|
3
|
+
|
4
|
+
Alf::Lispy.extend(Alf::Lispy)
|
5
|
+
|
6
|
+
shared_examples_for "An operator class" do
|
7
|
+
|
8
|
+
it "should not have public set_args, _each and _prepare methods" do
|
9
|
+
operator_class.public_method_defined?(:set_args).should be_false
|
10
|
+
operator_class.public_method_defined?(:_each).should be_false
|
11
|
+
operator_class.public_method_defined?(:_prepare).should be_false
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should have a public run method" do
|
15
|
+
operator_class.public_method_defined?(:run).should be_true
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should have a public pipe method" do
|
19
|
+
operator_class.public_method_defined?(:pipe).should be_true
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should have a public each method" do
|
23
|
+
operator_class.public_method_defined?(:each).should be_true
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Tools
|
4
|
+
describe OrderingKey do
|
5
|
+
|
6
|
+
describe "coerce" do
|
7
|
+
|
8
|
+
specify "when passed an doubly array" do
|
9
|
+
key = OrderingKey.coerce [[:a, :asc], [:b, :desc]]
|
10
|
+
key.attributes.should == [:a, :b]
|
11
|
+
key.order_of(:a).should == :asc
|
12
|
+
key.order_of(:b).should == :desc
|
13
|
+
end
|
14
|
+
|
15
|
+
specify "when passed a single array" do
|
16
|
+
key = OrderingKey.coerce [:a, :b]
|
17
|
+
key.attributes.should == [:a, :b]
|
18
|
+
key.order_of(:a).should == :asc
|
19
|
+
key.order_of(:b).should == :asc
|
20
|
+
end
|
21
|
+
|
22
|
+
specify "when passed an ordering key" do
|
23
|
+
key = OrderingKey.coerce [:a, :b]
|
24
|
+
key2 = OrderingKey.coerce key
|
25
|
+
key.should == key2
|
26
|
+
end
|
27
|
+
|
28
|
+
specify "when passed a projection key" do
|
29
|
+
pkey = ProjectionKey.new [:a, :b]
|
30
|
+
key = OrderingKey.coerce pkey
|
31
|
+
key.attributes.should == [:a, :b]
|
32
|
+
key.order_of(:a).should == :asc
|
33
|
+
key.order_of(:b).should == :asc
|
34
|
+
end
|
35
|
+
|
36
|
+
end # coerce
|
37
|
+
|
38
|
+
describe "compare" do
|
39
|
+
|
40
|
+
specify "when passed a single key" do
|
41
|
+
key = OrderingKey.coerce [:a]
|
42
|
+
key.compare({:a => 1}, {:a => 2}).should == -1
|
43
|
+
key.compare({:a => 1}, {:a => 1}).should == 0
|
44
|
+
key.compare({:a => 2}, {:a => 1}).should == 1
|
45
|
+
end
|
46
|
+
|
47
|
+
specify "when passed a single key with desc order" do
|
48
|
+
key = OrderingKey.coerce [[:a, :desc]]
|
49
|
+
key.compare({:a => 1}, {:a => 2}).should == 1
|
50
|
+
key.compare({:a => 1}, {:a => 1}).should == 0
|
51
|
+
key.compare({:a => 2}, {:a => 1}).should == -1
|
52
|
+
end
|
53
|
+
|
54
|
+
specify "when passed a double key" do
|
55
|
+
key = OrderingKey.coerce [[:a, :asc], [:b, :desc]]
|
56
|
+
key.compare({:a => 1, :b => 1}, {:a => 0, :b => 1}).should == 1
|
57
|
+
key.compare({:a => 1, :b => 1}, {:a => 1, :b => 2}).should == 1
|
58
|
+
key.compare({:a => 1, :b => 1}, {:a => 1, :b => 1}).should == 0
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "+" do
|
64
|
+
|
65
|
+
specify "when passed another key" do
|
66
|
+
key = OrderingKey.coerce [:a]
|
67
|
+
key2 = key + OrderingKey.coerce([[:b, :desc]])
|
68
|
+
key2.ordering.should == [[:a, :asc], [:b, :desc]]
|
69
|
+
end
|
70
|
+
|
71
|
+
specify "when passed another array" do
|
72
|
+
key = OrderingKey.coerce [:a]
|
73
|
+
key2 = key + [[:b, :desc]]
|
74
|
+
key2.ordering.should == [[:a, :asc], [:b, :desc]]
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Tools
|
4
|
+
describe ProjectionKey do
|
5
|
+
|
6
|
+
describe "coerce" do
|
7
|
+
|
8
|
+
specify "when passed an array" do
|
9
|
+
key = ProjectionKey.coerce [:a, :b]
|
10
|
+
key.attributes.should == [:a, :b]
|
11
|
+
key.allbut.should == false
|
12
|
+
end
|
13
|
+
|
14
|
+
specify "when passed a ProjectionKey" do
|
15
|
+
key = ProjectionKey.coerce [:a, :b]
|
16
|
+
key2 = ProjectionKey.coerce key
|
17
|
+
key2.should == key
|
18
|
+
end
|
19
|
+
|
20
|
+
specify "when passed an OrderingKey" do
|
21
|
+
okey = OrderingKey.new [[:a, :asc], [:b, :asc]]
|
22
|
+
key = ProjectionKey.coerce(okey)
|
23
|
+
key.attributes.should == [:a, :b]
|
24
|
+
key.allbut.should == false
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "to_ordering_key" do
|
30
|
+
|
31
|
+
specify "when passed an array" do
|
32
|
+
key = ProjectionKey.coerce [:a, :b]
|
33
|
+
okey = key.to_ordering_key
|
34
|
+
okey.attributes.should == [:a, :b]
|
35
|
+
okey.order_of(:a).should == :asc
|
36
|
+
okey.order_of(:b).should == :asc
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "split" do
|
42
|
+
|
43
|
+
subject{ key.split(tuple) }
|
44
|
+
|
45
|
+
describe "when used without allbut" do
|
46
|
+
let(:key){ ProjectionKey.new [:a, :b] }
|
47
|
+
let(:tuple){ {:a => 1, :b => 2, :c => 3} }
|
48
|
+
let(:expected){ [{:a => 1, :b => 2}, {:c => 3}] }
|
49
|
+
it{ should == expected }
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "when used with allbut" do
|
53
|
+
let(:key){ ProjectionKey.new [:a, :b], true }
|
54
|
+
let(:tuple){ {:a => 1, :b => 2, :c => 3} }
|
55
|
+
let(:expected){ [{:c => 3}, {:a => 1, :b => 2}] }
|
56
|
+
it{ should == expected }
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "project" do
|
62
|
+
|
63
|
+
subject{ key.project(tuple) }
|
64
|
+
|
65
|
+
describe "when used without allbut" do
|
66
|
+
let(:key){ ProjectionKey.new [:a, :b] }
|
67
|
+
let(:tuple){ {:a => 1, :b => 2, :c => 3} }
|
68
|
+
let(:expected){ {:a => 1, :b => 2} }
|
69
|
+
it{ should == expected }
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "when used with allbut" do
|
73
|
+
let(:key){ ProjectionKey.new [:a, :b], true }
|
74
|
+
let(:tuple){ {:a => 1, :b => 2, :c => 3} }
|
75
|
+
let(:expected){ {:c => 3} }
|
76
|
+
it{ should == expected }
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|