1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
require 'spec_helper'
module Arel
module Testing
class Engine
attr_reader :rows
def initialize
@rows = []
end
def supports(operation)
false
end
def read(relation)
@rows.dup.map { |r| Row.new(relation, r) }
end
def create(insert)
@rows << insert.record.tuple
insert
end
end
end
end
class Thing < Arel::Relation
attr_reader :engine, :attributes
def initialize(engine, attributes)
@engine, @attributes = engine, []
attributes.each do |name, type|
@attributes << type.new(self, name)
end
end
def format(attribute, value)
value
end
def insert(row)
insert = super Arel::Row.new(self, row)
insert.record
end
end
def have_rows(expected)
simple_matcher "have rows" do |given, matcher|
found, got, expected = [], [], expected.map { |r| r.tuple }
given.each do |row|
got << row.tuple
found << expected.find { |r| row.tuple == r }
end
matcher.failure_message = "Expected to get:\n" \
"#{expected.map {|r| " #{r.inspect}" }.join("\n")}\n" \
"instead, got:\n" \
"#{got.map {|r| " #{r.inspect}" }.join("\n")}"
found.compact.length == expected.length && got.compact.length == expected.length
end
end
share_examples_for 'A Relation' do
before :all do
# The two needed instance variables need to be set in a
# before :all callback.
# @relation is the relation being tested here.
# @expected is an array of the elements that are expected to be in
# the relation.
%w[ @relation @expected ].each do |ivar|
raise "#{ivar} needs to be defined" unless instance_variable_get(ivar)
end
# There needs to be enough items to be able to run all the tests
raise "@expected needs to have at least 6 items" unless @expected.length >= 6
end
describe "#each" do
it "iterates over the rows in any order" do
@relation.should have_rows(@expected)
end
end
describe "#where" do
before :all do
@expected = @expected.sort_by { |r| r[@relation[:age]] }
@pivot = @expected[@expected.length / 2]
end
it "finds rows with an equal to predicate" do
expected = @expected.select { |r| r[@relation[:age]] == @pivot[@relation[:age]] }
@relation.where(@relation[:age].eq(@pivot[@relation[:age]])).should have_rows(expected)
end
end
end
module Arel
describe "Relation" do
before :all do
@engine = Testing::Engine.new
@relation = Thing.new(@engine,
:id => Attributes::Integer,
:name => Attributes::String,
:age => Attributes::Integer)
end
describe "..." do
before :all do
@expected = (1..20).map { |i| @relation.insert([i, nil, 2 * i]) }
end
it_should_behave_like 'A Relation'
end
describe "#insert" do
it "inserts the row into the engine" do
@relation.insert([1, 'Foo', 10])
@engine.rows.should == [[1, 'Foo', 10]]
end
end
end
end
|