sequel 3.28.0 → 3.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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