sequel 3.28.0 → 3.29.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +119 -3
- data/Rakefile +5 -3
- data/bin/sequel +1 -5
- data/doc/model_hooks.rdoc +9 -1
- data/doc/opening_databases.rdoc +49 -40
- data/doc/prepared_statements.rdoc +27 -6
- data/doc/release_notes/3.28.0.txt +2 -2
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +18 -9
- data/doc/transactions.rdoc +41 -1
- data/lib/sequel/adapters/ado.rb +28 -17
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/amalgalite.rb +11 -7
- data/lib/sequel/adapters/db2.rb +122 -70
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do.rb +5 -36
- data/lib/sequel/adapters/do/mysql.rb +0 -5
- data/lib/sequel/adapters/do/postgres.rb +0 -5
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/firebird.rb +3 -6
- data/lib/sequel/adapters/ibmdb.rb +24 -16
- data/lib/sequel/adapters/informix.rb +2 -4
- data/lib/sequel/adapters/jdbc.rb +47 -11
- data/lib/sequel/adapters/jdbc/as400.rb +5 -24
- data/lib/sequel/adapters/jdbc/db2.rb +0 -5
- data/lib/sequel/adapters/jdbc/derby.rb +217 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +0 -5
- data/lib/sequel/adapters/jdbc/h2.rb +10 -12
- data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
- data/lib/sequel/adapters/jdbc/informix.rb +0 -5
- data/lib/sequel/adapters/jdbc/jtds.rb +0 -5
- data/lib/sequel/adapters/jdbc/mysql.rb +0 -10
- data/lib/sequel/adapters/jdbc/oracle.rb +70 -3
- data/lib/sequel/adapters/jdbc/postgresql.rb +0 -11
- data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
- data/lib/sequel/adapters/jdbc/sqlserver.rb +0 -5
- data/lib/sequel/adapters/jdbc/transactions.rb +56 -7
- data/lib/sequel/adapters/mock.rb +315 -0
- data/lib/sequel/adapters/mysql.rb +64 -51
- data/lib/sequel/adapters/mysql2.rb +15 -9
- data/lib/sequel/adapters/odbc.rb +13 -6
- data/lib/sequel/adapters/odbc/db2.rb +0 -4
- data/lib/sequel/adapters/odbc/mssql.rb +0 -5
- data/lib/sequel/adapters/openbase.rb +2 -4
- data/lib/sequel/adapters/oracle.rb +333 -51
- data/lib/sequel/adapters/postgres.rb +80 -27
- data/lib/sequel/adapters/shared/access.rb +0 -6
- data/lib/sequel/adapters/shared/db2.rb +13 -15
- data/lib/sequel/adapters/shared/firebird.rb +6 -6
- data/lib/sequel/adapters/shared/mssql.rb +23 -18
- data/lib/sequel/adapters/shared/mysql.rb +6 -6
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
- data/lib/sequel/adapters/shared/oracle.rb +185 -30
- data/lib/sequel/adapters/shared/postgres.rb +35 -18
- data/lib/sequel/adapters/shared/progress.rb +0 -6
- data/lib/sequel/adapters/shared/sqlite.rb +116 -37
- data/lib/sequel/adapters/sqlite.rb +16 -8
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/swift/mysql.rb +0 -5
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +6 -4
- data/lib/sequel/adapters/tinytds.rb +13 -10
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -0
- data/lib/sequel/core.rb +40 -0
- data/lib/sequel/database/connecting.rb +1 -2
- data/lib/sequel/database/dataset.rb +3 -3
- data/lib/sequel/database/dataset_defaults.rb +58 -0
- data/lib/sequel/database/misc.rb +62 -2
- data/lib/sequel/database/query.rb +113 -49
- data/lib/sequel/database/schema_methods.rb +7 -2
- data/lib/sequel/dataset/actions.rb +37 -19
- data/lib/sequel/dataset/features.rb +24 -0
- data/lib/sequel/dataset/graph.rb +7 -6
- data/lib/sequel/dataset/misc.rb +11 -3
- data/lib/sequel/dataset/mutation.rb +2 -3
- data/lib/sequel/dataset/prepared_statements.rb +6 -4
- data/lib/sequel/dataset/query.rb +46 -15
- data/lib/sequel/dataset/sql.rb +28 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/model.rb +2 -1
- data/lib/sequel/model/associations.rb +115 -33
- data/lib/sequel/model/base.rb +91 -31
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +6 -10
- data/lib/sequel/plugins/prepared_statements.rb +12 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +6 -1
- data/lib/sequel/plugins/sharding.rb +0 -5
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/timezones.rb +42 -42
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +29 -29
- data/spec/adapters/mysql_spec.rb +86 -104
- data/spec/adapters/oracle_spec.rb +48 -76
- data/spec/adapters/postgres_spec.rb +98 -33
- data/spec/adapters/spec_helper.rb +0 -5
- data/spec/adapters/sqlite_spec.rb +24 -21
- data/spec/core/connection_pool_spec.rb +9 -15
- data/spec/core/core_sql_spec.rb +20 -31
- data/spec/core/database_spec.rb +491 -227
- data/spec/core/dataset_spec.rb +638 -1051
- data/spec/core/expression_filters_spec.rb +0 -1
- data/spec/core/mock_adapter_spec.rb +378 -0
- data/spec/core/object_graph_spec.rb +48 -114
- data/spec/core/schema_generator_spec.rb +3 -3
- data/spec/core/schema_spec.rb +51 -114
- data/spec/core/spec_helper.rb +3 -90
- data/spec/extensions/class_table_inheritance_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/instance_hooks_spec.rb +71 -0
- data/spec/extensions/named_timezones_spec.rb +22 -2
- data/spec/extensions/nested_attributes_spec.rb +3 -0
- data/spec/extensions/schema_spec.rb +1 -1
- data/spec/extensions/serialization_modification_detection_spec.rb +1 -0
- data/spec/extensions/serialization_spec.rb +5 -8
- data/spec/extensions/spec_helper.rb +4 -0
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/integration/associations_test.rb +123 -12
- data/spec/integration/dataset_test.rb +140 -47
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +179 -128
- data/spec/integration/prepared_statement_test.rb +92 -91
- data/spec/integration/schema_test.rb +42 -23
- data/spec/integration/spec_helper.rb +25 -31
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +161 -34
- data/spec/integration/type_test.rb +3 -3
- data/spec/model/association_reflection_spec.rb +83 -7
- data/spec/model/associations_spec.rb +393 -676
- data/spec/model/base_spec.rb +186 -116
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +343 -867
- data/spec/model/hooks_spec.rb +160 -79
- data/spec/model/model_spec.rb +118 -165
- data/spec/model/plugins_spec.rb +7 -13
- data/spec/model/record_spec.rb +138 -207
- data/spec/model/spec_helper.rb +10 -73
- metadata +14 -8
@@ -2,15 +2,19 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
2
|
|
3
3
|
describe Sequel::Model::Associations::AssociationReflection, "#associated_class" do
|
4
4
|
before do
|
5
|
-
@c = Class.new(Sequel::Model)
|
5
|
+
@c = Class.new(Sequel::Model(:foo))
|
6
6
|
class ::ParParent < Sequel::Model; end
|
7
7
|
end
|
8
|
+
after do
|
9
|
+
Object.send(:remove_const, :ParParent)
|
10
|
+
end
|
8
11
|
|
9
12
|
it "should use the :class value if present" do
|
10
13
|
@c.many_to_one :c, :class=>ParParent
|
11
14
|
@c.association_reflection(:c).keys.should include(:class)
|
12
15
|
@c.association_reflection(:c).associated_class.should == ParParent
|
13
16
|
end
|
17
|
+
|
14
18
|
it "should figure out the class if the :class value is not present" do
|
15
19
|
@c.many_to_one :c, :class=>'ParParent'
|
16
20
|
@c.association_reflection(:c).keys.should_not include(:class)
|
@@ -20,15 +24,19 @@ end
|
|
20
24
|
|
21
25
|
describe Sequel::Model::Associations::AssociationReflection, "#primary_key" do
|
22
26
|
before do
|
23
|
-
@c = Class.new(Sequel::Model)
|
27
|
+
@c = Class.new(Sequel::Model(:foo))
|
24
28
|
class ::ParParent < Sequel::Model; end
|
25
29
|
end
|
30
|
+
after do
|
31
|
+
Object.send(:remove_const, :ParParent)
|
32
|
+
end
|
26
33
|
|
27
34
|
it "should use the :primary_key value if present" do
|
28
35
|
@c.many_to_one :c, :class=>ParParent, :primary_key=>:blah__blah
|
29
36
|
@c.association_reflection(:c).keys.should include(:primary_key)
|
30
37
|
@c.association_reflection(:c).primary_key.should == :blah__blah
|
31
38
|
end
|
39
|
+
|
32
40
|
it "should use the associated table's primary key if :primary_key is not present" do
|
33
41
|
@c.many_to_one :c, :class=>'ParParent'
|
34
42
|
@c.association_reflection(:c).keys.should_not include(:primary_key)
|
@@ -49,8 +57,8 @@ describe Sequel::Model::Associations::AssociationReflection, "#reciprocal" do
|
|
49
57
|
end
|
50
58
|
|
51
59
|
it "should use the :reciprocal value if present" do
|
52
|
-
@c = Class.new(Sequel::Model)
|
53
|
-
@d = Class.new(Sequel::Model)
|
60
|
+
@c = Class.new(Sequel::Model(:foo))
|
61
|
+
@d = Class.new(Sequel::Model(:foo))
|
54
62
|
@c.many_to_one :c, :class=>@d, :reciprocal=>:xx
|
55
63
|
@c.association_reflection(:c).keys.should include(:reciprocal)
|
56
64
|
@c.association_reflection(:c).reciprocal.should == :xx
|
@@ -111,9 +119,12 @@ end
|
|
111
119
|
|
112
120
|
describe Sequel::Model::Associations::AssociationReflection, "#select" do
|
113
121
|
before do
|
114
|
-
@c = Class.new(Sequel::Model)
|
122
|
+
@c = Class.new(Sequel::Model(:foo))
|
115
123
|
class ::ParParent < Sequel::Model; end
|
116
124
|
end
|
125
|
+
after do
|
126
|
+
Object.send(:remove_const, :ParParent)
|
127
|
+
end
|
117
128
|
|
118
129
|
it "should use the :select value if present" do
|
119
130
|
@c.many_to_one :c, :class=>ParParent, :select=>[:par_parents__id]
|
@@ -143,9 +154,12 @@ end
|
|
143
154
|
|
144
155
|
describe Sequel::Model::Associations::AssociationReflection, "#associated_object_keys" do
|
145
156
|
before do
|
146
|
-
@c = Class.new(Sequel::Model)
|
157
|
+
@c = Class.new(Sequel::Model(:foo))
|
147
158
|
class ::ParParent < Sequel::Model; end
|
148
159
|
end
|
160
|
+
after do
|
161
|
+
Object.send(:remove_const, :ParParent)
|
162
|
+
end
|
149
163
|
|
150
164
|
it "should use the primary keys for a many_to_one association" do
|
151
165
|
@c.many_to_one :c, :class=>ParParent
|
@@ -175,7 +189,7 @@ end
|
|
175
189
|
|
176
190
|
describe Sequel::Model::Associations::AssociationReflection, "#remove_before_destroy?" do
|
177
191
|
before do
|
178
|
-
@c = Class.new(Sequel::Model)
|
192
|
+
@c = Class.new(Sequel::Model(:foo))
|
179
193
|
end
|
180
194
|
|
181
195
|
it "should be true for many_to_one and many_to_many associations" do
|
@@ -283,3 +297,65 @@ describe Sequel::Model::Associations::AssociationReflection, "#eager_limit_strat
|
|
283
297
|
@c.association_reflection(:c).eager_limit_strategy.should be_nil
|
284
298
|
end
|
285
299
|
end
|
300
|
+
|
301
|
+
describe Sequel::Model, " association reflection methods" do
|
302
|
+
before do
|
303
|
+
@c1 = Class.new(Sequel::Model(:nodes)) do
|
304
|
+
def self.name; 'Node'; end
|
305
|
+
def self.to_s; 'Node'; end
|
306
|
+
end
|
307
|
+
MODEL_DB.reset
|
308
|
+
end
|
309
|
+
|
310
|
+
it "#all_association_reflections should include all association reflection hashes" do
|
311
|
+
@c1.all_association_reflections.should == []
|
312
|
+
|
313
|
+
@c1.associate :many_to_one, :parent, :class => @c1
|
314
|
+
@c1.all_association_reflections.collect{|v| v[:name]}.should == [:parent]
|
315
|
+
@c1.all_association_reflections.collect{|v| v[:type]}.should == [:many_to_one]
|
316
|
+
@c1.all_association_reflections.collect{|v| v[:class]}.should == [@c1]
|
317
|
+
|
318
|
+
@c1.associate :one_to_many, :children, :class => @c1
|
319
|
+
@c1.all_association_reflections.sort_by{|x|x[:name].to_s}
|
320
|
+
@c1.all_association_reflections.sort_by{|x|x[:name].to_s}.collect{|v| v[:name]}.should == [:children, :parent]
|
321
|
+
@c1.all_association_reflections.sort_by{|x|x[:name].to_s}.collect{|v| v[:type]}.should == [:one_to_many, :many_to_one]
|
322
|
+
@c1.all_association_reflections.sort_by{|x|x[:name].to_s}.collect{|v| v[:class]}.should == [@c1, @c1]
|
323
|
+
end
|
324
|
+
|
325
|
+
it "#association_reflection should return nil for nonexistent association" do
|
326
|
+
@c1.association_reflection(:blah).should == nil
|
327
|
+
end
|
328
|
+
|
329
|
+
it "#association_reflection should return association reflection hash if association exists" do
|
330
|
+
@c1.associate :many_to_one, :parent, :class => @c1
|
331
|
+
@c1.association_reflection(:parent).should be_a_kind_of(Sequel::Model::Associations::AssociationReflection)
|
332
|
+
@c1.association_reflection(:parent)[:name].should == :parent
|
333
|
+
@c1.association_reflection(:parent)[:type].should == :many_to_one
|
334
|
+
@c1.association_reflection(:parent)[:class].should == @c1
|
335
|
+
|
336
|
+
@c1.associate :one_to_many, :children, :class => @c1
|
337
|
+
@c1.association_reflection(:children).should be_a_kind_of(Sequel::Model::Associations::AssociationReflection)
|
338
|
+
@c1.association_reflection(:children)[:name].should == :children
|
339
|
+
@c1.association_reflection(:children)[:type].should == :one_to_many
|
340
|
+
@c1.association_reflection(:children)[:class].should == @c1
|
341
|
+
end
|
342
|
+
|
343
|
+
it "#associations should include all association names" do
|
344
|
+
@c1.associations.should == []
|
345
|
+
@c1.associate :many_to_one, :parent, :class => @c1
|
346
|
+
@c1.associations.should == [:parent]
|
347
|
+
@c1.associate :one_to_many, :children, :class => @c1
|
348
|
+
@c1.associations.sort_by{|x|x.to_s}.should == [:children, :parent]
|
349
|
+
end
|
350
|
+
|
351
|
+
it "association reflections should be copied upon subclasing" do
|
352
|
+
@c1.associate :many_to_one, :parent, :class => @c1
|
353
|
+
c = Class.new(@c1)
|
354
|
+
@c1.associations.should == [:parent]
|
355
|
+
c.associations.should == [:parent]
|
356
|
+
c.associate :many_to_one, :parent2, :class => @c1
|
357
|
+
@c1.associations.should == [:parent]
|
358
|
+
c.associations.sort_by{|x| x.to_s}.should == [:parent, :parent2]
|
359
|
+
c.instance_methods.map{|x| x.to_s}.should include('parent')
|
360
|
+
end
|
361
|
+
end
|
@@ -2,42 +2,47 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
2
|
|
3
3
|
describe Sequel::Model, "associate" do
|
4
4
|
it "should use explicit class if given a class, symbol, or string" do
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
begin
|
6
|
+
klass = Class.new(Sequel::Model(:nodes))
|
7
|
+
class ::ParParent < Sequel::Model; end
|
8
|
+
|
9
|
+
klass.associate :many_to_one, :par_parent0, :class=>ParParent
|
10
|
+
klass.associate :one_to_many, :par_parent1s, :class=>'ParParent'
|
11
|
+
klass.associate :many_to_many, :par_parent2s, :class=>:ParParent
|
12
|
+
|
13
|
+
klass.association_reflection(:"par_parent0").associated_class.should == ParParent
|
14
|
+
klass.association_reflection(:"par_parent1s").associated_class.should == ParParent
|
15
|
+
klass.association_reflection(:"par_parent2s").associated_class.should == ParParent
|
16
|
+
ensure
|
17
|
+
Object.send(:remove_const, :ParParent)
|
8
18
|
end
|
9
|
-
|
10
|
-
klass.associate :many_to_one, :par_parent0, :class=>ParParent
|
11
|
-
klass.associate :one_to_many, :par_parent1s, :class=>'ParParent'
|
12
|
-
klass.associate :many_to_many, :par_parent2s, :class=>:ParParent
|
13
|
-
|
14
|
-
klass.association_reflection(:"par_parent0").associated_class.should == ParParent
|
15
|
-
klass.association_reflection(:"par_parent1s").associated_class.should == ParParent
|
16
|
-
klass.association_reflection(:"par_parent2s").associated_class.should == ParParent
|
17
19
|
end
|
18
20
|
|
19
21
|
it "should default to associating to other models in the same scope" do
|
20
|
-
|
21
|
-
class
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
begin
|
23
|
+
class ::AssociationModuleTest
|
24
|
+
class Album < Sequel::Model
|
25
|
+
many_to_one :artist
|
26
|
+
many_to_many :tags
|
27
|
+
end
|
28
|
+
class Artist< Sequel::Model
|
29
|
+
one_to_many :albums
|
30
|
+
end
|
31
|
+
class Tag < Sequel::Model
|
32
|
+
many_to_many :albums
|
33
|
+
end
|
30
34
|
end
|
35
|
+
|
36
|
+
::AssociationModuleTest::Album.association_reflection(:artist).associated_class.should == ::AssociationModuleTest::Artist
|
37
|
+
::AssociationModuleTest::Album.association_reflection(:tags).associated_class.should == ::AssociationModuleTest::Tag
|
38
|
+
::AssociationModuleTest::Artist.association_reflection(:albums).associated_class.should == ::AssociationModuleTest::Album
|
39
|
+
::AssociationModuleTest::Tag.association_reflection(:albums).associated_class.should == ::AssociationModuleTest::Album
|
40
|
+
ensure
|
41
|
+
Object.send(:remove_const, :AssociationModuleTest)
|
31
42
|
end
|
32
|
-
|
33
|
-
::AssociationModuleTest::Album.association_reflection(:artist).associated_class.should == ::AssociationModuleTest::Artist
|
34
|
-
::AssociationModuleTest::Album.association_reflection(:tags).associated_class.should == ::AssociationModuleTest::Tag
|
35
|
-
::AssociationModuleTest::Artist.association_reflection(:albums).associated_class.should == ::AssociationModuleTest::Album
|
36
|
-
::AssociationModuleTest::Tag.association_reflection(:albums).associated_class.should == ::AssociationModuleTest::Album
|
37
43
|
end
|
38
44
|
|
39
45
|
it "should add a model_object and association_reflection accessors to the dataset, and return it with the current model object" do
|
40
|
-
MODEL_DB.reset
|
41
46
|
klass = Class.new(Sequel::Model(:nodes)) do
|
42
47
|
columns :id, :a_id
|
43
48
|
end
|
@@ -64,7 +69,6 @@ describe Sequel::Model, "associate" do
|
|
64
69
|
end
|
65
70
|
|
66
71
|
it "should allow extending the dataset with :extend option" do
|
67
|
-
MODEL_DB.reset
|
68
72
|
klass = Class.new(Sequel::Model(:nodes)) do
|
69
73
|
columns :id, :a_id
|
70
74
|
end
|
@@ -91,44 +95,46 @@ describe Sequel::Model, "associate" do
|
|
91
95
|
end
|
92
96
|
|
93
97
|
it "should clone an existing association with the :clone option" do
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
98
|
+
begin
|
99
|
+
class ::ParParent < Sequel::Model; end
|
100
|
+
klass = Class.new(Sequel::Model(:nodes))
|
101
|
+
|
102
|
+
klass.many_to_one(:par_parent, :order=>:a){1}
|
103
|
+
klass.one_to_many(:par_parent1s, :class=>'ParParent', :limit=>12){4}
|
104
|
+
klass.many_to_many(:par_parent2s, :class=>:ParParent, :uniq=>true){2}
|
100
105
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
106
|
+
klass.many_to_one :par, :clone=>:par_parent, :select=>:b
|
107
|
+
klass.one_to_many :par1s, :clone=>:par_parent1s, :order=>:b, :limit=>10, :block=>nil
|
108
|
+
klass.many_to_many(:par2s, :clone=>:par_parent2s, :order=>:c){3}
|
109
|
+
|
110
|
+
klass.association_reflection(:par).associated_class.should == ParParent
|
111
|
+
klass.association_reflection(:par1s).associated_class.should == ParParent
|
112
|
+
klass.association_reflection(:par2s).associated_class.should == ParParent
|
113
|
+
|
114
|
+
klass.association_reflection(:par)[:order].should == :a
|
115
|
+
klass.association_reflection(:par).select.should == :b
|
116
|
+
klass.association_reflection(:par)[:block].call.should == 1
|
117
|
+
klass.association_reflection(:par1s)[:limit].should == 10
|
118
|
+
klass.association_reflection(:par1s)[:order].should == :b
|
119
|
+
klass.association_reflection(:par1s)[:block].should == nil
|
120
|
+
klass.association_reflection(:par2s)[:after_load].length.should == 1
|
121
|
+
klass.association_reflection(:par2s)[:order].should == :c
|
122
|
+
klass.association_reflection(:par2s)[:block].call.should == 3
|
123
|
+
ensure
|
124
|
+
Object.send(:remove_const, :ParParent)
|
125
|
+
end
|
118
126
|
end
|
119
127
|
|
120
128
|
end
|
121
129
|
|
122
130
|
describe Sequel::Model, "many_to_one" do
|
123
131
|
before do
|
124
|
-
MODEL_DB.reset
|
125
|
-
|
126
132
|
@c2 = Class.new(Sequel::Model(:nodes)) do
|
127
133
|
unrestrict_primary_key
|
128
134
|
columns :id, :parent_id, :par_parent_id, :blah
|
129
135
|
end
|
130
|
-
|
131
136
|
@dataset = @c2.dataset
|
137
|
+
MODEL_DB.reset
|
132
138
|
end
|
133
139
|
|
134
140
|
it "should use implicit key if omitted" do
|
@@ -143,31 +149,27 @@ describe Sequel::Model, "many_to_one" do
|
|
143
149
|
end
|
144
150
|
|
145
151
|
it "should use implicit class if omitted" do
|
146
|
-
|
152
|
+
begin
|
153
|
+
class ::ParParent < Sequel::Model; end
|
154
|
+
@c2.many_to_one :par_parent
|
155
|
+
@c2.new(:id => 1, :par_parent_id => 234).par_parent.class.should == ParParent
|
156
|
+
MODEL_DB.sqls.should == ["SELECT * FROM par_parents WHERE (par_parents.id = 234) LIMIT 1"]
|
157
|
+
ensure
|
158
|
+
Object.send(:remove_const, :ParParent)
|
147
159
|
end
|
148
|
-
|
149
|
-
@c2.many_to_one :par_parent
|
150
|
-
|
151
|
-
d = @c2.new(:id => 1, :par_parent_id => 234)
|
152
|
-
p = d.par_parent
|
153
|
-
p.class.should == ParParent
|
154
|
-
|
155
|
-
MODEL_DB.sqls.should == ["SELECT * FROM par_parents WHERE (par_parents.id = 234) LIMIT 1"]
|
156
160
|
end
|
157
161
|
|
158
162
|
it "should use class inside module if given as a string" do
|
159
|
-
|
160
|
-
|
163
|
+
begin
|
164
|
+
module ::Par
|
165
|
+
class Parent < Sequel::Model; end
|
161
166
|
end
|
167
|
+
@c2.many_to_one :par_parent, :class=>"Par::Parent"
|
168
|
+
@c2.new(:id => 1, :par_parent_id => 234).par_parent.class.should == Par::Parent
|
169
|
+
MODEL_DB.sqls.should == ["SELECT * FROM parents WHERE (parents.id = 234) LIMIT 1"]
|
170
|
+
ensure
|
171
|
+
Object.send(:remove_const, :Par)
|
162
172
|
end
|
163
|
-
|
164
|
-
@c2.many_to_one :par_parent, :class=>"Par::Parent"
|
165
|
-
|
166
|
-
d = @c2.new(:id => 1, :par_parent_id => 234)
|
167
|
-
p = d.par_parent
|
168
|
-
p.class.should == Par::Parent
|
169
|
-
|
170
|
-
MODEL_DB.sqls.should == ["SELECT * FROM parents WHERE (parents.id = 234) LIMIT 1"]
|
171
173
|
end
|
172
174
|
|
173
175
|
it "should use explicit key if given" do
|
@@ -181,6 +183,12 @@ describe Sequel::Model, "many_to_one" do
|
|
181
183
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (nodes.id = 567) LIMIT 1"]
|
182
184
|
end
|
183
185
|
|
186
|
+
it "should respect :qualify => false option" do
|
187
|
+
@c2.many_to_one :parent, :class => @c2, :key => :blah, :qualify=>false
|
188
|
+
@c2.new(:id => 1, :blah => 567).parent
|
189
|
+
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (id = 567) LIMIT 1"]
|
190
|
+
end
|
191
|
+
|
184
192
|
it "should use :primary_key option if given" do
|
185
193
|
@c2.many_to_one :parent, :class => @c2, :key => :blah, :primary_key => :pk
|
186
194
|
@c2.new(:id => 1, :blah => 567).parent
|
@@ -218,14 +226,12 @@ describe Sequel::Model, "many_to_one" do
|
|
218
226
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.id = 567) AND (a = 32)) LIMIT 1"]
|
219
227
|
|
220
228
|
@c2.many_to_one :parent, :class => @c2, :key => :blah, :conditions=>:a
|
221
|
-
MODEL_DB.sqls.clear
|
222
229
|
@c2.new(:id => 1, :blah => 567).parent
|
223
230
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.id = 567) AND a) LIMIT 1"]
|
224
231
|
end
|
225
232
|
|
226
233
|
it "should support :order, :limit (only for offset), and :dataset options, as well as a block" do
|
227
|
-
c2
|
228
|
-
@c2.many_to_one :child_20, :class => @c2, :key=>:id, :dataset=>proc{c2.filter(:parent_id=>pk)}, :limit=>[10,20], :order=>:name do |ds|
|
234
|
+
@c2.many_to_one :child_20, :class => @c2, :key=>:id, :dataset=>proc{model.filter(:parent_id=>pk)}, :limit=>[10,20], :order=>:name do |ds|
|
229
235
|
ds.filter(:x.sql_number > 1)
|
230
236
|
end
|
231
237
|
@c2.load(:id => 100).child_20
|
@@ -234,24 +240,19 @@ describe Sequel::Model, "many_to_one" do
|
|
234
240
|
|
235
241
|
it "should return nil if key value is nil" do
|
236
242
|
@c2.many_to_one :parent, :class => @c2
|
237
|
-
|
238
|
-
|
239
|
-
d.parent.should == nil
|
243
|
+
@c2.new(:id => 1).parent.should == nil
|
244
|
+
MODEL_DB.sqls.should == []
|
240
245
|
end
|
241
246
|
|
242
247
|
it "should cache negative lookup" do
|
243
248
|
@c2.many_to_one :parent, :class => @c2
|
244
|
-
|
245
|
-
def ds.fetch_rows(sql, &block)
|
246
|
-
MODEL_DB.sqls << sql
|
247
|
-
end
|
248
|
-
|
249
|
+
@c2.dataset._fetch = []
|
249
250
|
d = @c2.new(:id => 1, :parent_id=>555)
|
250
251
|
MODEL_DB.sqls.should == []
|
251
252
|
d.parent.should == nil
|
252
253
|
MODEL_DB.sqls.should == ['SELECT * FROM nodes WHERE (nodes.id = 555) LIMIT 1']
|
253
254
|
d.parent.should == nil
|
254
|
-
MODEL_DB.sqls.should == [
|
255
|
+
MODEL_DB.sqls.should == []
|
255
256
|
end
|
256
257
|
|
257
258
|
it "should define a setter method" do
|
@@ -314,11 +315,9 @@ describe Sequel::Model, "many_to_one" do
|
|
314
315
|
@c2.many_to_one :parent, :class => @c2
|
315
316
|
|
316
317
|
d = @c2.load(:id => 1)
|
317
|
-
MODEL_DB.reset
|
318
318
|
d.parent_id = 234
|
319
319
|
d.associations[:parent].should == nil
|
320
|
-
|
321
|
-
def ds.fetch_rows(sql, &block); MODEL_DB.sqls << sql; yield({:id=>234}) end
|
320
|
+
@c2.dataset._fetch = {:id=>234}
|
322
321
|
e = d.parent
|
323
322
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (nodes.id = 234) LIMIT 1"]
|
324
323
|
d.associations[:parent].should == e
|
@@ -382,10 +381,7 @@ describe Sequel::Model, "many_to_one" do
|
|
382
381
|
it "should have the setter add to the reciprocal one_to_many cached association list if it exists" do
|
383
382
|
@c2.many_to_one :parent, :class => @c2
|
384
383
|
@c2.one_to_many :children, :class => @c2, :key=>:parent_id
|
385
|
-
|
386
|
-
def ds.fetch_rows(sql, &block)
|
387
|
-
MODEL_DB.sqls << sql
|
388
|
-
end
|
384
|
+
@c2.dataset._fetch = []
|
389
385
|
|
390
386
|
d = @c2.new(:id => 1)
|
391
387
|
e = @c2.new(:id => 2)
|
@@ -394,14 +390,13 @@ describe Sequel::Model, "many_to_one" do
|
|
394
390
|
e.children.should_not(include(d))
|
395
391
|
MODEL_DB.sqls.should == ['SELECT * FROM nodes WHERE (nodes.parent_id = 2)']
|
396
392
|
|
397
|
-
MODEL_DB.reset
|
398
393
|
d = @c2.new(:id => 1)
|
399
394
|
e = @c2.new(:id => 2)
|
400
395
|
e.children.should_not(include(d))
|
401
396
|
MODEL_DB.sqls.should == ['SELECT * FROM nodes WHERE (nodes.parent_id = 2)']
|
402
397
|
d.parent = e
|
403
398
|
e.children.should(include(d))
|
404
|
-
MODEL_DB.sqls.should == [
|
399
|
+
MODEL_DB.sqls.should == []
|
405
400
|
end
|
406
401
|
|
407
402
|
it "should have many_to_one setter deal with a one_to_one reciprocal" do
|
@@ -429,10 +424,7 @@ describe Sequel::Model, "many_to_one" do
|
|
429
424
|
it "should have the setter remove the object from the previous associated object's reciprocal one_to_many cached association list if it exists" do
|
430
425
|
@c2.many_to_one :parent, :class => @c2
|
431
426
|
@c2.one_to_many :children, :class => @c2, :key=>:parent_id
|
432
|
-
|
433
|
-
def ds.fetch_rows(sql, &block)
|
434
|
-
MODEL_DB.sqls << sql
|
435
|
-
end
|
427
|
+
@c2.dataset._fetch = []
|
436
428
|
|
437
429
|
d = @c2.new(:id => 1)
|
438
430
|
e = @c2.new(:id => 2)
|
@@ -451,17 +443,9 @@ describe Sequel::Model, "many_to_one" do
|
|
451
443
|
end
|
452
444
|
|
453
445
|
it "should get all matching records and only return the first if :key option is set to nil" do
|
454
|
-
c2 = @c2
|
455
446
|
@c2.one_to_many :children, :class => @c2, :key=>:parent_id
|
456
|
-
@c2.many_to_one :first_grand_parent, :class => @c2, :key=>nil, :eager_graph=>:children, :dataset=>proc{
|
457
|
-
|
458
|
-
def ds.columns
|
459
|
-
[:id, :parent_id, :par_parent_id, :blah]
|
460
|
-
end
|
461
|
-
def ds.fetch_rows(sql, &block)
|
462
|
-
MODEL_DB.sqls << sql
|
463
|
-
yield({:id=>1, :parent_id=>0, :par_parent_id=>3, :blah=>4, :children_id=>2, :children_parent_id=>1, :children_par_parent_id=>5, :children_blah=>6})
|
464
|
-
end
|
447
|
+
@c2.many_to_one :first_grand_parent, :class => @c2, :key=>nil, :eager_graph=>:children, :dataset=>proc{model.filter(:children_id=>parent_id)}
|
448
|
+
@c2.dataset.columns(:id, :parent_id, :par_parent_id, :blah)._fetch = [{:id=>1, :parent_id=>0, :par_parent_id=>3, :blah=>4, :children_id=>2, :children_parent_id=>1, :children_par_parent_id=>5, :children_blah=>6}, {}]
|
465
449
|
p = @c2.new(:parent_id=>2)
|
466
450
|
fgp = p.first_grand_parent
|
467
451
|
MODEL_DB.sqls.should == ["SELECT nodes.id, nodes.parent_id, nodes.par_parent_id, nodes.blah, children.id AS children_id, children.parent_id AS children_parent_id, children.par_parent_id AS children_par_parent_id, children.blah AS children_blah FROM nodes LEFT OUTER JOIN nodes AS children ON (children.parent_id = nodes.id) WHERE (children_id = 2)"]
|
@@ -522,15 +506,15 @@ describe Sequel::Model, "many_to_one" do
|
|
522
506
|
h = []
|
523
507
|
@c2.many_to_one :parent, :class => @c2, :before_set=>[proc{|x,y| h << x.pk; h << (y ? -y.pk : :y)}, :blah], :after_set=>proc{h << 3}
|
524
508
|
@c2.class_eval do
|
525
|
-
|
509
|
+
self::Foo = h
|
526
510
|
def []=(a, v)
|
527
|
-
a == :parent_id ? (
|
511
|
+
a == :parent_id ? (model::Foo << (v ? 4 : 5)) : super
|
528
512
|
end
|
529
513
|
def blah(x)
|
530
|
-
|
514
|
+
model::Foo << (x ? x.pk : :x)
|
531
515
|
end
|
532
516
|
def blahr(x)
|
533
|
-
|
517
|
+
model::Foo << 6
|
534
518
|
end
|
535
519
|
end
|
536
520
|
p = @c2.load(:id=>10)
|
@@ -546,13 +530,11 @@ describe Sequel::Model, "many_to_one" do
|
|
546
530
|
h = []
|
547
531
|
@c2.many_to_one :parent, :class => @c2, :after_load=>[proc{|x,y| h << [x.pk, y.pk]}, :al]
|
548
532
|
@c2.class_eval do
|
549
|
-
|
533
|
+
self::Foo = h
|
550
534
|
def al(v)
|
551
|
-
|
552
|
-
end
|
553
|
-
def @dataset.fetch_rows(sql)
|
554
|
-
yield({:id=>20})
|
535
|
+
model::Foo << v.pk
|
555
536
|
end
|
537
|
+
dataset._fetch = {:id=>20}
|
556
538
|
end
|
557
539
|
p = @c2.load(:id=>10, :parent_id=>20)
|
558
540
|
parent = p.parent
|
@@ -561,7 +543,6 @@ describe Sequel::Model, "many_to_one" do
|
|
561
543
|
end
|
562
544
|
|
563
545
|
it "should support after_load association callback that changes the cached object" do
|
564
|
-
h = []
|
565
546
|
@c2.many_to_one :parent, :class => @c2, :after_load=>:al
|
566
547
|
@c2.class_eval do
|
567
548
|
def al(v)
|
@@ -600,35 +581,32 @@ describe Sequel::Model, "many_to_one" do
|
|
600
581
|
d = @c2.load(:id=>321)
|
601
582
|
p = @c2.new
|
602
583
|
p.associations[:parent] = d
|
603
|
-
h = []
|
604
584
|
@c2.many_to_one :parent, :class => @c2, :before_set=>:bs, :after_set=>:as
|
605
585
|
@c2.class_eval do
|
606
|
-
|
586
|
+
self::Foo = []
|
607
587
|
def []=(a, v)
|
608
|
-
a == :parent_id ? (
|
588
|
+
a == :parent_id ? (model::Foo << 5) : super
|
609
589
|
end
|
610
590
|
def bs(x)
|
611
|
-
|
591
|
+
model::Foo << x.pk
|
612
592
|
end
|
613
593
|
def as(x)
|
614
|
-
|
594
|
+
model::Foo << x.pk * 2
|
615
595
|
end
|
616
596
|
end
|
617
597
|
p.parent = c
|
618
|
-
|
598
|
+
@c2::Foo.should == [123, 5, 246]
|
619
599
|
end
|
620
600
|
end
|
621
601
|
|
622
602
|
describe Sequel::Model, "one_to_one" do
|
623
603
|
before do
|
624
604
|
@c1 = Class.new(Sequel::Model(:attributes)) do
|
625
|
-
def _refresh(ds); end
|
626
605
|
unrestrict_primary_key
|
627
606
|
columns :id, :node_id, :y
|
628
607
|
end
|
629
608
|
|
630
609
|
@c2 = Class.new(Sequel::Model(:nodes)) do
|
631
|
-
def _refresh(ds); end
|
632
610
|
unrestrict_primary_key
|
633
611
|
attr_accessor :xxx
|
634
612
|
|
@@ -637,24 +615,8 @@ describe Sequel::Model, "one_to_one" do
|
|
637
615
|
columns :id, :x, :parent_id, :par_parent_id, :blah, :node_id
|
638
616
|
end
|
639
617
|
@dataset = @c2.dataset
|
640
|
-
|
641
|
-
@
|
642
|
-
def empty?; false; end
|
643
|
-
def fetch_rows(sql)
|
644
|
-
@db << sql
|
645
|
-
yield Hash.new
|
646
|
-
end
|
647
|
-
})
|
648
|
-
|
649
|
-
@c1.dataset.extend(Module.new {
|
650
|
-
def empty?; opts.has_key?(:empty) ? (super; true) : false; end
|
651
|
-
def fetch_rows(sql)
|
652
|
-
@db << sql
|
653
|
-
yield Hash.new
|
654
|
-
end
|
655
|
-
})
|
656
|
-
|
657
|
-
@dataset = @c2.dataset
|
618
|
+
@dataset._fetch = {}
|
619
|
+
@c1.dataset._fetch = {}
|
658
620
|
MODEL_DB.reset
|
659
621
|
end
|
660
622
|
|
@@ -676,26 +638,24 @@ describe Sequel::Model, "one_to_one" do
|
|
676
638
|
it "should add a setter method" do
|
677
639
|
@c2.one_to_one :attribute, :class => @c1
|
678
640
|
attrib = @c1.new(:id=>3)
|
679
|
-
|
680
|
-
@c1.class_eval{remove_method :_refresh}
|
681
|
-
def d.fetch_rows(s); yield({:id=>3}) end
|
641
|
+
@c1.dataset._fetch = {:id=>3}
|
682
642
|
@c2.new(:id => 1234).attribute = attrib
|
643
|
+
sqls = MODEL_DB.sqls
|
683
644
|
['INSERT INTO attributes (node_id, id) VALUES (1234, 3)',
|
684
|
-
'INSERT INTO attributes (id, node_id) VALUES (3, 1234)'].should(include(
|
685
|
-
|
686
|
-
|
645
|
+
'INSERT INTO attributes (id, node_id) VALUES (3, 1234)'].should(include(sqls.slice! 1))
|
646
|
+
sqls.should == ['UPDATE attributes SET node_id = NULL WHERE ((node_id = 1234) AND (id != 3))', "SELECT * FROM attributes WHERE (id = 3) LIMIT 1"]
|
647
|
+
|
687
648
|
@c2.new(:id => 1234).attribute.should == attrib
|
688
|
-
MODEL_DB.sqls.clear
|
689
649
|
attrib = @c1.load(:id=>3)
|
690
650
|
@c2.new(:id => 1234).attribute = attrib
|
691
|
-
MODEL_DB.sqls.should == [
|
651
|
+
MODEL_DB.sqls.should == ["SELECT * FROM attributes WHERE (attributes.node_id = 1234) LIMIT 1",
|
652
|
+
'UPDATE attributes SET node_id = NULL WHERE ((node_id = 1234) AND (id != 3))',
|
692
653
|
"UPDATE attributes SET node_id = 1234 WHERE (id = 3)"]
|
693
654
|
end
|
694
655
|
|
695
656
|
it "should use a transaction in the setter method" do
|
696
657
|
@c2.one_to_one :attribute, :class => @c1
|
697
658
|
@c2.use_transactions = true
|
698
|
-
MODEL_DB.sqls.clear
|
699
659
|
attrib = @c1.load(:id=>3)
|
700
660
|
@c2.new(:id => 1234).attribute = attrib
|
701
661
|
MODEL_DB.sqls.should == ['BEGIN',
|
@@ -708,7 +668,6 @@ describe Sequel::Model, "one_to_one" do
|
|
708
668
|
@c2.one_to_one :attribute, :class => @c1, :conditions=>{:a=>1} do |ds|
|
709
669
|
ds.filter(:b=>2)
|
710
670
|
end
|
711
|
-
MODEL_DB.sqls.clear
|
712
671
|
attrib = @c1.load(:id=>3)
|
713
672
|
@c2.new(:id => 1234).attribute = attrib
|
714
673
|
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = NULL WHERE ((node_id = 1234) AND (a = 1) AND (b = 2) AND (id != 3))',
|
@@ -718,30 +677,30 @@ describe Sequel::Model, "one_to_one" do
|
|
718
677
|
it "should have the setter method respect the :primary_key option" do
|
719
678
|
@c2.one_to_one :attribute, :class => @c1, :primary_key=>:xxx
|
720
679
|
attrib = @c1.new(:id=>3)
|
721
|
-
|
722
|
-
@c1.class_eval{remove_method :_refresh}
|
723
|
-
def d.fetch_rows(s); yield({:id=>3}) end
|
680
|
+
@c1.dataset._fetch = {:id=>3}
|
724
681
|
@c2.new(:id => 1234, :xxx=>5).attribute = attrib
|
682
|
+
sqls = MODEL_DB.sqls
|
725
683
|
['INSERT INTO attributes (node_id, id) VALUES (5, 3)',
|
726
|
-
'INSERT INTO attributes (id, node_id) VALUES (3, 5)'].should(include(
|
727
|
-
|
728
|
-
|
684
|
+
'INSERT INTO attributes (id, node_id) VALUES (3, 5)'].should(include(sqls.slice! 1))
|
685
|
+
sqls.should == ['UPDATE attributes SET node_id = NULL WHERE ((node_id = 5) AND (id != 3))', "SELECT * FROM attributes WHERE (id = 3) LIMIT 1"]
|
686
|
+
|
729
687
|
@c2.new(:id => 321, :xxx=>5).attribute.should == attrib
|
730
|
-
MODEL_DB.sqls.clear
|
731
688
|
attrib = @c1.load(:id=>3)
|
732
689
|
@c2.new(:id => 621, :xxx=>5).attribute = attrib
|
733
|
-
MODEL_DB.sqls.should == [
|
690
|
+
MODEL_DB.sqls.should == ["SELECT * FROM attributes WHERE (attributes.node_id = 5) LIMIT 1",
|
691
|
+
'UPDATE attributes SET node_id = NULL WHERE ((node_id = 5) AND (id != 3))',
|
734
692
|
'UPDATE attributes SET node_id = 5 WHERE (id = 3)']
|
735
693
|
end
|
736
694
|
|
737
695
|
it "should have the setter method respect composite keys" do
|
738
696
|
@c2.one_to_one :attribute, :class => @c1, :key=>[:node_id, :y], :primary_key=>[:id, :x]
|
739
697
|
attrib = @c1.load(:id=>3, :y=>6)
|
740
|
-
|
741
|
-
def d.fetch_rows(s); yield({:id=>3, :y=>6}) end
|
698
|
+
@c1.dataset._fetch = {:id=>3, :y=>6}
|
742
699
|
@c2.load(:id => 1234, :x=>5).attribute = attrib
|
743
|
-
|
744
|
-
|
700
|
+
sqls = MODEL_DB.sqls
|
701
|
+
sqls.last.should =~ /UPDATE attributes SET (node_id = 1234|y = 5), (node_id = 1234|y = 5) WHERE \(id = 3\)/
|
702
|
+
sqls.first.should =~ /UPDATE attributes SET (node_id|y) = NULL, (node_id|y) = NULL WHERE \(\(node_id = 1234\) AND \(y = 5\) AND \(id != 3\)\)/
|
703
|
+
sqls.length.should == 2
|
745
704
|
end
|
746
705
|
|
747
706
|
it "should use implicit key if omitted" do
|
@@ -756,31 +715,27 @@ describe Sequel::Model, "one_to_one" do
|
|
756
715
|
end
|
757
716
|
|
758
717
|
it "should use implicit class if omitted" do
|
759
|
-
|
718
|
+
begin
|
719
|
+
class ::ParParent < Sequel::Model; end
|
720
|
+
@c2.one_to_one :par_parent
|
721
|
+
@c2.new(:id => 234).par_parent.class.should == ParParent
|
722
|
+
MODEL_DB.sqls.should == ["SELECT * FROM par_parents WHERE (par_parents.node_id = 234) LIMIT 1"]
|
723
|
+
ensure
|
724
|
+
Object.send(:remove_const, :ParParent)
|
760
725
|
end
|
761
|
-
|
762
|
-
@c2.one_to_one :par_parent
|
763
|
-
|
764
|
-
d = @c2.new(:id => 234)
|
765
|
-
p = d.par_parent
|
766
|
-
p.class.should == ParParent
|
767
|
-
|
768
|
-
MODEL_DB.sqls.should == ["SELECT * FROM par_parents WHERE (par_parents.node_id = 234) LIMIT 1"]
|
769
726
|
end
|
770
727
|
|
771
728
|
it "should use class inside module if given as a string" do
|
772
|
-
|
773
|
-
|
729
|
+
begin
|
730
|
+
module ::Par
|
731
|
+
class Parent < Sequel::Model; end
|
774
732
|
end
|
733
|
+
@c2.one_to_one :par_parent, :class=>"Par::Parent"
|
734
|
+
@c2.new(:id => 234).par_parent.class.should == Par::Parent
|
735
|
+
MODEL_DB.sqls.should == ["SELECT * FROM parents WHERE (parents.node_id = 234) LIMIT 1"]
|
736
|
+
ensure
|
737
|
+
Object.send(:remove_const, :Par)
|
775
738
|
end
|
776
|
-
|
777
|
-
@c2.one_to_one :par_parent, :class=>"Par::Parent"
|
778
|
-
|
779
|
-
d = @c2.new(:id => 234)
|
780
|
-
p = d.par_parent
|
781
|
-
p.class.should == Par::Parent
|
782
|
-
|
783
|
-
MODEL_DB.sqls.should == ["SELECT * FROM parents WHERE (parents.node_id = 234) LIMIT 1"]
|
784
739
|
end
|
785
740
|
|
786
741
|
it "should use explicit key if given" do
|
@@ -831,14 +786,12 @@ describe Sequel::Model, "one_to_one" do
|
|
831
786
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.node_id = 567) AND (a = 32)) LIMIT 1"]
|
832
787
|
|
833
788
|
@c2.one_to_one :parent, :class => @c2, :conditions=>:a
|
834
|
-
MODEL_DB.sqls.clear
|
835
789
|
@c2.new(:id => 567).parent
|
836
790
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.node_id = 567) AND a) LIMIT 1"]
|
837
791
|
end
|
838
792
|
|
839
793
|
it "should support :order, :limit (only for offset), and :dataset options, as well as a block" do
|
840
|
-
c2
|
841
|
-
@c2.one_to_one :child_20, :class => @c2, :key=>:id, :dataset=>proc{c2.filter(:parent_id=>pk)}, :limit=>[10,20], :order=>:name do |ds|
|
794
|
+
@c2.one_to_one :child_20, :class => @c2, :key=>:id, :dataset=>proc{model.filter(:parent_id=>pk)}, :limit=>[10,20], :order=>:name do |ds|
|
842
795
|
ds.filter(:x.sql_number > 1)
|
843
796
|
end
|
844
797
|
@c2.load(:id => 100).child_20
|
@@ -848,24 +801,19 @@ describe Sequel::Model, "one_to_one" do
|
|
848
801
|
it "should return nil if primary_key value is nil" do
|
849
802
|
@c2.one_to_one :parent, :class => @c2, :primary_key=>:node_id
|
850
803
|
|
851
|
-
|
852
|
-
d.parent.should == nil
|
804
|
+
@c2.new(:id => 1).parent.should be_nil
|
853
805
|
MODEL_DB.sqls.should == []
|
854
806
|
end
|
855
807
|
|
856
808
|
it "should cache negative lookup" do
|
857
809
|
@c2.one_to_one :parent, :class => @c2
|
858
|
-
|
859
|
-
def ds.fetch_rows(sql, &block)
|
860
|
-
MODEL_DB.sqls << sql
|
861
|
-
end
|
862
|
-
|
810
|
+
@c2.dataset._fetch = []
|
863
811
|
d = @c2.new(:id => 555)
|
864
812
|
MODEL_DB.sqls.should == []
|
865
813
|
d.parent.should == nil
|
866
814
|
MODEL_DB.sqls.should == ['SELECT * FROM nodes WHERE (nodes.node_id = 555) LIMIT 1']
|
867
815
|
d.parent.should == nil
|
868
|
-
MODEL_DB.sqls.should == [
|
816
|
+
MODEL_DB.sqls.should == []
|
869
817
|
end
|
870
818
|
|
871
819
|
it "should define a setter method" do
|
@@ -873,28 +821,44 @@ describe Sequel::Model, "one_to_one" do
|
|
873
821
|
|
874
822
|
d = @c2.new(:id => 1)
|
875
823
|
f = @c2.new(:id => 3, :node_id=> 4321)
|
824
|
+
@c2.dataset._fetch = {:id => 3, :node_id=>1}
|
876
825
|
d.parent = f
|
877
826
|
f.values.should == {:id => 3, :node_id=>1}
|
878
827
|
d.parent.should == f
|
828
|
+
sqls = MODEL_DB.sqls
|
829
|
+
["INSERT INTO nodes (node_id, id) VALUES (1, 3)",
|
830
|
+
"INSERT INTO nodes (id, node_id) VALUES (3, 1)"].should include(sqls.slice! 1)
|
831
|
+
sqls.should == ["UPDATE nodes SET node_id = NULL WHERE ((node_id = 1) AND (id != 3))", "SELECT * FROM nodes WHERE (id = 3) LIMIT 1"]
|
879
832
|
|
880
833
|
d.parent = nil
|
881
834
|
d.parent.should == nil
|
835
|
+
MODEL_DB.sqls.should == ["UPDATE nodes SET node_id = NULL WHERE (node_id = 1)"]
|
882
836
|
end
|
883
837
|
|
884
838
|
it "should have the setter method respect the :primary_key option" do
|
885
839
|
@c2.one_to_one :parent, :class => @c2, :primary_key=>:blah
|
886
840
|
d = @c2.new(:id => 1, :blah => 3)
|
887
841
|
e = @c2.new(:id => 4321, :node_id=>444)
|
842
|
+
@c2.dataset._fetch = {:id => 4321, :node_id => 3}
|
888
843
|
d.parent = e
|
889
844
|
e.values.should == {:id => 4321, :node_id => 3}
|
845
|
+
sqls = MODEL_DB.sqls
|
846
|
+
["INSERT INTO nodes (node_id, id) VALUES (3, 4321)",
|
847
|
+
"INSERT INTO nodes (id, node_id) VALUES (4321, 3)"].should include(sqls.slice! 1)
|
848
|
+
sqls.should == ["UPDATE nodes SET node_id = NULL WHERE ((node_id = 3) AND (id != 4321))", "SELECT * FROM nodes WHERE (id = 4321) LIMIT 1"]
|
890
849
|
end
|
891
850
|
|
892
851
|
it "should have the setter method respect the :key option" do
|
893
852
|
@c2.one_to_one :parent, :class => @c2, :key=>:blah
|
894
853
|
d = @c2.new(:id => 3)
|
895
854
|
e = @c2.new(:id => 4321, :blah=>444)
|
855
|
+
@c2.dataset._fetch = {:id => 4321, :blah => 3}
|
896
856
|
d.parent = e
|
897
857
|
e.values.should == {:id => 4321, :blah => 3}
|
858
|
+
sqls = MODEL_DB.sqls
|
859
|
+
["INSERT INTO nodes (blah, id) VALUES (3, 4321)",
|
860
|
+
"INSERT INTO nodes (id, blah) VALUES (4321, 3)"].should include(sqls.slice! 1)
|
861
|
+
sqls.should == ["UPDATE nodes SET blah = NULL WHERE ((blah = 3) AND (id != 4321))", "SELECT * FROM nodes WHERE (id = 4321) LIMIT 1"]
|
898
862
|
end
|
899
863
|
|
900
864
|
it "should persist changes to associated object when the setter is called" do
|
@@ -910,12 +874,11 @@ describe Sequel::Model, "one_to_one" do
|
|
910
874
|
|
911
875
|
d = @c2.load(:id => 1)
|
912
876
|
d.associations[:parent].should == nil
|
913
|
-
|
914
|
-
def ds.fetch_rows(sql, &block); MODEL_DB.sqls << sql; yield({:id=>234}) end
|
877
|
+
@c2.dataset._fetch = {:id=>234}
|
915
878
|
e = d.parent
|
916
879
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (nodes.node_id = 1) LIMIT 1"]
|
917
880
|
d.parent
|
918
|
-
MODEL_DB.sqls.should == [
|
881
|
+
MODEL_DB.sqls.should == []
|
919
882
|
d.associations[:parent].should == e
|
920
883
|
end
|
921
884
|
|
@@ -957,7 +920,6 @@ describe Sequel::Model, "one_to_one" do
|
|
957
920
|
e.child.should == d
|
958
921
|
MODEL_DB.sqls.should == ["UPDATE nodes SET parent_id = NULL WHERE ((parent_id = 1) AND (id != 2))",
|
959
922
|
"UPDATE nodes SET parent_id = 1 WHERE (id = 2)"]
|
960
|
-
MODEL_DB.reset
|
961
923
|
d.parent = nil
|
962
924
|
e.child.should == nil
|
963
925
|
MODEL_DB.sqls.should == ["UPDATE nodes SET parent_id = NULL WHERE (parent_id = 1)"]
|
@@ -966,17 +928,13 @@ describe Sequel::Model, "one_to_one" do
|
|
966
928
|
it "should have the setter remove the object from the previous associated object's reciprocal many_to_one cached association list if it exists" do
|
967
929
|
@c2.one_to_one :parent, :class => @c2, :key=>:parent_id
|
968
930
|
@c2.many_to_one :child, :class => @c2, :key=>:parent_id
|
969
|
-
|
970
|
-
def ds.fetch_rows(sql, &block)
|
971
|
-
MODEL_DB.sqls << sql
|
972
|
-
end
|
931
|
+
@c2.dataset._fetch = []
|
973
932
|
|
974
933
|
d = @c2.load(:id => 1)
|
975
934
|
e = @c2.load(:id => 2)
|
976
935
|
f = @c2.load(:id => 3)
|
977
936
|
e.child.should == nil
|
978
937
|
f.child.should == nil
|
979
|
-
MODEL_DB.reset
|
980
938
|
d.parent = e
|
981
939
|
e.child.should == d
|
982
940
|
d.parent = f
|
@@ -1018,12 +976,12 @@ describe Sequel::Model, "one_to_one" do
|
|
1018
976
|
h = []
|
1019
977
|
@c2.one_to_one :parent, :class => @c2, :before_set=>[proc{|x,y| h << x.pk; h << (y ? -y.pk : :y)}, :blah], :after_set=>proc{h << 3}
|
1020
978
|
@c2.class_eval do
|
1021
|
-
|
979
|
+
self::Foo = h
|
1022
980
|
def blah(x)
|
1023
|
-
|
981
|
+
model::Foo << (x ? x.pk : :x)
|
1024
982
|
end
|
1025
983
|
def blahr(x)
|
1026
|
-
|
984
|
+
model::Foo << 6
|
1027
985
|
end
|
1028
986
|
end
|
1029
987
|
p = @c2.load(:id=>10)
|
@@ -1039,13 +997,11 @@ describe Sequel::Model, "one_to_one" do
|
|
1039
997
|
h = []
|
1040
998
|
@c2.one_to_one :parent, :class => @c2, :after_load=>[proc{|x,y| h << [x.pk, y.pk]}, :al]
|
1041
999
|
@c2.class_eval do
|
1042
|
-
|
1000
|
+
self::Foo = h
|
1043
1001
|
def al(v)
|
1044
|
-
|
1045
|
-
end
|
1046
|
-
def @dataset.fetch_rows(sql)
|
1047
|
-
yield({:id=>20})
|
1002
|
+
model::Foo << v.pk
|
1048
1003
|
end
|
1004
|
+
@dataset._fetch = {:id=>20}
|
1049
1005
|
end
|
1050
1006
|
p = @c2.load(:id=>10)
|
1051
1007
|
parent = p.parent
|
@@ -1083,15 +1039,15 @@ describe Sequel::Model, "one_to_one" do
|
|
1083
1039
|
h = []
|
1084
1040
|
@c2.one_to_one :parent, :class => @c2, :before_set=>:bs, :after_set=>:as
|
1085
1041
|
@c2.class_eval do
|
1086
|
-
|
1042
|
+
self::Foo = h
|
1087
1043
|
def []=(a, v)
|
1088
|
-
a == :node_id ? (
|
1044
|
+
a == :node_id ? (model::Foo << 5) : super
|
1089
1045
|
end
|
1090
1046
|
def bs(x)
|
1091
|
-
|
1047
|
+
model::Foo << x.pk
|
1092
1048
|
end
|
1093
1049
|
def as(x)
|
1094
|
-
|
1050
|
+
model::Foo << x.pk * 2
|
1095
1051
|
end
|
1096
1052
|
end
|
1097
1053
|
p.parent = c
|
@@ -1107,16 +1063,9 @@ end
|
|
1107
1063
|
|
1108
1064
|
describe Sequel::Model, "one_to_many" do
|
1109
1065
|
before do
|
1110
|
-
MODEL_DB.reset
|
1111
|
-
|
1112
1066
|
@c1 = Class.new(Sequel::Model(:attributes)) do
|
1113
|
-
def _refresh(ds); end
|
1114
1067
|
unrestrict_primary_key
|
1115
1068
|
columns :id, :node_id, :y, :z
|
1116
|
-
|
1117
|
-
def self.[](id)
|
1118
|
-
load(id.is_a?(Array) ? {:id => id[0], :z => id[1]} : {:id => id})
|
1119
|
-
end
|
1120
1069
|
end
|
1121
1070
|
|
1122
1071
|
@c2 = Class.new(Sequel::Model(:nodes)) do
|
@@ -1129,66 +1078,50 @@ describe Sequel::Model, "one_to_many" do
|
|
1129
1078
|
columns :id, :x
|
1130
1079
|
end
|
1131
1080
|
@dataset = @c2.dataset
|
1132
|
-
|
1133
|
-
@
|
1134
|
-
|
1135
|
-
def fetch_rows(sql)
|
1136
|
-
@db << sql
|
1137
|
-
yield Hash.new
|
1138
|
-
end
|
1139
|
-
})
|
1140
|
-
|
1141
|
-
@c1.dataset.extend(Module.new {
|
1142
|
-
def empty?; opts.has_key?(:empty) ? (super; true) : false; end
|
1143
|
-
def fetch_rows(sql)
|
1144
|
-
@db << sql
|
1145
|
-
yield Hash.new
|
1146
|
-
end
|
1147
|
-
})
|
1081
|
+
@dataset._fetch = {}
|
1082
|
+
@c1.dataset._fetch = proc{|sql| sql =~ /SELECT 1/ ? {:a=>1} : {}}
|
1083
|
+
MODEL_DB.reset
|
1148
1084
|
end
|
1149
1085
|
|
1150
1086
|
it "should use implicit key if omitted" do
|
1151
1087
|
@c2.one_to_many :attributes, :class => @c1
|
1152
|
-
|
1153
|
-
n = @c2.new(:id => 1234)
|
1154
|
-
a = n.attributes_dataset
|
1155
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
1156
|
-
a.sql.should == 'SELECT * FROM attributes WHERE (attributes.node_id = 1234)'
|
1088
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE (attributes.node_id = 1234)'
|
1157
1089
|
end
|
1158
1090
|
|
1159
1091
|
it "should use implicit class if omitted" do
|
1160
|
-
|
1092
|
+
begin
|
1093
|
+
class ::HistoricalValue < Sequel::Model; end
|
1094
|
+
@c2.one_to_many :historical_values
|
1095
|
+
|
1096
|
+
v = @c2.new(:id => 1234).historical_values_dataset
|
1097
|
+
v.should be_a_kind_of(Sequel::Dataset)
|
1098
|
+
v.sql.should == 'SELECT * FROM historical_values WHERE (historical_values.node_id = 1234)'
|
1099
|
+
v.model.should == HistoricalValue
|
1100
|
+
ensure
|
1101
|
+
Object.send(:remove_const, :HistoricalValue)
|
1161
1102
|
end
|
1162
|
-
|
1163
|
-
@c2.one_to_many :historical_values
|
1164
|
-
|
1165
|
-
n = @c2.new(:id => 1234)
|
1166
|
-
v = n.historical_values_dataset
|
1167
|
-
v.should be_a_kind_of(Sequel::Dataset)
|
1168
|
-
v.sql.should == 'SELECT * FROM historical_values WHERE (historical_values.node_id = 1234)'
|
1169
|
-
v.model.should == HistoricalValue
|
1170
1103
|
end
|
1171
1104
|
|
1172
1105
|
it "should use class inside a module if given as a string" do
|
1173
|
-
|
1174
|
-
|
1106
|
+
begin
|
1107
|
+
module ::Historical
|
1108
|
+
class Value < Sequel::Model; end
|
1175
1109
|
end
|
1110
|
+
@c2.one_to_many :historical_values, :class=>'Historical::Value'
|
1111
|
+
|
1112
|
+
v = @c2.new(:id => 1234).historical_values_dataset
|
1113
|
+
v.should be_a_kind_of(Sequel::Dataset)
|
1114
|
+
v.sql.should == 'SELECT * FROM values WHERE (values.node_id = 1234)'
|
1115
|
+
v.model.should == Historical::Value
|
1116
|
+
ensure
|
1117
|
+
Object.send(:remove_const, :Historical)
|
1176
1118
|
end
|
1177
|
-
|
1178
|
-
@c2.one_to_many :historical_values, :class=>'Historical::Value'
|
1179
|
-
|
1180
|
-
n = @c2.new(:id => 1234)
|
1181
|
-
v = n.historical_values_dataset
|
1182
|
-
v.should be_a_kind_of(Sequel::Dataset)
|
1183
|
-
v.sql.should == 'SELECT * FROM values WHERE (values.node_id = 1234)'
|
1184
|
-
v.model.should == Historical::Value
|
1185
1119
|
end
|
1186
1120
|
|
1187
1121
|
it "should use a callback if given one as the argument" do
|
1188
1122
|
@c2.one_to_many :attributes, :class => @c1, :key => :nodeid
|
1189
1123
|
|
1190
|
-
d = @c2.
|
1191
|
-
MODEL_DB.reset
|
1124
|
+
d = @c2.load(:id => 1234)
|
1192
1125
|
d.associations[:attributes] = []
|
1193
1126
|
d.attributes(proc{|ds| ds.filter{name > 'M'}}).should_not == []
|
1194
1127
|
MODEL_DB.sqls.should == ["SELECT * FROM attributes WHERE ((attributes.nodeid = 1234) AND (name > 'M'))"]
|
@@ -1196,11 +1129,7 @@ describe Sequel::Model, "one_to_many" do
|
|
1196
1129
|
|
1197
1130
|
it "should use explicit key if given" do
|
1198
1131
|
@c2.one_to_many :attributes, :class => @c1, :key => :nodeid
|
1199
|
-
|
1200
|
-
n = @c2.new(:id => 1234)
|
1201
|
-
a = n.attributes_dataset
|
1202
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
1203
|
-
a.sql.should == 'SELECT * FROM attributes WHERE (attributes.nodeid = 1234)'
|
1132
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE (attributes.nodeid = 1234)'
|
1204
1133
|
end
|
1205
1134
|
|
1206
1135
|
it "should support_composite keys" do
|
@@ -1225,10 +1154,8 @@ describe Sequel::Model, "one_to_many" do
|
|
1225
1154
|
it "should define an add_ method that works on existing records" do
|
1226
1155
|
@c2.one_to_many :attributes, :class => @c1
|
1227
1156
|
|
1228
|
-
n = @c2.
|
1229
|
-
a = @c1.
|
1230
|
-
a.save
|
1231
|
-
MODEL_DB.reset
|
1157
|
+
n = @c2.load(:id => 1234)
|
1158
|
+
a = @c1.load(:id => 2345)
|
1232
1159
|
a.should == n.add_attribute(a)
|
1233
1160
|
a.values.should == {:node_id => 1234, :id => 2345}
|
1234
1161
|
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 1234 WHERE (id = 2345)']
|
@@ -1237,34 +1164,32 @@ describe Sequel::Model, "one_to_many" do
|
|
1237
1164
|
it "should define an add_ method that works on new records" do
|
1238
1165
|
@c2.one_to_many :attributes, :class => @c1
|
1239
1166
|
|
1240
|
-
n = @c2.
|
1167
|
+
n = @c2.load(:id => 1234)
|
1241
1168
|
a = @c1.new(:id => 234)
|
1242
|
-
|
1243
|
-
MODEL_DB.reset
|
1169
|
+
@c1.dataset._fetch = {:node_id => 1234, :id => 234}
|
1244
1170
|
a.should == n.add_attribute(a)
|
1245
|
-
MODEL_DB.sqls
|
1171
|
+
sqls = MODEL_DB.sqls
|
1172
|
+
sqls.shift.should =~ /INSERT INTO attributes \((node_)?id, (node_)?id\) VALUES \(1?234, 1?234\)/
|
1173
|
+
sqls.should == ["SELECT * FROM attributes WHERE (id = 234) LIMIT 1"]
|
1246
1174
|
a.values.should == {:node_id => 1234, :id => 234}
|
1247
1175
|
end
|
1248
1176
|
|
1249
1177
|
it "should define a remove_ method that works on existing records" do
|
1250
1178
|
@c2.one_to_many :attributes, :class => @c1
|
1251
1179
|
|
1252
|
-
n = @c2.
|
1253
|
-
a = @c1.
|
1254
|
-
a.save
|
1255
|
-
MODEL_DB.reset
|
1180
|
+
n = @c2.load(:id => 1234)
|
1181
|
+
a = @c1.load(:id => 2345, :node_id => 1234)
|
1256
1182
|
a.should == n.remove_attribute(a)
|
1257
1183
|
a.values.should == {:node_id => nil, :id => 2345}
|
1258
|
-
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = NULL WHERE (id = 2345)']
|
1184
|
+
MODEL_DB.sqls.should == ["SELECT 1 FROM attributes WHERE ((attributes.node_id = 1234) AND (id = 2345)) LIMIT 1", 'UPDATE attributes SET node_id = NULL WHERE (id = 2345)']
|
1259
1185
|
end
|
1260
1186
|
|
1261
1187
|
it "should have the remove_ method raise an error if the passed object is not already associated" do
|
1262
1188
|
@c2.one_to_many :attributes, :class => @c1
|
1263
|
-
@c1.dataset.opts[:empty] = true
|
1264
1189
|
|
1265
1190
|
n = @c2.new(:id => 1234)
|
1266
1191
|
a = @c1.load(:id => 2345, :node_id => 1234)
|
1267
|
-
|
1192
|
+
@c1.dataset._fetch = []
|
1268
1193
|
proc{n.remove_attribute(a)}.should raise_error(Sequel::Error)
|
1269
1194
|
MODEL_DB.sqls.should == ["SELECT 1 FROM attributes WHERE ((attributes.node_id = 1234) AND (id = 2345)) LIMIT 1"]
|
1270
1195
|
end
|
@@ -1273,16 +1198,19 @@ describe Sequel::Model, "one_to_many" do
|
|
1273
1198
|
@c2.one_to_many :attributes, :class => @c1
|
1274
1199
|
n = @c2.new(:id => 1234)
|
1275
1200
|
MODEL_DB.reset
|
1276
|
-
@c1.
|
1277
|
-
|
1201
|
+
@c1.dataset._fetch = {:node_id => 1234, :id => 234}
|
1202
|
+
n.add_attribute(:id => 234).should == @c1.load(:node_id => 1234, :id => 234)
|
1203
|
+
sqls = MODEL_DB.sqls
|
1204
|
+
sqls.shift.should =~ /INSERT INTO attributes \((node_)?id, (node_)?id\) VALUES \(1?234, 1?234\)/
|
1205
|
+
sqls.should == ["SELECT * FROM attributes WHERE (id = 234) LIMIT 1"]
|
1278
1206
|
end
|
1279
1207
|
|
1280
1208
|
it "should accept a primary key for the add_ method" do
|
1281
1209
|
@c2.one_to_many :attributes, :class => @c1
|
1282
1210
|
n = @c2.new(:id => 1234)
|
1283
|
-
|
1284
|
-
@c1.load(:node_id => 1234, :id => 234)
|
1285
|
-
MODEL_DB.sqls.
|
1211
|
+
@c1.dataset._fetch = {:id=>234, :node_id=>nil}
|
1212
|
+
n.add_attribute(234).should == @c1.load(:node_id => 1234, :id => 234)
|
1213
|
+
MODEL_DB.sqls.should == ["SELECT * FROM attributes WHERE id = 234", "UPDATE attributes SET node_id = 1234 WHERE (id = 234)"]
|
1286
1214
|
end
|
1287
1215
|
|
1288
1216
|
it "should raise an error in the add_ method if the passed associated object is not of the correct type" do
|
@@ -1293,13 +1221,8 @@ describe Sequel::Model, "one_to_many" do
|
|
1293
1221
|
it "should accept a primary key for the remove_ method and remove an existing record" do
|
1294
1222
|
@c2.one_to_many :attributes, :class => @c1
|
1295
1223
|
n = @c2.new(:id => 1234)
|
1296
|
-
|
1297
|
-
|
1298
|
-
db << sql
|
1299
|
-
yield({:id=>234, :node_id=>1234})
|
1300
|
-
end
|
1301
|
-
MODEL_DB.reset
|
1302
|
-
@c1.load(:node_id => nil, :id => 234).should == n.remove_attribute(234)
|
1224
|
+
@c1.dataset._fetch = {:id=>234, :node_id=>1234}
|
1225
|
+
n.remove_attribute(234).should == @c1.load(:node_id => nil, :id => 234)
|
1303
1226
|
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (attributes.id = 234)) LIMIT 1',
|
1304
1227
|
'UPDATE attributes SET node_id = NULL WHERE (id = 234)']
|
1305
1228
|
end
|
@@ -1313,10 +1236,8 @@ describe Sequel::Model, "one_to_many" do
|
|
1313
1236
|
@c2.one_to_many :attributes, :class => @c1, :primary_key=>:xxx
|
1314
1237
|
|
1315
1238
|
n = @c2.new(:id => 1234, :xxx=>5)
|
1316
|
-
a = @c1.
|
1317
|
-
a.
|
1318
|
-
MODEL_DB.reset
|
1319
|
-
a.should == n.add_attribute(a)
|
1239
|
+
a = @c1.load(:id => 2345)
|
1240
|
+
n.add_attribute(a).should == a
|
1320
1241
|
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 5 WHERE (id = 2345)']
|
1321
1242
|
end
|
1322
1243
|
|
@@ -1324,15 +1245,13 @@ describe Sequel::Model, "one_to_many" do
|
|
1324
1245
|
@c2.one_to_many :attributes, :class => @c1
|
1325
1246
|
|
1326
1247
|
n = @c2.new(:id => 1234)
|
1327
|
-
a = @c1.
|
1328
|
-
a.save
|
1329
|
-
MODEL_DB.reset
|
1248
|
+
a = @c1.load(:id => 2345)
|
1330
1249
|
n.associations[:attributes] = []
|
1331
1250
|
a.should == n.add_attribute(a)
|
1332
1251
|
a.should == n.add_attribute(a)
|
1333
1252
|
a.values.should == {:node_id => 1234, :id => 2345}
|
1334
|
-
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 1234 WHERE (id = 2345)'] * 2
|
1335
1253
|
n.attributes.should == [a]
|
1254
|
+
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 1234 WHERE (id = 2345)'] * 2
|
1336
1255
|
end
|
1337
1256
|
|
1338
1257
|
it "should have add_ method respect composite keys" do
|
@@ -1340,18 +1259,24 @@ describe Sequel::Model, "one_to_many" do
|
|
1340
1259
|
|
1341
1260
|
n = @c2.load(:id => 1234, :x=>5)
|
1342
1261
|
a = @c1.load(:id => 2345)
|
1343
|
-
a.should ==
|
1344
|
-
|
1262
|
+
n.add_attribute(a).should == a
|
1263
|
+
sqls = MODEL_DB.sqls
|
1264
|
+
sqls.shift.should =~ /UPDATE attributes SET (node_id = 1234|y = 5), (node_id = 1234|y = 5) WHERE \(id = 2345\)/
|
1265
|
+
sqls.should == []
|
1345
1266
|
end
|
1346
1267
|
|
1347
1268
|
it "should have add_ method accept a composite key" do
|
1348
1269
|
@c1.set_primary_key :id, :z
|
1349
1270
|
@c2.one_to_many :attributes, :class => @c1, :key =>[:node_id, :y], :primary_key=>[:id, :x]
|
1271
|
+
@c1.dataset._fetch = {:id => 2345, :z => 8, :node_id => 1234, :y=>5}
|
1350
1272
|
|
1351
1273
|
n = @c2.load(:id => 1234, :x=>5)
|
1352
1274
|
a = @c1.load(:id => 2345, :z => 8, :node_id => 1234, :y=>5)
|
1353
|
-
|
1354
|
-
|
1275
|
+
n.add_attribute([2345, 8]).should == a
|
1276
|
+
sqls = MODEL_DB.sqls
|
1277
|
+
sqls.shift.should =~ /SELECT \* FROM attributes WHERE \(\((id|z) = (2345|8)\) AND \((id|z) = (2345|8)\)\) LIMIT 1/
|
1278
|
+
sqls.shift.should =~ /UPDATE attributes SET (node_id|y) = (1234|5), (node_id|y) = (1234|5) WHERE \(\((id|z) = (2345|8)\) AND \((id|z) = (2345|8)\)\)/
|
1279
|
+
sqls.should == []
|
1355
1280
|
end
|
1356
1281
|
|
1357
1282
|
it "should have remove_ method respect composite keys" do
|
@@ -1359,24 +1284,22 @@ describe Sequel::Model, "one_to_many" do
|
|
1359
1284
|
|
1360
1285
|
n = @c2.load(:id => 1234, :x=>5)
|
1361
1286
|
a = @c1.load(:id => 2345, :node_id=>1234, :y=>5)
|
1362
|
-
a.should ==
|
1363
|
-
|
1287
|
+
n.remove_attribute(a).should == a
|
1288
|
+
sqls = MODEL_DB.sqls
|
1289
|
+
sqls.pop.should =~ /UPDATE attributes SET (node_id|y) = NULL, (node_id|y) = NULL WHERE \(id = 2345\)/
|
1290
|
+
sqls.should == ["SELECT 1 FROM attributes WHERE ((attributes.node_id = 1234) AND (attributes.y = 5) AND (id = 2345)) LIMIT 1"]
|
1364
1291
|
end
|
1365
1292
|
|
1366
1293
|
it "should accept a array of composite primary key values for the remove_ method and remove an existing record" do
|
1367
1294
|
@c1.set_primary_key :id, :y
|
1368
1295
|
@c2.one_to_many :attributes, :class => @c1, :key=>:node_id, :primary_key=>:id
|
1369
1296
|
n = @c2.new(:id => 123)
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
@c1.load(:node_id => nil, :y => 5, :id => 234).should == n.remove_attribute([234, 5])
|
1377
|
-
MODEL_DB.sqls.length.should == 2
|
1378
|
-
MODEL_DB.sqls.first.should =~ /SELECT \* FROM attributes WHERE \(\(attributes.node_id = 123\) AND \(attributes\.(id|y) = (234|5)\) AND \(attributes\.(id|y) = (234|5)\)\) LIMIT 1/
|
1379
|
-
MODEL_DB.sqls.last.should =~ /UPDATE attributes SET node_id = NULL WHERE \(\((id|y) = (234|5)\) AND \((id|y) = (234|5)\)\)/
|
1297
|
+
@c1.dataset._fetch = {:id=>234, :node_id=>123, :y=>5}
|
1298
|
+
n.remove_attribute([234, 5]).should == @c1.load(:node_id => nil, :y => 5, :id => 234)
|
1299
|
+
sqls = MODEL_DB.sqls
|
1300
|
+
sqls.length.should == 2
|
1301
|
+
sqls.first.should =~ /SELECT \* FROM attributes WHERE \(\(attributes.node_id = 123\) AND \(attributes\.(id|y) = (234|5)\) AND \(attributes\.(id|y) = (234|5)\)\) LIMIT 1/
|
1302
|
+
sqls.last.should =~ /UPDATE attributes SET node_id = NULL WHERE \(\((id|y) = (234|5)\) AND \((id|y) = (234|5)\)\)/
|
1380
1303
|
end
|
1381
1304
|
|
1382
1305
|
it "should raise an error in add_ and remove_ if the passed object returns false to save (is not valid)" do
|
@@ -1409,81 +1332,48 @@ describe Sequel::Model, "one_to_many" do
|
|
1409
1332
|
|
1410
1333
|
it "should use :primary_key option if given" do
|
1411
1334
|
@c1.one_to_many :nodes, :class => @c2, :primary_key => :node_id, :key=>:id
|
1412
|
-
|
1413
|
-
n.nodes_dataset.sql.should == "SELECT * FROM nodes WHERE (nodes.id = 4321)"
|
1335
|
+
@c1.load(:id => 1234, :node_id=>4321).nodes_dataset.sql.should == "SELECT * FROM nodes WHERE (nodes.id = 4321)"
|
1414
1336
|
end
|
1415
1337
|
|
1416
1338
|
it "should support a select option" do
|
1417
1339
|
@c2.one_to_many :attributes, :class => @c1, :select => [:id, :name]
|
1418
|
-
|
1419
|
-
n = @c2.new(:id => 1234)
|
1420
|
-
n.attributes_dataset.sql.should == "SELECT id, name FROM attributes WHERE (attributes.node_id = 1234)"
|
1340
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == "SELECT id, name FROM attributes WHERE (attributes.node_id = 1234)"
|
1421
1341
|
end
|
1422
1342
|
|
1423
1343
|
it "should support a conditions option" do
|
1424
1344
|
@c2.one_to_many :attributes, :class => @c1, :conditions => {:a=>32}
|
1425
|
-
|
1426
|
-
n.attributes_dataset.sql.should == "SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (a = 32))"
|
1345
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == "SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (a = 32))"
|
1427
1346
|
@c2.one_to_many :attributes, :class => @c1, :conditions => ~:a
|
1428
|
-
|
1429
|
-
n.attributes_dataset.sql.should == "SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND NOT a)"
|
1347
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == "SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND NOT a)"
|
1430
1348
|
end
|
1431
1349
|
|
1432
1350
|
it "should support an order option" do
|
1433
1351
|
@c2.one_to_many :attributes, :class => @c1, :order => :kind
|
1434
|
-
|
1435
|
-
n = @c2.new(:id => 1234)
|
1436
|
-
n.attributes_dataset.sql.should == "SELECT * FROM attributes WHERE (attributes.node_id = 1234) ORDER BY kind"
|
1352
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == "SELECT * FROM attributes WHERE (attributes.node_id = 1234) ORDER BY kind"
|
1437
1353
|
end
|
1438
1354
|
|
1439
1355
|
it "should support an array for the order option" do
|
1440
1356
|
@c2.one_to_many :attributes, :class => @c1, :order => [:kind1, :kind2]
|
1441
|
-
|
1442
|
-
n = @c2.new(:id => 1234)
|
1443
|
-
n.attributes_dataset.sql.should == "SELECT * FROM attributes WHERE (attributes.node_id = 1234) ORDER BY kind1, kind2"
|
1357
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == "SELECT * FROM attributes WHERE (attributes.node_id = 1234) ORDER BY kind1, kind2"
|
1444
1358
|
end
|
1445
1359
|
|
1446
1360
|
it "should return array with all members of the association" do
|
1447
1361
|
@c2.one_to_many :attributes, :class => @c1
|
1448
|
-
|
1449
|
-
n = @c2.new(:id => 1234)
|
1450
|
-
atts = n.attributes
|
1451
|
-
atts.should be_a_kind_of(Array)
|
1452
|
-
atts.size.should == 1
|
1453
|
-
atts.first.should be_a_kind_of(@c1)
|
1454
|
-
atts.first.values.should == {}
|
1455
|
-
|
1456
|
-
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE (attributes.node_id = 1234)']
|
1362
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE (attributes.node_id = 1234)'
|
1457
1363
|
end
|
1458
1364
|
|
1459
1365
|
it "should accept a block" do
|
1460
1366
|
@c2.one_to_many :attributes, :class => @c1 do |ds|
|
1461
1367
|
ds.filter(:xxx => @xxx)
|
1462
1368
|
end
|
1463
|
-
|
1464
|
-
n = @c2.new(:id => 1234)
|
1465
|
-
atts = n.attributes
|
1466
|
-
atts.should be_a_kind_of(Array)
|
1467
|
-
atts.size.should == 1
|
1468
|
-
atts.first.should be_a_kind_of(@c1)
|
1469
|
-
atts.first.values.should == {}
|
1470
|
-
|
1471
|
-
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (xxx IS NULL))']
|
1369
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (xxx IS NULL))'
|
1472
1370
|
end
|
1473
1371
|
|
1474
1372
|
it "should support :order option with block" do
|
1475
1373
|
@c2.one_to_many :attributes, :class => @c1, :order => :kind do |ds|
|
1476
1374
|
ds.filter(:xxx => @xxx)
|
1477
1375
|
end
|
1478
|
-
|
1479
|
-
n = @c2.new(:id => 1234)
|
1480
|
-
atts = n.attributes
|
1481
|
-
atts.should be_a_kind_of(Array)
|
1482
|
-
atts.size.should == 1
|
1483
|
-
atts.first.should be_a_kind_of(@c1)
|
1484
|
-
atts.first.values.should == {}
|
1485
|
-
|
1486
|
-
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (xxx IS NULL)) ORDER BY kind']
|
1376
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (xxx IS NULL)) ORDER BY kind'
|
1487
1377
|
end
|
1488
1378
|
|
1489
1379
|
it "should have the block argument affect the _dataset method" do
|
@@ -1495,18 +1385,11 @@ describe Sequel::Model, "one_to_many" do
|
|
1495
1385
|
|
1496
1386
|
it "should support a :dataset option that is used instead of the default" do
|
1497
1387
|
c1 = @c1
|
1498
|
-
@c2.one_to_many :all_other_attributes, :class => @c1, :dataset=>proc{c1.
|
1388
|
+
@c2.one_to_many :all_other_attributes, :class => @c1, :dataset=>proc{c1.exclude(:nodeid=>pk)}, :order=>:a, :limit=>10 do |ds|
|
1499
1389
|
ds.filter(:xxx => 5)
|
1500
1390
|
end
|
1501
|
-
|
1502
1391
|
@c2.new(:id => 1234).all_other_attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE ((nodeid != 1234) AND (xxx = 5)) ORDER BY a LIMIT 10'
|
1503
|
-
|
1504
|
-
atts = n.all_other_attributes
|
1505
|
-
atts.should be_a_kind_of(Array)
|
1506
|
-
atts.size.should == 1
|
1507
|
-
atts.first.should be_a_kind_of(@c1)
|
1508
|
-
atts.first.values.should == {}
|
1509
|
-
|
1392
|
+
@c2.new(:id => 1234).all_other_attributes.should == [@c1.load({})]
|
1510
1393
|
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE ((nodeid != 1234) AND (xxx = 5)) ORDER BY a LIMIT 10']
|
1511
1394
|
end
|
1512
1395
|
|
@@ -1524,9 +1407,7 @@ describe Sequel::Model, "one_to_many" do
|
|
1524
1407
|
|
1525
1408
|
it "should set cached instance variable when accessed" do
|
1526
1409
|
@c2.one_to_many :attributes, :class => @c1
|
1527
|
-
|
1528
1410
|
n = @c2.new(:id => 1234)
|
1529
|
-
MODEL_DB.reset
|
1530
1411
|
n.associations.include?(:attributes).should == false
|
1531
1412
|
atts = n.attributes
|
1532
1413
|
atts.should == n.associations[:attributes]
|
@@ -1535,9 +1416,7 @@ describe Sequel::Model, "one_to_many" do
|
|
1535
1416
|
|
1536
1417
|
it "should use cached instance variable if available" do
|
1537
1418
|
@c2.one_to_many :attributes, :class => @c1
|
1538
|
-
|
1539
1419
|
n = @c2.new(:id => 1234)
|
1540
|
-
MODEL_DB.reset
|
1541
1420
|
n.associations[:attributes] = 42
|
1542
1421
|
n.attributes.should == 42
|
1543
1422
|
MODEL_DB.sqls.should == []
|
@@ -1545,9 +1424,7 @@ describe Sequel::Model, "one_to_many" do
|
|
1545
1424
|
|
1546
1425
|
it "should not use cached instance variable if asked to reload" do
|
1547
1426
|
@c2.one_to_many :attributes, :class => @c1
|
1548
|
-
|
1549
1427
|
n = @c2.new(:id => 1234)
|
1550
|
-
MODEL_DB.reset
|
1551
1428
|
n.associations[:attributes] = 42
|
1552
1429
|
n.attributes(true).should_not == 42
|
1553
1430
|
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE (attributes.node_id = 1234)']
|
@@ -1555,10 +1432,8 @@ describe Sequel::Model, "one_to_many" do
|
|
1555
1432
|
|
1556
1433
|
it "should add item to cached instance variable if it exists when calling add_" do
|
1557
1434
|
@c2.one_to_many :attributes, :class => @c1
|
1558
|
-
|
1559
1435
|
n = @c2.new(:id => 1234)
|
1560
|
-
att = @c1.
|
1561
|
-
MODEL_DB.reset
|
1436
|
+
att = @c1.load(:id => 345)
|
1562
1437
|
a = []
|
1563
1438
|
n.associations[:attributes] = a
|
1564
1439
|
n.add_attribute(att)
|
@@ -1580,7 +1455,6 @@ describe Sequel::Model, "one_to_many" do
|
|
1580
1455
|
|
1581
1456
|
n = @c2.load(:id => 1234)
|
1582
1457
|
att = @c1.load(:id => 345)
|
1583
|
-
MODEL_DB.reset
|
1584
1458
|
a = [att]
|
1585
1459
|
n.associations[:attributes] = a
|
1586
1460
|
n.remove_attribute(att)
|
@@ -1632,13 +1506,9 @@ describe Sequel::Model, "one_to_many" do
|
|
1632
1506
|
n = @c2.new(:id => 1234)
|
1633
1507
|
atts = n.attributes
|
1634
1508
|
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE (attributes.node_id = 1234)']
|
1635
|
-
atts.should
|
1636
|
-
atts.
|
1637
|
-
|
1638
|
-
atts.first.values.should == {}
|
1639
|
-
atts.first.node.should == n
|
1640
|
-
|
1641
|
-
MODEL_DB.sqls.length.should == 1
|
1509
|
+
atts.should == [@c1.load({})]
|
1510
|
+
atts.map{|a| a.node}.should == [n]
|
1511
|
+
MODEL_DB.sqls.should == []
|
1642
1512
|
end
|
1643
1513
|
|
1644
1514
|
it "should use an explicit reciprocal instance variable if given" do
|
@@ -1647,19 +1517,15 @@ describe Sequel::Model, "one_to_many" do
|
|
1647
1517
|
n = @c2.new(:id => 1234)
|
1648
1518
|
atts = n.attributes
|
1649
1519
|
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE (attributes.node_id = 1234)']
|
1650
|
-
atts.should
|
1651
|
-
atts.
|
1652
|
-
|
1653
|
-
atts.first.values.should == {}
|
1654
|
-
atts.first.associations[:wxyz].should == n
|
1655
|
-
|
1656
|
-
MODEL_DB.sqls.length.should == 1
|
1520
|
+
atts.should == [@c1.load({})]
|
1521
|
+
atts.map{|a| a.associations[:wxyz]}.should == [n]
|
1522
|
+
MODEL_DB.sqls.should == []
|
1657
1523
|
end
|
1658
1524
|
|
1659
1525
|
it "should have an remove_all_ method that removes all associations" do
|
1660
1526
|
@c2.one_to_many :attributes, :class => @c1
|
1661
1527
|
@c2.new(:id => 1234).remove_all_attributes
|
1662
|
-
MODEL_DB.sqls.
|
1528
|
+
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = NULL WHERE (node_id = 1234)']
|
1663
1529
|
end
|
1664
1530
|
|
1665
1531
|
it "should have remove_all method respect association filters" do
|
@@ -1673,13 +1539,15 @@ describe Sequel::Model, "one_to_many" do
|
|
1673
1539
|
it "should have the remove_all_ method respect the :primary_key option" do
|
1674
1540
|
@c2.one_to_many :attributes, :class => @c1, :primary_key=>:xxx
|
1675
1541
|
@c2.new(:id => 1234, :xxx=>5).remove_all_attributes
|
1676
|
-
MODEL_DB.sqls.
|
1542
|
+
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = NULL WHERE (node_id = 5)']
|
1677
1543
|
end
|
1678
1544
|
|
1679
1545
|
it "should have the remove_all_ method respect composite keys" do
|
1680
1546
|
@c2.one_to_many :attributes, :class => @c1, :key=>[:node_id, :y], :primary_key=>[:id, :x]
|
1681
1547
|
@c2.new(:id => 1234, :x=>5).remove_all_attributes
|
1682
|
-
|
1548
|
+
sqls = MODEL_DB.sqls
|
1549
|
+
sqls.pop.should =~ /UPDATE attributes SET (node_id|y) = NULL, (node_id|y) = NULL WHERE \(\(node_id = 1234\) AND \(y = 5\)\)/
|
1550
|
+
sqls.should == []
|
1683
1551
|
end
|
1684
1552
|
|
1685
1553
|
it "remove_all should set the cached instance variable to []" do
|
@@ -1693,10 +1561,8 @@ describe Sequel::Model, "one_to_many" do
|
|
1693
1561
|
@c2.one_to_many :attributes, :class => @c1
|
1694
1562
|
attrib = @c1.new(:id=>3)
|
1695
1563
|
node = @c2.new(:id => 1234)
|
1696
|
-
|
1697
|
-
def d.fetch_rows(s); end
|
1564
|
+
@c1.dataset._fetch = [[], [{:id=>3, :node_id=>1234}]]
|
1698
1565
|
node.attributes.should == []
|
1699
|
-
def attrib.save(*); self end
|
1700
1566
|
node.add_attribute(attrib)
|
1701
1567
|
node.associations[:attributes].should == [attrib]
|
1702
1568
|
node.remove_all_attributes.should == [attrib]
|
@@ -1710,15 +1576,12 @@ describe Sequel::Model, "one_to_many" do
|
|
1710
1576
|
it "remove_all should remove the current item from all reciprocal instance varaibles if it cached instance variable exists" do
|
1711
1577
|
@c2.one_to_many :attributes, :class => @c1
|
1712
1578
|
@c1.many_to_one :node, :class => @c2
|
1713
|
-
|
1714
|
-
|
1715
|
-
d = @c2.dataset
|
1716
|
-
def d.fetch_rows(s); end
|
1579
|
+
@c2.dataset._fetch = []
|
1580
|
+
@c1.dataset._fetch = [[], [{:id=>3, :node_id=>1234}]]
|
1717
1581
|
attrib = @c1.new(:id=>3)
|
1718
|
-
node = @c2.
|
1582
|
+
node = @c2.load(:id => 1234)
|
1719
1583
|
node.attributes.should == []
|
1720
1584
|
attrib.node.should == nil
|
1721
|
-
def attrib.save(*); self end
|
1722
1585
|
node.add_attribute(attrib)
|
1723
1586
|
attrib.associations[:node].should == node
|
1724
1587
|
node.remove_all_attributes
|
@@ -1806,18 +1669,18 @@ describe Sequel::Model, "one_to_many" do
|
|
1806
1669
|
h = []
|
1807
1670
|
@c2.one_to_many :attributes, :class => @c1, :before_add=>[proc{|x,y| h << x.pk; h << -y.pk}, :blah], :after_add=>proc{h << 3}, :before_remove=>:blah, :after_remove=>[:blahr]
|
1808
1671
|
@c2.class_eval do
|
1809
|
-
|
1672
|
+
self::Foo = h
|
1810
1673
|
def _add_attribute(v)
|
1811
|
-
|
1674
|
+
model::Foo << 4
|
1812
1675
|
end
|
1813
1676
|
def _remove_attribute(v)
|
1814
|
-
|
1677
|
+
model::Foo << 5
|
1815
1678
|
end
|
1816
1679
|
def blah(x)
|
1817
|
-
|
1680
|
+
model::Foo << x.pk
|
1818
1681
|
end
|
1819
1682
|
def blahr(x)
|
1820
|
-
|
1683
|
+
model::Foo << 6
|
1821
1684
|
end
|
1822
1685
|
end
|
1823
1686
|
p = @c2.load(:id=>10)
|
@@ -1833,17 +1696,12 @@ describe Sequel::Model, "one_to_many" do
|
|
1833
1696
|
h = []
|
1834
1697
|
@c2.one_to_many :attributes, :class => @c1, :after_load=>[proc{|x,y| h << [x.pk, y.collect{|z|z.pk}]}, :al]
|
1835
1698
|
@c2.class_eval do
|
1836
|
-
|
1699
|
+
self::Foo = h
|
1837
1700
|
def al(v)
|
1838
|
-
v.each{|x|
|
1839
|
-
end
|
1840
|
-
end
|
1841
|
-
@c1.class_eval do
|
1842
|
-
def @dataset.fetch_rows(sql)
|
1843
|
-
yield({:id=>20})
|
1844
|
-
yield({:id=>30})
|
1701
|
+
v.each{|x| model::Foo << x.pk}
|
1845
1702
|
end
|
1846
1703
|
end
|
1704
|
+
@c1.dataset._fetch = [{:id=>20}, {:id=>30}]
|
1847
1705
|
p = @c2.load(:id=>10, :parent_id=>20)
|
1848
1706
|
attributes = p.attributes
|
1849
1707
|
h.should == [[10, [20, 30]], 20, 30]
|
@@ -1890,23 +1748,13 @@ describe Sequel::Model, "one_to_many" do
|
|
1890
1748
|
end
|
1891
1749
|
|
1892
1750
|
describe Sequel::Model, "many_to_many" do
|
1893
|
-
|
1894
1751
|
before do
|
1895
|
-
MODEL_DB.reset
|
1896
|
-
|
1897
1752
|
@c1 = Class.new(Sequel::Model(:attributes)) do
|
1898
1753
|
unrestrict_primary_key
|
1899
1754
|
attr_accessor :yyy
|
1900
1755
|
def self.name; 'Attribute'; end
|
1901
1756
|
def self.to_s; 'Attribute'; end
|
1902
1757
|
columns :id, :y
|
1903
|
-
def _refresh(ds)
|
1904
|
-
self
|
1905
|
-
end
|
1906
|
-
|
1907
|
-
def self.[](id)
|
1908
|
-
load(id.is_a?(Array) ? {:id => id[0], :y => id[1]} : {:id => id})
|
1909
|
-
end
|
1910
1758
|
end
|
1911
1759
|
|
1912
1760
|
@c2 = Class.new(Sequel::Model(:nodes)) do
|
@@ -1918,98 +1766,61 @@ describe Sequel::Model, "many_to_many" do
|
|
1918
1766
|
columns :id, :x
|
1919
1767
|
end
|
1920
1768
|
@dataset = @c2.dataset
|
1769
|
+
@c1.dataset.autoid = 1
|
1921
1770
|
|
1922
|
-
[@c1, @c2].each
|
1923
|
-
|
1924
|
-
def fetch_rows(sql)
|
1925
|
-
@db << sql
|
1926
|
-
yield Hash.new
|
1927
|
-
end
|
1928
|
-
})
|
1929
|
-
end
|
1771
|
+
[@c1, @c2].each{|c| c.dataset._fetch = {}}
|
1772
|
+
MODEL_DB.reset
|
1930
1773
|
end
|
1931
1774
|
|
1932
1775
|
it "should use implicit key values and join table if omitted" do
|
1933
1776
|
@c2.many_to_many :attributes, :class => @c1
|
1934
|
-
|
1935
|
-
n = @c2.new(:id => 1234)
|
1936
|
-
a = n.attributes_dataset
|
1937
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
1938
|
-
a.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))'
|
1777
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))'
|
1939
1778
|
end
|
1940
1779
|
|
1941
1780
|
it "should use implicit class if omitted" do
|
1942
|
-
|
1781
|
+
begin
|
1782
|
+
class ::Tag < Sequel::Model; end
|
1783
|
+
@c2.many_to_many :tags
|
1784
|
+
@c2.new(:id => 1234).tags_dataset.sql.should == 'SELECT tags.* FROM tags INNER JOIN nodes_tags ON ((nodes_tags.tag_id = tags.id) AND (nodes_tags.node_id = 1234))'
|
1785
|
+
ensure
|
1786
|
+
Object.send(:remove_const, :Tag)
|
1943
1787
|
end
|
1944
|
-
|
1945
|
-
@c2.many_to_many :tags
|
1946
|
-
|
1947
|
-
n = @c2.new(:id => 1234)
|
1948
|
-
a = n.tags_dataset
|
1949
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
1950
|
-
a.sql.should == 'SELECT tags.* FROM tags INNER JOIN nodes_tags ON ((nodes_tags.tag_id = tags.id) AND (nodes_tags.node_id = 1234))'
|
1951
1788
|
end
|
1952
1789
|
|
1953
1790
|
it "should use class inside module if given as a string" do
|
1954
|
-
|
1955
|
-
|
1791
|
+
begin
|
1792
|
+
module ::Historical
|
1793
|
+
class Tag < Sequel::Model; end
|
1956
1794
|
end
|
1795
|
+
@c2.many_to_many :tags, :class=>'::Historical::Tag'
|
1796
|
+
@c2.new(:id => 1234).tags_dataset.sql.should == 'SELECT tags.* FROM tags INNER JOIN nodes_tags ON ((nodes_tags.tag_id = tags.id) AND (nodes_tags.node_id = 1234))'
|
1797
|
+
ensure
|
1798
|
+
Object.send(:remove_const, :Historical)
|
1957
1799
|
end
|
1958
|
-
|
1959
|
-
@c2.many_to_many :tags, :class=>'::Historical::Tag'
|
1960
|
-
|
1961
|
-
n = @c2.new(:id => 1234)
|
1962
|
-
a = n.tags_dataset
|
1963
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
1964
|
-
a.sql.should == 'SELECT tags.* FROM tags INNER JOIN nodes_tags ON ((nodes_tags.tag_id = tags.id) AND (nodes_tags.node_id = 1234))'
|
1965
1800
|
end
|
1966
1801
|
|
1967
1802
|
it "should use explicit key values and join table if given" do
|
1968
1803
|
@c2.many_to_many :attributes, :class => @c1, :left_key => :nodeid, :right_key => :attributeid, :join_table => :attribute2node
|
1969
|
-
|
1970
|
-
n = @c2.new(:id => 1234)
|
1971
|
-
a = n.attributes_dataset
|
1972
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
1973
|
-
a.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attribute2node ON ((attribute2node.attributeid = attributes.id) AND (attribute2node.nodeid = 1234))'
|
1974
|
-
end
|
1975
|
-
|
1976
|
-
it "should handle an aliased join table when eager loading" do
|
1977
|
-
r = @c2.many_to_many(:attributes, :class => @c1, :join_table => :attribute2node___attributes_nodes)
|
1978
|
-
|
1979
|
-
a = @c2.eager_loading_dataset(r, @c2.dataset, [:id], nil)
|
1980
|
-
a.sql.should == 'SELECT id, attributes_nodes.node_id AS x_foreign_key_x FROM nodes'
|
1804
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attribute2node ON ((attribute2node.attributeid = attributes.id) AND (attribute2node.nodeid = 1234))'
|
1981
1805
|
end
|
1982
1806
|
|
1983
1807
|
it "should support a conditions option" do
|
1984
1808
|
@c2.many_to_many :attributes, :class => @c1, :conditions => {:a=>32}
|
1985
|
-
|
1986
|
-
|
1987
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
1988
|
-
a.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (a = 32)'
|
1809
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (a = 32)'
|
1810
|
+
|
1989
1811
|
@c2.many_to_many :attributes, :class => @c1, :conditions => ['a = ?', 32]
|
1990
|
-
|
1991
|
-
|
1992
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
1993
|
-
a.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (a = 32)'
|
1994
|
-
n.attributes.should == [@c1.load({})]
|
1812
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (a = 32)'
|
1813
|
+
@c2.new(:id => 1234).attributes.should == [@c1.load({})]
|
1995
1814
|
end
|
1996
1815
|
|
1997
1816
|
it "should support an order option" do
|
1998
1817
|
@c2.many_to_many :attributes, :class => @c1, :order => :blah
|
1999
|
-
|
2000
|
-
n = @c2.new(:id => 1234)
|
2001
|
-
a = n.attributes_dataset
|
2002
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
2003
|
-
a.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) ORDER BY blah'
|
1818
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) ORDER BY blah'
|
2004
1819
|
end
|
2005
1820
|
|
2006
1821
|
it "should support an array for the order option" do
|
2007
1822
|
@c2.many_to_many :attributes, :class => @c1, :order => [:blah1, :blah2]
|
2008
|
-
|
2009
|
-
n = @c2.new(:id => 1234)
|
2010
|
-
a = n.attributes_dataset
|
2011
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
2012
|
-
a.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) ORDER BY blah1, blah2'
|
1823
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) ORDER BY blah1, blah2'
|
2013
1824
|
end
|
2014
1825
|
|
2015
1826
|
it "should support :left_primary_key and :right_primary_key options" do
|
@@ -2044,19 +1855,13 @@ describe Sequel::Model, "many_to_many" do
|
|
2044
1855
|
it "should support a select option" do
|
2045
1856
|
@c2.many_to_many :attributes, :class => @c1, :select => :blah
|
2046
1857
|
|
2047
|
-
|
2048
|
-
a = n.attributes_dataset
|
2049
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
2050
|
-
a.sql.should == 'SELECT blah FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))'
|
1858
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT blah FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))'
|
2051
1859
|
end
|
2052
1860
|
|
2053
1861
|
it "should support an array for the select option" do
|
2054
1862
|
@c2.many_to_many :attributes, :class => @c1, :select => [:attributes.*, :attribute_nodes__blah2]
|
2055
1863
|
|
2056
|
-
|
2057
|
-
a = n.attributes_dataset
|
2058
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
2059
|
-
a.sql.should == 'SELECT attributes.*, attribute_nodes.blah2 FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))'
|
1864
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.*, attribute_nodes.blah2 FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))'
|
2060
1865
|
end
|
2061
1866
|
|
2062
1867
|
it "should accept a block" do
|
@@ -2066,11 +1871,7 @@ describe Sequel::Model, "many_to_many" do
|
|
2066
1871
|
|
2067
1872
|
n = @c2.new(:id => 1234)
|
2068
1873
|
n.xxx = 555
|
2069
|
-
|
2070
|
-
a.should be_a_kind_of(Array)
|
2071
|
-
a.size.should == 1
|
2072
|
-
a.first.should be_a_kind_of(@c1)
|
2073
|
-
MODEL_DB.sqls.first.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (xxx = 555)'
|
1874
|
+
n.attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (xxx = 555)'
|
2074
1875
|
end
|
2075
1876
|
|
2076
1877
|
it "should allow the :order option while accepting a block" do
|
@@ -2080,20 +1881,9 @@ describe Sequel::Model, "many_to_many" do
|
|
2080
1881
|
|
2081
1882
|
n = @c2.new(:id => 1234)
|
2082
1883
|
n.xxx = 555
|
2083
|
-
|
2084
|
-
a.should be_a_kind_of(Array)
|
2085
|
-
a.size.should == 1
|
2086
|
-
a.first.should be_a_kind_of(@c1)
|
2087
|
-
MODEL_DB.sqls.first.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (xxx = 555) ORDER BY blah1, blah2'
|
1884
|
+
n.attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (xxx = 555) ORDER BY blah1, blah2'
|
2088
1885
|
end
|
2089
1886
|
|
2090
|
-
it "should have the block argument affect the _dataset method" do
|
2091
|
-
@c2.many_to_many :attributes, :class => @c1 do |ds|
|
2092
|
-
ds.filter(:xxx => 456)
|
2093
|
-
end
|
2094
|
-
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (xxx = 456)'
|
2095
|
-
end
|
2096
|
-
|
2097
1887
|
it "should support a :dataset option that is used instead of the default" do
|
2098
1888
|
c1 = @c1
|
2099
1889
|
@c2.many_to_many :attributes, :class => @c1, :dataset=>proc{c1.join_table(:natural, :an).filter(:an__nodeid=>pk)}, :order=> :a, :limit=>10, :select=>nil do |ds|
|
@@ -2103,11 +1893,8 @@ describe Sequel::Model, "many_to_many" do
|
|
2103
1893
|
n = @c2.new(:id => 1234)
|
2104
1894
|
n.xxx = 555
|
2105
1895
|
n.attributes_dataset.sql.should == 'SELECT * FROM attributes NATURAL JOIN an WHERE ((an.nodeid = 1234) AND (xxx = 555)) ORDER BY a LIMIT 10'
|
2106
|
-
|
2107
|
-
|
2108
|
-
a.size.should == 1
|
2109
|
-
a.first.should be_a_kind_of(@c1)
|
2110
|
-
MODEL_DB.sqls.first.should == 'SELECT * FROM attributes NATURAL JOIN an WHERE ((an.nodeid = 1234) AND (xxx = 555)) ORDER BY a LIMIT 10'
|
1896
|
+
n.attributes.should == [@c1.load({})]
|
1897
|
+
MODEL_DB.sqls.should == ['SELECT * FROM attributes NATURAL JOIN an WHERE ((an.nodeid = 1234) AND (xxx = 555)) ORDER BY a LIMIT 10']
|
2111
1898
|
end
|
2112
1899
|
|
2113
1900
|
it "should support a :limit option" do
|
@@ -2122,15 +1909,32 @@ describe Sequel::Model, "many_to_many" do
|
|
2122
1909
|
@c2.new(:id => 1234).attributes_dataset.opts[:eager].should == {:attributes=>nil}
|
2123
1910
|
end
|
2124
1911
|
|
1912
|
+
it "should handle an aliased join table" do
|
1913
|
+
@c2.many_to_many :attributes, :class => @c1, :join_table => :attribute2node___attributes_nodes
|
1914
|
+
n = @c2.load(:id => 1234)
|
1915
|
+
a = @c1.load(:id => 2345)
|
1916
|
+
n.attributes_dataset.sql.should == "SELECT attributes.* FROM attributes INNER JOIN attribute2node AS attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))"
|
1917
|
+
a.should == n.add_attribute(a)
|
1918
|
+
a.should == n.remove_attribute(a)
|
1919
|
+
n.remove_all_attributes
|
1920
|
+
sqls = MODEL_DB.sqls
|
1921
|
+
['INSERT INTO attribute2node (node_id, attribute_id) VALUES (1234, 2345)',
|
1922
|
+
'INSERT INTO attribute2node (attribute_id, node_id) VALUES (2345, 1234)'].should(include(sqls.shift))
|
1923
|
+
["DELETE FROM attribute2node WHERE ((node_id = 1234) AND (attribute_id = 2345))",
|
1924
|
+
"DELETE FROM attribute2node WHERE ((attribute_id = 2345) AND (node_id = 1234))"].should(include(sqls.shift))
|
1925
|
+
sqls.should == ["DELETE FROM attribute2node WHERE (node_id = 1234)"]
|
1926
|
+
end
|
1927
|
+
|
2125
1928
|
it "should define an add_ method that works on existing records" do
|
2126
1929
|
@c2.many_to_many :attributes, :class => @c1
|
2127
1930
|
|
2128
1931
|
n = @c2.load(:id => 1234)
|
2129
1932
|
a = @c1.load(:id => 2345)
|
2130
|
-
a.should ==
|
1933
|
+
n.add_attribute(a).should == a
|
1934
|
+
sqls = MODEL_DB.sqls
|
2131
1935
|
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 2345)',
|
2132
|
-
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (2345, 1234)'
|
2133
|
-
|
1936
|
+
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (2345, 1234)'].should(include(sqls.shift))
|
1937
|
+
sqls.should == []
|
2134
1938
|
end
|
2135
1939
|
|
2136
1940
|
it "should define an add_ method that works with a primary key" do
|
@@ -2138,21 +1942,25 @@ describe Sequel::Model, "many_to_many" do
|
|
2138
1942
|
|
2139
1943
|
n = @c2.load(:id => 1234)
|
2140
1944
|
a = @c1.load(:id => 2345)
|
2141
|
-
|
1945
|
+
@c1.dataset._fetch = {:id=>2345}
|
1946
|
+
n.add_attribute(2345).should == a
|
1947
|
+
sqls = MODEL_DB.sqls
|
2142
1948
|
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 2345)',
|
2143
|
-
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (2345, 1234)'
|
2144
|
-
|
1949
|
+
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (2345, 1234)'].should(include(sqls.pop))
|
1950
|
+
sqls.should == ["SELECT * FROM attributes WHERE id = 2345"]
|
2145
1951
|
end
|
2146
1952
|
|
2147
1953
|
it "should allow passing a hash to the add_ method which creates a new record" do
|
2148
1954
|
@c2.many_to_many :attributes, :class => @c1
|
2149
1955
|
|
2150
1956
|
n = @c2.load(:id => 1234)
|
2151
|
-
@c1.
|
2152
|
-
|
1957
|
+
@c1.dataset._fetch = {:id=>1}
|
1958
|
+
n.add_attribute(:id => 1).should == @c1.load(:id => 1)
|
1959
|
+
sqls = MODEL_DB.sqls
|
2153
1960
|
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 1)',
|
2154
1961
|
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (1, 1234)'
|
2155
|
-
].should(include(
|
1962
|
+
].should(include(sqls.pop))
|
1963
|
+
sqls.should == ['INSERT INTO attributes (id) VALUES (1)', "SELECT * FROM attributes WHERE (id = 1) LIMIT 1"]
|
2156
1964
|
end
|
2157
1965
|
|
2158
1966
|
it "should define a remove_ method that works on existing records" do
|
@@ -2160,8 +1968,8 @@ describe Sequel::Model, "many_to_many" do
|
|
2160
1968
|
|
2161
1969
|
n = @c2.new(:id => 1234)
|
2162
1970
|
a = @c1.new(:id => 2345)
|
2163
|
-
a.should ==
|
2164
|
-
MODEL_DB.sqls.
|
1971
|
+
n.remove_attribute(a).should == a
|
1972
|
+
MODEL_DB.sqls.should == ['DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (attribute_id = 2345))']
|
2165
1973
|
end
|
2166
1974
|
|
2167
1975
|
it "should raise an error in the add_ method if the passed associated object is not of the correct type" do
|
@@ -2172,13 +1980,8 @@ describe Sequel::Model, "many_to_many" do
|
|
2172
1980
|
it "should accept a primary key for the remove_ method and remove an existing record" do
|
2173
1981
|
@c2.many_to_many :attributes, :class => @c1
|
2174
1982
|
n = @c2.new(:id => 1234)
|
2175
|
-
|
2176
|
-
|
2177
|
-
db << sql
|
2178
|
-
yield({:id=>234})
|
2179
|
-
end
|
2180
|
-
MODEL_DB.reset
|
2181
|
-
@c1.load(:id => 234).should == n.remove_attribute(234)
|
1983
|
+
@c1.dataset._fetch = {:id=>234}
|
1984
|
+
n.remove_attribute(234).should == @c1.load(:id => 234)
|
2182
1985
|
MODEL_DB.sqls.should == ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (attributes.id = 234) LIMIT 1",
|
2183
1986
|
"DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (attribute_id = 234))"]
|
2184
1987
|
end
|
@@ -2193,10 +1996,12 @@ describe Sequel::Model, "many_to_many" do
|
|
2193
1996
|
|
2194
1997
|
n = @c2.load(:id => 1234).set(:xxx=>5)
|
2195
1998
|
a = @c1.load(:id => 2345).set(:yyy=>8)
|
2196
|
-
a.should ==
|
1999
|
+
n.add_attribute(a).should == a
|
2000
|
+
sqls = MODEL_DB.sqls
|
2197
2001
|
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (5, 8)',
|
2198
2002
|
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (8, 5)'
|
2199
|
-
].should(include(
|
2003
|
+
].should(include(sqls.pop))
|
2004
|
+
sqls.should == []
|
2200
2005
|
end
|
2201
2006
|
|
2202
2007
|
it "should have add_ method not add the same object to the cached association array if the object is already in the array" do
|
@@ -2215,7 +2020,9 @@ describe Sequel::Model, "many_to_many" do
|
|
2215
2020
|
n = @c2.load(:id => 1234, :x=>5)
|
2216
2021
|
a = @c1.load(:id => 2345, :y=>8)
|
2217
2022
|
a.should == n.add_attribute(a)
|
2218
|
-
|
2023
|
+
sqls = MODEL_DB.sqls
|
2024
|
+
m = /INSERT INTO attributes_nodes \((\w+), (\w+), (\w+), (\w+)\) VALUES \((\d+), (\d+), (\d+), (\d+)\)/.match(sqls.pop)
|
2025
|
+
sqls.should == []
|
2219
2026
|
m.should_not == nil
|
2220
2027
|
map = {'l1'=>1234, 'l2'=>5, 'r1'=>2345, 'r2'=>8}
|
2221
2028
|
%w[l1 l2 r1 r2].each do |x|
|
@@ -2232,10 +2039,15 @@ describe Sequel::Model, "many_to_many" do
|
|
2232
2039
|
|
2233
2040
|
it "should have the add_ method respect composite keys" do
|
2234
2041
|
@c2.many_to_many :attributes, :class => @c1, :left_key=>[:l1, :l2], :right_key=>[:r1, :r2], :left_primary_key=>[:id, :x], :right_primary_key=>[:id, :y]
|
2042
|
+
@c1.set_primary_key [:id, :y]
|
2235
2043
|
n = @c2.load(:id => 1234, :x=>5)
|
2236
2044
|
a = @c1.load(:id => 2345, :y=>8)
|
2237
|
-
|
2238
|
-
|
2045
|
+
@c1.dataset._fetch = {:id => 2345, :y=>8}
|
2046
|
+
n.add_attribute([2345, 8]).should == a
|
2047
|
+
sqls = MODEL_DB.sqls
|
2048
|
+
sqls.shift.should =~ /SELECT \* FROM attributes WHERE \(\((id|y) = (8|2345)\) AND \((id|y) = (8|2345)\)\) LIMIT 1/
|
2049
|
+
sqls.pop.should =~ /INSERT INTO attributes_nodes \([lr][12], [lr][12], [lr][12], [lr][12]\) VALUES \((1234|5|2345|8), (1234|5|2345|8), (1234|5|2345|8), (1234|5|2345|8)\)/
|
2050
|
+
sqls.should == []
|
2239
2051
|
end
|
2240
2052
|
|
2241
2053
|
it "should have the remove_ method respect the :left_primary_key and :right_primary_key options" do
|
@@ -2243,8 +2055,8 @@ describe Sequel::Model, "many_to_many" do
|
|
2243
2055
|
|
2244
2056
|
n = @c2.new(:id => 1234, :xxx=>5)
|
2245
2057
|
a = @c1.new(:id => 2345, :yyy=>8)
|
2246
|
-
a.should ==
|
2247
|
-
MODEL_DB.sqls.
|
2058
|
+
n.remove_attribute(a).should == a
|
2059
|
+
MODEL_DB.sqls.should == ['DELETE FROM attributes_nodes WHERE ((node_id = 5) AND (attribute_id = 8))']
|
2248
2060
|
end
|
2249
2061
|
|
2250
2062
|
it "should have the remove_ method respect composite keys" do
|
@@ -2259,17 +2071,12 @@ describe Sequel::Model, "many_to_many" do
|
|
2259
2071
|
@c1.set_primary_key [:id, :y]
|
2260
2072
|
@c2.many_to_many :attributes, :class => @c1
|
2261
2073
|
n = @c2.new(:id => 1234)
|
2262
|
-
|
2263
|
-
def ds.fetch_rows(sql)
|
2264
|
-
db << sql
|
2265
|
-
yield({:id=>234, :y=>8})
|
2266
|
-
end
|
2267
|
-
MODEL_DB.reset
|
2074
|
+
@c1.dataset._fetch = {:id=>234, :y=>8}
|
2268
2075
|
@c1.load(:id => 234, :y=>8).should == n.remove_attribute([234, 8])
|
2076
|
+
sqls = MODEL_DB.sqls
|
2269
2077
|
["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE ((attributes.id = 234) AND (attributes.y = 8)) LIMIT 1",
|
2270
|
-
"SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE ((attributes.y = 8) AND (attributes.id = 234)) LIMIT 1"].should include(
|
2271
|
-
|
2272
|
-
MODEL_DB.sqls.length.should == 2
|
2078
|
+
"SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE ((attributes.y = 8) AND (attributes.id = 234)) LIMIT 1"].should include(sqls.shift)
|
2079
|
+
sqls.should == ["DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (attribute_id = 234))"]
|
2273
2080
|
end
|
2274
2081
|
|
2275
2082
|
it "should raise an error if the model object doesn't have a valid primary key" do
|
@@ -2287,6 +2094,7 @@ describe Sequel::Model, "many_to_many" do
|
|
2287
2094
|
n = @c1.new
|
2288
2095
|
a = @c2.load(:id=>123)
|
2289
2096
|
n.new?.should == true
|
2097
|
+
@c1.dataset._fetch = {:id=>1}
|
2290
2098
|
a.add_attribute(n)
|
2291
2099
|
n.new?.should == false
|
2292
2100
|
end
|
@@ -2313,6 +2121,7 @@ describe Sequel::Model, "many_to_many" do
|
|
2313
2121
|
n = @c1.new
|
2314
2122
|
a = @c2.load(:id=>123)
|
2315
2123
|
def n.validate() errors.add(:id, 'foo') end
|
2124
|
+
@c1.dataset._fetch = {:id=>1}
|
2316
2125
|
a.add_attribute(n)
|
2317
2126
|
n.new?.should == false
|
2318
2127
|
end
|
@@ -2327,31 +2136,23 @@ describe Sequel::Model, "many_to_many" do
|
|
2327
2136
|
it "should provide an array with all members of the association" do
|
2328
2137
|
@c2.many_to_many :attributes, :class => @c1
|
2329
2138
|
|
2330
|
-
|
2331
|
-
|
2332
|
-
atts.should be_a_kind_of(Array)
|
2333
|
-
atts.size.should == 1
|
2334
|
-
atts.first.should be_a_kind_of(@c1)
|
2335
|
-
|
2336
|
-
MODEL_DB.sqls.first.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))'
|
2139
|
+
@c2.new(:id => 1234).attributes.should == [@c1.load({})]
|
2140
|
+
MODEL_DB.sqls.should == ['SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))']
|
2337
2141
|
end
|
2338
2142
|
|
2339
2143
|
it "should set cached instance variable when accessed" do
|
2340
2144
|
@c2.many_to_many :attributes, :class => @c1
|
2341
2145
|
|
2342
2146
|
n = @c2.new(:id => 1234)
|
2343
|
-
MODEL_DB.reset
|
2344
2147
|
n.associations.include?(:attributes).should == false
|
2345
2148
|
atts = n.attributes
|
2346
2149
|
atts.should == n.associations[:attributes]
|
2347
|
-
MODEL_DB.sqls.length.should == 1
|
2348
2150
|
end
|
2349
2151
|
|
2350
2152
|
it "should use cached instance variable if available" do
|
2351
2153
|
@c2.many_to_many :attributes, :class => @c1
|
2352
2154
|
|
2353
2155
|
n = @c2.new(:id => 1234)
|
2354
|
-
MODEL_DB.reset
|
2355
2156
|
n.associations[:attributes] = 42
|
2356
2157
|
n.attributes.should == 42
|
2357
2158
|
MODEL_DB.sqls.should == []
|
@@ -2361,18 +2162,16 @@ describe Sequel::Model, "many_to_many" do
|
|
2361
2162
|
@c2.many_to_many :attributes, :class => @c1
|
2362
2163
|
|
2363
2164
|
n = @c2.new(:id => 1234)
|
2364
|
-
MODEL_DB.reset
|
2365
2165
|
n.associations[:attributes] = 42
|
2366
2166
|
n.attributes(true).should_not == 42
|
2367
|
-
MODEL_DB.sqls.
|
2167
|
+
MODEL_DB.sqls.should == ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))"]
|
2368
2168
|
end
|
2369
2169
|
|
2370
2170
|
it "should add item to cached instance variable if it exists when calling add_" do
|
2371
2171
|
@c2.many_to_many :attributes, :class => @c1
|
2372
2172
|
|
2373
2173
|
n = @c2.new(:id => 1234)
|
2374
|
-
att = @c1.
|
2375
|
-
MODEL_DB.reset
|
2174
|
+
att = @c1.load(:id => 345)
|
2376
2175
|
a = []
|
2377
2176
|
n.associations[:attributes] = a
|
2378
2177
|
n.add_attribute(att)
|
@@ -2384,7 +2183,7 @@ describe Sequel::Model, "many_to_many" do
|
|
2384
2183
|
@c1.many_to_many :nodes, :class => @c2
|
2385
2184
|
|
2386
2185
|
n = @c2.new(:id => 1234)
|
2387
|
-
att = @c1.
|
2186
|
+
att = @c1.load(:id => 345)
|
2388
2187
|
att.associations[:nodes] = []
|
2389
2188
|
n.add_attribute(att)
|
2390
2189
|
att.nodes.should == [n]
|
@@ -2394,8 +2193,7 @@ describe Sequel::Model, "many_to_many" do
|
|
2394
2193
|
@c2.many_to_many :attributes, :class => @c1
|
2395
2194
|
|
2396
2195
|
n = @c2.new(:id => 1234)
|
2397
|
-
att = @c1.
|
2398
|
-
MODEL_DB.reset
|
2196
|
+
att = @c1.load(:id => 345)
|
2399
2197
|
a = [att]
|
2400
2198
|
n.associations[:attributes] = a
|
2401
2199
|
n.remove_attribute(att)
|
@@ -2442,13 +2240,13 @@ describe Sequel::Model, "many_to_many" do
|
|
2442
2240
|
it "should have an remove_all_ method that removes all associations" do
|
2443
2241
|
@c2.many_to_many :attributes, :class => @c1
|
2444
2242
|
@c2.new(:id => 1234).remove_all_attributes
|
2445
|
-
MODEL_DB.sqls.
|
2243
|
+
MODEL_DB.sqls.should == ['DELETE FROM attributes_nodes WHERE (node_id = 1234)']
|
2446
2244
|
end
|
2447
2245
|
|
2448
2246
|
it "should have the remove_all_ method respect the :left_primary_key option" do
|
2449
2247
|
@c2.many_to_many :attributes, :class => @c1, :left_primary_key=>:xxx
|
2450
2248
|
@c2.new(:id => 1234, :xxx=>5).remove_all_attributes
|
2451
|
-
MODEL_DB.sqls.
|
2249
|
+
MODEL_DB.sqls.should == ['DELETE FROM attributes_nodes WHERE (node_id = 5)']
|
2452
2250
|
end
|
2453
2251
|
|
2454
2252
|
it "should have the remove_all_ method respect composite keys" do
|
@@ -2466,10 +2264,9 @@ describe Sequel::Model, "many_to_many" do
|
|
2466
2264
|
|
2467
2265
|
it "remove_all should return the array of previously associated items if the cached instance variable exists" do
|
2468
2266
|
@c2.many_to_many :attributes, :class => @c1
|
2469
|
-
attrib = @c1.
|
2470
|
-
node = @c2.
|
2471
|
-
|
2472
|
-
def d.fetch_rows(s); end
|
2267
|
+
attrib = @c1.load(:id=>3)
|
2268
|
+
node = @c2.load(:id => 1234)
|
2269
|
+
@c1.dataset._fetch = []
|
2473
2270
|
node.attributes.should == []
|
2474
2271
|
node.add_attribute(attrib)
|
2475
2272
|
node.associations[:attributes].should == [attrib]
|
@@ -2484,11 +2281,9 @@ describe Sequel::Model, "many_to_many" do
|
|
2484
2281
|
it "remove_all should remove the current item from all reciprocal instance varaibles if it cached instance variable exists" do
|
2485
2282
|
@c2.many_to_many :attributes, :class => @c1
|
2486
2283
|
@c1.many_to_many :nodes, :class => @c2
|
2487
|
-
|
2488
|
-
|
2489
|
-
|
2490
|
-
def d.fetch_rows(s); end
|
2491
|
-
attrib = @c1.new(:id=>3)
|
2284
|
+
@c1.dataset._fetch = []
|
2285
|
+
@c2.dataset._fetch = []
|
2286
|
+
attrib = @c1.load(:id=>3)
|
2492
2287
|
node = @c2.new(:id => 1234)
|
2493
2288
|
node.attributes.should == []
|
2494
2289
|
attrib.nodes.should == []
|
@@ -2504,8 +2299,9 @@ describe Sequel::Model, "many_to_many" do
|
|
2504
2299
|
o.add_attribute(@c1.load(:id=>44))
|
2505
2300
|
o.remove_attribute(@c1.load(:id=>45))
|
2506
2301
|
o.remove_all_attributes
|
2507
|
-
MODEL_DB.sqls
|
2508
|
-
|
2302
|
+
sqls = MODEL_DB.sqls
|
2303
|
+
sqls.shift =~ /INSERT INTO attributes_nodes \((node_id|attribute_id|x), (node_id|attribute_id|x), (node_id|attribute_id|x)\) VALUES \((1234|123|44), (1234|123|44), (1234|123|44)\)/
|
2304
|
+
sqls.should == ["DELETE FROM attributes_nodes WHERE ((x = 123) AND (node_id = 1234) AND (attribute_id = 45))",
|
2509
2305
|
"DELETE FROM attributes_nodes WHERE ((x = 123) AND (node_id = 1234))"]
|
2510
2306
|
end
|
2511
2307
|
|
@@ -2588,18 +2384,18 @@ describe Sequel::Model, "many_to_many" do
|
|
2588
2384
|
h = []
|
2589
2385
|
@c2.many_to_many :attributes, :class => @c1, :before_add=>[proc{|x,y| h << x.pk; h << -y.pk}, :blah], :after_add=>proc{h << 3}, :before_remove=>:blah, :after_remove=>[:blahr]
|
2590
2386
|
@c2.class_eval do
|
2591
|
-
|
2387
|
+
self::Foo = h
|
2592
2388
|
def _add_attribute(v)
|
2593
|
-
|
2389
|
+
model::Foo << 4
|
2594
2390
|
end
|
2595
2391
|
def _remove_attribute(v)
|
2596
|
-
|
2392
|
+
model::Foo << 5
|
2597
2393
|
end
|
2598
2394
|
def blah(x)
|
2599
|
-
|
2395
|
+
model::Foo << x.pk
|
2600
2396
|
end
|
2601
2397
|
def blahr(x)
|
2602
|
-
|
2398
|
+
model::Foo << 6
|
2603
2399
|
end
|
2604
2400
|
end
|
2605
2401
|
p = @c2.load(:id=>10)
|
@@ -2615,17 +2411,12 @@ describe Sequel::Model, "many_to_many" do
|
|
2615
2411
|
h = []
|
2616
2412
|
@c2.many_to_many :attributes, :class => @c1, :after_load=>[proc{|x,y| h << [x.pk, y.collect{|z|z.pk}]}, :al]
|
2617
2413
|
@c2.class_eval do
|
2618
|
-
|
2414
|
+
self::Foo = h
|
2619
2415
|
def al(v)
|
2620
|
-
v.each{|x|
|
2621
|
-
end
|
2622
|
-
end
|
2623
|
-
@c1.class_eval do
|
2624
|
-
def @dataset.fetch_rows(sql)
|
2625
|
-
yield({:id=>20})
|
2626
|
-
yield({:id=>30})
|
2416
|
+
v.each{|x| model::Foo << x.pk}
|
2627
2417
|
end
|
2628
2418
|
end
|
2419
|
+
@c1.dataset._fetch = [{:id=>20}, {:id=>30}]
|
2629
2420
|
p = @c2.load(:id=>10, :parent_id=>20)
|
2630
2421
|
attributes = p.attributes
|
2631
2422
|
h.should == [[10, [20, 30]], 20, 30]
|
@@ -2668,14 +2459,7 @@ describe Sequel::Model, "many_to_many" do
|
|
2668
2459
|
|
2669
2460
|
it "should support a :uniq option that removes duplicates from the association" do
|
2670
2461
|
@c2.many_to_many :attributes, :class => @c1, :uniq=>true
|
2671
|
-
@c1.
|
2672
|
-
def @dataset.fetch_rows(sql)
|
2673
|
-
yield({:id=>20})
|
2674
|
-
yield({:id=>30})
|
2675
|
-
yield({:id=>20})
|
2676
|
-
yield({:id=>30})
|
2677
|
-
end
|
2678
|
-
end
|
2462
|
+
@c1.dataset._fetch = [{:id=>20}, {:id=>30}, {:id=>20}, {:id=>30}]
|
2679
2463
|
@c2.load(:id=>10, :parent_id=>20).attributes.should == [@c1.load(:id=>20), @c1.load(:id=>30)]
|
2680
2464
|
end
|
2681
2465
|
|
@@ -2696,80 +2480,13 @@ describe Sequel::Model, "many_to_many" do
|
|
2696
2480
|
@c2.many_to_many :attributes, :class => @c1 do |ds|
|
2697
2481
|
ds.filter(:join_table_att=>3)
|
2698
2482
|
end
|
2699
|
-
@c1.dataset.
|
2700
|
-
def fetch_rows(sql, &block)
|
2701
|
-
db.sqls << sql
|
2702
|
-
yield(:id=>2)
|
2703
|
-
end
|
2704
|
-
end
|
2483
|
+
@c1.dataset._fetch = {:id=>2}
|
2705
2484
|
@c2.load(:id=>1).remove_attribute(2)
|
2706
2485
|
MODEL_DB.sqls.should == ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1)) WHERE ((join_table_att = 3) AND (attributes.id = 2)) LIMIT 1",
|
2707
2486
|
"DELETE FROM attributes_nodes WHERE ((node_id = 1) AND (attribute_id = 2))"]
|
2708
2487
|
end
|
2709
2488
|
end
|
2710
2489
|
|
2711
|
-
describe Sequel::Model, " association reflection methods" do
|
2712
|
-
before do
|
2713
|
-
MODEL_DB.reset
|
2714
|
-
@c1 = Class.new(Sequel::Model(:nodes)) do
|
2715
|
-
def self.name; 'Node'; end
|
2716
|
-
def self.to_s; 'Node'; end
|
2717
|
-
end
|
2718
|
-
end
|
2719
|
-
|
2720
|
-
it "#all_association_reflections should include all association reflection hashes" do
|
2721
|
-
@c1.all_association_reflections.should == []
|
2722
|
-
|
2723
|
-
@c1.associate :many_to_one, :parent, :class => @c1
|
2724
|
-
@c1.all_association_reflections.collect{|v| v[:name]}.should == [:parent]
|
2725
|
-
@c1.all_association_reflections.collect{|v| v[:type]}.should == [:many_to_one]
|
2726
|
-
@c1.all_association_reflections.collect{|v| v[:class]}.should == [@c1]
|
2727
|
-
|
2728
|
-
@c1.associate :one_to_many, :children, :class => @c1
|
2729
|
-
@c1.all_association_reflections.sort_by{|x|x[:name].to_s}
|
2730
|
-
@c1.all_association_reflections.sort_by{|x|x[:name].to_s}.collect{|v| v[:name]}.should == [:children, :parent]
|
2731
|
-
@c1.all_association_reflections.sort_by{|x|x[:name].to_s}.collect{|v| v[:type]}.should == [:one_to_many, :many_to_one]
|
2732
|
-
@c1.all_association_reflections.sort_by{|x|x[:name].to_s}.collect{|v| v[:class]}.should == [@c1, @c1]
|
2733
|
-
end
|
2734
|
-
|
2735
|
-
it "#association_reflection should return nil for nonexistent association" do
|
2736
|
-
@c1.association_reflection(:blah).should == nil
|
2737
|
-
end
|
2738
|
-
|
2739
|
-
it "#association_reflection should return association reflection hash if association exists" do
|
2740
|
-
@c1.associate :many_to_one, :parent, :class => @c1
|
2741
|
-
@c1.association_reflection(:parent).should be_a_kind_of(Sequel::Model::Associations::AssociationReflection)
|
2742
|
-
@c1.association_reflection(:parent)[:name].should == :parent
|
2743
|
-
@c1.association_reflection(:parent)[:type].should == :many_to_one
|
2744
|
-
@c1.association_reflection(:parent)[:class].should == @c1
|
2745
|
-
|
2746
|
-
@c1.associate :one_to_many, :children, :class => @c1
|
2747
|
-
@c1.association_reflection(:children).should be_a_kind_of(Sequel::Model::Associations::AssociationReflection)
|
2748
|
-
@c1.association_reflection(:children)[:name].should == :children
|
2749
|
-
@c1.association_reflection(:children)[:type].should == :one_to_many
|
2750
|
-
@c1.association_reflection(:children)[:class].should == @c1
|
2751
|
-
end
|
2752
|
-
|
2753
|
-
it "#associations should include all association names" do
|
2754
|
-
@c1.associations.should == []
|
2755
|
-
@c1.associate :many_to_one, :parent, :class => @c1
|
2756
|
-
@c1.associations.should == [:parent]
|
2757
|
-
@c1.associate :one_to_many, :children, :class => @c1
|
2758
|
-
@c1.associations.sort_by{|x|x.to_s}.should == [:children, :parent]
|
2759
|
-
end
|
2760
|
-
|
2761
|
-
it "association reflections should be copied upon subclasing" do
|
2762
|
-
@c1.associate :many_to_one, :parent, :class => @c1
|
2763
|
-
c = Class.new(@c1)
|
2764
|
-
@c1.associations.should == [:parent]
|
2765
|
-
c.associations.should == [:parent]
|
2766
|
-
c.associate :many_to_one, :parent2, :class => @c1
|
2767
|
-
@c1.associations.should == [:parent]
|
2768
|
-
c.associations.sort_by{|x| x.to_s}.should == [:parent, :parent2]
|
2769
|
-
c.instance_methods.map{|x| x.to_s}.should include('parent')
|
2770
|
-
end
|
2771
|
-
end
|
2772
|
-
|
2773
2490
|
describe "Filtering by associations" do
|
2774
2491
|
before do
|
2775
2492
|
@Album = Class.new(Sequel::Model(:albums))
|