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