sequel 3.21.0 → 3.32.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 +539 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +20 -6
- data/Rakefile +37 -19
- data/bin/sequel +1 -5
- data/doc/advanced_associations.rdoc +17 -0
- data/doc/association_basics.rdoc +293 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/dataset_filtering.rdoc +8 -0
- 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 +89 -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/release_notes/3.30.0.txt +135 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/doc/release_notes/3.32.0.txt +202 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +129 -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 +17 -9
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +5 -7
- 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 +16 -34
- data/lib/sequel/adapters/jdbc/db2.rb +52 -0
- data/lib/sequel/adapters/jdbc/derby.rb +260 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +66 -30
- data/lib/sequel/adapters/jdbc/hsqldb.rb +177 -0
- data/lib/sequel/adapters/jdbc/informix.rb +26 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
- data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
- data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +231 -78
- data/lib/sequel/adapters/mock.rb +339 -0
- data/lib/sequel/adapters/mysql.rb +85 -184
- data/lib/sequel/adapters/mysql2.rb +26 -25
- data/lib/sequel/adapters/odbc/db2.rb +17 -0
- data/lib/sequel/adapters/odbc/mssql.rb +1 -6
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +355 -53
- data/lib/sequel/adapters/postgres.rb +194 -33
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +328 -0
- data/lib/sequel/adapters/shared/firebird.rb +221 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +278 -107
- data/lib/sequel/adapters/shared/mysql.rb +203 -65
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +237 -46
- data/lib/sequel/adapters/shared/postgres.rb +214 -82
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +200 -50
- data/lib/sequel/adapters/sqlite.rb +29 -21
- data/lib/sequel/adapters/swift/mysql.rb +12 -7
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +8 -6
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/tinytds.rb +160 -19
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- 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 +68 -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 +104 -19
- data/lib/sequel/database/query.rb +163 -59
- data/lib/sequel/database/schema_generator.rb +17 -7
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +240 -76
- data/lib/sequel/dataset/features.rb +91 -8
- data/lib/sequel/dataset/graph.rb +38 -11
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +59 -27
- data/lib/sequel/dataset/query.rb +236 -43
- data/lib/sequel/dataset/sql.rb +676 -267
- 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/query.rb +1 -1
- 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 +1081 -344
- data/lib/sequel/model/base.rb +420 -133
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +20 -10
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +43 -10
- 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 +68 -7
- data/lib/sequel/plugins/nested_attributes.rb +65 -10
- 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 +98 -49
- data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- 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 +109 -52
- data/lib/sequel/timezones.rb +57 -38
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +135 -30
- data/spec/adapters/mysql_spec.rb +244 -212
- data/spec/adapters/oracle_spec.rb +67 -77
- data/spec/adapters/postgres_spec.rb +267 -78
- 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 +21 -30
- data/spec/core/database_spec.rb +789 -512
- data/spec/core/dataset_spec.rb +1176 -1061
- data/spec/core/expression_filters_spec.rb +159 -42
- data/spec/core/mock_adapter_spec.rb +419 -0
- data/spec/core/object_graph_spec.rb +86 -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/active_model_spec.rb +13 -0
- data/spec/extensions/association_autoreloading_spec.rb +1 -10
- data/spec/extensions/association_dependencies_spec.rb +2 -12
- data/spec/extensions/association_pks_spec.rb +66 -32
- data/spec/extensions/caching_spec.rb +23 -50
- data/spec/extensions/class_table_inheritance_spec.rb +31 -83
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/hook_class_methods_spec.rb +65 -91
- data/spec/extensions/identity_map_spec.rb +114 -22
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +53 -0
- data/spec/extensions/json_serializer_spec.rb +4 -5
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +17 -39
- data/spec/extensions/many_through_many_spec.rb +283 -250
- data/spec/extensions/migration_spec.rb +35 -32
- data/spec/extensions/named_timezones_spec.rb +23 -3
- data/spec/extensions/nested_attributes_spec.rb +97 -88
- data/spec/extensions/optimistic_locking_spec.rb +9 -20
- data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
- data/spec/extensions/prepared_statements_spec.rb +53 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +1 -6
- data/spec/extensions/query_spec.rb +6 -0
- data/spec/extensions/rcte_tree_spec.rb +41 -43
- data/spec/extensions/schema_dumper_spec.rb +5 -8
- data/spec/extensions/schema_spec.rb +13 -21
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +81 -43
- data/spec/extensions/sharding_spec.rb +66 -140
- data/spec/extensions/single_table_inheritance_spec.rb +18 -29
- data/spec/extensions/spec_helper.rb +13 -61
- data/spec/extensions/sql_expr_spec.rb +20 -60
- data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +4 -7
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +30 -51
- data/spec/extensions/validation_helpers_spec.rb +16 -35
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +661 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +500 -67
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +367 -119
- data/spec/integration/prepared_statement_test.rb +222 -125
- data/spec/integration/schema_test.rb +217 -39
- data/spec/integration/spec_helper.rb +39 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +182 -5
- data/spec/integration/type_test.rb +17 -3
- data/spec/model/association_reflection_spec.rb +201 -7
- data/spec/model/associations_spec.rb +955 -662
- data/spec/model/base_spec.rb +275 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +677 -676
- data/spec/model/hooks_spec.rb +349 -67
- data/spec/model/model_spec.rb +222 -168
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +381 -218
- data/spec/model/spec_helper.rb +13 -71
- data/spec/model/validations_spec.rb +11 -0
- metadata +117 -73
|
@@ -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
|
|
@@ -142,32 +148,43 @@ describe Sequel::Model, "many_to_one" do
|
|
|
142
148
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (nodes.id = 234) LIMIT 1"]
|
|
143
149
|
end
|
|
144
150
|
|
|
151
|
+
it "should allow association with the same name as the key if :key_alias is given" do
|
|
152
|
+
@c2.def_column_alias(:parent_id_id, :parent_id)
|
|
153
|
+
@c2.many_to_one :parent_id, :key_column=>:parent_id, :class => @c2
|
|
154
|
+
d = @c2.load(:id => 1, :parent_id => 234)
|
|
155
|
+
d.parent_id_dataset.sql.should == "SELECT * FROM nodes WHERE (nodes.id = 234) LIMIT 1"
|
|
156
|
+
d.parent_id.should == @c2.load(:x => 1, :id => 1)
|
|
157
|
+
d.parent_id_id.should == 234
|
|
158
|
+
d[:parent_id].should == 234
|
|
159
|
+
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (nodes.id = 234) LIMIT 1"]
|
|
160
|
+
|
|
161
|
+
d.parent_id_id = 3
|
|
162
|
+
d.parent_id_id.should == 3
|
|
163
|
+
d[:parent_id].should == 3
|
|
164
|
+
end
|
|
165
|
+
|
|
145
166
|
it "should use implicit class if omitted" do
|
|
146
|
-
|
|
167
|
+
begin
|
|
168
|
+
class ::ParParent < Sequel::Model; end
|
|
169
|
+
@c2.many_to_one :par_parent
|
|
170
|
+
@c2.new(:id => 1, :par_parent_id => 234).par_parent.class.should == ParParent
|
|
171
|
+
MODEL_DB.sqls.should == ["SELECT * FROM par_parents WHERE (par_parents.id = 234) LIMIT 1"]
|
|
172
|
+
ensure
|
|
173
|
+
Object.send(:remove_const, :ParParent)
|
|
147
174
|
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
175
|
end
|
|
157
176
|
|
|
158
177
|
it "should use class inside module if given as a string" do
|
|
159
|
-
|
|
160
|
-
|
|
178
|
+
begin
|
|
179
|
+
module ::Par
|
|
180
|
+
class Parent < Sequel::Model; end
|
|
161
181
|
end
|
|
182
|
+
@c2.many_to_one :par_parent, :class=>"Par::Parent"
|
|
183
|
+
@c2.new(:id => 1, :par_parent_id => 234).par_parent.class.should == Par::Parent
|
|
184
|
+
MODEL_DB.sqls.should == ["SELECT * FROM parents WHERE (parents.id = 234) LIMIT 1"]
|
|
185
|
+
ensure
|
|
186
|
+
Object.send(:remove_const, :Par)
|
|
162
187
|
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
188
|
end
|
|
172
189
|
|
|
173
190
|
it "should use explicit key if given" do
|
|
@@ -181,6 +198,12 @@ describe Sequel::Model, "many_to_one" do
|
|
|
181
198
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (nodes.id = 567) LIMIT 1"]
|
|
182
199
|
end
|
|
183
200
|
|
|
201
|
+
it "should respect :qualify => false option" do
|
|
202
|
+
@c2.many_to_one :parent, :class => @c2, :key => :blah, :qualify=>false
|
|
203
|
+
@c2.new(:id => 1, :blah => 567).parent
|
|
204
|
+
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (id = 567) LIMIT 1"]
|
|
205
|
+
end
|
|
206
|
+
|
|
184
207
|
it "should use :primary_key option if given" do
|
|
185
208
|
@c2.many_to_one :parent, :class => @c2, :key => :blah, :primary_key => :pk
|
|
186
209
|
@c2.new(:id => 1, :blah => 567).parent
|
|
@@ -218,14 +241,12 @@ describe Sequel::Model, "many_to_one" do
|
|
|
218
241
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.id = 567) AND (a = 32)) LIMIT 1"]
|
|
219
242
|
|
|
220
243
|
@c2.many_to_one :parent, :class => @c2, :key => :blah, :conditions=>:a
|
|
221
|
-
MODEL_DB.sqls.clear
|
|
222
244
|
@c2.new(:id => 1, :blah => 567).parent
|
|
223
245
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.id = 567) AND a) LIMIT 1"]
|
|
224
246
|
end
|
|
225
247
|
|
|
226
248
|
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|
|
|
249
|
+
@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
250
|
ds.filter(:x.sql_number > 1)
|
|
230
251
|
end
|
|
231
252
|
@c2.load(:id => 100).child_20
|
|
@@ -234,24 +255,19 @@ describe Sequel::Model, "many_to_one" do
|
|
|
234
255
|
|
|
235
256
|
it "should return nil if key value is nil" do
|
|
236
257
|
@c2.many_to_one :parent, :class => @c2
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
d.parent.should == nil
|
|
258
|
+
@c2.new(:id => 1).parent.should == nil
|
|
259
|
+
MODEL_DB.sqls.should == []
|
|
240
260
|
end
|
|
241
261
|
|
|
242
262
|
it "should cache negative lookup" do
|
|
243
263
|
@c2.many_to_one :parent, :class => @c2
|
|
244
|
-
|
|
245
|
-
def ds.fetch_rows(sql, &block)
|
|
246
|
-
MODEL_DB.sqls << sql
|
|
247
|
-
end
|
|
248
|
-
|
|
264
|
+
@c2.dataset._fetch = []
|
|
249
265
|
d = @c2.new(:id => 1, :parent_id=>555)
|
|
250
266
|
MODEL_DB.sqls.should == []
|
|
251
267
|
d.parent.should == nil
|
|
252
268
|
MODEL_DB.sqls.should == ['SELECT * FROM nodes WHERE (nodes.id = 555) LIMIT 1']
|
|
253
269
|
d.parent.should == nil
|
|
254
|
-
MODEL_DB.sqls.should == [
|
|
270
|
+
MODEL_DB.sqls.should == []
|
|
255
271
|
end
|
|
256
272
|
|
|
257
273
|
it "should define a setter method" do
|
|
@@ -314,11 +330,9 @@ describe Sequel::Model, "many_to_one" do
|
|
|
314
330
|
@c2.many_to_one :parent, :class => @c2
|
|
315
331
|
|
|
316
332
|
d = @c2.load(:id => 1)
|
|
317
|
-
MODEL_DB.reset
|
|
318
333
|
d.parent_id = 234
|
|
319
334
|
d.associations[:parent].should == nil
|
|
320
|
-
|
|
321
|
-
def ds.fetch_rows(sql, &block); MODEL_DB.sqls << sql; yield({:id=>234}) end
|
|
335
|
+
@c2.dataset._fetch = {:id=>234}
|
|
322
336
|
e = d.parent
|
|
323
337
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (nodes.id = 234) LIMIT 1"]
|
|
324
338
|
d.associations[:parent].should == e
|
|
@@ -357,13 +371,32 @@ describe Sequel::Model, "many_to_one" do
|
|
|
357
371
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (nodes.id = 234) LIMIT 1"]
|
|
358
372
|
end
|
|
359
373
|
|
|
374
|
+
it "should use a callback if given one as the argument" do
|
|
375
|
+
@c2.many_to_one :parent, :class => @c2
|
|
376
|
+
|
|
377
|
+
d = @c2.create(:id => 1)
|
|
378
|
+
MODEL_DB.reset
|
|
379
|
+
d.parent_id = 234
|
|
380
|
+
d.associations[:parent] = 42
|
|
381
|
+
d.parent(proc{|ds| ds.filter{name > 'M'}}).should_not == 42
|
|
382
|
+
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.id = 234) AND (name > 'M')) LIMIT 1"]
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
it "should use a block given to the association method as a callback on ruby 1.8.7+" do
|
|
386
|
+
@c2.many_to_one :parent, :class => @c2
|
|
387
|
+
|
|
388
|
+
d = @c2.create(:id => 1)
|
|
389
|
+
MODEL_DB.reset
|
|
390
|
+
d.parent_id = 234
|
|
391
|
+
d.associations[:parent] = 42
|
|
392
|
+
d.parent{|ds| ds.filter{name > 'M'}}.should_not == 42
|
|
393
|
+
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.id = 234) AND (name > 'M')) LIMIT 1"]
|
|
394
|
+
end if RUBY_VERSION >= '1.8.7'
|
|
395
|
+
|
|
360
396
|
it "should have the setter add to the reciprocal one_to_many cached association list if it exists" do
|
|
361
397
|
@c2.many_to_one :parent, :class => @c2
|
|
362
398
|
@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
|
|
399
|
+
@c2.dataset._fetch = []
|
|
367
400
|
|
|
368
401
|
d = @c2.new(:id => 1)
|
|
369
402
|
e = @c2.new(:id => 2)
|
|
@@ -372,14 +405,13 @@ describe Sequel::Model, "many_to_one" do
|
|
|
372
405
|
e.children.should_not(include(d))
|
|
373
406
|
MODEL_DB.sqls.should == ['SELECT * FROM nodes WHERE (nodes.parent_id = 2)']
|
|
374
407
|
|
|
375
|
-
MODEL_DB.reset
|
|
376
408
|
d = @c2.new(:id => 1)
|
|
377
409
|
e = @c2.new(:id => 2)
|
|
378
410
|
e.children.should_not(include(d))
|
|
379
411
|
MODEL_DB.sqls.should == ['SELECT * FROM nodes WHERE (nodes.parent_id = 2)']
|
|
380
412
|
d.parent = e
|
|
381
413
|
e.children.should(include(d))
|
|
382
|
-
MODEL_DB.sqls.should == [
|
|
414
|
+
MODEL_DB.sqls.should == []
|
|
383
415
|
end
|
|
384
416
|
|
|
385
417
|
it "should have many_to_one setter deal with a one_to_one reciprocal" do
|
|
@@ -407,10 +439,7 @@ describe Sequel::Model, "many_to_one" do
|
|
|
407
439
|
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
440
|
@c2.many_to_one :parent, :class => @c2
|
|
409
441
|
@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
|
|
442
|
+
@c2.dataset._fetch = []
|
|
414
443
|
|
|
415
444
|
d = @c2.new(:id => 1)
|
|
416
445
|
e = @c2.new(:id => 2)
|
|
@@ -429,17 +458,9 @@ describe Sequel::Model, "many_to_one" do
|
|
|
429
458
|
end
|
|
430
459
|
|
|
431
460
|
it "should get all matching records and only return the first if :key option is set to nil" do
|
|
432
|
-
c2 = @c2
|
|
433
461
|
@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
|
|
462
|
+
@c2.many_to_one :first_grand_parent, :class => @c2, :key=>nil, :eager_graph=>:children, :dataset=>proc{model.filter(:children_id=>parent_id)}
|
|
463
|
+
@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
464
|
p = @c2.new(:parent_id=>2)
|
|
444
465
|
fgp = p.first_grand_parent
|
|
445
466
|
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 +521,15 @@ describe Sequel::Model, "many_to_one" do
|
|
|
500
521
|
h = []
|
|
501
522
|
@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
523
|
@c2.class_eval do
|
|
503
|
-
|
|
524
|
+
self::Foo = h
|
|
504
525
|
def []=(a, v)
|
|
505
|
-
a == :parent_id ? (
|
|
526
|
+
a == :parent_id ? (model::Foo << (v ? 4 : 5)) : super
|
|
506
527
|
end
|
|
507
528
|
def blah(x)
|
|
508
|
-
|
|
529
|
+
model::Foo << (x ? x.pk : :x)
|
|
509
530
|
end
|
|
510
531
|
def blahr(x)
|
|
511
|
-
|
|
532
|
+
model::Foo << 6
|
|
512
533
|
end
|
|
513
534
|
end
|
|
514
535
|
p = @c2.load(:id=>10)
|
|
@@ -524,13 +545,11 @@ describe Sequel::Model, "many_to_one" do
|
|
|
524
545
|
h = []
|
|
525
546
|
@c2.many_to_one :parent, :class => @c2, :after_load=>[proc{|x,y| h << [x.pk, y.pk]}, :al]
|
|
526
547
|
@c2.class_eval do
|
|
527
|
-
|
|
548
|
+
self::Foo = h
|
|
528
549
|
def al(v)
|
|
529
|
-
|
|
530
|
-
end
|
|
531
|
-
def @dataset.fetch_rows(sql)
|
|
532
|
-
yield({:id=>20})
|
|
550
|
+
model::Foo << v.pk
|
|
533
551
|
end
|
|
552
|
+
dataset._fetch = {:id=>20}
|
|
534
553
|
end
|
|
535
554
|
p = @c2.load(:id=>10, :parent_id=>20)
|
|
536
555
|
parent = p.parent
|
|
@@ -538,6 +557,18 @@ describe Sequel::Model, "many_to_one" do
|
|
|
538
557
|
parent.pk.should == 20
|
|
539
558
|
end
|
|
540
559
|
|
|
560
|
+
it "should support after_load association callback that changes the cached object" do
|
|
561
|
+
@c2.many_to_one :parent, :class => @c2, :after_load=>:al
|
|
562
|
+
@c2.class_eval do
|
|
563
|
+
def al(v)
|
|
564
|
+
associations[:parent] = :foo
|
|
565
|
+
end
|
|
566
|
+
end
|
|
567
|
+
p = @c2.load(:id=>10, :parent_id=>20)
|
|
568
|
+
p.parent.should == :foo
|
|
569
|
+
p.associations[:parent].should == :foo
|
|
570
|
+
end
|
|
571
|
+
|
|
541
572
|
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
573
|
# The reason for this is that assignment in ruby always returns the argument instead of the result
|
|
543
574
|
# of the method, so we can't return nil to signal that the association callback prevented the modification
|
|
@@ -565,35 +596,32 @@ describe Sequel::Model, "many_to_one" do
|
|
|
565
596
|
d = @c2.load(:id=>321)
|
|
566
597
|
p = @c2.new
|
|
567
598
|
p.associations[:parent] = d
|
|
568
|
-
h = []
|
|
569
599
|
@c2.many_to_one :parent, :class => @c2, :before_set=>:bs, :after_set=>:as
|
|
570
600
|
@c2.class_eval do
|
|
571
|
-
|
|
601
|
+
self::Foo = []
|
|
572
602
|
def []=(a, v)
|
|
573
|
-
a == :parent_id ? (
|
|
603
|
+
a == :parent_id ? (model::Foo << 5) : super
|
|
574
604
|
end
|
|
575
605
|
def bs(x)
|
|
576
|
-
|
|
606
|
+
model::Foo << x.pk
|
|
577
607
|
end
|
|
578
608
|
def as(x)
|
|
579
|
-
|
|
609
|
+
model::Foo << x.pk * 2
|
|
580
610
|
end
|
|
581
611
|
end
|
|
582
612
|
p.parent = c
|
|
583
|
-
|
|
613
|
+
@c2::Foo.should == [123, 5, 246]
|
|
584
614
|
end
|
|
585
615
|
end
|
|
586
616
|
|
|
587
617
|
describe Sequel::Model, "one_to_one" do
|
|
588
618
|
before do
|
|
589
619
|
@c1 = Class.new(Sequel::Model(:attributes)) do
|
|
590
|
-
def _refresh(ds); end
|
|
591
620
|
unrestrict_primary_key
|
|
592
621
|
columns :id, :node_id, :y
|
|
593
622
|
end
|
|
594
623
|
|
|
595
624
|
@c2 = Class.new(Sequel::Model(:nodes)) do
|
|
596
|
-
def _refresh(ds); end
|
|
597
625
|
unrestrict_primary_key
|
|
598
626
|
attr_accessor :xxx
|
|
599
627
|
|
|
@@ -602,24 +630,8 @@ describe Sequel::Model, "one_to_one" do
|
|
|
602
630
|
columns :id, :x, :parent_id, :par_parent_id, :blah, :node_id
|
|
603
631
|
end
|
|
604
632
|
@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
|
|
633
|
+
@dataset._fetch = {}
|
|
634
|
+
@c1.dataset._fetch = {}
|
|
623
635
|
MODEL_DB.reset
|
|
624
636
|
end
|
|
625
637
|
|
|
@@ -641,26 +653,24 @@ describe Sequel::Model, "one_to_one" do
|
|
|
641
653
|
it "should add a setter method" do
|
|
642
654
|
@c2.one_to_one :attribute, :class => @c1
|
|
643
655
|
attrib = @c1.new(:id=>3)
|
|
644
|
-
|
|
645
|
-
@c1.class_eval{remove_method :_refresh}
|
|
646
|
-
def d.fetch_rows(s); yield({:id=>3}) end
|
|
656
|
+
@c1.dataset._fetch = {:id=>3}
|
|
647
657
|
@c2.new(:id => 1234).attribute = attrib
|
|
658
|
+
sqls = MODEL_DB.sqls
|
|
648
659
|
['INSERT INTO attributes (node_id, id) VALUES (1234, 3)',
|
|
649
|
-
'INSERT INTO attributes (id, node_id) VALUES (3, 1234)'].should(include(
|
|
650
|
-
|
|
651
|
-
|
|
660
|
+
'INSERT INTO attributes (id, node_id) VALUES (3, 1234)'].should(include(sqls.slice! 1))
|
|
661
|
+
sqls.should == ['UPDATE attributes SET node_id = NULL WHERE ((node_id = 1234) AND (id != 3))', "SELECT * FROM attributes WHERE (id = 3) LIMIT 1"]
|
|
662
|
+
|
|
652
663
|
@c2.new(:id => 1234).attribute.should == attrib
|
|
653
|
-
MODEL_DB.sqls.clear
|
|
654
664
|
attrib = @c1.load(:id=>3)
|
|
655
665
|
@c2.new(:id => 1234).attribute = attrib
|
|
656
|
-
MODEL_DB.sqls.should == [
|
|
666
|
+
MODEL_DB.sqls.should == ["SELECT * FROM attributes WHERE (attributes.node_id = 1234) LIMIT 1",
|
|
667
|
+
'UPDATE attributes SET node_id = NULL WHERE ((node_id = 1234) AND (id != 3))',
|
|
657
668
|
"UPDATE attributes SET node_id = 1234 WHERE (id = 3)"]
|
|
658
669
|
end
|
|
659
670
|
|
|
660
671
|
it "should use a transaction in the setter method" do
|
|
661
672
|
@c2.one_to_one :attribute, :class => @c1
|
|
662
673
|
@c2.use_transactions = true
|
|
663
|
-
MODEL_DB.sqls.clear
|
|
664
674
|
attrib = @c1.load(:id=>3)
|
|
665
675
|
@c2.new(:id => 1234).attribute = attrib
|
|
666
676
|
MODEL_DB.sqls.should == ['BEGIN',
|
|
@@ -673,7 +683,6 @@ describe Sequel::Model, "one_to_one" do
|
|
|
673
683
|
@c2.one_to_one :attribute, :class => @c1, :conditions=>{:a=>1} do |ds|
|
|
674
684
|
ds.filter(:b=>2)
|
|
675
685
|
end
|
|
676
|
-
MODEL_DB.sqls.clear
|
|
677
686
|
attrib = @c1.load(:id=>3)
|
|
678
687
|
@c2.new(:id => 1234).attribute = attrib
|
|
679
688
|
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 +692,30 @@ describe Sequel::Model, "one_to_one" do
|
|
|
683
692
|
it "should have the setter method respect the :primary_key option" do
|
|
684
693
|
@c2.one_to_one :attribute, :class => @c1, :primary_key=>:xxx
|
|
685
694
|
attrib = @c1.new(:id=>3)
|
|
686
|
-
|
|
687
|
-
@c1.class_eval{remove_method :_refresh}
|
|
688
|
-
def d.fetch_rows(s); yield({:id=>3}) end
|
|
695
|
+
@c1.dataset._fetch = {:id=>3}
|
|
689
696
|
@c2.new(:id => 1234, :xxx=>5).attribute = attrib
|
|
697
|
+
sqls = MODEL_DB.sqls
|
|
690
698
|
['INSERT INTO attributes (node_id, id) VALUES (5, 3)',
|
|
691
|
-
'INSERT INTO attributes (id, node_id) VALUES (3, 5)'].should(include(
|
|
692
|
-
|
|
693
|
-
|
|
699
|
+
'INSERT INTO attributes (id, node_id) VALUES (3, 5)'].should(include(sqls.slice! 1))
|
|
700
|
+
sqls.should == ['UPDATE attributes SET node_id = NULL WHERE ((node_id = 5) AND (id != 3))', "SELECT * FROM attributes WHERE (id = 3) LIMIT 1"]
|
|
701
|
+
|
|
694
702
|
@c2.new(:id => 321, :xxx=>5).attribute.should == attrib
|
|
695
|
-
MODEL_DB.sqls.clear
|
|
696
703
|
attrib = @c1.load(:id=>3)
|
|
697
704
|
@c2.new(:id => 621, :xxx=>5).attribute = attrib
|
|
698
|
-
MODEL_DB.sqls.should == [
|
|
705
|
+
MODEL_DB.sqls.should == ["SELECT * FROM attributes WHERE (attributes.node_id = 5) LIMIT 1",
|
|
706
|
+
'UPDATE attributes SET node_id = NULL WHERE ((node_id = 5) AND (id != 3))',
|
|
699
707
|
'UPDATE attributes SET node_id = 5 WHERE (id = 3)']
|
|
700
708
|
end
|
|
701
709
|
|
|
702
710
|
it "should have the setter method respect composite keys" do
|
|
703
711
|
@c2.one_to_one :attribute, :class => @c1, :key=>[:node_id, :y], :primary_key=>[:id, :x]
|
|
704
712
|
attrib = @c1.load(:id=>3, :y=>6)
|
|
705
|
-
|
|
706
|
-
def d.fetch_rows(s); yield({:id=>3, :y=>6}) end
|
|
713
|
+
@c1.dataset._fetch = {:id=>3, :y=>6}
|
|
707
714
|
@c2.load(:id => 1234, :x=>5).attribute = attrib
|
|
708
|
-
|
|
709
|
-
|
|
715
|
+
sqls = MODEL_DB.sqls
|
|
716
|
+
sqls.last.should =~ /UPDATE attributes SET (node_id = 1234|y = 5), (node_id = 1234|y = 5) WHERE \(id = 3\)/
|
|
717
|
+
sqls.first.should =~ /UPDATE attributes SET (node_id|y) = NULL, (node_id|y) = NULL WHERE \(\(node_id = 1234\) AND \(y = 5\) AND \(id != 3\)\)/
|
|
718
|
+
sqls.length.should == 2
|
|
710
719
|
end
|
|
711
720
|
|
|
712
721
|
it "should use implicit key if omitted" do
|
|
@@ -721,31 +730,27 @@ describe Sequel::Model, "one_to_one" do
|
|
|
721
730
|
end
|
|
722
731
|
|
|
723
732
|
it "should use implicit class if omitted" do
|
|
724
|
-
|
|
733
|
+
begin
|
|
734
|
+
class ::ParParent < Sequel::Model; end
|
|
735
|
+
@c2.one_to_one :par_parent
|
|
736
|
+
@c2.new(:id => 234).par_parent.class.should == ParParent
|
|
737
|
+
MODEL_DB.sqls.should == ["SELECT * FROM par_parents WHERE (par_parents.node_id = 234) LIMIT 1"]
|
|
738
|
+
ensure
|
|
739
|
+
Object.send(:remove_const, :ParParent)
|
|
725
740
|
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
741
|
end
|
|
735
742
|
|
|
736
743
|
it "should use class inside module if given as a string" do
|
|
737
|
-
|
|
738
|
-
|
|
744
|
+
begin
|
|
745
|
+
module ::Par
|
|
746
|
+
class Parent < Sequel::Model; end
|
|
739
747
|
end
|
|
748
|
+
@c2.one_to_one :par_parent, :class=>"Par::Parent"
|
|
749
|
+
@c2.new(:id => 234).par_parent.class.should == Par::Parent
|
|
750
|
+
MODEL_DB.sqls.should == ["SELECT * FROM parents WHERE (parents.node_id = 234) LIMIT 1"]
|
|
751
|
+
ensure
|
|
752
|
+
Object.send(:remove_const, :Par)
|
|
740
753
|
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
754
|
end
|
|
750
755
|
|
|
751
756
|
it "should use explicit key if given" do
|
|
@@ -796,14 +801,12 @@ describe Sequel::Model, "one_to_one" do
|
|
|
796
801
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.node_id = 567) AND (a = 32)) LIMIT 1"]
|
|
797
802
|
|
|
798
803
|
@c2.one_to_one :parent, :class => @c2, :conditions=>:a
|
|
799
|
-
MODEL_DB.sqls.clear
|
|
800
804
|
@c2.new(:id => 567).parent
|
|
801
805
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.node_id = 567) AND a) LIMIT 1"]
|
|
802
806
|
end
|
|
803
807
|
|
|
804
808
|
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|
|
|
809
|
+
@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
810
|
ds.filter(:x.sql_number > 1)
|
|
808
811
|
end
|
|
809
812
|
@c2.load(:id => 100).child_20
|
|
@@ -813,24 +816,19 @@ describe Sequel::Model, "one_to_one" do
|
|
|
813
816
|
it "should return nil if primary_key value is nil" do
|
|
814
817
|
@c2.one_to_one :parent, :class => @c2, :primary_key=>:node_id
|
|
815
818
|
|
|
816
|
-
|
|
817
|
-
d.parent.should == nil
|
|
819
|
+
@c2.new(:id => 1).parent.should be_nil
|
|
818
820
|
MODEL_DB.sqls.should == []
|
|
819
821
|
end
|
|
820
822
|
|
|
821
823
|
it "should cache negative lookup" do
|
|
822
824
|
@c2.one_to_one :parent, :class => @c2
|
|
823
|
-
|
|
824
|
-
def ds.fetch_rows(sql, &block)
|
|
825
|
-
MODEL_DB.sqls << sql
|
|
826
|
-
end
|
|
827
|
-
|
|
825
|
+
@c2.dataset._fetch = []
|
|
828
826
|
d = @c2.new(:id => 555)
|
|
829
827
|
MODEL_DB.sqls.should == []
|
|
830
828
|
d.parent.should == nil
|
|
831
829
|
MODEL_DB.sqls.should == ['SELECT * FROM nodes WHERE (nodes.node_id = 555) LIMIT 1']
|
|
832
830
|
d.parent.should == nil
|
|
833
|
-
MODEL_DB.sqls.should == [
|
|
831
|
+
MODEL_DB.sqls.should == []
|
|
834
832
|
end
|
|
835
833
|
|
|
836
834
|
it "should define a setter method" do
|
|
@@ -838,28 +836,44 @@ describe Sequel::Model, "one_to_one" do
|
|
|
838
836
|
|
|
839
837
|
d = @c2.new(:id => 1)
|
|
840
838
|
f = @c2.new(:id => 3, :node_id=> 4321)
|
|
839
|
+
@c2.dataset._fetch = {:id => 3, :node_id=>1}
|
|
841
840
|
d.parent = f
|
|
842
841
|
f.values.should == {:id => 3, :node_id=>1}
|
|
843
842
|
d.parent.should == f
|
|
843
|
+
sqls = MODEL_DB.sqls
|
|
844
|
+
["INSERT INTO nodes (node_id, id) VALUES (1, 3)",
|
|
845
|
+
"INSERT INTO nodes (id, node_id) VALUES (3, 1)"].should include(sqls.slice! 1)
|
|
846
|
+
sqls.should == ["UPDATE nodes SET node_id = NULL WHERE ((node_id = 1) AND (id != 3))", "SELECT * FROM nodes WHERE (id = 3) LIMIT 1"]
|
|
844
847
|
|
|
845
848
|
d.parent = nil
|
|
846
849
|
d.parent.should == nil
|
|
850
|
+
MODEL_DB.sqls.should == ["UPDATE nodes SET node_id = NULL WHERE (node_id = 1)"]
|
|
847
851
|
end
|
|
848
852
|
|
|
849
853
|
it "should have the setter method respect the :primary_key option" do
|
|
850
854
|
@c2.one_to_one :parent, :class => @c2, :primary_key=>:blah
|
|
851
855
|
d = @c2.new(:id => 1, :blah => 3)
|
|
852
856
|
e = @c2.new(:id => 4321, :node_id=>444)
|
|
857
|
+
@c2.dataset._fetch = {:id => 4321, :node_id => 3}
|
|
853
858
|
d.parent = e
|
|
854
859
|
e.values.should == {:id => 4321, :node_id => 3}
|
|
860
|
+
sqls = MODEL_DB.sqls
|
|
861
|
+
["INSERT INTO nodes (node_id, id) VALUES (3, 4321)",
|
|
862
|
+
"INSERT INTO nodes (id, node_id) VALUES (4321, 3)"].should include(sqls.slice! 1)
|
|
863
|
+
sqls.should == ["UPDATE nodes SET node_id = NULL WHERE ((node_id = 3) AND (id != 4321))", "SELECT * FROM nodes WHERE (id = 4321) LIMIT 1"]
|
|
855
864
|
end
|
|
856
865
|
|
|
857
866
|
it "should have the setter method respect the :key option" do
|
|
858
867
|
@c2.one_to_one :parent, :class => @c2, :key=>:blah
|
|
859
868
|
d = @c2.new(:id => 3)
|
|
860
869
|
e = @c2.new(:id => 4321, :blah=>444)
|
|
870
|
+
@c2.dataset._fetch = {:id => 4321, :blah => 3}
|
|
861
871
|
d.parent = e
|
|
862
872
|
e.values.should == {:id => 4321, :blah => 3}
|
|
873
|
+
sqls = MODEL_DB.sqls
|
|
874
|
+
["INSERT INTO nodes (blah, id) VALUES (3, 4321)",
|
|
875
|
+
"INSERT INTO nodes (id, blah) VALUES (4321, 3)"].should include(sqls.slice! 1)
|
|
876
|
+
sqls.should == ["UPDATE nodes SET blah = NULL WHERE ((blah = 3) AND (id != 4321))", "SELECT * FROM nodes WHERE (id = 4321) LIMIT 1"]
|
|
863
877
|
end
|
|
864
878
|
|
|
865
879
|
it "should persist changes to associated object when the setter is called" do
|
|
@@ -875,12 +889,11 @@ describe Sequel::Model, "one_to_one" do
|
|
|
875
889
|
|
|
876
890
|
d = @c2.load(:id => 1)
|
|
877
891
|
d.associations[:parent].should == nil
|
|
878
|
-
|
|
879
|
-
def ds.fetch_rows(sql, &block); MODEL_DB.sqls << sql; yield({:id=>234}) end
|
|
892
|
+
@c2.dataset._fetch = {:id=>234}
|
|
880
893
|
e = d.parent
|
|
881
894
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (nodes.node_id = 1) LIMIT 1"]
|
|
882
895
|
d.parent
|
|
883
|
-
MODEL_DB.sqls.should == [
|
|
896
|
+
MODEL_DB.sqls.should == []
|
|
884
897
|
d.associations[:parent].should == e
|
|
885
898
|
end
|
|
886
899
|
|
|
@@ -922,7 +935,6 @@ describe Sequel::Model, "one_to_one" do
|
|
|
922
935
|
e.child.should == d
|
|
923
936
|
MODEL_DB.sqls.should == ["UPDATE nodes SET parent_id = NULL WHERE ((parent_id = 1) AND (id != 2))",
|
|
924
937
|
"UPDATE nodes SET parent_id = 1 WHERE (id = 2)"]
|
|
925
|
-
MODEL_DB.reset
|
|
926
938
|
d.parent = nil
|
|
927
939
|
e.child.should == nil
|
|
928
940
|
MODEL_DB.sqls.should == ["UPDATE nodes SET parent_id = NULL WHERE (parent_id = 1)"]
|
|
@@ -931,17 +943,13 @@ describe Sequel::Model, "one_to_one" do
|
|
|
931
943
|
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
944
|
@c2.one_to_one :parent, :class => @c2, :key=>:parent_id
|
|
933
945
|
@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
|
|
946
|
+
@c2.dataset._fetch = []
|
|
938
947
|
|
|
939
948
|
d = @c2.load(:id => 1)
|
|
940
949
|
e = @c2.load(:id => 2)
|
|
941
950
|
f = @c2.load(:id => 3)
|
|
942
951
|
e.child.should == nil
|
|
943
952
|
f.child.should == nil
|
|
944
|
-
MODEL_DB.reset
|
|
945
953
|
d.parent = e
|
|
946
954
|
e.child.should == d
|
|
947
955
|
d.parent = f
|
|
@@ -983,12 +991,12 @@ describe Sequel::Model, "one_to_one" do
|
|
|
983
991
|
h = []
|
|
984
992
|
@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
993
|
@c2.class_eval do
|
|
986
|
-
|
|
994
|
+
self::Foo = h
|
|
987
995
|
def blah(x)
|
|
988
|
-
|
|
996
|
+
model::Foo << (x ? x.pk : :x)
|
|
989
997
|
end
|
|
990
998
|
def blahr(x)
|
|
991
|
-
|
|
999
|
+
model::Foo << 6
|
|
992
1000
|
end
|
|
993
1001
|
end
|
|
994
1002
|
p = @c2.load(:id=>10)
|
|
@@ -1004,13 +1012,11 @@ describe Sequel::Model, "one_to_one" do
|
|
|
1004
1012
|
h = []
|
|
1005
1013
|
@c2.one_to_one :parent, :class => @c2, :after_load=>[proc{|x,y| h << [x.pk, y.pk]}, :al]
|
|
1006
1014
|
@c2.class_eval do
|
|
1007
|
-
|
|
1015
|
+
self::Foo = h
|
|
1008
1016
|
def al(v)
|
|
1009
|
-
|
|
1010
|
-
end
|
|
1011
|
-
def @dataset.fetch_rows(sql)
|
|
1012
|
-
yield({:id=>20})
|
|
1017
|
+
model::Foo << v.pk
|
|
1013
1018
|
end
|
|
1019
|
+
@dataset._fetch = {:id=>20}
|
|
1014
1020
|
end
|
|
1015
1021
|
p = @c2.load(:id=>10)
|
|
1016
1022
|
parent = p.parent
|
|
@@ -1048,15 +1054,15 @@ describe Sequel::Model, "one_to_one" do
|
|
|
1048
1054
|
h = []
|
|
1049
1055
|
@c2.one_to_one :parent, :class => @c2, :before_set=>:bs, :after_set=>:as
|
|
1050
1056
|
@c2.class_eval do
|
|
1051
|
-
|
|
1057
|
+
self::Foo = h
|
|
1052
1058
|
def []=(a, v)
|
|
1053
|
-
a == :node_id ? (
|
|
1059
|
+
a == :node_id ? (model::Foo << 5) : super
|
|
1054
1060
|
end
|
|
1055
1061
|
def bs(x)
|
|
1056
|
-
|
|
1062
|
+
model::Foo << x.pk
|
|
1057
1063
|
end
|
|
1058
1064
|
def as(x)
|
|
1059
|
-
|
|
1065
|
+
model::Foo << x.pk * 2
|
|
1060
1066
|
end
|
|
1061
1067
|
end
|
|
1062
1068
|
p.parent = c
|
|
@@ -1072,16 +1078,9 @@ end
|
|
|
1072
1078
|
|
|
1073
1079
|
describe Sequel::Model, "one_to_many" do
|
|
1074
1080
|
before do
|
|
1075
|
-
MODEL_DB.reset
|
|
1076
|
-
|
|
1077
1081
|
@c1 = Class.new(Sequel::Model(:attributes)) do
|
|
1078
|
-
def _refresh(ds); end
|
|
1079
1082
|
unrestrict_primary_key
|
|
1080
1083
|
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
1084
|
end
|
|
1086
1085
|
|
|
1087
1086
|
@c2 = Class.new(Sequel::Model(:nodes)) do
|
|
@@ -1094,68 +1093,58 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1094
1093
|
columns :id, :x
|
|
1095
1094
|
end
|
|
1096
1095
|
@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
|
-
})
|
|
1096
|
+
@dataset._fetch = {}
|
|
1097
|
+
@c1.dataset._fetch = proc{|sql| sql =~ /SELECT 1/ ? {:a=>1} : {}}
|
|
1098
|
+
MODEL_DB.reset
|
|
1113
1099
|
end
|
|
1114
1100
|
|
|
1115
1101
|
it "should use implicit key if omitted" do
|
|
1116
1102
|
@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)'
|
|
1103
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE (attributes.node_id = 1234)'
|
|
1122
1104
|
end
|
|
1123
1105
|
|
|
1124
1106
|
it "should use implicit class if omitted" do
|
|
1125
|
-
|
|
1107
|
+
begin
|
|
1108
|
+
class ::HistoricalValue < Sequel::Model; end
|
|
1109
|
+
@c2.one_to_many :historical_values
|
|
1110
|
+
|
|
1111
|
+
v = @c2.new(:id => 1234).historical_values_dataset
|
|
1112
|
+
v.should be_a_kind_of(Sequel::Dataset)
|
|
1113
|
+
v.sql.should == 'SELECT * FROM historical_values WHERE (historical_values.node_id = 1234)'
|
|
1114
|
+
v.model.should == HistoricalValue
|
|
1115
|
+
ensure
|
|
1116
|
+
Object.send(:remove_const, :HistoricalValue)
|
|
1126
1117
|
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
1118
|
end
|
|
1136
1119
|
|
|
1137
1120
|
it "should use class inside a module if given as a string" do
|
|
1138
|
-
|
|
1139
|
-
|
|
1121
|
+
begin
|
|
1122
|
+
module ::Historical
|
|
1123
|
+
class Value < Sequel::Model; end
|
|
1140
1124
|
end
|
|
1125
|
+
@c2.one_to_many :historical_values, :class=>'Historical::Value'
|
|
1126
|
+
|
|
1127
|
+
v = @c2.new(:id => 1234).historical_values_dataset
|
|
1128
|
+
v.should be_a_kind_of(Sequel::Dataset)
|
|
1129
|
+
v.sql.should == 'SELECT * FROM values WHERE (values.node_id = 1234)'
|
|
1130
|
+
v.model.should == Historical::Value
|
|
1131
|
+
ensure
|
|
1132
|
+
Object.send(:remove_const, :Historical)
|
|
1141
1133
|
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
1134
|
end
|
|
1151
1135
|
|
|
1152
|
-
it "should use
|
|
1136
|
+
it "should use a callback if given one as the argument" do
|
|
1153
1137
|
@c2.one_to_many :attributes, :class => @c1, :key => :nodeid
|
|
1154
1138
|
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1139
|
+
d = @c2.load(:id => 1234)
|
|
1140
|
+
d.associations[:attributes] = []
|
|
1141
|
+
d.attributes(proc{|ds| ds.filter{name > 'M'}}).should_not == []
|
|
1142
|
+
MODEL_DB.sqls.should == ["SELECT * FROM attributes WHERE ((attributes.nodeid = 1234) AND (name > 'M'))"]
|
|
1143
|
+
end
|
|
1144
|
+
|
|
1145
|
+
it "should use explicit key if given" do
|
|
1146
|
+
@c2.one_to_many :attributes, :class => @c1, :key => :nodeid
|
|
1147
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE (attributes.nodeid = 1234)'
|
|
1159
1148
|
end
|
|
1160
1149
|
|
|
1161
1150
|
it "should support_composite keys" do
|
|
@@ -1180,10 +1169,8 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1180
1169
|
it "should define an add_ method that works on existing records" do
|
|
1181
1170
|
@c2.one_to_many :attributes, :class => @c1
|
|
1182
1171
|
|
|
1183
|
-
n = @c2.
|
|
1184
|
-
a = @c1.
|
|
1185
|
-
a.save
|
|
1186
|
-
MODEL_DB.reset
|
|
1172
|
+
n = @c2.load(:id => 1234)
|
|
1173
|
+
a = @c1.load(:id => 2345)
|
|
1187
1174
|
a.should == n.add_attribute(a)
|
|
1188
1175
|
a.values.should == {:node_id => 1234, :id => 2345}
|
|
1189
1176
|
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 1234 WHERE (id = 2345)']
|
|
@@ -1192,52 +1179,53 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1192
1179
|
it "should define an add_ method that works on new records" do
|
|
1193
1180
|
@c2.one_to_many :attributes, :class => @c1
|
|
1194
1181
|
|
|
1195
|
-
n = @c2.
|
|
1182
|
+
n = @c2.load(:id => 1234)
|
|
1196
1183
|
a = @c1.new(:id => 234)
|
|
1197
|
-
|
|
1198
|
-
MODEL_DB.reset
|
|
1184
|
+
@c1.dataset._fetch = {:node_id => 1234, :id => 234}
|
|
1199
1185
|
a.should == n.add_attribute(a)
|
|
1200
|
-
MODEL_DB.sqls
|
|
1186
|
+
sqls = MODEL_DB.sqls
|
|
1187
|
+
sqls.shift.should =~ /INSERT INTO attributes \((node_)?id, (node_)?id\) VALUES \(1?234, 1?234\)/
|
|
1188
|
+
sqls.should == ["SELECT * FROM attributes WHERE (id = 234) LIMIT 1"]
|
|
1201
1189
|
a.values.should == {:node_id => 1234, :id => 234}
|
|
1202
1190
|
end
|
|
1203
1191
|
|
|
1204
1192
|
it "should define a remove_ method that works on existing records" do
|
|
1205
1193
|
@c2.one_to_many :attributes, :class => @c1
|
|
1206
1194
|
|
|
1207
|
-
n = @c2.
|
|
1208
|
-
a = @c1.
|
|
1209
|
-
a.save
|
|
1210
|
-
MODEL_DB.reset
|
|
1195
|
+
n = @c2.load(:id => 1234)
|
|
1196
|
+
a = @c1.load(:id => 2345, :node_id => 1234)
|
|
1211
1197
|
a.should == n.remove_attribute(a)
|
|
1212
1198
|
a.values.should == {:node_id => nil, :id => 2345}
|
|
1213
|
-
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = NULL WHERE (id = 2345)']
|
|
1199
|
+
MODEL_DB.sqls.should == ["SELECT 1 AS one FROM attributes WHERE ((attributes.node_id = 1234) AND (id = 2345)) LIMIT 1", 'UPDATE attributes SET node_id = NULL WHERE (id = 2345)']
|
|
1214
1200
|
end
|
|
1215
1201
|
|
|
1216
1202
|
it "should have the remove_ method raise an error if the passed object is not already associated" do
|
|
1217
1203
|
@c2.one_to_many :attributes, :class => @c1
|
|
1218
|
-
@c1.dataset.opts[:empty] = true
|
|
1219
1204
|
|
|
1220
1205
|
n = @c2.new(:id => 1234)
|
|
1221
1206
|
a = @c1.load(:id => 2345, :node_id => 1234)
|
|
1222
|
-
|
|
1207
|
+
@c1.dataset._fetch = []
|
|
1223
1208
|
proc{n.remove_attribute(a)}.should raise_error(Sequel::Error)
|
|
1224
|
-
MODEL_DB.sqls.should == ["SELECT 1 FROM attributes WHERE ((attributes.node_id = 1234) AND (id = 2345)) LIMIT 1"]
|
|
1209
|
+
MODEL_DB.sqls.should == ["SELECT 1 AS one FROM attributes WHERE ((attributes.node_id = 1234) AND (id = 2345)) LIMIT 1"]
|
|
1225
1210
|
end
|
|
1226
1211
|
|
|
1227
1212
|
it "should accept a hash for the add_ method and create a new record" do
|
|
1228
1213
|
@c2.one_to_many :attributes, :class => @c1
|
|
1229
1214
|
n = @c2.new(:id => 1234)
|
|
1230
1215
|
MODEL_DB.reset
|
|
1231
|
-
@c1.
|
|
1232
|
-
|
|
1216
|
+
@c1.dataset._fetch = {:node_id => 1234, :id => 234}
|
|
1217
|
+
n.add_attribute(:id => 234).should == @c1.load(:node_id => 1234, :id => 234)
|
|
1218
|
+
sqls = MODEL_DB.sqls
|
|
1219
|
+
sqls.shift.should =~ /INSERT INTO attributes \((node_)?id, (node_)?id\) VALUES \(1?234, 1?234\)/
|
|
1220
|
+
sqls.should == ["SELECT * FROM attributes WHERE (id = 234) LIMIT 1"]
|
|
1233
1221
|
end
|
|
1234
1222
|
|
|
1235
1223
|
it "should accept a primary key for the add_ method" do
|
|
1236
1224
|
@c2.one_to_many :attributes, :class => @c1
|
|
1237
1225
|
n = @c2.new(:id => 1234)
|
|
1238
|
-
|
|
1239
|
-
@c1.load(:node_id => 1234, :id => 234)
|
|
1240
|
-
MODEL_DB.sqls.
|
|
1226
|
+
@c1.dataset._fetch = {:id=>234, :node_id=>nil}
|
|
1227
|
+
n.add_attribute(234).should == @c1.load(:node_id => 1234, :id => 234)
|
|
1228
|
+
MODEL_DB.sqls.should == ["SELECT * FROM attributes WHERE id = 234", "UPDATE attributes SET node_id = 1234 WHERE (id = 234)"]
|
|
1241
1229
|
end
|
|
1242
1230
|
|
|
1243
1231
|
it "should raise an error in the add_ method if the passed associated object is not of the correct type" do
|
|
@@ -1248,13 +1236,8 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1248
1236
|
it "should accept a primary key for the remove_ method and remove an existing record" do
|
|
1249
1237
|
@c2.one_to_many :attributes, :class => @c1
|
|
1250
1238
|
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)
|
|
1239
|
+
@c1.dataset._fetch = {:id=>234, :node_id=>1234}
|
|
1240
|
+
n.remove_attribute(234).should == @c1.load(:node_id => nil, :id => 234)
|
|
1258
1241
|
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (attributes.id = 234)) LIMIT 1',
|
|
1259
1242
|
'UPDATE attributes SET node_id = NULL WHERE (id = 234)']
|
|
1260
1243
|
end
|
|
@@ -1268,10 +1251,8 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1268
1251
|
@c2.one_to_many :attributes, :class => @c1, :primary_key=>:xxx
|
|
1269
1252
|
|
|
1270
1253
|
n = @c2.new(:id => 1234, :xxx=>5)
|
|
1271
|
-
a = @c1.
|
|
1272
|
-
a.
|
|
1273
|
-
MODEL_DB.reset
|
|
1274
|
-
a.should == n.add_attribute(a)
|
|
1254
|
+
a = @c1.load(:id => 2345)
|
|
1255
|
+
n.add_attribute(a).should == a
|
|
1275
1256
|
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 5 WHERE (id = 2345)']
|
|
1276
1257
|
end
|
|
1277
1258
|
|
|
@@ -1279,15 +1260,13 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1279
1260
|
@c2.one_to_many :attributes, :class => @c1
|
|
1280
1261
|
|
|
1281
1262
|
n = @c2.new(:id => 1234)
|
|
1282
|
-
a = @c1.
|
|
1283
|
-
a.save
|
|
1284
|
-
MODEL_DB.reset
|
|
1263
|
+
a = @c1.load(:id => 2345)
|
|
1285
1264
|
n.associations[:attributes] = []
|
|
1286
1265
|
a.should == n.add_attribute(a)
|
|
1287
1266
|
a.should == n.add_attribute(a)
|
|
1288
1267
|
a.values.should == {:node_id => 1234, :id => 2345}
|
|
1289
|
-
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 1234 WHERE (id = 2345)'] * 2
|
|
1290
1268
|
n.attributes.should == [a]
|
|
1269
|
+
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 1234 WHERE (id = 2345)'] * 2
|
|
1291
1270
|
end
|
|
1292
1271
|
|
|
1293
1272
|
it "should have add_ method respect composite keys" do
|
|
@@ -1295,18 +1274,24 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1295
1274
|
|
|
1296
1275
|
n = @c2.load(:id => 1234, :x=>5)
|
|
1297
1276
|
a = @c1.load(:id => 2345)
|
|
1298
|
-
a.should ==
|
|
1299
|
-
|
|
1277
|
+
n.add_attribute(a).should == a
|
|
1278
|
+
sqls = MODEL_DB.sqls
|
|
1279
|
+
sqls.shift.should =~ /UPDATE attributes SET (node_id = 1234|y = 5), (node_id = 1234|y = 5) WHERE \(id = 2345\)/
|
|
1280
|
+
sqls.should == []
|
|
1300
1281
|
end
|
|
1301
1282
|
|
|
1302
1283
|
it "should have add_ method accept a composite key" do
|
|
1303
1284
|
@c1.set_primary_key :id, :z
|
|
1304
1285
|
@c2.one_to_many :attributes, :class => @c1, :key =>[:node_id, :y], :primary_key=>[:id, :x]
|
|
1286
|
+
@c1.dataset._fetch = {:id => 2345, :z => 8, :node_id => 1234, :y=>5}
|
|
1305
1287
|
|
|
1306
1288
|
n = @c2.load(:id => 1234, :x=>5)
|
|
1307
1289
|
a = @c1.load(:id => 2345, :z => 8, :node_id => 1234, :y=>5)
|
|
1308
|
-
|
|
1309
|
-
|
|
1290
|
+
n.add_attribute([2345, 8]).should == a
|
|
1291
|
+
sqls = MODEL_DB.sqls
|
|
1292
|
+
sqls.shift.should =~ /SELECT \* FROM attributes WHERE \(\((id|z) = (2345|8)\) AND \((id|z) = (2345|8)\)\) LIMIT 1/
|
|
1293
|
+
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)\)\)/
|
|
1294
|
+
sqls.should == []
|
|
1310
1295
|
end
|
|
1311
1296
|
|
|
1312
1297
|
it "should have remove_ method respect composite keys" do
|
|
@@ -1314,31 +1299,29 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1314
1299
|
|
|
1315
1300
|
n = @c2.load(:id => 1234, :x=>5)
|
|
1316
1301
|
a = @c1.load(:id => 2345, :node_id=>1234, :y=>5)
|
|
1317
|
-
a.should ==
|
|
1318
|
-
|
|
1302
|
+
n.remove_attribute(a).should == a
|
|
1303
|
+
sqls = MODEL_DB.sqls
|
|
1304
|
+
sqls.pop.should =~ /UPDATE attributes SET (node_id|y) = NULL, (node_id|y) = NULL WHERE \(id = 2345\)/
|
|
1305
|
+
sqls.should == ["SELECT 1 AS one FROM attributes WHERE ((attributes.node_id = 1234) AND (attributes.y = 5) AND (id = 2345)) LIMIT 1"]
|
|
1319
1306
|
end
|
|
1320
1307
|
|
|
1321
1308
|
it "should accept a array of composite primary key values for the remove_ method and remove an existing record" do
|
|
1322
1309
|
@c1.set_primary_key :id, :y
|
|
1323
1310
|
@c2.one_to_many :attributes, :class => @c1, :key=>:node_id, :primary_key=>:id
|
|
1324
1311
|
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)\)\)/
|
|
1312
|
+
@c1.dataset._fetch = {:id=>234, :node_id=>123, :y=>5}
|
|
1313
|
+
n.remove_attribute([234, 5]).should == @c1.load(:node_id => nil, :y => 5, :id => 234)
|
|
1314
|
+
sqls = MODEL_DB.sqls
|
|
1315
|
+
sqls.length.should == 2
|
|
1316
|
+
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/
|
|
1317
|
+
sqls.last.should =~ /UPDATE attributes SET node_id = NULL WHERE \(\((id|y) = (234|5)\) AND \((id|y) = (234|5)\)\)/
|
|
1335
1318
|
end
|
|
1336
1319
|
|
|
1337
1320
|
it "should raise an error in add_ and remove_ if the passed object returns false to save (is not valid)" do
|
|
1338
1321
|
@c2.one_to_many :attributes, :class => @c1
|
|
1339
1322
|
n = @c2.new(:id => 1234)
|
|
1340
1323
|
a = @c1.new(:id => 2345)
|
|
1341
|
-
def a.
|
|
1324
|
+
def a.validate() errors.add(:id, 'foo') end
|
|
1342
1325
|
proc{n.add_attribute(a)}.should raise_error(Sequel::Error)
|
|
1343
1326
|
proc{n.remove_attribute(a)}.should raise_error(Sequel::Error)
|
|
1344
1327
|
end
|
|
@@ -1347,7 +1330,7 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1347
1330
|
@c2.one_to_many :attributes, :class => @c1, :validate=>false
|
|
1348
1331
|
n = @c2.new(:id => 1234)
|
|
1349
1332
|
a = @c1.new(:id => 2345)
|
|
1350
|
-
def a.
|
|
1333
|
+
def a.validate() errors.add(:id, 'foo') end
|
|
1351
1334
|
n.add_attribute(a).should == a
|
|
1352
1335
|
n.remove_attribute(a).should == a
|
|
1353
1336
|
end
|
|
@@ -1364,81 +1347,48 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1364
1347
|
|
|
1365
1348
|
it "should use :primary_key option if given" do
|
|
1366
1349
|
@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)"
|
|
1350
|
+
@c1.load(:id => 1234, :node_id=>4321).nodes_dataset.sql.should == "SELECT * FROM nodes WHERE (nodes.id = 4321)"
|
|
1369
1351
|
end
|
|
1370
1352
|
|
|
1371
1353
|
it "should support a select option" do
|
|
1372
1354
|
@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)"
|
|
1355
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == "SELECT id, name FROM attributes WHERE (attributes.node_id = 1234)"
|
|
1376
1356
|
end
|
|
1377
1357
|
|
|
1378
1358
|
it "should support a conditions option" do
|
|
1379
1359
|
@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))"
|
|
1360
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == "SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (a = 32))"
|
|
1382
1361
|
@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)"
|
|
1362
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == "SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND NOT a)"
|
|
1385
1363
|
end
|
|
1386
1364
|
|
|
1387
1365
|
it "should support an order option" do
|
|
1388
1366
|
@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"
|
|
1367
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == "SELECT * FROM attributes WHERE (attributes.node_id = 1234) ORDER BY kind"
|
|
1392
1368
|
end
|
|
1393
1369
|
|
|
1394
1370
|
it "should support an array for the order option" do
|
|
1395
1371
|
@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"
|
|
1372
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == "SELECT * FROM attributes WHERE (attributes.node_id = 1234) ORDER BY kind1, kind2"
|
|
1399
1373
|
end
|
|
1400
1374
|
|
|
1401
1375
|
it "should return array with all members of the association" do
|
|
1402
1376
|
@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)']
|
|
1377
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE (attributes.node_id = 1234)'
|
|
1412
1378
|
end
|
|
1413
1379
|
|
|
1414
1380
|
it "should accept a block" do
|
|
1415
1381
|
@c2.one_to_many :attributes, :class => @c1 do |ds|
|
|
1416
1382
|
ds.filter(:xxx => @xxx)
|
|
1417
1383
|
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))']
|
|
1384
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (xxx IS NULL))'
|
|
1427
1385
|
end
|
|
1428
1386
|
|
|
1429
1387
|
it "should support :order option with block" do
|
|
1430
1388
|
@c2.one_to_many :attributes, :class => @c1, :order => :kind do |ds|
|
|
1431
1389
|
ds.filter(:xxx => @xxx)
|
|
1432
1390
|
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']
|
|
1391
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (xxx IS NULL)) ORDER BY kind'
|
|
1442
1392
|
end
|
|
1443
1393
|
|
|
1444
1394
|
it "should have the block argument affect the _dataset method" do
|
|
@@ -1450,18 +1400,11 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1450
1400
|
|
|
1451
1401
|
it "should support a :dataset option that is used instead of the default" do
|
|
1452
1402
|
c1 = @c1
|
|
1453
|
-
@c2.one_to_many :all_other_attributes, :class => @c1, :dataset=>proc{c1.
|
|
1403
|
+
@c2.one_to_many :all_other_attributes, :class => @c1, :dataset=>proc{c1.exclude(:nodeid=>pk)}, :order=>:a, :limit=>10 do |ds|
|
|
1454
1404
|
ds.filter(:xxx => 5)
|
|
1455
1405
|
end
|
|
1456
|
-
|
|
1457
1406
|
@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
|
-
|
|
1407
|
+
@c2.new(:id => 1234).all_other_attributes.should == [@c1.load({})]
|
|
1465
1408
|
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE ((nodeid != 1234) AND (xxx = 5)) ORDER BY a LIMIT 10']
|
|
1466
1409
|
end
|
|
1467
1410
|
|
|
@@ -1479,9 +1422,7 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1479
1422
|
|
|
1480
1423
|
it "should set cached instance variable when accessed" do
|
|
1481
1424
|
@c2.one_to_many :attributes, :class => @c1
|
|
1482
|
-
|
|
1483
1425
|
n = @c2.new(:id => 1234)
|
|
1484
|
-
MODEL_DB.reset
|
|
1485
1426
|
n.associations.include?(:attributes).should == false
|
|
1486
1427
|
atts = n.attributes
|
|
1487
1428
|
atts.should == n.associations[:attributes]
|
|
@@ -1490,9 +1431,7 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1490
1431
|
|
|
1491
1432
|
it "should use cached instance variable if available" do
|
|
1492
1433
|
@c2.one_to_many :attributes, :class => @c1
|
|
1493
|
-
|
|
1494
1434
|
n = @c2.new(:id => 1234)
|
|
1495
|
-
MODEL_DB.reset
|
|
1496
1435
|
n.associations[:attributes] = 42
|
|
1497
1436
|
n.attributes.should == 42
|
|
1498
1437
|
MODEL_DB.sqls.should == []
|
|
@@ -1500,9 +1439,7 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1500
1439
|
|
|
1501
1440
|
it "should not use cached instance variable if asked to reload" do
|
|
1502
1441
|
@c2.one_to_many :attributes, :class => @c1
|
|
1503
|
-
|
|
1504
1442
|
n = @c2.new(:id => 1234)
|
|
1505
|
-
MODEL_DB.reset
|
|
1506
1443
|
n.associations[:attributes] = 42
|
|
1507
1444
|
n.attributes(true).should_not == 42
|
|
1508
1445
|
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE (attributes.node_id = 1234)']
|
|
@@ -1510,10 +1447,8 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1510
1447
|
|
|
1511
1448
|
it "should add item to cached instance variable if it exists when calling add_" do
|
|
1512
1449
|
@c2.one_to_many :attributes, :class => @c1
|
|
1513
|
-
|
|
1514
1450
|
n = @c2.new(:id => 1234)
|
|
1515
|
-
att = @c1.
|
|
1516
|
-
MODEL_DB.reset
|
|
1451
|
+
att = @c1.load(:id => 345)
|
|
1517
1452
|
a = []
|
|
1518
1453
|
n.associations[:attributes] = a
|
|
1519
1454
|
n.add_attribute(att)
|
|
@@ -1535,7 +1470,6 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1535
1470
|
|
|
1536
1471
|
n = @c2.load(:id => 1234)
|
|
1537
1472
|
att = @c1.load(:id => 345)
|
|
1538
|
-
MODEL_DB.reset
|
|
1539
1473
|
a = [att]
|
|
1540
1474
|
n.associations[:attributes] = a
|
|
1541
1475
|
n.remove_attribute(att)
|
|
@@ -1587,13 +1521,9 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1587
1521
|
n = @c2.new(:id => 1234)
|
|
1588
1522
|
atts = n.attributes
|
|
1589
1523
|
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
|
|
1524
|
+
atts.should == [@c1.load({})]
|
|
1525
|
+
atts.map{|a| a.node}.should == [n]
|
|
1526
|
+
MODEL_DB.sqls.should == []
|
|
1597
1527
|
end
|
|
1598
1528
|
|
|
1599
1529
|
it "should use an explicit reciprocal instance variable if given" do
|
|
@@ -1602,19 +1532,15 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1602
1532
|
n = @c2.new(:id => 1234)
|
|
1603
1533
|
atts = n.attributes
|
|
1604
1534
|
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
|
|
1535
|
+
atts.should == [@c1.load({})]
|
|
1536
|
+
atts.map{|a| a.associations[:wxyz]}.should == [n]
|
|
1537
|
+
MODEL_DB.sqls.should == []
|
|
1612
1538
|
end
|
|
1613
1539
|
|
|
1614
1540
|
it "should have an remove_all_ method that removes all associations" do
|
|
1615
1541
|
@c2.one_to_many :attributes, :class => @c1
|
|
1616
1542
|
@c2.new(:id => 1234).remove_all_attributes
|
|
1617
|
-
MODEL_DB.sqls.
|
|
1543
|
+
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = NULL WHERE (node_id = 1234)']
|
|
1618
1544
|
end
|
|
1619
1545
|
|
|
1620
1546
|
it "should have remove_all method respect association filters" do
|
|
@@ -1628,13 +1554,15 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1628
1554
|
it "should have the remove_all_ method respect the :primary_key option" do
|
|
1629
1555
|
@c2.one_to_many :attributes, :class => @c1, :primary_key=>:xxx
|
|
1630
1556
|
@c2.new(:id => 1234, :xxx=>5).remove_all_attributes
|
|
1631
|
-
MODEL_DB.sqls.
|
|
1557
|
+
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = NULL WHERE (node_id = 5)']
|
|
1632
1558
|
end
|
|
1633
1559
|
|
|
1634
1560
|
it "should have the remove_all_ method respect composite keys" do
|
|
1635
1561
|
@c2.one_to_many :attributes, :class => @c1, :key=>[:node_id, :y], :primary_key=>[:id, :x]
|
|
1636
1562
|
@c2.new(:id => 1234, :x=>5).remove_all_attributes
|
|
1637
|
-
|
|
1563
|
+
sqls = MODEL_DB.sqls
|
|
1564
|
+
sqls.pop.should =~ /UPDATE attributes SET (node_id|y) = NULL, (node_id|y) = NULL WHERE \(\(node_id = 1234\) AND \(y = 5\)\)/
|
|
1565
|
+
sqls.should == []
|
|
1638
1566
|
end
|
|
1639
1567
|
|
|
1640
1568
|
it "remove_all should set the cached instance variable to []" do
|
|
@@ -1648,10 +1576,8 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1648
1576
|
@c2.one_to_many :attributes, :class => @c1
|
|
1649
1577
|
attrib = @c1.new(:id=>3)
|
|
1650
1578
|
node = @c2.new(:id => 1234)
|
|
1651
|
-
|
|
1652
|
-
def d.fetch_rows(s); end
|
|
1579
|
+
@c1.dataset._fetch = [[], [{:id=>3, :node_id=>1234}]]
|
|
1653
1580
|
node.attributes.should == []
|
|
1654
|
-
def attrib.save(*); self end
|
|
1655
1581
|
node.add_attribute(attrib)
|
|
1656
1582
|
node.associations[:attributes].should == [attrib]
|
|
1657
1583
|
node.remove_all_attributes.should == [attrib]
|
|
@@ -1665,15 +1591,12 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1665
1591
|
it "remove_all should remove the current item from all reciprocal instance varaibles if it cached instance variable exists" do
|
|
1666
1592
|
@c2.one_to_many :attributes, :class => @c1
|
|
1667
1593
|
@c1.many_to_one :node, :class => @c2
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
d = @c2.dataset
|
|
1671
|
-
def d.fetch_rows(s); end
|
|
1594
|
+
@c2.dataset._fetch = []
|
|
1595
|
+
@c1.dataset._fetch = [[], [{:id=>3, :node_id=>1234}]]
|
|
1672
1596
|
attrib = @c1.new(:id=>3)
|
|
1673
|
-
node = @c2.
|
|
1597
|
+
node = @c2.load(:id => 1234)
|
|
1674
1598
|
node.attributes.should == []
|
|
1675
1599
|
attrib.node.should == nil
|
|
1676
|
-
def attrib.save(*); self end
|
|
1677
1600
|
node.add_attribute(attrib)
|
|
1678
1601
|
attrib.associations[:node].should == node
|
|
1679
1602
|
node.remove_all_attributes
|
|
@@ -1761,18 +1684,18 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1761
1684
|
h = []
|
|
1762
1685
|
@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
1686
|
@c2.class_eval do
|
|
1764
|
-
|
|
1687
|
+
self::Foo = h
|
|
1765
1688
|
def _add_attribute(v)
|
|
1766
|
-
|
|
1689
|
+
model::Foo << 4
|
|
1767
1690
|
end
|
|
1768
1691
|
def _remove_attribute(v)
|
|
1769
|
-
|
|
1692
|
+
model::Foo << 5
|
|
1770
1693
|
end
|
|
1771
1694
|
def blah(x)
|
|
1772
|
-
|
|
1695
|
+
model::Foo << x.pk
|
|
1773
1696
|
end
|
|
1774
1697
|
def blahr(x)
|
|
1775
|
-
|
|
1698
|
+
model::Foo << 6
|
|
1776
1699
|
end
|
|
1777
1700
|
end
|
|
1778
1701
|
p = @c2.load(:id=>10)
|
|
@@ -1788,17 +1711,12 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1788
1711
|
h = []
|
|
1789
1712
|
@c2.one_to_many :attributes, :class => @c1, :after_load=>[proc{|x,y| h << [x.pk, y.collect{|z|z.pk}]}, :al]
|
|
1790
1713
|
@c2.class_eval do
|
|
1791
|
-
|
|
1714
|
+
self::Foo = h
|
|
1792
1715
|
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})
|
|
1716
|
+
v.each{|x| model::Foo << x.pk}
|
|
1800
1717
|
end
|
|
1801
1718
|
end
|
|
1719
|
+
@c1.dataset._fetch = [{:id=>20}, {:id=>30}]
|
|
1802
1720
|
p = @c2.load(:id=>10, :parent_id=>20)
|
|
1803
1721
|
attributes = p.attributes
|
|
1804
1722
|
h.should == [[10, [20, 30]], 20, 30]
|
|
@@ -1845,23 +1763,13 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1845
1763
|
end
|
|
1846
1764
|
|
|
1847
1765
|
describe Sequel::Model, "many_to_many" do
|
|
1848
|
-
|
|
1849
1766
|
before do
|
|
1850
|
-
MODEL_DB.reset
|
|
1851
|
-
|
|
1852
1767
|
@c1 = Class.new(Sequel::Model(:attributes)) do
|
|
1853
1768
|
unrestrict_primary_key
|
|
1854
1769
|
attr_accessor :yyy
|
|
1855
1770
|
def self.name; 'Attribute'; end
|
|
1856
1771
|
def self.to_s; 'Attribute'; end
|
|
1857
1772
|
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
1773
|
end
|
|
1866
1774
|
|
|
1867
1775
|
@c2 = Class.new(Sequel::Model(:nodes)) do
|
|
@@ -1873,98 +1781,61 @@ describe Sequel::Model, "many_to_many" do
|
|
|
1873
1781
|
columns :id, :x
|
|
1874
1782
|
end
|
|
1875
1783
|
@dataset = @c2.dataset
|
|
1784
|
+
@c1.dataset.autoid = 1
|
|
1876
1785
|
|
|
1877
|
-
[@c1, @c2].each
|
|
1878
|
-
|
|
1879
|
-
def fetch_rows(sql)
|
|
1880
|
-
@db << sql
|
|
1881
|
-
yield Hash.new
|
|
1882
|
-
end
|
|
1883
|
-
})
|
|
1884
|
-
end
|
|
1786
|
+
[@c1, @c2].each{|c| c.dataset._fetch = {}}
|
|
1787
|
+
MODEL_DB.reset
|
|
1885
1788
|
end
|
|
1886
1789
|
|
|
1887
1790
|
it "should use implicit key values and join table if omitted" do
|
|
1888
1791
|
@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))'
|
|
1792
|
+
@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
1793
|
end
|
|
1895
1794
|
|
|
1896
1795
|
it "should use implicit class if omitted" do
|
|
1897
|
-
|
|
1796
|
+
begin
|
|
1797
|
+
class ::Tag < Sequel::Model; end
|
|
1798
|
+
@c2.many_to_many :tags
|
|
1799
|
+
@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))'
|
|
1800
|
+
ensure
|
|
1801
|
+
Object.send(:remove_const, :Tag)
|
|
1898
1802
|
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
1803
|
end
|
|
1907
1804
|
|
|
1908
1805
|
it "should use class inside module if given as a string" do
|
|
1909
|
-
|
|
1910
|
-
|
|
1806
|
+
begin
|
|
1807
|
+
module ::Historical
|
|
1808
|
+
class Tag < Sequel::Model; end
|
|
1911
1809
|
end
|
|
1810
|
+
@c2.many_to_many :tags, :class=>'::Historical::Tag'
|
|
1811
|
+
@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))'
|
|
1812
|
+
ensure
|
|
1813
|
+
Object.send(:remove_const, :Historical)
|
|
1912
1814
|
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
1815
|
end
|
|
1921
1816
|
|
|
1922
1817
|
it "should use explicit key values and join table if given" do
|
|
1923
1818
|
@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'
|
|
1819
|
+
@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
1820
|
end
|
|
1937
1821
|
|
|
1938
1822
|
it "should support a conditions option" do
|
|
1939
1823
|
@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)'
|
|
1824
|
+
@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)'
|
|
1825
|
+
|
|
1944
1826
|
@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({})]
|
|
1827
|
+
@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)'
|
|
1828
|
+
@c2.new(:id => 1234).attributes.should == [@c1.load({})]
|
|
1950
1829
|
end
|
|
1951
1830
|
|
|
1952
1831
|
it "should support an order option" do
|
|
1953
1832
|
@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'
|
|
1833
|
+
@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
1834
|
end
|
|
1960
1835
|
|
|
1961
1836
|
it "should support an array for the order option" do
|
|
1962
1837
|
@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'
|
|
1838
|
+
@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
1839
|
end
|
|
1969
1840
|
|
|
1970
1841
|
it "should support :left_primary_key and :right_primary_key options" do
|
|
@@ -1999,19 +1870,13 @@ describe Sequel::Model, "many_to_many" do
|
|
|
1999
1870
|
it "should support a select option" do
|
|
2000
1871
|
@c2.many_to_many :attributes, :class => @c1, :select => :blah
|
|
2001
1872
|
|
|
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))'
|
|
1873
|
+
@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
1874
|
end
|
|
2007
1875
|
|
|
2008
1876
|
it "should support an array for the select option" do
|
|
2009
1877
|
@c2.many_to_many :attributes, :class => @c1, :select => [:attributes.*, :attribute_nodes__blah2]
|
|
2010
1878
|
|
|
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))'
|
|
1879
|
+
@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
1880
|
end
|
|
2016
1881
|
|
|
2017
1882
|
it "should accept a block" do
|
|
@@ -2021,11 +1886,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2021
1886
|
|
|
2022
1887
|
n = @c2.new(:id => 1234)
|
|
2023
1888
|
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)'
|
|
1889
|
+
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
1890
|
end
|
|
2030
1891
|
|
|
2031
1892
|
it "should allow the :order option while accepting a block" do
|
|
@@ -2035,20 +1896,9 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2035
1896
|
|
|
2036
1897
|
n = @c2.new(:id => 1234)
|
|
2037
1898
|
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'
|
|
1899
|
+
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
1900
|
end
|
|
2044
1901
|
|
|
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
1902
|
it "should support a :dataset option that is used instead of the default" do
|
|
2053
1903
|
c1 = @c1
|
|
2054
1904
|
@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 +1908,8 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2058
1908
|
n = @c2.new(:id => 1234)
|
|
2059
1909
|
n.xxx = 555
|
|
2060
1910
|
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'
|
|
1911
|
+
n.attributes.should == [@c1.load({})]
|
|
1912
|
+
MODEL_DB.sqls.should == ['SELECT * FROM attributes NATURAL JOIN an WHERE ((an.nodeid = 1234) AND (xxx = 555)) ORDER BY a LIMIT 10']
|
|
2066
1913
|
end
|
|
2067
1914
|
|
|
2068
1915
|
it "should support a :limit option" do
|
|
@@ -2077,15 +1924,32 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2077
1924
|
@c2.new(:id => 1234).attributes_dataset.opts[:eager].should == {:attributes=>nil}
|
|
2078
1925
|
end
|
|
2079
1926
|
|
|
1927
|
+
it "should handle an aliased join table" do
|
|
1928
|
+
@c2.many_to_many :attributes, :class => @c1, :join_table => :attribute2node___attributes_nodes
|
|
1929
|
+
n = @c2.load(:id => 1234)
|
|
1930
|
+
a = @c1.load(:id => 2345)
|
|
1931
|
+
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))"
|
|
1932
|
+
a.should == n.add_attribute(a)
|
|
1933
|
+
a.should == n.remove_attribute(a)
|
|
1934
|
+
n.remove_all_attributes
|
|
1935
|
+
sqls = MODEL_DB.sqls
|
|
1936
|
+
['INSERT INTO attribute2node (node_id, attribute_id) VALUES (1234, 2345)',
|
|
1937
|
+
'INSERT INTO attribute2node (attribute_id, node_id) VALUES (2345, 1234)'].should(include(sqls.shift))
|
|
1938
|
+
["DELETE FROM attribute2node WHERE ((node_id = 1234) AND (attribute_id = 2345))",
|
|
1939
|
+
"DELETE FROM attribute2node WHERE ((attribute_id = 2345) AND (node_id = 1234))"].should(include(sqls.shift))
|
|
1940
|
+
sqls.should == ["DELETE FROM attribute2node WHERE (node_id = 1234)"]
|
|
1941
|
+
end
|
|
1942
|
+
|
|
2080
1943
|
it "should define an add_ method that works on existing records" do
|
|
2081
1944
|
@c2.many_to_many :attributes, :class => @c1
|
|
2082
1945
|
|
|
2083
1946
|
n = @c2.load(:id => 1234)
|
|
2084
1947
|
a = @c1.load(:id => 2345)
|
|
2085
|
-
a.should ==
|
|
1948
|
+
n.add_attribute(a).should == a
|
|
1949
|
+
sqls = MODEL_DB.sqls
|
|
2086
1950
|
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 2345)',
|
|
2087
|
-
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (2345, 1234)'
|
|
2088
|
-
|
|
1951
|
+
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (2345, 1234)'].should(include(sqls.shift))
|
|
1952
|
+
sqls.should == []
|
|
2089
1953
|
end
|
|
2090
1954
|
|
|
2091
1955
|
it "should define an add_ method that works with a primary key" do
|
|
@@ -2093,21 +1957,25 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2093
1957
|
|
|
2094
1958
|
n = @c2.load(:id => 1234)
|
|
2095
1959
|
a = @c1.load(:id => 2345)
|
|
2096
|
-
|
|
1960
|
+
@c1.dataset._fetch = {:id=>2345}
|
|
1961
|
+
n.add_attribute(2345).should == a
|
|
1962
|
+
sqls = MODEL_DB.sqls
|
|
2097
1963
|
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 2345)',
|
|
2098
|
-
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (2345, 1234)'
|
|
2099
|
-
|
|
1964
|
+
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (2345, 1234)'].should(include(sqls.pop))
|
|
1965
|
+
sqls.should == ["SELECT * FROM attributes WHERE id = 2345"]
|
|
2100
1966
|
end
|
|
2101
1967
|
|
|
2102
1968
|
it "should allow passing a hash to the add_ method which creates a new record" do
|
|
2103
1969
|
@c2.many_to_many :attributes, :class => @c1
|
|
2104
1970
|
|
|
2105
1971
|
n = @c2.load(:id => 1234)
|
|
2106
|
-
@c1.
|
|
2107
|
-
|
|
1972
|
+
@c1.dataset._fetch = {:id=>1}
|
|
1973
|
+
n.add_attribute(:id => 1).should == @c1.load(:id => 1)
|
|
1974
|
+
sqls = MODEL_DB.sqls
|
|
2108
1975
|
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 1)',
|
|
2109
1976
|
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (1, 1234)'
|
|
2110
|
-
].should(include(
|
|
1977
|
+
].should(include(sqls.pop))
|
|
1978
|
+
sqls.should == ['INSERT INTO attributes (id) VALUES (1)', "SELECT * FROM attributes WHERE (id = 1) LIMIT 1"]
|
|
2111
1979
|
end
|
|
2112
1980
|
|
|
2113
1981
|
it "should define a remove_ method that works on existing records" do
|
|
@@ -2115,8 +1983,8 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2115
1983
|
|
|
2116
1984
|
n = @c2.new(:id => 1234)
|
|
2117
1985
|
a = @c1.new(:id => 2345)
|
|
2118
|
-
a.should ==
|
|
2119
|
-
MODEL_DB.sqls.
|
|
1986
|
+
n.remove_attribute(a).should == a
|
|
1987
|
+
MODEL_DB.sqls.should == ['DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (attribute_id = 2345))']
|
|
2120
1988
|
end
|
|
2121
1989
|
|
|
2122
1990
|
it "should raise an error in the add_ method if the passed associated object is not of the correct type" do
|
|
@@ -2127,13 +1995,8 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2127
1995
|
it "should accept a primary key for the remove_ method and remove an existing record" do
|
|
2128
1996
|
@c2.many_to_many :attributes, :class => @c1
|
|
2129
1997
|
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)
|
|
1998
|
+
@c1.dataset._fetch = {:id=>234}
|
|
1999
|
+
n.remove_attribute(234).should == @c1.load(:id => 234)
|
|
2137
2000
|
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
2001
|
"DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (attribute_id = 234))"]
|
|
2139
2002
|
end
|
|
@@ -2148,10 +2011,12 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2148
2011
|
|
|
2149
2012
|
n = @c2.load(:id => 1234).set(:xxx=>5)
|
|
2150
2013
|
a = @c1.load(:id => 2345).set(:yyy=>8)
|
|
2151
|
-
a.should ==
|
|
2014
|
+
n.add_attribute(a).should == a
|
|
2015
|
+
sqls = MODEL_DB.sqls
|
|
2152
2016
|
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (5, 8)',
|
|
2153
2017
|
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (8, 5)'
|
|
2154
|
-
].should(include(
|
|
2018
|
+
].should(include(sqls.pop))
|
|
2019
|
+
sqls.should == []
|
|
2155
2020
|
end
|
|
2156
2021
|
|
|
2157
2022
|
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 +2035,9 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2170
2035
|
n = @c2.load(:id => 1234, :x=>5)
|
|
2171
2036
|
a = @c1.load(:id => 2345, :y=>8)
|
|
2172
2037
|
a.should == n.add_attribute(a)
|
|
2173
|
-
|
|
2038
|
+
sqls = MODEL_DB.sqls
|
|
2039
|
+
m = /INSERT INTO attributes_nodes \((\w+), (\w+), (\w+), (\w+)\) VALUES \((\d+), (\d+), (\d+), (\d+)\)/.match(sqls.pop)
|
|
2040
|
+
sqls.should == []
|
|
2174
2041
|
m.should_not == nil
|
|
2175
2042
|
map = {'l1'=>1234, 'l2'=>5, 'r1'=>2345, 'r2'=>8}
|
|
2176
2043
|
%w[l1 l2 r1 r2].each do |x|
|
|
@@ -2187,10 +2054,15 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2187
2054
|
|
|
2188
2055
|
it "should have the add_ method respect composite keys" do
|
|
2189
2056
|
@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]
|
|
2057
|
+
@c1.set_primary_key [:id, :y]
|
|
2190
2058
|
n = @c2.load(:id => 1234, :x=>5)
|
|
2191
2059
|
a = @c1.load(:id => 2345, :y=>8)
|
|
2192
|
-
|
|
2193
|
-
|
|
2060
|
+
@c1.dataset._fetch = {:id => 2345, :y=>8}
|
|
2061
|
+
n.add_attribute([2345, 8]).should == a
|
|
2062
|
+
sqls = MODEL_DB.sqls
|
|
2063
|
+
sqls.shift.should =~ /SELECT \* FROM attributes WHERE \(\((id|y) = (8|2345)\) AND \((id|y) = (8|2345)\)\) LIMIT 1/
|
|
2064
|
+
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)\)/
|
|
2065
|
+
sqls.should == []
|
|
2194
2066
|
end
|
|
2195
2067
|
|
|
2196
2068
|
it "should have the remove_ method respect the :left_primary_key and :right_primary_key options" do
|
|
@@ -2198,8 +2070,8 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2198
2070
|
|
|
2199
2071
|
n = @c2.new(:id => 1234, :xxx=>5)
|
|
2200
2072
|
a = @c1.new(:id => 2345, :yyy=>8)
|
|
2201
|
-
a.should ==
|
|
2202
|
-
MODEL_DB.sqls.
|
|
2073
|
+
n.remove_attribute(a).should == a
|
|
2074
|
+
MODEL_DB.sqls.should == ['DELETE FROM attributes_nodes WHERE ((node_id = 5) AND (attribute_id = 8))']
|
|
2203
2075
|
end
|
|
2204
2076
|
|
|
2205
2077
|
it "should have the remove_ method respect composite keys" do
|
|
@@ -2214,17 +2086,12 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2214
2086
|
@c1.set_primary_key [:id, :y]
|
|
2215
2087
|
@c2.many_to_many :attributes, :class => @c1
|
|
2216
2088
|
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
|
|
2089
|
+
@c1.dataset._fetch = {:id=>234, :y=>8}
|
|
2223
2090
|
@c1.load(:id => 234, :y=>8).should == n.remove_attribute([234, 8])
|
|
2091
|
+
sqls = MODEL_DB.sqls
|
|
2224
2092
|
["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
|
|
2093
|
+
"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)
|
|
2094
|
+
sqls.should == ["DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (attribute_id = 234))"]
|
|
2228
2095
|
end
|
|
2229
2096
|
|
|
2230
2097
|
it "should raise an error if the model object doesn't have a valid primary key" do
|
|
@@ -2242,6 +2109,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2242
2109
|
n = @c1.new
|
|
2243
2110
|
a = @c2.load(:id=>123)
|
|
2244
2111
|
n.new?.should == true
|
|
2112
|
+
@c1.dataset._fetch = {:id=>1}
|
|
2245
2113
|
a.add_attribute(n)
|
|
2246
2114
|
n.new?.should == false
|
|
2247
2115
|
end
|
|
@@ -2250,7 +2118,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2250
2118
|
@c2.many_to_many :attributes, :class => @c1
|
|
2251
2119
|
n = @c1.new
|
|
2252
2120
|
a = @c2.load(:id=>123)
|
|
2253
|
-
def n.
|
|
2121
|
+
def n.validate() errors.add(:id, 'foo') end
|
|
2254
2122
|
proc{a.add_attribute(n)}.should raise_error(Sequel::ValidationFailed)
|
|
2255
2123
|
end
|
|
2256
2124
|
|
|
@@ -2259,7 +2127,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2259
2127
|
n = @c1.new
|
|
2260
2128
|
n.raise_on_save_failure = false
|
|
2261
2129
|
a = @c2.load(:id=>123)
|
|
2262
|
-
def n.
|
|
2130
|
+
def n.validate() errors.add(:id, 'foo') end
|
|
2263
2131
|
proc{a.add_attribute(n)}.should raise_error(Sequel::Error)
|
|
2264
2132
|
end
|
|
2265
2133
|
|
|
@@ -2267,7 +2135,8 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2267
2135
|
@c2.many_to_many :attributes, :class => @c1, :validate=>false
|
|
2268
2136
|
n = @c1.new
|
|
2269
2137
|
a = @c2.load(:id=>123)
|
|
2270
|
-
def n.
|
|
2138
|
+
def n.validate() errors.add(:id, 'foo') end
|
|
2139
|
+
@c1.dataset._fetch = {:id=>1}
|
|
2271
2140
|
a.add_attribute(n)
|
|
2272
2141
|
n.new?.should == false
|
|
2273
2142
|
end
|
|
@@ -2282,31 +2151,23 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2282
2151
|
it "should provide an array with all members of the association" do
|
|
2283
2152
|
@c2.many_to_many :attributes, :class => @c1
|
|
2284
2153
|
|
|
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))'
|
|
2154
|
+
@c2.new(:id => 1234).attributes.should == [@c1.load({})]
|
|
2155
|
+
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
2156
|
end
|
|
2293
2157
|
|
|
2294
2158
|
it "should set cached instance variable when accessed" do
|
|
2295
2159
|
@c2.many_to_many :attributes, :class => @c1
|
|
2296
2160
|
|
|
2297
2161
|
n = @c2.new(:id => 1234)
|
|
2298
|
-
MODEL_DB.reset
|
|
2299
2162
|
n.associations.include?(:attributes).should == false
|
|
2300
2163
|
atts = n.attributes
|
|
2301
2164
|
atts.should == n.associations[:attributes]
|
|
2302
|
-
MODEL_DB.sqls.length.should == 1
|
|
2303
2165
|
end
|
|
2304
2166
|
|
|
2305
2167
|
it "should use cached instance variable if available" do
|
|
2306
2168
|
@c2.many_to_many :attributes, :class => @c1
|
|
2307
2169
|
|
|
2308
2170
|
n = @c2.new(:id => 1234)
|
|
2309
|
-
MODEL_DB.reset
|
|
2310
2171
|
n.associations[:attributes] = 42
|
|
2311
2172
|
n.attributes.should == 42
|
|
2312
2173
|
MODEL_DB.sqls.should == []
|
|
@@ -2316,18 +2177,16 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2316
2177
|
@c2.many_to_many :attributes, :class => @c1
|
|
2317
2178
|
|
|
2318
2179
|
n = @c2.new(:id => 1234)
|
|
2319
|
-
MODEL_DB.reset
|
|
2320
2180
|
n.associations[:attributes] = 42
|
|
2321
2181
|
n.attributes(true).should_not == 42
|
|
2322
|
-
MODEL_DB.sqls.
|
|
2182
|
+
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
2183
|
end
|
|
2324
2184
|
|
|
2325
2185
|
it "should add item to cached instance variable if it exists when calling add_" do
|
|
2326
2186
|
@c2.many_to_many :attributes, :class => @c1
|
|
2327
2187
|
|
|
2328
2188
|
n = @c2.new(:id => 1234)
|
|
2329
|
-
att = @c1.
|
|
2330
|
-
MODEL_DB.reset
|
|
2189
|
+
att = @c1.load(:id => 345)
|
|
2331
2190
|
a = []
|
|
2332
2191
|
n.associations[:attributes] = a
|
|
2333
2192
|
n.add_attribute(att)
|
|
@@ -2339,7 +2198,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2339
2198
|
@c1.many_to_many :nodes, :class => @c2
|
|
2340
2199
|
|
|
2341
2200
|
n = @c2.new(:id => 1234)
|
|
2342
|
-
att = @c1.
|
|
2201
|
+
att = @c1.load(:id => 345)
|
|
2343
2202
|
att.associations[:nodes] = []
|
|
2344
2203
|
n.add_attribute(att)
|
|
2345
2204
|
att.nodes.should == [n]
|
|
@@ -2349,8 +2208,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2349
2208
|
@c2.many_to_many :attributes, :class => @c1
|
|
2350
2209
|
|
|
2351
2210
|
n = @c2.new(:id => 1234)
|
|
2352
|
-
att = @c1.
|
|
2353
|
-
MODEL_DB.reset
|
|
2211
|
+
att = @c1.load(:id => 345)
|
|
2354
2212
|
a = [att]
|
|
2355
2213
|
n.associations[:attributes] = a
|
|
2356
2214
|
n.remove_attribute(att)
|
|
@@ -2397,13 +2255,13 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2397
2255
|
it "should have an remove_all_ method that removes all associations" do
|
|
2398
2256
|
@c2.many_to_many :attributes, :class => @c1
|
|
2399
2257
|
@c2.new(:id => 1234).remove_all_attributes
|
|
2400
|
-
MODEL_DB.sqls.
|
|
2258
|
+
MODEL_DB.sqls.should == ['DELETE FROM attributes_nodes WHERE (node_id = 1234)']
|
|
2401
2259
|
end
|
|
2402
2260
|
|
|
2403
2261
|
it "should have the remove_all_ method respect the :left_primary_key option" do
|
|
2404
2262
|
@c2.many_to_many :attributes, :class => @c1, :left_primary_key=>:xxx
|
|
2405
2263
|
@c2.new(:id => 1234, :xxx=>5).remove_all_attributes
|
|
2406
|
-
MODEL_DB.sqls.
|
|
2264
|
+
MODEL_DB.sqls.should == ['DELETE FROM attributes_nodes WHERE (node_id = 5)']
|
|
2407
2265
|
end
|
|
2408
2266
|
|
|
2409
2267
|
it "should have the remove_all_ method respect composite keys" do
|
|
@@ -2421,10 +2279,9 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2421
2279
|
|
|
2422
2280
|
it "remove_all should return the array of previously associated items if the cached instance variable exists" do
|
|
2423
2281
|
@c2.many_to_many :attributes, :class => @c1
|
|
2424
|
-
attrib = @c1.
|
|
2425
|
-
node = @c2.
|
|
2426
|
-
|
|
2427
|
-
def d.fetch_rows(s); end
|
|
2282
|
+
attrib = @c1.load(:id=>3)
|
|
2283
|
+
node = @c2.load(:id => 1234)
|
|
2284
|
+
@c1.dataset._fetch = []
|
|
2428
2285
|
node.attributes.should == []
|
|
2429
2286
|
node.add_attribute(attrib)
|
|
2430
2287
|
node.associations[:attributes].should == [attrib]
|
|
@@ -2439,11 +2296,9 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2439
2296
|
it "remove_all should remove the current item from all reciprocal instance varaibles if it cached instance variable exists" do
|
|
2440
2297
|
@c2.many_to_many :attributes, :class => @c1
|
|
2441
2298
|
@c1.many_to_many :nodes, :class => @c2
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
def d.fetch_rows(s); end
|
|
2446
|
-
attrib = @c1.new(:id=>3)
|
|
2299
|
+
@c1.dataset._fetch = []
|
|
2300
|
+
@c2.dataset._fetch = []
|
|
2301
|
+
attrib = @c1.load(:id=>3)
|
|
2447
2302
|
node = @c2.new(:id => 1234)
|
|
2448
2303
|
node.attributes.should == []
|
|
2449
2304
|
attrib.nodes.should == []
|
|
@@ -2459,8 +2314,9 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2459
2314
|
o.add_attribute(@c1.load(:id=>44))
|
|
2460
2315
|
o.remove_attribute(@c1.load(:id=>45))
|
|
2461
2316
|
o.remove_all_attributes
|
|
2462
|
-
MODEL_DB.sqls
|
|
2463
|
-
|
|
2317
|
+
sqls = MODEL_DB.sqls
|
|
2318
|
+
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)\)/
|
|
2319
|
+
sqls.should == ["DELETE FROM attributes_nodes WHERE ((x = 123) AND (node_id = 1234) AND (attribute_id = 45))",
|
|
2464
2320
|
"DELETE FROM attributes_nodes WHERE ((x = 123) AND (node_id = 1234))"]
|
|
2465
2321
|
end
|
|
2466
2322
|
|
|
@@ -2543,18 +2399,18 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2543
2399
|
h = []
|
|
2544
2400
|
@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
2401
|
@c2.class_eval do
|
|
2546
|
-
|
|
2402
|
+
self::Foo = h
|
|
2547
2403
|
def _add_attribute(v)
|
|
2548
|
-
|
|
2404
|
+
model::Foo << 4
|
|
2549
2405
|
end
|
|
2550
2406
|
def _remove_attribute(v)
|
|
2551
|
-
|
|
2407
|
+
model::Foo << 5
|
|
2552
2408
|
end
|
|
2553
2409
|
def blah(x)
|
|
2554
|
-
|
|
2410
|
+
model::Foo << x.pk
|
|
2555
2411
|
end
|
|
2556
2412
|
def blahr(x)
|
|
2557
|
-
|
|
2413
|
+
model::Foo << 6
|
|
2558
2414
|
end
|
|
2559
2415
|
end
|
|
2560
2416
|
p = @c2.load(:id=>10)
|
|
@@ -2570,17 +2426,12 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2570
2426
|
h = []
|
|
2571
2427
|
@c2.many_to_many :attributes, :class => @c1, :after_load=>[proc{|x,y| h << [x.pk, y.collect{|z|z.pk}]}, :al]
|
|
2572
2428
|
@c2.class_eval do
|
|
2573
|
-
|
|
2429
|
+
self::Foo = h
|
|
2574
2430
|
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})
|
|
2431
|
+
v.each{|x| model::Foo << x.pk}
|
|
2582
2432
|
end
|
|
2583
2433
|
end
|
|
2434
|
+
@c1.dataset._fetch = [{:id=>20}, {:id=>30}]
|
|
2584
2435
|
p = @c2.load(:id=>10, :parent_id=>20)
|
|
2585
2436
|
attributes = p.attributes
|
|
2586
2437
|
h.should == [[10, [20, 30]], 20, 30]
|
|
@@ -2623,14 +2474,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2623
2474
|
|
|
2624
2475
|
it "should support a :uniq option that removes duplicates from the association" do
|
|
2625
2476
|
@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
|
|
2477
|
+
@c1.dataset._fetch = [{:id=>20}, {:id=>30}, {:id=>20}, {:id=>30}]
|
|
2634
2478
|
@c2.load(:id=>10, :parent_id=>20).attributes.should == [@c1.load(:id=>20), @c1.load(:id=>30)]
|
|
2635
2479
|
end
|
|
2636
2480
|
|
|
@@ -2651,76 +2495,525 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2651
2495
|
@c2.many_to_many :attributes, :class => @c1 do |ds|
|
|
2652
2496
|
ds.filter(:join_table_att=>3)
|
|
2653
2497
|
end
|
|
2654
|
-
@c1.dataset.
|
|
2655
|
-
def fetch_rows(sql, &block)
|
|
2656
|
-
db.sqls << sql
|
|
2657
|
-
yield(:id=>2)
|
|
2658
|
-
end
|
|
2659
|
-
end
|
|
2498
|
+
@c1.dataset._fetch = {:id=>2}
|
|
2660
2499
|
@c2.load(:id=>1).remove_attribute(2)
|
|
2661
2500
|
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
2501
|
"DELETE FROM attributes_nodes WHERE ((node_id = 1) AND (attribute_id = 2))"]
|
|
2663
2502
|
end
|
|
2664
2503
|
end
|
|
2665
2504
|
|
|
2666
|
-
describe
|
|
2505
|
+
describe "Filtering by associations" do
|
|
2667
2506
|
before do
|
|
2668
|
-
|
|
2669
|
-
@
|
|
2670
|
-
|
|
2671
|
-
|
|
2507
|
+
@Album = Class.new(Sequel::Model(:albums))
|
|
2508
|
+
artist = @Artist = Class.new(Sequel::Model(:artists))
|
|
2509
|
+
tag = @Tag = Class.new(Sequel::Model(:tags))
|
|
2510
|
+
track = @Track = Class.new(Sequel::Model(:tracks))
|
|
2511
|
+
album_info = @AlbumInfo = Class.new(Sequel::Model(:album_infos))
|
|
2512
|
+
@Artist.columns :id, :id1, :id2
|
|
2513
|
+
@Tag.columns :id, :tid1, :tid2
|
|
2514
|
+
@Track.columns :id, :album_id, :album_id1, :album_id2
|
|
2515
|
+
@AlbumInfo.columns :id, :album_id, :album_id1, :album_id2
|
|
2516
|
+
@Album.class_eval do
|
|
2517
|
+
columns :id, :id1, :id2, :artist_id, :artist_id1, :artist_id2
|
|
2518
|
+
many_to_one :artist, :class=>artist
|
|
2519
|
+
one_to_many :tracks, :class=>track, :key=>:album_id
|
|
2520
|
+
one_to_one :album_info, :class=>album_info, :key=>:album_id
|
|
2521
|
+
many_to_many :tags, :class=>tag, :left_key=>:album_id, :join_table=>:albums_tags
|
|
2522
|
+
|
|
2523
|
+
many_to_one :cartist, :class=>artist, :key=>[:artist_id1, :artist_id2], :primary_key=>[:id1, :id2]
|
|
2524
|
+
one_to_many :ctracks, :class=>track, :key=>[:album_id1, :album_id2], :primary_key=>[:id1, :id2]
|
|
2525
|
+
one_to_one :calbum_info, :class=>album_info, :key=>[:album_id1, :album_id2], :primary_key=>[:id1, :id2]
|
|
2526
|
+
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
2527
|
end
|
|
2673
2528
|
end
|
|
2674
|
-
|
|
2675
|
-
it "#all_association_reflections should include all association reflection hashes" do
|
|
2676
|
-
@c1.all_association_reflections.should == []
|
|
2677
2529
|
|
|
2678
|
-
|
|
2679
|
-
@
|
|
2680
|
-
|
|
2681
|
-
|
|
2530
|
+
it "should be able to filter on many_to_one associations" do
|
|
2531
|
+
@Album.filter(:artist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (albums.artist_id = 3)'
|
|
2532
|
+
end
|
|
2533
|
+
|
|
2534
|
+
it "should be able to filter on one_to_many associations" do
|
|
2535
|
+
@Album.filter(:tracks=>@Track.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE (albums.id = 3)'
|
|
2536
|
+
end
|
|
2537
|
+
|
|
2538
|
+
it "should be able to filter on one_to_one associations" do
|
|
2539
|
+
@Album.filter(:album_info=>@AlbumInfo.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE (albums.id = 3)'
|
|
2540
|
+
end
|
|
2541
|
+
|
|
2542
|
+
it "should be able to filter on many_to_many associations" do
|
|
2543
|
+
@Album.filter(:tags=>@Tag.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id = 3) AND (albums_tags.album_id IS NOT NULL))))'
|
|
2544
|
+
end
|
|
2545
|
+
|
|
2546
|
+
it "should be able to filter on many_to_one associations with composite keys" do
|
|
2547
|
+
@Album.filter(:cartist=>@Artist.load(:id1=>3, :id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id1 = 3) AND (albums.artist_id2 = 4))'
|
|
2548
|
+
end
|
|
2549
|
+
|
|
2550
|
+
it "should be able to filter on one_to_many associations with composite keys" do
|
|
2551
|
+
@Album.filter(:ctracks=>@Track.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((albums.id1 = 3) AND (albums.id2 = 4))'
|
|
2552
|
+
end
|
|
2553
|
+
|
|
2554
|
+
it "should be able to filter on one_to_one associations with composite keys" do
|
|
2555
|
+
@Album.filter(:calbum_info=>@AlbumInfo.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((albums.id1 = 3) AND (albums.id2 = 4))'
|
|
2556
|
+
end
|
|
2557
|
+
|
|
2558
|
+
it "should be able to filter on many_to_many associations with composite keys" do
|
|
2559
|
+
@Album.filter(:ctags=>@Tag.load(:tid1=>3, :tid2=>4)).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE ((albums_tags.tag_id1 = 3) AND (albums_tags.tag_id2 = 4) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL))))'
|
|
2560
|
+
end
|
|
2561
|
+
|
|
2562
|
+
it "should work inside a complex filter" do
|
|
2563
|
+
artist = @Artist.load(:id=>3)
|
|
2564
|
+
@Album.filter{foo & {:artist=>artist}}.sql.should == 'SELECT * FROM albums WHERE (foo AND (albums.artist_id = 3))'
|
|
2565
|
+
track = @Track.load(:album_id=>4)
|
|
2566
|
+
@Album.filter{foo & [[:artist, artist], [:tracks, track]]}.sql.should == 'SELECT * FROM albums WHERE (foo AND (albums.artist_id = 3) AND (albums.id = 4))'
|
|
2567
|
+
end
|
|
2682
2568
|
|
|
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]
|
|
2569
|
+
it "should raise for an invalid association name" do
|
|
2570
|
+
proc{@Album.filter(:foo=>@Artist.load(:id=>3)).sql}.should raise_error(Sequel::Error)
|
|
2688
2571
|
end
|
|
2689
2572
|
|
|
2690
|
-
it "
|
|
2691
|
-
@
|
|
2573
|
+
it "should raise for an invalid association type" do
|
|
2574
|
+
@Album.many_to_many :iatags, :clone=>:tags
|
|
2575
|
+
@Album.association_reflection(:iatags)[:type] = :foo
|
|
2576
|
+
proc{@Album.filter(:iatags=>@Tag.load(:id=>3)).sql}.should raise_error(Sequel::Error)
|
|
2692
2577
|
end
|
|
2693
2578
|
|
|
2694
|
-
it "
|
|
2695
|
-
@
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
@
|
|
2579
|
+
it "should raise for an invalid associated object class " do
|
|
2580
|
+
proc{@Album.filter(:tags=>@Artist.load(:id=>3)).sql}.should raise_error(Sequel::Error)
|
|
2581
|
+
end
|
|
2582
|
+
|
|
2583
|
+
it "should raise for an invalid associated object class when multiple objects are used" do
|
|
2584
|
+
proc{@Album.filter(:tags=>[@Tag.load(:id=>3), @Artist.load(:id=>3)]).sql}.should raise_error(Sequel::Error)
|
|
2585
|
+
end
|
|
2586
|
+
|
|
2587
|
+
it "should correctly handle case when a multiple value association is used" do
|
|
2588
|
+
proc{@Album.filter(:tags=>[@Tag.load(:id=>3), @Artist.load(:id=>3)]).sql}.should raise_error(Sequel::Error)
|
|
2589
|
+
end
|
|
2590
|
+
|
|
2591
|
+
it "should not affect non-association IN/NOT IN filtering with an empty array" do
|
|
2592
|
+
@Album.filter(:tag_id=>[]).sql.should == 'SELECT * FROM albums WHERE (tag_id != tag_id)'
|
|
2593
|
+
@Album.exclude(:tag_id=>[]).sql.should == 'SELECT * FROM albums WHERE (tag_id = tag_id)'
|
|
2594
|
+
end
|
|
2700
2595
|
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
@c1.association_reflection(:children)[:class].should == @c1
|
|
2596
|
+
it "should work correctly in subclasses" do
|
|
2597
|
+
c = Class.new(@Album)
|
|
2598
|
+
c.many_to_one :sartist, :class=>@Artist
|
|
2599
|
+
c.filter(:sartist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (albums.sartist_id = 3)'
|
|
2706
2600
|
end
|
|
2707
2601
|
|
|
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]
|
|
2602
|
+
it "should be able to exclude on many_to_one associations" do
|
|
2603
|
+
@Album.exclude(:artist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id != 3) OR (albums.artist_id IS NULL))'
|
|
2714
2604
|
end
|
|
2715
2605
|
|
|
2716
|
-
it "
|
|
2717
|
-
@
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2606
|
+
it "should be able to exclude on one_to_many associations" do
|
|
2607
|
+
@Album.exclude(:tracks=>@Track.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE ((albums.id != 3) OR (albums.id IS NULL))'
|
|
2608
|
+
end
|
|
2609
|
+
|
|
2610
|
+
it "should be able to exclude on one_to_one associations" do
|
|
2611
|
+
@Album.exclude(:album_info=>@AlbumInfo.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE ((albums.id != 3) OR (albums.id IS NULL))'
|
|
2612
|
+
end
|
|
2613
|
+
|
|
2614
|
+
it "should be able to exclude on many_to_many associations" do
|
|
2615
|
+
@Album.exclude(:tags=>@Tag.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id = 3) AND (albums_tags.album_id IS NOT NULL)))) OR (albums.id IS NULL))'
|
|
2616
|
+
end
|
|
2617
|
+
|
|
2618
|
+
it "should be able to exclude on many_to_one associations with composite keys" do
|
|
2619
|
+
@Album.exclude(:cartist=>@Artist.load(:id1=>3, :id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id1 != 3) OR (albums.artist_id2 != 4) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))'
|
|
2620
|
+
end
|
|
2621
|
+
|
|
2622
|
+
it "should be able to exclude on one_to_many associations with composite keys" do
|
|
2623
|
+
@Album.exclude(:ctracks=>@Track.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((albums.id1 != 3) OR (albums.id2 != 4) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
|
2624
|
+
end
|
|
2625
|
+
|
|
2626
|
+
it "should be able to exclude on one_to_one associations with composite keys" do
|
|
2627
|
+
@Album.exclude(:calbum_info=>@AlbumInfo.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((albums.id1 != 3) OR (albums.id2 != 4) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
|
2628
|
+
end
|
|
2629
|
+
|
|
2630
|
+
it "should be able to exclude on many_to_many associations with composite keys" do
|
|
2631
|
+
@Album.exclude(:ctags=>@Tag.load(:tid1=>3, :tid2=>4)).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE ((albums_tags.tag_id1 = 3) AND (albums_tags.tag_id2 = 4) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
|
2632
|
+
end
|
|
2633
|
+
|
|
2634
|
+
it "should be able to filter on multiple many_to_one associations" do
|
|
2635
|
+
@Album.filter(:artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE (albums.artist_id IN (3, 4))'
|
|
2636
|
+
end
|
|
2637
|
+
|
|
2638
|
+
it "should be able to filter on multiple one_to_many associations" do
|
|
2639
|
+
@Album.filter(:tracks=>[@Track.load(:album_id=>3), @Track.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (3, 4))'
|
|
2640
|
+
end
|
|
2641
|
+
|
|
2642
|
+
it "should be able to filter on multiple one_to_one associations" do
|
|
2643
|
+
@Album.filter(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (3, 4))'
|
|
2644
|
+
end
|
|
2645
|
+
|
|
2646
|
+
it "should be able to filter on multiple many_to_many associations" do
|
|
2647
|
+
@Album.filter(:tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (3, 4)) AND (albums_tags.album_id IS NOT NULL))))'
|
|
2648
|
+
end
|
|
2649
|
+
|
|
2650
|
+
it "should be able to filter on multiple many_to_one associations with composite keys" do
|
|
2651
|
+
@Album.filter(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>5, :id2=>6)]).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN ((3, 4), (5, 6)))'
|
|
2652
|
+
end
|
|
2653
|
+
|
|
2654
|
+
it "should be able to filter on multiple one_to_many associations with composite keys" do
|
|
2655
|
+
@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 ((albums.id1, albums.id2) IN ((3, 4), (5, 6)))'
|
|
2656
|
+
end
|
|
2657
|
+
|
|
2658
|
+
it "should be able to filter on multiple one_to_one associations with composite keys" do
|
|
2659
|
+
@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 ((albums.id1, albums.id2) IN ((3, 4), (5, 6)))'
|
|
2660
|
+
end
|
|
2661
|
+
|
|
2662
|
+
it "should be able to filter on multiple many_to_many associations with composite keys" do
|
|
2663
|
+
@Album.filter(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5, :tid2=>6)]).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN ((3, 4), (5, 6))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL))))'
|
|
2664
|
+
end
|
|
2665
|
+
|
|
2666
|
+
it "should be able to exclude on multiple many_to_one associations" do
|
|
2667
|
+
@Album.exclude(:artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id NOT IN (3, 4)) OR (albums.artist_id IS NULL))'
|
|
2668
|
+
end
|
|
2669
|
+
|
|
2670
|
+
it "should be able to exclude on multiple one_to_many associations" do
|
|
2671
|
+
@Album.exclude(:tracks=>[@Track.load(:album_id=>3), @Track.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE ((albums.id NOT IN (3, 4)) OR (albums.id IS NULL))'
|
|
2672
|
+
end
|
|
2673
|
+
|
|
2674
|
+
it "should be able to exclude on multiple one_to_one associations" do
|
|
2675
|
+
@Album.exclude(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE ((albums.id NOT IN (3, 4)) OR (albums.id IS NULL))'
|
|
2676
|
+
end
|
|
2677
|
+
|
|
2678
|
+
it "should be able to exclude on multiple many_to_many associations" do
|
|
2679
|
+
@Album.exclude(:tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (3, 4)) AND (albums_tags.album_id IS NOT NULL)))) OR (albums.id IS NULL))'
|
|
2680
|
+
end
|
|
2681
|
+
|
|
2682
|
+
it "should be able to exclude on multiple many_to_one associations with composite keys" do
|
|
2683
|
+
@Album.exclude(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>5, :id2=>6)]).sql.should == 'SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN ((3, 4), (5, 6))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))'
|
|
2684
|
+
end
|
|
2685
|
+
|
|
2686
|
+
it "should be able to exclude on multiple one_to_many associations with composite keys" do
|
|
2687
|
+
@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 (((albums.id1, albums.id2) NOT IN ((3, 4), (5, 6))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
|
2688
|
+
end
|
|
2689
|
+
|
|
2690
|
+
it "should be able to exclude on multiple one_to_one associations with composite keys" do
|
|
2691
|
+
@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 (((albums.id1, albums.id2) NOT IN ((3, 4), (5, 6))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
|
2692
|
+
end
|
|
2693
|
+
|
|
2694
|
+
it "should be able to exclude on multiple many_to_many associations with composite keys" do
|
|
2695
|
+
@Album.exclude(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5, :tid2=>6)]).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN ((3, 4), (5, 6))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
|
2696
|
+
end
|
|
2697
|
+
|
|
2698
|
+
it "should be able to handle NULL values when filtering many_to_one associations" do
|
|
2699
|
+
@Album.filter(:artist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2700
|
+
end
|
|
2701
|
+
|
|
2702
|
+
it "should be able to handle NULL values when filtering one_to_many associations" do
|
|
2703
|
+
@Album.filter(:tracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2704
|
+
end
|
|
2705
|
+
|
|
2706
|
+
it "should be able to handle NULL values when filtering one_to_one associations" do
|
|
2707
|
+
@Album.filter(:album_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2708
|
+
end
|
|
2709
|
+
|
|
2710
|
+
it "should be able to handle NULL values when filtering many_to_many associations" do
|
|
2711
|
+
@Album.filter(:tags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2712
|
+
end
|
|
2713
|
+
|
|
2714
|
+
it "should be able to handle filtering with NULL values for many_to_one associations with composite keys" do
|
|
2715
|
+
@Album.filter(:cartist=>@Artist.load(:id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2716
|
+
@Album.filter(:cartist=>@Artist.load(:id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2717
|
+
@Album.filter(:cartist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2718
|
+
end
|
|
2719
|
+
|
|
2720
|
+
it "should be able to filter with NULL values for one_to_many associations with composite keys" do
|
|
2721
|
+
@Album.filter(:ctracks=>@Track.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2722
|
+
@Album.filter(:ctracks=>@Track.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2723
|
+
@Album.filter(:ctracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2724
|
+
end
|
|
2725
|
+
|
|
2726
|
+
it "should be able to filter with NULL values for one_to_one associations with composite keys" do
|
|
2727
|
+
@Album.filter(:calbum_info=>@AlbumInfo.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2728
|
+
@Album.filter(:calbum_info=>@AlbumInfo.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2729
|
+
@Album.filter(:calbum_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2730
|
+
end
|
|
2731
|
+
|
|
2732
|
+
it "should be able to filter with NULL values for many_to_many associations with composite keys" do
|
|
2733
|
+
@Album.filter(:ctags=>@Tag.load(:tid1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2734
|
+
@Album.filter(:ctags=>@Tag.load(:tid2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2735
|
+
@Album.filter(:ctags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2736
|
+
end
|
|
2737
|
+
|
|
2738
|
+
it "should be able to handle NULL values when excluding many_to_one associations" do
|
|
2739
|
+
@Album.exclude(:artist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2740
|
+
end
|
|
2741
|
+
|
|
2742
|
+
it "should be able to handle NULL values when excluding one_to_many associations" do
|
|
2743
|
+
@Album.exclude(:tracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2744
|
+
end
|
|
2745
|
+
|
|
2746
|
+
it "should be able to handle NULL values when excluding one_to_one associations" do
|
|
2747
|
+
@Album.exclude(:album_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2748
|
+
end
|
|
2749
|
+
|
|
2750
|
+
it "should be able to handle NULL values when excluding many_to_many associations" do
|
|
2751
|
+
@Album.exclude(:tags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2752
|
+
end
|
|
2753
|
+
|
|
2754
|
+
it "should be able to handle excluding with NULL values for many_to_one associations with composite keys" do
|
|
2755
|
+
@Album.exclude(:cartist=>@Artist.load(:id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2756
|
+
@Album.exclude(:cartist=>@Artist.load(:id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2757
|
+
@Album.exclude(:cartist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2758
|
+
end
|
|
2759
|
+
|
|
2760
|
+
it "should be able to excluding with NULL values for one_to_many associations with composite keys" do
|
|
2761
|
+
@Album.exclude(:ctracks=>@Track.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2762
|
+
@Album.exclude(:ctracks=>@Track.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2763
|
+
@Album.exclude(:ctracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2764
|
+
end
|
|
2765
|
+
|
|
2766
|
+
it "should be able to excluding with NULL values for one_to_one associations with composite keys" do
|
|
2767
|
+
@Album.exclude(:calbum_info=>@AlbumInfo.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2768
|
+
@Album.exclude(:calbum_info=>@AlbumInfo.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2769
|
+
@Album.exclude(:calbum_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2770
|
+
end
|
|
2771
|
+
|
|
2772
|
+
it "should be able to excluding with NULL values for many_to_many associations with composite keys" do
|
|
2773
|
+
@Album.exclude(:ctags=>@Tag.load(:tid1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2774
|
+
@Album.exclude(:ctags=>@Tag.load(:tid2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2775
|
+
@Album.exclude(:ctags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2776
|
+
end
|
|
2777
|
+
|
|
2778
|
+
it "should be able to handle NULL values when filtering multiple many_to_one associations" do
|
|
2779
|
+
@Album.filter(:artist=>[@Artist.load(:id=>3), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE (albums.artist_id IN (3))'
|
|
2780
|
+
@Album.filter(:artist=>[@Artist.new, @Artist.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2781
|
+
end
|
|
2782
|
+
|
|
2783
|
+
it "should be able to handle NULL values when filtering multiple one_to_many associations" do
|
|
2784
|
+
@Album.filter(:tracks=>[@Track.load(:album_id=>3), @Track.new]).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (3))'
|
|
2785
|
+
@Album.filter(:tracks=>[@Track.new, @Track.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2786
|
+
end
|
|
2787
|
+
|
|
2788
|
+
it "should be able to handle NULL values when filtering multiple one_to_one associations" do
|
|
2789
|
+
@Album.filter(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (3))'
|
|
2790
|
+
@Album.filter(:album_info=>[@AlbumInfo.new, @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2791
|
+
end
|
|
2792
|
+
|
|
2793
|
+
it "should be able to handle NULL values when filtering multiple many_to_many associations" do
|
|
2794
|
+
@Album.filter(:tags=>[@Tag.load(:id=>3), @Tag.new]).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (3)) AND (albums_tags.album_id IS NOT NULL))))'
|
|
2795
|
+
@Album.filter(:tags=>[@Tag.new, @Tag.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2796
|
+
end
|
|
2797
|
+
|
|
2798
|
+
it "should be able to handle NULL values when filtering multiple many_to_one associations with composite keys" do
|
|
2799
|
+
@Album.filter(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>3)]).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN ((3, 4)))'
|
|
2800
|
+
@Album.filter(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN ((3, 4)))'
|
|
2801
|
+
end
|
|
2802
|
+
|
|
2803
|
+
it "should be able handle NULL values when filtering multiple one_to_many associations with composite keys" do
|
|
2804
|
+
@Album.filter(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.load(:album_id1=>3)]).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN ((3, 4)))'
|
|
2805
|
+
@Album.filter(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.new]).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN ((3, 4)))'
|
|
2806
|
+
end
|
|
2807
|
+
|
|
2808
|
+
it "should be able to handle NULL values when filtering multiple one_to_one associations with composite keys" do
|
|
2809
|
+
@Album.filter(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.load(:album_id1=>5)]).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN ((3, 4)))'
|
|
2810
|
+
@Album.filter(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN ((3, 4)))'
|
|
2811
|
+
end
|
|
2812
|
+
|
|
2813
|
+
it "should be able to handle NULL values when filtering multiple many_to_many associations with composite keys" do
|
|
2814
|
+
@Album.filter(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5)]).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN ((3, 4))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL))))'
|
|
2815
|
+
@Album.filter(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.new]).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN ((3, 4))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL))))'
|
|
2816
|
+
end
|
|
2817
|
+
|
|
2818
|
+
it "should be able to handle NULL values when excluding multiple many_to_one associations" do
|
|
2819
|
+
@Album.exclude(:artist=>[@Artist.load(:id=>3), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id NOT IN (3)) OR (albums.artist_id IS NULL))'
|
|
2820
|
+
@Album.exclude(:artist=>[@Artist.new, @Artist.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2821
|
+
end
|
|
2822
|
+
|
|
2823
|
+
it "should be able to handle NULL values when excluding multiple one_to_many associations" do
|
|
2824
|
+
@Album.exclude(:tracks=>[@Track.load(:album_id=>3), @Track.new]).sql.should == 'SELECT * FROM albums WHERE ((albums.id NOT IN (3)) OR (albums.id IS NULL))'
|
|
2825
|
+
@Album.exclude(:tracks=>[@Track.new, @Track.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2826
|
+
end
|
|
2827
|
+
|
|
2828
|
+
it "should be able to handle NULL values when excluding multiple one_to_one associations" do
|
|
2829
|
+
@Album.exclude(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE ((albums.id NOT IN (3)) OR (albums.id IS NULL))'
|
|
2830
|
+
@Album.exclude(:album_info=>[@AlbumInfo.new, @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2831
|
+
end
|
|
2832
|
+
|
|
2833
|
+
it "should be able to handle NULL values when excluding multiple many_to_many associations" do
|
|
2834
|
+
@Album.exclude(:tags=>[@Tag.load(:id=>3), @Tag.new]).sql.should == 'SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (3)) AND (albums_tags.album_id IS NOT NULL)))) OR (albums.id IS NULL))'
|
|
2835
|
+
@Album.exclude(:tags=>[@Tag.new, @Tag.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2836
|
+
end
|
|
2837
|
+
|
|
2838
|
+
it "should be able to handle NULL values when excluding multiple many_to_one associations with composite keys" do
|
|
2839
|
+
@Album.exclude(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>3)]).sql.should == 'SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN ((3, 4))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))'
|
|
2840
|
+
@Album.exclude(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN ((3, 4))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))'
|
|
2841
|
+
end
|
|
2842
|
+
|
|
2843
|
+
it "should be able handle NULL values when excluding multiple one_to_many associations with composite keys" do
|
|
2844
|
+
@Album.exclude(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.load(:album_id1=>3)]).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
|
2845
|
+
@Album.exclude(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.new]).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
|
2846
|
+
end
|
|
2847
|
+
|
|
2848
|
+
it "should be able to handle NULL values when excluding multiple one_to_one associations with composite keys" do
|
|
2849
|
+
@Album.exclude(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.load(:album_id1=>5)]).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
|
2850
|
+
@Album.exclude(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
|
2851
|
+
end
|
|
2852
|
+
|
|
2853
|
+
it "should be able to handle NULL values when excluding multiple many_to_many associations with composite keys" do
|
|
2854
|
+
@Album.exclude(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5)]).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN ((3, 4))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
|
2855
|
+
@Album.exclude(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.new]).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN ((3, 4))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
|
2856
|
+
end
|
|
2857
|
+
|
|
2858
|
+
it "should be able to filter on many_to_one association datasets" do
|
|
2859
|
+
@Album.filter(:artist=>@Artist.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists WHERE ((x = 1) AND (artists.id IS NOT NULL))))'
|
|
2860
|
+
end
|
|
2861
|
+
|
|
2862
|
+
it "should be able to filter on one_to_many association datasets" do
|
|
2863
|
+
@Album.filter(:tracks=>@Track.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((x = 1) AND (tracks.album_id IS NOT NULL))))'
|
|
2864
|
+
end
|
|
2865
|
+
|
|
2866
|
+
it "should be able to filter on one_to_one association datasets" do
|
|
2867
|
+
@Album.filter(:album_info=>@AlbumInfo.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (SELECT album_infos.album_id FROM album_infos WHERE ((x = 1) AND (album_infos.album_id IS NOT NULL))))'
|
|
2868
|
+
end
|
|
2869
|
+
|
|
2870
|
+
it "should be able to filter on many_to_many association datasets" do
|
|
2871
|
+
@Album.filter(:tags=>@Tag.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (SELECT tags.id FROM tags WHERE ((x = 1) AND (tags.id IS NOT NULL)))) AND (albums_tags.album_id IS NOT NULL))))'
|
|
2872
|
+
end
|
|
2873
|
+
|
|
2874
|
+
it "should be able to filter on many_to_one association datasets with composite keys" do
|
|
2875
|
+
@Album.filter(:cartist=>@Artist.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((x = 1) AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL))))'
|
|
2876
|
+
end
|
|
2877
|
+
|
|
2878
|
+
it "should be able to filter on one_to_many association datasets with composite keys" do
|
|
2879
|
+
@Album.filter(:ctracks=>@Track.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((x = 1) AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL))))'
|
|
2880
|
+
end
|
|
2881
|
+
|
|
2882
|
+
it "should be able to filter on one_to_one association datasets with composite keys" do
|
|
2883
|
+
@Album.filter(:calbum_info=>@AlbumInfo.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((x = 1) AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL))))'
|
|
2884
|
+
end
|
|
2885
|
+
|
|
2886
|
+
it "should be able to filter on many_to_many association datasets with composite keys" do
|
|
2887
|
+
@Album.filter(:ctags=>@Tag.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN (SELECT tags.tid1, tags.tid2 FROM tags WHERE ((x = 1) AND (tags.tid1 IS NOT NULL) AND (tags.tid2 IS NOT NULL)))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL))))'
|
|
2888
|
+
end
|
|
2889
|
+
|
|
2890
|
+
it "should be able to exclude on many_to_one association datasets" do
|
|
2891
|
+
@Album.exclude(:artist=>@Artist.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id NOT IN (SELECT artists.id FROM artists WHERE ((x = 1) AND (artists.id IS NOT NULL)))) OR (albums.artist_id IS NULL))'
|
|
2892
|
+
end
|
|
2893
|
+
|
|
2894
|
+
it "should be able to exclude on one_to_many association datasets" do
|
|
2895
|
+
@Album.exclude(:tracks=>@Track.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT tracks.album_id FROM tracks WHERE ((x = 1) AND (tracks.album_id IS NOT NULL)))) OR (albums.id IS NULL))'
|
|
2896
|
+
end
|
|
2897
|
+
|
|
2898
|
+
it "should be able to exclude on one_to_one association datasets" do
|
|
2899
|
+
@Album.exclude(:album_info=>@AlbumInfo.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT album_infos.album_id FROM album_infos WHERE ((x = 1) AND (album_infos.album_id IS NOT NULL)))) OR (albums.id IS NULL))'
|
|
2900
|
+
end
|
|
2901
|
+
|
|
2902
|
+
it "should be able to exclude on many_to_many association datasets" do
|
|
2903
|
+
@Album.exclude(:tags=>@Tag.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (SELECT tags.id FROM tags WHERE ((x = 1) AND (tags.id IS NOT NULL)))) AND (albums_tags.album_id IS NOT NULL)))) OR (albums.id IS NULL))'
|
|
2904
|
+
end
|
|
2905
|
+
|
|
2906
|
+
it "should be able to exclude on many_to_one association datasets with composite keys" do
|
|
2907
|
+
@Album.exclude(:cartist=>@Artist.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((x = 1) AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL)))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))'
|
|
2908
|
+
end
|
|
2909
|
+
|
|
2910
|
+
it "should be able to exclude on one_to_many association datasets with composite keys" do
|
|
2911
|
+
@Album.exclude(:ctracks=>@Track.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((x = 1) AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
|
2912
|
+
end
|
|
2913
|
+
|
|
2914
|
+
it "should be able to exclude on one_to_one association datasets with composite keys" do
|
|
2915
|
+
@Album.exclude(:calbum_info=>@AlbumInfo.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((x = 1) AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
|
2916
|
+
end
|
|
2917
|
+
|
|
2918
|
+
it "should be able to exclude on many_to_many association datasets with composite keys" do
|
|
2919
|
+
@Album.exclude(:ctags=>@Tag.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN (SELECT tags.tid1, tags.tid2 FROM tags WHERE ((x = 1) AND (tags.tid1 IS NOT NULL) AND (tags.tid2 IS NOT NULL)))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
|
2920
|
+
end
|
|
2921
|
+
|
|
2922
|
+
it "should do a regular IN query if the dataset for a different model is used" do
|
|
2923
|
+
@Album.filter(:artist=>@Album.select(:x)).sql.should == 'SELECT * FROM albums WHERE (artist IN (SELECT x FROM albums))'
|
|
2924
|
+
end
|
|
2925
|
+
|
|
2926
|
+
it "should do a regular IN query if a non-model dataset is used" do
|
|
2927
|
+
@Album.filter(:artist=>@Album.db.from(:albums).select(:x)).sql.should == 'SELECT * FROM albums WHERE (artist IN (SELECT x FROM albums))'
|
|
2725
2928
|
end
|
|
2726
2929
|
end
|
|
2930
|
+
|
|
2931
|
+
describe "Sequel::Model Associations with clashing column names" do
|
|
2932
|
+
before do
|
|
2933
|
+
@db = Sequel.mock(:fetch=>{:id=>1, :object_id=>2})
|
|
2934
|
+
@Foo = Class.new(Sequel::Model(@db[:foos]))
|
|
2935
|
+
@Bar = Class.new(Sequel::Model(@db[:bars]))
|
|
2936
|
+
@Foo.columns :id, :object_id
|
|
2937
|
+
@Bar.columns :id, :object_id
|
|
2938
|
+
@Foo.def_column_alias(:obj_id, :object_id)
|
|
2939
|
+
@Bar.def_column_alias(:obj_id, :object_id)
|
|
2940
|
+
@Foo.one_to_many :bars, :primary_key=>:obj_id, :primary_key_column=>:object_id, :key=>:object_id, :key_method=>:obj_id, :eager_loader_key=>:object_id, :class=>@Bar
|
|
2941
|
+
@Foo.one_to_one :bar, :primary_key=>:obj_id, :primary_key_column=>:object_id, :key=>:object_id, :key_method=>:obj_id, :eager_loader_key=>:object_id, :class=>@Bar
|
|
2942
|
+
@Bar.many_to_one :foo, :key=>:obj_id, :key_column=>:object_id, :primary_key=>:object_id, :primary_key_method=>:obj_id, :class=>@Foo
|
|
2943
|
+
@Foo.many_to_many :mtmbars, :join_table=>:bars_foos, :left_primary_key=>:obj_id, :left_primary_key_column=>:object_id, :right_primary_key=>:object_id, :right_primary_key_method=>:obj_id, :left_key=>:foo_id, :right_key=>:object_id, :eager_loader_key=>:object_id, :class=>@Bar
|
|
2944
|
+
@Bar.many_to_many :mtmfoos, :join_table=>:bars_foos, :left_primary_key=>:obj_id, :left_primary_key_column=>:object_id, :right_primary_key=>:object_id, :right_primary_key_method=>:obj_id, :left_key=>:object_id, :right_key=>:foo_id, :eager_loader_key=>:object_id, :class=>@Foo
|
|
2945
|
+
@foo = @Foo.load(:id=>1, :object_id=>2)
|
|
2946
|
+
@bar = @Bar.load(:id=>1, :object_id=>2)
|
|
2947
|
+
@db.sqls
|
|
2948
|
+
end
|
|
2949
|
+
|
|
2950
|
+
it "should have working regular association methods" do
|
|
2951
|
+
@Bar.first.foo.should == @foo
|
|
2952
|
+
@Foo.first.bars.should == [@bar]
|
|
2953
|
+
@Foo.first.bar.should == @bar
|
|
2954
|
+
@Foo.first.mtmbars.should == [@bar]
|
|
2955
|
+
@Bar.first.mtmfoos.should == [@foo]
|
|
2956
|
+
end
|
|
2957
|
+
|
|
2958
|
+
it "should have working eager loading methods" do
|
|
2959
|
+
@Bar.eager(:foo).all.map{|o| [o, o.foo]}.should == [[@bar, @foo]]
|
|
2960
|
+
@Foo.eager(:bars).all.map{|o| [o, o.bars]}.should == [[@foo, [@bar]]]
|
|
2961
|
+
@Foo.eager(:bar).all.map{|o| [o, o.bar]}.should == [[@foo, @bar]]
|
|
2962
|
+
@db.fetch = [[{:id=>1, :object_id=>2}], [{:id=>1, :object_id=>2, :x_foreign_key_x=>2}]]
|
|
2963
|
+
@Foo.eager(:mtmbars).all.map{|o| [o, o.mtmbars]}.should == [[@foo, [@bar]]]
|
|
2964
|
+
@db.fetch = [[{:id=>1, :object_id=>2}], [{:id=>1, :object_id=>2, :x_foreign_key_x=>2}]]
|
|
2965
|
+
@Bar.eager(:mtmfoos).all.map{|o| [o, o.mtmfoos]}.should == [[@bar, [@foo]]]
|
|
2966
|
+
end
|
|
2967
|
+
|
|
2968
|
+
it "should have working eager graphing methods" do
|
|
2969
|
+
@db.fetch = {:id=>1, :object_id=>2, :foo_id=>1, :foo_object_id=>2}
|
|
2970
|
+
@Bar.eager_graph(:foo).all.map{|o| [o, o.foo]}.should == [[@bar, @foo]]
|
|
2971
|
+
@db.fetch = {:id=>1, :object_id=>2, :bars_id=>1, :bars_object_id=>2}
|
|
2972
|
+
@Foo.eager_graph(:bars).all.map{|o| [o, o.bars]}.should == [[@foo, [@bar]]]
|
|
2973
|
+
@db.fetch = {:id=>1, :object_id=>2, :bar_id=>1, :bar_object_id=>2}
|
|
2974
|
+
@Foo.eager_graph(:bar).all.map{|o| [o, o.bar]}.should == [[@foo, @bar]]
|
|
2975
|
+
@db.fetch = {:id=>1, :object_id=>2, :mtmfoos_id=>1, :mtmfoos_object_id=>2}
|
|
2976
|
+
@Bar.eager_graph(:mtmfoos).all.map{|o| [o, o.mtmfoos]}.should == [[@bar, [@foo]]]
|
|
2977
|
+
@db.fetch = {:id=>1, :object_id=>2, :mtmbars_id=>1, :mtmbars_object_id=>2}
|
|
2978
|
+
@Foo.eager_graph(:mtmbars).all.map{|o| [o, o.mtmbars]}.should == [[@foo, [@bar]]]
|
|
2979
|
+
end
|
|
2980
|
+
|
|
2981
|
+
it "should have working modification methods" do
|
|
2982
|
+
b = @Bar.load(:id=>2, :object_id=>3)
|
|
2983
|
+
f = @Foo.load(:id=>2, :object_id=>3)
|
|
2984
|
+
@db.numrows = 1
|
|
2985
|
+
|
|
2986
|
+
@bar.foo = f
|
|
2987
|
+
@bar.obj_id.should == 3
|
|
2988
|
+
@foo.bar = @bar
|
|
2989
|
+
@bar.obj_id.should == 2
|
|
2990
|
+
|
|
2991
|
+
@foo.add_bar(b)
|
|
2992
|
+
@db.fetch = [[{:id=>1, :object_id=>2}, {:id=>2, :object_id=>2}], [{:id=>1, :object_id=>2}]]
|
|
2993
|
+
@foo.bars.should == [@bar, b]
|
|
2994
|
+
@foo.remove_bar(b)
|
|
2995
|
+
@foo.bars.should == [@bar]
|
|
2996
|
+
@foo.remove_all_bars
|
|
2997
|
+
@foo.bars.should == []
|
|
2998
|
+
|
|
2999
|
+
@db.fetch = [[{:id=>1, :object_id=>2}], [], [{:id=>2, :object_id=>2}]]
|
|
3000
|
+
@bar = @Bar.load(:id=>1, :object_id=>2)
|
|
3001
|
+
@foo.mtmbars.should == [@bar]
|
|
3002
|
+
@foo.remove_all_mtmbars
|
|
3003
|
+
@foo.mtmbars.should == []
|
|
3004
|
+
@foo.add_mtmbar(b)
|
|
3005
|
+
@foo.mtmbars.should == [b]
|
|
3006
|
+
@foo.remove_mtmbar(b)
|
|
3007
|
+
@foo.mtmbars.should == []
|
|
3008
|
+
|
|
3009
|
+
@db.fetch = [[{:id=>2, :object_id=>3}], [], [{:id=>2, :object_id=>3}]]
|
|
3010
|
+
@bar.add_mtmfoo(f)
|
|
3011
|
+
@bar.mtmfoos.should == [f]
|
|
3012
|
+
@bar.remove_all_mtmfoos
|
|
3013
|
+
@bar.mtmfoos.should == []
|
|
3014
|
+
@bar.add_mtmfoo(f)
|
|
3015
|
+
@bar.mtmfoos.should == [f]
|
|
3016
|
+
@bar.remove_mtmfoo(f)
|
|
3017
|
+
@bar.mtmfoos.should == []
|
|
3018
|
+
end
|
|
3019
|
+
end
|