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