sequel 3.21.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 +413 -3
- data/README.rdoc +20 -6
- data/Rakefile +23 -16
- data/bin/sequel +1 -5
- data/doc/association_basics.rdoc +210 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/mass_assignment.rdoc +54 -0
- data/doc/migration.rdoc +15 -538
- data/doc/model_hooks.rdoc +72 -27
- data/doc/opening_databases.rdoc +86 -50
- data/doc/prepared_statements.rdoc +40 -13
- data/doc/reflection.rdoc +8 -2
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +115 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +15 -7
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- 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/do.rb +17 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +448 -0
- data/lib/sequel/adapters/informix.rb +6 -23
- data/lib/sequel/adapters/jdbc/as400.rb +5 -31
- data/lib/sequel/adapters/jdbc/db2.rb +44 -0
- data/lib/sequel/adapters/jdbc/derby.rb +217 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +26 -17
- data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
- data/lib/sequel/adapters/jdbc/informix.rb +26 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
- data/lib/sequel/adapters/jdbc/mysql.rb +9 -10
- data/lib/sequel/adapters/jdbc/oracle.rb +67 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +6 -11
- data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
- data/lib/sequel/adapters/jdbc/sqlserver.rb +41 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +107 -38
- data/lib/sequel/adapters/mock.rb +315 -0
- data/lib/sequel/adapters/mysql.rb +78 -182
- data/lib/sequel/adapters/mysql2.rb +24 -23
- data/lib/sequel/adapters/odbc/db2.rb +17 -0
- data/lib/sequel/adapters/odbc/mssql.rb +0 -5
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +2 -4
- data/lib/sequel/adapters/oracle.rb +349 -51
- data/lib/sequel/adapters/postgres.rb +169 -21
- data/lib/sequel/adapters/shared/access.rb +21 -6
- data/lib/sequel/adapters/shared/db2.rb +288 -0
- data/lib/sequel/adapters/shared/firebird.rb +214 -0
- data/lib/sequel/adapters/shared/informix.rb +45 -0
- data/lib/sequel/adapters/shared/mssql.rb +108 -65
- data/lib/sequel/adapters/shared/mysql.rb +56 -13
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +185 -34
- data/lib/sequel/adapters/shared/postgres.rb +107 -58
- data/lib/sequel/adapters/shared/progress.rb +0 -6
- data/lib/sequel/adapters/shared/sqlite.rb +168 -41
- data/lib/sequel/adapters/sqlite.rb +27 -18
- data/lib/sequel/adapters/swift/mysql.rb +9 -5
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +6 -4
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/tinytds.rb +152 -17
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +63 -0
- data/lib/sequel/ast_transformer.rb +190 -0
- data/lib/sequel/connection_pool/threaded.rb +3 -2
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +46 -5
- data/lib/sequel/database/connecting.rb +5 -6
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +59 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +100 -19
- data/lib/sequel/database/query.rb +153 -58
- data/lib/sequel/database/schema_generator.rb +8 -5
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +194 -57
- data/lib/sequel/dataset/features.rb +81 -8
- data/lib/sequel/dataset/graph.rb +8 -7
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +5 -6
- data/lib/sequel/dataset/prepared_statements.rb +32 -15
- data/lib/sequel/dataset/query.rb +223 -42
- data/lib/sequel/dataset/sql.rb +58 -61
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +6 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +997 -331
- data/lib/sequel/model/base.rb +386 -129
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +15 -8
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +114 -7
- data/lib/sequel/plugins/many_through_many.rb +65 -7
- data/lib/sequel/plugins/prepared_statements.rb +151 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +6 -1
- data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
- data/lib/sequel/plugins/sharding.rb +12 -25
- data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +107 -51
- data/lib/sequel/timezones.rb +44 -35
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +65 -29
- data/spec/adapters/mysql_spec.rb +122 -123
- data/spec/adapters/oracle_spec.rb +48 -76
- data/spec/adapters/postgres_spec.rb +213 -61
- data/spec/adapters/spec_helper.rb +6 -5
- data/spec/adapters/sqlite_spec.rb +35 -21
- data/spec/core/connection_pool_spec.rb +71 -92
- data/spec/core/core_sql_spec.rb +20 -31
- data/spec/core/database_spec.rb +729 -508
- data/spec/core/dataset_spec.rb +980 -1044
- data/spec/core/expression_filters_spec.rb +159 -42
- 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 +298 -38
- data/spec/core/spec_helper.rb +6 -48
- data/spec/extensions/association_pks_spec.rb +38 -0
- data/spec/extensions/class_table_inheritance_spec.rb +1 -1
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/identity_map_spec.rb +162 -0
- data/spec/extensions/instance_hooks_spec.rb +71 -0
- data/spec/extensions/many_through_many_spec.rb +195 -20
- data/spec/extensions/migration_spec.rb +17 -17
- data/spec/extensions/named_timezones_spec.rb +22 -2
- data/spec/extensions/nested_attributes_spec.rb +4 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
- data/spec/extensions/prepared_statements_spec.rb +72 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
- data/spec/extensions/schema_dumper_spec.rb +2 -2
- data/spec/extensions/schema_spec.rb +13 -21
- data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
- data/spec/extensions/serialization_spec.rb +5 -8
- data/spec/extensions/single_table_inheritance_spec.rb +11 -0
- data/spec/extensions/spec_helper.rb +7 -1
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/to_dot_spec.rb +3 -5
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +522 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +375 -62
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +304 -116
- data/spec/integration/prepared_statement_test.rb +200 -120
- data/spec/integration/schema_test.rb +161 -30
- data/spec/integration/spec_helper.rb +39 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +172 -5
- data/spec/integration/type_test.rb +17 -3
- data/spec/model/association_reflection_spec.rb +174 -7
- data/spec/model/associations_spec.rb +849 -661
- data/spec/model/base_spec.rb +255 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +640 -676
- data/spec/model/hooks_spec.rb +309 -67
- data/spec/model/model_spec.rb +207 -167
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +321 -218
- data/spec/model/spec_helper.rb +13 -71
- data/spec/model/validations_spec.rb +11 -0
- metadata +95 -38
|
@@ -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
|
|
@@ -357,13 +356,32 @@ describe Sequel::Model, "many_to_one" do
|
|
|
357
356
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (nodes.id = 234) LIMIT 1"]
|
|
358
357
|
end
|
|
359
358
|
|
|
359
|
+
it "should use a callback if given one as the argument" do
|
|
360
|
+
@c2.many_to_one :parent, :class => @c2
|
|
361
|
+
|
|
362
|
+
d = @c2.create(:id => 1)
|
|
363
|
+
MODEL_DB.reset
|
|
364
|
+
d.parent_id = 234
|
|
365
|
+
d.associations[:parent] = 42
|
|
366
|
+
d.parent(proc{|ds| ds.filter{name > 'M'}}).should_not == 42
|
|
367
|
+
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.id = 234) AND (name > 'M')) LIMIT 1"]
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
it "should use a block given to the association method as a callback on ruby 1.8.7+" do
|
|
371
|
+
@c2.many_to_one :parent, :class => @c2
|
|
372
|
+
|
|
373
|
+
d = @c2.create(:id => 1)
|
|
374
|
+
MODEL_DB.reset
|
|
375
|
+
d.parent_id = 234
|
|
376
|
+
d.associations[:parent] = 42
|
|
377
|
+
d.parent{|ds| ds.filter{name > 'M'}}.should_not == 42
|
|
378
|
+
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.id = 234) AND (name > 'M')) LIMIT 1"]
|
|
379
|
+
end if RUBY_VERSION >= '1.8.7'
|
|
380
|
+
|
|
360
381
|
it "should have the setter add to the reciprocal one_to_many cached association list if it exists" do
|
|
361
382
|
@c2.many_to_one :parent, :class => @c2
|
|
362
383
|
@c2.one_to_many :children, :class => @c2, :key=>:parent_id
|
|
363
|
-
|
|
364
|
-
def ds.fetch_rows(sql, &block)
|
|
365
|
-
MODEL_DB.sqls << sql
|
|
366
|
-
end
|
|
384
|
+
@c2.dataset._fetch = []
|
|
367
385
|
|
|
368
386
|
d = @c2.new(:id => 1)
|
|
369
387
|
e = @c2.new(:id => 2)
|
|
@@ -372,14 +390,13 @@ describe Sequel::Model, "many_to_one" do
|
|
|
372
390
|
e.children.should_not(include(d))
|
|
373
391
|
MODEL_DB.sqls.should == ['SELECT * FROM nodes WHERE (nodes.parent_id = 2)']
|
|
374
392
|
|
|
375
|
-
MODEL_DB.reset
|
|
376
393
|
d = @c2.new(:id => 1)
|
|
377
394
|
e = @c2.new(:id => 2)
|
|
378
395
|
e.children.should_not(include(d))
|
|
379
396
|
MODEL_DB.sqls.should == ['SELECT * FROM nodes WHERE (nodes.parent_id = 2)']
|
|
380
397
|
d.parent = e
|
|
381
398
|
e.children.should(include(d))
|
|
382
|
-
MODEL_DB.sqls.should == [
|
|
399
|
+
MODEL_DB.sqls.should == []
|
|
383
400
|
end
|
|
384
401
|
|
|
385
402
|
it "should have many_to_one setter deal with a one_to_one reciprocal" do
|
|
@@ -407,10 +424,7 @@ describe Sequel::Model, "many_to_one" do
|
|
|
407
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
|
|
408
425
|
@c2.many_to_one :parent, :class => @c2
|
|
409
426
|
@c2.one_to_many :children, :class => @c2, :key=>:parent_id
|
|
410
|
-
|
|
411
|
-
def ds.fetch_rows(sql, &block)
|
|
412
|
-
MODEL_DB.sqls << sql
|
|
413
|
-
end
|
|
427
|
+
@c2.dataset._fetch = []
|
|
414
428
|
|
|
415
429
|
d = @c2.new(:id => 1)
|
|
416
430
|
e = @c2.new(:id => 2)
|
|
@@ -429,17 +443,9 @@ describe Sequel::Model, "many_to_one" do
|
|
|
429
443
|
end
|
|
430
444
|
|
|
431
445
|
it "should get all matching records and only return the first if :key option is set to nil" do
|
|
432
|
-
c2 = @c2
|
|
433
446
|
@c2.one_to_many :children, :class => @c2, :key=>:parent_id
|
|
434
|
-
@c2.many_to_one :first_grand_parent, :class => @c2, :key=>nil, :eager_graph=>:children, :dataset=>proc{
|
|
435
|
-
|
|
436
|
-
def ds.columns
|
|
437
|
-
[:id, :parent_id, :par_parent_id, :blah]
|
|
438
|
-
end
|
|
439
|
-
def ds.fetch_rows(sql, &block)
|
|
440
|
-
MODEL_DB.sqls << sql
|
|
441
|
-
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})
|
|
442
|
-
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}, {}]
|
|
443
449
|
p = @c2.new(:parent_id=>2)
|
|
444
450
|
fgp = p.first_grand_parent
|
|
445
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)"]
|
|
@@ -500,15 +506,15 @@ describe Sequel::Model, "many_to_one" do
|
|
|
500
506
|
h = []
|
|
501
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}
|
|
502
508
|
@c2.class_eval do
|
|
503
|
-
|
|
509
|
+
self::Foo = h
|
|
504
510
|
def []=(a, v)
|
|
505
|
-
a == :parent_id ? (
|
|
511
|
+
a == :parent_id ? (model::Foo << (v ? 4 : 5)) : super
|
|
506
512
|
end
|
|
507
513
|
def blah(x)
|
|
508
|
-
|
|
514
|
+
model::Foo << (x ? x.pk : :x)
|
|
509
515
|
end
|
|
510
516
|
def blahr(x)
|
|
511
|
-
|
|
517
|
+
model::Foo << 6
|
|
512
518
|
end
|
|
513
519
|
end
|
|
514
520
|
p = @c2.load(:id=>10)
|
|
@@ -524,13 +530,11 @@ describe Sequel::Model, "many_to_one" do
|
|
|
524
530
|
h = []
|
|
525
531
|
@c2.many_to_one :parent, :class => @c2, :after_load=>[proc{|x,y| h << [x.pk, y.pk]}, :al]
|
|
526
532
|
@c2.class_eval do
|
|
527
|
-
|
|
533
|
+
self::Foo = h
|
|
528
534
|
def al(v)
|
|
529
|
-
|
|
530
|
-
end
|
|
531
|
-
def @dataset.fetch_rows(sql)
|
|
532
|
-
yield({:id=>20})
|
|
535
|
+
model::Foo << v.pk
|
|
533
536
|
end
|
|
537
|
+
dataset._fetch = {:id=>20}
|
|
534
538
|
end
|
|
535
539
|
p = @c2.load(:id=>10, :parent_id=>20)
|
|
536
540
|
parent = p.parent
|
|
@@ -538,6 +542,18 @@ describe Sequel::Model, "many_to_one" do
|
|
|
538
542
|
parent.pk.should == 20
|
|
539
543
|
end
|
|
540
544
|
|
|
545
|
+
it "should support after_load association callback that changes the cached object" do
|
|
546
|
+
@c2.many_to_one :parent, :class => @c2, :after_load=>:al
|
|
547
|
+
@c2.class_eval do
|
|
548
|
+
def al(v)
|
|
549
|
+
associations[:parent] = :foo
|
|
550
|
+
end
|
|
551
|
+
end
|
|
552
|
+
p = @c2.load(:id=>10, :parent_id=>20)
|
|
553
|
+
p.parent.should == :foo
|
|
554
|
+
p.associations[:parent].should == :foo
|
|
555
|
+
end
|
|
556
|
+
|
|
541
557
|
it "should raise error and not call internal add or remove method if before callback returns false, even if raise_on_save_failure is false" do
|
|
542
558
|
# The reason for this is that assignment in ruby always returns the argument instead of the result
|
|
543
559
|
# of the method, so we can't return nil to signal that the association callback prevented the modification
|
|
@@ -565,35 +581,32 @@ describe Sequel::Model, "many_to_one" do
|
|
|
565
581
|
d = @c2.load(:id=>321)
|
|
566
582
|
p = @c2.new
|
|
567
583
|
p.associations[:parent] = d
|
|
568
|
-
h = []
|
|
569
584
|
@c2.many_to_one :parent, :class => @c2, :before_set=>:bs, :after_set=>:as
|
|
570
585
|
@c2.class_eval do
|
|
571
|
-
|
|
586
|
+
self::Foo = []
|
|
572
587
|
def []=(a, v)
|
|
573
|
-
a == :parent_id ? (
|
|
588
|
+
a == :parent_id ? (model::Foo << 5) : super
|
|
574
589
|
end
|
|
575
590
|
def bs(x)
|
|
576
|
-
|
|
591
|
+
model::Foo << x.pk
|
|
577
592
|
end
|
|
578
593
|
def as(x)
|
|
579
|
-
|
|
594
|
+
model::Foo << x.pk * 2
|
|
580
595
|
end
|
|
581
596
|
end
|
|
582
597
|
p.parent = c
|
|
583
|
-
|
|
598
|
+
@c2::Foo.should == [123, 5, 246]
|
|
584
599
|
end
|
|
585
600
|
end
|
|
586
601
|
|
|
587
602
|
describe Sequel::Model, "one_to_one" do
|
|
588
603
|
before do
|
|
589
604
|
@c1 = Class.new(Sequel::Model(:attributes)) do
|
|
590
|
-
def _refresh(ds); end
|
|
591
605
|
unrestrict_primary_key
|
|
592
606
|
columns :id, :node_id, :y
|
|
593
607
|
end
|
|
594
608
|
|
|
595
609
|
@c2 = Class.new(Sequel::Model(:nodes)) do
|
|
596
|
-
def _refresh(ds); end
|
|
597
610
|
unrestrict_primary_key
|
|
598
611
|
attr_accessor :xxx
|
|
599
612
|
|
|
@@ -602,24 +615,8 @@ describe Sequel::Model, "one_to_one" do
|
|
|
602
615
|
columns :id, :x, :parent_id, :par_parent_id, :blah, :node_id
|
|
603
616
|
end
|
|
604
617
|
@dataset = @c2.dataset
|
|
605
|
-
|
|
606
|
-
@
|
|
607
|
-
def empty?; false; end
|
|
608
|
-
def fetch_rows(sql)
|
|
609
|
-
@db << sql
|
|
610
|
-
yield Hash.new
|
|
611
|
-
end
|
|
612
|
-
})
|
|
613
|
-
|
|
614
|
-
@c1.dataset.extend(Module.new {
|
|
615
|
-
def empty?; opts.has_key?(:empty) ? (super; true) : false; end
|
|
616
|
-
def fetch_rows(sql)
|
|
617
|
-
@db << sql
|
|
618
|
-
yield Hash.new
|
|
619
|
-
end
|
|
620
|
-
})
|
|
621
|
-
|
|
622
|
-
@dataset = @c2.dataset
|
|
618
|
+
@dataset._fetch = {}
|
|
619
|
+
@c1.dataset._fetch = {}
|
|
623
620
|
MODEL_DB.reset
|
|
624
621
|
end
|
|
625
622
|
|
|
@@ -641,26 +638,24 @@ describe Sequel::Model, "one_to_one" do
|
|
|
641
638
|
it "should add a setter method" do
|
|
642
639
|
@c2.one_to_one :attribute, :class => @c1
|
|
643
640
|
attrib = @c1.new(:id=>3)
|
|
644
|
-
|
|
645
|
-
@c1.class_eval{remove_method :_refresh}
|
|
646
|
-
def d.fetch_rows(s); yield({:id=>3}) end
|
|
641
|
+
@c1.dataset._fetch = {:id=>3}
|
|
647
642
|
@c2.new(:id => 1234).attribute = attrib
|
|
643
|
+
sqls = MODEL_DB.sqls
|
|
648
644
|
['INSERT INTO attributes (node_id, id) VALUES (1234, 3)',
|
|
649
|
-
'INSERT INTO attributes (id, node_id) VALUES (3, 1234)'].should(include(
|
|
650
|
-
|
|
651
|
-
|
|
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
|
+
|
|
652
648
|
@c2.new(:id => 1234).attribute.should == attrib
|
|
653
|
-
MODEL_DB.sqls.clear
|
|
654
649
|
attrib = @c1.load(:id=>3)
|
|
655
650
|
@c2.new(:id => 1234).attribute = attrib
|
|
656
|
-
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))',
|
|
657
653
|
"UPDATE attributes SET node_id = 1234 WHERE (id = 3)"]
|
|
658
654
|
end
|
|
659
655
|
|
|
660
656
|
it "should use a transaction in the setter method" do
|
|
661
657
|
@c2.one_to_one :attribute, :class => @c1
|
|
662
658
|
@c2.use_transactions = true
|
|
663
|
-
MODEL_DB.sqls.clear
|
|
664
659
|
attrib = @c1.load(:id=>3)
|
|
665
660
|
@c2.new(:id => 1234).attribute = attrib
|
|
666
661
|
MODEL_DB.sqls.should == ['BEGIN',
|
|
@@ -673,7 +668,6 @@ describe Sequel::Model, "one_to_one" do
|
|
|
673
668
|
@c2.one_to_one :attribute, :class => @c1, :conditions=>{:a=>1} do |ds|
|
|
674
669
|
ds.filter(:b=>2)
|
|
675
670
|
end
|
|
676
|
-
MODEL_DB.sqls.clear
|
|
677
671
|
attrib = @c1.load(:id=>3)
|
|
678
672
|
@c2.new(:id => 1234).attribute = attrib
|
|
679
673
|
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = NULL WHERE ((node_id = 1234) AND (a = 1) AND (b = 2) AND (id != 3))',
|
|
@@ -683,30 +677,30 @@ describe Sequel::Model, "one_to_one" do
|
|
|
683
677
|
it "should have the setter method respect the :primary_key option" do
|
|
684
678
|
@c2.one_to_one :attribute, :class => @c1, :primary_key=>:xxx
|
|
685
679
|
attrib = @c1.new(:id=>3)
|
|
686
|
-
|
|
687
|
-
@c1.class_eval{remove_method :_refresh}
|
|
688
|
-
def d.fetch_rows(s); yield({:id=>3}) end
|
|
680
|
+
@c1.dataset._fetch = {:id=>3}
|
|
689
681
|
@c2.new(:id => 1234, :xxx=>5).attribute = attrib
|
|
682
|
+
sqls = MODEL_DB.sqls
|
|
690
683
|
['INSERT INTO attributes (node_id, id) VALUES (5, 3)',
|
|
691
|
-
'INSERT INTO attributes (id, node_id) VALUES (3, 5)'].should(include(
|
|
692
|
-
|
|
693
|
-
|
|
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
|
+
|
|
694
687
|
@c2.new(:id => 321, :xxx=>5).attribute.should == attrib
|
|
695
|
-
MODEL_DB.sqls.clear
|
|
696
688
|
attrib = @c1.load(:id=>3)
|
|
697
689
|
@c2.new(:id => 621, :xxx=>5).attribute = attrib
|
|
698
|
-
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))',
|
|
699
692
|
'UPDATE attributes SET node_id = 5 WHERE (id = 3)']
|
|
700
693
|
end
|
|
701
694
|
|
|
702
695
|
it "should have the setter method respect composite keys" do
|
|
703
696
|
@c2.one_to_one :attribute, :class => @c1, :key=>[:node_id, :y], :primary_key=>[:id, :x]
|
|
704
697
|
attrib = @c1.load(:id=>3, :y=>6)
|
|
705
|
-
|
|
706
|
-
def d.fetch_rows(s); yield({:id=>3, :y=>6}) end
|
|
698
|
+
@c1.dataset._fetch = {:id=>3, :y=>6}
|
|
707
699
|
@c2.load(:id => 1234, :x=>5).attribute = attrib
|
|
708
|
-
|
|
709
|
-
|
|
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
|
|
710
704
|
end
|
|
711
705
|
|
|
712
706
|
it "should use implicit key if omitted" do
|
|
@@ -721,31 +715,27 @@ describe Sequel::Model, "one_to_one" do
|
|
|
721
715
|
end
|
|
722
716
|
|
|
723
717
|
it "should use implicit class if omitted" do
|
|
724
|
-
|
|
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)
|
|
725
725
|
end
|
|
726
|
-
|
|
727
|
-
@c2.one_to_one :par_parent
|
|
728
|
-
|
|
729
|
-
d = @c2.new(:id => 234)
|
|
730
|
-
p = d.par_parent
|
|
731
|
-
p.class.should == ParParent
|
|
732
|
-
|
|
733
|
-
MODEL_DB.sqls.should == ["SELECT * FROM par_parents WHERE (par_parents.node_id = 234) LIMIT 1"]
|
|
734
726
|
end
|
|
735
727
|
|
|
736
728
|
it "should use class inside module if given as a string" do
|
|
737
|
-
|
|
738
|
-
|
|
729
|
+
begin
|
|
730
|
+
module ::Par
|
|
731
|
+
class Parent < Sequel::Model; end
|
|
739
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)
|
|
740
738
|
end
|
|
741
|
-
|
|
742
|
-
@c2.one_to_one :par_parent, :class=>"Par::Parent"
|
|
743
|
-
|
|
744
|
-
d = @c2.new(:id => 234)
|
|
745
|
-
p = d.par_parent
|
|
746
|
-
p.class.should == Par::Parent
|
|
747
|
-
|
|
748
|
-
MODEL_DB.sqls.should == ["SELECT * FROM parents WHERE (parents.node_id = 234) LIMIT 1"]
|
|
749
739
|
end
|
|
750
740
|
|
|
751
741
|
it "should use explicit key if given" do
|
|
@@ -796,14 +786,12 @@ describe Sequel::Model, "one_to_one" do
|
|
|
796
786
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.node_id = 567) AND (a = 32)) LIMIT 1"]
|
|
797
787
|
|
|
798
788
|
@c2.one_to_one :parent, :class => @c2, :conditions=>:a
|
|
799
|
-
MODEL_DB.sqls.clear
|
|
800
789
|
@c2.new(:id => 567).parent
|
|
801
790
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.node_id = 567) AND a) LIMIT 1"]
|
|
802
791
|
end
|
|
803
792
|
|
|
804
793
|
it "should support :order, :limit (only for offset), and :dataset options, as well as a block" do
|
|
805
|
-
c2
|
|
806
|
-
@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|
|
|
807
795
|
ds.filter(:x.sql_number > 1)
|
|
808
796
|
end
|
|
809
797
|
@c2.load(:id => 100).child_20
|
|
@@ -813,24 +801,19 @@ describe Sequel::Model, "one_to_one" do
|
|
|
813
801
|
it "should return nil if primary_key value is nil" do
|
|
814
802
|
@c2.one_to_one :parent, :class => @c2, :primary_key=>:node_id
|
|
815
803
|
|
|
816
|
-
|
|
817
|
-
d.parent.should == nil
|
|
804
|
+
@c2.new(:id => 1).parent.should be_nil
|
|
818
805
|
MODEL_DB.sqls.should == []
|
|
819
806
|
end
|
|
820
807
|
|
|
821
808
|
it "should cache negative lookup" do
|
|
822
809
|
@c2.one_to_one :parent, :class => @c2
|
|
823
|
-
|
|
824
|
-
def ds.fetch_rows(sql, &block)
|
|
825
|
-
MODEL_DB.sqls << sql
|
|
826
|
-
end
|
|
827
|
-
|
|
810
|
+
@c2.dataset._fetch = []
|
|
828
811
|
d = @c2.new(:id => 555)
|
|
829
812
|
MODEL_DB.sqls.should == []
|
|
830
813
|
d.parent.should == nil
|
|
831
814
|
MODEL_DB.sqls.should == ['SELECT * FROM nodes WHERE (nodes.node_id = 555) LIMIT 1']
|
|
832
815
|
d.parent.should == nil
|
|
833
|
-
MODEL_DB.sqls.should == [
|
|
816
|
+
MODEL_DB.sqls.should == []
|
|
834
817
|
end
|
|
835
818
|
|
|
836
819
|
it "should define a setter method" do
|
|
@@ -838,28 +821,44 @@ describe Sequel::Model, "one_to_one" do
|
|
|
838
821
|
|
|
839
822
|
d = @c2.new(:id => 1)
|
|
840
823
|
f = @c2.new(:id => 3, :node_id=> 4321)
|
|
824
|
+
@c2.dataset._fetch = {:id => 3, :node_id=>1}
|
|
841
825
|
d.parent = f
|
|
842
826
|
f.values.should == {:id => 3, :node_id=>1}
|
|
843
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"]
|
|
844
832
|
|
|
845
833
|
d.parent = nil
|
|
846
834
|
d.parent.should == nil
|
|
835
|
+
MODEL_DB.sqls.should == ["UPDATE nodes SET node_id = NULL WHERE (node_id = 1)"]
|
|
847
836
|
end
|
|
848
837
|
|
|
849
838
|
it "should have the setter method respect the :primary_key option" do
|
|
850
839
|
@c2.one_to_one :parent, :class => @c2, :primary_key=>:blah
|
|
851
840
|
d = @c2.new(:id => 1, :blah => 3)
|
|
852
841
|
e = @c2.new(:id => 4321, :node_id=>444)
|
|
842
|
+
@c2.dataset._fetch = {:id => 4321, :node_id => 3}
|
|
853
843
|
d.parent = e
|
|
854
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"]
|
|
855
849
|
end
|
|
856
850
|
|
|
857
851
|
it "should have the setter method respect the :key option" do
|
|
858
852
|
@c2.one_to_one :parent, :class => @c2, :key=>:blah
|
|
859
853
|
d = @c2.new(:id => 3)
|
|
860
854
|
e = @c2.new(:id => 4321, :blah=>444)
|
|
855
|
+
@c2.dataset._fetch = {:id => 4321, :blah => 3}
|
|
861
856
|
d.parent = e
|
|
862
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"]
|
|
863
862
|
end
|
|
864
863
|
|
|
865
864
|
it "should persist changes to associated object when the setter is called" do
|
|
@@ -875,12 +874,11 @@ describe Sequel::Model, "one_to_one" do
|
|
|
875
874
|
|
|
876
875
|
d = @c2.load(:id => 1)
|
|
877
876
|
d.associations[:parent].should == nil
|
|
878
|
-
|
|
879
|
-
def ds.fetch_rows(sql, &block); MODEL_DB.sqls << sql; yield({:id=>234}) end
|
|
877
|
+
@c2.dataset._fetch = {:id=>234}
|
|
880
878
|
e = d.parent
|
|
881
879
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (nodes.node_id = 1) LIMIT 1"]
|
|
882
880
|
d.parent
|
|
883
|
-
MODEL_DB.sqls.should == [
|
|
881
|
+
MODEL_DB.sqls.should == []
|
|
884
882
|
d.associations[:parent].should == e
|
|
885
883
|
end
|
|
886
884
|
|
|
@@ -922,7 +920,6 @@ describe Sequel::Model, "one_to_one" do
|
|
|
922
920
|
e.child.should == d
|
|
923
921
|
MODEL_DB.sqls.should == ["UPDATE nodes SET parent_id = NULL WHERE ((parent_id = 1) AND (id != 2))",
|
|
924
922
|
"UPDATE nodes SET parent_id = 1 WHERE (id = 2)"]
|
|
925
|
-
MODEL_DB.reset
|
|
926
923
|
d.parent = nil
|
|
927
924
|
e.child.should == nil
|
|
928
925
|
MODEL_DB.sqls.should == ["UPDATE nodes SET parent_id = NULL WHERE (parent_id = 1)"]
|
|
@@ -931,17 +928,13 @@ describe Sequel::Model, "one_to_one" do
|
|
|
931
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
|
|
932
929
|
@c2.one_to_one :parent, :class => @c2, :key=>:parent_id
|
|
933
930
|
@c2.many_to_one :child, :class => @c2, :key=>:parent_id
|
|
934
|
-
|
|
935
|
-
def ds.fetch_rows(sql, &block)
|
|
936
|
-
MODEL_DB.sqls << sql
|
|
937
|
-
end
|
|
931
|
+
@c2.dataset._fetch = []
|
|
938
932
|
|
|
939
933
|
d = @c2.load(:id => 1)
|
|
940
934
|
e = @c2.load(:id => 2)
|
|
941
935
|
f = @c2.load(:id => 3)
|
|
942
936
|
e.child.should == nil
|
|
943
937
|
f.child.should == nil
|
|
944
|
-
MODEL_DB.reset
|
|
945
938
|
d.parent = e
|
|
946
939
|
e.child.should == d
|
|
947
940
|
d.parent = f
|
|
@@ -983,12 +976,12 @@ describe Sequel::Model, "one_to_one" do
|
|
|
983
976
|
h = []
|
|
984
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}
|
|
985
978
|
@c2.class_eval do
|
|
986
|
-
|
|
979
|
+
self::Foo = h
|
|
987
980
|
def blah(x)
|
|
988
|
-
|
|
981
|
+
model::Foo << (x ? x.pk : :x)
|
|
989
982
|
end
|
|
990
983
|
def blahr(x)
|
|
991
|
-
|
|
984
|
+
model::Foo << 6
|
|
992
985
|
end
|
|
993
986
|
end
|
|
994
987
|
p = @c2.load(:id=>10)
|
|
@@ -1004,13 +997,11 @@ describe Sequel::Model, "one_to_one" do
|
|
|
1004
997
|
h = []
|
|
1005
998
|
@c2.one_to_one :parent, :class => @c2, :after_load=>[proc{|x,y| h << [x.pk, y.pk]}, :al]
|
|
1006
999
|
@c2.class_eval do
|
|
1007
|
-
|
|
1000
|
+
self::Foo = h
|
|
1008
1001
|
def al(v)
|
|
1009
|
-
|
|
1010
|
-
end
|
|
1011
|
-
def @dataset.fetch_rows(sql)
|
|
1012
|
-
yield({:id=>20})
|
|
1002
|
+
model::Foo << v.pk
|
|
1013
1003
|
end
|
|
1004
|
+
@dataset._fetch = {:id=>20}
|
|
1014
1005
|
end
|
|
1015
1006
|
p = @c2.load(:id=>10)
|
|
1016
1007
|
parent = p.parent
|
|
@@ -1048,15 +1039,15 @@ describe Sequel::Model, "one_to_one" do
|
|
|
1048
1039
|
h = []
|
|
1049
1040
|
@c2.one_to_one :parent, :class => @c2, :before_set=>:bs, :after_set=>:as
|
|
1050
1041
|
@c2.class_eval do
|
|
1051
|
-
|
|
1042
|
+
self::Foo = h
|
|
1052
1043
|
def []=(a, v)
|
|
1053
|
-
a == :node_id ? (
|
|
1044
|
+
a == :node_id ? (model::Foo << 5) : super
|
|
1054
1045
|
end
|
|
1055
1046
|
def bs(x)
|
|
1056
|
-
|
|
1047
|
+
model::Foo << x.pk
|
|
1057
1048
|
end
|
|
1058
1049
|
def as(x)
|
|
1059
|
-
|
|
1050
|
+
model::Foo << x.pk * 2
|
|
1060
1051
|
end
|
|
1061
1052
|
end
|
|
1062
1053
|
p.parent = c
|
|
@@ -1072,16 +1063,9 @@ end
|
|
|
1072
1063
|
|
|
1073
1064
|
describe Sequel::Model, "one_to_many" do
|
|
1074
1065
|
before do
|
|
1075
|
-
MODEL_DB.reset
|
|
1076
|
-
|
|
1077
1066
|
@c1 = Class.new(Sequel::Model(:attributes)) do
|
|
1078
|
-
def _refresh(ds); end
|
|
1079
1067
|
unrestrict_primary_key
|
|
1080
1068
|
columns :id, :node_id, :y, :z
|
|
1081
|
-
|
|
1082
|
-
def self.[](id)
|
|
1083
|
-
load(id.is_a?(Array) ? {:id => id[0], :z => id[1]} : {:id => id})
|
|
1084
|
-
end
|
|
1085
1069
|
end
|
|
1086
1070
|
|
|
1087
1071
|
@c2 = Class.new(Sequel::Model(:nodes)) do
|
|
@@ -1094,68 +1078,58 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1094
1078
|
columns :id, :x
|
|
1095
1079
|
end
|
|
1096
1080
|
@dataset = @c2.dataset
|
|
1097
|
-
|
|
1098
|
-
@
|
|
1099
|
-
|
|
1100
|
-
def fetch_rows(sql)
|
|
1101
|
-
@db << sql
|
|
1102
|
-
yield Hash.new
|
|
1103
|
-
end
|
|
1104
|
-
})
|
|
1105
|
-
|
|
1106
|
-
@c1.dataset.extend(Module.new {
|
|
1107
|
-
def empty?; opts.has_key?(:empty) ? (super; true) : false; end
|
|
1108
|
-
def fetch_rows(sql)
|
|
1109
|
-
@db << sql
|
|
1110
|
-
yield Hash.new
|
|
1111
|
-
end
|
|
1112
|
-
})
|
|
1081
|
+
@dataset._fetch = {}
|
|
1082
|
+
@c1.dataset._fetch = proc{|sql| sql =~ /SELECT 1/ ? {:a=>1} : {}}
|
|
1083
|
+
MODEL_DB.reset
|
|
1113
1084
|
end
|
|
1114
1085
|
|
|
1115
1086
|
it "should use implicit key if omitted" do
|
|
1116
1087
|
@c2.one_to_many :attributes, :class => @c1
|
|
1117
|
-
|
|
1118
|
-
n = @c2.new(:id => 1234)
|
|
1119
|
-
a = n.attributes_dataset
|
|
1120
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
|
1121
|
-
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)'
|
|
1122
1089
|
end
|
|
1123
1090
|
|
|
1124
1091
|
it "should use implicit class if omitted" do
|
|
1125
|
-
|
|
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)
|
|
1126
1102
|
end
|
|
1127
|
-
|
|
1128
|
-
@c2.one_to_many :historical_values
|
|
1129
|
-
|
|
1130
|
-
n = @c2.new(:id => 1234)
|
|
1131
|
-
v = n.historical_values_dataset
|
|
1132
|
-
v.should be_a_kind_of(Sequel::Dataset)
|
|
1133
|
-
v.sql.should == 'SELECT * FROM historical_values WHERE (historical_values.node_id = 1234)'
|
|
1134
|
-
v.model.should == HistoricalValue
|
|
1135
1103
|
end
|
|
1136
1104
|
|
|
1137
1105
|
it "should use class inside a module if given as a string" do
|
|
1138
|
-
|
|
1139
|
-
|
|
1106
|
+
begin
|
|
1107
|
+
module ::Historical
|
|
1108
|
+
class Value < Sequel::Model; end
|
|
1140
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)
|
|
1141
1118
|
end
|
|
1142
|
-
|
|
1143
|
-
@c2.one_to_many :historical_values, :class=>'Historical::Value'
|
|
1144
|
-
|
|
1145
|
-
n = @c2.new(:id => 1234)
|
|
1146
|
-
v = n.historical_values_dataset
|
|
1147
|
-
v.should be_a_kind_of(Sequel::Dataset)
|
|
1148
|
-
v.sql.should == 'SELECT * FROM values WHERE (values.node_id = 1234)'
|
|
1149
|
-
v.model.should == Historical::Value
|
|
1150
1119
|
end
|
|
1151
1120
|
|
|
1152
|
-
it "should use
|
|
1121
|
+
it "should use a callback if given one as the argument" do
|
|
1153
1122
|
@c2.one_to_many :attributes, :class => @c1, :key => :nodeid
|
|
1154
1123
|
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1124
|
+
d = @c2.load(:id => 1234)
|
|
1125
|
+
d.associations[:attributes] = []
|
|
1126
|
+
d.attributes(proc{|ds| ds.filter{name > 'M'}}).should_not == []
|
|
1127
|
+
MODEL_DB.sqls.should == ["SELECT * FROM attributes WHERE ((attributes.nodeid = 1234) AND (name > 'M'))"]
|
|
1128
|
+
end
|
|
1129
|
+
|
|
1130
|
+
it "should use explicit key if given" do
|
|
1131
|
+
@c2.one_to_many :attributes, :class => @c1, :key => :nodeid
|
|
1132
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE (attributes.nodeid = 1234)'
|
|
1159
1133
|
end
|
|
1160
1134
|
|
|
1161
1135
|
it "should support_composite keys" do
|
|
@@ -1180,10 +1154,8 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1180
1154
|
it "should define an add_ method that works on existing records" do
|
|
1181
1155
|
@c2.one_to_many :attributes, :class => @c1
|
|
1182
1156
|
|
|
1183
|
-
n = @c2.
|
|
1184
|
-
a = @c1.
|
|
1185
|
-
a.save
|
|
1186
|
-
MODEL_DB.reset
|
|
1157
|
+
n = @c2.load(:id => 1234)
|
|
1158
|
+
a = @c1.load(:id => 2345)
|
|
1187
1159
|
a.should == n.add_attribute(a)
|
|
1188
1160
|
a.values.should == {:node_id => 1234, :id => 2345}
|
|
1189
1161
|
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 1234 WHERE (id = 2345)']
|
|
@@ -1192,34 +1164,32 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1192
1164
|
it "should define an add_ method that works on new records" do
|
|
1193
1165
|
@c2.one_to_many :attributes, :class => @c1
|
|
1194
1166
|
|
|
1195
|
-
n = @c2.
|
|
1167
|
+
n = @c2.load(:id => 1234)
|
|
1196
1168
|
a = @c1.new(:id => 234)
|
|
1197
|
-
|
|
1198
|
-
MODEL_DB.reset
|
|
1169
|
+
@c1.dataset._fetch = {:node_id => 1234, :id => 234}
|
|
1199
1170
|
a.should == n.add_attribute(a)
|
|
1200
|
-
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"]
|
|
1201
1174
|
a.values.should == {:node_id => 1234, :id => 234}
|
|
1202
1175
|
end
|
|
1203
1176
|
|
|
1204
1177
|
it "should define a remove_ method that works on existing records" do
|
|
1205
1178
|
@c2.one_to_many :attributes, :class => @c1
|
|
1206
1179
|
|
|
1207
|
-
n = @c2.
|
|
1208
|
-
a = @c1.
|
|
1209
|
-
a.save
|
|
1210
|
-
MODEL_DB.reset
|
|
1180
|
+
n = @c2.load(:id => 1234)
|
|
1181
|
+
a = @c1.load(:id => 2345, :node_id => 1234)
|
|
1211
1182
|
a.should == n.remove_attribute(a)
|
|
1212
1183
|
a.values.should == {:node_id => nil, :id => 2345}
|
|
1213
|
-
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)']
|
|
1214
1185
|
end
|
|
1215
1186
|
|
|
1216
1187
|
it "should have the remove_ method raise an error if the passed object is not already associated" do
|
|
1217
1188
|
@c2.one_to_many :attributes, :class => @c1
|
|
1218
|
-
@c1.dataset.opts[:empty] = true
|
|
1219
1189
|
|
|
1220
1190
|
n = @c2.new(:id => 1234)
|
|
1221
1191
|
a = @c1.load(:id => 2345, :node_id => 1234)
|
|
1222
|
-
|
|
1192
|
+
@c1.dataset._fetch = []
|
|
1223
1193
|
proc{n.remove_attribute(a)}.should raise_error(Sequel::Error)
|
|
1224
1194
|
MODEL_DB.sqls.should == ["SELECT 1 FROM attributes WHERE ((attributes.node_id = 1234) AND (id = 2345)) LIMIT 1"]
|
|
1225
1195
|
end
|
|
@@ -1228,16 +1198,19 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1228
1198
|
@c2.one_to_many :attributes, :class => @c1
|
|
1229
1199
|
n = @c2.new(:id => 1234)
|
|
1230
1200
|
MODEL_DB.reset
|
|
1231
|
-
@c1.
|
|
1232
|
-
|
|
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"]
|
|
1233
1206
|
end
|
|
1234
1207
|
|
|
1235
1208
|
it "should accept a primary key for the add_ method" do
|
|
1236
1209
|
@c2.one_to_many :attributes, :class => @c1
|
|
1237
1210
|
n = @c2.new(:id => 1234)
|
|
1238
|
-
|
|
1239
|
-
@c1.load(:node_id => 1234, :id => 234)
|
|
1240
|
-
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)"]
|
|
1241
1214
|
end
|
|
1242
1215
|
|
|
1243
1216
|
it "should raise an error in the add_ method if the passed associated object is not of the correct type" do
|
|
@@ -1248,13 +1221,8 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1248
1221
|
it "should accept a primary key for the remove_ method and remove an existing record" do
|
|
1249
1222
|
@c2.one_to_many :attributes, :class => @c1
|
|
1250
1223
|
n = @c2.new(:id => 1234)
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
db << sql
|
|
1254
|
-
yield({:id=>234, :node_id=>1234})
|
|
1255
|
-
end
|
|
1256
|
-
MODEL_DB.reset
|
|
1257
|
-
@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)
|
|
1258
1226
|
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (attributes.id = 234)) LIMIT 1',
|
|
1259
1227
|
'UPDATE attributes SET node_id = NULL WHERE (id = 234)']
|
|
1260
1228
|
end
|
|
@@ -1268,10 +1236,8 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1268
1236
|
@c2.one_to_many :attributes, :class => @c1, :primary_key=>:xxx
|
|
1269
1237
|
|
|
1270
1238
|
n = @c2.new(:id => 1234, :xxx=>5)
|
|
1271
|
-
a = @c1.
|
|
1272
|
-
a.
|
|
1273
|
-
MODEL_DB.reset
|
|
1274
|
-
a.should == n.add_attribute(a)
|
|
1239
|
+
a = @c1.load(:id => 2345)
|
|
1240
|
+
n.add_attribute(a).should == a
|
|
1275
1241
|
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 5 WHERE (id = 2345)']
|
|
1276
1242
|
end
|
|
1277
1243
|
|
|
@@ -1279,15 +1245,13 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1279
1245
|
@c2.one_to_many :attributes, :class => @c1
|
|
1280
1246
|
|
|
1281
1247
|
n = @c2.new(:id => 1234)
|
|
1282
|
-
a = @c1.
|
|
1283
|
-
a.save
|
|
1284
|
-
MODEL_DB.reset
|
|
1248
|
+
a = @c1.load(:id => 2345)
|
|
1285
1249
|
n.associations[:attributes] = []
|
|
1286
1250
|
a.should == n.add_attribute(a)
|
|
1287
1251
|
a.should == n.add_attribute(a)
|
|
1288
1252
|
a.values.should == {:node_id => 1234, :id => 2345}
|
|
1289
|
-
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 1234 WHERE (id = 2345)'] * 2
|
|
1290
1253
|
n.attributes.should == [a]
|
|
1254
|
+
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 1234 WHERE (id = 2345)'] * 2
|
|
1291
1255
|
end
|
|
1292
1256
|
|
|
1293
1257
|
it "should have add_ method respect composite keys" do
|
|
@@ -1295,18 +1259,24 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1295
1259
|
|
|
1296
1260
|
n = @c2.load(:id => 1234, :x=>5)
|
|
1297
1261
|
a = @c1.load(:id => 2345)
|
|
1298
|
-
a.should ==
|
|
1299
|
-
|
|
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 == []
|
|
1300
1266
|
end
|
|
1301
1267
|
|
|
1302
1268
|
it "should have add_ method accept a composite key" do
|
|
1303
1269
|
@c1.set_primary_key :id, :z
|
|
1304
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}
|
|
1305
1272
|
|
|
1306
1273
|
n = @c2.load(:id => 1234, :x=>5)
|
|
1307
1274
|
a = @c1.load(:id => 2345, :z => 8, :node_id => 1234, :y=>5)
|
|
1308
|
-
|
|
1309
|
-
|
|
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 == []
|
|
1310
1280
|
end
|
|
1311
1281
|
|
|
1312
1282
|
it "should have remove_ method respect composite keys" do
|
|
@@ -1314,31 +1284,29 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1314
1284
|
|
|
1315
1285
|
n = @c2.load(:id => 1234, :x=>5)
|
|
1316
1286
|
a = @c1.load(:id => 2345, :node_id=>1234, :y=>5)
|
|
1317
|
-
a.should ==
|
|
1318
|
-
|
|
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"]
|
|
1319
1291
|
end
|
|
1320
1292
|
|
|
1321
1293
|
it "should accept a array of composite primary key values for the remove_ method and remove an existing record" do
|
|
1322
1294
|
@c1.set_primary_key :id, :y
|
|
1323
1295
|
@c2.one_to_many :attributes, :class => @c1, :key=>:node_id, :primary_key=>:id
|
|
1324
1296
|
n = @c2.new(:id => 123)
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
@c1.load(:node_id => nil, :y => 5, :id => 234).should == n.remove_attribute([234, 5])
|
|
1332
|
-
MODEL_DB.sqls.length.should == 2
|
|
1333
|
-
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/
|
|
1334
|
-
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)\)\)/
|
|
1335
1303
|
end
|
|
1336
1304
|
|
|
1337
1305
|
it "should raise an error in add_ and remove_ if the passed object returns false to save (is not valid)" do
|
|
1338
1306
|
@c2.one_to_many :attributes, :class => @c1
|
|
1339
1307
|
n = @c2.new(:id => 1234)
|
|
1340
1308
|
a = @c1.new(:id => 2345)
|
|
1341
|
-
def a.
|
|
1309
|
+
def a.validate() errors.add(:id, 'foo') end
|
|
1342
1310
|
proc{n.add_attribute(a)}.should raise_error(Sequel::Error)
|
|
1343
1311
|
proc{n.remove_attribute(a)}.should raise_error(Sequel::Error)
|
|
1344
1312
|
end
|
|
@@ -1347,7 +1315,7 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1347
1315
|
@c2.one_to_many :attributes, :class => @c1, :validate=>false
|
|
1348
1316
|
n = @c2.new(:id => 1234)
|
|
1349
1317
|
a = @c1.new(:id => 2345)
|
|
1350
|
-
def a.
|
|
1318
|
+
def a.validate() errors.add(:id, 'foo') end
|
|
1351
1319
|
n.add_attribute(a).should == a
|
|
1352
1320
|
n.remove_attribute(a).should == a
|
|
1353
1321
|
end
|
|
@@ -1364,81 +1332,48 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1364
1332
|
|
|
1365
1333
|
it "should use :primary_key option if given" do
|
|
1366
1334
|
@c1.one_to_many :nodes, :class => @c2, :primary_key => :node_id, :key=>:id
|
|
1367
|
-
|
|
1368
|
-
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)"
|
|
1369
1336
|
end
|
|
1370
1337
|
|
|
1371
1338
|
it "should support a select option" do
|
|
1372
1339
|
@c2.one_to_many :attributes, :class => @c1, :select => [:id, :name]
|
|
1373
|
-
|
|
1374
|
-
n = @c2.new(:id => 1234)
|
|
1375
|
-
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)"
|
|
1376
1341
|
end
|
|
1377
1342
|
|
|
1378
1343
|
it "should support a conditions option" do
|
|
1379
1344
|
@c2.one_to_many :attributes, :class => @c1, :conditions => {:a=>32}
|
|
1380
|
-
|
|
1381
|
-
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))"
|
|
1382
1346
|
@c2.one_to_many :attributes, :class => @c1, :conditions => ~:a
|
|
1383
|
-
|
|
1384
|
-
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)"
|
|
1385
1348
|
end
|
|
1386
1349
|
|
|
1387
1350
|
it "should support an order option" do
|
|
1388
1351
|
@c2.one_to_many :attributes, :class => @c1, :order => :kind
|
|
1389
|
-
|
|
1390
|
-
n = @c2.new(:id => 1234)
|
|
1391
|
-
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"
|
|
1392
1353
|
end
|
|
1393
1354
|
|
|
1394
1355
|
it "should support an array for the order option" do
|
|
1395
1356
|
@c2.one_to_many :attributes, :class => @c1, :order => [:kind1, :kind2]
|
|
1396
|
-
|
|
1397
|
-
n = @c2.new(:id => 1234)
|
|
1398
|
-
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"
|
|
1399
1358
|
end
|
|
1400
1359
|
|
|
1401
1360
|
it "should return array with all members of the association" do
|
|
1402
1361
|
@c2.one_to_many :attributes, :class => @c1
|
|
1403
|
-
|
|
1404
|
-
n = @c2.new(:id => 1234)
|
|
1405
|
-
atts = n.attributes
|
|
1406
|
-
atts.should be_a_kind_of(Array)
|
|
1407
|
-
atts.size.should == 1
|
|
1408
|
-
atts.first.should be_a_kind_of(@c1)
|
|
1409
|
-
atts.first.values.should == {}
|
|
1410
|
-
|
|
1411
|
-
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)'
|
|
1412
1363
|
end
|
|
1413
1364
|
|
|
1414
1365
|
it "should accept a block" do
|
|
1415
1366
|
@c2.one_to_many :attributes, :class => @c1 do |ds|
|
|
1416
1367
|
ds.filter(:xxx => @xxx)
|
|
1417
1368
|
end
|
|
1418
|
-
|
|
1419
|
-
n = @c2.new(:id => 1234)
|
|
1420
|
-
atts = n.attributes
|
|
1421
|
-
atts.should be_a_kind_of(Array)
|
|
1422
|
-
atts.size.should == 1
|
|
1423
|
-
atts.first.should be_a_kind_of(@c1)
|
|
1424
|
-
atts.first.values.should == {}
|
|
1425
|
-
|
|
1426
|
-
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))'
|
|
1427
1370
|
end
|
|
1428
1371
|
|
|
1429
1372
|
it "should support :order option with block" do
|
|
1430
1373
|
@c2.one_to_many :attributes, :class => @c1, :order => :kind do |ds|
|
|
1431
1374
|
ds.filter(:xxx => @xxx)
|
|
1432
1375
|
end
|
|
1433
|
-
|
|
1434
|
-
n = @c2.new(:id => 1234)
|
|
1435
|
-
atts = n.attributes
|
|
1436
|
-
atts.should be_a_kind_of(Array)
|
|
1437
|
-
atts.size.should == 1
|
|
1438
|
-
atts.first.should be_a_kind_of(@c1)
|
|
1439
|
-
atts.first.values.should == {}
|
|
1440
|
-
|
|
1441
|
-
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'
|
|
1442
1377
|
end
|
|
1443
1378
|
|
|
1444
1379
|
it "should have the block argument affect the _dataset method" do
|
|
@@ -1450,18 +1385,11 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1450
1385
|
|
|
1451
1386
|
it "should support a :dataset option that is used instead of the default" do
|
|
1452
1387
|
c1 = @c1
|
|
1453
|
-
@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|
|
|
1454
1389
|
ds.filter(:xxx => 5)
|
|
1455
1390
|
end
|
|
1456
|
-
|
|
1457
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'
|
|
1458
|
-
|
|
1459
|
-
atts = n.all_other_attributes
|
|
1460
|
-
atts.should be_a_kind_of(Array)
|
|
1461
|
-
atts.size.should == 1
|
|
1462
|
-
atts.first.should be_a_kind_of(@c1)
|
|
1463
|
-
atts.first.values.should == {}
|
|
1464
|
-
|
|
1392
|
+
@c2.new(:id => 1234).all_other_attributes.should == [@c1.load({})]
|
|
1465
1393
|
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE ((nodeid != 1234) AND (xxx = 5)) ORDER BY a LIMIT 10']
|
|
1466
1394
|
end
|
|
1467
1395
|
|
|
@@ -1479,9 +1407,7 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1479
1407
|
|
|
1480
1408
|
it "should set cached instance variable when accessed" do
|
|
1481
1409
|
@c2.one_to_many :attributes, :class => @c1
|
|
1482
|
-
|
|
1483
1410
|
n = @c2.new(:id => 1234)
|
|
1484
|
-
MODEL_DB.reset
|
|
1485
1411
|
n.associations.include?(:attributes).should == false
|
|
1486
1412
|
atts = n.attributes
|
|
1487
1413
|
atts.should == n.associations[:attributes]
|
|
@@ -1490,9 +1416,7 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1490
1416
|
|
|
1491
1417
|
it "should use cached instance variable if available" do
|
|
1492
1418
|
@c2.one_to_many :attributes, :class => @c1
|
|
1493
|
-
|
|
1494
1419
|
n = @c2.new(:id => 1234)
|
|
1495
|
-
MODEL_DB.reset
|
|
1496
1420
|
n.associations[:attributes] = 42
|
|
1497
1421
|
n.attributes.should == 42
|
|
1498
1422
|
MODEL_DB.sqls.should == []
|
|
@@ -1500,9 +1424,7 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1500
1424
|
|
|
1501
1425
|
it "should not use cached instance variable if asked to reload" do
|
|
1502
1426
|
@c2.one_to_many :attributes, :class => @c1
|
|
1503
|
-
|
|
1504
1427
|
n = @c2.new(:id => 1234)
|
|
1505
|
-
MODEL_DB.reset
|
|
1506
1428
|
n.associations[:attributes] = 42
|
|
1507
1429
|
n.attributes(true).should_not == 42
|
|
1508
1430
|
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE (attributes.node_id = 1234)']
|
|
@@ -1510,10 +1432,8 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1510
1432
|
|
|
1511
1433
|
it "should add item to cached instance variable if it exists when calling add_" do
|
|
1512
1434
|
@c2.one_to_many :attributes, :class => @c1
|
|
1513
|
-
|
|
1514
1435
|
n = @c2.new(:id => 1234)
|
|
1515
|
-
att = @c1.
|
|
1516
|
-
MODEL_DB.reset
|
|
1436
|
+
att = @c1.load(:id => 345)
|
|
1517
1437
|
a = []
|
|
1518
1438
|
n.associations[:attributes] = a
|
|
1519
1439
|
n.add_attribute(att)
|
|
@@ -1535,7 +1455,6 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1535
1455
|
|
|
1536
1456
|
n = @c2.load(:id => 1234)
|
|
1537
1457
|
att = @c1.load(:id => 345)
|
|
1538
|
-
MODEL_DB.reset
|
|
1539
1458
|
a = [att]
|
|
1540
1459
|
n.associations[:attributes] = a
|
|
1541
1460
|
n.remove_attribute(att)
|
|
@@ -1587,13 +1506,9 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1587
1506
|
n = @c2.new(:id => 1234)
|
|
1588
1507
|
atts = n.attributes
|
|
1589
1508
|
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE (attributes.node_id = 1234)']
|
|
1590
|
-
atts.should
|
|
1591
|
-
atts.
|
|
1592
|
-
|
|
1593
|
-
atts.first.values.should == {}
|
|
1594
|
-
atts.first.node.should == n
|
|
1595
|
-
|
|
1596
|
-
MODEL_DB.sqls.length.should == 1
|
|
1509
|
+
atts.should == [@c1.load({})]
|
|
1510
|
+
atts.map{|a| a.node}.should == [n]
|
|
1511
|
+
MODEL_DB.sqls.should == []
|
|
1597
1512
|
end
|
|
1598
1513
|
|
|
1599
1514
|
it "should use an explicit reciprocal instance variable if given" do
|
|
@@ -1602,19 +1517,15 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1602
1517
|
n = @c2.new(:id => 1234)
|
|
1603
1518
|
atts = n.attributes
|
|
1604
1519
|
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE (attributes.node_id = 1234)']
|
|
1605
|
-
atts.should
|
|
1606
|
-
atts.
|
|
1607
|
-
|
|
1608
|
-
atts.first.values.should == {}
|
|
1609
|
-
atts.first.associations[:wxyz].should == n
|
|
1610
|
-
|
|
1611
|
-
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 == []
|
|
1612
1523
|
end
|
|
1613
1524
|
|
|
1614
1525
|
it "should have an remove_all_ method that removes all associations" do
|
|
1615
1526
|
@c2.one_to_many :attributes, :class => @c1
|
|
1616
1527
|
@c2.new(:id => 1234).remove_all_attributes
|
|
1617
|
-
MODEL_DB.sqls.
|
|
1528
|
+
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = NULL WHERE (node_id = 1234)']
|
|
1618
1529
|
end
|
|
1619
1530
|
|
|
1620
1531
|
it "should have remove_all method respect association filters" do
|
|
@@ -1628,13 +1539,15 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1628
1539
|
it "should have the remove_all_ method respect the :primary_key option" do
|
|
1629
1540
|
@c2.one_to_many :attributes, :class => @c1, :primary_key=>:xxx
|
|
1630
1541
|
@c2.new(:id => 1234, :xxx=>5).remove_all_attributes
|
|
1631
|
-
MODEL_DB.sqls.
|
|
1542
|
+
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = NULL WHERE (node_id = 5)']
|
|
1632
1543
|
end
|
|
1633
1544
|
|
|
1634
1545
|
it "should have the remove_all_ method respect composite keys" do
|
|
1635
1546
|
@c2.one_to_many :attributes, :class => @c1, :key=>[:node_id, :y], :primary_key=>[:id, :x]
|
|
1636
1547
|
@c2.new(:id => 1234, :x=>5).remove_all_attributes
|
|
1637
|
-
|
|
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 == []
|
|
1638
1551
|
end
|
|
1639
1552
|
|
|
1640
1553
|
it "remove_all should set the cached instance variable to []" do
|
|
@@ -1648,10 +1561,8 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1648
1561
|
@c2.one_to_many :attributes, :class => @c1
|
|
1649
1562
|
attrib = @c1.new(:id=>3)
|
|
1650
1563
|
node = @c2.new(:id => 1234)
|
|
1651
|
-
|
|
1652
|
-
def d.fetch_rows(s); end
|
|
1564
|
+
@c1.dataset._fetch = [[], [{:id=>3, :node_id=>1234}]]
|
|
1653
1565
|
node.attributes.should == []
|
|
1654
|
-
def attrib.save(*); self end
|
|
1655
1566
|
node.add_attribute(attrib)
|
|
1656
1567
|
node.associations[:attributes].should == [attrib]
|
|
1657
1568
|
node.remove_all_attributes.should == [attrib]
|
|
@@ -1665,15 +1576,12 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1665
1576
|
it "remove_all should remove the current item from all reciprocal instance varaibles if it cached instance variable exists" do
|
|
1666
1577
|
@c2.one_to_many :attributes, :class => @c1
|
|
1667
1578
|
@c1.many_to_one :node, :class => @c2
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
d = @c2.dataset
|
|
1671
|
-
def d.fetch_rows(s); end
|
|
1579
|
+
@c2.dataset._fetch = []
|
|
1580
|
+
@c1.dataset._fetch = [[], [{:id=>3, :node_id=>1234}]]
|
|
1672
1581
|
attrib = @c1.new(:id=>3)
|
|
1673
|
-
node = @c2.
|
|
1582
|
+
node = @c2.load(:id => 1234)
|
|
1674
1583
|
node.attributes.should == []
|
|
1675
1584
|
attrib.node.should == nil
|
|
1676
|
-
def attrib.save(*); self end
|
|
1677
1585
|
node.add_attribute(attrib)
|
|
1678
1586
|
attrib.associations[:node].should == node
|
|
1679
1587
|
node.remove_all_attributes
|
|
@@ -1761,18 +1669,18 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1761
1669
|
h = []
|
|
1762
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]
|
|
1763
1671
|
@c2.class_eval do
|
|
1764
|
-
|
|
1672
|
+
self::Foo = h
|
|
1765
1673
|
def _add_attribute(v)
|
|
1766
|
-
|
|
1674
|
+
model::Foo << 4
|
|
1767
1675
|
end
|
|
1768
1676
|
def _remove_attribute(v)
|
|
1769
|
-
|
|
1677
|
+
model::Foo << 5
|
|
1770
1678
|
end
|
|
1771
1679
|
def blah(x)
|
|
1772
|
-
|
|
1680
|
+
model::Foo << x.pk
|
|
1773
1681
|
end
|
|
1774
1682
|
def blahr(x)
|
|
1775
|
-
|
|
1683
|
+
model::Foo << 6
|
|
1776
1684
|
end
|
|
1777
1685
|
end
|
|
1778
1686
|
p = @c2.load(:id=>10)
|
|
@@ -1788,17 +1696,12 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1788
1696
|
h = []
|
|
1789
1697
|
@c2.one_to_many :attributes, :class => @c1, :after_load=>[proc{|x,y| h << [x.pk, y.collect{|z|z.pk}]}, :al]
|
|
1790
1698
|
@c2.class_eval do
|
|
1791
|
-
|
|
1699
|
+
self::Foo = h
|
|
1792
1700
|
def al(v)
|
|
1793
|
-
v.each{|x|
|
|
1794
|
-
end
|
|
1795
|
-
end
|
|
1796
|
-
@c1.class_eval do
|
|
1797
|
-
def @dataset.fetch_rows(sql)
|
|
1798
|
-
yield({:id=>20})
|
|
1799
|
-
yield({:id=>30})
|
|
1701
|
+
v.each{|x| model::Foo << x.pk}
|
|
1800
1702
|
end
|
|
1801
1703
|
end
|
|
1704
|
+
@c1.dataset._fetch = [{:id=>20}, {:id=>30}]
|
|
1802
1705
|
p = @c2.load(:id=>10, :parent_id=>20)
|
|
1803
1706
|
attributes = p.attributes
|
|
1804
1707
|
h.should == [[10, [20, 30]], 20, 30]
|
|
@@ -1845,23 +1748,13 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1845
1748
|
end
|
|
1846
1749
|
|
|
1847
1750
|
describe Sequel::Model, "many_to_many" do
|
|
1848
|
-
|
|
1849
1751
|
before do
|
|
1850
|
-
MODEL_DB.reset
|
|
1851
|
-
|
|
1852
1752
|
@c1 = Class.new(Sequel::Model(:attributes)) do
|
|
1853
1753
|
unrestrict_primary_key
|
|
1854
1754
|
attr_accessor :yyy
|
|
1855
1755
|
def self.name; 'Attribute'; end
|
|
1856
1756
|
def self.to_s; 'Attribute'; end
|
|
1857
1757
|
columns :id, :y
|
|
1858
|
-
def _refresh(ds)
|
|
1859
|
-
self
|
|
1860
|
-
end
|
|
1861
|
-
|
|
1862
|
-
def self.[](id)
|
|
1863
|
-
load(id.is_a?(Array) ? {:id => id[0], :y => id[1]} : {:id => id})
|
|
1864
|
-
end
|
|
1865
1758
|
end
|
|
1866
1759
|
|
|
1867
1760
|
@c2 = Class.new(Sequel::Model(:nodes)) do
|
|
@@ -1873,98 +1766,61 @@ describe Sequel::Model, "many_to_many" do
|
|
|
1873
1766
|
columns :id, :x
|
|
1874
1767
|
end
|
|
1875
1768
|
@dataset = @c2.dataset
|
|
1769
|
+
@c1.dataset.autoid = 1
|
|
1876
1770
|
|
|
1877
|
-
[@c1, @c2].each
|
|
1878
|
-
|
|
1879
|
-
def fetch_rows(sql)
|
|
1880
|
-
@db << sql
|
|
1881
|
-
yield Hash.new
|
|
1882
|
-
end
|
|
1883
|
-
})
|
|
1884
|
-
end
|
|
1771
|
+
[@c1, @c2].each{|c| c.dataset._fetch = {}}
|
|
1772
|
+
MODEL_DB.reset
|
|
1885
1773
|
end
|
|
1886
1774
|
|
|
1887
1775
|
it "should use implicit key values and join table if omitted" do
|
|
1888
1776
|
@c2.many_to_many :attributes, :class => @c1
|
|
1889
|
-
|
|
1890
|
-
n = @c2.new(:id => 1234)
|
|
1891
|
-
a = n.attributes_dataset
|
|
1892
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
|
1893
|
-
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))'
|
|
1894
1778
|
end
|
|
1895
1779
|
|
|
1896
1780
|
it "should use implicit class if omitted" do
|
|
1897
|
-
|
|
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)
|
|
1898
1787
|
end
|
|
1899
|
-
|
|
1900
|
-
@c2.many_to_many :tags
|
|
1901
|
-
|
|
1902
|
-
n = @c2.new(:id => 1234)
|
|
1903
|
-
a = n.tags_dataset
|
|
1904
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
|
1905
|
-
a.sql.should == 'SELECT tags.* FROM tags INNER JOIN nodes_tags ON ((nodes_tags.tag_id = tags.id) AND (nodes_tags.node_id = 1234))'
|
|
1906
1788
|
end
|
|
1907
1789
|
|
|
1908
1790
|
it "should use class inside module if given as a string" do
|
|
1909
|
-
|
|
1910
|
-
|
|
1791
|
+
begin
|
|
1792
|
+
module ::Historical
|
|
1793
|
+
class Tag < Sequel::Model; end
|
|
1911
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)
|
|
1912
1799
|
end
|
|
1913
|
-
|
|
1914
|
-
@c2.many_to_many :tags, :class=>'::Historical::Tag'
|
|
1915
|
-
|
|
1916
|
-
n = @c2.new(:id => 1234)
|
|
1917
|
-
a = n.tags_dataset
|
|
1918
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
|
1919
|
-
a.sql.should == 'SELECT tags.* FROM tags INNER JOIN nodes_tags ON ((nodes_tags.tag_id = tags.id) AND (nodes_tags.node_id = 1234))'
|
|
1920
1800
|
end
|
|
1921
1801
|
|
|
1922
1802
|
it "should use explicit key values and join table if given" do
|
|
1923
1803
|
@c2.many_to_many :attributes, :class => @c1, :left_key => :nodeid, :right_key => :attributeid, :join_table => :attribute2node
|
|
1924
|
-
|
|
1925
|
-
n = @c2.new(:id => 1234)
|
|
1926
|
-
a = n.attributes_dataset
|
|
1927
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
|
1928
|
-
a.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attribute2node ON ((attribute2node.attributeid = attributes.id) AND (attribute2node.nodeid = 1234))'
|
|
1929
|
-
end
|
|
1930
|
-
|
|
1931
|
-
it "should handle an aliased join table when eager loading" do
|
|
1932
|
-
r = @c2.many_to_many(:attributes, :class => @c1, :join_table => :attribute2node___attributes_nodes)
|
|
1933
|
-
|
|
1934
|
-
a = @c2.eager_loading_dataset(r, @c2.dataset, [:id], nil)
|
|
1935
|
-
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))'
|
|
1936
1805
|
end
|
|
1937
1806
|
|
|
1938
1807
|
it "should support a conditions option" do
|
|
1939
1808
|
@c2.many_to_many :attributes, :class => @c1, :conditions => {:a=>32}
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
|
1943
|
-
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
|
+
|
|
1944
1811
|
@c2.many_to_many :attributes, :class => @c1, :conditions => ['a = ?', 32]
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
|
1948
|
-
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)'
|
|
1949
|
-
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({})]
|
|
1950
1814
|
end
|
|
1951
1815
|
|
|
1952
1816
|
it "should support an order option" do
|
|
1953
1817
|
@c2.many_to_many :attributes, :class => @c1, :order => :blah
|
|
1954
|
-
|
|
1955
|
-
n = @c2.new(:id => 1234)
|
|
1956
|
-
a = n.attributes_dataset
|
|
1957
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
|
1958
|
-
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'
|
|
1959
1819
|
end
|
|
1960
1820
|
|
|
1961
1821
|
it "should support an array for the order option" do
|
|
1962
1822
|
@c2.many_to_many :attributes, :class => @c1, :order => [:blah1, :blah2]
|
|
1963
|
-
|
|
1964
|
-
n = @c2.new(:id => 1234)
|
|
1965
|
-
a = n.attributes_dataset
|
|
1966
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
|
1967
|
-
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'
|
|
1968
1824
|
end
|
|
1969
1825
|
|
|
1970
1826
|
it "should support :left_primary_key and :right_primary_key options" do
|
|
@@ -1999,19 +1855,13 @@ describe Sequel::Model, "many_to_many" do
|
|
|
1999
1855
|
it "should support a select option" do
|
|
2000
1856
|
@c2.many_to_many :attributes, :class => @c1, :select => :blah
|
|
2001
1857
|
|
|
2002
|
-
|
|
2003
|
-
a = n.attributes_dataset
|
|
2004
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
|
2005
|
-
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))'
|
|
2006
1859
|
end
|
|
2007
1860
|
|
|
2008
1861
|
it "should support an array for the select option" do
|
|
2009
1862
|
@c2.many_to_many :attributes, :class => @c1, :select => [:attributes.*, :attribute_nodes__blah2]
|
|
2010
1863
|
|
|
2011
|
-
|
|
2012
|
-
a = n.attributes_dataset
|
|
2013
|
-
a.should be_a_kind_of(Sequel::Dataset)
|
|
2014
|
-
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))'
|
|
2015
1865
|
end
|
|
2016
1866
|
|
|
2017
1867
|
it "should accept a block" do
|
|
@@ -2021,11 +1871,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2021
1871
|
|
|
2022
1872
|
n = @c2.new(:id => 1234)
|
|
2023
1873
|
n.xxx = 555
|
|
2024
|
-
|
|
2025
|
-
a.should be_a_kind_of(Array)
|
|
2026
|
-
a.size.should == 1
|
|
2027
|
-
a.first.should be_a_kind_of(@c1)
|
|
2028
|
-
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)'
|
|
2029
1875
|
end
|
|
2030
1876
|
|
|
2031
1877
|
it "should allow the :order option while accepting a block" do
|
|
@@ -2035,20 +1881,9 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2035
1881
|
|
|
2036
1882
|
n = @c2.new(:id => 1234)
|
|
2037
1883
|
n.xxx = 555
|
|
2038
|
-
|
|
2039
|
-
a.should be_a_kind_of(Array)
|
|
2040
|
-
a.size.should == 1
|
|
2041
|
-
a.first.should be_a_kind_of(@c1)
|
|
2042
|
-
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'
|
|
2043
1885
|
end
|
|
2044
1886
|
|
|
2045
|
-
it "should have the block argument affect the _dataset method" do
|
|
2046
|
-
@c2.many_to_many :attributes, :class => @c1 do |ds|
|
|
2047
|
-
ds.filter(:xxx => 456)
|
|
2048
|
-
end
|
|
2049
|
-
@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)'
|
|
2050
|
-
end
|
|
2051
|
-
|
|
2052
1887
|
it "should support a :dataset option that is used instead of the default" do
|
|
2053
1888
|
c1 = @c1
|
|
2054
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|
|
|
@@ -2058,11 +1893,8 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2058
1893
|
n = @c2.new(:id => 1234)
|
|
2059
1894
|
n.xxx = 555
|
|
2060
1895
|
n.attributes_dataset.sql.should == 'SELECT * FROM attributes NATURAL JOIN an WHERE ((an.nodeid = 1234) AND (xxx = 555)) ORDER BY a LIMIT 10'
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
a.size.should == 1
|
|
2064
|
-
a.first.should be_a_kind_of(@c1)
|
|
2065
|
-
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']
|
|
2066
1898
|
end
|
|
2067
1899
|
|
|
2068
1900
|
it "should support a :limit option" do
|
|
@@ -2077,15 +1909,32 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2077
1909
|
@c2.new(:id => 1234).attributes_dataset.opts[:eager].should == {:attributes=>nil}
|
|
2078
1910
|
end
|
|
2079
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
|
+
|
|
2080
1928
|
it "should define an add_ method that works on existing records" do
|
|
2081
1929
|
@c2.many_to_many :attributes, :class => @c1
|
|
2082
1930
|
|
|
2083
1931
|
n = @c2.load(:id => 1234)
|
|
2084
1932
|
a = @c1.load(:id => 2345)
|
|
2085
|
-
a.should ==
|
|
1933
|
+
n.add_attribute(a).should == a
|
|
1934
|
+
sqls = MODEL_DB.sqls
|
|
2086
1935
|
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 2345)',
|
|
2087
|
-
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (2345, 1234)'
|
|
2088
|
-
|
|
1936
|
+
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (2345, 1234)'].should(include(sqls.shift))
|
|
1937
|
+
sqls.should == []
|
|
2089
1938
|
end
|
|
2090
1939
|
|
|
2091
1940
|
it "should define an add_ method that works with a primary key" do
|
|
@@ -2093,21 +1942,25 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2093
1942
|
|
|
2094
1943
|
n = @c2.load(:id => 1234)
|
|
2095
1944
|
a = @c1.load(:id => 2345)
|
|
2096
|
-
|
|
1945
|
+
@c1.dataset._fetch = {:id=>2345}
|
|
1946
|
+
n.add_attribute(2345).should == a
|
|
1947
|
+
sqls = MODEL_DB.sqls
|
|
2097
1948
|
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 2345)',
|
|
2098
|
-
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (2345, 1234)'
|
|
2099
|
-
|
|
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"]
|
|
2100
1951
|
end
|
|
2101
1952
|
|
|
2102
1953
|
it "should allow passing a hash to the add_ method which creates a new record" do
|
|
2103
1954
|
@c2.many_to_many :attributes, :class => @c1
|
|
2104
1955
|
|
|
2105
1956
|
n = @c2.load(:id => 1234)
|
|
2106
|
-
@c1.
|
|
2107
|
-
|
|
1957
|
+
@c1.dataset._fetch = {:id=>1}
|
|
1958
|
+
n.add_attribute(:id => 1).should == @c1.load(:id => 1)
|
|
1959
|
+
sqls = MODEL_DB.sqls
|
|
2108
1960
|
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 1)',
|
|
2109
1961
|
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (1, 1234)'
|
|
2110
|
-
].should(include(
|
|
1962
|
+
].should(include(sqls.pop))
|
|
1963
|
+
sqls.should == ['INSERT INTO attributes (id) VALUES (1)', "SELECT * FROM attributes WHERE (id = 1) LIMIT 1"]
|
|
2111
1964
|
end
|
|
2112
1965
|
|
|
2113
1966
|
it "should define a remove_ method that works on existing records" do
|
|
@@ -2115,8 +1968,8 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2115
1968
|
|
|
2116
1969
|
n = @c2.new(:id => 1234)
|
|
2117
1970
|
a = @c1.new(:id => 2345)
|
|
2118
|
-
a.should ==
|
|
2119
|
-
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))']
|
|
2120
1973
|
end
|
|
2121
1974
|
|
|
2122
1975
|
it "should raise an error in the add_ method if the passed associated object is not of the correct type" do
|
|
@@ -2127,13 +1980,8 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2127
1980
|
it "should accept a primary key for the remove_ method and remove an existing record" do
|
|
2128
1981
|
@c2.many_to_many :attributes, :class => @c1
|
|
2129
1982
|
n = @c2.new(:id => 1234)
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
db << sql
|
|
2133
|
-
yield({:id=>234})
|
|
2134
|
-
end
|
|
2135
|
-
MODEL_DB.reset
|
|
2136
|
-
@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)
|
|
2137
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",
|
|
2138
1986
|
"DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (attribute_id = 234))"]
|
|
2139
1987
|
end
|
|
@@ -2148,10 +1996,12 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2148
1996
|
|
|
2149
1997
|
n = @c2.load(:id => 1234).set(:xxx=>5)
|
|
2150
1998
|
a = @c1.load(:id => 2345).set(:yyy=>8)
|
|
2151
|
-
a.should ==
|
|
1999
|
+
n.add_attribute(a).should == a
|
|
2000
|
+
sqls = MODEL_DB.sqls
|
|
2152
2001
|
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (5, 8)',
|
|
2153
2002
|
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (8, 5)'
|
|
2154
|
-
].should(include(
|
|
2003
|
+
].should(include(sqls.pop))
|
|
2004
|
+
sqls.should == []
|
|
2155
2005
|
end
|
|
2156
2006
|
|
|
2157
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
|
|
@@ -2170,7 +2020,9 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2170
2020
|
n = @c2.load(:id => 1234, :x=>5)
|
|
2171
2021
|
a = @c1.load(:id => 2345, :y=>8)
|
|
2172
2022
|
a.should == n.add_attribute(a)
|
|
2173
|
-
|
|
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 == []
|
|
2174
2026
|
m.should_not == nil
|
|
2175
2027
|
map = {'l1'=>1234, 'l2'=>5, 'r1'=>2345, 'r2'=>8}
|
|
2176
2028
|
%w[l1 l2 r1 r2].each do |x|
|
|
@@ -2187,10 +2039,15 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2187
2039
|
|
|
2188
2040
|
it "should have the add_ method respect composite keys" do
|
|
2189
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]
|
|
2190
2043
|
n = @c2.load(:id => 1234, :x=>5)
|
|
2191
2044
|
a = @c1.load(:id => 2345, :y=>8)
|
|
2192
|
-
|
|
2193
|
-
|
|
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 == []
|
|
2194
2051
|
end
|
|
2195
2052
|
|
|
2196
2053
|
it "should have the remove_ method respect the :left_primary_key and :right_primary_key options" do
|
|
@@ -2198,8 +2055,8 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2198
2055
|
|
|
2199
2056
|
n = @c2.new(:id => 1234, :xxx=>5)
|
|
2200
2057
|
a = @c1.new(:id => 2345, :yyy=>8)
|
|
2201
|
-
a.should ==
|
|
2202
|
-
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))']
|
|
2203
2060
|
end
|
|
2204
2061
|
|
|
2205
2062
|
it "should have the remove_ method respect composite keys" do
|
|
@@ -2214,17 +2071,12 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2214
2071
|
@c1.set_primary_key [:id, :y]
|
|
2215
2072
|
@c2.many_to_many :attributes, :class => @c1
|
|
2216
2073
|
n = @c2.new(:id => 1234)
|
|
2217
|
-
|
|
2218
|
-
def ds.fetch_rows(sql)
|
|
2219
|
-
db << sql
|
|
2220
|
-
yield({:id=>234, :y=>8})
|
|
2221
|
-
end
|
|
2222
|
-
MODEL_DB.reset
|
|
2074
|
+
@c1.dataset._fetch = {:id=>234, :y=>8}
|
|
2223
2075
|
@c1.load(:id => 234, :y=>8).should == n.remove_attribute([234, 8])
|
|
2076
|
+
sqls = MODEL_DB.sqls
|
|
2224
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",
|
|
2225
|
-
"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(
|
|
2226
|
-
|
|
2227
|
-
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))"]
|
|
2228
2080
|
end
|
|
2229
2081
|
|
|
2230
2082
|
it "should raise an error if the model object doesn't have a valid primary key" do
|
|
@@ -2242,6 +2094,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2242
2094
|
n = @c1.new
|
|
2243
2095
|
a = @c2.load(:id=>123)
|
|
2244
2096
|
n.new?.should == true
|
|
2097
|
+
@c1.dataset._fetch = {:id=>1}
|
|
2245
2098
|
a.add_attribute(n)
|
|
2246
2099
|
n.new?.should == false
|
|
2247
2100
|
end
|
|
@@ -2250,7 +2103,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2250
2103
|
@c2.many_to_many :attributes, :class => @c1
|
|
2251
2104
|
n = @c1.new
|
|
2252
2105
|
a = @c2.load(:id=>123)
|
|
2253
|
-
def n.
|
|
2106
|
+
def n.validate() errors.add(:id, 'foo') end
|
|
2254
2107
|
proc{a.add_attribute(n)}.should raise_error(Sequel::ValidationFailed)
|
|
2255
2108
|
end
|
|
2256
2109
|
|
|
@@ -2259,7 +2112,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2259
2112
|
n = @c1.new
|
|
2260
2113
|
n.raise_on_save_failure = false
|
|
2261
2114
|
a = @c2.load(:id=>123)
|
|
2262
|
-
def n.
|
|
2115
|
+
def n.validate() errors.add(:id, 'foo') end
|
|
2263
2116
|
proc{a.add_attribute(n)}.should raise_error(Sequel::Error)
|
|
2264
2117
|
end
|
|
2265
2118
|
|
|
@@ -2267,7 +2120,8 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2267
2120
|
@c2.many_to_many :attributes, :class => @c1, :validate=>false
|
|
2268
2121
|
n = @c1.new
|
|
2269
2122
|
a = @c2.load(:id=>123)
|
|
2270
|
-
def n.
|
|
2123
|
+
def n.validate() errors.add(:id, 'foo') end
|
|
2124
|
+
@c1.dataset._fetch = {:id=>1}
|
|
2271
2125
|
a.add_attribute(n)
|
|
2272
2126
|
n.new?.should == false
|
|
2273
2127
|
end
|
|
@@ -2282,31 +2136,23 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2282
2136
|
it "should provide an array with all members of the association" do
|
|
2283
2137
|
@c2.many_to_many :attributes, :class => @c1
|
|
2284
2138
|
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
atts.should be_a_kind_of(Array)
|
|
2288
|
-
atts.size.should == 1
|
|
2289
|
-
atts.first.should be_a_kind_of(@c1)
|
|
2290
|
-
|
|
2291
|
-
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))']
|
|
2292
2141
|
end
|
|
2293
2142
|
|
|
2294
2143
|
it "should set cached instance variable when accessed" do
|
|
2295
2144
|
@c2.many_to_many :attributes, :class => @c1
|
|
2296
2145
|
|
|
2297
2146
|
n = @c2.new(:id => 1234)
|
|
2298
|
-
MODEL_DB.reset
|
|
2299
2147
|
n.associations.include?(:attributes).should == false
|
|
2300
2148
|
atts = n.attributes
|
|
2301
2149
|
atts.should == n.associations[:attributes]
|
|
2302
|
-
MODEL_DB.sqls.length.should == 1
|
|
2303
2150
|
end
|
|
2304
2151
|
|
|
2305
2152
|
it "should use cached instance variable if available" do
|
|
2306
2153
|
@c2.many_to_many :attributes, :class => @c1
|
|
2307
2154
|
|
|
2308
2155
|
n = @c2.new(:id => 1234)
|
|
2309
|
-
MODEL_DB.reset
|
|
2310
2156
|
n.associations[:attributes] = 42
|
|
2311
2157
|
n.attributes.should == 42
|
|
2312
2158
|
MODEL_DB.sqls.should == []
|
|
@@ -2316,18 +2162,16 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2316
2162
|
@c2.many_to_many :attributes, :class => @c1
|
|
2317
2163
|
|
|
2318
2164
|
n = @c2.new(:id => 1234)
|
|
2319
|
-
MODEL_DB.reset
|
|
2320
2165
|
n.associations[:attributes] = 42
|
|
2321
2166
|
n.attributes(true).should_not == 42
|
|
2322
|
-
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))"]
|
|
2323
2168
|
end
|
|
2324
2169
|
|
|
2325
2170
|
it "should add item to cached instance variable if it exists when calling add_" do
|
|
2326
2171
|
@c2.many_to_many :attributes, :class => @c1
|
|
2327
2172
|
|
|
2328
2173
|
n = @c2.new(:id => 1234)
|
|
2329
|
-
att = @c1.
|
|
2330
|
-
MODEL_DB.reset
|
|
2174
|
+
att = @c1.load(:id => 345)
|
|
2331
2175
|
a = []
|
|
2332
2176
|
n.associations[:attributes] = a
|
|
2333
2177
|
n.add_attribute(att)
|
|
@@ -2339,7 +2183,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2339
2183
|
@c1.many_to_many :nodes, :class => @c2
|
|
2340
2184
|
|
|
2341
2185
|
n = @c2.new(:id => 1234)
|
|
2342
|
-
att = @c1.
|
|
2186
|
+
att = @c1.load(:id => 345)
|
|
2343
2187
|
att.associations[:nodes] = []
|
|
2344
2188
|
n.add_attribute(att)
|
|
2345
2189
|
att.nodes.should == [n]
|
|
@@ -2349,8 +2193,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2349
2193
|
@c2.many_to_many :attributes, :class => @c1
|
|
2350
2194
|
|
|
2351
2195
|
n = @c2.new(:id => 1234)
|
|
2352
|
-
att = @c1.
|
|
2353
|
-
MODEL_DB.reset
|
|
2196
|
+
att = @c1.load(:id => 345)
|
|
2354
2197
|
a = [att]
|
|
2355
2198
|
n.associations[:attributes] = a
|
|
2356
2199
|
n.remove_attribute(att)
|
|
@@ -2397,13 +2240,13 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2397
2240
|
it "should have an remove_all_ method that removes all associations" do
|
|
2398
2241
|
@c2.many_to_many :attributes, :class => @c1
|
|
2399
2242
|
@c2.new(:id => 1234).remove_all_attributes
|
|
2400
|
-
MODEL_DB.sqls.
|
|
2243
|
+
MODEL_DB.sqls.should == ['DELETE FROM attributes_nodes WHERE (node_id = 1234)']
|
|
2401
2244
|
end
|
|
2402
2245
|
|
|
2403
2246
|
it "should have the remove_all_ method respect the :left_primary_key option" do
|
|
2404
2247
|
@c2.many_to_many :attributes, :class => @c1, :left_primary_key=>:xxx
|
|
2405
2248
|
@c2.new(:id => 1234, :xxx=>5).remove_all_attributes
|
|
2406
|
-
MODEL_DB.sqls.
|
|
2249
|
+
MODEL_DB.sqls.should == ['DELETE FROM attributes_nodes WHERE (node_id = 5)']
|
|
2407
2250
|
end
|
|
2408
2251
|
|
|
2409
2252
|
it "should have the remove_all_ method respect composite keys" do
|
|
@@ -2421,10 +2264,9 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2421
2264
|
|
|
2422
2265
|
it "remove_all should return the array of previously associated items if the cached instance variable exists" do
|
|
2423
2266
|
@c2.many_to_many :attributes, :class => @c1
|
|
2424
|
-
attrib = @c1.
|
|
2425
|
-
node = @c2.
|
|
2426
|
-
|
|
2427
|
-
def d.fetch_rows(s); end
|
|
2267
|
+
attrib = @c1.load(:id=>3)
|
|
2268
|
+
node = @c2.load(:id => 1234)
|
|
2269
|
+
@c1.dataset._fetch = []
|
|
2428
2270
|
node.attributes.should == []
|
|
2429
2271
|
node.add_attribute(attrib)
|
|
2430
2272
|
node.associations[:attributes].should == [attrib]
|
|
@@ -2439,11 +2281,9 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2439
2281
|
it "remove_all should remove the current item from all reciprocal instance varaibles if it cached instance variable exists" do
|
|
2440
2282
|
@c2.many_to_many :attributes, :class => @c1
|
|
2441
2283
|
@c1.many_to_many :nodes, :class => @c2
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
def d.fetch_rows(s); end
|
|
2446
|
-
attrib = @c1.new(:id=>3)
|
|
2284
|
+
@c1.dataset._fetch = []
|
|
2285
|
+
@c2.dataset._fetch = []
|
|
2286
|
+
attrib = @c1.load(:id=>3)
|
|
2447
2287
|
node = @c2.new(:id => 1234)
|
|
2448
2288
|
node.attributes.should == []
|
|
2449
2289
|
attrib.nodes.should == []
|
|
@@ -2459,8 +2299,9 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2459
2299
|
o.add_attribute(@c1.load(:id=>44))
|
|
2460
2300
|
o.remove_attribute(@c1.load(:id=>45))
|
|
2461
2301
|
o.remove_all_attributes
|
|
2462
|
-
MODEL_DB.sqls
|
|
2463
|
-
|
|
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))",
|
|
2464
2305
|
"DELETE FROM attributes_nodes WHERE ((x = 123) AND (node_id = 1234))"]
|
|
2465
2306
|
end
|
|
2466
2307
|
|
|
@@ -2543,18 +2384,18 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2543
2384
|
h = []
|
|
2544
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]
|
|
2545
2386
|
@c2.class_eval do
|
|
2546
|
-
|
|
2387
|
+
self::Foo = h
|
|
2547
2388
|
def _add_attribute(v)
|
|
2548
|
-
|
|
2389
|
+
model::Foo << 4
|
|
2549
2390
|
end
|
|
2550
2391
|
def _remove_attribute(v)
|
|
2551
|
-
|
|
2392
|
+
model::Foo << 5
|
|
2552
2393
|
end
|
|
2553
2394
|
def blah(x)
|
|
2554
|
-
|
|
2395
|
+
model::Foo << x.pk
|
|
2555
2396
|
end
|
|
2556
2397
|
def blahr(x)
|
|
2557
|
-
|
|
2398
|
+
model::Foo << 6
|
|
2558
2399
|
end
|
|
2559
2400
|
end
|
|
2560
2401
|
p = @c2.load(:id=>10)
|
|
@@ -2570,17 +2411,12 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2570
2411
|
h = []
|
|
2571
2412
|
@c2.many_to_many :attributes, :class => @c1, :after_load=>[proc{|x,y| h << [x.pk, y.collect{|z|z.pk}]}, :al]
|
|
2572
2413
|
@c2.class_eval do
|
|
2573
|
-
|
|
2414
|
+
self::Foo = h
|
|
2574
2415
|
def al(v)
|
|
2575
|
-
v.each{|x|
|
|
2576
|
-
end
|
|
2577
|
-
end
|
|
2578
|
-
@c1.class_eval do
|
|
2579
|
-
def @dataset.fetch_rows(sql)
|
|
2580
|
-
yield({:id=>20})
|
|
2581
|
-
yield({:id=>30})
|
|
2416
|
+
v.each{|x| model::Foo << x.pk}
|
|
2582
2417
|
end
|
|
2583
2418
|
end
|
|
2419
|
+
@c1.dataset._fetch = [{:id=>20}, {:id=>30}]
|
|
2584
2420
|
p = @c2.load(:id=>10, :parent_id=>20)
|
|
2585
2421
|
attributes = p.attributes
|
|
2586
2422
|
h.should == [[10, [20, 30]], 20, 30]
|
|
@@ -2623,14 +2459,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2623
2459
|
|
|
2624
2460
|
it "should support a :uniq option that removes duplicates from the association" do
|
|
2625
2461
|
@c2.many_to_many :attributes, :class => @c1, :uniq=>true
|
|
2626
|
-
@c1.
|
|
2627
|
-
def @dataset.fetch_rows(sql)
|
|
2628
|
-
yield({:id=>20})
|
|
2629
|
-
yield({:id=>30})
|
|
2630
|
-
yield({:id=>20})
|
|
2631
|
-
yield({:id=>30})
|
|
2632
|
-
end
|
|
2633
|
-
end
|
|
2462
|
+
@c1.dataset._fetch = [{:id=>20}, {:id=>30}, {:id=>20}, {:id=>30}]
|
|
2634
2463
|
@c2.load(:id=>10, :parent_id=>20).attributes.should == [@c1.load(:id=>20), @c1.load(:id=>30)]
|
|
2635
2464
|
end
|
|
2636
2465
|
|
|
@@ -2651,76 +2480,435 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2651
2480
|
@c2.many_to_many :attributes, :class => @c1 do |ds|
|
|
2652
2481
|
ds.filter(:join_table_att=>3)
|
|
2653
2482
|
end
|
|
2654
|
-
@c1.dataset.
|
|
2655
|
-
def fetch_rows(sql, &block)
|
|
2656
|
-
db.sqls << sql
|
|
2657
|
-
yield(:id=>2)
|
|
2658
|
-
end
|
|
2659
|
-
end
|
|
2483
|
+
@c1.dataset._fetch = {:id=>2}
|
|
2660
2484
|
@c2.load(:id=>1).remove_attribute(2)
|
|
2661
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",
|
|
2662
2486
|
"DELETE FROM attributes_nodes WHERE ((node_id = 1) AND (attribute_id = 2))"]
|
|
2663
2487
|
end
|
|
2664
2488
|
end
|
|
2665
2489
|
|
|
2666
|
-
describe
|
|
2490
|
+
describe "Filtering by associations" do
|
|
2667
2491
|
before do
|
|
2668
|
-
|
|
2669
|
-
@
|
|
2670
|
-
|
|
2671
|
-
|
|
2492
|
+
@Album = Class.new(Sequel::Model(:albums))
|
|
2493
|
+
artist = @Artist = Class.new(Sequel::Model(:artists))
|
|
2494
|
+
tag = @Tag = Class.new(Sequel::Model(:tags))
|
|
2495
|
+
track = @Track = Class.new(Sequel::Model(:tracks))
|
|
2496
|
+
album_info = @AlbumInfo = Class.new(Sequel::Model(:album_infos))
|
|
2497
|
+
@Artist.columns :id, :id1, :id2
|
|
2498
|
+
@Tag.columns :id, :tid1, :tid2
|
|
2499
|
+
@Track.columns :id, :album_id, :album_id1, :album_id2
|
|
2500
|
+
@AlbumInfo.columns :id, :album_id, :album_id1, :album_id2
|
|
2501
|
+
@Album.class_eval do
|
|
2502
|
+
columns :id, :id1, :id2, :artist_id, :artist_id1, :artist_id2
|
|
2503
|
+
many_to_one :artist, :class=>artist
|
|
2504
|
+
one_to_many :tracks, :class=>track, :key=>:album_id
|
|
2505
|
+
one_to_one :album_info, :class=>album_info, :key=>:album_id
|
|
2506
|
+
many_to_many :tags, :class=>tag, :left_key=>:album_id, :join_table=>:albums_tags
|
|
2507
|
+
|
|
2508
|
+
many_to_one :cartist, :class=>artist, :key=>[:artist_id1, :artist_id2], :primary_key=>[:id1, :id2]
|
|
2509
|
+
one_to_many :ctracks, :class=>track, :key=>[:album_id1, :album_id2], :primary_key=>[:id1, :id2]
|
|
2510
|
+
one_to_one :calbum_info, :class=>album_info, :key=>[:album_id1, :album_id2], :primary_key=>[:id1, :id2]
|
|
2511
|
+
many_to_many :ctags, :class=>tag, :left_key=>[:album_id1, :album_id2], :left_primary_key=>[:id1, :id2], :right_key=>[:tag_id1, :tag_id2], :right_primary_key=>[:tid1, :tid2], :join_table=>:albums_tags
|
|
2672
2512
|
end
|
|
2673
2513
|
end
|
|
2674
|
-
|
|
2675
|
-
it "#all_association_reflections should include all association reflection hashes" do
|
|
2676
|
-
@c1.all_association_reflections.should == []
|
|
2677
2514
|
|
|
2678
|
-
|
|
2679
|
-
@
|
|
2680
|
-
|
|
2681
|
-
|
|
2515
|
+
it "should be able to filter on many_to_one associations" do
|
|
2516
|
+
@Album.filter(:artist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (artist_id = 3)'
|
|
2517
|
+
end
|
|
2518
|
+
|
|
2519
|
+
it "should be able to filter on one_to_many associations" do
|
|
2520
|
+
@Album.filter(:tracks=>@Track.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE (id = 3)'
|
|
2521
|
+
end
|
|
2522
|
+
|
|
2523
|
+
it "should be able to filter on one_to_one associations" do
|
|
2524
|
+
@Album.filter(:album_info=>@AlbumInfo.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE (id = 3)'
|
|
2525
|
+
end
|
|
2526
|
+
|
|
2527
|
+
it "should be able to filter on many_to_many associations" do
|
|
2528
|
+
@Album.filter(:tags=>@Tag.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (id IN (SELECT album_id FROM albums_tags WHERE ((tag_id = 3) AND (album_id IS NOT NULL))))'
|
|
2529
|
+
end
|
|
2530
|
+
|
|
2531
|
+
it "should be able to filter on many_to_one associations with composite keys" do
|
|
2532
|
+
@Album.filter(:cartist=>@Artist.load(:id1=>3, :id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((artist_id1 = 3) AND (artist_id2 = 4))'
|
|
2533
|
+
end
|
|
2534
|
+
|
|
2535
|
+
it "should be able to filter on one_to_many associations with composite keys" do
|
|
2536
|
+
@Album.filter(:ctracks=>@Track.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((id1 = 3) AND (id2 = 4))'
|
|
2537
|
+
end
|
|
2538
|
+
|
|
2539
|
+
it "should be able to filter on one_to_one associations with composite keys" do
|
|
2540
|
+
@Album.filter(:calbum_info=>@AlbumInfo.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((id1 = 3) AND (id2 = 4))'
|
|
2541
|
+
end
|
|
2542
|
+
|
|
2543
|
+
it "should be able to filter on many_to_many associations with composite keys" do
|
|
2544
|
+
@Album.filter(:ctags=>@Tag.load(:tid1=>3, :tid2=>4)).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN (SELECT album_id1, album_id2 FROM albums_tags WHERE ((tag_id1 = 3) AND (tag_id2 = 4) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL))))'
|
|
2545
|
+
end
|
|
2546
|
+
|
|
2547
|
+
it "should work inside a complex filter" do
|
|
2548
|
+
artist = @Artist.load(:id=>3)
|
|
2549
|
+
@Album.filter{foo & {:artist=>artist}}.sql.should == 'SELECT * FROM albums WHERE (foo AND (artist_id = 3))'
|
|
2550
|
+
track = @Track.load(:album_id=>4)
|
|
2551
|
+
@Album.filter{foo & [[:artist, artist], [:tracks, track]]}.sql.should == 'SELECT * FROM albums WHERE (foo AND (artist_id = 3) AND (id = 4))'
|
|
2552
|
+
end
|
|
2553
|
+
|
|
2554
|
+
it "should raise for an invalid association name" do
|
|
2555
|
+
proc{@Album.filter(:foo=>@Artist.load(:id=>3)).sql}.should raise_error(Sequel::Error)
|
|
2556
|
+
end
|
|
2557
|
+
|
|
2558
|
+
it "should raise for an invalid association type" do
|
|
2559
|
+
@Album.many_to_many :iatags, :clone=>:tags
|
|
2560
|
+
@Album.association_reflection(:iatags)[:type] = :foo
|
|
2561
|
+
proc{@Album.filter(:iatags=>@Tag.load(:id=>3)).sql}.should raise_error(Sequel::Error)
|
|
2562
|
+
end
|
|
2563
|
+
|
|
2564
|
+
it "should raise for an invalid associated object class " do
|
|
2565
|
+
proc{@Album.filter(:tags=>@Artist.load(:id=>3)).sql}.should raise_error(Sequel::Error)
|
|
2566
|
+
end
|
|
2567
|
+
|
|
2568
|
+
it "should raise for an invalid associated object class when multiple objects are used" do
|
|
2569
|
+
proc{@Album.filter(:tags=>[@Tag.load(:id=>3), @Artist.load(:id=>3)]).sql}.should raise_error(Sequel::Error)
|
|
2570
|
+
end
|
|
2571
|
+
|
|
2572
|
+
it "should correctly handle case when a multiple value association is used" do
|
|
2573
|
+
proc{@Album.filter(:tags=>[@Tag.load(:id=>3), @Artist.load(:id=>3)]).sql}.should raise_error(Sequel::Error)
|
|
2574
|
+
end
|
|
2575
|
+
|
|
2576
|
+
it "should not affect non-association IN/NOT IN filtering with an empty array" do
|
|
2577
|
+
@Album.filter(:tag_id=>[]).sql.should == 'SELECT * FROM albums WHERE (tag_id != tag_id)'
|
|
2578
|
+
@Album.exclude(:tag_id=>[]).sql.should == 'SELECT * FROM albums WHERE (1 = 1)'
|
|
2579
|
+
end
|
|
2580
|
+
|
|
2581
|
+
it "should work correctly in subclasses" do
|
|
2582
|
+
c = Class.new(@Album)
|
|
2583
|
+
c.many_to_one :sartist, :class=>@Artist
|
|
2584
|
+
c.filter(:sartist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (sartist_id = 3)'
|
|
2585
|
+
end
|
|
2586
|
+
|
|
2587
|
+
it "should be able to exclude on many_to_one associations" do
|
|
2588
|
+
@Album.exclude(:artist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE ((artist_id != 3) OR (artist_id IS NULL))'
|
|
2589
|
+
end
|
|
2590
|
+
|
|
2591
|
+
it "should be able to exclude on one_to_many associations" do
|
|
2592
|
+
@Album.exclude(:tracks=>@Track.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE ((id != 3) OR (id IS NULL))'
|
|
2593
|
+
end
|
|
2594
|
+
|
|
2595
|
+
it "should be able to exclude on one_to_one associations" do
|
|
2596
|
+
@Album.exclude(:album_info=>@AlbumInfo.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE ((id != 3) OR (id IS NULL))'
|
|
2597
|
+
end
|
|
2598
|
+
|
|
2599
|
+
it "should be able to exclude on many_to_many associations" do
|
|
2600
|
+
@Album.exclude(:tags=>@Tag.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (SELECT album_id FROM albums_tags WHERE ((tag_id = 3) AND (album_id IS NOT NULL)))) OR (id IS NULL))'
|
|
2601
|
+
end
|
|
2602
|
+
|
|
2603
|
+
it "should be able to exclude on many_to_one associations with composite keys" do
|
|
2604
|
+
@Album.exclude(:cartist=>@Artist.load(:id1=>3, :id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((artist_id1 != 3) OR (artist_id2 != 4) OR (artist_id1 IS NULL) OR (artist_id2 IS NULL))'
|
|
2605
|
+
end
|
|
2606
|
+
|
|
2607
|
+
it "should be able to exclude on one_to_many associations with composite keys" do
|
|
2608
|
+
@Album.exclude(:ctracks=>@Track.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((id1 != 3) OR (id2 != 4) OR (id1 IS NULL) OR (id2 IS NULL))'
|
|
2609
|
+
end
|
|
2610
|
+
|
|
2611
|
+
it "should be able to exclude on one_to_one associations with composite keys" do
|
|
2612
|
+
@Album.exclude(:calbum_info=>@AlbumInfo.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((id1 != 3) OR (id2 != 4) OR (id1 IS NULL) OR (id2 IS NULL))'
|
|
2613
|
+
end
|
|
2614
|
+
|
|
2615
|
+
it "should be able to exclude on many_to_many associations with composite keys" do
|
|
2616
|
+
@Album.exclude(:ctags=>@Tag.load(:tid1=>3, :tid2=>4)).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN (SELECT album_id1, album_id2 FROM albums_tags WHERE ((tag_id1 = 3) AND (tag_id2 = 4) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL)))) OR (id1 IS NULL) OR (id2 IS NULL))'
|
|
2617
|
+
end
|
|
2618
|
+
|
|
2619
|
+
it "should be able to filter on multiple many_to_one associations" do
|
|
2620
|
+
@Album.filter(:artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE (artist_id IN (3, 4))'
|
|
2621
|
+
end
|
|
2622
|
+
|
|
2623
|
+
it "should be able to filter on multiple one_to_many associations" do
|
|
2624
|
+
@Album.filter(:tracks=>[@Track.load(:album_id=>3), @Track.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE (id IN (3, 4))'
|
|
2625
|
+
end
|
|
2626
|
+
|
|
2627
|
+
it "should be able to filter on multiple one_to_one associations" do
|
|
2628
|
+
@Album.filter(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE (id IN (3, 4))'
|
|
2629
|
+
end
|
|
2682
2630
|
|
|
2683
|
-
|
|
2684
|
-
@
|
|
2685
|
-
@c1.all_association_reflections.sort_by{|x|x[:name].to_s}.collect{|v| v[:name]}.should == [:children, :parent]
|
|
2686
|
-
@c1.all_association_reflections.sort_by{|x|x[:name].to_s}.collect{|v| v[:type]}.should == [:one_to_many, :many_to_one]
|
|
2687
|
-
@c1.all_association_reflections.sort_by{|x|x[:name].to_s}.collect{|v| v[:class]}.should == [@c1, @c1]
|
|
2631
|
+
it "should be able to filter on multiple many_to_many associations" do
|
|
2632
|
+
@Album.filter(:tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE (id IN (SELECT album_id FROM albums_tags WHERE ((tag_id IN (3, 4)) AND (album_id IS NOT NULL))))'
|
|
2688
2633
|
end
|
|
2689
2634
|
|
|
2690
|
-
it "
|
|
2691
|
-
@
|
|
2635
|
+
it "should be able to filter on multiple many_to_one associations with composite keys" do
|
|
2636
|
+
@Album.filter(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>5, :id2=>6)]).sql.should == 'SELECT * FROM albums WHERE ((artist_id1, artist_id2) IN ((3, 4), (5, 6)))'
|
|
2692
2637
|
end
|
|
2693
2638
|
|
|
2694
|
-
it "
|
|
2695
|
-
@
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
@
|
|
2639
|
+
it "should be able to filter on multiple one_to_many associations with composite keys" do
|
|
2640
|
+
@Album.filter(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.load(:album_id1=>5, :album_id2=>6)]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN ((3, 4), (5, 6)))'
|
|
2641
|
+
end
|
|
2642
|
+
|
|
2643
|
+
it "should be able to filter on multiple one_to_one associations with composite keys" do
|
|
2644
|
+
@Album.filter(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.load(:album_id1=>5, :album_id2=>6)]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN ((3, 4), (5, 6)))'
|
|
2645
|
+
end
|
|
2646
|
+
|
|
2647
|
+
it "should be able to filter on multiple many_to_many associations with composite keys" do
|
|
2648
|
+
@Album.filter(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5, :tid2=>6)]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN (SELECT album_id1, album_id2 FROM albums_tags WHERE (((tag_id1, tag_id2) IN ((3, 4), (5, 6))) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL))))'
|
|
2649
|
+
end
|
|
2650
|
+
|
|
2651
|
+
it "should be able to exclude on multiple many_to_one associations" do
|
|
2652
|
+
@Album.exclude(:artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE ((artist_id NOT IN (3, 4)) OR (artist_id IS NULL))'
|
|
2653
|
+
end
|
|
2654
|
+
|
|
2655
|
+
it "should be able to exclude on multiple one_to_many associations" do
|
|
2656
|
+
@Album.exclude(:tracks=>[@Track.load(:album_id=>3), @Track.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (3, 4)) OR (id IS NULL))'
|
|
2657
|
+
end
|
|
2658
|
+
|
|
2659
|
+
it "should be able to exclude on multiple one_to_one associations" do
|
|
2660
|
+
@Album.exclude(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (3, 4)) OR (id IS NULL))'
|
|
2661
|
+
end
|
|
2662
|
+
|
|
2663
|
+
it "should be able to exclude on multiple many_to_many associations" do
|
|
2664
|
+
@Album.exclude(:tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (SELECT album_id FROM albums_tags WHERE ((tag_id IN (3, 4)) AND (album_id IS NOT NULL)))) OR (id IS NULL))'
|
|
2665
|
+
end
|
|
2666
|
+
|
|
2667
|
+
it "should be able to exclude on multiple many_to_one associations with composite keys" do
|
|
2668
|
+
@Album.exclude(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>5, :id2=>6)]).sql.should == 'SELECT * FROM albums WHERE (((artist_id1, artist_id2) NOT IN ((3, 4), (5, 6))) OR (artist_id1 IS NULL) OR (artist_id2 IS NULL))'
|
|
2669
|
+
end
|
|
2670
|
+
|
|
2671
|
+
it "should be able to exclude on multiple one_to_many associations with composite keys" do
|
|
2672
|
+
@Album.exclude(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.load(:album_id1=>5, :album_id2=>6)]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN ((3, 4), (5, 6))) OR (id1 IS NULL) OR (id2 IS NULL))'
|
|
2673
|
+
end
|
|
2674
|
+
|
|
2675
|
+
it "should be able to exclude on multiple one_to_one associations with composite keys" do
|
|
2676
|
+
@Album.exclude(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.load(:album_id1=>5, :album_id2=>6)]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN ((3, 4), (5, 6))) OR (id1 IS NULL) OR (id2 IS NULL))'
|
|
2677
|
+
end
|
|
2678
|
+
|
|
2679
|
+
it "should be able to exclude on multiple many_to_many associations with composite keys" do
|
|
2680
|
+
@Album.exclude(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5, :tid2=>6)]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN (SELECT album_id1, album_id2 FROM albums_tags WHERE (((tag_id1, tag_id2) IN ((3, 4), (5, 6))) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL)))) OR (id1 IS NULL) OR (id2 IS NULL))'
|
|
2681
|
+
end
|
|
2682
|
+
|
|
2683
|
+
it "should be able to handle NULL values when filtering many_to_one associations" do
|
|
2684
|
+
@Album.filter(:artist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2685
|
+
end
|
|
2686
|
+
|
|
2687
|
+
it "should be able to handle NULL values when filtering one_to_many associations" do
|
|
2688
|
+
@Album.filter(:tracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2689
|
+
end
|
|
2690
|
+
|
|
2691
|
+
it "should be able to handle NULL values when filtering one_to_one associations" do
|
|
2692
|
+
@Album.filter(:album_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2693
|
+
end
|
|
2694
|
+
|
|
2695
|
+
it "should be able to handle NULL values when filtering many_to_many associations" do
|
|
2696
|
+
@Album.filter(:tags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2697
|
+
end
|
|
2698
|
+
|
|
2699
|
+
it "should be able to handle filteringing with NULL values for many_to_one associations with composite keys" do
|
|
2700
|
+
@Album.filter(:cartist=>@Artist.load(:id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2701
|
+
@Album.filter(:cartist=>@Artist.load(:id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2702
|
+
@Album.filter(:cartist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2703
|
+
end
|
|
2704
|
+
|
|
2705
|
+
it "should be able to filtering with NULL values for one_to_many associations with composite keys" do
|
|
2706
|
+
@Album.filter(:ctracks=>@Track.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2707
|
+
@Album.filter(:ctracks=>@Track.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2708
|
+
@Album.filter(:ctracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2709
|
+
end
|
|
2710
|
+
|
|
2711
|
+
it "should be able to filtering with NULL values for one_to_one associations with composite keys" do
|
|
2712
|
+
@Album.filter(:calbum_info=>@AlbumInfo.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2713
|
+
@Album.filter(:calbum_info=>@AlbumInfo.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2714
|
+
@Album.filter(:calbum_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2715
|
+
end
|
|
2716
|
+
|
|
2717
|
+
it "should be able to filtering with NULL values for many_to_many associations with composite keys" do
|
|
2718
|
+
@Album.filter(:ctags=>@Tag.load(:tid1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2719
|
+
@Album.filter(:ctags=>@Tag.load(:tid2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2720
|
+
@Album.filter(:ctags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2721
|
+
end
|
|
2722
|
+
|
|
2723
|
+
it "should be able to handle NULL values when excluding many_to_one associations" do
|
|
2724
|
+
@Album.exclude(:artist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2725
|
+
end
|
|
2726
|
+
|
|
2727
|
+
it "should be able to handle NULL values when excluding one_to_many associations" do
|
|
2728
|
+
@Album.exclude(:tracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2729
|
+
end
|
|
2730
|
+
|
|
2731
|
+
it "should be able to handle NULL values when excluding one_to_one associations" do
|
|
2732
|
+
@Album.exclude(:album_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2733
|
+
end
|
|
2734
|
+
|
|
2735
|
+
it "should be able to handle NULL values when excluding many_to_many associations" do
|
|
2736
|
+
@Album.exclude(:tags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2737
|
+
end
|
|
2738
|
+
|
|
2739
|
+
it "should be able to handle excluding with NULL values for many_to_one associations with composite keys" do
|
|
2740
|
+
@Album.exclude(:cartist=>@Artist.load(:id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2741
|
+
@Album.exclude(:cartist=>@Artist.load(:id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2742
|
+
@Album.exclude(:cartist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2743
|
+
end
|
|
2744
|
+
|
|
2745
|
+
it "should be able to excluding with NULL values for one_to_many associations with composite keys" do
|
|
2746
|
+
@Album.exclude(:ctracks=>@Track.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2747
|
+
@Album.exclude(:ctracks=>@Track.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2748
|
+
@Album.exclude(:ctracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2749
|
+
end
|
|
2750
|
+
|
|
2751
|
+
it "should be able to excluding with NULL values for one_to_one associations with composite keys" do
|
|
2752
|
+
@Album.exclude(:calbum_info=>@AlbumInfo.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2753
|
+
@Album.exclude(:calbum_info=>@AlbumInfo.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2754
|
+
@Album.exclude(:calbum_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2755
|
+
end
|
|
2756
|
+
|
|
2757
|
+
it "should be able to excluding with NULL values for many_to_many associations with composite keys" do
|
|
2758
|
+
@Album.exclude(:ctags=>@Tag.load(:tid1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2759
|
+
@Album.exclude(:ctags=>@Tag.load(:tid2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2760
|
+
@Album.exclude(:ctags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2761
|
+
end
|
|
2762
|
+
|
|
2763
|
+
it "should be able to handle NULL values when filtering multiple many_to_one associations" do
|
|
2764
|
+
@Album.filter(:artist=>[@Artist.load(:id=>3), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE (artist_id IN (3))'
|
|
2765
|
+
@Album.filter(:artist=>[@Artist.new, @Artist.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2766
|
+
end
|
|
2767
|
+
|
|
2768
|
+
it "should be able to handle NULL values when filtering multiple one_to_many associations" do
|
|
2769
|
+
@Album.filter(:tracks=>[@Track.load(:album_id=>3), @Track.new]).sql.should == 'SELECT * FROM albums WHERE (id IN (3))'
|
|
2770
|
+
@Album.filter(:tracks=>[@Track.new, @Track.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2771
|
+
end
|
|
2772
|
+
|
|
2773
|
+
it "should be able to handle NULL values when filtering multiple one_to_one associations" do
|
|
2774
|
+
@Album.filter(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE (id IN (3))'
|
|
2775
|
+
@Album.filter(:album_info=>[@AlbumInfo.new, @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2776
|
+
end
|
|
2777
|
+
|
|
2778
|
+
it "should be able to handle NULL values when filtering multiple many_to_many associations" do
|
|
2779
|
+
@Album.filter(:tags=>[@Tag.load(:id=>3), @Tag.new]).sql.should == 'SELECT * FROM albums WHERE (id IN (SELECT album_id FROM albums_tags WHERE ((tag_id IN (3)) AND (album_id IS NOT NULL))))'
|
|
2780
|
+
@Album.filter(:tags=>[@Tag.new, @Tag.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2781
|
+
end
|
|
2782
|
+
|
|
2783
|
+
it "should be able to handle NULL values when filtering multiple many_to_one associations with composite keys" do
|
|
2784
|
+
@Album.filter(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>3)]).sql.should == 'SELECT * FROM albums WHERE ((artist_id1, artist_id2) IN ((3, 4)))'
|
|
2785
|
+
@Album.filter(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE ((artist_id1, artist_id2) IN ((3, 4)))'
|
|
2786
|
+
end
|
|
2787
|
+
|
|
2788
|
+
it "should be able handle NULL values when filtering multiple one_to_many associations with composite keys" do
|
|
2789
|
+
@Album.filter(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.load(:album_id1=>3)]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN ((3, 4)))'
|
|
2790
|
+
@Album.filter(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.new]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN ((3, 4)))'
|
|
2791
|
+
end
|
|
2792
|
+
|
|
2793
|
+
it "should be able to handle NULL values when filtering multiple one_to_one associations with composite keys" do
|
|
2794
|
+
@Album.filter(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.load(:album_id1=>5)]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN ((3, 4)))'
|
|
2795
|
+
@Album.filter(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN ((3, 4)))'
|
|
2796
|
+
end
|
|
2797
|
+
|
|
2798
|
+
it "should be able to handle NULL values when filtering multiple many_to_many associations with composite keys" do
|
|
2799
|
+
@Album.filter(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5)]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN (SELECT album_id1, album_id2 FROM albums_tags WHERE (((tag_id1, tag_id2) IN ((3, 4))) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL))))'
|
|
2800
|
+
@Album.filter(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.new]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN (SELECT album_id1, album_id2 FROM albums_tags WHERE (((tag_id1, tag_id2) IN ((3, 4))) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL))))'
|
|
2801
|
+
end
|
|
2802
|
+
|
|
2803
|
+
it "should be able to handle NULL values when excluding multiple many_to_one associations" do
|
|
2804
|
+
@Album.exclude(:artist=>[@Artist.load(:id=>3), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE ((artist_id NOT IN (3)) OR (artist_id IS NULL))'
|
|
2805
|
+
@Album.exclude(:artist=>[@Artist.new, @Artist.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2806
|
+
end
|
|
2807
|
+
|
|
2808
|
+
it "should be able to handle NULL values when excluding multiple one_to_many associations" do
|
|
2809
|
+
@Album.exclude(:tracks=>[@Track.load(:album_id=>3), @Track.new]).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (3)) OR (id IS NULL))'
|
|
2810
|
+
@Album.exclude(:tracks=>[@Track.new, @Track.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2811
|
+
end
|
|
2812
|
+
|
|
2813
|
+
it "should be able to handle NULL values when excluding multiple one_to_one associations" do
|
|
2814
|
+
@Album.exclude(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (3)) OR (id IS NULL))'
|
|
2815
|
+
@Album.exclude(:album_info=>[@AlbumInfo.new, @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2816
|
+
end
|
|
2817
|
+
|
|
2818
|
+
it "should be able to handle NULL values when excluding multiple many_to_many associations" do
|
|
2819
|
+
@Album.exclude(:tags=>[@Tag.load(:id=>3), @Tag.new]).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (SELECT album_id FROM albums_tags WHERE ((tag_id IN (3)) AND (album_id IS NOT NULL)))) OR (id IS NULL))'
|
|
2820
|
+
@Album.exclude(:tags=>[@Tag.new, @Tag.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2821
|
+
end
|
|
2822
|
+
|
|
2823
|
+
it "should be able to handle NULL values when excluding multiple many_to_one associations with composite keys" do
|
|
2824
|
+
@Album.exclude(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>3)]).sql.should == 'SELECT * FROM albums WHERE (((artist_id1, artist_id2) NOT IN ((3, 4))) OR (artist_id1 IS NULL) OR (artist_id2 IS NULL))'
|
|
2825
|
+
@Album.exclude(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE (((artist_id1, artist_id2) NOT IN ((3, 4))) OR (artist_id1 IS NULL) OR (artist_id2 IS NULL))'
|
|
2826
|
+
end
|
|
2827
|
+
|
|
2828
|
+
it "should be able handle NULL values when excluding multiple one_to_many associations with composite keys" do
|
|
2829
|
+
@Album.exclude(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.load(:album_id1=>3)]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN ((3, 4))) OR (id1 IS NULL) OR (id2 IS NULL))'
|
|
2830
|
+
@Album.exclude(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.new]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN ((3, 4))) OR (id1 IS NULL) OR (id2 IS NULL))'
|
|
2831
|
+
end
|
|
2832
|
+
|
|
2833
|
+
it "should be able to handle NULL values when excluding multiple one_to_one associations with composite keys" do
|
|
2834
|
+
@Album.exclude(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.load(:album_id1=>5)]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN ((3, 4))) OR (id1 IS NULL) OR (id2 IS NULL))'
|
|
2835
|
+
@Album.exclude(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN ((3, 4))) OR (id1 IS NULL) OR (id2 IS NULL))'
|
|
2836
|
+
end
|
|
2837
|
+
|
|
2838
|
+
it "should be able to handle NULL values when excluding multiple many_to_many associations with composite keys" do
|
|
2839
|
+
@Album.exclude(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5)]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN (SELECT album_id1, album_id2 FROM albums_tags WHERE (((tag_id1, tag_id2) IN ((3, 4))) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL)))) OR (id1 IS NULL) OR (id2 IS NULL))'
|
|
2840
|
+
@Album.exclude(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.new]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN (SELECT album_id1, album_id2 FROM albums_tags WHERE (((tag_id1, tag_id2) IN ((3, 4))) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL)))) OR (id1 IS NULL) OR (id2 IS NULL))'
|
|
2841
|
+
end
|
|
2842
|
+
|
|
2843
|
+
it "should be able to filter on many_to_one association datasets" do
|
|
2844
|
+
@Album.filter(:artist=>@Artist.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (artist_id IN (SELECT id FROM artists WHERE ((x = 1) AND (id IS NOT NULL))))'
|
|
2845
|
+
end
|
|
2846
|
+
|
|
2847
|
+
it "should be able to filter on one_to_many association datasets" do
|
|
2848
|
+
@Album.filter(:tracks=>@Track.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (id IN (SELECT album_id FROM tracks WHERE ((x = 1) AND (album_id IS NOT NULL))))'
|
|
2849
|
+
end
|
|
2850
|
+
|
|
2851
|
+
it "should be able to filter on one_to_one association datasets" do
|
|
2852
|
+
@Album.filter(:album_info=>@AlbumInfo.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (id IN (SELECT album_id FROM album_infos WHERE ((x = 1) AND (album_id IS NOT NULL))))'
|
|
2853
|
+
end
|
|
2854
|
+
|
|
2855
|
+
it "should be able to filter on many_to_many association datasets" do
|
|
2856
|
+
@Album.filter(:tags=>@Tag.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (id IN (SELECT album_id FROM albums_tags WHERE ((tag_id IN (SELECT id FROM tags WHERE ((x = 1) AND (id IS NOT NULL)))) AND (album_id IS NOT NULL))))'
|
|
2857
|
+
end
|
|
2858
|
+
|
|
2859
|
+
it "should be able to filter on many_to_one association datasets with composite keys" do
|
|
2860
|
+
@Album.filter(:cartist=>@Artist.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((artist_id1, artist_id2) IN (SELECT id1, id2 FROM artists WHERE ((x = 1) AND (id1 IS NOT NULL) AND (id2 IS NOT NULL))))'
|
|
2861
|
+
end
|
|
2862
|
+
|
|
2863
|
+
it "should be able to filter on one_to_many association datasets with composite keys" do
|
|
2864
|
+
@Album.filter(:ctracks=>@Track.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN (SELECT album_id1, album_id2 FROM tracks WHERE ((x = 1) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL))))'
|
|
2865
|
+
end
|
|
2866
|
+
|
|
2867
|
+
it "should be able to filter on one_to_one association datasets with composite keys" do
|
|
2868
|
+
@Album.filter(:calbum_info=>@AlbumInfo.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN (SELECT album_id1, album_id2 FROM album_infos WHERE ((x = 1) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL))))'
|
|
2869
|
+
end
|
|
2870
|
+
|
|
2871
|
+
it "should be able to filter on many_to_many association datasets with composite keys" do
|
|
2872
|
+
@Album.filter(:ctags=>@Tag.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN (SELECT album_id1, album_id2 FROM albums_tags WHERE (((tag_id1, tag_id2) IN (SELECT tid1, tid2 FROM tags WHERE ((x = 1) AND (tid1 IS NOT NULL) AND (tid2 IS NOT NULL)))) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL))))'
|
|
2873
|
+
end
|
|
2874
|
+
|
|
2875
|
+
it "should be able to exclude on many_to_one association datasets" do
|
|
2876
|
+
@Album.exclude(:artist=>@Artist.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((artist_id NOT IN (SELECT id FROM artists WHERE ((x = 1) AND (id IS NOT NULL)))) OR (artist_id IS NULL))'
|
|
2877
|
+
end
|
|
2878
|
+
|
|
2879
|
+
it "should be able to exclude on one_to_many association datasets" do
|
|
2880
|
+
@Album.exclude(:tracks=>@Track.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (SELECT album_id FROM tracks WHERE ((x = 1) AND (album_id IS NOT NULL)))) OR (id IS NULL))'
|
|
2881
|
+
end
|
|
2882
|
+
|
|
2883
|
+
it "should be able to exclude on one_to_one association datasets" do
|
|
2884
|
+
@Album.exclude(:album_info=>@AlbumInfo.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (SELECT album_id FROM album_infos WHERE ((x = 1) AND (album_id IS NOT NULL)))) OR (id IS NULL))'
|
|
2885
|
+
end
|
|
2886
|
+
|
|
2887
|
+
it "should be able to exclude on many_to_many association datasets" do
|
|
2888
|
+
@Album.exclude(:tags=>@Tag.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (SELECT album_id FROM albums_tags WHERE ((tag_id IN (SELECT id FROM tags WHERE ((x = 1) AND (id IS NOT NULL)))) AND (album_id IS NOT NULL)))) OR (id IS NULL))'
|
|
2889
|
+
end
|
|
2890
|
+
|
|
2891
|
+
it "should be able to exclude on many_to_one association datasets with composite keys" do
|
|
2892
|
+
@Album.exclude(:cartist=>@Artist.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (((artist_id1, artist_id2) NOT IN (SELECT id1, id2 FROM artists WHERE ((x = 1) AND (id1 IS NOT NULL) AND (id2 IS NOT NULL)))) OR (artist_id1 IS NULL) OR (artist_id2 IS NULL))'
|
|
2893
|
+
end
|
|
2894
|
+
|
|
2895
|
+
it "should be able to exclude on one_to_many association datasets with composite keys" do
|
|
2896
|
+
@Album.exclude(:ctracks=>@Track.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN (SELECT album_id1, album_id2 FROM tracks WHERE ((x = 1) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL)))) OR (id1 IS NULL) OR (id2 IS NULL))'
|
|
2897
|
+
end
|
|
2898
|
+
|
|
2899
|
+
it "should be able to exclude on one_to_one association datasets with composite keys" do
|
|
2900
|
+
@Album.exclude(:calbum_info=>@AlbumInfo.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN (SELECT album_id1, album_id2 FROM album_infos WHERE ((x = 1) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL)))) OR (id1 IS NULL) OR (id2 IS NULL))'
|
|
2901
|
+
end
|
|
2700
2902
|
|
|
2701
|
-
|
|
2702
|
-
@
|
|
2703
|
-
@c1.association_reflection(:children)[:name].should == :children
|
|
2704
|
-
@c1.association_reflection(:children)[:type].should == :one_to_many
|
|
2705
|
-
@c1.association_reflection(:children)[:class].should == @c1
|
|
2903
|
+
it "should be able to exclude on many_to_many association datasets with composite keys" do
|
|
2904
|
+
@Album.exclude(:ctags=>@Tag.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN (SELECT album_id1, album_id2 FROM albums_tags WHERE (((tag_id1, tag_id2) IN (SELECT tid1, tid2 FROM tags WHERE ((x = 1) AND (tid1 IS NOT NULL) AND (tid2 IS NOT NULL)))) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL)))) OR (id1 IS NULL) OR (id2 IS NULL))'
|
|
2706
2905
|
end
|
|
2707
2906
|
|
|
2708
|
-
it "
|
|
2709
|
-
@
|
|
2710
|
-
@c1.associate :many_to_one, :parent, :class => @c1
|
|
2711
|
-
@c1.associations.should == [:parent]
|
|
2712
|
-
@c1.associate :one_to_many, :children, :class => @c1
|
|
2713
|
-
@c1.associations.sort_by{|x|x.to_s}.should == [:children, :parent]
|
|
2907
|
+
it "should do a regular IN query if the dataset for a different model is used" do
|
|
2908
|
+
@Album.filter(:artist=>@Album.select(:x)).sql.should == 'SELECT * FROM albums WHERE (artist IN (SELECT x FROM albums))'
|
|
2714
2909
|
end
|
|
2715
2910
|
|
|
2716
|
-
it "
|
|
2717
|
-
@
|
|
2718
|
-
c = Class.new(@c1)
|
|
2719
|
-
@c1.associations.should == [:parent]
|
|
2720
|
-
c.associations.should == [:parent]
|
|
2721
|
-
c.associate :many_to_one, :parent2, :class => @c1
|
|
2722
|
-
@c1.associations.should == [:parent]
|
|
2723
|
-
c.associations.sort_by{|x| x.to_s}.should == [:parent, :parent2]
|
|
2724
|
-
c.instance_methods.map{|x| x.to_s}.should include('parent')
|
|
2911
|
+
it "should do a regular IN query if a non-model dataset is used" do
|
|
2912
|
+
@Album.filter(:artist=>@Album.db.from(:albums).select(:x)).sql.should == 'SELECT * FROM albums WHERE (artist IN (SELECT x FROM albums))'
|
|
2725
2913
|
end
|
|
2726
2914
|
end
|