sequel 3.28.0 → 3.29.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. data/CHANGELOG +119 -3
  2. data/Rakefile +5 -3
  3. data/bin/sequel +1 -5
  4. data/doc/model_hooks.rdoc +9 -1
  5. data/doc/opening_databases.rdoc +49 -40
  6. data/doc/prepared_statements.rdoc +27 -6
  7. data/doc/release_notes/3.28.0.txt +2 -2
  8. data/doc/release_notes/3.29.0.txt +459 -0
  9. data/doc/sharding.rdoc +7 -1
  10. data/doc/testing.rdoc +18 -9
  11. data/doc/transactions.rdoc +41 -1
  12. data/lib/sequel/adapters/ado.rb +28 -17
  13. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  14. data/lib/sequel/adapters/amalgalite.rb +11 -7
  15. data/lib/sequel/adapters/db2.rb +122 -70
  16. data/lib/sequel/adapters/dbi.rb +15 -15
  17. data/lib/sequel/adapters/do.rb +5 -36
  18. data/lib/sequel/adapters/do/mysql.rb +0 -5
  19. data/lib/sequel/adapters/do/postgres.rb +0 -5
  20. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  21. data/lib/sequel/adapters/firebird.rb +3 -6
  22. data/lib/sequel/adapters/ibmdb.rb +24 -16
  23. data/lib/sequel/adapters/informix.rb +2 -4
  24. data/lib/sequel/adapters/jdbc.rb +47 -11
  25. data/lib/sequel/adapters/jdbc/as400.rb +5 -24
  26. data/lib/sequel/adapters/jdbc/db2.rb +0 -5
  27. data/lib/sequel/adapters/jdbc/derby.rb +217 -0
  28. data/lib/sequel/adapters/jdbc/firebird.rb +0 -5
  29. data/lib/sequel/adapters/jdbc/h2.rb +10 -12
  30. data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
  31. data/lib/sequel/adapters/jdbc/informix.rb +0 -5
  32. data/lib/sequel/adapters/jdbc/jtds.rb +0 -5
  33. data/lib/sequel/adapters/jdbc/mysql.rb +0 -10
  34. data/lib/sequel/adapters/jdbc/oracle.rb +70 -3
  35. data/lib/sequel/adapters/jdbc/postgresql.rb +0 -11
  36. data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
  37. data/lib/sequel/adapters/jdbc/sqlserver.rb +0 -5
  38. data/lib/sequel/adapters/jdbc/transactions.rb +56 -7
  39. data/lib/sequel/adapters/mock.rb +315 -0
  40. data/lib/sequel/adapters/mysql.rb +64 -51
  41. data/lib/sequel/adapters/mysql2.rb +15 -9
  42. data/lib/sequel/adapters/odbc.rb +13 -6
  43. data/lib/sequel/adapters/odbc/db2.rb +0 -4
  44. data/lib/sequel/adapters/odbc/mssql.rb +0 -5
  45. data/lib/sequel/adapters/openbase.rb +2 -4
  46. data/lib/sequel/adapters/oracle.rb +333 -51
  47. data/lib/sequel/adapters/postgres.rb +80 -27
  48. data/lib/sequel/adapters/shared/access.rb +0 -6
  49. data/lib/sequel/adapters/shared/db2.rb +13 -15
  50. data/lib/sequel/adapters/shared/firebird.rb +6 -6
  51. data/lib/sequel/adapters/shared/mssql.rb +23 -18
  52. data/lib/sequel/adapters/shared/mysql.rb +6 -6
  53. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
  54. data/lib/sequel/adapters/shared/oracle.rb +185 -30
  55. data/lib/sequel/adapters/shared/postgres.rb +35 -18
  56. data/lib/sequel/adapters/shared/progress.rb +0 -6
  57. data/lib/sequel/adapters/shared/sqlite.rb +116 -37
  58. data/lib/sequel/adapters/sqlite.rb +16 -8
  59. data/lib/sequel/adapters/swift.rb +5 -5
  60. data/lib/sequel/adapters/swift/mysql.rb +0 -5
  61. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  62. data/lib/sequel/adapters/swift/sqlite.rb +6 -4
  63. data/lib/sequel/adapters/tinytds.rb +13 -10
  64. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -0
  65. data/lib/sequel/core.rb +40 -0
  66. data/lib/sequel/database/connecting.rb +1 -2
  67. data/lib/sequel/database/dataset.rb +3 -3
  68. data/lib/sequel/database/dataset_defaults.rb +58 -0
  69. data/lib/sequel/database/misc.rb +62 -2
  70. data/lib/sequel/database/query.rb +113 -49
  71. data/lib/sequel/database/schema_methods.rb +7 -2
  72. data/lib/sequel/dataset/actions.rb +37 -19
  73. data/lib/sequel/dataset/features.rb +24 -0
  74. data/lib/sequel/dataset/graph.rb +7 -6
  75. data/lib/sequel/dataset/misc.rb +11 -3
  76. data/lib/sequel/dataset/mutation.rb +2 -3
  77. data/lib/sequel/dataset/prepared_statements.rb +6 -4
  78. data/lib/sequel/dataset/query.rb +46 -15
  79. data/lib/sequel/dataset/sql.rb +28 -4
  80. data/lib/sequel/extensions/named_timezones.rb +5 -0
  81. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  82. data/lib/sequel/model.rb +2 -1
  83. data/lib/sequel/model/associations.rb +115 -33
  84. data/lib/sequel/model/base.rb +91 -31
  85. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  86. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  87. data/lib/sequel/plugins/force_encoding.rb +6 -6
  88. data/lib/sequel/plugins/identity_map.rb +1 -1
  89. data/lib/sequel/plugins/many_through_many.rb +6 -10
  90. data/lib/sequel/plugins/prepared_statements.rb +12 -1
  91. data/lib/sequel/plugins/prepared_statements_associations.rb +1 -1
  92. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  93. data/lib/sequel/plugins/serialization.rb +6 -1
  94. data/lib/sequel/plugins/sharding.rb +0 -5
  95. data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
  96. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  97. data/lib/sequel/plugins/update_primary_key.rb +1 -1
  98. data/lib/sequel/timezones.rb +42 -42
  99. data/lib/sequel/version.rb +1 -1
  100. data/spec/adapters/mssql_spec.rb +29 -29
  101. data/spec/adapters/mysql_spec.rb +86 -104
  102. data/spec/adapters/oracle_spec.rb +48 -76
  103. data/spec/adapters/postgres_spec.rb +98 -33
  104. data/spec/adapters/spec_helper.rb +0 -5
  105. data/spec/adapters/sqlite_spec.rb +24 -21
  106. data/spec/core/connection_pool_spec.rb +9 -15
  107. data/spec/core/core_sql_spec.rb +20 -31
  108. data/spec/core/database_spec.rb +491 -227
  109. data/spec/core/dataset_spec.rb +638 -1051
  110. data/spec/core/expression_filters_spec.rb +0 -1
  111. data/spec/core/mock_adapter_spec.rb +378 -0
  112. data/spec/core/object_graph_spec.rb +48 -114
  113. data/spec/core/schema_generator_spec.rb +3 -3
  114. data/spec/core/schema_spec.rb +51 -114
  115. data/spec/core/spec_helper.rb +3 -90
  116. data/spec/extensions/class_table_inheritance_spec.rb +1 -1
  117. data/spec/extensions/dataset_associations_spec.rb +199 -0
  118. data/spec/extensions/instance_hooks_spec.rb +71 -0
  119. data/spec/extensions/named_timezones_spec.rb +22 -2
  120. data/spec/extensions/nested_attributes_spec.rb +3 -0
  121. data/spec/extensions/schema_spec.rb +1 -1
  122. data/spec/extensions/serialization_modification_detection_spec.rb +1 -0
  123. data/spec/extensions/serialization_spec.rb +5 -8
  124. data/spec/extensions/spec_helper.rb +4 -0
  125. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  126. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  127. data/spec/integration/associations_test.rb +123 -12
  128. data/spec/integration/dataset_test.rb +140 -47
  129. data/spec/integration/eager_loader_test.rb +19 -21
  130. data/spec/integration/model_test.rb +80 -1
  131. data/spec/integration/plugin_test.rb +179 -128
  132. data/spec/integration/prepared_statement_test.rb +92 -91
  133. data/spec/integration/schema_test.rb +42 -23
  134. data/spec/integration/spec_helper.rb +25 -31
  135. data/spec/integration/timezone_test.rb +38 -12
  136. data/spec/integration/transaction_test.rb +161 -34
  137. data/spec/integration/type_test.rb +3 -3
  138. data/spec/model/association_reflection_spec.rb +83 -7
  139. data/spec/model/associations_spec.rb +393 -676
  140. data/spec/model/base_spec.rb +186 -116
  141. data/spec/model/dataset_methods_spec.rb +7 -27
  142. data/spec/model/eager_loading_spec.rb +343 -867
  143. data/spec/model/hooks_spec.rb +160 -79
  144. data/spec/model/model_spec.rb +118 -165
  145. data/spec/model/plugins_spec.rb +7 -13
  146. data/spec/model/record_spec.rb +138 -207
  147. data/spec/model/spec_helper.rb +10 -73
  148. metadata +14 -8
@@ -3,39 +3,25 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
3
3
  describe Sequel::Model::DatasetMethods, "#destroy" do
4
4
  before do
5
5
  @c = Class.new(Sequel::Model(:items)) do
6
- class_variable_set(:@@destroyed, [])
6
+ self::Destroyed = []
7
7
  def destroy
8
- self.class.send(:class_variable_get, :@@destroyed) << self
9
- end
10
- def self.destroyed
11
- class_variable_get(:@@destroyed)
8
+ model::Destroyed << self
12
9
  end
13
10
  end
14
11
  @d = @c.dataset
12
+ @d._fetch = [{:id=>1}, {:id=>2}]
15
13
  MODEL_DB.reset
16
14
  end
17
15
 
18
16
  it "should instantiate objects in the dataset and call destroy on each" do
19
- def @d.fetch_rows(sql)
20
- yield({:id=>1})
21
- yield({:id=>2})
22
- end
23
17
  @d.destroy
24
- @c.destroyed.collect{|x| x.values}.should == [{:id=>1}, {:id=>2}]
18
+ @c::Destroyed.collect{|x| x.values}.should == [{:id=>1}, {:id=>2}]
25
19
  end
26
20
 
27
21
  it "should return the number of records destroyed" do
28
- def @d.fetch_rows(sql)
29
- yield({:id=>1})
30
- yield({:id=>2})
31
- end
32
22
  @d.destroy.should == 2
33
- def @d.fetch_rows(sql)
34
- yield({:id=>1})
35
- end
23
+ @d._fetch = [[{:i=>1}], []]
36
24
  @d.destroy.should == 1
37
- def @d.fetch_rows(sql)
38
- end
39
25
  @d.destroy.should == 0
40
26
  end
41
27
 
@@ -61,10 +47,7 @@ describe Sequel::Model::DatasetMethods, "#to_hash" do
61
47
  end
62
48
 
63
49
  it "should result in a hash with primary key value keys and model object values" do
64
- def @d.fetch_rows(sql)
65
- yield({:name=>1})
66
- yield({:name=>2})
67
- end
50
+ @d._fetch = [{:name=>1}, {:name=>2}]
68
51
  h = @d.to_hash
69
52
  h.should be_a_kind_of(Hash)
70
53
  a = h.to_a
@@ -73,10 +56,7 @@ describe Sequel::Model::DatasetMethods, "#to_hash" do
73
56
  end
74
57
 
75
58
  it "should result in a hash with given value keys and model object values" do
76
- def @d.fetch_rows(sql)
77
- yield({:name=>1, :number=>3})
78
- yield({:name=>2, :number=>4})
79
- end
59
+ @d._fetch = [{:name=>1, :number=>3}, {:name=>2, :number=>4}]
80
60
  h = @d.to_hash(:number)
81
61
  h.should be_a_kind_of(Hash)
82
62
  a = h.to_a
@@ -1,9 +1,7 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
3
3
  describe Sequel::Model, "#eager" do
4
- before(:each) do
5
- MODEL_DB.reset
6
-
4
+ before do
7
5
  class ::EagerAlbum < Sequel::Model(:albums)
8
6
  columns :id, :band_id
9
7
  many_to_one :band, :class=>'EagerBand', :key=>:band_id
@@ -48,63 +46,45 @@ describe Sequel::Model, "#eager" do
48
46
  many_to_many :bands, :class=>'EagerBand', :left_key=>:member_id, :right_key=>:band_id, :join_table=>:bm, :order =>:id
49
47
  end
50
48
 
51
- EagerAlbum.dataset.extend(Module.new {
52
- def columns
53
- [:id, :band_id]
49
+ EagerAlbum.dataset.columns(:id, :band_id)
50
+ EagerAlbum.dataset._fetch = proc do |sql|
51
+ h = if sql =~ /101/
52
+ {:id => 101, :band_id=> 101}
53
+ else
54
+ {:id => 1, :band_id=> 2}
54
55
  end
56
+ h[:x_foreign_key_x] = 4 if sql =~ /ag\.genre_id/
57
+ h
58
+ end
55
59
 
56
- def fetch_rows(sql)
57
- h = if sql =~ /101/
58
- {:id => 101, :band_id=> 101}
59
- else
60
- {:id => 1, :band_id=> 2}
61
- end
62
- h.merge!(:x_foreign_key_x=>4) if sql =~ /ag\.genre_id/
63
- @db << sql
64
- yield h
65
- end
66
- })
67
-
68
- EagerBand.dataset.extend(Module.new {
69
- def fetch_rows(sql)
60
+ EagerBand.dataset._fetch = proc do |sql|
61
+ case sql
62
+ when /id IN (101)/
63
+ # nothing
64
+ when /id > 100/
65
+ [{:id => 101}, {:id => 102}]
66
+ else
70
67
  h = {:id => 2}
71
- h.merge!(:x_foreign_key_x=>5) if sql =~ /bm\.member_id/
72
- @db << sql
73
- case sql
74
- when /id IN (101)/
75
- when /id > 100/
76
- yield({:id => 101})
77
- yield({:id => 102})
78
- else
79
- yield h
80
- end
68
+ h[:x_foreign_key_x] = 5 if sql =~ /bm\.member_id/
69
+ h
81
70
  end
82
- })
71
+ end
83
72
 
84
- EagerTrack.dataset.extend(Module.new {
85
- def fetch_rows(sql)
86
- @db << sql
87
- yield({:id => 3, :album_id => 1})
88
- end
89
- })
73
+ EagerTrack.dataset._fetch = {:id => 3, :album_id => 1}
90
74
 
91
- EagerGenre.dataset.extend(Module.new {
92
- def fetch_rows(sql)
93
- h = {:id => 4}
94
- h.merge!(:x_foreign_key_x=>1) if sql =~ /ag\.album_id/
95
- @db << sql
96
- yield h
97
- end
98
- })
75
+ EagerGenre.dataset._fetch = proc do |sql|
76
+ h = {:id => 4}
77
+ h[:x_foreign_key_x] = 1 if sql =~ /ag\.album_id/
78
+ h
79
+ end
99
80
 
100
- EagerBandMember.dataset.extend(Module.new {
101
- def fetch_rows(sql)
102
- h = {:id => 5}
103
- h.merge!(:x_foreign_key_x=>2) if sql =~ /bm\.band_id/
104
- @db << sql
105
- yield h
106
- end
107
- })
81
+ EagerBandMember.dataset._fetch = proc do |sql|
82
+ h = {:id => 5}
83
+ h[:x_foreign_key_x] = 2 if sql =~ /bm\.band_id/
84
+ h
85
+ end
86
+
87
+ MODEL_DB.reset
108
88
  end
109
89
  after do
110
90
  [:EagerAlbum, :EagerBand, :EagerTrack, :EagerGenre, :EagerBandMember].each{|x| Object.send(:remove_const, x)}
@@ -116,15 +96,10 @@ describe Sequel::Model, "#eager" do
116
96
 
117
97
  it "should eagerly load a single many_to_one association" do
118
98
  a = EagerAlbum.eager(:band).all
119
- a.should be_a_kind_of(Array)
120
- a.size.should == 1
121
- a.first.should be_a_kind_of(EagerAlbum)
122
- a.first.values.should == {:id => 1, :band_id => 2}
123
99
  MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM bands WHERE (bands.id IN (2))']
124
- a = a.first
125
- a.band.should be_a_kind_of(EagerBand)
126
- a.band.values.should == {:id => 2}
127
- MODEL_DB.sqls.length.should == 2
100
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
101
+ a.first.band.should == EagerBand.load(:id=>2)
102
+ MODEL_DB.sqls.should == []
128
103
  end
129
104
 
130
105
  it "should eagerly load a single one_to_one association" do
@@ -133,7 +108,7 @@ describe Sequel::Model, "#eager" do
133
108
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
134
109
  MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE (tracks.album_id IN (1))']
135
110
  a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
136
- MODEL_DB.sqls.length.should == 2
111
+ MODEL_DB.sqls.should == []
137
112
  end
138
113
 
139
114
  it "should eagerly load a single one_to_one association using the :distinct_on strategy" do
@@ -143,7 +118,7 @@ describe Sequel::Model, "#eager" do
143
118
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
144
119
  MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT DISTINCT ON (tracks.album_id) * FROM tracks WHERE (tracks.album_id IN (1)) ORDER BY tracks.album_id']
145
120
  a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
146
- MODEL_DB.sqls.length.should == 2
121
+ MODEL_DB.sqls.should == []
147
122
  end
148
123
 
149
124
  it "should eagerly load a single one_to_one association using the :window_function strategy" do
@@ -153,7 +128,7 @@ describe Sequel::Model, "#eager" do
153
128
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
154
129
  MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks WHERE (tracks.album_id IN (1))) AS t1 WHERE (x_sequel_row_number_x = 1)']
155
130
  a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
156
- MODEL_DB.sqls.length.should == 2
131
+ MODEL_DB.sqls.should == []
157
132
  end
158
133
 
159
134
  it "should eagerly load a single one_to_one association using the :correlated_subquery strategy" do
@@ -162,7 +137,7 @@ describe Sequel::Model, "#eager" do
162
137
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
163
138
  MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE ((tracks.album_id IN (1)) AND (tracks.id IN (SELECT t1.id FROM tracks AS t1 WHERE (t1.album_id = tracks.album_id) ORDER BY name LIMIT 1))) ORDER BY name']
164
139
  a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
165
- MODEL_DB.sqls.length.should == 2
140
+ MODEL_DB.sqls.should == []
166
141
  end
167
142
 
168
143
  it "should handle qualified order clauses when eagerly loading a single one_to_one association using the :correlated_subquery strategy" do
@@ -171,7 +146,7 @@ describe Sequel::Model, "#eager" do
171
146
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
172
147
  MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE ((tracks.album_id IN (1)) AND (tracks.id IN (SELECT t1.id FROM tracks AS t1 WHERE (t1.album_id = tracks.album_id) ORDER BY t1.name, t1.name DESC, t1.name, t.name, 1 LIMIT 1))) ORDER BY tracks.name, tracks.name DESC, tracks.name, t.name, 1']
173
148
  a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
174
- MODEL_DB.sqls.length.should == 2
149
+ MODEL_DB.sqls.should == []
175
150
  end
176
151
 
177
152
  it "should handle qualified composite keys when eagerly loading a single one_to_one association using the :correlated_subquery strategy" do
@@ -180,17 +155,12 @@ describe Sequel::Model, "#eager" do
180
155
  c1.set_primary_key [:id, :band_id]
181
156
  c2.set_primary_key [:id, :album_id]
182
157
  c1.one_to_one :track, :class=>c2, :key=>[:album_id, :id], :eager_limit_strategy=>:correlated_subquery
183
- c2.dataset.extend(Module.new do
184
- def fetch_rows(sql)
185
- MODEL_DB << sql
186
- yield({:id => 2, :album_id=>1})
187
- end
188
- end)
158
+ c2.dataset._fetch = {:id => 2, :album_id=>1}
189
159
  a = c1.eager(:track).all
190
160
  a.should == [c1.load(:id => 1, :band_id => 2)]
191
161
  MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE (((tracks.album_id, tracks.id) IN ((1, 2))) AND ((tracks.id, tracks.album_id) IN (SELECT t1.id, t1.album_id FROM tracks AS t1 WHERE ((t1.album_id = tracks.album_id) AND (t1.id = tracks.id)) LIMIT 1)))']
192
162
  a.first.track.should == c2.load(:id => 2, :album_id=>1)
193
- MODEL_DB.sqls.length.should == 2
163
+ MODEL_DB.sqls.should == []
194
164
  end
195
165
 
196
166
  it "should eagerly load a single one_to_many association" do
@@ -198,22 +168,15 @@ describe Sequel::Model, "#eager" do
198
168
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
199
169
  MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE (tracks.album_id IN (1))']
200
170
  a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
201
- MODEL_DB.sqls.length.should == 2
171
+ MODEL_DB.sqls.should == []
202
172
  end
203
173
 
204
174
  it "should eagerly load a single many_to_many association" do
205
175
  a = EagerAlbum.eager(:genres).all
206
- a.should be_a_kind_of(Array)
207
- a.size.should == 1
208
- a.first.should be_a_kind_of(EagerAlbum)
209
- a.first.values.should == {:id => 1, :band_id => 2}
176
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
210
177
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
211
- a = a.first
212
- a.genres.should be_a_kind_of(Array)
213
- a.genres.size.should == 1
214
- a.genres.first.should be_a_kind_of(EagerGenre)
215
- a.genres.first.values.should == {:id => 4}
216
- MODEL_DB.sqls.length.should == 2
178
+ a.first.genres.should == [EagerGenre.load(:id=>4)]
179
+ MODEL_DB.sqls.should == []
217
180
  end
218
181
 
219
182
  it "should correctly handle a :select=>[] option to many_to_many" do
@@ -222,150 +185,88 @@ describe Sequel::Model, "#eager" do
222
185
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT *, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
223
186
  end
224
187
 
188
+ it "should correctly handle an aliased join table in many_to_many" do
189
+ EagerAlbum.many_to_many :sgenres, :clone=>:genres, :join_table=>:ag___ga
190
+ a = EagerAlbum.eager(:sgenres).all
191
+ MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ga.album_id AS x_foreign_key_x FROM genres INNER JOIN ag AS ga ON ((ga.genre_id = genres.id) AND (ga.album_id IN (1)))"]
192
+ end
193
+
225
194
  it "should eagerly load multiple associations in a single call" do
226
195
  a = EagerAlbum.eager(:genres, :tracks, :band).all
227
- a.should be_a_kind_of(Array)
228
- a.size.should == 1
229
- a.first.should be_a_kind_of(EagerAlbum)
230
- a.first.values.should == {:id => 1, :band_id => 2}
231
- MODEL_DB.sqls.length.should == 4
232
- MODEL_DB.sqls[0].should == 'SELECT * FROM albums'
233
- MODEL_DB.sqls[1..-1].should(include('SELECT * FROM bands WHERE (bands.id IN (2))'))
234
- MODEL_DB.sqls[1..-1].should(include('SELECT * FROM tracks WHERE (tracks.album_id IN (1))'))
235
- MODEL_DB.sqls[1..-1].should(include('SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))'))
196
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
197
+ sqls = MODEL_DB.sqls
198
+ sqls.shift.should == 'SELECT * FROM albums'
199
+ sqls.sort.should == ['SELECT * FROM bands WHERE (bands.id IN (2))',
200
+ 'SELECT * FROM tracks WHERE (tracks.album_id IN (1))',
201
+ 'SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))']
236
202
  a = a.first
237
- a.band.should be_a_kind_of(EagerBand)
238
- a.band.values.should == {:id => 2}
239
- a.tracks.should be_a_kind_of(Array)
240
- a.tracks.size.should == 1
241
- a.tracks.first.should be_a_kind_of(EagerTrack)
242
- a.tracks.first.values.should == {:id => 3, :album_id=>1}
243
- a.genres.should be_a_kind_of(Array)
244
- a.genres.size.should == 1
245
- a.genres.first.should be_a_kind_of(EagerGenre)
246
- a.genres.first.values.should == {:id => 4}
247
- MODEL_DB.sqls.length.should == 4
203
+ a.band.should == EagerBand.load(:id=>2)
204
+ a.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
205
+ a.genres.should == [EagerGenre.load(:id => 4)]
206
+ MODEL_DB.sqls.should == []
248
207
  end
249
208
 
250
209
  it "should eagerly load multiple associations in separate calls" do
251
210
  a = EagerAlbum.eager(:genres).eager(:tracks).eager(:band).all
252
- a.should be_a_kind_of(Array)
253
- a.size.should == 1
254
- a.first.should be_a_kind_of(EagerAlbum)
255
- a.first.values.should == {:id => 1, :band_id => 2}
256
- MODEL_DB.sqls.length.should == 4
257
- MODEL_DB.sqls[0].should == 'SELECT * FROM albums'
258
- MODEL_DB.sqls[1..-1].should(include('SELECT * FROM bands WHERE (bands.id IN (2))'))
259
- MODEL_DB.sqls[1..-1].should(include('SELECT * FROM tracks WHERE (tracks.album_id IN (1))'))
260
- MODEL_DB.sqls[1..-1].should(include('SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))'))
211
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
212
+ sqls = MODEL_DB.sqls
213
+ sqls.shift.should == 'SELECT * FROM albums'
214
+ sqls.sort.should == ['SELECT * FROM bands WHERE (bands.id IN (2))',
215
+ 'SELECT * FROM tracks WHERE (tracks.album_id IN (1))',
216
+ 'SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))']
261
217
  a = a.first
262
- a.band.should be_a_kind_of(EagerBand)
263
- a.band.values.should == {:id => 2}
264
- a.tracks.should be_a_kind_of(Array)
265
- a.tracks.size.should == 1
266
- a.tracks.first.should be_a_kind_of(EagerTrack)
267
- a.tracks.first.values.should == {:id => 3, :album_id=>1}
268
- a.genres.should be_a_kind_of(Array)
269
- a.genres.size.should == 1
270
- a.genres.first.should be_a_kind_of(EagerGenre)
271
- a.genres.first.values.should == {:id => 4}
272
- MODEL_DB.sqls.length.should == 4
218
+ a.band.should == EagerBand.load(:id=>2)
219
+ a.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
220
+ a.genres.should == [EagerGenre.load(:id => 4)]
221
+ MODEL_DB.sqls.should == []
273
222
  end
274
223
 
275
224
  it "should allow cascading of eager loading for associations of associated models" do
276
225
  a = EagerTrack.eager(:album=>{:band=>:members}).all
277
- a.should be_a_kind_of(Array)
278
- a.size.should == 1
279
- a.first.should be_a_kind_of(EagerTrack)
280
- a.first.values.should == {:id => 3, :album_id => 1}
281
- MODEL_DB.sqls.length.should == 4
226
+ a.should == [EagerTrack.load(:id => 3, :album_id => 1)]
282
227
  MODEL_DB.sqls.should == ['SELECT * FROM tracks',
283
228
  'SELECT * FROM albums WHERE (albums.id IN (1))',
284
229
  'SELECT * FROM bands WHERE (bands.id IN (2))',
285
230
  "SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON ((bm.member_id = members.id) AND (bm.band_id IN (2)))"]
286
231
  a = a.first
287
- a.album.should be_a_kind_of(EagerAlbum)
288
- a.album.values.should == {:id => 1, :band_id => 2}
289
- a.album.band.should be_a_kind_of(EagerBand)
290
- a.album.band.values.should == {:id => 2}
291
- a.album.band.members.should be_a_kind_of(Array)
292
- a.album.band.members.size.should == 1
293
- a.album.band.members.first.should be_a_kind_of(EagerBandMember)
294
- a.album.band.members.first.values.should == {:id => 5}
295
- MODEL_DB.sqls.length.should == 4
232
+ a.album.should == EagerAlbum.load(:id => 1, :band_id => 2)
233
+ a.album.band.should == EagerBand.load(:id => 2)
234
+ a.album.band.members.should == [EagerBandMember.load(:id => 5)]
235
+ MODEL_DB.sqls.should == []
296
236
  end
297
237
 
298
238
  it "should cascade eagerly loading when the :eager association option is used" do
299
239
  a = EagerBand.eager(:albums).all
300
- a.should be_a_kind_of(Array)
301
- a.size.should == 1
302
- a.first.should be_a_kind_of(EagerBand)
303
- a.first.values.should == {:id => 2}
240
+ a.should == [EagerBand.load(:id=>2)]
304
241
  MODEL_DB.sqls.should == ['SELECT * FROM bands',
305
- 'SELECT * FROM albums WHERE (albums.band_id IN (2))',
306
- 'SELECT * FROM tracks WHERE (tracks.album_id IN (1))']
307
- a = a.first
308
- a.albums.should be_a_kind_of(Array)
309
- a.albums.size.should == 1
310
- a.albums.first.should be_a_kind_of(EagerAlbum)
311
- a.albums.first.values.should == {:id => 1, :band_id => 2}
312
- a = a.albums.first
313
- a.tracks.should be_a_kind_of(Array)
314
- a.tracks.size.should == 1
315
- a.tracks.first.should be_a_kind_of(EagerTrack)
316
- a.tracks.first.values.should == {:id => 3, :album_id => 1}
317
- MODEL_DB.sqls.length.should == 3
242
+ 'SELECT * FROM albums WHERE (albums.band_id IN (2))',
243
+ 'SELECT * FROM tracks WHERE (tracks.album_id IN (1))']
244
+ a.first.albums.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
245
+ a.first.albums.first.tracks.should == [EagerTrack.load(:id => 3, :album_id => 1)]
246
+ MODEL_DB.sqls.should == []
318
247
  end
319
248
 
320
249
  it "should respect :eager when lazily loading an association" do
321
250
  a = EagerBand.all
322
- a.should be_a_kind_of(Array)
323
- a.size.should == 1
324
- a.first.should be_a_kind_of(EagerBand)
325
- a.first.values.should == {:id => 2}
251
+ a.should == [EagerBand.load(:id=>2)]
326
252
  MODEL_DB.sqls.should == ['SELECT * FROM bands']
327
- a = a.first
328
- a.albums
329
- MODEL_DB.sqls.should == ['SELECT * FROM bands',
330
- 'SELECT * FROM albums WHERE (albums.band_id = 2)',
331
- 'SELECT * FROM tracks WHERE (tracks.album_id IN (1))']
332
- a.albums.should be_a_kind_of(Array)
333
- a.albums.size.should == 1
334
- a.albums.first.should be_a_kind_of(EagerAlbum)
335
- a.albums.first.values.should == {:id => 1, :band_id => 2}
336
- a = a.albums.first
337
- a.tracks.should be_a_kind_of(Array)
338
- a.tracks.size.should == 1
339
- a.tracks.first.should be_a_kind_of(EagerTrack)
340
- a.tracks.first.values.should == {:id => 3, :album_id => 1}
341
- MODEL_DB.sqls.length.should == 3
253
+ a = a.first.albums
254
+ MODEL_DB.sqls.should == ['SELECT * FROM albums WHERE (albums.band_id = 2)',
255
+ 'SELECT * FROM tracks WHERE (tracks.album_id IN (1))']
256
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
257
+ a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id => 1)]
258
+ MODEL_DB.sqls.should == []
342
259
  end
343
260
 
344
261
  it "should cascade eagerly loading when the :eager_graph association option is used" do
345
- EagerAlbum.dataset.extend(Module.new {
346
- def fetch_rows(sql)
347
- @db << sql
348
- yield({:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1})
349
- end
350
- })
262
+ EagerAlbum.dataset._fetch = {:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1}
351
263
  a = EagerBand.eager(:graph_albums).all
352
- a.should be_a_kind_of(Array)
353
- a.size.should == 1
354
- a.first.should be_a_kind_of(EagerBand)
355
- a.first.values.should == {:id => 2}
264
+ a.should == [EagerBand.load(:id=>2)]
356
265
  MODEL_DB.sqls.should == ['SELECT * FROM bands',
357
- 'SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) WHERE (albums.band_id IN (2))']
358
- a = a.first
359
- a.graph_albums.should be_a_kind_of(Array)
360
- a.graph_albums.size.should == 1
361
- a.graph_albums.first.should be_a_kind_of(EagerAlbum)
362
- a.graph_albums.first.values.should == {:id => 1, :band_id => 2}
363
- a = a.graph_albums.first
364
- a.tracks.should be_a_kind_of(Array)
365
- a.tracks.size.should == 1
366
- a.tracks.first.should be_a_kind_of(EagerTrack)
367
- a.tracks.first.values.should == {:id => 3, :album_id => 1}
368
- MODEL_DB.sqls.length.should == 2
266
+ 'SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) WHERE (albums.band_id IN (2))']
267
+ a.first.graph_albums.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
268
+ a.first.graph_albums.first.tracks.should == [EagerTrack.load(:id => 3, :album_id => 1)]
269
+ MODEL_DB.sqls.should == []
369
270
  end
370
271
 
371
272
  it "should raise an Error when eager loading a many_to_many association with the :eager_graph option" do
@@ -374,67 +275,36 @@ describe Sequel::Model, "#eager" do
374
275
 
375
276
  it "should respect :eager_graph when lazily loading an association" do
376
277
  a = EagerBand.all
377
- a.should be_a_kind_of(Array)
378
- a.size.should == 1
379
- a.first.should be_a_kind_of(EagerBand)
380
- a.first.values.should == {:id => 2}
278
+ a.should == [EagerBand.load(:id=>2)]
381
279
  MODEL_DB.sqls.should == ['SELECT * FROM bands']
382
280
  a = a.first
383
- EagerAlbum.dataset.extend(Module.new {
384
- def fetch_rows(sql)
385
- @db << sql
386
- yield({:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1})
387
- end
388
- })
281
+ EagerAlbum.dataset._fetch = {:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1}
389
282
  a.graph_albums
390
- MODEL_DB.sqls.should == ['SELECT * FROM bands',
391
- 'SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) WHERE (albums.band_id = 2)']
392
- a.graph_albums.should be_a_kind_of(Array)
393
- a.graph_albums.size.should == 1
394
- a.graph_albums.first.should be_a_kind_of(EagerAlbum)
395
- a.graph_albums.first.values.should == {:id => 1, :band_id => 2}
396
- a = a.graph_albums.first
397
- a.tracks.should be_a_kind_of(Array)
398
- a.tracks.size.should == 1
399
- a.tracks.first.should be_a_kind_of(EagerTrack)
400
- a.tracks.first.values.should == {:id => 3, :album_id => 1}
401
- MODEL_DB.sqls.length.should == 2
283
+ MODEL_DB.sqls.should == ['SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) WHERE (albums.band_id = 2)']
284
+ a.graph_albums.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
285
+ a.graph_albums.first.tracks.should == [EagerTrack.load(:id => 3, :album_id => 1)]
286
+ MODEL_DB.sqls.should == []
402
287
  end
403
288
 
404
289
  it "should respect :eager_graph when lazily loading a many_to_many association" do
405
- EagerBandMember.dataset.extend(Module.new {
406
- def columns
407
- [:id]
408
- end
409
- def fetch_rows(sql)
410
- @db << sql
411
- yield({:id=>5, :bands_id=>2, :p_k=>6})
412
- yield({:id=>5, :bands_id=>3, :p_k=>6})
413
- end
414
- })
290
+ ds = EagerBandMember.dataset
291
+ def ds.columns() [:id] end
292
+ ds._fetch = [{:id=>5, :bands_id=>2, :p_k=>6}, {:id=>5, :bands_id=>3, :p_k=>6}]
415
293
  a = EagerBand.load(:id=>2)
416
294
  a.graph_members.should == [EagerBandMember.load(:id=>5)]
417
295
  MODEL_DB.sqls.should == ['SELECT members.id, bands.id AS bands_id, bands.p_k FROM (SELECT members.* FROM members INNER JOIN bm ON ((bm.member_id = members.id) AND (bm.band_id = 2))) AS members LEFT OUTER JOIN bm AS bm_0 ON (bm_0.member_id = members.id) LEFT OUTER JOIN bands ON (bands.id = bm_0.band_id) ORDER BY bands.id']
418
296
  a.graph_members.first.bands.should == [EagerBand.load(:id=>2, :p_k=>6), EagerBand.load(:id=>3, :p_k=>6)]
419
- MODEL_DB.sqls.length.should == 1
297
+ MODEL_DB.sqls.should == []
420
298
  end
421
299
 
422
300
  it "should respect :conditions when eagerly loading" do
423
301
  EagerBandMember.many_to_many :good_bands, :clone=>:bands, :conditions=>{:a=>32}
424
302
  a = EagerBandMember.eager(:good_bands).all
425
- a.should be_a_kind_of(Array)
426
- a.size.should == 1
427
- a.first.should be_a_kind_of(EagerBandMember)
428
- a.first.values.should == {:id => 5}
303
+ a.should == [EagerBandMember.load(:id => 5)]
429
304
  MODEL_DB.sqls.should == ['SELECT * FROM members', 'SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON ((bm.band_id = bands.id) AND (bm.member_id IN (5))) WHERE (a = 32) ORDER BY id']
430
- a = a.first
431
- a.good_bands.should be_a_kind_of(Array)
432
- a.good_bands.size.should == 1
433
- a.good_bands.first.should be_a_kind_of(EagerBand)
434
- a.good_bands.first.values.should == {:id => 2}
435
- MODEL_DB.sqls.length.should == 2
305
+ a.first.good_bands.should == [EagerBand.load(:id => 2)]
306
+ MODEL_DB.sqls.should == []
436
307
 
437
- MODEL_DB.sqls.clear
438
308
  EagerBandMember.many_to_many :good_bands, :clone=>:bands, :conditions=>"x = 1"
439
309
  a = EagerBandMember.eager(:good_bands).all
440
310
  MODEL_DB.sqls.should == ['SELECT * FROM members', 'SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON ((bm.band_id = bands.id) AND (bm.member_id IN (5))) WHERE (x = 1) ORDER BY id']
@@ -442,63 +312,36 @@ describe Sequel::Model, "#eager" do
442
312
 
443
313
  it "should respect :order when eagerly loading" do
444
314
  a = EagerBandMember.eager(:bands).all
445
- a.should be_a_kind_of(Array)
446
- a.size.should == 1
447
- a.first.should be_a_kind_of(EagerBandMember)
448
- a.first.values.should == {:id => 5}
315
+ a.should == [EagerBandMember.load(:id => 5)]
449
316
  MODEL_DB.sqls.should == ['SELECT * FROM members', 'SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON ((bm.band_id = bands.id) AND (bm.member_id IN (5))) ORDER BY id']
450
- a = a.first
451
- a.bands.should be_a_kind_of(Array)
452
- a.bands.size.should == 1
453
- a.bands.first.should be_a_kind_of(EagerBand)
454
- a.bands.first.values.should == {:id => 2}
455
- MODEL_DB.sqls.length.should == 2
317
+ a.first.bands.should == [EagerBand.load(:id => 2)]
318
+ MODEL_DB.sqls.should == []
456
319
  end
457
320
 
458
321
  it "should populate the reciprocal many_to_one association when eagerly loading the one_to_many association" do
459
322
  a = EagerAlbum.eager(:tracks).all
460
- a.should be_a_kind_of(Array)
461
- a.size.should == 1
462
- a.first.should be_a_kind_of(EagerAlbum)
463
- a.first.values.should == {:id => 1, :band_id => 2}
323
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
464
324
  MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE (tracks.album_id IN (1))']
465
- a = a.first
466
- a.tracks.should be_a_kind_of(Array)
467
- a.tracks.size.should == 1
468
- a.tracks.first.should be_a_kind_of(EagerTrack)
469
- a.tracks.first.values.should == {:id => 3, :album_id=>1}
470
- a.tracks.first.album.should be_a_kind_of(EagerAlbum)
471
- a.tracks.first.album.should == a
472
- MODEL_DB.sqls.length.should == 2
325
+ a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
326
+ a.first.tracks.first.album.should == a.first
327
+ MODEL_DB.sqls.should == []
473
328
  end
474
329
 
475
330
  it "should cache the negative lookup when eagerly loading a many_to_one association" do
476
331
  a = EagerAlbum.eager(:band).filter(:id=>101).all
477
- a.should be_a_kind_of(Array)
478
- a.size.should == 1
479
- a.first.should be_a_kind_of(EagerAlbum)
480
- a.first.values.should == {:id => 101, :band_id => 101}
332
+ a.should == [EagerAlbum.load(:id => 101, :band_id => 101)]
481
333
  MODEL_DB.sqls.should == ['SELECT * FROM albums WHERE (id = 101)', 'SELECT * FROM bands WHERE (bands.id IN (101))']
482
- a = a.first
483
- a.associations.fetch(:band, 2).should == nil
484
- a.band.should == nil
485
- MODEL_DB.sqls.length.should == 2
334
+ a.first.associations.fetch(:band, 2).should be_nil
335
+ a.first.band.should be_nil
336
+ MODEL_DB.sqls.should == []
486
337
  end
487
338
 
488
339
  it "should cache the negative lookup when eagerly loading a *_to_many associations" do
489
340
  a = EagerBand.eager(:albums).filter('id > 100').all
490
- a.should be_a_kind_of(Array)
491
- a.size.should == 2
492
- a.first.should be_a_kind_of(EagerBand)
493
- a.first.values.should == {:id => 101}
494
- a.last.values.should == {:id => 102}
341
+ a.should == [EagerBand.load(:id => 101), EagerBand.load(:id =>102)]
495
342
  MODEL_DB.sqls.should == ['SELECT * FROM bands WHERE (id > 100)', 'SELECT * FROM albums WHERE (albums.band_id IN (101, 102))', "SELECT * FROM tracks WHERE (tracks.album_id IN (101))"]
496
- a.first.associations[:albums].should be_a_kind_of(Array)
497
- a.first.albums.length.should == 1
498
- a.first.albums.first.should be_a_kind_of(EagerAlbum)
499
- a.last.associations[:albums].should == []
500
- a.last.albums.should == []
501
- MODEL_DB.sqls.length.should == 3
343
+ a.map{|b| b.associations[:albums]}.should == [[EagerAlbum.load({:band_id=>101, :id=>101})], []]
344
+ MODEL_DB.sqls.should == []
502
345
  end
503
346
 
504
347
  it "should use the association's block when eager loading by default" do
@@ -509,7 +352,6 @@ describe Sequel::Model, "#eager" do
509
352
  it "should use the eager_block option when eager loading if given" do
510
353
  EagerBand.eager(:good_albums).all
511
354
  MODEL_DB.sqls.should == ['SELECT * FROM bands', "SELECT * FROM albums WHERE ((albums.band_id IN (2)) AND (name = 'good'))"]
512
- MODEL_DB.sqls.clear
513
355
  EagerBand.eager(:good_albums=>:good_tracks).all
514
356
  MODEL_DB.sqls.should == ['SELECT * FROM bands', "SELECT * FROM albums WHERE ((albums.band_id IN (2)) AND (name = 'good'))", "SELECT * FROM tracks WHERE ((tracks.album_id IN (1)) AND (name = 'Good'))"]
515
357
  end
@@ -522,34 +364,31 @@ describe Sequel::Model, "#eager" do
522
364
  it "should respect the association's :select option" do
523
365
  EagerAlbum.eager(:band_name).all
524
366
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT id, name FROM bands WHERE (bands.id IN (2))"]
525
- MODEL_DB.sqls.clear
526
367
  EagerAlbum.eager(:track_names).all
527
368
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT id, name FROM tracks WHERE (tracks.album_id IN (1))"]
528
- MODEL_DB.sqls.clear
529
369
  EagerAlbum.eager(:genre_names).all
530
370
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT id, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
531
371
  end
532
372
 
373
+ it "should respect many_to_one association's :qualify option" do
374
+ EagerAlbum.many_to_one :special_band, :class=>:EagerBand, :qualify=>false, :key=>:band_id
375
+ EagerBand.dataset._fetch = {:id=>2}
376
+ as = EagerAlbum.eager(:special_band).all
377
+ MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM bands WHERE (id IN (2))"]
378
+ as.map{|a| a.special_band}.should == [EagerBand.load(:id=>2)]
379
+ MODEL_DB.sqls.should == []
380
+ end
381
+
533
382
  it "should respect the association's :primary_key option" do
534
383
  EagerAlbum.many_to_one :special_band, :class=>:EagerBand, :primary_key=>:p_k, :key=>:band_id
535
- EagerBand.dataset.extend(Module.new {
536
- def fetch_rows(sql)
537
- MODEL_DB.sqls << sql
538
- yield({:p_k=>2, :id=>1})
539
- end
540
- })
384
+ EagerBand.dataset._fetch = {:p_k=>2, :id=>1}
541
385
  as = EagerAlbum.eager(:special_band).all
542
386
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM bands WHERE (bands.p_k IN (2))"]
543
387
  as.length.should == 1
544
388
  as.first.special_band.should == EagerBand.load(:p_k=>2, :id=>1)
545
- MODEL_DB.sqls.clear
389
+
546
390
  EagerAlbum.one_to_many :special_tracks, :class=>:EagerTrack, :primary_key=>:band_id, :key=>:album_id
547
- EagerTrack.dataset.extend(Module.new {
548
- def fetch_rows(sql)
549
- MODEL_DB.sqls << sql
550
- yield({:album_id=>2, :id=>1})
551
- end
552
- })
391
+ EagerTrack.dataset._fetch = {:album_id=>2, :id=>1}
553
392
  as = EagerAlbum.eager(:special_tracks).all
554
393
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM tracks WHERE (tracks.album_id IN (2))"]
555
394
  as.length.should == 1
@@ -558,12 +397,7 @@ describe Sequel::Model, "#eager" do
558
397
 
559
398
  it "should respect the many_to_one association's composite keys" do
560
399
  EagerAlbum.many_to_one :special_band, :class=>:EagerBand, :primary_key=>[:id, :p_k], :key=>[:band_id, :id]
561
- EagerBand.dataset.extend(Module.new {
562
- def fetch_rows(sql)
563
- MODEL_DB.sqls << sql
564
- yield({:p_k=>1, :id=>2})
565
- end
566
- })
400
+ EagerBand.dataset._fetch = {:p_k=>1, :id=>2}
567
401
  as = EagerAlbum.eager(:special_band).all
568
402
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM bands WHERE ((bands.id, bands.p_k) IN ((2, 1)))"]
569
403
  as.length.should == 1
@@ -572,12 +406,7 @@ describe Sequel::Model, "#eager" do
572
406
 
573
407
  it "should respect the one_to_many association's composite keys" do
574
408
  EagerAlbum.one_to_many :special_tracks, :class=>:EagerTrack, :primary_key=>[:band_id, :id], :key=>[:id, :album_id]
575
- EagerTrack.dataset.extend(Module.new {
576
- def fetch_rows(sql)
577
- MODEL_DB.sqls << sql
578
- yield({:album_id=>1, :id=>2})
579
- end
580
- })
409
+ EagerTrack.dataset._fetch = {:album_id=>1, :id=>2}
581
410
  as = EagerAlbum.eager(:special_tracks).all
582
411
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM tracks WHERE ((tracks.id, tracks.album_id) IN ((2, 1)))"]
583
412
  as.length.should == 1
@@ -586,13 +415,7 @@ describe Sequel::Model, "#eager" do
586
415
 
587
416
  it "should respect many_to_many association's composite keys" do
588
417
  EagerAlbum.many_to_many :special_genres, :class=>:EagerGenre, :left_primary_key=>[:band_id, :id], :left_key=>[:l1, :l2], :right_primary_key=>[:xxx, :id], :right_key=>[:r1, :r2], :join_table=>:ag
589
- EagerGenre.dataset.extend(Module.new {
590
- def fetch_rows(sql)
591
- MODEL_DB.sqls << sql
592
- yield({:x_foreign_key_0_x=>2, :x_foreign_key_1_x=>1, :id=>5})
593
- yield({:x_foreign_key_0_x=>2, :x_foreign_key_1_x=>1, :id=>6})
594
- end
595
- })
418
+ EagerGenre.dataset._fetch = [{:x_foreign_key_0_x=>2, :x_foreign_key_1_x=>1, :id=>5}, {:x_foreign_key_0_x=>2, :x_foreign_key_1_x=>1, :id=>6}]
596
419
  as = EagerAlbum.eager(:special_genres).all
597
420
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.l1 AS x_foreign_key_0_x, ag.l2 AS x_foreign_key_1_x FROM genres INNER JOIN ag ON ((ag.r1 = genres.xxx) AND (ag.r2 = genres.id) AND ((ag.l1, ag.l2) IN ((2, 1))))"]
598
421
  as.length.should == 1
@@ -601,13 +424,7 @@ describe Sequel::Model, "#eager" do
601
424
 
602
425
  it "should respect many_to_many association's :left_primary_key and :right_primary_key options" do
603
426
  EagerAlbum.many_to_many :special_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_primary_key=>:xxx, :right_key=>:genre_id, :join_table=>:ag
604
- EagerGenre.dataset.extend(Module.new {
605
- def fetch_rows(sql)
606
- MODEL_DB.sqls << sql
607
- yield({:x_foreign_key_x=>2, :id=>5})
608
- yield({:x_foreign_key_x=>2, :id=>6})
609
- end
610
- })
427
+ EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}]
611
428
  as = EagerAlbum.eager(:special_genres).all
612
429
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.xxx) AND (ag.album_id IN (2)))"]
613
430
  as.length.should == 1
@@ -616,14 +433,7 @@ describe Sequel::Model, "#eager" do
616
433
 
617
434
  it "should respect the :limit option on a one_to_many association" do
618
435
  EagerAlbum.one_to_many :first_two_tracks, :class=>:EagerTrack, :key=>:album_id, :limit=>2
619
- EagerTrack.dataset.extend(Module.new {
620
- def fetch_rows(sql)
621
- MODEL_DB.sqls << sql
622
- yield({:album_id=>1, :id=>2})
623
- yield({:album_id=>1, :id=>3})
624
- yield({:album_id=>1, :id=>4})
625
- end
626
- })
436
+ EagerTrack.dataset._fetch = [{:album_id=>1, :id=>2}, {:album_id=>1, :id=>3}, {:album_id=>1, :id=>4}]
627
437
  as = EagerAlbum.eager(:first_two_tracks).all
628
438
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM tracks WHERE (tracks.album_id IN (1))"]
629
439
  as.length.should == 1
@@ -644,7 +454,7 @@ describe Sequel::Model, "#eager" do
644
454
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
645
455
  MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks WHERE (tracks.album_id IN (1))) AS t1 WHERE (x_sequel_row_number_x <= 2)']
646
456
  a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
647
- MODEL_DB.sqls.length.should == 2
457
+ MODEL_DB.sqls.should == []
648
458
  end
649
459
 
650
460
  it "should respect the :limit option with an offset on a one_to_many association using the :window_function strategy" do
@@ -654,7 +464,7 @@ describe Sequel::Model, "#eager" do
654
464
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
655
465
  MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks WHERE (tracks.album_id IN (1))) AS t1 WHERE ((x_sequel_row_number_x >= 2) AND (x_sequel_row_number_x < 4))']
656
466
  a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
657
- MODEL_DB.sqls.length.should == 2
467
+ MODEL_DB.sqls.should == []
658
468
  end
659
469
 
660
470
  it "should respect the :limit option on a one_to_many association using the :correlated_subquery strategy" do
@@ -663,7 +473,7 @@ describe Sequel::Model, "#eager" do
663
473
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
664
474
  MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE ((tracks.album_id IN (1)) AND (tracks.id IN (SELECT t1.id FROM tracks AS t1 WHERE (t1.album_id = tracks.album_id) ORDER BY name LIMIT 2))) ORDER BY name']
665
475
  a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
666
- MODEL_DB.sqls.length.should == 2
476
+ MODEL_DB.sqls.should == []
667
477
  end
668
478
 
669
479
  it "should respect the :limit option with an offset on a one_to_many association using the :correlated_subquery strategy" do
@@ -672,25 +482,18 @@ describe Sequel::Model, "#eager" do
672
482
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
673
483
  MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE ((tracks.album_id IN (1)) AND (tracks.id IN (SELECT t1.id FROM tracks AS t1 WHERE (t1.album_id = tracks.album_id) ORDER BY name LIMIT 2 OFFSET 1))) ORDER BY name']
674
484
  a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
675
- MODEL_DB.sqls.length.should == 2
485
+ MODEL_DB.sqls.should == []
676
486
  end
677
487
 
678
488
  it "should respect the limit option on a many_to_many association" do
679
489
  EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>2
680
- EagerGenre.dataset.extend(Module.new {
681
- def fetch_rows(sql)
682
- MODEL_DB.sqls << sql
683
- yield({:x_foreign_key_x=>2, :id=>5})
684
- yield({:x_foreign_key_x=>2, :id=>6})
685
- yield({:x_foreign_key_x=>2, :id=>7})
686
- end
687
- })
490
+ EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}, {:x_foreign_key_x=>2, :id=>7}]
688
491
  as = EagerAlbum.eager(:first_two_genres).all
689
492
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2)))"]
690
493
  as.length.should == 1
691
494
  as.first.first_two_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
692
495
 
693
- MODEL_DB.reset
496
+ EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}, {:x_foreign_key_x=>2, :id=>7}]
694
497
  EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>[2, 1]
695
498
  as = EagerAlbum.eager(:first_two_genres).all
696
499
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2)))"]
@@ -701,19 +504,13 @@ describe Sequel::Model, "#eager" do
701
504
  it "should respect the limit option on a many_to_many association using the :window_function strategy" do
702
505
  EagerGenre.dataset.meta_def(:supports_window_functions?){true}
703
506
  EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :eager_limit_strategy=>true, :limit=>2, :order=>:name
704
- EagerGenre.dataset.extend(Module.new {
705
- def fetch_rows(sql)
706
- MODEL_DB.sqls << sql
707
- yield({:x_foreign_key_x=>2, :id=>5})
708
- yield({:x_foreign_key_x=>2, :id=>6})
709
- end
710
- })
507
+ EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}]
711
508
  as = EagerAlbum.eager(:first_two_genres).all
712
509
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM (SELECT genres.*, ag.album_id AS x_foreign_key_x, row_number() OVER (PARTITION BY ag.album_id ORDER BY name) AS x_sequel_row_number_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2)))) AS t1 WHERE (x_sequel_row_number_x <= 2)"]
713
510
  as.length.should == 1
714
511
  as.first.first_two_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
715
512
 
716
- MODEL_DB.reset
513
+ EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}]
717
514
  EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :eager_limit_strategy=>true, :limit=>[2, 1], :order=>:name
718
515
  as = EagerAlbum.eager(:first_two_genres).all
719
516
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM (SELECT genres.*, ag.album_id AS x_foreign_key_x, row_number() OVER (PARTITION BY ag.album_id ORDER BY name) AS x_sequel_row_number_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2)))) AS t1 WHERE ((x_sequel_row_number_x >= 2) AND (x_sequel_row_number_x < 4))"]
@@ -723,19 +520,13 @@ describe Sequel::Model, "#eager" do
723
520
 
724
521
  it "should respect the limit option on a many_to_many association using the :correlated_subquery strategy" do
725
522
  EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :eager_limit_strategy=>:correlated_subquery, :limit=>2, :order=>:name
726
- EagerGenre.dataset.extend(Module.new {
727
- def fetch_rows(sql)
728
- MODEL_DB.sqls << sql
729
- yield({:x_foreign_key_x=>2, :id=>5})
730
- yield({:x_foreign_key_x=>2, :id=>6})
731
- end
732
- })
523
+ EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}]
733
524
  as = EagerAlbum.eager(:first_two_genres).all
734
525
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2))) WHERE (genres.id IN (SELECT t1.id FROM genres AS t1 INNER JOIN ag AS t2 ON ((t2.genre_id = t1.id) AND (t2.album_id = ag.album_id)) ORDER BY name LIMIT 2)) ORDER BY name"]
735
526
  as.length.should == 1
736
527
  as.first.first_two_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
737
528
 
738
- MODEL_DB.reset
529
+ EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}]
739
530
  EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :eager_limit_strategy=>:correlated_subquery, :limit=>[2, 1], :order=>:name
740
531
  as = EagerAlbum.eager(:first_two_genres).all
741
532
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2))) WHERE (genres.id IN (SELECT t1.id FROM genres AS t1 INNER JOIN ag AS t2 ON ((t2.genre_id = t1.id) AND (t2.album_id = ag.album_id)) ORDER BY name LIMIT 2 OFFSET 1)) ORDER BY name"]
@@ -757,27 +548,17 @@ describe Sequel::Model, "#eager" do
757
548
  records.each{|r| r.associations[:special_genres] = items}
758
549
  end)
759
550
  a = EagerAlbum.eager(:special_genres, :special_tracks, :special_band).all
760
- a.should be_a_kind_of(Array)
761
- a.size.should == 1
762
- a.first.should be_a_kind_of(EagerAlbum)
763
- a.first.values.should == {:id => 1, :band_id => 2}
764
- MODEL_DB.sqls.length.should == 4
765
- MODEL_DB.sqls[0].should == 'SELECT * FROM albums'
766
- MODEL_DB.sqls[1..-1].should(include('SELECT * FROM bands WHERE (album_id IN (1, 2)) ORDER BY name LIMIT 1'))
767
- MODEL_DB.sqls[1..-1].should(include('SELECT * FROM tracks WHERE (album_id IN (1, 2))'))
768
- MODEL_DB.sqls[1..-1].should(include('SELECT * FROM genres INNER JOIN ag USING (genre_id) WHERE (album_id IN (1))'))
551
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
552
+ sqls = MODEL_DB.sqls
553
+ sqls.shift.should == 'SELECT * FROM albums'
554
+ sqls.sort.should == ['SELECT * FROM bands WHERE (album_id IN (1, 2)) ORDER BY name LIMIT 1',
555
+ 'SELECT * FROM genres INNER JOIN ag USING (genre_id) WHERE (album_id IN (1))',
556
+ 'SELECT * FROM tracks WHERE (album_id IN (1, 2))']
769
557
  a = a.first
770
- a.special_band.should be_a_kind_of(EagerBand)
771
- a.special_band.values.should == {:id => 2}
772
- a.special_tracks.should be_a_kind_of(Array)
773
- a.special_tracks.size.should == 1
774
- a.special_tracks.first.should be_a_kind_of(EagerTrack)
775
- a.special_tracks.first.values.should == {:id => 3, :album_id=>1}
776
- a.special_genres.should be_a_kind_of(Array)
777
- a.special_genres.size.should == 1
778
- a.special_genres.first.should be_a_kind_of(EagerGenre)
779
- a.special_genres.first.values.should == {:id => 4}
780
- MODEL_DB.sqls.length.should == 4
558
+ a.special_band.should == EagerBand.load(:id => 2)
559
+ a.special_tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
560
+ a.special_genres.should == [EagerGenre.load(:id => 4)]
561
+ MODEL_DB.sqls.should == []
781
562
  end
782
563
 
783
564
  it "should raise an error if you use an :eager_loader proc with the wrong arity" do
@@ -797,13 +578,7 @@ describe Sequel::Model, "#eager" do
797
578
 
798
579
  it "should respect :uniq option when eagerly loading many_to_many associations" do
799
580
  EagerAlbum.many_to_many :al_genres, :class=>'EagerGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :uniq=>true
800
- EagerGenre.dataset.extend(Module.new {
801
- def fetch_rows(sql)
802
- MODEL_DB.sqls << sql
803
- yield({:x_foreign_key_x=>1, :id=>8})
804
- yield({:x_foreign_key_x=>1, :id=>8})
805
- end
806
- })
581
+ EagerGenre.dataset._fetch = [{:x_foreign_key_x=>1, :id=>8}, {:x_foreign_key_x=>1, :id=>8}]
807
582
  a = EagerAlbum.eager(:al_genres).all.first
808
583
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
809
584
  a.should == EagerAlbum.load(:id => 1, :band_id => 2)
@@ -820,15 +595,10 @@ describe Sequel::Model, "#eager" do
820
595
 
821
596
  it "should eagerly load a many_to_one association with custom eager block" do
822
597
  a = EagerAlbum.eager(:band => proc {|ds| ds.select(:id, :name)}).all
823
- a.should be_a_kind_of(Array)
824
- a.size.should == 1
825
- a.first.should be_a_kind_of(EagerAlbum)
826
- a.first.values.should == {:id => 1, :band_id => 2}
598
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
827
599
  MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT id, name FROM bands WHERE (bands.id IN (2))']
828
- a = a.first
829
- a.band.should be_a_kind_of(EagerBand)
830
- a.band.values.should == {:id => 2}
831
- MODEL_DB.sqls.length.should == 2
600
+ a.first.band.should == EagerBand.load(:id => 2)
601
+ MODEL_DB.sqls.should == []
832
602
  end
833
603
 
834
604
  it "should eagerly load a one_to_one association with custom eager block" do
@@ -837,122 +607,78 @@ describe Sequel::Model, "#eager" do
837
607
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
838
608
  MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT id FROM tracks WHERE (tracks.album_id IN (1))']
839
609
  a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
840
- MODEL_DB.sqls.length.should == 2
610
+ MODEL_DB.sqls.should == []
841
611
  end
842
612
 
843
613
  it "should eagerly load a one_to_many association with custom eager block" do
844
614
  a = EagerAlbum.eager(:tracks => proc {|ds| ds.select(:id)}).all
845
- a.should be_a_kind_of(Array)
846
- a.size.should == 1
847
- a.first.should be_a_kind_of(EagerAlbum)
848
- a.first.values.should == {:id => 1, :band_id => 2}
615
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
849
616
  MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT id FROM tracks WHERE (tracks.album_id IN (1))']
850
- a = a.first
851
- a.tracks.should be_a_kind_of(Array)
852
- a.tracks.size.should == 1
853
- a.tracks.first.should be_a_kind_of(EagerTrack)
854
- a.tracks.first.values.should == {:id => 3, :album_id=>1}
855
- MODEL_DB.sqls.length.should == 2
617
+ a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
618
+ MODEL_DB.sqls.should == []
856
619
  end
857
620
 
858
621
  it "should eagerly load a many_to_many association with custom eager block" do
859
622
  a = EagerAlbum.eager(:genres => proc {|ds| ds.select(:name)}).all
860
- a.should be_a_kind_of(Array)
861
- a.size.should == 1
862
- a.first.should be_a_kind_of(EagerAlbum)
863
- a.first.values.should == {:id => 1, :band_id => 2}
623
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
864
624
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT name, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
865
- a = a.first
866
- a.genres.should be_a_kind_of(Array)
867
- a.genres.size.should == 1
868
- a.genres.first.should be_a_kind_of(EagerGenre)
869
- a.genres.first.values.should == {:id => 4}
870
- MODEL_DB.sqls.length.should == 2
625
+ a.first.genres.should == [EagerGenre.load(:id => 4)]
626
+ MODEL_DB.sqls.should == []
871
627
  end
872
628
 
873
629
  it "should allow cascading of eager loading within a custom eager block" do
874
630
  a = EagerTrack.eager(:album => proc {|ds| ds.eager(:band => :members)}).all
875
- a.should be_a_kind_of(Array)
876
- a.size.should == 1
877
- a.first.should be_a_kind_of(EagerTrack)
878
- a.first.values.should == {:id => 3, :album_id => 1}
879
- MODEL_DB.sqls.length.should == 4
631
+ a.should == [EagerTrack.load(:id => 3, :album_id => 1)]
880
632
  MODEL_DB.sqls.should == ['SELECT * FROM tracks',
881
633
  'SELECT * FROM albums WHERE (albums.id IN (1))',
882
634
  'SELECT * FROM bands WHERE (bands.id IN (2))',
883
635
  "SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON ((bm.member_id = members.id) AND (bm.band_id IN (2)))"]
884
636
  a = a.first
885
- a.album.should be_a_kind_of(EagerAlbum)
886
- a.album.values.should == {:id => 1, :band_id => 2}
887
- a.album.band.should be_a_kind_of(EagerBand)
888
- a.album.band.values.should == {:id => 2}
889
- a.album.band.members.should be_a_kind_of(Array)
890
- a.album.band.members.size.should == 1
891
- a.album.band.members.first.should be_a_kind_of(EagerBandMember)
892
- a.album.band.members.first.values.should == {:id => 5}
893
- MODEL_DB.sqls.length.should == 4
637
+ a.album.should == EagerAlbum.load(:id => 1, :band_id => 2)
638
+ a.album.band.should == EagerBand.load(:id => 2)
639
+ a.album.band.members.should == [EagerBandMember.load(:id => 5)]
640
+ MODEL_DB.sqls.should == []
894
641
  end
895
642
 
896
643
  it "should allow cascading of eager loading with custom callback with hash value" do
897
644
  a = EagerTrack.eager(:album=>{proc{|ds| ds.select(:id, :band_id)}=>{:band => :members}}).all
898
- a.should be_a_kind_of(Array)
899
- a.size.should == 1
900
- a.first.should be_a_kind_of(EagerTrack)
901
- a.first.values.should == {:id => 3, :album_id => 1}
902
- MODEL_DB.sqls.length.should == 4
645
+ a.should == [EagerTrack.load(:id => 3, :album_id => 1)]
903
646
  MODEL_DB.sqls.should == ['SELECT * FROM tracks',
904
647
  'SELECT id, band_id FROM albums WHERE (albums.id IN (1))',
905
648
  'SELECT * FROM bands WHERE (bands.id IN (2))',
906
649
  "SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON ((bm.member_id = members.id) AND (bm.band_id IN (2)))"]
907
650
  a = a.first
908
- a.album.should be_a_kind_of(EagerAlbum)
909
- a.album.values.should == {:id => 1, :band_id => 2}
910
- a.album.band.should be_a_kind_of(EagerBand)
911
- a.album.band.values.should == {:id => 2}
912
- a.album.band.members.should be_a_kind_of(Array)
913
- a.album.band.members.size.should == 1
914
- a.album.band.members.first.should be_a_kind_of(EagerBandMember)
915
- a.album.band.members.first.values.should == {:id => 5}
916
- MODEL_DB.sqls.length.should == 4
651
+ a.album.should == EagerAlbum.load(:id => 1, :band_id => 2)
652
+ a.album.band.should == EagerBand.load(:id => 2)
653
+ a.album.band.members.should == [EagerBandMember.load(:id => 5)]
654
+ MODEL_DB.sqls.should == []
917
655
  end
918
656
 
919
657
  it "should allow cascading of eager loading with custom callback with symbol value" do
920
658
  a = EagerTrack.eager(:album=>{proc{|ds| ds.select(:id, :band_id)}=>:band}).all
921
- a.should be_a_kind_of(Array)
922
- a.size.should == 1
923
- a.first.should be_a_kind_of(EagerTrack)
924
- a.first.values.should == {:id => 3, :album_id => 1}
925
- MODEL_DB.sqls.length.should == 3
659
+ a.should == [EagerTrack.load(:id => 3, :album_id => 1)]
926
660
  MODEL_DB.sqls.should == ['SELECT * FROM tracks',
927
661
  'SELECT id, band_id FROM albums WHERE (albums.id IN (1))',
928
662
  'SELECT * FROM bands WHERE (bands.id IN (2))']
929
663
  a = a.first
930
- a.album.should be_a_kind_of(EagerAlbum)
931
- a.album.values.should == {:id => 1, :band_id => 2}
932
- a.album.band.should be_a_kind_of(EagerBand)
933
- a.album.band.values.should == {:id => 2}
934
- MODEL_DB.sqls.length.should == 3
664
+ a.album.should == EagerAlbum.load(:id => 1, :band_id => 2)
665
+ a.album.band.should == EagerBand.load(:id => 2)
666
+ MODEL_DB.sqls.should == []
935
667
  end
936
668
 
937
669
  it "should allow cascading of eager loading with custom callback with array value" do
938
670
  a = EagerTrack.eager(:album=>{proc{|ds| ds.select(:id, :band_id)}=>[:band, :band_name]}).all
939
- a.should be_a_kind_of(Array)
940
- a.size.should == 1
941
- a.first.should be_a_kind_of(EagerTrack)
942
- a.first.values.should == {:id => 3, :album_id => 1}
943
- MODEL_DB.sqls.length.should == 4
944
- MODEL_DB.sqls[0..1].should == ['SELECT * FROM tracks',
671
+ a.should == [EagerTrack.load(:id => 3, :album_id => 1)]
672
+ sqls = MODEL_DB.sqls
673
+ sqls.slice!(0..1).should == ['SELECT * FROM tracks',
945
674
  'SELECT id, band_id FROM albums WHERE (albums.id IN (1))']
946
- MODEL_DB.sqls[2..-1].sort.should == ['SELECT * FROM bands WHERE (bands.id IN (2))',
675
+ sqls.sort.should == ['SELECT * FROM bands WHERE (bands.id IN (2))',
947
676
  'SELECT id, name FROM bands WHERE (bands.id IN (2))']
948
677
  a = a.first
949
- a.album.should be_a_kind_of(EagerAlbum)
950
- a.album.values.should == {:id => 1, :band_id => 2}
951
- a.album.band.should be_a_kind_of(EagerBand)
952
- a.album.band.values.should == {:id => 2}
953
- a.album.band_name.should be_a_kind_of(EagerBand)
954
- a.album.band_name.values.should == {:id => 2}
955
- MODEL_DB.sqls.length.should == 4
678
+ a.album.should == EagerAlbum.load(:id => 1, :band_id => 2)
679
+ a.album.band.should == EagerBand.load(:id => 2)
680
+ a.album.band_name.should == EagerBand.load(:id => 2)
681
+ MODEL_DB.sqls.should == []
956
682
  end
957
683
 
958
684
  it "should call both association and custom eager blocks" do
@@ -962,28 +688,7 @@ describe Sequel::Model, "#eager" do
962
688
  end
963
689
 
964
690
  describe Sequel::Model, "#eager_graph" do
965
- after(:all) do
966
- class ::MockDataset
967
- alias clone orig_clone
968
- end
969
- end
970
-
971
691
  before(:all) do
972
- class ::MockDataset
973
- alias orig_clone clone
974
- def clone(opts = {})
975
- c = super()
976
- c.opts = @opts.merge(opts)
977
- c.instance_variable_set(:@columns, (@columns.dup if @columns))
978
- c
979
- end
980
- def select_columns(*a)
981
- ds = select(*a)
982
- ds.instance_variable_set(:@columns, a)
983
- ds
984
- end
985
- end
986
-
987
692
  class ::GraphAlbum < Sequel::Model(:albums)
988
693
  dataset.opts[:from] = [:albums]
989
694
  columns :id, :band_id
@@ -1020,6 +725,9 @@ describe Sequel::Model, "#eager_graph" do
1020
725
  many_to_many :bands, :class=>'GraphBand', :left_key=>:member_id, :right_key=>:band_id, :join_table=>:bm
1021
726
  end
1022
727
  end
728
+ after(:all) do
729
+ [:GraphAlbum, :GraphBand, :GraphTrack, :GraphGenre, :GraphBandMember].each{|x| Object.send(:remove_const, x)}
730
+ end
1023
731
 
1024
732
  it "should raise an error if called without a symbol or hash" do
1025
733
  proc{GraphAlbum.eager_graph(Object.new)}.should raise_error(Sequel::Error)
@@ -1028,35 +736,24 @@ describe Sequel::Model, "#eager_graph" do
1028
736
  it "should not split results and assign associations if ungraphed is called" do
1029
737
  ds = GraphAlbum.eager_graph(:band).ungraphed
1030
738
  ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
1031
- def ds.fetch_rows(sql, &block)
1032
- yield({:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>3})
1033
- end
739
+ ds._fetch = {:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>3}
1034
740
  ds.all.should == [GraphAlbum.load(:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>3)]
1035
741
  end
1036
742
 
1037
743
  it "should eagerly load a single many_to_one association" do
1038
744
  ds = GraphAlbum.eager_graph(:band)
1039
745
  ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
1040
- def ds.fetch_rows(sql, &block)
1041
- yield({:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>3})
1042
- end
746
+ ds._fetch = {:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>3}
1043
747
  a = ds.all
1044
- a.should be_a_kind_of(Array)
1045
- a.size.should == 1
1046
- a.first.should be_a_kind_of(GraphAlbum)
1047
- a.first.values.should == {:id => 1, :band_id => 2}
1048
- a = a.first
1049
- a.band.should be_a_kind_of(GraphBand)
1050
- a.band.values.should == {:id => 2, :vocalist_id=>3}
748
+ a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
749
+ a.first.band.should == GraphBand.load(:id => 2, :vocalist_id=>3)
1051
750
  end
1052
751
 
1053
752
  it "should eagerly load a single one_to_one association" do
1054
753
  GraphAlbum.one_to_one :track, :class=>'GraphTrack', :key=>:album_id
1055
754
  ds = GraphAlbum.eager_graph(:track)
1056
755
  ds.sql.should == 'SELECT albums.id, albums.band_id, track.id AS track_id, track.album_id FROM albums LEFT OUTER JOIN tracks AS track ON (track.album_id = albums.id)'
1057
- def ds.fetch_rows(sql, &block)
1058
- yield({:id=>1, :band_id=>2, :track_id=>3, :album_id=>1})
1059
- end
756
+ ds._fetch = {:id=>1, :band_id=>2, :track_id=>3, :album_id=>1}
1060
757
  a = ds.all
1061
758
  a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
1062
759
  a.first.track.should == GraphTrack.load(:id => 3, :album_id=>1)
@@ -1065,130 +762,88 @@ describe Sequel::Model, "#eager_graph" do
1065
762
  it "should eagerly load a single one_to_many association" do
1066
763
  ds = GraphAlbum.eager_graph(:tracks)
1067
764
  ds.sql.should == 'SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)'
1068
- def ds.fetch_rows(sql, &block)
1069
- yield({:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1})
1070
- end
765
+ ds._fetch = {:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1}
1071
766
  a = ds.all
1072
- a.should be_a_kind_of(Array)
1073
- a.size.should == 1
1074
- a.first.should be_a_kind_of(GraphAlbum)
1075
- a.first.values.should == {:id => 1, :band_id => 2}
1076
- a = a.first
1077
- a.tracks.should be_a_kind_of(Array)
1078
- a.tracks.size.should == 1
1079
- a.tracks.first.should be_a_kind_of(GraphTrack)
1080
- a.tracks.first.values.should == {:id => 3, :album_id=>1}
767
+ a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
768
+ a.first.tracks.should == [GraphTrack.load(:id => 3, :album_id=>1)]
1081
769
  end
1082
770
 
1083
771
  it "should eagerly load a single many_to_many association" do
1084
772
  ds = GraphAlbum.eager_graph(:genres)
1085
773
  ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id)'
1086
- def ds.fetch_rows(sql, &block)
1087
- yield({:id=>1, :band_id=>2, :genres_id=>4})
1088
- end
774
+ ds._fetch = {:id=>1, :band_id=>2, :genres_id=>4}
1089
775
  a = ds.all
1090
- a.should be_a_kind_of(Array)
1091
- a.size.should == 1
1092
- a.first.should be_a_kind_of(GraphAlbum)
1093
- a.first.values.should == {:id => 1, :band_id => 2}
1094
- a = a.first
1095
- a.genres.should be_a_kind_of(Array)
1096
- a.genres.size.should == 1
1097
- a.genres.first.should be_a_kind_of(GraphGenre)
1098
- a.genres.first.values.should == {:id => 4}
776
+ a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
777
+ a.first.genres.should == [GraphGenre.load(:id => 4)]
1099
778
  end
1100
779
 
780
+ it "should correctly handle an aliased join table in many_to_many" do
781
+ c = Class.new(GraphAlbum)
782
+ c.many_to_many :genres, :clone=>:genres, :join_table=>:ag___ga
783
+ c.eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag AS ga ON (ga.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ga.genre_id)'
784
+
785
+ c.many_to_many :genres, :clone=>:genres, :join_table=>:ag___albums
786
+ c.eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag AS albums_0 ON (albums_0.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = albums_0.genre_id)'
787
+
788
+ c.many_to_many :genres, :clone=>:genres, :join_table=>:ag___genres
789
+ c.eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag AS genres_0 ON (genres_0.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = genres_0.genre_id)'
790
+ end
791
+
1101
792
  it "should eagerly load multiple associations in a single call" do
1102
793
  ds = GraphAlbum.eager_graph(:genres, :tracks, :band)
1103
794
  ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id, tracks.id AS tracks_id, tracks.album_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
1104
- def ds.fetch_rows(sql, &block)
1105
- yield({:id=>1, :band_id=>2, :genres_id=>4, :tracks_id=>3, :album_id=>1, :band_id_0=>2, :vocalist_id=>6})
1106
- end
795
+ ds._fetch = {:id=>1, :band_id=>2, :genres_id=>4, :tracks_id=>3, :album_id=>1, :band_id_0=>2, :vocalist_id=>6}
1107
796
  a = ds.all
1108
- a.should be_a_kind_of(Array)
1109
- a.size.should == 1
1110
- a.first.should be_a_kind_of(GraphAlbum)
1111
- a.first.values.should == {:id => 1, :band_id => 2}
797
+ a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
1112
798
  a = a.first
1113
- a.band.should be_a_kind_of(GraphBand)
1114
- a.band.values.should == {:id => 2, :vocalist_id=>6}
1115
- a.tracks.should be_a_kind_of(Array)
1116
- a.tracks.size.should == 1
1117
- a.tracks.first.should be_a_kind_of(GraphTrack)
1118
- a.tracks.first.values.should == {:id => 3, :album_id=>1}
1119
- a.genres.should be_a_kind_of(Array)
1120
- a.genres.size.should == 1
1121
- a.genres.first.should be_a_kind_of(GraphGenre)
1122
- a.genres.first.values.should == {:id => 4}
799
+ a.band.should == GraphBand.load(:id => 2, :vocalist_id=>6)
800
+ a.tracks.should == [GraphTrack.load({:id => 3, :album_id=>1})]
801
+ a.genres.should == [GraphGenre.load(:id => 4)]
1123
802
  end
1124
803
 
1125
804
  it "should eagerly load multiple associations in separate calls" do
1126
805
  ds = GraphAlbum.eager_graph(:genres).eager_graph(:tracks).eager_graph(:band)
1127
806
  ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id, tracks.id AS tracks_id, tracks.album_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
1128
- def ds.fetch_rows(sql, &block)
1129
- yield({:id=>1, :band_id=>2, :genres_id=>4, :tracks_id=>3, :album_id=>1, :band_id_0=>2, :vocalist_id=>6})
1130
- end
807
+ ds._fetch = {:id=>1, :band_id=>2, :genres_id=>4, :tracks_id=>3, :album_id=>1, :band_id_0=>2, :vocalist_id=>6}
1131
808
  a = ds.all
1132
- a.should be_a_kind_of(Array)
1133
- a.size.should == 1
1134
- a.first.should be_a_kind_of(GraphAlbum)
1135
- a.first.values.should == {:id => 1, :band_id => 2}
809
+ a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
1136
810
  a = a.first
1137
- a.band.should be_a_kind_of(GraphBand)
1138
- a.band.values.should == {:id => 2, :vocalist_id=>6}
1139
- a.tracks.should be_a_kind_of(Array)
1140
- a.tracks.size.should == 1
1141
- a.tracks.first.should be_a_kind_of(GraphTrack)
1142
- a.tracks.first.values.should == {:id => 3, :album_id=>1}
1143
- a.genres.should be_a_kind_of(Array)
1144
- a.genres.size.should == 1
1145
- a.genres.first.should be_a_kind_of(GraphGenre)
1146
- a.genres.first.values.should == {:id => 4}
811
+ a.band.should == GraphBand.load(:id => 2, :vocalist_id=>6)
812
+ a.tracks.should == [GraphTrack.load({:id => 3, :album_id=>1})]
813
+ a.genres.should == [GraphGenre.load(:id => 4)]
1147
814
  end
1148
815
 
1149
816
  it "should allow cascading of eager loading for associations of associated models" do
1150
817
  ds = GraphTrack.eager_graph(:album=>{:band=>:members})
1151
818
  ds.sql.should == 'SELECT tracks.id, tracks.album_id, album.id AS album_id_0, album.band_id, band.id AS band_id_0, band.vocalist_id, members.id AS members_id FROM tracks LEFT OUTER JOIN albums AS album ON (album.id = tracks.album_id) LEFT OUTER JOIN bands AS band ON (band.id = album.band_id) LEFT OUTER JOIN bm ON (bm.band_id = band.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
1152
- def ds.fetch_rows(sql, &block)
1153
- yield({:id=>3, :album_id=>1, :album_id_0=>1, :band_id=>2, :members_id=>5, :band_id_0=>2, :vocalist_id=>6})
1154
- end
819
+ ds._fetch = {:id=>3, :album_id=>1, :album_id_0=>1, :band_id=>2, :members_id=>5, :band_id_0=>2, :vocalist_id=>6}
1155
820
  a = ds.all
1156
- a.should be_a_kind_of(Array)
1157
- a.size.should == 1
1158
- a.first.should be_a_kind_of(GraphTrack)
1159
- a.first.values.should == {:id => 3, :album_id => 1}
821
+ a.should == [GraphTrack.load(:id => 3, :album_id => 1)]
1160
822
  a = a.first
1161
- a.album.should be_a_kind_of(GraphAlbum)
1162
- a.album.values.should == {:id => 1, :band_id => 2}
1163
- a.album.band.should be_a_kind_of(GraphBand)
1164
- a.album.band.values.should == {:id => 2, :vocalist_id=>6}
1165
- a.album.band.members.should be_a_kind_of(Array)
1166
- a.album.band.members.size.should == 1
1167
- a.album.band.members.first.should be_a_kind_of(GraphBandMember)
1168
- a.album.band.members.first.values.should == {:id => 5}
823
+ a.album.should == GraphAlbum.load(:id => 1, :band_id => 2)
824
+ a.album.band.should == GraphBand.load(:id => 2, :vocalist_id=>6)
825
+ a.album.band.members.should == [GraphBandMember.load(:id => 5)]
1169
826
  end
1170
827
 
1171
828
  it "should allow cascading of eager loading for multiple *_to_many associations, eliminating duplicates caused by cartesian products" do
1172
829
  ds = GraphBand.eager_graph({:albums=>:tracks}, :members)
1173
830
  ds.sql.should == 'SELECT bands.id, bands.vocalist_id, albums.id AS albums_id, albums.band_id, tracks.id AS tracks_id, tracks.album_id, members.id AS members_id FROM bands LEFT OUTER JOIN albums ON (albums.band_id = bands.id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) LEFT OUTER JOIN bm ON (bm.band_id = bands.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
1174
- def ds.fetch_rows(sql, &block)
1175
- yield({:id=>1, :vocalist_id=>2, :albums_id=>3, :band_id=>1, :tracks_id=>4, :album_id=>3, :members_id=>5})
1176
- yield({:id=>1, :vocalist_id=>2, :albums_id=>3, :band_id=>1, :tracks_id=>4, :album_id=>3, :members_id=>6})
1177
- yield({:id=>1, :vocalist_id=>2, :albums_id=>3, :band_id=>1, :tracks_id=>5, :album_id=>3, :members_id=>5})
1178
- yield({:id=>1, :vocalist_id=>2, :albums_id=>3, :band_id=>1, :tracks_id=>5, :album_id=>3, :members_id=>6})
1179
- yield({:id=>1, :vocalist_id=>2, :albums_id=>4, :band_id=>1, :tracks_id=>6, :album_id=>4, :members_id=>5})
1180
- yield({:id=>1, :vocalist_id=>2, :albums_id=>4, :band_id=>1, :tracks_id=>6, :album_id=>4, :members_id=>6})
1181
- yield({:id=>1, :vocalist_id=>2, :albums_id=>4, :band_id=>1, :tracks_id=>7, :album_id=>4, :members_id=>5})
1182
- yield({:id=>1, :vocalist_id=>2, :albums_id=>4, :band_id=>1, :tracks_id=>7, :album_id=>4, :members_id=>6})
1183
- yield({:id=>2, :vocalist_id=>2, :albums_id=>5, :band_id=>2, :tracks_id=>8, :album_id=>5, :members_id=>5})
1184
- yield({:id=>2, :vocalist_id=>2, :albums_id=>5, :band_id=>2, :tracks_id=>8, :album_id=>5, :members_id=>6})
1185
- yield({:id=>2, :vocalist_id=>2, :albums_id=>5, :band_id=>2, :tracks_id=>9, :album_id=>5, :members_id=>5})
1186
- yield({:id=>2, :vocalist_id=>2, :albums_id=>5, :band_id=>2, :tracks_id=>9, :album_id=>5, :members_id=>6})
1187
- yield({:id=>2, :vocalist_id=>2, :albums_id=>6, :band_id=>2, :tracks_id=>1, :album_id=>6, :members_id=>5})
1188
- yield({:id=>2, :vocalist_id=>2, :albums_id=>6, :band_id=>2, :tracks_id=>1, :album_id=>6, :members_id=>6})
1189
- yield({:id=>2, :vocalist_id=>2, :albums_id=>6, :band_id=>2, :tracks_id=>2, :album_id=>6, :members_id=>5})
1190
- yield({:id=>2, :vocalist_id=>2, :albums_id=>6, :band_id=>2, :tracks_id=>2, :album_id=>6, :members_id=>6})
1191
- end
831
+ ds._fetch = [{:id=>1, :vocalist_id=>2, :albums_id=>3, :band_id=>1, :tracks_id=>4, :album_id=>3, :members_id=>5},
832
+ {:id=>1, :vocalist_id=>2, :albums_id=>3, :band_id=>1, :tracks_id=>4, :album_id=>3, :members_id=>6},
833
+ {:id=>1, :vocalist_id=>2, :albums_id=>3, :band_id=>1, :tracks_id=>5, :album_id=>3, :members_id=>5},
834
+ {:id=>1, :vocalist_id=>2, :albums_id=>3, :band_id=>1, :tracks_id=>5, :album_id=>3, :members_id=>6},
835
+ {:id=>1, :vocalist_id=>2, :albums_id=>4, :band_id=>1, :tracks_id=>6, :album_id=>4, :members_id=>5},
836
+ {:id=>1, :vocalist_id=>2, :albums_id=>4, :band_id=>1, :tracks_id=>6, :album_id=>4, :members_id=>6},
837
+ {:id=>1, :vocalist_id=>2, :albums_id=>4, :band_id=>1, :tracks_id=>7, :album_id=>4, :members_id=>5},
838
+ {:id=>1, :vocalist_id=>2, :albums_id=>4, :band_id=>1, :tracks_id=>7, :album_id=>4, :members_id=>6},
839
+ {:id=>2, :vocalist_id=>2, :albums_id=>5, :band_id=>2, :tracks_id=>8, :album_id=>5, :members_id=>5},
840
+ {:id=>2, :vocalist_id=>2, :albums_id=>5, :band_id=>2, :tracks_id=>8, :album_id=>5, :members_id=>6},
841
+ {:id=>2, :vocalist_id=>2, :albums_id=>5, :band_id=>2, :tracks_id=>9, :album_id=>5, :members_id=>5},
842
+ {:id=>2, :vocalist_id=>2, :albums_id=>5, :band_id=>2, :tracks_id=>9, :album_id=>5, :members_id=>6},
843
+ {:id=>2, :vocalist_id=>2, :albums_id=>6, :band_id=>2, :tracks_id=>1, :album_id=>6, :members_id=>5},
844
+ {:id=>2, :vocalist_id=>2, :albums_id=>6, :band_id=>2, :tracks_id=>1, :album_id=>6, :members_id=>6},
845
+ {:id=>2, :vocalist_id=>2, :albums_id=>6, :band_id=>2, :tracks_id=>2, :album_id=>6, :members_id=>5},
846
+ {:id=>2, :vocalist_id=>2, :albums_id=>6, :band_id=>2, :tracks_id=>2, :album_id=>6, :members_id=>6}]
1192
847
  a = ds.all
1193
848
  a.should == [GraphBand.load(:id=>1, :vocalist_id=>2), GraphBand.load(:id=>2, :vocalist_id=>2)]
1194
849
  members = a.map{|x| x.members}
@@ -1203,85 +858,49 @@ describe Sequel::Model, "#eager_graph" do
1203
858
  MODEL_DB.reset
1204
859
  ds = GraphAlbum.eager_graph(:tracks)
1205
860
  ds.sql.should == 'SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)'
1206
- def ds.fetch_rows(sql, &block)
1207
- @db << sql
1208
- yield({:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1})
1209
- end
861
+ ds._fetch = {:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1}
1210
862
  a = ds.all
1211
- a.should be_a_kind_of(Array)
1212
- a.size.should == 1
1213
- a.first.should be_a_kind_of(GraphAlbum)
1214
- a.first.values.should == {:id => 1, :band_id => 2}
863
+ a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
1215
864
  a = a.first
1216
- a.tracks.should be_a_kind_of(Array)
1217
- a.tracks.size.should == 1
1218
- a.tracks.first.should be_a_kind_of(GraphTrack)
1219
- a.tracks.first.values.should == {:id => 3, :album_id=>1}
1220
- a.tracks.first.album.should be_a_kind_of(GraphAlbum)
865
+ a.tracks.should == [GraphTrack.load(:id => 3, :album_id=>1)]
1221
866
  a.tracks.first.album.should == a
1222
- MODEL_DB.sqls.length.should == 1
867
+ MODEL_DB.sqls.should == ['SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)']
1223
868
  end
1224
869
 
1225
870
  it "should eager load multiple associations from the same table" do
1226
871
  ds = GraphBand.eager_graph(:vocalist, :members)
1227
872
  ds.sql.should == 'SELECT bands.id, bands.vocalist_id, vocalist.id AS vocalist_id_0, members.id AS members_id FROM bands LEFT OUTER JOIN members AS vocalist ON (vocalist.id = bands.vocalist_id) LEFT OUTER JOIN bm ON (bm.band_id = bands.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
1228
- def ds.fetch_rows(sql, &block)
1229
- yield({:id=>2, :vocalist_id=>6, :vocalist_id_0=>6, :members_id=>5})
1230
- end
873
+ ds._fetch = {:id=>2, :vocalist_id=>6, :vocalist_id_0=>6, :members_id=>5}
1231
874
  a = ds.all
1232
- a.should be_a_kind_of(Array)
1233
- a.size.should == 1
1234
- a.first.should be_a_kind_of(GraphBand)
1235
- a.first.values.should == {:id => 2, :vocalist_id => 6}
875
+ a.should == [GraphBand.load(:id => 2, :vocalist_id => 6)]
1236
876
  a = a.first
1237
- a.vocalist.should be_a_kind_of(GraphBandMember)
1238
- a.vocalist.values.should == {:id => 6}
1239
- a.members.should be_a_kind_of(Array)
1240
- a.members.size.should == 1
1241
- a.members.first.should be_a_kind_of(GraphBandMember)
1242
- a.members.first.values.should == {:id => 5}
877
+ a.vocalist.should == GraphBandMember.load(:id => 6)
878
+ a.members.should == [GraphBandMember.load(:id => 5)]
1243
879
  end
1244
880
 
1245
881
  it "should give you a plain hash when called without .all" do
1246
882
  ds = GraphAlbum.eager_graph(:band)
1247
883
  ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
1248
- def ds.fetch_rows(sql, &block)
1249
- yield({:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>3})
1250
- end
884
+ ds._fetch = {:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>3}
1251
885
  ds.first.should == {:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>3}
1252
886
  end
1253
887
 
1254
888
  it "should not drop any associated objects if the graph could not be a cartesian product" do
1255
889
  ds = GraphBand.eager_graph(:members, :vocalist)
1256
890
  ds.sql.should == 'SELECT bands.id, bands.vocalist_id, members.id AS members_id, vocalist.id AS vocalist_id_0 FROM bands LEFT OUTER JOIN bm ON (bm.band_id = bands.id) LEFT OUTER JOIN members ON (members.id = bm.member_id) LEFT OUTER JOIN members AS vocalist ON (vocalist.id = bands.vocalist_id)'
1257
- def ds.fetch_rows(sql, &block)
1258
- yield({:id=>2, :vocalist_id=>6, :members_id=>5, :vocalist_id_0=>6})
1259
- yield({:id=>2, :vocalist_id=>6, :members_id=>5, :vocalist_id_0=>6})
1260
- end
891
+ ds._fetch = [{:id=>2, :vocalist_id=>6, :members_id=>5, :vocalist_id_0=>6}, {:id=>2, :vocalist_id=>6, :members_id=>5, :vocalist_id_0=>6}]
1261
892
  a = ds.all
1262
- a.should be_a_kind_of(Array)
1263
- a.size.should == 1
1264
- a.first.should be_a_kind_of(GraphBand)
1265
- a.first.values.should == {:id => 2, :vocalist_id => 6}
893
+ a.should == [GraphBand.load(:id => 2, :vocalist_id => 6)]
1266
894
  a = a.first
1267
- a.vocalist.should be_a_kind_of(GraphBandMember)
1268
- a.vocalist.values.should == {:id => 6}
1269
- a.members.should be_a_kind_of(Array)
1270
- a.members.size.should == 2
1271
- a.members.first.should be_a_kind_of(GraphBandMember)
1272
- a.members.first.values.should == {:id => 5}
1273
- a.members.last.should be_a_kind_of(GraphBandMember)
1274
- a.members.last.values.should == {:id => 5}
895
+ a.vocalist.should == GraphBandMember.load(:id => 6)
896
+ a.members.should == [GraphBandMember.load(:id => 5), GraphBandMember.load(:id => 5)]
1275
897
  end
1276
898
 
1277
899
  it "should respect the :cartesian_product_number option" do
1278
900
  GraphBand.many_to_one :other_vocalist, :class=>'GraphBandMember', :key=>:vocalist_id, :cartesian_product_number=>1
1279
901
  ds = GraphBand.eager_graph(:members, :other_vocalist)
1280
902
  ds.sql.should == 'SELECT bands.id, bands.vocalist_id, members.id AS members_id, other_vocalist.id AS other_vocalist_id FROM bands LEFT OUTER JOIN bm ON (bm.band_id = bands.id) LEFT OUTER JOIN members ON (members.id = bm.member_id) LEFT OUTER JOIN members AS other_vocalist ON (other_vocalist.id = bands.vocalist_id)'
1281
- def ds.fetch_rows(sql, &block)
1282
- yield({:id=>2, :vocalist_id=>6, :members_id=>5, :other_vocalist_id=>6})
1283
- yield({:id=>2, :vocalist_id=>6, :members_id=>5, :other_vocalist_id=>6})
1284
- end
903
+ ds._fetch = [{:id=>2, :vocalist_id=>6, :members_id=>5, :other_vocalist_id=>6}, {:id=>2, :vocalist_id=>6, :members_id=>5, :other_vocalist_id=>6}]
1285
904
  a = ds.all
1286
905
  a.should == [GraphBand.load(:id=>2, :vocalist_id => 6)]
1287
906
  a.first.other_vocalist.should == GraphBandMember.load(:id=>6)
@@ -1291,57 +910,28 @@ describe Sequel::Model, "#eager_graph" do
1291
910
  it "should drop duplicate items that occur in sequence if the graph could be a cartesian product" do
1292
911
  ds = GraphBand.eager_graph(:members, :genres)
1293
912
  ds.sql.should == 'SELECT bands.id, bands.vocalist_id, members.id AS members_id, genres.id AS genres_id FROM bands LEFT OUTER JOIN bm ON (bm.band_id = bands.id) LEFT OUTER JOIN members ON (members.id = bm.member_id) LEFT OUTER JOIN bg ON (bg.band_id = bands.id) LEFT OUTER JOIN genres ON (genres.id = bg.genre_id)'
1294
- def ds.fetch_rows(sql, &block)
1295
- yield({:id=>2, :vocalist_id=>6, :members_id=>5, :genres_id=>7})
1296
- yield({:id=>2, :vocalist_id=>6, :members_id=>5, :genres_id=>8})
1297
- yield({:id=>2, :vocalist_id=>6, :members_id=>6, :genres_id=>7})
1298
- yield({:id=>2, :vocalist_id=>6, :members_id=>6, :genres_id=>8})
1299
- end
913
+ ds._fetch = [{:id=>2, :vocalist_id=>6, :members_id=>5, :genres_id=>7},
914
+ {:id=>2, :vocalist_id=>6, :members_id=>5, :genres_id=>8},
915
+ {:id=>2, :vocalist_id=>6, :members_id=>6, :genres_id=>7},
916
+ {:id=>2, :vocalist_id=>6, :members_id=>6, :genres_id=>8}]
1300
917
  a = ds.all
1301
- a.should be_a_kind_of(Array)
1302
- a.size.should == 1
1303
- a.first.should be_a_kind_of(GraphBand)
1304
- a.first.values.should == {:id => 2, :vocalist_id => 6}
918
+ a.should == [GraphBand.load(:id => 2, :vocalist_id => 6)]
1305
919
  a = a.first
1306
- a.members.should be_a_kind_of(Array)
1307
- a.members.size.should == 2
1308
- a.members.first.should be_a_kind_of(GraphBandMember)
1309
- a.members.first.values.should == {:id => 5}
1310
- a.members.last.should be_a_kind_of(GraphBandMember)
1311
- a.members.last.values.should == {:id => 6}
1312
- a.genres.size.should == 2
1313
- a.genres.first.should be_a_kind_of(GraphGenre)
1314
- a.genres.first.values.should == {:id => 7}
1315
- a.genres.last.should be_a_kind_of(GraphGenre)
1316
- a.genres.last.values.should == {:id => 8}
920
+ a.members.should == [GraphBandMember.load(:id => 5), GraphBandMember.load(:id => 6)]
921
+ a.genres.should == [GraphGenre.load(:id => 7), GraphGenre.load(:id => 8)]
1317
922
  end
1318
923
 
1319
924
  it "should be able to be used in combination with #eager" do
1320
925
  MODEL_DB.reset
1321
926
  ds = GraphAlbum.eager_graph(:tracks).eager(:genres)
1322
- def ds.fetch_rows(sql, &block)
1323
- @db << sql
1324
- yield({:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1})
1325
- end
927
+ ds._fetch = {:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1}
1326
928
  ds2 = GraphGenre.dataset
1327
- def ds2.fetch_rows(sql, &block)
1328
- @db << sql
1329
- yield({:id=>6, :x_foreign_key_x=>1})
1330
- end
929
+ ds2._fetch = {:id=>6, :x_foreign_key_x=>1}
1331
930
  a = ds.all
1332
- a.should be_a_kind_of(Array)
1333
- a.size.should == 1
1334
- a.first.should be_a_kind_of(GraphAlbum)
1335
- a.first.values.should == {:id => 1, :band_id => 2}
931
+ a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
1336
932
  a = a.first
1337
- a.tracks.should be_a_kind_of(Array)
1338
- a.tracks.size.should == 1
1339
- a.tracks.first.should be_a_kind_of(GraphTrack)
1340
- a.tracks.first.values.should == {:id=>3, :album_id=>1}
1341
- a.genres.should be_a_kind_of(Array)
1342
- a.genres.size.should == 1
1343
- a.genres.first.should be_a_kind_of(GraphGenre)
1344
- a.genres.first.values.should == {:id=>6}
933
+ a.tracks.should == [GraphTrack.load(:id=>3, :album_id=>1)]
934
+ a.genres.should == [GraphGenre.load(:id => 6)]
1345
935
  MODEL_DB.sqls.should == ['SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)',
1346
936
  "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
1347
937
  end
@@ -1349,110 +939,65 @@ describe Sequel::Model, "#eager_graph" do
1349
939
  it "should handle no associated records for a single many_to_one association" do
1350
940
  ds = GraphAlbum.eager_graph(:band)
1351
941
  ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
1352
- def ds.fetch_rows(sql, &block)
1353
- yield({:id=>1, :band_id=>2, :band_id_0=>nil, :vocalist_id=>nil})
1354
- end
942
+ ds._fetch = {:id=>1, :band_id=>2, :band_id_0=>nil, :vocalist_id=>nil}
1355
943
  a = ds.all
1356
- a.should be_a_kind_of(Array)
1357
- a.size.should == 1
1358
- a.first.should be_a_kind_of(GraphAlbum)
1359
- a.first.values.should == {:id => 1, :band_id => 2}
1360
- a.first.associations.fetch(:band, 2).should == nil
944
+ a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
945
+ a.first.band.should == nil
1361
946
  end
1362
947
 
1363
948
  it "should handle no associated records for a single one_to_many association" do
1364
949
  ds = GraphAlbum.eager_graph(:tracks)
1365
950
  ds.sql.should == 'SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)'
1366
- def ds.fetch_rows(sql, &block)
1367
- yield({:id=>1, :band_id=>2, :tracks_id=>nil, :album_id=>nil})
1368
- end
951
+ ds._fetch = {:id=>1, :band_id=>2, :tracks_id=>nil, :album_id=>nil}
1369
952
  a = ds.all
1370
- a.should be_a_kind_of(Array)
1371
- a.size.should == 1
1372
- a.first.should be_a_kind_of(GraphAlbum)
1373
- a.first.values.should == {:id => 1, :band_id => 2}
953
+ a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
1374
954
  a.first.tracks.should == []
1375
955
  end
1376
956
 
1377
957
  it "should handle no associated records for a single many_to_many association" do
1378
958
  ds = GraphAlbum.eager_graph(:genres)
1379
959
  ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id)'
1380
- def ds.fetch_rows(sql, &block)
1381
- yield({:id=>1, :band_id=>2, :genres_id=>nil})
1382
- end
960
+ ds._fetch = {:id=>1, :band_id=>2, :genres_id=>nil}
1383
961
  a = ds.all
1384
- a.should be_a_kind_of(Array)
1385
- a.size.should == 1
1386
- a.first.should be_a_kind_of(GraphAlbum)
1387
- a.first.values.should == {:id => 1, :band_id => 2}
962
+ a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
1388
963
  a.first.genres.should == []
1389
964
  end
1390
965
 
1391
966
  it "should handle missing associated records when loading multiple associations" do
1392
967
  ds = GraphAlbum.eager_graph(:genres, :tracks, :band)
1393
968
  ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id, tracks.id AS tracks_id, tracks.album_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
1394
- def ds.fetch_rows(sql, &block)
1395
- yield({:id=>1, :band_id=>2, :genres_id=>nil, :tracks_id=>3, :album_id=>1, :band_id_0=>nil, :vocalist_id=>nil})
1396
- yield({:id=>1, :band_id=>2, :genres_id=>nil, :tracks_id=>4, :album_id=>1, :band_id_0=>nil, :vocalist_id=>nil})
1397
- yield({:id=>1, :band_id=>2, :genres_id=>nil, :tracks_id=>5, :album_id=>1, :band_id_0=>nil, :vocalist_id=>nil})
1398
- yield({:id=>1, :band_id=>2, :genres_id=>nil, :tracks_id=>6, :album_id=>1, :band_id_0=>nil, :vocalist_id=>nil})
1399
- end
969
+ ds._fetch = [{:id=>1, :band_id=>2, :genres_id=>nil, :tracks_id=>3, :album_id=>1, :band_id_0=>nil, :vocalist_id=>nil},
970
+ {:id=>1, :band_id=>2, :genres_id=>nil, :tracks_id=>4, :album_id=>1, :band_id_0=>nil, :vocalist_id=>nil},
971
+ {:id=>1, :band_id=>2, :genres_id=>nil, :tracks_id=>5, :album_id=>1, :band_id_0=>nil, :vocalist_id=>nil},
972
+ {:id=>1, :band_id=>2, :genres_id=>nil, :tracks_id=>6, :album_id=>1, :band_id_0=>nil, :vocalist_id=>nil}]
1400
973
  a = ds.all
1401
- a.should be_a_kind_of(Array)
1402
- a.size.should == 1
1403
- a.first.should be_a_kind_of(GraphAlbum)
1404
- a.first.values.should == {:id => 1, :band_id => 2}
974
+ a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
1405
975
  a = a.first
1406
- a.tracks.should be_a_kind_of(Array)
1407
- a.tracks.size.should == 4
1408
- a.tracks.first.should be_a_kind_of(GraphTrack)
1409
- a.tracks.collect{|x|x[:id]}.should == [3,4,5,6]
1410
- a.associations.fetch(:band, 2).should == nil
976
+ a.tracks.should == [GraphTrack.load(:id => 3, :album_id => 1), GraphTrack.load(:id => 4, :album_id => 1), GraphTrack.load(:id => 5, :album_id => 1), GraphTrack.load(:id => 6, :album_id => 1)]
977
+ a.band.should == nil
1411
978
  a.genres.should == []
1412
979
  end
1413
980
 
1414
981
  it "should handle missing associated records when cascading eager loading for associations of associated models" do
1415
982
  ds = GraphTrack.eager_graph(:album=>{:band=>:members})
1416
983
  ds.sql.should == 'SELECT tracks.id, tracks.album_id, album.id AS album_id_0, album.band_id, band.id AS band_id_0, band.vocalist_id, members.id AS members_id FROM tracks LEFT OUTER JOIN albums AS album ON (album.id = tracks.album_id) LEFT OUTER JOIN bands AS band ON (band.id = album.band_id) LEFT OUTER JOIN bm ON (bm.band_id = band.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
1417
- def ds.fetch_rows(sql, &block)
1418
- yield({:id=>2, :album_id=>2, :album_id_0=>nil, :band_id=>nil, :members_id=>nil, :band_id_0=>nil, :vocalist_id=>nil})
1419
- yield({:id=>3, :album_id=>3, :album_id_0=>3, :band_id=>3, :members_id=>nil, :band_id_0=>nil, :vocalist_id=>nil})
1420
- yield({:id=>4, :album_id=>4, :album_id_0=>4, :band_id=>2, :members_id=>nil, :band_id_0=>2, :vocalist_id=>6})
1421
- yield({:id=>5, :album_id=>1, :album_id_0=>1, :band_id=>4, :members_id=>5, :band_id_0=>4, :vocalist_id=>8})
1422
- yield({:id=>5, :album_id=>1, :album_id_0=>1, :band_id=>4, :members_id=>6, :band_id_0=>4, :vocalist_id=>8})
1423
- end
984
+ ds._fetch = [{:id=>2, :album_id=>2, :album_id_0=>nil, :band_id=>nil, :members_id=>nil, :band_id_0=>nil, :vocalist_id=>nil},
985
+ {:id=>3, :album_id=>3, :album_id_0=>3, :band_id=>3, :members_id=>nil, :band_id_0=>nil, :vocalist_id=>nil},
986
+ {:id=>4, :album_id=>4, :album_id_0=>4, :band_id=>2, :members_id=>nil, :band_id_0=>2, :vocalist_id=>6},
987
+ {:id=>5, :album_id=>1, :album_id_0=>1, :band_id=>4, :members_id=>5, :band_id_0=>4, :vocalist_id=>8},
988
+ {:id=>5, :album_id=>1, :album_id_0=>1, :band_id=>4, :members_id=>6, :band_id_0=>4, :vocalist_id=>8}]
1424
989
  a = ds.all
1425
- a.should be_a_kind_of(Array)
1426
- a.size.should == 4
1427
- a.first.should be_a_kind_of(GraphTrack)
1428
- a.collect{|x|x[:id]}.should == [2,3,4,5]
1429
- a[0].associations.fetch(:album, 2).should == nil
1430
- a[1].album.should be_a_kind_of(GraphAlbum)
1431
- a[1].album.values.should == {:id => 3, :band_id => 3}
1432
- a[1].album.associations.fetch(:band, 2).should == nil
1433
- a[2].album.should be_a_kind_of(GraphAlbum)
1434
- a[2].album.values.should == {:id => 4, :band_id => 2}
1435
- a[2].album.band.should be_a_kind_of(GraphBand)
1436
- a[2].album.band.values.should == {:id => 2, :vocalist_id=>6}
1437
- a[2].album.band.members.should == []
1438
- a[3].album.should be_a_kind_of(GraphAlbum)
1439
- a[3].album.values.should == {:id => 1, :band_id => 4}
1440
- a[3].album.band.should be_a_kind_of(GraphBand)
1441
- a[3].album.band.values.should == {:id => 4, :vocalist_id=>8}
1442
- a[3].album.band.members.size.should == 2
1443
- a[3].album.band.members.first.should be_a_kind_of(GraphBandMember)
1444
- a[3].album.band.members.first.values.should == {:id => 5}
1445
- a[3].album.band.members.last.should be_a_kind_of(GraphBandMember)
1446
- a[3].album.band.members.last.values.should == {:id => 6}
990
+ a.should == [GraphTrack.load(:id => 2, :album_id => 2), GraphTrack.load(:id => 3, :album_id => 3), GraphTrack.load(:id => 4, :album_id => 4), GraphTrack.load(:id => 5, :album_id => 1)]
991
+ a.map{|x| x.album}.should == [nil, GraphAlbum.load(:id => 3, :band_id => 3), GraphAlbum.load(:id => 4, :band_id => 2), GraphAlbum.load(:id => 1, :band_id => 4)]
992
+ a.map{|x| x.album.band if x.album}.should == [nil, nil, GraphBand.load(:id => 2, :vocalist_id=>6), GraphBand.load(:id => 4, :vocalist_id=>8)]
993
+ a.map{|x| x.album.band.members if x.album && x.album.band}.should == [nil, nil, [], [GraphBandMember.load(:id => 5), GraphBandMember.load(:id => 6)]]
1447
994
  end
1448
995
 
1449
996
  it "should respect the association's :primary_key option" do
1450
997
  GraphAlbum.many_to_one :inner_band, :class=>'GraphBand', :key=>:band_id, :primary_key=>:vocalist_id
1451
998
  ds = GraphAlbum.eager_graph(:inner_band)
1452
999
  ds.sql.should == 'SELECT albums.id, albums.band_id, inner_band.id AS inner_band_id, inner_band.vocalist_id FROM albums LEFT OUTER JOIN bands AS inner_band ON (inner_band.vocalist_id = albums.band_id)'
1453
- def ds.fetch_rows(sql, &block)
1454
- yield({:id=>3, :band_id=>2, :inner_band_id=>5, :vocalist_id=>2})
1455
- end
1000
+ ds._fetch = {:id=>3, :band_id=>2, :inner_band_id=>5, :vocalist_id=>2}
1456
1001
  as = ds.all
1457
1002
  as.should == [GraphAlbum.load(:id=>3, :band_id=>2)]
1458
1003
  as.first.inner_band.should == GraphBand.load(:id=>5, :vocalist_id=>2)
@@ -1460,10 +1005,7 @@ describe Sequel::Model, "#eager_graph" do
1460
1005
  GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>:album_id, :primary_key=>:band_id
1461
1006
  ds = GraphAlbum.eager_graph(:right_tracks)
1462
1007
  ds.sql.should == 'SELECT albums.id, albums.band_id, right_tracks.id AS right_tracks_id, right_tracks.album_id FROM albums LEFT OUTER JOIN tracks AS right_tracks ON (right_tracks.album_id = albums.band_id)'
1463
- def ds.fetch_rows(sql, &block)
1464
- yield({:id=>3, :band_id=>2, :right_tracks_id=>5, :album_id=>2})
1465
- yield({:id=>3, :band_id=>2, :right_tracks_id=>6, :album_id=>2})
1466
- end
1008
+ ds._fetch = [{:id=>3, :band_id=>2, :right_tracks_id=>5, :album_id=>2}, {:id=>3, :band_id=>2, :right_tracks_id=>6, :album_id=>2}]
1467
1009
  as = ds.all
1468
1010
  as.should == [GraphAlbum.load(:id=>3, :band_id=>2)]
1469
1011
  as.first.right_tracks.should == [GraphTrack.load(:id=>5, :album_id=>2), GraphTrack.load(:id=>6, :album_id=>2)]
@@ -1473,9 +1015,7 @@ describe Sequel::Model, "#eager_graph" do
1473
1015
  GraphAlbum.many_to_one :inner_band, :class=>'GraphBand', :key=>[:band_id, :id], :primary_key=>[:vocalist_id, :id]
1474
1016
  ds = GraphAlbum.eager_graph(:inner_band)
1475
1017
  ds.sql.should == 'SELECT albums.id, albums.band_id, inner_band.id AS inner_band_id, inner_band.vocalist_id FROM albums LEFT OUTER JOIN bands AS inner_band ON ((inner_band.vocalist_id = albums.band_id) AND (inner_band.id = albums.id))'
1476
- def ds.fetch_rows(sql, &block)
1477
- yield({:id=>3, :band_id=>2, :inner_band_id=>3, :vocalist_id=>2})
1478
- end
1018
+ ds._fetch = {:id=>3, :band_id=>2, :inner_band_id=>3, :vocalist_id=>2}
1479
1019
  as = ds.all
1480
1020
  as.should == [GraphAlbum.load(:id=>3, :band_id=>2)]
1481
1021
  as.first.inner_band.should == GraphBand.load(:id=>3, :vocalist_id=>2)
@@ -1485,9 +1025,7 @@ describe Sequel::Model, "#eager_graph" do
1485
1025
  GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>[:album_id, :id], :primary_key=>[:band_id, :id]
1486
1026
  ds = GraphAlbum.eager_graph(:right_tracks)
1487
1027
  ds.sql.should == 'SELECT albums.id, albums.band_id, right_tracks.id AS right_tracks_id, right_tracks.album_id FROM albums LEFT OUTER JOIN tracks AS right_tracks ON ((right_tracks.album_id = albums.band_id) AND (right_tracks.id = albums.id))'
1488
- def ds.fetch_rows(sql, &block)
1489
- yield({:id=>3, :band_id=>2, :right_tracks_id=>3, :album_id=>2})
1490
- end
1028
+ ds._fetch = {:id=>3, :band_id=>2, :right_tracks_id=>3, :album_id=>2}
1491
1029
  as = ds.all
1492
1030
  as.should == [GraphAlbum.load(:id=>3, :band_id=>2)]
1493
1031
  as.first.right_tracks.should == [GraphTrack.load(:id=>3, :album_id=>2)]
@@ -1497,10 +1035,7 @@ describe Sequel::Model, "#eager_graph" do
1497
1035
  GraphAlbum.many_to_many :sbands, :class=>'GraphBand', :left_key=>[:l1, :l2], :left_primary_key=>[:band_id, :id], :right_key=>[:r1, :r2], :right_primary_key=>[:vocalist_id, :id], :join_table=>:b
1498
1036
  ds = GraphAlbum.eager_graph(:sbands)
1499
1037
  ds.sql.should == 'SELECT albums.id, albums.band_id, sbands.id AS sbands_id, sbands.vocalist_id FROM albums LEFT OUTER JOIN b ON ((b.l1 = albums.band_id) AND (b.l2 = albums.id)) LEFT OUTER JOIN bands AS sbands ON ((sbands.vocalist_id = b.r1) AND (sbands.id = b.r2))'
1500
- def ds.fetch_rows(sql, &block)
1501
- yield({:id=>3, :band_id=>2, :sbands_id=>5, :vocalist_id=>6})
1502
- yield({:id=>3, :band_id=>2, :sbands_id=>6, :vocalist_id=>22})
1503
- end
1038
+ ds._fetch = [{:id=>3, :band_id=>2, :sbands_id=>5, :vocalist_id=>6}, {:id=>3, :band_id=>2, :sbands_id=>6, :vocalist_id=>22}]
1504
1039
  as = ds.all
1505
1040
  as.should == [GraphAlbum.load(:id=>3, :band_id=>2)]
1506
1041
  as.first.sbands.should == [GraphBand.load(:id=>5, :vocalist_id=>6), GraphBand.load(:id=>6, :vocalist_id=>22)]
@@ -1510,10 +1045,7 @@ describe Sequel::Model, "#eager_graph" do
1510
1045
  GraphAlbum.many_to_many :inner_genres, :class=>'GraphGenre', :left_key=>:album_id, :left_primary_key=>:band_id, :right_key=>:genre_id, :right_primary_key=>:xxx, :join_table=>:ag
1511
1046
  ds = GraphAlbum.eager_graph(:inner_genres)
1512
1047
  ds.sql.should == 'SELECT albums.id, albums.band_id, inner_genres.id AS inner_genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.band_id) LEFT OUTER JOIN genres AS inner_genres ON (inner_genres.xxx = ag.genre_id)'
1513
- def ds.fetch_rows(sql, &block)
1514
- yield({:id=>3, :band_id=>2, :inner_genres_id=>5, :xxx=>12})
1515
- yield({:id=>3, :band_id=>2, :inner_genres_id=>6, :xxx=>22})
1516
- end
1048
+ ds._fetch = [{:id=>3, :band_id=>2, :inner_genres_id=>5, :xxx=>12}, {:id=>3, :band_id=>2, :inner_genres_id=>6, :xxx=>22}]
1517
1049
  as = ds.all
1518
1050
  as.should == [GraphAlbum.load(:id=>3, :band_id=>2)]
1519
1051
  as.first.inner_genres.should == [GraphGenre.load(:id=>5), GraphGenre.load(:id=>6)]
@@ -1528,12 +1060,10 @@ describe Sequel::Model, "#eager_graph" do
1528
1060
  c2.one_to_many :salbums, :class=>c1, :key=>[:band_id, :id]
1529
1061
  ds = c1.eager_graph(:sbands=>:salbums)
1530
1062
  ds.sql.should == 'SELECT albums.id, albums.band_id, sbands.id AS sbands_id, sbands.vocalist_id, salbums.id AS salbums_id, salbums.band_id AS salbums_band_id FROM albums LEFT OUTER JOIN b ON ((b.l1 = albums.band_id) AND (b.l2 = albums.id)) LEFT OUTER JOIN bands AS sbands ON ((sbands.vocalist_id = b.r1) AND (sbands.id = b.r2)) LEFT OUTER JOIN albums AS salbums ON ((salbums.band_id = sbands.vocalist_id) AND (salbums.id = sbands.id))'
1531
- def ds.fetch_rows(sql, &block)
1532
- yield({:id=>3, :band_id=>2, :sbands_id=>5, :vocalist_id=>6, :salbums_id=>7, :salbums_band_id=>8})
1533
- yield({:id=>3, :band_id=>2, :sbands_id=>5, :vocalist_id=>6, :salbums_id=>9, :salbums_band_id=>10})
1534
- yield({:id=>3, :band_id=>2, :sbands_id=>6, :vocalist_id=>22, :salbums_id=>nil, :salbums_band_id=>nil})
1535
- yield({:id=>7, :band_id=>8, :sbands_id=>nil, :vocalist_id=>nil, :salbums_id=>nil, :salbums_band_id=>nil})
1536
- end
1063
+ ds._fetch = [{:id=>3, :band_id=>2, :sbands_id=>5, :vocalist_id=>6, :salbums_id=>7, :salbums_band_id=>8},
1064
+ {:id=>3, :band_id=>2, :sbands_id=>5, :vocalist_id=>6, :salbums_id=>9, :salbums_band_id=>10},
1065
+ {:id=>3, :band_id=>2, :sbands_id=>6, :vocalist_id=>22, :salbums_id=>nil, :salbums_band_id=>nil},
1066
+ {:id=>7, :band_id=>8, :sbands_id=>nil, :vocalist_id=>nil, :salbums_id=>nil, :salbums_band_id=>nil}]
1537
1067
  as = ds.all
1538
1068
  as.should == [c1.load(:id=>3, :band_id=>2), c1.load(:id=>7, :band_id=>8)]
1539
1069
  as.map{|x| x.sbands}.should == [[c2.load(:id=>5, :vocalist_id=>6), c2.load(:id=>6, :vocalist_id=>22)], []]
@@ -1703,10 +1233,7 @@ describe Sequel::Model, "#eager_graph" do
1703
1233
  GraphAlbum.many_to_many :inner_genres, :class=>'GraphGenre', :left_key=>:album_id, :left_primary_key=>:band_id, :right_key=>:genre_id, :right_primary_key=>:xxx, :join_table=>:ag
1704
1234
  ds = GraphAlbum.eager_graph(:inner_genres)
1705
1235
  ds.sql.should == 'SELECT albums.id, albums.band_id, inner_genres.id AS inner_genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.band_id) LEFT OUTER JOIN genres AS inner_genres ON (inner_genres.xxx = ag.genre_id)'
1706
- def ds.fetch_rows(sql, &block)
1707
- yield({:id=>3, :band_id=>2, :inner_genres_id=>5, :xxx=>12})
1708
- yield({:id=>3, :band_id=>2, :inner_genres_id=>6, :xxx=>22})
1709
- end
1236
+ ds._fetch = [{:id=>3, :band_id=>2, :inner_genres_id=>5, :xxx=>12}, {:id=>3, :band_id=>2, :inner_genres_id=>6, :xxx=>22}]
1710
1237
  as = ds.all
1711
1238
  as.should == [GraphAlbum.load(:id=>3, :band_id=>2)]
1712
1239
  as.first.inner_genres.should == [GraphGenre.load(:id=>5), GraphGenre.load(:id=>6)]
@@ -1731,7 +1258,8 @@ describe Sequel::Model, "#eager_graph" do
1731
1258
  it "should eagerly load schema qualified tables correctly with joins" do
1732
1259
  c1 = Class.new(GraphAlbum)
1733
1260
  c2 = Class.new(GraphGenre)
1734
- c1.dataset = c1.dataset.from(:s__a)
1261
+ ds = c1.dataset = c1.dataset.from(:s__a)
1262
+ def ds.columns() [:id] end
1735
1263
  c2.dataset = c2.dataset.from(:s__g)
1736
1264
  c1.many_to_many :a_genres, :class=>c2, :left_primary_key=>:id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:s__ag
1737
1265
  ds = c1.join(:s__t, [:b_id]).eager_graph(:a_genres)
@@ -1744,9 +1272,7 @@ describe Sequel::Model, "#eager_graph" do
1744
1272
  GraphAlbum.many_to_many :al_genres, :class=>GraphGenre, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :after_load=>proc{|o, os| os.each{|a| a.id *=2}}
1745
1273
  ds = GraphAlbum.eager_graph(:al_band, :al_tracks, :al_genres)
1746
1274
  ds.sql.should == "SELECT albums.id, albums.band_id, al_band.id AS al_band_id, al_band.vocalist_id, al_tracks.id AS al_tracks_id, al_tracks.album_id, al_genres.id AS al_genres_id FROM albums LEFT OUTER JOIN bands AS al_band ON (al_band.id = albums.band_id) LEFT OUTER JOIN tracks AS al_tracks ON (al_tracks.album_id = albums.id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS al_genres ON (al_genres.id = ag.genre_id)"
1747
- def ds.fetch_rows(sql)
1748
- yield({:id=>1, :band_id=>2, :al_band_id=>3, :vocalist_id=>4, :al_tracks_id=>5, :album_id=>6, :al_genres_id=>7})
1749
- end
1275
+ ds._fetch = {:id=>1, :band_id=>2, :al_band_id=>3, :vocalist_id=>4, :al_tracks_id=>5, :album_id=>6, :al_genres_id=>7}
1750
1276
  a = ds.all.first
1751
1277
  a.should == GraphAlbum.load(:id => 1, :band_id => 2)
1752
1278
  a.al_band.should == GraphBand.load(:id=>6, :vocalist_id=>4)
@@ -1760,11 +1286,9 @@ describe Sequel::Model, "#eager_graph" do
1760
1286
  GraphAlbum.many_to_many :al_genres, :class=>GraphGenre, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>2
1761
1287
  ds = GraphAlbum.eager_graph(:al_band, :al_tracks, :al_genres)
1762
1288
  ds.sql.should == "SELECT albums.id, albums.band_id, al_band.id AS al_band_id, al_band.vocalist_id, al_tracks.id AS al_tracks_id, al_tracks.album_id, al_genres.id AS al_genres_id FROM albums LEFT OUTER JOIN bands AS al_band ON (al_band.id = albums.band_id) LEFT OUTER JOIN tracks AS al_tracks ON (al_tracks.album_id = albums.id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS al_genres ON (al_genres.id = ag.genre_id)"
1763
- def ds.fetch_rows(sql)
1764
- yield({:id=>1, :band_id=>2, :al_band_id=>3, :vocalist_id=>4, :al_tracks_id=>5, :album_id=>6, :al_genres_id=>7})
1765
- yield({:id=>1, :band_id=>2, :al_band_id=>8, :vocalist_id=>9, :al_tracks_id=>10, :album_id=>11, :al_genres_id=>12})
1766
- yield({:id=>1, :band_id=>2, :al_band_id=>13, :vocalist_id=>14, :al_tracks_id=>15, :album_id=>16, :al_genres_id=>17})
1767
- end
1289
+ ds._fetch = [{:id=>1, :band_id=>2, :al_band_id=>3, :vocalist_id=>4, :al_tracks_id=>5, :album_id=>6, :al_genres_id=>7},
1290
+ {:id=>1, :band_id=>2, :al_band_id=>8, :vocalist_id=>9, :al_tracks_id=>10, :album_id=>11, :al_genres_id=>12},
1291
+ {:id=>1, :band_id=>2, :al_band_id=>13, :vocalist_id=>14, :al_tracks_id=>15, :album_id=>16, :al_genres_id=>17}]
1768
1292
  a = ds.all.first
1769
1293
  a.should == GraphAlbum.load(:id => 1, :band_id => 2)
1770
1294
  a.al_band.should == GraphBand.load(:id=>3, :vocalist_id=>4)
@@ -1773,111 +1297,63 @@ describe Sequel::Model, "#eager_graph" do
1773
1297
  end
1774
1298
 
1775
1299
  it "should eagerly load a many_to_one association with a custom callback" do
1776
- ds = GraphAlbum.eager_graph(:band => proc {|ds| ds.select_columns(:id)})
1300
+ ds = GraphAlbum.eager_graph(:band => proc {|ds| ds.select(:id).columns(:id)})
1777
1301
  ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0 FROM albums LEFT OUTER JOIN (SELECT id FROM bands) AS band ON (band.id = albums.band_id)'
1778
- def ds.fetch_rows(sql, &block)
1779
- yield({:id=>1, :band_id=>2, :band_id_0=>2})
1780
- end
1302
+ ds._fetch = {:id=>1, :band_id=>2, :band_id_0=>2}
1781
1303
  a = ds.all
1782
- a.should be_a_kind_of(Array)
1783
- a.size.should == 1
1784
- a.first.should be_a_kind_of(GraphAlbum)
1785
- a.first.values.should == {:id => 1, :band_id => 2}
1786
- a = a.first
1787
- a.band.should be_a_kind_of(GraphBand)
1788
- a.band.values.should == {:id => 2}
1304
+ a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
1305
+ a.first.band.should == GraphBand.load(:id => 2)
1789
1306
  end
1790
1307
 
1791
1308
  it "should eagerly load a one_to_one association with a custom callback" do
1792
1309
  GraphAlbum.one_to_one :track, :class=>'GraphTrack', :key=>:album_id
1793
- ds = GraphAlbum.eager_graph(:track => proc {|ds| ds.select_columns(:album_id)})
1310
+ ds = GraphAlbum.eager_graph(:track => proc {|ds| ds.select(:album_id).columns(:album_id)})
1794
1311
  ds.sql.should == 'SELECT albums.id, albums.band_id, track.album_id FROM albums LEFT OUTER JOIN (SELECT album_id FROM tracks) AS track ON (track.album_id = albums.id)'
1795
- def ds.fetch_rows(sql, &block)
1796
- yield({:id=>1, :band_id=>2, :album_id=>1})
1797
- end
1312
+ ds._fetch = {:id=>1, :band_id=>2, :album_id=>1}
1798
1313
  a = ds.all
1799
1314
  a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
1800
1315
  a.first.track.should == GraphTrack.load(:album_id=>1)
1801
1316
  end
1802
1317
 
1803
1318
  it "should eagerly load a one_to_many association with a custom callback" do
1804
- ds = GraphAlbum.eager_graph(:tracks => proc {|ds| ds.select_columns(:album_id)})
1319
+ ds = GraphAlbum.eager_graph(:tracks => proc {|ds| ds.select(:album_id).columns(:album_id)})
1805
1320
  ds.sql.should == 'SELECT albums.id, albums.band_id, tracks.album_id FROM albums LEFT OUTER JOIN (SELECT album_id FROM tracks) AS tracks ON (tracks.album_id = albums.id)'
1806
- def ds.fetch_rows(sql, &block)
1807
- yield({:id=>1, :band_id=>2, :album_id=>1})
1808
- end
1321
+ ds._fetch = {:id=>1, :band_id=>2, :album_id=>1}
1809
1322
  a = ds.all
1810
- a.should be_a_kind_of(Array)
1811
- a.size.should == 1
1812
- a.first.should be_a_kind_of(GraphAlbum)
1813
- a.first.values.should == {:id => 1, :band_id => 2}
1814
- a = a.first
1815
- a.tracks.should be_a_kind_of(Array)
1816
- a.tracks.size.should == 1
1817
- a.tracks.first.should be_a_kind_of(GraphTrack)
1818
- a.tracks.first.values.should == {:album_id=>1}
1323
+ a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
1324
+ a.first.tracks.should == [GraphTrack.load(:album_id=>1)]
1819
1325
  end
1820
1326
 
1821
1327
  it "should eagerly load a many_to_many association with a custom callback" do
1822
- ds = GraphAlbum.eager_graph(:genres => proc {|ds| ds.select_columns(:id)})
1328
+ ds = GraphAlbum.eager_graph(:genres => proc {|ds| ds.select(:id).columns(:id)})
1823
1329
  ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN (SELECT id FROM genres) AS genres ON (genres.id = ag.genre_id)'
1824
- def ds.fetch_rows(sql, &block)
1825
- yield({:id=>1, :band_id=>2, :genres_id=>4})
1826
- end
1330
+ ds._fetch = {:id=>1, :band_id=>2, :genres_id=>4}
1827
1331
  a = ds.all
1828
- a.should be_a_kind_of(Array)
1829
- a.size.should == 1
1830
- a.first.should be_a_kind_of(GraphAlbum)
1831
- a.first.values.should == {:id => 1, :band_id => 2}
1832
- a = a.first
1833
- a.genres.should be_a_kind_of(Array)
1834
- a.genres.size.should == 1
1835
- a.genres.first.should be_a_kind_of(GraphGenre)
1836
- a.genres.first.values.should == {:id => 4}
1332
+ a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
1333
+ a.first.genres.should == [GraphGenre.load(:id => 4)]
1837
1334
  end
1838
1335
 
1839
1336
  it "should allow cascading of eager loading with a custom callback with hash value" do
1840
- ds = GraphTrack.eager_graph(:album=>{proc{|ds| ds.select_columns(:id, :band_id)}=>{:band=>:members}})
1337
+ ds = GraphTrack.eager_graph(:album=>{proc{|ds| ds.select(:id, :band_id).columns(:id, :band_id)}=>{:band=>:members}})
1841
1338
  ds.sql.should == 'SELECT tracks.id, tracks.album_id, album.id AS album_id_0, album.band_id, band.id AS band_id_0, band.vocalist_id, members.id AS members_id FROM tracks LEFT OUTER JOIN (SELECT id, band_id FROM albums) AS album ON (album.id = tracks.album_id) LEFT OUTER JOIN bands AS band ON (band.id = album.band_id) LEFT OUTER JOIN bm ON (bm.band_id = band.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
1842
- def ds.fetch_rows(sql, &block)
1843
- yield({:id=>3, :album_id=>1, :album_id_0=>1, :band_id=>2, :members_id=>5, :band_id_0=>2, :vocalist_id=>6})
1844
- end
1339
+ ds._fetch = {:id=>3, :album_id=>1, :album_id_0=>1, :band_id=>2, :members_id=>5, :band_id_0=>2, :vocalist_id=>6}
1845
1340
  a = ds.all
1846
- a.should be_a_kind_of(Array)
1847
- a.size.should == 1
1848
- a.first.should be_a_kind_of(GraphTrack)
1849
- a.first.values.should == {:id => 3, :album_id => 1}
1341
+ a.should == [GraphTrack.load(:id => 3, :album_id => 1)]
1850
1342
  a = a.first
1851
- a.album.should be_a_kind_of(GraphAlbum)
1852
- a.album.values.should == {:id => 1, :band_id => 2}
1853
- a.album.band.should be_a_kind_of(GraphBand)
1854
- a.album.band.values.should == {:id => 2, :vocalist_id=>6}
1855
- a.album.band.members.should be_a_kind_of(Array)
1856
- a.album.band.members.size.should == 1
1857
- a.album.band.members.first.should be_a_kind_of(GraphBandMember)
1858
- a.album.band.members.first.values.should == {:id => 5}
1343
+ a.album.should == GraphAlbum.load(:id => 1, :band_id => 2)
1344
+ a.album.band.should == GraphBand.load(:id => 2, :vocalist_id=>6)
1345
+ a.album.band.members.should == [GraphBandMember.load(:id => 5)]
1859
1346
  end
1860
1347
 
1861
1348
  it "should allow cascading of eager loading with a custom callback with array value" do
1862
- ds = GraphTrack.eager_graph(:album=>{proc{|ds| ds.select_columns(:id, :band_id)}=>[:band, :tracks]})
1349
+ ds = GraphTrack.eager_graph(:album=>{proc{|ds| ds.select(:id, :band_id).columns(:id, :band_id)}=>[:band, :tracks]})
1863
1350
  ds.sql.should == 'SELECT tracks.id, tracks.album_id, album.id AS album_id_0, album.band_id, band.id AS band_id_0, band.vocalist_id, tracks_0.id AS tracks_0_id, tracks_0.album_id AS tracks_0_album_id FROM tracks LEFT OUTER JOIN (SELECT id, band_id FROM albums) AS album ON (album.id = tracks.album_id) LEFT OUTER JOIN bands AS band ON (band.id = album.band_id) LEFT OUTER JOIN tracks AS tracks_0 ON (tracks_0.album_id = album.id)'
1864
- def ds.fetch_rows(sql, &block)
1865
- yield({:id=>3, :album_id=>1, :album_id_0=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>6, :tracks_0_id=>3, :tracks_0_album_id=>1})
1866
- end
1351
+ ds._fetch = {:id=>3, :album_id=>1, :album_id_0=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>6, :tracks_0_id=>3, :tracks_0_album_id=>1}
1867
1352
  a = ds.all
1868
- a.should be_a_kind_of(Array)
1869
- a.size.should == 1
1870
- a.first.should be_a_kind_of(GraphTrack)
1871
- a.first.values.should == {:id => 3, :album_id => 1}
1353
+ a.should == [GraphTrack.load(:id => 3, :album_id => 1)]
1872
1354
  a = a.first
1873
- a.album.should be_a_kind_of(GraphAlbum)
1874
- a.album.values.should == {:id => 1, :band_id => 2}
1875
- a.album.band.should be_a_kind_of(GraphBand)
1876
- a.album.band.values.should == {:id => 2, :vocalist_id=>6}
1877
- a.album.tracks.should be_a_kind_of(Array)
1878
- a.album.tracks.size.should == 1
1879
- a.album.tracks.first.should be_a_kind_of(GraphTrack)
1880
- a.album.tracks.first.values.should == {:id => 3, :album_id => 1}
1355
+ a.album.should == GraphAlbum.load(:id => 1, :band_id => 2)
1356
+ a.album.band.should == GraphBand.load(:id => 2, :vocalist_id=>6)
1357
+ a.album.tracks.should == [GraphTrack.load(:id => 3, :album_id => 1)]
1881
1358
  end
1882
-
1883
1359
  end