sequel 3.21.0 → 3.36.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 +855 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +23 -7
- data/Rakefile +42 -24
- data/bin/sequel +26 -8
- data/doc/active_record.rdoc +1 -0
- data/doc/advanced_associations.rdoc +171 -11
- data/doc/association_basics.rdoc +293 -43
- data/doc/dataset_basics.rdoc +5 -5
- data/doc/dataset_filtering.rdoc +8 -0
- data/doc/mass_assignment.rdoc +56 -0
- data/doc/migration.rdoc +85 -552
- data/doc/model_hooks.rdoc +78 -27
- data/doc/object_model.rdoc +541 -0
- data/doc/opening_databases.rdoc +97 -50
- data/doc/prepared_statements.rdoc +40 -14
- data/doc/querying.rdoc +28 -4
- data/doc/reflection.rdoc +30 -4
- 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/release_notes/3.33.0.txt +157 -0
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/release_notes/3.35.0.txt +144 -0
- data/doc/release_notes/3.36.0.txt +245 -0
- data/doc/schema_modification.rdoc +572 -0
- data/doc/sharding.rdoc +95 -3
- data/doc/testing.rdoc +129 -0
- data/doc/thread_safety.rdoc +17 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +51 -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 +17 -11
- data/lib/sequel/adapters/do/postgres.rb +1 -57
- data/lib/sequel/adapters/do/sqlite.rb +0 -10
- data/lib/sequel/adapters/do.rb +18 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +453 -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 +47 -0
- data/lib/sequel/adapters/jdbc/derby.rb +287 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
- data/lib/sequel/adapters/jdbc/h2.rb +73 -31
- data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
- data/lib/sequel/adapters/jdbc/informix.rb +21 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +58 -48
- data/lib/sequel/adapters/jdbc/progress.rb +21 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
- data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +265 -94
- data/lib/sequel/adapters/mock.rb +361 -0
- data/lib/sequel/adapters/mysql.rb +118 -222
- data/lib/sequel/adapters/mysql2.rb +58 -57
- data/lib/sequel/adapters/odbc/mssql.rb +15 -7
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +349 -53
- data/lib/sequel/adapters/postgres.rb +356 -107
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +342 -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 +335 -118
- data/lib/sequel/adapters/shared/mysql.rb +340 -76
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
- data/lib/sequel/adapters/shared/oracle.rb +243 -45
- data/lib/sequel/adapters/shared/postgres.rb +524 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +265 -89
- data/lib/sequel/adapters/sqlite.rb +101 -39
- data/lib/sequel/adapters/swift/mysql.rb +9 -12
- data/lib/sequel/adapters/swift/postgres.rb +9 -74
- data/lib/sequel/adapters/swift/sqlite.rb +8 -6
- data/lib/sequel/adapters/swift.rb +8 -7
- data/lib/sequel/adapters/tinytds.rb +161 -21
- 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 +194 -0
- data/lib/sequel/connection_pool/sharded_single.rb +11 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +28 -2
- data/lib/sequel/connection_pool/single.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +38 -14
- data/lib/sequel/connection_pool.rb +10 -2
- data/lib/sequel/core.rb +118 -11
- data/lib/sequel/database/connecting.rb +38 -28
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +63 -2
- data/lib/sequel/database/logging.rb +7 -2
- data/lib/sequel/database/misc.rb +150 -46
- data/lib/sequel/database/query.rb +215 -65
- data/lib/sequel/database/schema_generator.rb +64 -20
- data/lib/sequel/database/schema_methods.rb +212 -54
- data/lib/sequel/dataset/actions.rb +322 -85
- data/lib/sequel/dataset/features.rb +96 -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 +68 -30
- data/lib/sequel/dataset/query.rb +237 -44
- data/lib/sequel/dataset/sql.rb +698 -278
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/_pretty_table.rb +79 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +108 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +16 -34
- data/lib/sequel/extensions/migration.rb +97 -11
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/null_dataset.rb +90 -0
- data/lib/sequel/extensions/pg_array.rb +460 -0
- data/lib/sequel/extensions/pg_array_ops.rb +220 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +169 -0
- data/lib/sequel/extensions/pg_hstore.rb +296 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
- data/lib/sequel/extensions/pg_inet.rb +89 -0
- data/lib/sequel/extensions/pg_json.rb +178 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
- data/lib/sequel/extensions/pretty_table.rb +5 -71
- data/lib/sequel/extensions/query.rb +1 -1
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +251 -37
- data/lib/sequel/extensions/select_remove.rb +35 -0
- data/lib/sequel/extensions/server_block.rb +139 -0
- data/lib/sequel/extensions/sql_expr.rb +4 -110
- 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 +1187 -393
- data/lib/sequel/model/base.rb +578 -170
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model.rb +30 -11
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +44 -12
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/dirty.rb +214 -0
- data/lib/sequel/plugins/eager_each.rb +59 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +123 -8
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +58 -6
- data/lib/sequel/plugins/list.rb +12 -2
- data/lib/sequel/plugins/many_through_many.rb +79 -28
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +139 -63
- data/lib/sequel/plugins/optimistic_locking.rb +8 -0
- data/lib/sequel/plugins/prepared_statements.rb +167 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +87 -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/schema.rb +7 -2
- 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 +5 -3
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/subclasses.rb +10 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/plugins/timestamps.rb +1 -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/validation_class_methods.rb +1 -1
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +526 -59
- 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/firebird_spec.rb +1 -1
- data/spec/adapters/mssql_spec.rb +142 -40
- data/spec/adapters/mysql_spec.rb +380 -234
- data/spec/adapters/oracle_spec.rb +67 -77
- data/spec/adapters/postgres_spec.rb +1050 -212
- data/spec/adapters/spec_helper.rb +8 -5
- data/spec/adapters/sqlite_spec.rb +139 -27
- data/spec/core/connection_pool_spec.rb +196 -93
- data/spec/core/database_spec.rb +879 -510
- data/spec/core/dataset_spec.rb +1415 -1086
- data/spec/core/expression_filters_spec.rb +554 -109
- data/spec/core/mock_adapter_spec.rb +449 -0
- data/spec/core/object_graph_spec.rb +86 -114
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +482 -38
- data/spec/core/spec_helper.rb +6 -48
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/arbitrary_servers_spec.rb +110 -0
- data/spec/extensions/association_autoreloading_spec.rb +18 -10
- data/spec/extensions/association_dependencies_spec.rb +15 -25
- data/spec/extensions/association_pks_spec.rb +66 -32
- data/spec/extensions/association_proxies_spec.rb +4 -4
- data/spec/extensions/caching_spec.rb +47 -51
- 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/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +119 -139
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +69 -92
- data/spec/extensions/identity_map_spec.rb +131 -22
- data/spec/extensions/inflector_spec.rb +0 -4
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +72 -0
- data/spec/extensions/json_serializer_spec.rb +49 -6
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +48 -39
- data/spec/extensions/many_through_many_spec.rb +283 -250
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +140 -35
- data/spec/extensions/named_timezones_spec.rb +29 -11
- data/spec/extensions/nested_attributes_spec.rb +251 -89
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +24 -21
- data/spec/extensions/pg_array_ops_spec.rb +105 -0
- data/spec/extensions/pg_array_spec.rb +196 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
- data/spec/extensions/pg_hstore_spec.rb +195 -0
- data/spec/extensions/pg_inet_spec.rb +44 -0
- data/spec/extensions/pg_json_spec.rb +101 -0
- data/spec/extensions/pg_statement_cache_spec.rb +209 -0
- 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 +87 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +7 -6
- data/spec/extensions/query_literals_spec.rb +168 -0
- data/spec/extensions/query_spec.rb +6 -0
- data/spec/extensions/rcte_tree_spec.rb +50 -43
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +429 -22
- data/spec/extensions/schema_spec.rb +25 -21
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +85 -43
- data/spec/extensions/server_block_spec.rb +90 -0
- data/spec/extensions/sharding_spec.rb +69 -143
- data/spec/extensions/single_table_inheritance_spec.rb +23 -29
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +22 -61
- data/spec/extensions/sql_expr_spec.rb +29 -60
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +17 -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 +9 -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 +29 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
- data/spec/integration/associations_test.rb +659 -21
- data/spec/integration/database_test.rb +9 -3
- data/spec/integration/dataset_test.rb +605 -91
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +81 -2
- data/spec/integration/plugin_test.rb +454 -143
- data/spec/integration/prepared_statement_test.rb +263 -128
- data/spec/integration/schema_test.rb +309 -43
- data/spec/integration/spec_helper.rb +40 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +18 -4
- data/spec/model/association_reflection_spec.rb +201 -7
- data/spec/model/associations_spec.rb +1067 -661
- data/spec/model/base_spec.rb +329 -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 +240 -168
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +490 -232
- data/spec/model/spec_helper.rb +14 -71
- data/spec/model/validations_spec.rb +11 -0
- data/spec/rcov.opts +2 -0
- metadata +178 -80
|
@@ -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" 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
|
|
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)
|
|
@@ -428,18 +457,24 @@ describe Sequel::Model, "many_to_one" do
|
|
|
428
457
|
MODEL_DB.sqls.should == []
|
|
429
458
|
end
|
|
430
459
|
|
|
460
|
+
it "should have the setter not modify the reciprocal if set to same value as current" do
|
|
461
|
+
@c2.many_to_one :parent, :class => @c2
|
|
462
|
+
@c2.one_to_many :children, :class => @c2, :key=>:parent_id
|
|
463
|
+
|
|
464
|
+
c1 = @c2.load(:id => 1, :parent_id=>nil)
|
|
465
|
+
c2 = @c2.load(:id => 2, :parent_id=>1)
|
|
466
|
+
c3 = @c2.load(:id => 3, :parent_id=>1)
|
|
467
|
+
c1.associations[:children] = [c2, c3]
|
|
468
|
+
c2.associations[:parent] = c1
|
|
469
|
+
c2.parent = c1
|
|
470
|
+
c1.children.should == [c2, c3]
|
|
471
|
+
MODEL_DB.sqls.should == []
|
|
472
|
+
end
|
|
473
|
+
|
|
431
474
|
it "should get all matching records and only return the first if :key option is set to nil" do
|
|
432
|
-
c2 = @c2
|
|
433
475
|
@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
|
|
476
|
+
@c2.many_to_one :first_grand_parent, :class => @c2, :key=>nil, :eager_graph=>:children, :dataset=>proc{model.filter(:children_id=>parent_id)}
|
|
477
|
+
@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
478
|
p = @c2.new(:parent_id=>2)
|
|
444
479
|
fgp = p.first_grand_parent
|
|
445
480
|
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 +535,15 @@ describe Sequel::Model, "many_to_one" do
|
|
|
500
535
|
h = []
|
|
501
536
|
@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
537
|
@c2.class_eval do
|
|
503
|
-
|
|
538
|
+
self::Foo = h
|
|
504
539
|
def []=(a, v)
|
|
505
|
-
a == :parent_id ? (
|
|
540
|
+
a == :parent_id ? (model::Foo << (v ? 4 : 5)) : super
|
|
506
541
|
end
|
|
507
542
|
def blah(x)
|
|
508
|
-
|
|
543
|
+
model::Foo << (x ? x.pk : :x)
|
|
509
544
|
end
|
|
510
545
|
def blahr(x)
|
|
511
|
-
|
|
546
|
+
model::Foo << 6
|
|
512
547
|
end
|
|
513
548
|
end
|
|
514
549
|
p = @c2.load(:id=>10)
|
|
@@ -524,13 +559,11 @@ describe Sequel::Model, "many_to_one" do
|
|
|
524
559
|
h = []
|
|
525
560
|
@c2.many_to_one :parent, :class => @c2, :after_load=>[proc{|x,y| h << [x.pk, y.pk]}, :al]
|
|
526
561
|
@c2.class_eval do
|
|
527
|
-
|
|
562
|
+
self::Foo = h
|
|
528
563
|
def al(v)
|
|
529
|
-
|
|
530
|
-
end
|
|
531
|
-
def @dataset.fetch_rows(sql)
|
|
532
|
-
yield({:id=>20})
|
|
564
|
+
model::Foo << v.pk
|
|
533
565
|
end
|
|
566
|
+
dataset._fetch = {:id=>20}
|
|
534
567
|
end
|
|
535
568
|
p = @c2.load(:id=>10, :parent_id=>20)
|
|
536
569
|
parent = p.parent
|
|
@@ -538,6 +571,18 @@ describe Sequel::Model, "many_to_one" do
|
|
|
538
571
|
parent.pk.should == 20
|
|
539
572
|
end
|
|
540
573
|
|
|
574
|
+
it "should support after_load association callback that changes the cached object" do
|
|
575
|
+
@c2.many_to_one :parent, :class => @c2, :after_load=>:al
|
|
576
|
+
@c2.class_eval do
|
|
577
|
+
def al(v)
|
|
578
|
+
associations[:parent] = :foo
|
|
579
|
+
end
|
|
580
|
+
end
|
|
581
|
+
p = @c2.load(:id=>10, :parent_id=>20)
|
|
582
|
+
p.parent.should == :foo
|
|
583
|
+
p.associations[:parent].should == :foo
|
|
584
|
+
end
|
|
585
|
+
|
|
541
586
|
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
587
|
# The reason for this is that assignment in ruby always returns the argument instead of the result
|
|
543
588
|
# of the method, so we can't return nil to signal that the association callback prevented the modification
|
|
@@ -565,35 +610,32 @@ describe Sequel::Model, "many_to_one" do
|
|
|
565
610
|
d = @c2.load(:id=>321)
|
|
566
611
|
p = @c2.new
|
|
567
612
|
p.associations[:parent] = d
|
|
568
|
-
h = []
|
|
569
613
|
@c2.many_to_one :parent, :class => @c2, :before_set=>:bs, :after_set=>:as
|
|
570
614
|
@c2.class_eval do
|
|
571
|
-
|
|
615
|
+
self::Foo = []
|
|
572
616
|
def []=(a, v)
|
|
573
|
-
a == :parent_id ? (
|
|
617
|
+
a == :parent_id ? (model::Foo << 5) : super
|
|
574
618
|
end
|
|
575
619
|
def bs(x)
|
|
576
|
-
|
|
620
|
+
model::Foo << x.pk
|
|
577
621
|
end
|
|
578
622
|
def as(x)
|
|
579
|
-
|
|
623
|
+
model::Foo << x.pk * 2
|
|
580
624
|
end
|
|
581
625
|
end
|
|
582
626
|
p.parent = c
|
|
583
|
-
|
|
627
|
+
@c2::Foo.should == [123, 5, 246]
|
|
584
628
|
end
|
|
585
629
|
end
|
|
586
630
|
|
|
587
631
|
describe Sequel::Model, "one_to_one" do
|
|
588
632
|
before do
|
|
589
633
|
@c1 = Class.new(Sequel::Model(:attributes)) do
|
|
590
|
-
def _refresh(ds); end
|
|
591
634
|
unrestrict_primary_key
|
|
592
635
|
columns :id, :node_id, :y
|
|
593
636
|
end
|
|
594
637
|
|
|
595
638
|
@c2 = Class.new(Sequel::Model(:nodes)) do
|
|
596
|
-
def _refresh(ds); end
|
|
597
639
|
unrestrict_primary_key
|
|
598
640
|
attr_accessor :xxx
|
|
599
641
|
|
|
@@ -602,24 +644,8 @@ describe Sequel::Model, "one_to_one" do
|
|
|
602
644
|
columns :id, :x, :parent_id, :par_parent_id, :blah, :node_id
|
|
603
645
|
end
|
|
604
646
|
@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
|
|
647
|
+
@dataset._fetch = {}
|
|
648
|
+
@c1.dataset._fetch = {}
|
|
623
649
|
MODEL_DB.reset
|
|
624
650
|
end
|
|
625
651
|
|
|
@@ -641,26 +667,24 @@ describe Sequel::Model, "one_to_one" do
|
|
|
641
667
|
it "should add a setter method" do
|
|
642
668
|
@c2.one_to_one :attribute, :class => @c1
|
|
643
669
|
attrib = @c1.new(:id=>3)
|
|
644
|
-
|
|
645
|
-
@c1.class_eval{remove_method :_refresh}
|
|
646
|
-
def d.fetch_rows(s); yield({:id=>3}) end
|
|
670
|
+
@c1.dataset._fetch = @c1.instance_dataset._fetch = {:id=>3}
|
|
647
671
|
@c2.new(:id => 1234).attribute = attrib
|
|
672
|
+
sqls = MODEL_DB.sqls
|
|
648
673
|
['INSERT INTO attributes (node_id, id) VALUES (1234, 3)',
|
|
649
|
-
'INSERT INTO attributes (id, node_id) VALUES (3, 1234)'].should(include(
|
|
650
|
-
|
|
651
|
-
|
|
674
|
+
'INSERT INTO attributes (id, node_id) VALUES (3, 1234)'].should(include(sqls.slice! 1))
|
|
675
|
+
sqls.should == ['UPDATE attributes SET node_id = NULL WHERE ((node_id = 1234) AND (id != 3))', "SELECT * FROM attributes WHERE (id = 3) LIMIT 1"]
|
|
676
|
+
|
|
652
677
|
@c2.new(:id => 1234).attribute.should == attrib
|
|
653
|
-
MODEL_DB.sqls.clear
|
|
654
678
|
attrib = @c1.load(:id=>3)
|
|
655
679
|
@c2.new(:id => 1234).attribute = attrib
|
|
656
|
-
MODEL_DB.sqls.should == [
|
|
680
|
+
MODEL_DB.sqls.should == ["SELECT * FROM attributes WHERE (attributes.node_id = 1234) LIMIT 1",
|
|
681
|
+
'UPDATE attributes SET node_id = NULL WHERE ((node_id = 1234) AND (id != 3))',
|
|
657
682
|
"UPDATE attributes SET node_id = 1234 WHERE (id = 3)"]
|
|
658
683
|
end
|
|
659
684
|
|
|
660
685
|
it "should use a transaction in the setter method" do
|
|
661
686
|
@c2.one_to_one :attribute, :class => @c1
|
|
662
687
|
@c2.use_transactions = true
|
|
663
|
-
MODEL_DB.sqls.clear
|
|
664
688
|
attrib = @c1.load(:id=>3)
|
|
665
689
|
@c2.new(:id => 1234).attribute = attrib
|
|
666
690
|
MODEL_DB.sqls.should == ['BEGIN',
|
|
@@ -673,7 +697,6 @@ describe Sequel::Model, "one_to_one" do
|
|
|
673
697
|
@c2.one_to_one :attribute, :class => @c1, :conditions=>{:a=>1} do |ds|
|
|
674
698
|
ds.filter(:b=>2)
|
|
675
699
|
end
|
|
676
|
-
MODEL_DB.sqls.clear
|
|
677
700
|
attrib = @c1.load(:id=>3)
|
|
678
701
|
@c2.new(:id => 1234).attribute = attrib
|
|
679
702
|
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 +706,30 @@ describe Sequel::Model, "one_to_one" do
|
|
|
683
706
|
it "should have the setter method respect the :primary_key option" do
|
|
684
707
|
@c2.one_to_one :attribute, :class => @c1, :primary_key=>:xxx
|
|
685
708
|
attrib = @c1.new(:id=>3)
|
|
686
|
-
|
|
687
|
-
@c1.class_eval{remove_method :_refresh}
|
|
688
|
-
def d.fetch_rows(s); yield({:id=>3}) end
|
|
709
|
+
@c1.dataset._fetch = @c1.instance_dataset._fetch = {:id=>3}
|
|
689
710
|
@c2.new(:id => 1234, :xxx=>5).attribute = attrib
|
|
711
|
+
sqls = MODEL_DB.sqls
|
|
690
712
|
['INSERT INTO attributes (node_id, id) VALUES (5, 3)',
|
|
691
|
-
'INSERT INTO attributes (id, node_id) VALUES (3, 5)'].should(include(
|
|
692
|
-
|
|
693
|
-
|
|
713
|
+
'INSERT INTO attributes (id, node_id) VALUES (3, 5)'].should(include(sqls.slice! 1))
|
|
714
|
+
sqls.should == ['UPDATE attributes SET node_id = NULL WHERE ((node_id = 5) AND (id != 3))', "SELECT * FROM attributes WHERE (id = 3) LIMIT 1"]
|
|
715
|
+
|
|
694
716
|
@c2.new(:id => 321, :xxx=>5).attribute.should == attrib
|
|
695
|
-
MODEL_DB.sqls.clear
|
|
696
717
|
attrib = @c1.load(:id=>3)
|
|
697
718
|
@c2.new(:id => 621, :xxx=>5).attribute = attrib
|
|
698
|
-
MODEL_DB.sqls.should == [
|
|
719
|
+
MODEL_DB.sqls.should == ["SELECT * FROM attributes WHERE (attributes.node_id = 5) LIMIT 1",
|
|
720
|
+
'UPDATE attributes SET node_id = NULL WHERE ((node_id = 5) AND (id != 3))',
|
|
699
721
|
'UPDATE attributes SET node_id = 5 WHERE (id = 3)']
|
|
700
722
|
end
|
|
701
723
|
|
|
702
724
|
it "should have the setter method respect composite keys" do
|
|
703
725
|
@c2.one_to_one :attribute, :class => @c1, :key=>[:node_id, :y], :primary_key=>[:id, :x]
|
|
704
726
|
attrib = @c1.load(:id=>3, :y=>6)
|
|
705
|
-
|
|
706
|
-
def d.fetch_rows(s); yield({:id=>3, :y=>6}) end
|
|
727
|
+
@c1.dataset._fetch = {:id=>3, :y=>6}
|
|
707
728
|
@c2.load(:id => 1234, :x=>5).attribute = attrib
|
|
708
|
-
|
|
709
|
-
|
|
729
|
+
sqls = MODEL_DB.sqls
|
|
730
|
+
sqls.last.should =~ /UPDATE attributes SET (node_id = 1234|y = 5), (node_id = 1234|y = 5) WHERE \(id = 3\)/
|
|
731
|
+
sqls.first.should =~ /UPDATE attributes SET (node_id|y) = NULL, (node_id|y) = NULL WHERE \(\(node_id = 1234\) AND \(y = 5\) AND \(id != 3\)\)/
|
|
732
|
+
sqls.length.should == 2
|
|
710
733
|
end
|
|
711
734
|
|
|
712
735
|
it "should use implicit key if omitted" do
|
|
@@ -721,31 +744,27 @@ describe Sequel::Model, "one_to_one" do
|
|
|
721
744
|
end
|
|
722
745
|
|
|
723
746
|
it "should use implicit class if omitted" do
|
|
724
|
-
|
|
747
|
+
begin
|
|
748
|
+
class ::ParParent < Sequel::Model; end
|
|
749
|
+
@c2.one_to_one :par_parent
|
|
750
|
+
@c2.new(:id => 234).par_parent.class.should == ParParent
|
|
751
|
+
MODEL_DB.sqls.should == ["SELECT * FROM par_parents WHERE (par_parents.node_id = 234) LIMIT 1"]
|
|
752
|
+
ensure
|
|
753
|
+
Object.send(:remove_const, :ParParent)
|
|
725
754
|
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
755
|
end
|
|
735
756
|
|
|
736
757
|
it "should use class inside module if given as a string" do
|
|
737
|
-
|
|
738
|
-
|
|
758
|
+
begin
|
|
759
|
+
module ::Par
|
|
760
|
+
class Parent < Sequel::Model; end
|
|
739
761
|
end
|
|
762
|
+
@c2.one_to_one :par_parent, :class=>"Par::Parent"
|
|
763
|
+
@c2.new(:id => 234).par_parent.class.should == Par::Parent
|
|
764
|
+
MODEL_DB.sqls.should == ["SELECT * FROM parents WHERE (parents.node_id = 234) LIMIT 1"]
|
|
765
|
+
ensure
|
|
766
|
+
Object.send(:remove_const, :Par)
|
|
740
767
|
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
768
|
end
|
|
750
769
|
|
|
751
770
|
it "should use explicit key if given" do
|
|
@@ -796,14 +815,12 @@ describe Sequel::Model, "one_to_one" do
|
|
|
796
815
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.node_id = 567) AND (a = 32)) LIMIT 1"]
|
|
797
816
|
|
|
798
817
|
@c2.one_to_one :parent, :class => @c2, :conditions=>:a
|
|
799
|
-
MODEL_DB.sqls.clear
|
|
800
818
|
@c2.new(:id => 567).parent
|
|
801
819
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.node_id = 567) AND a) LIMIT 1"]
|
|
802
820
|
end
|
|
803
821
|
|
|
804
822
|
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|
|
|
823
|
+
@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
824
|
ds.filter(:x.sql_number > 1)
|
|
808
825
|
end
|
|
809
826
|
@c2.load(:id => 100).child_20
|
|
@@ -813,24 +830,19 @@ describe Sequel::Model, "one_to_one" do
|
|
|
813
830
|
it "should return nil if primary_key value is nil" do
|
|
814
831
|
@c2.one_to_one :parent, :class => @c2, :primary_key=>:node_id
|
|
815
832
|
|
|
816
|
-
|
|
817
|
-
d.parent.should == nil
|
|
833
|
+
@c2.new(:id => 1).parent.should be_nil
|
|
818
834
|
MODEL_DB.sqls.should == []
|
|
819
835
|
end
|
|
820
836
|
|
|
821
837
|
it "should cache negative lookup" do
|
|
822
838
|
@c2.one_to_one :parent, :class => @c2
|
|
823
|
-
|
|
824
|
-
def ds.fetch_rows(sql, &block)
|
|
825
|
-
MODEL_DB.sqls << sql
|
|
826
|
-
end
|
|
827
|
-
|
|
839
|
+
@c2.dataset._fetch = []
|
|
828
840
|
d = @c2.new(:id => 555)
|
|
829
841
|
MODEL_DB.sqls.should == []
|
|
830
842
|
d.parent.should == nil
|
|
831
843
|
MODEL_DB.sqls.should == ['SELECT * FROM nodes WHERE (nodes.node_id = 555) LIMIT 1']
|
|
832
844
|
d.parent.should == nil
|
|
833
|
-
MODEL_DB.sqls.should == [
|
|
845
|
+
MODEL_DB.sqls.should == []
|
|
834
846
|
end
|
|
835
847
|
|
|
836
848
|
it "should define a setter method" do
|
|
@@ -838,28 +850,44 @@ describe Sequel::Model, "one_to_one" do
|
|
|
838
850
|
|
|
839
851
|
d = @c2.new(:id => 1)
|
|
840
852
|
f = @c2.new(:id => 3, :node_id=> 4321)
|
|
853
|
+
@c2.dataset._fetch = @c2.instance_dataset._fetch = {:id => 3, :node_id=>1}
|
|
841
854
|
d.parent = f
|
|
842
855
|
f.values.should == {:id => 3, :node_id=>1}
|
|
843
856
|
d.parent.should == f
|
|
857
|
+
sqls = MODEL_DB.sqls
|
|
858
|
+
["INSERT INTO nodes (node_id, id) VALUES (1, 3)",
|
|
859
|
+
"INSERT INTO nodes (id, node_id) VALUES (3, 1)"].should include(sqls.slice! 1)
|
|
860
|
+
sqls.should == ["UPDATE nodes SET node_id = NULL WHERE ((node_id = 1) AND (id != 3))", "SELECT * FROM nodes WHERE (id = 3) LIMIT 1"]
|
|
844
861
|
|
|
845
862
|
d.parent = nil
|
|
846
863
|
d.parent.should == nil
|
|
864
|
+
MODEL_DB.sqls.should == ["UPDATE nodes SET node_id = NULL WHERE (node_id = 1)"]
|
|
847
865
|
end
|
|
848
866
|
|
|
849
867
|
it "should have the setter method respect the :primary_key option" do
|
|
850
868
|
@c2.one_to_one :parent, :class => @c2, :primary_key=>:blah
|
|
851
869
|
d = @c2.new(:id => 1, :blah => 3)
|
|
852
870
|
e = @c2.new(:id => 4321, :node_id=>444)
|
|
871
|
+
@c2.dataset._fetch = @c2.instance_dataset._fetch = {:id => 4321, :node_id => 3}
|
|
853
872
|
d.parent = e
|
|
854
873
|
e.values.should == {:id => 4321, :node_id => 3}
|
|
874
|
+
sqls = MODEL_DB.sqls
|
|
875
|
+
["INSERT INTO nodes (node_id, id) VALUES (3, 4321)",
|
|
876
|
+
"INSERT INTO nodes (id, node_id) VALUES (4321, 3)"].should include(sqls.slice! 1)
|
|
877
|
+
sqls.should == ["UPDATE nodes SET node_id = NULL WHERE ((node_id = 3) AND (id != 4321))", "SELECT * FROM nodes WHERE (id = 4321) LIMIT 1"]
|
|
855
878
|
end
|
|
856
879
|
|
|
857
880
|
it "should have the setter method respect the :key option" do
|
|
858
881
|
@c2.one_to_one :parent, :class => @c2, :key=>:blah
|
|
859
882
|
d = @c2.new(:id => 3)
|
|
860
883
|
e = @c2.new(:id => 4321, :blah=>444)
|
|
884
|
+
@c2.dataset._fetch = @c2.instance_dataset._fetch = {:id => 4321, :blah => 3}
|
|
861
885
|
d.parent = e
|
|
862
886
|
e.values.should == {:id => 4321, :blah => 3}
|
|
887
|
+
sqls = MODEL_DB.sqls
|
|
888
|
+
["INSERT INTO nodes (blah, id) VALUES (3, 4321)",
|
|
889
|
+
"INSERT INTO nodes (id, blah) VALUES (4321, 3)"].should include(sqls.slice! 1)
|
|
890
|
+
sqls.should == ["UPDATE nodes SET blah = NULL WHERE ((blah = 3) AND (id != 4321))", "SELECT * FROM nodes WHERE (id = 4321) LIMIT 1"]
|
|
863
891
|
end
|
|
864
892
|
|
|
865
893
|
it "should persist changes to associated object when the setter is called" do
|
|
@@ -875,12 +903,11 @@ describe Sequel::Model, "one_to_one" do
|
|
|
875
903
|
|
|
876
904
|
d = @c2.load(:id => 1)
|
|
877
905
|
d.associations[:parent].should == nil
|
|
878
|
-
|
|
879
|
-
def ds.fetch_rows(sql, &block); MODEL_DB.sqls << sql; yield({:id=>234}) end
|
|
906
|
+
@c2.dataset._fetch = {:id=>234}
|
|
880
907
|
e = d.parent
|
|
881
908
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (nodes.node_id = 1) LIMIT 1"]
|
|
882
909
|
d.parent
|
|
883
|
-
MODEL_DB.sqls.should == [
|
|
910
|
+
MODEL_DB.sqls.should == []
|
|
884
911
|
d.associations[:parent].should == e
|
|
885
912
|
end
|
|
886
913
|
|
|
@@ -922,7 +949,6 @@ describe Sequel::Model, "one_to_one" do
|
|
|
922
949
|
e.child.should == d
|
|
923
950
|
MODEL_DB.sqls.should == ["UPDATE nodes SET parent_id = NULL WHERE ((parent_id = 1) AND (id != 2))",
|
|
924
951
|
"UPDATE nodes SET parent_id = 1 WHERE (id = 2)"]
|
|
925
|
-
MODEL_DB.reset
|
|
926
952
|
d.parent = nil
|
|
927
953
|
e.child.should == nil
|
|
928
954
|
MODEL_DB.sqls.should == ["UPDATE nodes SET parent_id = NULL WHERE (parent_id = 1)"]
|
|
@@ -931,17 +957,13 @@ describe Sequel::Model, "one_to_one" do
|
|
|
931
957
|
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
958
|
@c2.one_to_one :parent, :class => @c2, :key=>:parent_id
|
|
933
959
|
@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
|
|
960
|
+
@c2.dataset._fetch = []
|
|
938
961
|
|
|
939
962
|
d = @c2.load(:id => 1)
|
|
940
963
|
e = @c2.load(:id => 2)
|
|
941
964
|
f = @c2.load(:id => 3)
|
|
942
965
|
e.child.should == nil
|
|
943
966
|
f.child.should == nil
|
|
944
|
-
MODEL_DB.reset
|
|
945
967
|
d.parent = e
|
|
946
968
|
e.child.should == d
|
|
947
969
|
d.parent = f
|
|
@@ -951,6 +973,19 @@ describe Sequel::Model, "one_to_one" do
|
|
|
951
973
|
f.child.should == nil
|
|
952
974
|
end
|
|
953
975
|
|
|
976
|
+
it "should have the setter not modify the reciprocal if set to same value as current" do
|
|
977
|
+
@c2.one_to_one :parent, :class => @c2, :key=>:parent_id
|
|
978
|
+
@c2.many_to_one :child, :class => @c2, :key=>:parent_id
|
|
979
|
+
|
|
980
|
+
c1 = @c2.load(:id => 1, :parent_id=>nil)
|
|
981
|
+
c2 = @c2.load(:id => 2, :parent_id=>1)
|
|
982
|
+
c1.associations[:child] = c2
|
|
983
|
+
c2.associations[:parent] = c1
|
|
984
|
+
c2.parent = c1
|
|
985
|
+
c1.child.should == c2
|
|
986
|
+
MODEL_DB.sqls.should == []
|
|
987
|
+
end
|
|
988
|
+
|
|
954
989
|
it "should not add associations methods directly to class" do
|
|
955
990
|
@c2.one_to_one :parent, :class => @c2
|
|
956
991
|
@c2.instance_methods.collect{|x| x.to_s}.should(include('parent'))
|
|
@@ -983,12 +1018,12 @@ describe Sequel::Model, "one_to_one" do
|
|
|
983
1018
|
h = []
|
|
984
1019
|
@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
1020
|
@c2.class_eval do
|
|
986
|
-
|
|
1021
|
+
self::Foo = h
|
|
987
1022
|
def blah(x)
|
|
988
|
-
|
|
1023
|
+
model::Foo << (x ? x.pk : :x)
|
|
989
1024
|
end
|
|
990
1025
|
def blahr(x)
|
|
991
|
-
|
|
1026
|
+
model::Foo << 6
|
|
992
1027
|
end
|
|
993
1028
|
end
|
|
994
1029
|
p = @c2.load(:id=>10)
|
|
@@ -1004,13 +1039,11 @@ describe Sequel::Model, "one_to_one" do
|
|
|
1004
1039
|
h = []
|
|
1005
1040
|
@c2.one_to_one :parent, :class => @c2, :after_load=>[proc{|x,y| h << [x.pk, y.pk]}, :al]
|
|
1006
1041
|
@c2.class_eval do
|
|
1007
|
-
|
|
1042
|
+
self::Foo = h
|
|
1008
1043
|
def al(v)
|
|
1009
|
-
|
|
1010
|
-
end
|
|
1011
|
-
def @dataset.fetch_rows(sql)
|
|
1012
|
-
yield({:id=>20})
|
|
1044
|
+
model::Foo << v.pk
|
|
1013
1045
|
end
|
|
1046
|
+
@dataset._fetch = {:id=>20}
|
|
1014
1047
|
end
|
|
1015
1048
|
p = @c2.load(:id=>10)
|
|
1016
1049
|
parent = p.parent
|
|
@@ -1048,15 +1081,15 @@ describe Sequel::Model, "one_to_one" do
|
|
|
1048
1081
|
h = []
|
|
1049
1082
|
@c2.one_to_one :parent, :class => @c2, :before_set=>:bs, :after_set=>:as
|
|
1050
1083
|
@c2.class_eval do
|
|
1051
|
-
|
|
1084
|
+
self::Foo = h
|
|
1052
1085
|
def []=(a, v)
|
|
1053
|
-
a == :node_id ? (
|
|
1086
|
+
a == :node_id ? (model::Foo << 5) : super
|
|
1054
1087
|
end
|
|
1055
1088
|
def bs(x)
|
|
1056
|
-
|
|
1089
|
+
model::Foo << x.pk
|
|
1057
1090
|
end
|
|
1058
1091
|
def as(x)
|
|
1059
|
-
|
|
1092
|
+
model::Foo << x.pk * 2
|
|
1060
1093
|
end
|
|
1061
1094
|
end
|
|
1062
1095
|
p.parent = c
|
|
@@ -1072,16 +1105,9 @@ end
|
|
|
1072
1105
|
|
|
1073
1106
|
describe Sequel::Model, "one_to_many" do
|
|
1074
1107
|
before do
|
|
1075
|
-
MODEL_DB.reset
|
|
1076
|
-
|
|
1077
1108
|
@c1 = Class.new(Sequel::Model(:attributes)) do
|
|
1078
|
-
def _refresh(ds); end
|
|
1079
1109
|
unrestrict_primary_key
|
|
1080
1110
|
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
1111
|
end
|
|
1086
1112
|
|
|
1087
1113
|
@c2 = Class.new(Sequel::Model(:nodes)) do
|
|
@@ -1094,68 +1120,58 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1094
1120
|
columns :id, :x
|
|
1095
1121
|
end
|
|
1096
1122
|
@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
|
-
})
|
|
1123
|
+
@dataset._fetch = {}
|
|
1124
|
+
@c1.dataset._fetch = proc{|sql| sql =~ /SELECT 1/ ? {:a=>1} : {}}
|
|
1125
|
+
MODEL_DB.reset
|
|
1113
1126
|
end
|
|
1114
1127
|
|
|
1115
1128
|
it "should use implicit key if omitted" do
|
|
1116
1129
|
@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)'
|
|
1130
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE (attributes.node_id = 1234)'
|
|
1122
1131
|
end
|
|
1123
1132
|
|
|
1124
1133
|
it "should use implicit class if omitted" do
|
|
1125
|
-
|
|
1134
|
+
begin
|
|
1135
|
+
class ::HistoricalValue < Sequel::Model; end
|
|
1136
|
+
@c2.one_to_many :historical_values
|
|
1137
|
+
|
|
1138
|
+
v = @c2.new(:id => 1234).historical_values_dataset
|
|
1139
|
+
v.should be_a_kind_of(Sequel::Dataset)
|
|
1140
|
+
v.sql.should == 'SELECT * FROM historical_values WHERE (historical_values.node_id = 1234)'
|
|
1141
|
+
v.model.should == HistoricalValue
|
|
1142
|
+
ensure
|
|
1143
|
+
Object.send(:remove_const, :HistoricalValue)
|
|
1126
1144
|
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
1145
|
end
|
|
1136
1146
|
|
|
1137
1147
|
it "should use class inside a module if given as a string" do
|
|
1138
|
-
|
|
1139
|
-
|
|
1148
|
+
begin
|
|
1149
|
+
module ::Historical
|
|
1150
|
+
class Value < Sequel::Model; end
|
|
1140
1151
|
end
|
|
1152
|
+
@c2.one_to_many :historical_values, :class=>'Historical::Value'
|
|
1153
|
+
|
|
1154
|
+
v = @c2.new(:id => 1234).historical_values_dataset
|
|
1155
|
+
v.should be_a_kind_of(Sequel::Dataset)
|
|
1156
|
+
v.sql.should == 'SELECT * FROM values WHERE (values.node_id = 1234)'
|
|
1157
|
+
v.model.should == Historical::Value
|
|
1158
|
+
ensure
|
|
1159
|
+
Object.send(:remove_const, :Historical)
|
|
1141
1160
|
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
1161
|
end
|
|
1151
1162
|
|
|
1152
|
-
it "should use
|
|
1163
|
+
it "should use a callback if given one as the argument" do
|
|
1153
1164
|
@c2.one_to_many :attributes, :class => @c1, :key => :nodeid
|
|
1154
1165
|
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1166
|
+
d = @c2.load(:id => 1234)
|
|
1167
|
+
d.associations[:attributes] = []
|
|
1168
|
+
d.attributes(proc{|ds| ds.filter{name > 'M'}}).should_not == []
|
|
1169
|
+
MODEL_DB.sqls.should == ["SELECT * FROM attributes WHERE ((attributes.nodeid = 1234) AND (name > 'M'))"]
|
|
1170
|
+
end
|
|
1171
|
+
|
|
1172
|
+
it "should use explicit key if given" do
|
|
1173
|
+
@c2.one_to_many :attributes, :class => @c1, :key => :nodeid
|
|
1174
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE (attributes.nodeid = 1234)'
|
|
1159
1175
|
end
|
|
1160
1176
|
|
|
1161
1177
|
it "should support_composite keys" do
|
|
@@ -1180,10 +1196,8 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1180
1196
|
it "should define an add_ method that works on existing records" do
|
|
1181
1197
|
@c2.one_to_many :attributes, :class => @c1
|
|
1182
1198
|
|
|
1183
|
-
n = @c2.
|
|
1184
|
-
a = @c1.
|
|
1185
|
-
a.save
|
|
1186
|
-
MODEL_DB.reset
|
|
1199
|
+
n = @c2.load(:id => 1234)
|
|
1200
|
+
a = @c1.load(:id => 2345)
|
|
1187
1201
|
a.should == n.add_attribute(a)
|
|
1188
1202
|
a.values.should == {:node_id => 1234, :id => 2345}
|
|
1189
1203
|
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 1234 WHERE (id = 2345)']
|
|
@@ -1192,52 +1206,53 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1192
1206
|
it "should define an add_ method that works on new records" do
|
|
1193
1207
|
@c2.one_to_many :attributes, :class => @c1
|
|
1194
1208
|
|
|
1195
|
-
n = @c2.
|
|
1209
|
+
n = @c2.load(:id => 1234)
|
|
1196
1210
|
a = @c1.new(:id => 234)
|
|
1197
|
-
|
|
1198
|
-
MODEL_DB.reset
|
|
1211
|
+
@c1.dataset._fetch = @c1.instance_dataset._fetch = {:node_id => 1234, :id => 234}
|
|
1199
1212
|
a.should == n.add_attribute(a)
|
|
1200
|
-
MODEL_DB.sqls
|
|
1213
|
+
sqls = MODEL_DB.sqls
|
|
1214
|
+
sqls.shift.should =~ /INSERT INTO attributes \((node_)?id, (node_)?id\) VALUES \(1?234, 1?234\)/
|
|
1215
|
+
sqls.should == ["SELECT * FROM attributes WHERE (id = 234) LIMIT 1"]
|
|
1201
1216
|
a.values.should == {:node_id => 1234, :id => 234}
|
|
1202
1217
|
end
|
|
1203
1218
|
|
|
1204
1219
|
it "should define a remove_ method that works on existing records" do
|
|
1205
1220
|
@c2.one_to_many :attributes, :class => @c1
|
|
1206
1221
|
|
|
1207
|
-
n = @c2.
|
|
1208
|
-
a = @c1.
|
|
1209
|
-
a.save
|
|
1210
|
-
MODEL_DB.reset
|
|
1222
|
+
n = @c2.load(:id => 1234)
|
|
1223
|
+
a = @c1.load(:id => 2345, :node_id => 1234)
|
|
1211
1224
|
a.should == n.remove_attribute(a)
|
|
1212
1225
|
a.values.should == {:node_id => nil, :id => 2345}
|
|
1213
|
-
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = NULL WHERE (id = 2345)']
|
|
1226
|
+
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
1227
|
end
|
|
1215
1228
|
|
|
1216
1229
|
it "should have the remove_ method raise an error if the passed object is not already associated" do
|
|
1217
1230
|
@c2.one_to_many :attributes, :class => @c1
|
|
1218
|
-
@c1.dataset.opts[:empty] = true
|
|
1219
1231
|
|
|
1220
1232
|
n = @c2.new(:id => 1234)
|
|
1221
1233
|
a = @c1.load(:id => 2345, :node_id => 1234)
|
|
1222
|
-
|
|
1234
|
+
@c1.dataset._fetch = []
|
|
1223
1235
|
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"]
|
|
1236
|
+
MODEL_DB.sqls.should == ["SELECT 1 AS one FROM attributes WHERE ((attributes.node_id = 1234) AND (id = 2345)) LIMIT 1"]
|
|
1225
1237
|
end
|
|
1226
1238
|
|
|
1227
1239
|
it "should accept a hash for the add_ method and create a new record" do
|
|
1228
1240
|
@c2.one_to_many :attributes, :class => @c1
|
|
1229
1241
|
n = @c2.new(:id => 1234)
|
|
1230
1242
|
MODEL_DB.reset
|
|
1231
|
-
@c1.
|
|
1232
|
-
|
|
1243
|
+
@c1.dataset._fetch = @c1.instance_dataset._fetch = {:node_id => 1234, :id => 234}
|
|
1244
|
+
n.add_attribute(:id => 234).should == @c1.load(:node_id => 1234, :id => 234)
|
|
1245
|
+
sqls = MODEL_DB.sqls
|
|
1246
|
+
sqls.shift.should =~ /INSERT INTO attributes \((node_)?id, (node_)?id\) VALUES \(1?234, 1?234\)/
|
|
1247
|
+
sqls.should == ["SELECT * FROM attributes WHERE (id = 234) LIMIT 1"]
|
|
1233
1248
|
end
|
|
1234
1249
|
|
|
1235
1250
|
it "should accept a primary key for the add_ method" do
|
|
1236
1251
|
@c2.one_to_many :attributes, :class => @c1
|
|
1237
1252
|
n = @c2.new(:id => 1234)
|
|
1238
|
-
|
|
1239
|
-
@c1.load(:node_id => 1234, :id => 234)
|
|
1240
|
-
MODEL_DB.sqls.
|
|
1253
|
+
@c1.dataset._fetch = {:id=>234, :node_id=>nil}
|
|
1254
|
+
n.add_attribute(234).should == @c1.load(:node_id => 1234, :id => 234)
|
|
1255
|
+
MODEL_DB.sqls.should == ["SELECT * FROM attributes WHERE id = 234", "UPDATE attributes SET node_id = 1234 WHERE (id = 234)"]
|
|
1241
1256
|
end
|
|
1242
1257
|
|
|
1243
1258
|
it "should raise an error in the add_ method if the passed associated object is not of the correct type" do
|
|
@@ -1248,13 +1263,8 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1248
1263
|
it "should accept a primary key for the remove_ method and remove an existing record" do
|
|
1249
1264
|
@c2.one_to_many :attributes, :class => @c1
|
|
1250
1265
|
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)
|
|
1266
|
+
@c1.dataset._fetch = {:id=>234, :node_id=>1234}
|
|
1267
|
+
n.remove_attribute(234).should == @c1.load(:node_id => nil, :id => 234)
|
|
1258
1268
|
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (attributes.id = 234)) LIMIT 1',
|
|
1259
1269
|
'UPDATE attributes SET node_id = NULL WHERE (id = 234)']
|
|
1260
1270
|
end
|
|
@@ -1268,10 +1278,8 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1268
1278
|
@c2.one_to_many :attributes, :class => @c1, :primary_key=>:xxx
|
|
1269
1279
|
|
|
1270
1280
|
n = @c2.new(:id => 1234, :xxx=>5)
|
|
1271
|
-
a = @c1.
|
|
1272
|
-
a.
|
|
1273
|
-
MODEL_DB.reset
|
|
1274
|
-
a.should == n.add_attribute(a)
|
|
1281
|
+
a = @c1.load(:id => 2345)
|
|
1282
|
+
n.add_attribute(a).should == a
|
|
1275
1283
|
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 5 WHERE (id = 2345)']
|
|
1276
1284
|
end
|
|
1277
1285
|
|
|
@@ -1279,15 +1287,13 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1279
1287
|
@c2.one_to_many :attributes, :class => @c1
|
|
1280
1288
|
|
|
1281
1289
|
n = @c2.new(:id => 1234)
|
|
1282
|
-
a = @c1.
|
|
1283
|
-
a.save
|
|
1284
|
-
MODEL_DB.reset
|
|
1290
|
+
a = @c1.load(:id => 2345)
|
|
1285
1291
|
n.associations[:attributes] = []
|
|
1286
1292
|
a.should == n.add_attribute(a)
|
|
1287
1293
|
a.should == n.add_attribute(a)
|
|
1288
1294
|
a.values.should == {:node_id => 1234, :id => 2345}
|
|
1289
|
-
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 1234 WHERE (id = 2345)'] * 2
|
|
1290
1295
|
n.attributes.should == [a]
|
|
1296
|
+
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 1234 WHERE (id = 2345)'] * 2
|
|
1291
1297
|
end
|
|
1292
1298
|
|
|
1293
1299
|
it "should have add_ method respect composite keys" do
|
|
@@ -1295,18 +1301,24 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1295
1301
|
|
|
1296
1302
|
n = @c2.load(:id => 1234, :x=>5)
|
|
1297
1303
|
a = @c1.load(:id => 2345)
|
|
1298
|
-
a.should ==
|
|
1299
|
-
|
|
1304
|
+
n.add_attribute(a).should == a
|
|
1305
|
+
sqls = MODEL_DB.sqls
|
|
1306
|
+
sqls.shift.should =~ /UPDATE attributes SET (node_id = 1234|y = 5), (node_id = 1234|y = 5) WHERE \(id = 2345\)/
|
|
1307
|
+
sqls.should == []
|
|
1300
1308
|
end
|
|
1301
1309
|
|
|
1302
1310
|
it "should have add_ method accept a composite key" do
|
|
1303
1311
|
@c1.set_primary_key :id, :z
|
|
1304
1312
|
@c2.one_to_many :attributes, :class => @c1, :key =>[:node_id, :y], :primary_key=>[:id, :x]
|
|
1313
|
+
@c1.dataset._fetch = {:id => 2345, :z => 8, :node_id => 1234, :y=>5}
|
|
1305
1314
|
|
|
1306
1315
|
n = @c2.load(:id => 1234, :x=>5)
|
|
1307
1316
|
a = @c1.load(:id => 2345, :z => 8, :node_id => 1234, :y=>5)
|
|
1308
|
-
|
|
1309
|
-
|
|
1317
|
+
n.add_attribute([2345, 8]).should == a
|
|
1318
|
+
sqls = MODEL_DB.sqls
|
|
1319
|
+
sqls.shift.should =~ /SELECT \* FROM attributes WHERE \(\((id|z) = (2345|8)\) AND \((id|z) = (2345|8)\)\) LIMIT 1/
|
|
1320
|
+
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)\)\)/
|
|
1321
|
+
sqls.should == []
|
|
1310
1322
|
end
|
|
1311
1323
|
|
|
1312
1324
|
it "should have remove_ method respect composite keys" do
|
|
@@ -1314,31 +1326,29 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1314
1326
|
|
|
1315
1327
|
n = @c2.load(:id => 1234, :x=>5)
|
|
1316
1328
|
a = @c1.load(:id => 2345, :node_id=>1234, :y=>5)
|
|
1317
|
-
a.should ==
|
|
1318
|
-
|
|
1329
|
+
n.remove_attribute(a).should == a
|
|
1330
|
+
sqls = MODEL_DB.sqls
|
|
1331
|
+
sqls.pop.should =~ /UPDATE attributes SET (node_id|y) = NULL, (node_id|y) = NULL WHERE \(id = 2345\)/
|
|
1332
|
+
sqls.should == ["SELECT 1 AS one FROM attributes WHERE ((attributes.node_id = 1234) AND (attributes.y = 5) AND (id = 2345)) LIMIT 1"]
|
|
1319
1333
|
end
|
|
1320
1334
|
|
|
1321
1335
|
it "should accept a array of composite primary key values for the remove_ method and remove an existing record" do
|
|
1322
1336
|
@c1.set_primary_key :id, :y
|
|
1323
1337
|
@c2.one_to_many :attributes, :class => @c1, :key=>:node_id, :primary_key=>:id
|
|
1324
1338
|
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)\)\)/
|
|
1339
|
+
@c1.dataset._fetch = {:id=>234, :node_id=>123, :y=>5}
|
|
1340
|
+
n.remove_attribute([234, 5]).should == @c1.load(:node_id => nil, :y => 5, :id => 234)
|
|
1341
|
+
sqls = MODEL_DB.sqls
|
|
1342
|
+
sqls.length.should == 2
|
|
1343
|
+
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/
|
|
1344
|
+
sqls.last.should =~ /UPDATE attributes SET node_id = NULL WHERE \(\((id|y) = (234|5)\) AND \((id|y) = (234|5)\)\)/
|
|
1335
1345
|
end
|
|
1336
1346
|
|
|
1337
1347
|
it "should raise an error in add_ and remove_ if the passed object returns false to save (is not valid)" do
|
|
1338
1348
|
@c2.one_to_many :attributes, :class => @c1
|
|
1339
1349
|
n = @c2.new(:id => 1234)
|
|
1340
1350
|
a = @c1.new(:id => 2345)
|
|
1341
|
-
def a.
|
|
1351
|
+
def a.validate() errors.add(:id, 'foo') end
|
|
1342
1352
|
proc{n.add_attribute(a)}.should raise_error(Sequel::Error)
|
|
1343
1353
|
proc{n.remove_attribute(a)}.should raise_error(Sequel::Error)
|
|
1344
1354
|
end
|
|
@@ -1347,7 +1357,7 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1347
1357
|
@c2.one_to_many :attributes, :class => @c1, :validate=>false
|
|
1348
1358
|
n = @c2.new(:id => 1234)
|
|
1349
1359
|
a = @c1.new(:id => 2345)
|
|
1350
|
-
def a.
|
|
1360
|
+
def a.validate() errors.add(:id, 'foo') end
|
|
1351
1361
|
n.add_attribute(a).should == a
|
|
1352
1362
|
n.remove_attribute(a).should == a
|
|
1353
1363
|
end
|
|
@@ -1364,81 +1374,48 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1364
1374
|
|
|
1365
1375
|
it "should use :primary_key option if given" do
|
|
1366
1376
|
@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)"
|
|
1377
|
+
@c1.load(:id => 1234, :node_id=>4321).nodes_dataset.sql.should == "SELECT * FROM nodes WHERE (nodes.id = 4321)"
|
|
1369
1378
|
end
|
|
1370
1379
|
|
|
1371
1380
|
it "should support a select option" do
|
|
1372
1381
|
@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)"
|
|
1382
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == "SELECT id, name FROM attributes WHERE (attributes.node_id = 1234)"
|
|
1376
1383
|
end
|
|
1377
1384
|
|
|
1378
1385
|
it "should support a conditions option" do
|
|
1379
1386
|
@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))"
|
|
1387
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == "SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (a = 32))"
|
|
1382
1388
|
@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)"
|
|
1389
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == "SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND NOT a)"
|
|
1385
1390
|
end
|
|
1386
1391
|
|
|
1387
1392
|
it "should support an order option" do
|
|
1388
1393
|
@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"
|
|
1394
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == "SELECT * FROM attributes WHERE (attributes.node_id = 1234) ORDER BY kind"
|
|
1392
1395
|
end
|
|
1393
1396
|
|
|
1394
1397
|
it "should support an array for the order option" do
|
|
1395
1398
|
@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"
|
|
1399
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == "SELECT * FROM attributes WHERE (attributes.node_id = 1234) ORDER BY kind1, kind2"
|
|
1399
1400
|
end
|
|
1400
1401
|
|
|
1401
1402
|
it "should return array with all members of the association" do
|
|
1402
1403
|
@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)']
|
|
1404
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE (attributes.node_id = 1234)'
|
|
1412
1405
|
end
|
|
1413
1406
|
|
|
1414
1407
|
it "should accept a block" do
|
|
1415
1408
|
@c2.one_to_many :attributes, :class => @c1 do |ds|
|
|
1416
1409
|
ds.filter(:xxx => @xxx)
|
|
1417
1410
|
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))']
|
|
1411
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (xxx IS NULL))'
|
|
1427
1412
|
end
|
|
1428
1413
|
|
|
1429
1414
|
it "should support :order option with block" do
|
|
1430
1415
|
@c2.one_to_many :attributes, :class => @c1, :order => :kind do |ds|
|
|
1431
1416
|
ds.filter(:xxx => @xxx)
|
|
1432
1417
|
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']
|
|
1418
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (xxx IS NULL)) ORDER BY kind'
|
|
1442
1419
|
end
|
|
1443
1420
|
|
|
1444
1421
|
it "should have the block argument affect the _dataset method" do
|
|
@@ -1450,18 +1427,11 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1450
1427
|
|
|
1451
1428
|
it "should support a :dataset option that is used instead of the default" do
|
|
1452
1429
|
c1 = @c1
|
|
1453
|
-
@c2.one_to_many :all_other_attributes, :class => @c1, :dataset=>proc{c1.
|
|
1430
|
+
@c2.one_to_many :all_other_attributes, :class => @c1, :dataset=>proc{c1.exclude(:nodeid=>pk)}, :order=>:a, :limit=>10 do |ds|
|
|
1454
1431
|
ds.filter(:xxx => 5)
|
|
1455
1432
|
end
|
|
1456
|
-
|
|
1457
1433
|
@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
|
-
|
|
1434
|
+
@c2.new(:id => 1234).all_other_attributes.should == [@c1.load({})]
|
|
1465
1435
|
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE ((nodeid != 1234) AND (xxx = 5)) ORDER BY a LIMIT 10']
|
|
1466
1436
|
end
|
|
1467
1437
|
|
|
@@ -1479,9 +1449,7 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1479
1449
|
|
|
1480
1450
|
it "should set cached instance variable when accessed" do
|
|
1481
1451
|
@c2.one_to_many :attributes, :class => @c1
|
|
1482
|
-
|
|
1483
1452
|
n = @c2.new(:id => 1234)
|
|
1484
|
-
MODEL_DB.reset
|
|
1485
1453
|
n.associations.include?(:attributes).should == false
|
|
1486
1454
|
atts = n.attributes
|
|
1487
1455
|
atts.should == n.associations[:attributes]
|
|
@@ -1490,9 +1458,7 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1490
1458
|
|
|
1491
1459
|
it "should use cached instance variable if available" do
|
|
1492
1460
|
@c2.one_to_many :attributes, :class => @c1
|
|
1493
|
-
|
|
1494
1461
|
n = @c2.new(:id => 1234)
|
|
1495
|
-
MODEL_DB.reset
|
|
1496
1462
|
n.associations[:attributes] = 42
|
|
1497
1463
|
n.attributes.should == 42
|
|
1498
1464
|
MODEL_DB.sqls.should == []
|
|
@@ -1500,9 +1466,7 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1500
1466
|
|
|
1501
1467
|
it "should not use cached instance variable if asked to reload" do
|
|
1502
1468
|
@c2.one_to_many :attributes, :class => @c1
|
|
1503
|
-
|
|
1504
1469
|
n = @c2.new(:id => 1234)
|
|
1505
|
-
MODEL_DB.reset
|
|
1506
1470
|
n.associations[:attributes] = 42
|
|
1507
1471
|
n.attributes(true).should_not == 42
|
|
1508
1472
|
MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE (attributes.node_id = 1234)']
|
|
@@ -1510,10 +1474,8 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1510
1474
|
|
|
1511
1475
|
it "should add item to cached instance variable if it exists when calling add_" do
|
|
1512
1476
|
@c2.one_to_many :attributes, :class => @c1
|
|
1513
|
-
|
|
1514
1477
|
n = @c2.new(:id => 1234)
|
|
1515
|
-
att = @c1.
|
|
1516
|
-
MODEL_DB.reset
|
|
1478
|
+
att = @c1.load(:id => 345)
|
|
1517
1479
|
a = []
|
|
1518
1480
|
n.associations[:attributes] = a
|
|
1519
1481
|
n.add_attribute(att)
|
|
@@ -1535,7 +1497,6 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1535
1497
|
|
|
1536
1498
|
n = @c2.load(:id => 1234)
|
|
1537
1499
|
att = @c1.load(:id => 345)
|
|
1538
|
-
MODEL_DB.reset
|
|
1539
1500
|
a = [att]
|
|
1540
1501
|
n.associations[:attributes] = a
|
|
1541
1502
|
n.remove_attribute(att)
|
|
@@ -1587,13 +1548,9 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1587
1548
|
n = @c2.new(:id => 1234)
|
|
1588
1549
|
atts = n.attributes
|
|
1589
1550
|
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
|
|
1551
|
+
atts.should == [@c1.load({})]
|
|
1552
|
+
atts.map{|a| a.node}.should == [n]
|
|
1553
|
+
MODEL_DB.sqls.should == []
|
|
1597
1554
|
end
|
|
1598
1555
|
|
|
1599
1556
|
it "should use an explicit reciprocal instance variable if given" do
|
|
@@ -1602,19 +1559,15 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1602
1559
|
n = @c2.new(:id => 1234)
|
|
1603
1560
|
atts = n.attributes
|
|
1604
1561
|
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
|
|
1562
|
+
atts.should == [@c1.load({})]
|
|
1563
|
+
atts.map{|a| a.associations[:wxyz]}.should == [n]
|
|
1564
|
+
MODEL_DB.sqls.should == []
|
|
1612
1565
|
end
|
|
1613
1566
|
|
|
1614
1567
|
it "should have an remove_all_ method that removes all associations" do
|
|
1615
1568
|
@c2.one_to_many :attributes, :class => @c1
|
|
1616
1569
|
@c2.new(:id => 1234).remove_all_attributes
|
|
1617
|
-
MODEL_DB.sqls.
|
|
1570
|
+
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = NULL WHERE (node_id = 1234)']
|
|
1618
1571
|
end
|
|
1619
1572
|
|
|
1620
1573
|
it "should have remove_all method respect association filters" do
|
|
@@ -1628,13 +1581,15 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1628
1581
|
it "should have the remove_all_ method respect the :primary_key option" do
|
|
1629
1582
|
@c2.one_to_many :attributes, :class => @c1, :primary_key=>:xxx
|
|
1630
1583
|
@c2.new(:id => 1234, :xxx=>5).remove_all_attributes
|
|
1631
|
-
MODEL_DB.sqls.
|
|
1584
|
+
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = NULL WHERE (node_id = 5)']
|
|
1632
1585
|
end
|
|
1633
1586
|
|
|
1634
1587
|
it "should have the remove_all_ method respect composite keys" do
|
|
1635
1588
|
@c2.one_to_many :attributes, :class => @c1, :key=>[:node_id, :y], :primary_key=>[:id, :x]
|
|
1636
1589
|
@c2.new(:id => 1234, :x=>5).remove_all_attributes
|
|
1637
|
-
|
|
1590
|
+
sqls = MODEL_DB.sqls
|
|
1591
|
+
sqls.pop.should =~ /UPDATE attributes SET (node_id|y) = NULL, (node_id|y) = NULL WHERE \(\(node_id = 1234\) AND \(y = 5\)\)/
|
|
1592
|
+
sqls.should == []
|
|
1638
1593
|
end
|
|
1639
1594
|
|
|
1640
1595
|
it "remove_all should set the cached instance variable to []" do
|
|
@@ -1648,10 +1603,8 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1648
1603
|
@c2.one_to_many :attributes, :class => @c1
|
|
1649
1604
|
attrib = @c1.new(:id=>3)
|
|
1650
1605
|
node = @c2.new(:id => 1234)
|
|
1651
|
-
|
|
1652
|
-
def d.fetch_rows(s); end
|
|
1606
|
+
@c1.dataset._fetch = [[], [{:id=>3, :node_id=>1234}]]
|
|
1653
1607
|
node.attributes.should == []
|
|
1654
|
-
def attrib.save(*); self end
|
|
1655
1608
|
node.add_attribute(attrib)
|
|
1656
1609
|
node.associations[:attributes].should == [attrib]
|
|
1657
1610
|
node.remove_all_attributes.should == [attrib]
|
|
@@ -1665,15 +1618,12 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1665
1618
|
it "remove_all should remove the current item from all reciprocal instance varaibles if it cached instance variable exists" do
|
|
1666
1619
|
@c2.one_to_many :attributes, :class => @c1
|
|
1667
1620
|
@c1.many_to_one :node, :class => @c2
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
d = @c2.dataset
|
|
1671
|
-
def d.fetch_rows(s); end
|
|
1621
|
+
@c2.dataset._fetch = []
|
|
1622
|
+
@c1.dataset._fetch = [[], [{:id=>3, :node_id=>1234}]]
|
|
1672
1623
|
attrib = @c1.new(:id=>3)
|
|
1673
|
-
node = @c2.
|
|
1624
|
+
node = @c2.load(:id => 1234)
|
|
1674
1625
|
node.attributes.should == []
|
|
1675
1626
|
attrib.node.should == nil
|
|
1676
|
-
def attrib.save(*); self end
|
|
1677
1627
|
node.add_attribute(attrib)
|
|
1678
1628
|
attrib.associations[:node].should == node
|
|
1679
1629
|
node.remove_all_attributes
|
|
@@ -1761,18 +1711,18 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1761
1711
|
h = []
|
|
1762
1712
|
@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
1713
|
@c2.class_eval do
|
|
1764
|
-
|
|
1714
|
+
self::Foo = h
|
|
1765
1715
|
def _add_attribute(v)
|
|
1766
|
-
|
|
1716
|
+
model::Foo << 4
|
|
1767
1717
|
end
|
|
1768
1718
|
def _remove_attribute(v)
|
|
1769
|
-
|
|
1719
|
+
model::Foo << 5
|
|
1770
1720
|
end
|
|
1771
1721
|
def blah(x)
|
|
1772
|
-
|
|
1722
|
+
model::Foo << x.pk
|
|
1773
1723
|
end
|
|
1774
1724
|
def blahr(x)
|
|
1775
|
-
|
|
1725
|
+
model::Foo << 6
|
|
1776
1726
|
end
|
|
1777
1727
|
end
|
|
1778
1728
|
p = @c2.load(:id=>10)
|
|
@@ -1788,17 +1738,12 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1788
1738
|
h = []
|
|
1789
1739
|
@c2.one_to_many :attributes, :class => @c1, :after_load=>[proc{|x,y| h << [x.pk, y.collect{|z|z.pk}]}, :al]
|
|
1790
1740
|
@c2.class_eval do
|
|
1791
|
-
|
|
1741
|
+
self::Foo = h
|
|
1792
1742
|
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})
|
|
1743
|
+
v.each{|x| model::Foo << x.pk}
|
|
1800
1744
|
end
|
|
1801
1745
|
end
|
|
1746
|
+
@c1.dataset._fetch = [{:id=>20}, {:id=>30}]
|
|
1802
1747
|
p = @c2.load(:id=>10, :parent_id=>20)
|
|
1803
1748
|
attributes = p.attributes
|
|
1804
1749
|
h.should == [[10, [20, 30]], 20, 30]
|
|
@@ -1845,23 +1790,13 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1845
1790
|
end
|
|
1846
1791
|
|
|
1847
1792
|
describe Sequel::Model, "many_to_many" do
|
|
1848
|
-
|
|
1849
1793
|
before do
|
|
1850
|
-
MODEL_DB.reset
|
|
1851
|
-
|
|
1852
1794
|
@c1 = Class.new(Sequel::Model(:attributes)) do
|
|
1853
1795
|
unrestrict_primary_key
|
|
1854
1796
|
attr_accessor :yyy
|
|
1855
1797
|
def self.name; 'Attribute'; end
|
|
1856
1798
|
def self.to_s; 'Attribute'; end
|
|
1857
1799
|
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
1800
|
end
|
|
1866
1801
|
|
|
1867
1802
|
@c2 = Class.new(Sequel::Model(:nodes)) do
|
|
@@ -1873,98 +1808,61 @@ describe Sequel::Model, "many_to_many" do
|
|
|
1873
1808
|
columns :id, :x
|
|
1874
1809
|
end
|
|
1875
1810
|
@dataset = @c2.dataset
|
|
1811
|
+
@c1.dataset.autoid = 1
|
|
1876
1812
|
|
|
1877
|
-
[@c1, @c2].each
|
|
1878
|
-
|
|
1879
|
-
def fetch_rows(sql)
|
|
1880
|
-
@db << sql
|
|
1881
|
-
yield Hash.new
|
|
1882
|
-
end
|
|
1883
|
-
})
|
|
1884
|
-
end
|
|
1813
|
+
[@c1, @c2].each{|c| c.dataset._fetch = {}}
|
|
1814
|
+
MODEL_DB.reset
|
|
1885
1815
|
end
|
|
1886
1816
|
|
|
1887
1817
|
it "should use implicit key values and join table if omitted" do
|
|
1888
1818
|
@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))'
|
|
1819
|
+
@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
1820
|
end
|
|
1895
1821
|
|
|
1896
1822
|
it "should use implicit class if omitted" do
|
|
1897
|
-
|
|
1823
|
+
begin
|
|
1824
|
+
class ::Tag < Sequel::Model; end
|
|
1825
|
+
@c2.many_to_many :tags
|
|
1826
|
+
@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))'
|
|
1827
|
+
ensure
|
|
1828
|
+
Object.send(:remove_const, :Tag)
|
|
1898
1829
|
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
1830
|
end
|
|
1907
1831
|
|
|
1908
1832
|
it "should use class inside module if given as a string" do
|
|
1909
|
-
|
|
1910
|
-
|
|
1833
|
+
begin
|
|
1834
|
+
module ::Historical
|
|
1835
|
+
class Tag < Sequel::Model; end
|
|
1911
1836
|
end
|
|
1837
|
+
@c2.many_to_many :tags, :class=>'::Historical::Tag'
|
|
1838
|
+
@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))'
|
|
1839
|
+
ensure
|
|
1840
|
+
Object.send(:remove_const, :Historical)
|
|
1912
1841
|
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
1842
|
end
|
|
1921
1843
|
|
|
1922
1844
|
it "should use explicit key values and join table if given" do
|
|
1923
1845
|
@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'
|
|
1846
|
+
@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
1847
|
end
|
|
1937
1848
|
|
|
1938
1849
|
it "should support a conditions option" do
|
|
1939
1850
|
@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)'
|
|
1851
|
+
@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)'
|
|
1852
|
+
|
|
1944
1853
|
@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({})]
|
|
1854
|
+
@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)'
|
|
1855
|
+
@c2.new(:id => 1234).attributes.should == [@c1.load({})]
|
|
1950
1856
|
end
|
|
1951
1857
|
|
|
1952
1858
|
it "should support an order option" do
|
|
1953
1859
|
@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'
|
|
1860
|
+
@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
1861
|
end
|
|
1960
1862
|
|
|
1961
1863
|
it "should support an array for the order option" do
|
|
1962
1864
|
@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'
|
|
1865
|
+
@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
1866
|
end
|
|
1969
1867
|
|
|
1970
1868
|
it "should support :left_primary_key and :right_primary_key options" do
|
|
@@ -1999,19 +1897,13 @@ describe Sequel::Model, "many_to_many" do
|
|
|
1999
1897
|
it "should support a select option" do
|
|
2000
1898
|
@c2.many_to_many :attributes, :class => @c1, :select => :blah
|
|
2001
1899
|
|
|
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))'
|
|
1900
|
+
@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
1901
|
end
|
|
2007
1902
|
|
|
2008
1903
|
it "should support an array for the select option" do
|
|
2009
1904
|
@c2.many_to_many :attributes, :class => @c1, :select => [:attributes.*, :attribute_nodes__blah2]
|
|
2010
1905
|
|
|
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))'
|
|
1906
|
+
@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
1907
|
end
|
|
2016
1908
|
|
|
2017
1909
|
it "should accept a block" do
|
|
@@ -2021,11 +1913,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2021
1913
|
|
|
2022
1914
|
n = @c2.new(:id => 1234)
|
|
2023
1915
|
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)'
|
|
1916
|
+
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
1917
|
end
|
|
2030
1918
|
|
|
2031
1919
|
it "should allow the :order option while accepting a block" do
|
|
@@ -2035,20 +1923,9 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2035
1923
|
|
|
2036
1924
|
n = @c2.new(:id => 1234)
|
|
2037
1925
|
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'
|
|
1926
|
+
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
1927
|
end
|
|
2044
1928
|
|
|
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
1929
|
it "should support a :dataset option that is used instead of the default" do
|
|
2053
1930
|
c1 = @c1
|
|
2054
1931
|
@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 +1935,8 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2058
1935
|
n = @c2.new(:id => 1234)
|
|
2059
1936
|
n.xxx = 555
|
|
2060
1937
|
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'
|
|
1938
|
+
n.attributes.should == [@c1.load({})]
|
|
1939
|
+
MODEL_DB.sqls.should == ['SELECT * FROM attributes NATURAL JOIN an WHERE ((an.nodeid = 1234) AND (xxx = 555)) ORDER BY a LIMIT 10']
|
|
2066
1940
|
end
|
|
2067
1941
|
|
|
2068
1942
|
it "should support a :limit option" do
|
|
@@ -2077,15 +1951,32 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2077
1951
|
@c2.new(:id => 1234).attributes_dataset.opts[:eager].should == {:attributes=>nil}
|
|
2078
1952
|
end
|
|
2079
1953
|
|
|
1954
|
+
it "should handle an aliased join table" do
|
|
1955
|
+
@c2.many_to_many :attributes, :class => @c1, :join_table => :attribute2node___attributes_nodes
|
|
1956
|
+
n = @c2.load(:id => 1234)
|
|
1957
|
+
a = @c1.load(:id => 2345)
|
|
1958
|
+
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))"
|
|
1959
|
+
a.should == n.add_attribute(a)
|
|
1960
|
+
a.should == n.remove_attribute(a)
|
|
1961
|
+
n.remove_all_attributes
|
|
1962
|
+
sqls = MODEL_DB.sqls
|
|
1963
|
+
['INSERT INTO attribute2node (node_id, attribute_id) VALUES (1234, 2345)',
|
|
1964
|
+
'INSERT INTO attribute2node (attribute_id, node_id) VALUES (2345, 1234)'].should(include(sqls.shift))
|
|
1965
|
+
["DELETE FROM attribute2node WHERE ((node_id = 1234) AND (attribute_id = 2345))",
|
|
1966
|
+
"DELETE FROM attribute2node WHERE ((attribute_id = 2345) AND (node_id = 1234))"].should(include(sqls.shift))
|
|
1967
|
+
sqls.should == ["DELETE FROM attribute2node WHERE (node_id = 1234)"]
|
|
1968
|
+
end
|
|
1969
|
+
|
|
2080
1970
|
it "should define an add_ method that works on existing records" do
|
|
2081
1971
|
@c2.many_to_many :attributes, :class => @c1
|
|
2082
1972
|
|
|
2083
1973
|
n = @c2.load(:id => 1234)
|
|
2084
1974
|
a = @c1.load(:id => 2345)
|
|
2085
|
-
a.should ==
|
|
1975
|
+
n.add_attribute(a).should == a
|
|
1976
|
+
sqls = MODEL_DB.sqls
|
|
2086
1977
|
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 2345)',
|
|
2087
|
-
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (2345, 1234)'
|
|
2088
|
-
|
|
1978
|
+
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (2345, 1234)'].should(include(sqls.shift))
|
|
1979
|
+
sqls.should == []
|
|
2089
1980
|
end
|
|
2090
1981
|
|
|
2091
1982
|
it "should define an add_ method that works with a primary key" do
|
|
@@ -2093,21 +1984,25 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2093
1984
|
|
|
2094
1985
|
n = @c2.load(:id => 1234)
|
|
2095
1986
|
a = @c1.load(:id => 2345)
|
|
2096
|
-
|
|
1987
|
+
@c1.dataset._fetch = {:id=>2345}
|
|
1988
|
+
n.add_attribute(2345).should == a
|
|
1989
|
+
sqls = MODEL_DB.sqls
|
|
2097
1990
|
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 2345)',
|
|
2098
|
-
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (2345, 1234)'
|
|
2099
|
-
|
|
1991
|
+
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (2345, 1234)'].should(include(sqls.pop))
|
|
1992
|
+
sqls.should == ["SELECT * FROM attributes WHERE id = 2345"]
|
|
2100
1993
|
end
|
|
2101
1994
|
|
|
2102
1995
|
it "should allow passing a hash to the add_ method which creates a new record" do
|
|
2103
1996
|
@c2.many_to_many :attributes, :class => @c1
|
|
2104
1997
|
|
|
2105
1998
|
n = @c2.load(:id => 1234)
|
|
2106
|
-
@c1.
|
|
2107
|
-
|
|
1999
|
+
@c1.dataset._fetch = @c1.instance_dataset._fetch = {:id=>1}
|
|
2000
|
+
n.add_attribute(:id => 1).should == @c1.load(:id => 1)
|
|
2001
|
+
sqls = MODEL_DB.sqls
|
|
2108
2002
|
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 1)',
|
|
2109
2003
|
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (1, 1234)'
|
|
2110
|
-
].should(include(
|
|
2004
|
+
].should(include(sqls.pop))
|
|
2005
|
+
sqls.should == ['INSERT INTO attributes (id) VALUES (1)', "SELECT * FROM attributes WHERE (id = 1) LIMIT 1"]
|
|
2111
2006
|
end
|
|
2112
2007
|
|
|
2113
2008
|
it "should define a remove_ method that works on existing records" do
|
|
@@ -2115,8 +2010,8 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2115
2010
|
|
|
2116
2011
|
n = @c2.new(:id => 1234)
|
|
2117
2012
|
a = @c1.new(:id => 2345)
|
|
2118
|
-
a.should ==
|
|
2119
|
-
MODEL_DB.sqls.
|
|
2013
|
+
n.remove_attribute(a).should == a
|
|
2014
|
+
MODEL_DB.sqls.should == ['DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (attribute_id = 2345))']
|
|
2120
2015
|
end
|
|
2121
2016
|
|
|
2122
2017
|
it "should raise an error in the add_ method if the passed associated object is not of the correct type" do
|
|
@@ -2127,13 +2022,8 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2127
2022
|
it "should accept a primary key for the remove_ method and remove an existing record" do
|
|
2128
2023
|
@c2.many_to_many :attributes, :class => @c1
|
|
2129
2024
|
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)
|
|
2025
|
+
@c1.dataset._fetch = {:id=>234}
|
|
2026
|
+
n.remove_attribute(234).should == @c1.load(:id => 234)
|
|
2137
2027
|
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
2028
|
"DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (attribute_id = 234))"]
|
|
2139
2029
|
end
|
|
@@ -2148,10 +2038,12 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2148
2038
|
|
|
2149
2039
|
n = @c2.load(:id => 1234).set(:xxx=>5)
|
|
2150
2040
|
a = @c1.load(:id => 2345).set(:yyy=>8)
|
|
2151
|
-
a.should ==
|
|
2041
|
+
n.add_attribute(a).should == a
|
|
2042
|
+
sqls = MODEL_DB.sqls
|
|
2152
2043
|
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (5, 8)',
|
|
2153
2044
|
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (8, 5)'
|
|
2154
|
-
].should(include(
|
|
2045
|
+
].should(include(sqls.pop))
|
|
2046
|
+
sqls.should == []
|
|
2155
2047
|
end
|
|
2156
2048
|
|
|
2157
2049
|
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 +2062,9 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2170
2062
|
n = @c2.load(:id => 1234, :x=>5)
|
|
2171
2063
|
a = @c1.load(:id => 2345, :y=>8)
|
|
2172
2064
|
a.should == n.add_attribute(a)
|
|
2173
|
-
|
|
2065
|
+
sqls = MODEL_DB.sqls
|
|
2066
|
+
m = /INSERT INTO attributes_nodes \((\w+), (\w+), (\w+), (\w+)\) VALUES \((\d+), (\d+), (\d+), (\d+)\)/.match(sqls.pop)
|
|
2067
|
+
sqls.should == []
|
|
2174
2068
|
m.should_not == nil
|
|
2175
2069
|
map = {'l1'=>1234, 'l2'=>5, 'r1'=>2345, 'r2'=>8}
|
|
2176
2070
|
%w[l1 l2 r1 r2].each do |x|
|
|
@@ -2187,10 +2081,15 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2187
2081
|
|
|
2188
2082
|
it "should have the add_ method respect composite keys" do
|
|
2189
2083
|
@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]
|
|
2084
|
+
@c1.set_primary_key [:id, :y]
|
|
2190
2085
|
n = @c2.load(:id => 1234, :x=>5)
|
|
2191
2086
|
a = @c1.load(:id => 2345, :y=>8)
|
|
2192
|
-
|
|
2193
|
-
|
|
2087
|
+
@c1.dataset._fetch = {:id => 2345, :y=>8}
|
|
2088
|
+
n.add_attribute([2345, 8]).should == a
|
|
2089
|
+
sqls = MODEL_DB.sqls
|
|
2090
|
+
sqls.shift.should =~ /SELECT \* FROM attributes WHERE \(\((id|y) = (8|2345)\) AND \((id|y) = (8|2345)\)\) LIMIT 1/
|
|
2091
|
+
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)\)/
|
|
2092
|
+
sqls.should == []
|
|
2194
2093
|
end
|
|
2195
2094
|
|
|
2196
2095
|
it "should have the remove_ method respect the :left_primary_key and :right_primary_key options" do
|
|
@@ -2198,8 +2097,8 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2198
2097
|
|
|
2199
2098
|
n = @c2.new(:id => 1234, :xxx=>5)
|
|
2200
2099
|
a = @c1.new(:id => 2345, :yyy=>8)
|
|
2201
|
-
a.should ==
|
|
2202
|
-
MODEL_DB.sqls.
|
|
2100
|
+
n.remove_attribute(a).should == a
|
|
2101
|
+
MODEL_DB.sqls.should == ['DELETE FROM attributes_nodes WHERE ((node_id = 5) AND (attribute_id = 8))']
|
|
2203
2102
|
end
|
|
2204
2103
|
|
|
2205
2104
|
it "should have the remove_ method respect composite keys" do
|
|
@@ -2214,17 +2113,12 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2214
2113
|
@c1.set_primary_key [:id, :y]
|
|
2215
2114
|
@c2.many_to_many :attributes, :class => @c1
|
|
2216
2115
|
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
|
|
2116
|
+
@c1.dataset._fetch = {:id=>234, :y=>8}
|
|
2223
2117
|
@c1.load(:id => 234, :y=>8).should == n.remove_attribute([234, 8])
|
|
2118
|
+
sqls = MODEL_DB.sqls
|
|
2224
2119
|
["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
|
|
2120
|
+
"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)
|
|
2121
|
+
sqls.should == ["DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (attribute_id = 234))"]
|
|
2228
2122
|
end
|
|
2229
2123
|
|
|
2230
2124
|
it "should raise an error if the model object doesn't have a valid primary key" do
|
|
@@ -2242,6 +2136,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2242
2136
|
n = @c1.new
|
|
2243
2137
|
a = @c2.load(:id=>123)
|
|
2244
2138
|
n.new?.should == true
|
|
2139
|
+
@c1.dataset._fetch = {:id=>1}
|
|
2245
2140
|
a.add_attribute(n)
|
|
2246
2141
|
n.new?.should == false
|
|
2247
2142
|
end
|
|
@@ -2250,7 +2145,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2250
2145
|
@c2.many_to_many :attributes, :class => @c1
|
|
2251
2146
|
n = @c1.new
|
|
2252
2147
|
a = @c2.load(:id=>123)
|
|
2253
|
-
def n.
|
|
2148
|
+
def n.validate() errors.add(:id, 'foo') end
|
|
2254
2149
|
proc{a.add_attribute(n)}.should raise_error(Sequel::ValidationFailed)
|
|
2255
2150
|
end
|
|
2256
2151
|
|
|
@@ -2259,7 +2154,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2259
2154
|
n = @c1.new
|
|
2260
2155
|
n.raise_on_save_failure = false
|
|
2261
2156
|
a = @c2.load(:id=>123)
|
|
2262
|
-
def n.
|
|
2157
|
+
def n.validate() errors.add(:id, 'foo') end
|
|
2263
2158
|
proc{a.add_attribute(n)}.should raise_error(Sequel::Error)
|
|
2264
2159
|
end
|
|
2265
2160
|
|
|
@@ -2267,7 +2162,8 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2267
2162
|
@c2.many_to_many :attributes, :class => @c1, :validate=>false
|
|
2268
2163
|
n = @c1.new
|
|
2269
2164
|
a = @c2.load(:id=>123)
|
|
2270
|
-
def n.
|
|
2165
|
+
def n.validate() errors.add(:id, 'foo') end
|
|
2166
|
+
@c1.dataset._fetch = {:id=>1}
|
|
2271
2167
|
a.add_attribute(n)
|
|
2272
2168
|
n.new?.should == false
|
|
2273
2169
|
end
|
|
@@ -2282,31 +2178,23 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2282
2178
|
it "should provide an array with all members of the association" do
|
|
2283
2179
|
@c2.many_to_many :attributes, :class => @c1
|
|
2284
2180
|
|
|
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))'
|
|
2181
|
+
@c2.new(:id => 1234).attributes.should == [@c1.load({})]
|
|
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))']
|
|
2292
2183
|
end
|
|
2293
2184
|
|
|
2294
2185
|
it "should set cached instance variable when accessed" do
|
|
2295
2186
|
@c2.many_to_many :attributes, :class => @c1
|
|
2296
2187
|
|
|
2297
2188
|
n = @c2.new(:id => 1234)
|
|
2298
|
-
MODEL_DB.reset
|
|
2299
2189
|
n.associations.include?(:attributes).should == false
|
|
2300
2190
|
atts = n.attributes
|
|
2301
2191
|
atts.should == n.associations[:attributes]
|
|
2302
|
-
MODEL_DB.sqls.length.should == 1
|
|
2303
2192
|
end
|
|
2304
2193
|
|
|
2305
2194
|
it "should use cached instance variable if available" do
|
|
2306
2195
|
@c2.many_to_many :attributes, :class => @c1
|
|
2307
2196
|
|
|
2308
2197
|
n = @c2.new(:id => 1234)
|
|
2309
|
-
MODEL_DB.reset
|
|
2310
2198
|
n.associations[:attributes] = 42
|
|
2311
2199
|
n.attributes.should == 42
|
|
2312
2200
|
MODEL_DB.sqls.should == []
|
|
@@ -2316,18 +2204,16 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2316
2204
|
@c2.many_to_many :attributes, :class => @c1
|
|
2317
2205
|
|
|
2318
2206
|
n = @c2.new(:id => 1234)
|
|
2319
|
-
MODEL_DB.reset
|
|
2320
2207
|
n.associations[:attributes] = 42
|
|
2321
2208
|
n.attributes(true).should_not == 42
|
|
2322
|
-
MODEL_DB.sqls.
|
|
2209
|
+
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
2210
|
end
|
|
2324
2211
|
|
|
2325
2212
|
it "should add item to cached instance variable if it exists when calling add_" do
|
|
2326
2213
|
@c2.many_to_many :attributes, :class => @c1
|
|
2327
2214
|
|
|
2328
2215
|
n = @c2.new(:id => 1234)
|
|
2329
|
-
att = @c1.
|
|
2330
|
-
MODEL_DB.reset
|
|
2216
|
+
att = @c1.load(:id => 345)
|
|
2331
2217
|
a = []
|
|
2332
2218
|
n.associations[:attributes] = a
|
|
2333
2219
|
n.add_attribute(att)
|
|
@@ -2339,7 +2225,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2339
2225
|
@c1.many_to_many :nodes, :class => @c2
|
|
2340
2226
|
|
|
2341
2227
|
n = @c2.new(:id => 1234)
|
|
2342
|
-
att = @c1.
|
|
2228
|
+
att = @c1.load(:id => 345)
|
|
2343
2229
|
att.associations[:nodes] = []
|
|
2344
2230
|
n.add_attribute(att)
|
|
2345
2231
|
att.nodes.should == [n]
|
|
@@ -2349,8 +2235,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2349
2235
|
@c2.many_to_many :attributes, :class => @c1
|
|
2350
2236
|
|
|
2351
2237
|
n = @c2.new(:id => 1234)
|
|
2352
|
-
att = @c1.
|
|
2353
|
-
MODEL_DB.reset
|
|
2238
|
+
att = @c1.load(:id => 345)
|
|
2354
2239
|
a = [att]
|
|
2355
2240
|
n.associations[:attributes] = a
|
|
2356
2241
|
n.remove_attribute(att)
|
|
@@ -2397,13 +2282,13 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2397
2282
|
it "should have an remove_all_ method that removes all associations" do
|
|
2398
2283
|
@c2.many_to_many :attributes, :class => @c1
|
|
2399
2284
|
@c2.new(:id => 1234).remove_all_attributes
|
|
2400
|
-
MODEL_DB.sqls.
|
|
2285
|
+
MODEL_DB.sqls.should == ['DELETE FROM attributes_nodes WHERE (node_id = 1234)']
|
|
2401
2286
|
end
|
|
2402
2287
|
|
|
2403
2288
|
it "should have the remove_all_ method respect the :left_primary_key option" do
|
|
2404
2289
|
@c2.many_to_many :attributes, :class => @c1, :left_primary_key=>:xxx
|
|
2405
2290
|
@c2.new(:id => 1234, :xxx=>5).remove_all_attributes
|
|
2406
|
-
MODEL_DB.sqls.
|
|
2291
|
+
MODEL_DB.sqls.should == ['DELETE FROM attributes_nodes WHERE (node_id = 5)']
|
|
2407
2292
|
end
|
|
2408
2293
|
|
|
2409
2294
|
it "should have the remove_all_ method respect composite keys" do
|
|
@@ -2421,10 +2306,9 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2421
2306
|
|
|
2422
2307
|
it "remove_all should return the array of previously associated items if the cached instance variable exists" do
|
|
2423
2308
|
@c2.many_to_many :attributes, :class => @c1
|
|
2424
|
-
attrib = @c1.
|
|
2425
|
-
node = @c2.
|
|
2426
|
-
|
|
2427
|
-
def d.fetch_rows(s); end
|
|
2309
|
+
attrib = @c1.load(:id=>3)
|
|
2310
|
+
node = @c2.load(:id => 1234)
|
|
2311
|
+
@c1.dataset._fetch = []
|
|
2428
2312
|
node.attributes.should == []
|
|
2429
2313
|
node.add_attribute(attrib)
|
|
2430
2314
|
node.associations[:attributes].should == [attrib]
|
|
@@ -2439,11 +2323,9 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2439
2323
|
it "remove_all should remove the current item from all reciprocal instance varaibles if it cached instance variable exists" do
|
|
2440
2324
|
@c2.many_to_many :attributes, :class => @c1
|
|
2441
2325
|
@c1.many_to_many :nodes, :class => @c2
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
def d.fetch_rows(s); end
|
|
2446
|
-
attrib = @c1.new(:id=>3)
|
|
2326
|
+
@c1.dataset._fetch = []
|
|
2327
|
+
@c2.dataset._fetch = []
|
|
2328
|
+
attrib = @c1.load(:id=>3)
|
|
2447
2329
|
node = @c2.new(:id => 1234)
|
|
2448
2330
|
node.attributes.should == []
|
|
2449
2331
|
attrib.nodes.should == []
|
|
@@ -2459,8 +2341,9 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2459
2341
|
o.add_attribute(@c1.load(:id=>44))
|
|
2460
2342
|
o.remove_attribute(@c1.load(:id=>45))
|
|
2461
2343
|
o.remove_all_attributes
|
|
2462
|
-
MODEL_DB.sqls
|
|
2463
|
-
|
|
2344
|
+
sqls = MODEL_DB.sqls
|
|
2345
|
+
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)\)/
|
|
2346
|
+
sqls.should == ["DELETE FROM attributes_nodes WHERE ((x = 123) AND (node_id = 1234) AND (attribute_id = 45))",
|
|
2464
2347
|
"DELETE FROM attributes_nodes WHERE ((x = 123) AND (node_id = 1234))"]
|
|
2465
2348
|
end
|
|
2466
2349
|
|
|
@@ -2543,18 +2426,18 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2543
2426
|
h = []
|
|
2544
2427
|
@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
2428
|
@c2.class_eval do
|
|
2546
|
-
|
|
2429
|
+
self::Foo = h
|
|
2547
2430
|
def _add_attribute(v)
|
|
2548
|
-
|
|
2431
|
+
model::Foo << 4
|
|
2549
2432
|
end
|
|
2550
2433
|
def _remove_attribute(v)
|
|
2551
|
-
|
|
2434
|
+
model::Foo << 5
|
|
2552
2435
|
end
|
|
2553
2436
|
def blah(x)
|
|
2554
|
-
|
|
2437
|
+
model::Foo << x.pk
|
|
2555
2438
|
end
|
|
2556
2439
|
def blahr(x)
|
|
2557
|
-
|
|
2440
|
+
model::Foo << 6
|
|
2558
2441
|
end
|
|
2559
2442
|
end
|
|
2560
2443
|
p = @c2.load(:id=>10)
|
|
@@ -2570,17 +2453,12 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2570
2453
|
h = []
|
|
2571
2454
|
@c2.many_to_many :attributes, :class => @c1, :after_load=>[proc{|x,y| h << [x.pk, y.collect{|z|z.pk}]}, :al]
|
|
2572
2455
|
@c2.class_eval do
|
|
2573
|
-
|
|
2456
|
+
self::Foo = h
|
|
2574
2457
|
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})
|
|
2458
|
+
v.each{|x| model::Foo << x.pk}
|
|
2582
2459
|
end
|
|
2583
2460
|
end
|
|
2461
|
+
@c1.dataset._fetch = [{:id=>20}, {:id=>30}]
|
|
2584
2462
|
p = @c2.load(:id=>10, :parent_id=>20)
|
|
2585
2463
|
attributes = p.attributes
|
|
2586
2464
|
h.should == [[10, [20, 30]], 20, 30]
|
|
@@ -2623,14 +2501,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2623
2501
|
|
|
2624
2502
|
it "should support a :uniq option that removes duplicates from the association" do
|
|
2625
2503
|
@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
|
|
2504
|
+
@c1.dataset._fetch = [{:id=>20}, {:id=>30}, {:id=>20}, {:id=>30}]
|
|
2634
2505
|
@c2.load(:id=>10, :parent_id=>20).attributes.should == [@c1.load(:id=>20), @c1.load(:id=>30)]
|
|
2635
2506
|
end
|
|
2636
2507
|
|
|
@@ -2651,76 +2522,611 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2651
2522
|
@c2.many_to_many :attributes, :class => @c1 do |ds|
|
|
2652
2523
|
ds.filter(:join_table_att=>3)
|
|
2653
2524
|
end
|
|
2654
|
-
@c1.dataset.
|
|
2655
|
-
def fetch_rows(sql, &block)
|
|
2656
|
-
db.sqls << sql
|
|
2657
|
-
yield(:id=>2)
|
|
2658
|
-
end
|
|
2659
|
-
end
|
|
2525
|
+
@c1.dataset._fetch = {:id=>2}
|
|
2660
2526
|
@c2.load(:id=>1).remove_attribute(2)
|
|
2661
2527
|
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
2528
|
"DELETE FROM attributes_nodes WHERE ((node_id = 1) AND (attribute_id = 2))"]
|
|
2663
2529
|
end
|
|
2664
2530
|
end
|
|
2665
2531
|
|
|
2666
|
-
describe
|
|
2532
|
+
describe "Filtering by associations" do
|
|
2667
2533
|
before do
|
|
2668
|
-
|
|
2669
|
-
@
|
|
2670
|
-
|
|
2671
|
-
|
|
2534
|
+
@Album = Class.new(Sequel::Model(:albums))
|
|
2535
|
+
artist = @Artist = Class.new(Sequel::Model(:artists))
|
|
2536
|
+
tag = @Tag = Class.new(Sequel::Model(:tags))
|
|
2537
|
+
track = @Track = Class.new(Sequel::Model(:tracks))
|
|
2538
|
+
album_info = @AlbumInfo = Class.new(Sequel::Model(:album_infos))
|
|
2539
|
+
@Artist.columns :id, :id1, :id2
|
|
2540
|
+
@Tag.columns :id, :tid1, :tid2
|
|
2541
|
+
@Track.columns :id, :album_id, :album_id1, :album_id2
|
|
2542
|
+
@AlbumInfo.columns :id, :album_id, :album_id1, :album_id2
|
|
2543
|
+
@Album.class_eval do
|
|
2544
|
+
columns :id, :id1, :id2, :artist_id, :artist_id1, :artist_id2
|
|
2545
|
+
many_to_one :artist, :class=>artist
|
|
2546
|
+
one_to_many :tracks, :class=>track, :key=>:album_id
|
|
2547
|
+
one_to_one :album_info, :class=>album_info, :key=>:album_id
|
|
2548
|
+
many_to_many :tags, :class=>tag, :left_key=>:album_id, :join_table=>:albums_tags
|
|
2549
|
+
|
|
2550
|
+
many_to_one :cartist, :class=>artist, :key=>[:artist_id1, :artist_id2], :primary_key=>[:id1, :id2]
|
|
2551
|
+
one_to_many :ctracks, :class=>track, :key=>[:album_id1, :album_id2], :primary_key=>[:id1, :id2]
|
|
2552
|
+
one_to_one :calbum_info, :class=>album_info, :key=>[:album_id1, :album_id2], :primary_key=>[:id1, :id2]
|
|
2553
|
+
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
2554
|
end
|
|
2673
2555
|
end
|
|
2556
|
+
|
|
2557
|
+
it "should be able to filter on many_to_one associations" do
|
|
2558
|
+
@Album.filter(:artist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (albums.artist_id = 3)'
|
|
2559
|
+
end
|
|
2560
|
+
|
|
2561
|
+
it "should be able to filter on one_to_many associations" do
|
|
2562
|
+
@Album.filter(:tracks=>@Track.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE (albums.id = 3)'
|
|
2563
|
+
end
|
|
2564
|
+
|
|
2565
|
+
it "should be able to filter on one_to_one associations" do
|
|
2566
|
+
@Album.filter(:album_info=>@AlbumInfo.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE (albums.id = 3)'
|
|
2567
|
+
end
|
|
2568
|
+
|
|
2569
|
+
it "should be able to filter on many_to_many associations" do
|
|
2570
|
+
@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))))'
|
|
2571
|
+
end
|
|
2572
|
+
|
|
2573
|
+
it "should be able to filter on many_to_one associations with composite keys" do
|
|
2574
|
+
@Album.filter(:cartist=>@Artist.load(:id1=>3, :id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id1 = 3) AND (albums.artist_id2 = 4))'
|
|
2575
|
+
end
|
|
2576
|
+
|
|
2577
|
+
it "should be able to filter on one_to_many associations with composite keys" do
|
|
2578
|
+
@Album.filter(:ctracks=>@Track.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((albums.id1 = 3) AND (albums.id2 = 4))'
|
|
2579
|
+
end
|
|
2580
|
+
|
|
2581
|
+
it "should be able to filter on one_to_one associations with composite keys" do
|
|
2582
|
+
@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))'
|
|
2583
|
+
end
|
|
2584
|
+
|
|
2585
|
+
it "should be able to filter on many_to_many associations with composite keys" do
|
|
2586
|
+
@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))))'
|
|
2587
|
+
end
|
|
2588
|
+
|
|
2589
|
+
it "should work inside a complex filter" do
|
|
2590
|
+
artist = @Artist.load(:id=>3)
|
|
2591
|
+
@Album.filter{foo & {:artist=>artist}}.sql.should == 'SELECT * FROM albums WHERE (foo AND (albums.artist_id = 3))'
|
|
2592
|
+
track = @Track.load(:album_id=>4)
|
|
2593
|
+
@Album.filter{foo & [[:artist, artist], [:tracks, track]]}.sql.should == 'SELECT * FROM albums WHERE (foo AND (albums.artist_id = 3) AND (albums.id = 4))'
|
|
2594
|
+
end
|
|
2595
|
+
|
|
2596
|
+
it "should raise for an invalid association name" do
|
|
2597
|
+
proc{@Album.filter(:foo=>@Artist.load(:id=>3)).sql}.should raise_error(Sequel::Error)
|
|
2598
|
+
end
|
|
2599
|
+
|
|
2600
|
+
it "should raise for an invalid association type" do
|
|
2601
|
+
@Album.many_to_many :iatags, :clone=>:tags
|
|
2602
|
+
@Album.association_reflection(:iatags)[:type] = :foo
|
|
2603
|
+
proc{@Album.filter(:iatags=>@Tag.load(:id=>3)).sql}.should raise_error(Sequel::Error)
|
|
2604
|
+
end
|
|
2605
|
+
|
|
2606
|
+
it "should raise for an invalid associated object class " do
|
|
2607
|
+
proc{@Album.filter(:tags=>@Artist.load(:id=>3)).sql}.should raise_error(Sequel::Error)
|
|
2608
|
+
end
|
|
2609
|
+
|
|
2610
|
+
it "should raise for an invalid associated object class when multiple objects are used" do
|
|
2611
|
+
proc{@Album.filter(:tags=>[@Tag.load(:id=>3), @Artist.load(:id=>3)]).sql}.should raise_error(Sequel::Error)
|
|
2612
|
+
end
|
|
2613
|
+
|
|
2614
|
+
it "should correctly handle case when a multiple value association is used" do
|
|
2615
|
+
proc{@Album.filter(:tags=>[@Tag.load(:id=>3), @Artist.load(:id=>3)]).sql}.should raise_error(Sequel::Error)
|
|
2616
|
+
end
|
|
2617
|
+
|
|
2618
|
+
it "should not affect non-association IN/NOT IN filtering with an empty array" do
|
|
2619
|
+
@Album.filter(:tag_id=>[]).sql.should == 'SELECT * FROM albums WHERE (tag_id != tag_id)'
|
|
2620
|
+
@Album.exclude(:tag_id=>[]).sql.should == 'SELECT * FROM albums WHERE (tag_id = tag_id)'
|
|
2621
|
+
end
|
|
2622
|
+
|
|
2623
|
+
it "should work correctly in subclasses" do
|
|
2624
|
+
c = Class.new(@Album)
|
|
2625
|
+
c.many_to_one :sartist, :class=>@Artist
|
|
2626
|
+
c.filter(:sartist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (albums.sartist_id = 3)'
|
|
2627
|
+
end
|
|
2628
|
+
|
|
2629
|
+
it "should be able to exclude on many_to_one associations" do
|
|
2630
|
+
@Album.exclude(:artist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id != 3) OR (albums.artist_id IS NULL))'
|
|
2631
|
+
end
|
|
2632
|
+
|
|
2633
|
+
it "should be able to exclude on one_to_many associations" do
|
|
2634
|
+
@Album.exclude(:tracks=>@Track.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE ((albums.id != 3) OR (albums.id IS NULL))'
|
|
2635
|
+
end
|
|
2636
|
+
|
|
2637
|
+
it "should be able to exclude on one_to_one associations" do
|
|
2638
|
+
@Album.exclude(:album_info=>@AlbumInfo.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE ((albums.id != 3) OR (albums.id IS NULL))'
|
|
2639
|
+
end
|
|
2640
|
+
|
|
2641
|
+
it "should be able to exclude on many_to_many associations" do
|
|
2642
|
+
@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))'
|
|
2643
|
+
end
|
|
2644
|
+
|
|
2645
|
+
it "should be able to exclude on many_to_one associations with composite keys" do
|
|
2646
|
+
@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))'
|
|
2647
|
+
end
|
|
2648
|
+
|
|
2649
|
+
it "should be able to exclude on one_to_many associations with composite keys" do
|
|
2650
|
+
@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))'
|
|
2651
|
+
end
|
|
2652
|
+
|
|
2653
|
+
it "should be able to exclude on one_to_one associations with composite keys" do
|
|
2654
|
+
@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))'
|
|
2655
|
+
end
|
|
2656
|
+
|
|
2657
|
+
it "should be able to exclude on many_to_many associations with composite keys" do
|
|
2658
|
+
@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))'
|
|
2659
|
+
end
|
|
2660
|
+
|
|
2661
|
+
it "should be able to filter on multiple many_to_one associations" do
|
|
2662
|
+
@Album.filter(:artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE (albums.artist_id IN (3, 4))'
|
|
2663
|
+
end
|
|
2664
|
+
|
|
2665
|
+
it "should be able to filter on multiple one_to_many associations" do
|
|
2666
|
+
@Album.filter(:tracks=>[@Track.load(:album_id=>3), @Track.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (3, 4))'
|
|
2667
|
+
end
|
|
2668
|
+
|
|
2669
|
+
it "should be able to filter on multiple one_to_one associations" do
|
|
2670
|
+
@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))'
|
|
2671
|
+
end
|
|
2672
|
+
|
|
2673
|
+
it "should be able to filter on multiple many_to_many associations" do
|
|
2674
|
+
@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))))'
|
|
2675
|
+
end
|
|
2676
|
+
|
|
2677
|
+
it "should be able to filter on multiple many_to_one associations with composite keys" do
|
|
2678
|
+
@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)))'
|
|
2679
|
+
end
|
|
2680
|
+
|
|
2681
|
+
it "should be able to filter on multiple one_to_many associations with composite keys" do
|
|
2682
|
+
@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)))'
|
|
2683
|
+
end
|
|
2684
|
+
|
|
2685
|
+
it "should be able to filter on multiple one_to_one associations with composite keys" do
|
|
2686
|
+
@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)))'
|
|
2687
|
+
end
|
|
2688
|
+
|
|
2689
|
+
it "should be able to filter on multiple many_to_many associations with composite keys" do
|
|
2690
|
+
@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))))'
|
|
2691
|
+
end
|
|
2692
|
+
|
|
2693
|
+
it "should be able to exclude on multiple many_to_one associations" do
|
|
2694
|
+
@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))'
|
|
2695
|
+
end
|
|
2696
|
+
|
|
2697
|
+
it "should be able to exclude on multiple one_to_many associations" do
|
|
2698
|
+
@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))'
|
|
2699
|
+
end
|
|
2700
|
+
|
|
2701
|
+
it "should be able to exclude on multiple one_to_one associations" do
|
|
2702
|
+
@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))'
|
|
2703
|
+
end
|
|
2704
|
+
|
|
2705
|
+
it "should be able to exclude on multiple many_to_many associations" do
|
|
2706
|
+
@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))'
|
|
2707
|
+
end
|
|
2708
|
+
|
|
2709
|
+
it "should be able to exclude on multiple many_to_one associations with composite keys" do
|
|
2710
|
+
@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))'
|
|
2711
|
+
end
|
|
2712
|
+
|
|
2713
|
+
it "should be able to exclude on multiple one_to_many associations with composite keys" do
|
|
2714
|
+
@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))'
|
|
2715
|
+
end
|
|
2716
|
+
|
|
2717
|
+
it "should be able to exclude on multiple one_to_one associations with composite keys" do
|
|
2718
|
+
@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))'
|
|
2719
|
+
end
|
|
2720
|
+
|
|
2721
|
+
it "should be able to exclude on multiple many_to_many associations with composite keys" do
|
|
2722
|
+
@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))'
|
|
2723
|
+
end
|
|
2724
|
+
|
|
2725
|
+
it "should be able to handle NULL values when filtering many_to_one associations" do
|
|
2726
|
+
@Album.filter(:artist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2727
|
+
end
|
|
2728
|
+
|
|
2729
|
+
it "should be able to handle NULL values when filtering one_to_many associations" do
|
|
2730
|
+
@Album.filter(:tracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2731
|
+
end
|
|
2732
|
+
|
|
2733
|
+
it "should be able to handle NULL values when filtering one_to_one associations" do
|
|
2734
|
+
@Album.filter(:album_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2735
|
+
end
|
|
2736
|
+
|
|
2737
|
+
it "should be able to handle NULL values when filtering many_to_many associations" do
|
|
2738
|
+
@Album.filter(:tags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2739
|
+
end
|
|
2740
|
+
|
|
2741
|
+
it "should be able to handle filtering with NULL values for many_to_one associations with composite keys" do
|
|
2742
|
+
@Album.filter(:cartist=>@Artist.load(:id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2743
|
+
@Album.filter(:cartist=>@Artist.load(:id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2744
|
+
@Album.filter(:cartist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2745
|
+
end
|
|
2746
|
+
|
|
2747
|
+
it "should be able to filter with NULL values for one_to_many associations with composite keys" do
|
|
2748
|
+
@Album.filter(:ctracks=>@Track.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2749
|
+
@Album.filter(:ctracks=>@Track.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2750
|
+
@Album.filter(:ctracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2751
|
+
end
|
|
2752
|
+
|
|
2753
|
+
it "should be able to filter with NULL values for one_to_one associations with composite keys" do
|
|
2754
|
+
@Album.filter(:calbum_info=>@AlbumInfo.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2755
|
+
@Album.filter(:calbum_info=>@AlbumInfo.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2756
|
+
@Album.filter(:calbum_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2757
|
+
end
|
|
2758
|
+
|
|
2759
|
+
it "should be able to filter with NULL values for many_to_many associations with composite keys" do
|
|
2760
|
+
@Album.filter(:ctags=>@Tag.load(:tid1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2761
|
+
@Album.filter(:ctags=>@Tag.load(:tid2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2762
|
+
@Album.filter(:ctags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2763
|
+
end
|
|
2764
|
+
|
|
2765
|
+
it "should be able to handle NULL values when excluding many_to_one associations" do
|
|
2766
|
+
@Album.exclude(:artist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2767
|
+
end
|
|
2768
|
+
|
|
2769
|
+
it "should be able to handle NULL values when excluding one_to_many associations" do
|
|
2770
|
+
@Album.exclude(:tracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2771
|
+
end
|
|
2772
|
+
|
|
2773
|
+
it "should be able to handle NULL values when excluding one_to_one associations" do
|
|
2774
|
+
@Album.exclude(:album_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2775
|
+
end
|
|
2776
|
+
|
|
2777
|
+
it "should be able to handle NULL values when excluding many_to_many associations" do
|
|
2778
|
+
@Album.exclude(:tags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2779
|
+
end
|
|
2780
|
+
|
|
2781
|
+
it "should be able to handle excluding with NULL values for many_to_one associations with composite keys" do
|
|
2782
|
+
@Album.exclude(:cartist=>@Artist.load(:id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2783
|
+
@Album.exclude(:cartist=>@Artist.load(:id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2784
|
+
@Album.exclude(:cartist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2785
|
+
end
|
|
2786
|
+
|
|
2787
|
+
it "should be able to excluding with NULL values for one_to_many associations with composite keys" do
|
|
2788
|
+
@Album.exclude(:ctracks=>@Track.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2789
|
+
@Album.exclude(:ctracks=>@Track.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2790
|
+
@Album.exclude(:ctracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2791
|
+
end
|
|
2792
|
+
|
|
2793
|
+
it "should be able to excluding with NULL values for one_to_one associations with composite keys" do
|
|
2794
|
+
@Album.exclude(:calbum_info=>@AlbumInfo.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2795
|
+
@Album.exclude(:calbum_info=>@AlbumInfo.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2796
|
+
@Album.exclude(:calbum_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2797
|
+
end
|
|
2798
|
+
|
|
2799
|
+
it "should be able to excluding with NULL values for many_to_many associations with composite keys" do
|
|
2800
|
+
@Album.exclude(:ctags=>@Tag.load(:tid1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2801
|
+
@Album.exclude(:ctags=>@Tag.load(:tid2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2802
|
+
@Album.exclude(:ctags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2803
|
+
end
|
|
2804
|
+
|
|
2805
|
+
it "should be able to handle NULL values when filtering multiple many_to_one associations" do
|
|
2806
|
+
@Album.filter(:artist=>[@Artist.load(:id=>3), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE (albums.artist_id IN (3))'
|
|
2807
|
+
@Album.filter(:artist=>[@Artist.new, @Artist.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2808
|
+
end
|
|
2809
|
+
|
|
2810
|
+
it "should be able to handle NULL values when filtering multiple one_to_many associations" do
|
|
2811
|
+
@Album.filter(:tracks=>[@Track.load(:album_id=>3), @Track.new]).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (3))'
|
|
2812
|
+
@Album.filter(:tracks=>[@Track.new, @Track.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2813
|
+
end
|
|
2814
|
+
|
|
2815
|
+
it "should be able to handle NULL values when filtering multiple one_to_one associations" do
|
|
2816
|
+
@Album.filter(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (3))'
|
|
2817
|
+
@Album.filter(:album_info=>[@AlbumInfo.new, @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2818
|
+
end
|
|
2819
|
+
|
|
2820
|
+
it "should be able to handle NULL values when filtering multiple many_to_many associations" do
|
|
2821
|
+
@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))))'
|
|
2822
|
+
@Album.filter(:tags=>[@Tag.new, @Tag.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2823
|
+
end
|
|
2824
|
+
|
|
2825
|
+
it "should be able to handle NULL values when filtering multiple many_to_one associations with composite keys" do
|
|
2826
|
+
@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)))'
|
|
2827
|
+
@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)))'
|
|
2828
|
+
end
|
|
2829
|
+
|
|
2830
|
+
it "should be able handle NULL values when filtering multiple one_to_many associations with composite keys" do
|
|
2831
|
+
@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)))'
|
|
2832
|
+
@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)))'
|
|
2833
|
+
end
|
|
2834
|
+
|
|
2835
|
+
it "should be able to handle NULL values when filtering multiple one_to_one associations with composite keys" do
|
|
2836
|
+
@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)))'
|
|
2837
|
+
@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)))'
|
|
2838
|
+
end
|
|
2839
|
+
|
|
2840
|
+
it "should be able to handle NULL values when filtering multiple many_to_many associations with composite keys" do
|
|
2841
|
+
@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))))'
|
|
2842
|
+
@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))))'
|
|
2843
|
+
end
|
|
2844
|
+
|
|
2845
|
+
it "should be able to handle NULL values when excluding multiple many_to_one associations" do
|
|
2846
|
+
@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))'
|
|
2847
|
+
@Album.exclude(:artist=>[@Artist.new, @Artist.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2848
|
+
end
|
|
2849
|
+
|
|
2850
|
+
it "should be able to handle NULL values when excluding multiple one_to_many associations" do
|
|
2851
|
+
@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))'
|
|
2852
|
+
@Album.exclude(:tracks=>[@Track.new, @Track.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2853
|
+
end
|
|
2854
|
+
|
|
2855
|
+
it "should be able to handle NULL values when excluding multiple one_to_one associations" do
|
|
2856
|
+
@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))'
|
|
2857
|
+
@Album.exclude(:album_info=>[@AlbumInfo.new, @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2858
|
+
end
|
|
2859
|
+
|
|
2860
|
+
it "should be able to handle NULL values when excluding multiple many_to_many associations" do
|
|
2861
|
+
@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))'
|
|
2862
|
+
@Album.exclude(:tags=>[@Tag.new, @Tag.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
2863
|
+
end
|
|
2864
|
+
|
|
2865
|
+
it "should be able to handle NULL values when excluding multiple many_to_one associations with composite keys" do
|
|
2866
|
+
@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))'
|
|
2867
|
+
@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))'
|
|
2868
|
+
end
|
|
2869
|
+
|
|
2870
|
+
it "should be able handle NULL values when excluding multiple one_to_many associations with composite keys" do
|
|
2871
|
+
@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))'
|
|
2872
|
+
@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))'
|
|
2873
|
+
end
|
|
2874
|
+
|
|
2875
|
+
it "should be able to handle NULL values when excluding multiple one_to_one associations with composite keys" do
|
|
2876
|
+
@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))'
|
|
2877
|
+
@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))'
|
|
2878
|
+
end
|
|
2879
|
+
|
|
2880
|
+
it "should be able to handle NULL values when excluding multiple many_to_many associations with composite keys" do
|
|
2881
|
+
@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))'
|
|
2882
|
+
@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))'
|
|
2883
|
+
end
|
|
2884
|
+
|
|
2885
|
+
it "should be able to filter on many_to_one association datasets" do
|
|
2886
|
+
@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))))'
|
|
2887
|
+
end
|
|
2888
|
+
|
|
2889
|
+
it "should be able to filter on one_to_many association datasets" do
|
|
2890
|
+
@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))))'
|
|
2891
|
+
end
|
|
2892
|
+
|
|
2893
|
+
it "should be able to filter on one_to_one association datasets" do
|
|
2894
|
+
@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))))'
|
|
2895
|
+
end
|
|
2896
|
+
|
|
2897
|
+
it "should be able to filter on many_to_many association datasets" do
|
|
2898
|
+
@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))))'
|
|
2899
|
+
end
|
|
2900
|
+
|
|
2901
|
+
it "should be able to filter on many_to_one association datasets with composite keys" do
|
|
2902
|
+
@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))))'
|
|
2903
|
+
end
|
|
2904
|
+
|
|
2905
|
+
it "should be able to filter on one_to_many association datasets with composite keys" do
|
|
2906
|
+
@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))))'
|
|
2907
|
+
end
|
|
2908
|
+
|
|
2909
|
+
it "should be able to filter on one_to_one association datasets with composite keys" do
|
|
2910
|
+
@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))))'
|
|
2911
|
+
end
|
|
2912
|
+
|
|
2913
|
+
it "should be able to filter on many_to_many association datasets with composite keys" do
|
|
2914
|
+
@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))))'
|
|
2915
|
+
end
|
|
2916
|
+
|
|
2917
|
+
it "should be able to exclude on many_to_one association datasets" do
|
|
2918
|
+
@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))'
|
|
2919
|
+
end
|
|
2920
|
+
|
|
2921
|
+
it "should be able to exclude on one_to_many association datasets" do
|
|
2922
|
+
@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))'
|
|
2923
|
+
end
|
|
2924
|
+
|
|
2925
|
+
it "should be able to exclude on one_to_one association datasets" do
|
|
2926
|
+
@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))'
|
|
2927
|
+
end
|
|
2928
|
+
|
|
2929
|
+
it "should be able to exclude on many_to_many association datasets" do
|
|
2930
|
+
@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))'
|
|
2931
|
+
end
|
|
2932
|
+
|
|
2933
|
+
it "should be able to exclude on many_to_one association datasets with composite keys" do
|
|
2934
|
+
@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))'
|
|
2935
|
+
end
|
|
2936
|
+
|
|
2937
|
+
it "should be able to exclude on one_to_many association datasets with composite keys" do
|
|
2938
|
+
@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))'
|
|
2939
|
+
end
|
|
2940
|
+
|
|
2941
|
+
it "should be able to exclude on one_to_one association datasets with composite keys" do
|
|
2942
|
+
@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))'
|
|
2943
|
+
end
|
|
2944
|
+
|
|
2945
|
+
it "should be able to exclude on many_to_many association datasets with composite keys" do
|
|
2946
|
+
@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))'
|
|
2947
|
+
end
|
|
2948
|
+
|
|
2949
|
+
it "should do a regular IN query if the dataset for a different model is used" do
|
|
2950
|
+
@Album.filter(:artist=>@Album.select(:x)).sql.should == 'SELECT * FROM albums WHERE (artist IN (SELECT x FROM albums))'
|
|
2951
|
+
end
|
|
2952
|
+
|
|
2953
|
+
it "should do a regular IN query if a non-model dataset is used" do
|
|
2954
|
+
@Album.filter(:artist=>@Album.db.from(:albums).select(:x)).sql.should == 'SELECT * FROM albums WHERE (artist IN (SELECT x FROM albums))'
|
|
2955
|
+
end
|
|
2956
|
+
end
|
|
2957
|
+
|
|
2958
|
+
describe "Sequel::Model Associations with clashing column names" do
|
|
2959
|
+
before do
|
|
2960
|
+
@db = Sequel.mock(:fetch=>{:id=>1, :object_id=>2})
|
|
2961
|
+
@Foo = Class.new(Sequel::Model(@db[:foos]))
|
|
2962
|
+
@Bar = Class.new(Sequel::Model(@db[:bars]))
|
|
2963
|
+
@Foo.columns :id, :object_id
|
|
2964
|
+
@Bar.columns :id, :object_id
|
|
2965
|
+
@Foo.def_column_alias(:obj_id, :object_id)
|
|
2966
|
+
@Bar.def_column_alias(:obj_id, :object_id)
|
|
2967
|
+
@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
|
|
2968
|
+
@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
|
|
2969
|
+
@Bar.many_to_one :foo, :key=>:obj_id, :key_column=>:object_id, :primary_key=>:object_id, :primary_key_method=>:obj_id, :class=>@Foo
|
|
2970
|
+
@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
|
|
2971
|
+
@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
|
|
2972
|
+
@foo = @Foo.load(:id=>1, :object_id=>2)
|
|
2973
|
+
@bar = @Bar.load(:id=>1, :object_id=>2)
|
|
2974
|
+
@db.sqls
|
|
2975
|
+
end
|
|
2976
|
+
|
|
2977
|
+
it "should have working regular association methods" do
|
|
2978
|
+
@Bar.first.foo.should == @foo
|
|
2979
|
+
@Foo.first.bars.should == [@bar]
|
|
2980
|
+
@Foo.first.bar.should == @bar
|
|
2981
|
+
@Foo.first.mtmbars.should == [@bar]
|
|
2982
|
+
@Bar.first.mtmfoos.should == [@foo]
|
|
2983
|
+
end
|
|
2984
|
+
|
|
2985
|
+
it "should have working eager loading methods" do
|
|
2986
|
+
@Bar.eager(:foo).all.map{|o| [o, o.foo]}.should == [[@bar, @foo]]
|
|
2987
|
+
@Foo.eager(:bars).all.map{|o| [o, o.bars]}.should == [[@foo, [@bar]]]
|
|
2988
|
+
@Foo.eager(:bar).all.map{|o| [o, o.bar]}.should == [[@foo, @bar]]
|
|
2989
|
+
@db.fetch = [[{:id=>1, :object_id=>2}], [{:id=>1, :object_id=>2, :x_foreign_key_x=>2}]]
|
|
2990
|
+
@Foo.eager(:mtmbars).all.map{|o| [o, o.mtmbars]}.should == [[@foo, [@bar]]]
|
|
2991
|
+
@db.fetch = [[{:id=>1, :object_id=>2}], [{:id=>1, :object_id=>2, :x_foreign_key_x=>2}]]
|
|
2992
|
+
@Bar.eager(:mtmfoos).all.map{|o| [o, o.mtmfoos]}.should == [[@bar, [@foo]]]
|
|
2993
|
+
end
|
|
2994
|
+
|
|
2995
|
+
it "should have working eager graphing methods" do
|
|
2996
|
+
@db.fetch = {:id=>1, :object_id=>2, :foo_id=>1, :foo_object_id=>2}
|
|
2997
|
+
@Bar.eager_graph(:foo).all.map{|o| [o, o.foo]}.should == [[@bar, @foo]]
|
|
2998
|
+
@db.fetch = {:id=>1, :object_id=>2, :bars_id=>1, :bars_object_id=>2}
|
|
2999
|
+
@Foo.eager_graph(:bars).all.map{|o| [o, o.bars]}.should == [[@foo, [@bar]]]
|
|
3000
|
+
@db.fetch = {:id=>1, :object_id=>2, :bar_id=>1, :bar_object_id=>2}
|
|
3001
|
+
@Foo.eager_graph(:bar).all.map{|o| [o, o.bar]}.should == [[@foo, @bar]]
|
|
3002
|
+
@db.fetch = {:id=>1, :object_id=>2, :mtmfoos_id=>1, :mtmfoos_object_id=>2}
|
|
3003
|
+
@Bar.eager_graph(:mtmfoos).all.map{|o| [o, o.mtmfoos]}.should == [[@bar, [@foo]]]
|
|
3004
|
+
@db.fetch = {:id=>1, :object_id=>2, :mtmbars_id=>1, :mtmbars_object_id=>2}
|
|
3005
|
+
@Foo.eager_graph(:mtmbars).all.map{|o| [o, o.mtmbars]}.should == [[@foo, [@bar]]]
|
|
3006
|
+
end
|
|
3007
|
+
|
|
3008
|
+
it "should have working modification methods" do
|
|
3009
|
+
b = @Bar.load(:id=>2, :object_id=>3)
|
|
3010
|
+
f = @Foo.load(:id=>2, :object_id=>3)
|
|
3011
|
+
@db.numrows = 1
|
|
3012
|
+
|
|
3013
|
+
@bar.foo = f
|
|
3014
|
+
@bar.obj_id.should == 3
|
|
3015
|
+
@foo.bar = @bar
|
|
3016
|
+
@bar.obj_id.should == 2
|
|
3017
|
+
|
|
3018
|
+
@foo.add_bar(b)
|
|
3019
|
+
@db.fetch = [[{:id=>1, :object_id=>2}, {:id=>2, :object_id=>2}], [{:id=>1, :object_id=>2}]]
|
|
3020
|
+
@foo.bars.should == [@bar, b]
|
|
3021
|
+
@foo.remove_bar(b)
|
|
3022
|
+
@foo.bars.should == [@bar]
|
|
3023
|
+
@foo.remove_all_bars
|
|
3024
|
+
@foo.bars.should == []
|
|
3025
|
+
|
|
3026
|
+
@db.fetch = [[{:id=>1, :object_id=>2}], [], [{:id=>2, :object_id=>2}]]
|
|
3027
|
+
@bar = @Bar.load(:id=>1, :object_id=>2)
|
|
3028
|
+
@foo.mtmbars.should == [@bar]
|
|
3029
|
+
@foo.remove_all_mtmbars
|
|
3030
|
+
@foo.mtmbars.should == []
|
|
3031
|
+
@foo.add_mtmbar(b)
|
|
3032
|
+
@foo.mtmbars.should == [b]
|
|
3033
|
+
@foo.remove_mtmbar(b)
|
|
3034
|
+
@foo.mtmbars.should == []
|
|
3035
|
+
|
|
3036
|
+
@db.fetch = [[{:id=>2, :object_id=>3}], [], [{:id=>2, :object_id=>3}]]
|
|
3037
|
+
@bar.add_mtmfoo(f)
|
|
3038
|
+
@bar.mtmfoos.should == [f]
|
|
3039
|
+
@bar.remove_all_mtmfoos
|
|
3040
|
+
@bar.mtmfoos.should == []
|
|
3041
|
+
@bar.add_mtmfoo(f)
|
|
3042
|
+
@bar.mtmfoos.should == [f]
|
|
3043
|
+
@bar.remove_mtmfoo(f)
|
|
3044
|
+
@bar.mtmfoos.should == []
|
|
3045
|
+
end
|
|
3046
|
+
end
|
|
3047
|
+
|
|
3048
|
+
describe "Model#pk_or_nil" do
|
|
3049
|
+
before do
|
|
3050
|
+
@m = Class.new(Sequel::Model)
|
|
3051
|
+
@m.columns :id, :x, :y
|
|
3052
|
+
end
|
|
2674
3053
|
|
|
2675
|
-
it "
|
|
2676
|
-
@
|
|
3054
|
+
it "should be default return the value of the :id column" do
|
|
3055
|
+
m = @m.load(:id => 111, :x => 2, :y => 3)
|
|
3056
|
+
m.pk_or_nil.should == 111
|
|
3057
|
+
end
|
|
3058
|
+
|
|
3059
|
+
it "should be return the primary key value for custom primary key" do
|
|
3060
|
+
@m.set_primary_key :x
|
|
3061
|
+
m = @m.load(:id => 111, :x => 2, :y => 3)
|
|
3062
|
+
m.pk_or_nil.should == 2
|
|
3063
|
+
end
|
|
2677
3064
|
|
|
2678
|
-
|
|
2679
|
-
@
|
|
2680
|
-
@
|
|
2681
|
-
|
|
3065
|
+
it "should be return the primary key value for composite primary key" do
|
|
3066
|
+
@m.set_primary_key [:y, :x]
|
|
3067
|
+
m = @m.load(:id => 111, :x => 2, :y => 3)
|
|
3068
|
+
m.pk_or_nil.should == [3, 2]
|
|
3069
|
+
end
|
|
3070
|
+
|
|
3071
|
+
it "should raise if no primary key" do
|
|
3072
|
+
@m.set_primary_key nil
|
|
3073
|
+
m = @m.new(:id => 111, :x => 2, :y => 3)
|
|
3074
|
+
m.pk_or_nil.should be_nil
|
|
3075
|
+
|
|
3076
|
+
@m.no_primary_key
|
|
3077
|
+
m = @m.new(:id => 111, :x => 2, :y => 3)
|
|
3078
|
+
m.pk_or_nil.should be_nil
|
|
3079
|
+
end
|
|
3080
|
+
end
|
|
2682
3081
|
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
@
|
|
2686
|
-
|
|
2687
|
-
|
|
3082
|
+
describe Sequel::Model, "#refresh" do
|
|
3083
|
+
before do
|
|
3084
|
+
@c = Class.new(Sequel::Model(:items)) do
|
|
3085
|
+
unrestrict_primary_key
|
|
3086
|
+
columns :id, :x
|
|
3087
|
+
end
|
|
3088
|
+
MODEL_DB.reset
|
|
2688
3089
|
end
|
|
2689
3090
|
|
|
2690
|
-
|
|
2691
|
-
@
|
|
3091
|
+
specify "should remove cached associations" do
|
|
3092
|
+
@c.many_to_one :node, :class=>@c
|
|
3093
|
+
@m = @c.new(:id => 555)
|
|
3094
|
+
@m.associations[:node] = 15
|
|
3095
|
+
@m.reload
|
|
3096
|
+
@m.associations.should == {}
|
|
2692
3097
|
end
|
|
3098
|
+
end
|
|
2693
3099
|
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
3100
|
+
describe "Model#freeze" do
|
|
3101
|
+
before do
|
|
3102
|
+
class ::Album < Sequel::Model
|
|
3103
|
+
columns :id
|
|
3104
|
+
class B < Sequel::Model
|
|
3105
|
+
columns :id, :album_id
|
|
3106
|
+
many_to_one :album, :class=>Album
|
|
3107
|
+
end
|
|
3108
|
+
one_to_one :b, :key=>:album_id, :class=>B
|
|
3109
|
+
end
|
|
3110
|
+
@o = Album.load(:id=>1).freeze
|
|
3111
|
+
MODEL_DB.sqls
|
|
3112
|
+
end
|
|
3113
|
+
after do
|
|
3114
|
+
Object.send(:remove_const, :Album)
|
|
3115
|
+
end
|
|
2700
3116
|
|
|
2701
|
-
|
|
2702
|
-
@
|
|
2703
|
-
@c1.association_reflection(:children)[:name].should == :children
|
|
2704
|
-
@c1.association_reflection(:children)[:type].should == :one_to_many
|
|
2705
|
-
@c1.association_reflection(:children)[:class].should == @c1
|
|
3117
|
+
it "should freeze the object's associations" do
|
|
3118
|
+
@o.associations.frozen?.should be_true
|
|
2706
3119
|
end
|
|
2707
3120
|
|
|
2708
|
-
it "
|
|
2709
|
-
|
|
2710
|
-
@
|
|
2711
|
-
@
|
|
2712
|
-
@c1.associate :one_to_many, :children, :class => @c1
|
|
2713
|
-
@c1.associations.sort_by{|x|x.to_s}.should == [:children, :parent]
|
|
3121
|
+
it "should not break associations getters" do
|
|
3122
|
+
Album::B.dataset._fetch = {:album_id=>1, :id=>2}
|
|
3123
|
+
@o.b.should == Album::B.load(:id=>2, :album_id=>1)
|
|
3124
|
+
@o.associations[:b].should be_nil
|
|
2714
3125
|
end
|
|
2715
3126
|
|
|
2716
|
-
it "
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
@
|
|
2720
|
-
c.associations.should == [:parent]
|
|
2721
|
-
c.associate :many_to_one, :parent2, :class => @c1
|
|
2722
|
-
@c1.associations.should == [:parent]
|
|
2723
|
-
c.associations.sort_by{|x| x.to_s}.should == [:parent, :parent2]
|
|
2724
|
-
c.instance_methods.map{|x| x.to_s}.should include('parent')
|
|
3127
|
+
it "should not break reciprocal associations" do
|
|
3128
|
+
b = Album::B.load(:id=>2, :album_id=>nil)
|
|
3129
|
+
b.album = @o
|
|
3130
|
+
@o.associations[:b].should be_nil
|
|
2725
3131
|
end
|
|
2726
3132
|
end
|