sequel 4.36.0 → 5.61.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.
- checksums.yaml +5 -5
- data/CHANGELOG +548 -5749
- data/MIT-LICENSE +1 -1
- data/README.rdoc +265 -159
- data/bin/sequel +34 -12
- data/doc/advanced_associations.rdoc +228 -187
- data/doc/association_basics.rdoc +281 -291
- data/doc/bin_sequel.rdoc +5 -3
- data/doc/cheat_sheet.rdoc +86 -51
- data/doc/code_order.rdoc +25 -19
- data/doc/core_extensions.rdoc +104 -63
- data/doc/dataset_basics.rdoc +12 -21
- data/doc/dataset_filtering.rdoc +99 -86
- data/doc/extensions.rdoc +3 -10
- data/doc/fork_safety.rdoc +84 -0
- data/doc/mass_assignment.rdoc +74 -31
- data/doc/migration.rdoc +59 -51
- data/doc/model_dataset_method_design.rdoc +129 -0
- data/doc/model_hooks.rdoc +15 -25
- data/doc/model_plugins.rdoc +12 -12
- data/doc/mssql_stored_procedures.rdoc +3 -3
- data/doc/object_model.rdoc +58 -68
- data/doc/opening_databases.rdoc +85 -95
- data/doc/postgresql.rdoc +263 -38
- data/doc/prepared_statements.rdoc +29 -24
- data/doc/querying.rdoc +189 -167
- data/doc/reflection.rdoc +5 -6
- data/doc/release_notes/5.0.0.txt +159 -0
- data/doc/release_notes/5.1.0.txt +31 -0
- data/doc/release_notes/5.10.0.txt +84 -0
- data/doc/release_notes/5.11.0.txt +83 -0
- data/doc/release_notes/5.12.0.txt +141 -0
- data/doc/release_notes/5.13.0.txt +27 -0
- data/doc/release_notes/5.14.0.txt +63 -0
- data/doc/release_notes/5.15.0.txt +39 -0
- data/doc/release_notes/5.16.0.txt +110 -0
- data/doc/release_notes/5.17.0.txt +31 -0
- data/doc/release_notes/5.18.0.txt +69 -0
- data/doc/release_notes/5.19.0.txt +28 -0
- data/doc/release_notes/5.2.0.txt +33 -0
- data/doc/release_notes/5.20.0.txt +89 -0
- data/doc/release_notes/5.21.0.txt +87 -0
- data/doc/release_notes/5.22.0.txt +48 -0
- data/doc/release_notes/5.23.0.txt +56 -0
- data/doc/release_notes/5.24.0.txt +56 -0
- data/doc/release_notes/5.25.0.txt +32 -0
- data/doc/release_notes/5.26.0.txt +35 -0
- data/doc/release_notes/5.27.0.txt +21 -0
- data/doc/release_notes/5.28.0.txt +16 -0
- data/doc/release_notes/5.29.0.txt +22 -0
- data/doc/release_notes/5.3.0.txt +121 -0
- data/doc/release_notes/5.30.0.txt +20 -0
- data/doc/release_notes/5.31.0.txt +148 -0
- data/doc/release_notes/5.32.0.txt +46 -0
- data/doc/release_notes/5.33.0.txt +24 -0
- data/doc/release_notes/5.34.0.txt +40 -0
- data/doc/release_notes/5.35.0.txt +56 -0
- data/doc/release_notes/5.36.0.txt +60 -0
- data/doc/release_notes/5.37.0.txt +30 -0
- data/doc/release_notes/5.38.0.txt +28 -0
- data/doc/release_notes/5.39.0.txt +19 -0
- data/doc/release_notes/5.4.0.txt +80 -0
- data/doc/release_notes/5.40.0.txt +40 -0
- data/doc/release_notes/5.41.0.txt +25 -0
- data/doc/release_notes/5.42.0.txt +136 -0
- data/doc/release_notes/5.43.0.txt +98 -0
- data/doc/release_notes/5.44.0.txt +32 -0
- data/doc/release_notes/5.45.0.txt +34 -0
- data/doc/release_notes/5.46.0.txt +87 -0
- data/doc/release_notes/5.47.0.txt +59 -0
- data/doc/release_notes/5.48.0.txt +14 -0
- data/doc/release_notes/5.49.0.txt +59 -0
- data/doc/release_notes/5.5.0.txt +61 -0
- data/doc/release_notes/5.50.0.txt +78 -0
- data/doc/release_notes/5.51.0.txt +47 -0
- data/doc/release_notes/5.52.0.txt +87 -0
- data/doc/release_notes/5.53.0.txt +23 -0
- data/doc/release_notes/5.54.0.txt +27 -0
- data/doc/release_notes/5.55.0.txt +21 -0
- data/doc/release_notes/5.56.0.txt +51 -0
- data/doc/release_notes/5.57.0.txt +23 -0
- data/doc/release_notes/5.58.0.txt +31 -0
- data/doc/release_notes/5.59.0.txt +73 -0
- data/doc/release_notes/5.6.0.txt +31 -0
- data/doc/release_notes/5.60.0.txt +22 -0
- data/doc/release_notes/5.61.0.txt +43 -0
- data/doc/release_notes/5.7.0.txt +108 -0
- data/doc/release_notes/5.8.0.txt +170 -0
- data/doc/release_notes/5.9.0.txt +99 -0
- data/doc/schema_modification.rdoc +95 -75
- data/doc/security.rdoc +109 -80
- data/doc/sharding.rdoc +74 -47
- data/doc/sql.rdoc +147 -122
- data/doc/testing.rdoc +43 -20
- data/doc/thread_safety.rdoc +2 -4
- data/doc/transactions.rdoc +97 -18
- data/doc/validations.rdoc +52 -50
- data/doc/virtual_rows.rdoc +90 -109
- data/lib/sequel/adapters/ado/access.rb +15 -17
- data/lib/sequel/adapters/ado/mssql.rb +6 -15
- data/lib/sequel/adapters/ado.rb +150 -20
- data/lib/sequel/adapters/amalgalite.rb +11 -23
- data/lib/sequel/adapters/ibmdb.rb +47 -55
- data/lib/sequel/adapters/jdbc/db2.rb +29 -39
- data/lib/sequel/adapters/jdbc/derby.rb +58 -54
- data/lib/sequel/adapters/jdbc/h2.rb +93 -35
- data/lib/sequel/adapters/jdbc/hsqldb.rb +24 -31
- data/lib/sequel/adapters/jdbc/jtds.rb +2 -10
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -11
- data/lib/sequel/adapters/jdbc/mysql.rb +17 -20
- data/lib/sequel/adapters/jdbc/oracle.rb +22 -18
- data/lib/sequel/adapters/jdbc/postgresql.rb +69 -71
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +11 -23
- data/lib/sequel/adapters/jdbc/sqlite.rb +47 -11
- data/lib/sequel/adapters/jdbc/sqlserver.rb +34 -9
- data/lib/sequel/adapters/jdbc/transactions.rb +22 -38
- data/lib/sequel/adapters/jdbc.rb +145 -130
- data/lib/sequel/adapters/mock.rb +100 -111
- data/lib/sequel/adapters/mysql.rb +114 -122
- data/lib/sequel/adapters/mysql2.rb +147 -63
- data/lib/sequel/adapters/odbc/db2.rb +1 -1
- data/lib/sequel/adapters/odbc/mssql.rb +8 -14
- data/lib/sequel/adapters/odbc/oracle.rb +11 -0
- data/lib/sequel/adapters/odbc.rb +20 -25
- data/lib/sequel/adapters/oracle.rb +50 -56
- data/lib/sequel/adapters/postgres.rb +305 -327
- data/lib/sequel/adapters/postgresql.rb +1 -1
- data/lib/sequel/adapters/shared/access.rb +74 -78
- data/lib/sequel/adapters/shared/db2.rb +118 -71
- data/lib/sequel/adapters/shared/mssql.rb +301 -220
- data/lib/sequel/adapters/shared/mysql.rb +299 -217
- data/lib/sequel/adapters/shared/oracle.rb +226 -65
- data/lib/sequel/adapters/shared/postgres.rb +935 -395
- data/lib/sequel/adapters/shared/sqlanywhere.rb +105 -126
- data/lib/sequel/adapters/shared/sqlite.rb +447 -173
- data/lib/sequel/adapters/sqlanywhere.rb +48 -35
- data/lib/sequel/adapters/sqlite.rb +156 -111
- data/lib/sequel/adapters/tinytds.rb +30 -38
- data/lib/sequel/adapters/utils/columns_limit_1.rb +22 -0
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +3 -6
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +2 -2
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +87 -0
- data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +56 -0
- data/lib/sequel/adapters/utils/replace.rb +1 -4
- data/lib/sequel/adapters/utils/stored_procedures.rb +7 -22
- data/lib/sequel/adapters/utils/unmodified_identifiers.rb +28 -0
- data/lib/sequel/ast_transformer.rb +17 -89
- data/lib/sequel/connection_pool/sharded_single.rb +18 -15
- data/lib/sequel/connection_pool/sharded_threaded.rb +130 -111
- data/lib/sequel/connection_pool/single.rb +18 -13
- data/lib/sequel/connection_pool/threaded.rb +121 -120
- data/lib/sequel/connection_pool.rb +48 -29
- data/lib/sequel/core.rb +351 -301
- data/lib/sequel/database/connecting.rb +69 -57
- data/lib/sequel/database/dataset.rb +13 -5
- data/lib/sequel/database/dataset_defaults.rb +18 -102
- data/lib/sequel/database/features.rb +18 -4
- data/lib/sequel/database/logging.rb +12 -11
- data/lib/sequel/database/misc.rb +180 -122
- data/lib/sequel/database/query.rb +47 -27
- data/lib/sequel/database/schema_generator.rb +178 -84
- data/lib/sequel/database/schema_methods.rb +172 -97
- data/lib/sequel/database/transactions.rb +205 -44
- data/lib/sequel/database.rb +17 -2
- data/lib/sequel/dataset/actions.rb +339 -155
- data/lib/sequel/dataset/dataset_module.rb +46 -0
- data/lib/sequel/dataset/features.rb +90 -35
- data/lib/sequel/dataset/graph.rb +80 -58
- data/lib/sequel/dataset/misc.rb +137 -47
- data/lib/sequel/dataset/placeholder_literalizer.rb +63 -25
- data/lib/sequel/dataset/prepared_statements.rb +188 -85
- data/lib/sequel/dataset/query.rb +530 -222
- data/lib/sequel/dataset/sql.rb +590 -368
- data/lib/sequel/dataset.rb +26 -16
- data/lib/sequel/deprecated.rb +12 -2
- data/lib/sequel/exceptions.rb +46 -16
- data/lib/sequel/extensions/_model_constraint_validations.rb +16 -0
- data/lib/sequel/extensions/_model_pg_row.rb +43 -0
- data/lib/sequel/extensions/_pretty_table.rb +2 -5
- data/lib/sequel/extensions/any_not_empty.rb +45 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +10 -10
- data/lib/sequel/extensions/async_thread_pool.rb +438 -0
- data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
- data/lib/sequel/extensions/blank.rb +8 -0
- data/lib/sequel/extensions/caller_logging.rb +79 -0
- data/lib/sequel/extensions/columns_introspection.rb +4 -3
- data/lib/sequel/extensions/connection_expiration.rb +20 -10
- data/lib/sequel/extensions/connection_validator.rb +11 -10
- data/lib/sequel/extensions/constant_sql_override.rb +65 -0
- data/lib/sequel/extensions/constraint_validations.rb +62 -39
- data/lib/sequel/extensions/core_extensions.rb +42 -48
- data/lib/sequel/extensions/core_refinements.rb +80 -59
- data/lib/sequel/extensions/current_datetime_timestamp.rb +1 -4
- data/lib/sequel/extensions/date_arithmetic.rb +98 -39
- data/lib/sequel/extensions/date_parse_input_handler.rb +67 -0
- data/lib/sequel/extensions/datetime_parse_to_time.rb +41 -0
- data/lib/sequel/extensions/duplicate_columns_handler.rb +21 -14
- data/lib/sequel/extensions/empty_array_consider_nulls.rb +2 -2
- data/lib/sequel/extensions/escaped_like.rb +100 -0
- data/lib/sequel/extensions/eval_inspect.rb +12 -15
- data/lib/sequel/extensions/exclude_or_null.rb +68 -0
- data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
- data/lib/sequel/extensions/freeze_datasets.rb +3 -0
- data/lib/sequel/extensions/from_block.rb +1 -34
- data/lib/sequel/extensions/graph_each.rb +4 -4
- data/lib/sequel/extensions/identifier_mangling.rb +180 -0
- data/lib/sequel/extensions/implicit_subquery.rb +48 -0
- data/lib/sequel/extensions/index_caching.rb +109 -0
- data/lib/sequel/extensions/inflector.rb +13 -5
- data/lib/sequel/extensions/integer64.rb +32 -0
- data/lib/sequel/extensions/is_distinct_from.rb +141 -0
- data/lib/sequel/extensions/looser_typecasting.rb +17 -8
- data/lib/sequel/extensions/migration.rb +119 -78
- data/lib/sequel/extensions/named_timezones.rb +88 -23
- data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -82
- data/lib/sequel/extensions/null_dataset.rb +8 -8
- data/lib/sequel/extensions/pagination.rb +32 -29
- data/lib/sequel/extensions/pg_array.rb +221 -287
- data/lib/sequel/extensions/pg_array_ops.rb +17 -9
- data/lib/sequel/extensions/pg_enum.rb +63 -23
- data/lib/sequel/extensions/pg_extended_date_support.rb +241 -0
- data/lib/sequel/extensions/pg_hstore.rb +45 -54
- data/lib/sequel/extensions/pg_hstore_ops.rb +58 -6
- data/lib/sequel/extensions/pg_inet.rb +31 -12
- data/lib/sequel/extensions/pg_inet_ops.rb +2 -2
- data/lib/sequel/extensions/pg_interval.rb +56 -29
- data/lib/sequel/extensions/pg_json.rb +417 -140
- data/lib/sequel/extensions/pg_json_ops.rb +270 -18
- data/lib/sequel/extensions/pg_loose_count.rb +4 -2
- data/lib/sequel/extensions/pg_multirange.rb +372 -0
- data/lib/sequel/extensions/pg_range.rb +131 -191
- data/lib/sequel/extensions/pg_range_ops.rb +42 -13
- data/lib/sequel/extensions/pg_row.rb +48 -81
- data/lib/sequel/extensions/pg_row_ops.rb +33 -14
- data/lib/sequel/extensions/pg_static_cache_updater.rb +2 -2
- data/lib/sequel/extensions/pg_timestamptz.rb +28 -0
- data/lib/sequel/extensions/query.rb +9 -7
- data/lib/sequel/extensions/round_timestamps.rb +0 -6
- data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
- data/lib/sequel/extensions/s.rb +60 -0
- data/lib/sequel/extensions/schema_caching.rb +10 -1
- data/lib/sequel/extensions/schema_dumper.rb +71 -48
- data/lib/sequel/extensions/select_remove.rb +4 -4
- data/lib/sequel/extensions/sequel_4_dataset_methods.rb +85 -0
- data/lib/sequel/extensions/server_block.rb +51 -27
- data/lib/sequel/extensions/split_array_nil.rb +4 -4
- data/lib/sequel/extensions/sql_comments.rb +119 -7
- data/lib/sequel/extensions/sql_expr.rb +2 -1
- data/lib/sequel/extensions/sql_log_normalizer.rb +108 -0
- data/lib/sequel/extensions/sqlite_json_ops.rb +255 -0
- data/lib/sequel/extensions/string_agg.rb +11 -8
- data/lib/sequel/extensions/string_date_time.rb +19 -23
- data/lib/sequel/extensions/symbol_aref.rb +55 -0
- data/lib/sequel/extensions/symbol_aref_refinement.rb +43 -0
- data/lib/sequel/extensions/symbol_as.rb +23 -0
- data/lib/sequel/extensions/symbol_as_refinement.rb +37 -0
- data/lib/sequel/extensions/synchronize_sql.rb +45 -0
- data/lib/sequel/extensions/to_dot.rb +10 -4
- data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
- data/lib/sequel/model/associations.rb +1006 -284
- data/lib/sequel/model/base.rb +560 -805
- data/lib/sequel/model/dataset_module.rb +11 -10
- data/lib/sequel/model/default_inflections.rb +1 -1
- data/lib/sequel/model/errors.rb +10 -3
- data/lib/sequel/model/exceptions.rb +8 -10
- data/lib/sequel/model/inflections.rb +7 -20
- data/lib/sequel/model/plugins.rb +114 -0
- data/lib/sequel/model.rb +32 -82
- data/lib/sequel/plugins/active_model.rb +30 -14
- data/lib/sequel/plugins/after_initialize.rb +1 -1
- data/lib/sequel/plugins/association_dependencies.rb +25 -18
- data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
- data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
- data/lib/sequel/plugins/association_pks.rb +147 -70
- data/lib/sequel/plugins/association_proxies.rb +33 -9
- data/lib/sequel/plugins/async_thread_pool.rb +39 -0
- data/lib/sequel/plugins/auto_restrict_eager_graph.rb +62 -0
- data/lib/sequel/plugins/auto_validations.rb +95 -28
- data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
- data/lib/sequel/plugins/before_after_save.rb +0 -42
- data/lib/sequel/plugins/blacklist_security.rb +21 -12
- data/lib/sequel/plugins/boolean_readers.rb +5 -5
- data/lib/sequel/plugins/boolean_subsets.rb +13 -8
- data/lib/sequel/plugins/caching.rb +25 -16
- data/lib/sequel/plugins/class_table_inheritance.rb +179 -100
- data/lib/sequel/plugins/column_conflicts.rb +16 -3
- data/lib/sequel/plugins/column_encryption.rb +728 -0
- data/lib/sequel/plugins/column_select.rb +7 -5
- data/lib/sequel/plugins/columns_updated.rb +42 -0
- data/lib/sequel/plugins/composition.rb +42 -26
- data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
- data/lib/sequel/plugins/constraint_validations.rb +20 -14
- data/lib/sequel/plugins/csv_serializer.rb +56 -35
- data/lib/sequel/plugins/dataset_associations.rb +40 -17
- data/lib/sequel/plugins/def_dataset_method.rb +90 -0
- data/lib/sequel/plugins/defaults_setter.rb +65 -10
- data/lib/sequel/plugins/delay_add_association.rb +1 -1
- data/lib/sequel/plugins/dirty.rb +62 -24
- data/lib/sequel/plugins/eager_each.rb +3 -3
- data/lib/sequel/plugins/eager_graph_eager.rb +139 -0
- data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
- data/lib/sequel/plugins/enum.rb +124 -0
- data/lib/sequel/plugins/error_splitter.rb +17 -12
- data/lib/sequel/plugins/finder.rb +246 -0
- data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
- data/lib/sequel/plugins/force_encoding.rb +7 -12
- data/lib/sequel/plugins/hook_class_methods.rb +37 -54
- data/lib/sequel/plugins/input_transformer.rb +18 -10
- data/lib/sequel/plugins/insert_conflict.rb +76 -0
- data/lib/sequel/plugins/insert_returning_select.rb +2 -2
- data/lib/sequel/plugins/instance_filters.rb +10 -8
- data/lib/sequel/plugins/instance_hooks.rb +34 -17
- data/lib/sequel/plugins/instance_specific_default.rb +113 -0
- data/lib/sequel/plugins/inverted_subsets.rb +22 -13
- data/lib/sequel/plugins/json_serializer.rb +124 -64
- data/lib/sequel/plugins/lazy_attributes.rb +21 -14
- data/lib/sequel/plugins/list.rb +35 -21
- data/lib/sequel/plugins/many_through_many.rb +134 -21
- data/lib/sequel/plugins/modification_detection.rb +15 -5
- data/lib/sequel/plugins/mssql_optimistic_locking.rb +6 -5
- data/lib/sequel/plugins/nested_attributes.rb +61 -31
- data/lib/sequel/plugins/optimistic_locking.rb +3 -3
- data/lib/sequel/plugins/pg_array_associations.rb +103 -53
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +350 -0
- data/lib/sequel/plugins/pg_row.rb +5 -51
- data/lib/sequel/plugins/prepared_statements.rb +60 -72
- data/lib/sequel/plugins/prepared_statements_safe.rb +9 -4
- data/lib/sequel/plugins/rcte_tree.rb +68 -82
- data/lib/sequel/plugins/require_valid_schema.rb +67 -0
- data/lib/sequel/plugins/serialization.rb +43 -46
- data/lib/sequel/plugins/serialization_modification_detection.rb +3 -2
- data/lib/sequel/plugins/sharding.rb +15 -10
- data/lib/sequel/plugins/single_table_inheritance.rb +67 -28
- data/lib/sequel/plugins/skip_create_refresh.rb +3 -3
- data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
- data/lib/sequel/plugins/split_values.rb +11 -6
- data/lib/sequel/plugins/sql_comments.rb +189 -0
- data/lib/sequel/plugins/static_cache.rb +77 -53
- data/lib/sequel/plugins/static_cache_cache.rb +53 -0
- data/lib/sequel/plugins/string_stripper.rb +3 -3
- data/lib/sequel/plugins/subclasses.rb +43 -10
- data/lib/sequel/plugins/subset_conditions.rb +15 -5
- data/lib/sequel/plugins/table_select.rb +2 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +96 -12
- data/lib/sequel/plugins/throw_failures.rb +110 -0
- data/lib/sequel/plugins/timestamps.rb +20 -8
- data/lib/sequel/plugins/touch.rb +19 -8
- data/lib/sequel/plugins/tree.rb +62 -32
- data/lib/sequel/plugins/typecast_on_load.rb +12 -4
- data/lib/sequel/plugins/unlimited_update.rb +1 -7
- data/lib/sequel/plugins/unused_associations.rb +521 -0
- data/lib/sequel/plugins/update_or_create.rb +4 -4
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/plugins/update_refresh.rb +26 -15
- data/lib/sequel/plugins/uuid.rb +7 -11
- data/lib/sequel/plugins/validate_associated.rb +18 -0
- data/lib/sequel/plugins/validation_class_methods.rb +38 -19
- data/lib/sequel/plugins/validation_contexts.rb +49 -0
- data/lib/sequel/plugins/validation_helpers.rb +57 -41
- data/lib/sequel/plugins/whitelist_security.rb +122 -0
- data/lib/sequel/plugins/xml_serializer.rb +30 -31
- data/lib/sequel/sql.rb +471 -331
- data/lib/sequel/timezones.rb +78 -47
- data/lib/sequel/version.rb +7 -2
- data/lib/sequel.rb +1 -1
- metadata +217 -521
- data/Rakefile +0 -164
- data/doc/active_record.rdoc +0 -928
- data/doc/release_notes/1.0.txt +0 -38
- data/doc/release_notes/1.1.txt +0 -143
- data/doc/release_notes/1.3.txt +0 -101
- data/doc/release_notes/1.4.0.txt +0 -53
- data/doc/release_notes/1.5.0.txt +0 -155
- data/doc/release_notes/2.0.0.txt +0 -298
- data/doc/release_notes/2.1.0.txt +0 -271
- data/doc/release_notes/2.10.0.txt +0 -328
- data/doc/release_notes/2.11.0.txt +0 -215
- data/doc/release_notes/2.12.0.txt +0 -534
- data/doc/release_notes/2.2.0.txt +0 -253
- data/doc/release_notes/2.3.0.txt +0 -88
- data/doc/release_notes/2.4.0.txt +0 -106
- data/doc/release_notes/2.5.0.txt +0 -137
- data/doc/release_notes/2.6.0.txt +0 -157
- data/doc/release_notes/2.7.0.txt +0 -166
- data/doc/release_notes/2.8.0.txt +0 -171
- data/doc/release_notes/2.9.0.txt +0 -97
- data/doc/release_notes/3.0.0.txt +0 -221
- data/doc/release_notes/3.1.0.txt +0 -406
- data/doc/release_notes/3.10.0.txt +0 -286
- data/doc/release_notes/3.11.0.txt +0 -254
- data/doc/release_notes/3.12.0.txt +0 -304
- data/doc/release_notes/3.13.0.txt +0 -210
- data/doc/release_notes/3.14.0.txt +0 -118
- data/doc/release_notes/3.15.0.txt +0 -78
- data/doc/release_notes/3.16.0.txt +0 -45
- data/doc/release_notes/3.17.0.txt +0 -58
- data/doc/release_notes/3.18.0.txt +0 -120
- data/doc/release_notes/3.19.0.txt +0 -67
- data/doc/release_notes/3.2.0.txt +0 -268
- data/doc/release_notes/3.20.0.txt +0 -41
- data/doc/release_notes/3.21.0.txt +0 -87
- data/doc/release_notes/3.22.0.txt +0 -39
- data/doc/release_notes/3.23.0.txt +0 -172
- data/doc/release_notes/3.24.0.txt +0 -420
- data/doc/release_notes/3.25.0.txt +0 -88
- data/doc/release_notes/3.26.0.txt +0 -88
- data/doc/release_notes/3.27.0.txt +0 -82
- data/doc/release_notes/3.28.0.txt +0 -304
- data/doc/release_notes/3.29.0.txt +0 -459
- data/doc/release_notes/3.3.0.txt +0 -192
- data/doc/release_notes/3.30.0.txt +0 -135
- data/doc/release_notes/3.31.0.txt +0 -146
- data/doc/release_notes/3.32.0.txt +0 -202
- data/doc/release_notes/3.33.0.txt +0 -157
- data/doc/release_notes/3.34.0.txt +0 -671
- data/doc/release_notes/3.35.0.txt +0 -144
- data/doc/release_notes/3.36.0.txt +0 -245
- data/doc/release_notes/3.37.0.txt +0 -338
- data/doc/release_notes/3.38.0.txt +0 -234
- data/doc/release_notes/3.39.0.txt +0 -237
- data/doc/release_notes/3.4.0.txt +0 -325
- data/doc/release_notes/3.40.0.txt +0 -73
- data/doc/release_notes/3.41.0.txt +0 -155
- data/doc/release_notes/3.42.0.txt +0 -74
- data/doc/release_notes/3.43.0.txt +0 -105
- data/doc/release_notes/3.44.0.txt +0 -152
- data/doc/release_notes/3.45.0.txt +0 -179
- data/doc/release_notes/3.46.0.txt +0 -122
- data/doc/release_notes/3.47.0.txt +0 -270
- data/doc/release_notes/3.48.0.txt +0 -477
- data/doc/release_notes/3.5.0.txt +0 -510
- data/doc/release_notes/3.6.0.txt +0 -366
- data/doc/release_notes/3.7.0.txt +0 -179
- data/doc/release_notes/3.8.0.txt +0 -151
- data/doc/release_notes/3.9.0.txt +0 -233
- data/doc/release_notes/4.0.0.txt +0 -262
- data/doc/release_notes/4.1.0.txt +0 -85
- data/doc/release_notes/4.10.0.txt +0 -226
- data/doc/release_notes/4.11.0.txt +0 -147
- data/doc/release_notes/4.12.0.txt +0 -105
- data/doc/release_notes/4.13.0.txt +0 -169
- data/doc/release_notes/4.14.0.txt +0 -68
- data/doc/release_notes/4.15.0.txt +0 -56
- data/doc/release_notes/4.16.0.txt +0 -36
- data/doc/release_notes/4.17.0.txt +0 -38
- data/doc/release_notes/4.18.0.txt +0 -36
- data/doc/release_notes/4.19.0.txt +0 -45
- data/doc/release_notes/4.2.0.txt +0 -129
- data/doc/release_notes/4.20.0.txt +0 -79
- data/doc/release_notes/4.21.0.txt +0 -94
- data/doc/release_notes/4.22.0.txt +0 -72
- data/doc/release_notes/4.23.0.txt +0 -65
- data/doc/release_notes/4.24.0.txt +0 -99
- data/doc/release_notes/4.25.0.txt +0 -181
- data/doc/release_notes/4.26.0.txt +0 -44
- data/doc/release_notes/4.27.0.txt +0 -78
- data/doc/release_notes/4.28.0.txt +0 -57
- data/doc/release_notes/4.29.0.txt +0 -41
- data/doc/release_notes/4.3.0.txt +0 -40
- data/doc/release_notes/4.30.0.txt +0 -37
- data/doc/release_notes/4.31.0.txt +0 -57
- data/doc/release_notes/4.32.0.txt +0 -132
- data/doc/release_notes/4.33.0.txt +0 -88
- data/doc/release_notes/4.34.0.txt +0 -86
- data/doc/release_notes/4.35.0.txt +0 -130
- data/doc/release_notes/4.36.0.txt +0 -116
- data/doc/release_notes/4.4.0.txt +0 -92
- data/doc/release_notes/4.5.0.txt +0 -34
- data/doc/release_notes/4.6.0.txt +0 -30
- data/doc/release_notes/4.7.0.txt +0 -103
- data/doc/release_notes/4.8.0.txt +0 -175
- data/doc/release_notes/4.9.0.txt +0 -190
- data/lib/sequel/adapters/cubrid.rb +0 -144
- data/lib/sequel/adapters/do/mysql.rb +0 -66
- data/lib/sequel/adapters/do/postgres.rb +0 -44
- data/lib/sequel/adapters/do/sqlite3.rb +0 -42
- data/lib/sequel/adapters/do.rb +0 -158
- data/lib/sequel/adapters/jdbc/as400.rb +0 -84
- data/lib/sequel/adapters/jdbc/cubrid.rb +0 -64
- data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -36
- data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -33
- data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -33
- data/lib/sequel/adapters/odbc/progress.rb +0 -10
- data/lib/sequel/adapters/shared/cubrid.rb +0 -245
- data/lib/sequel/adapters/shared/firebird.rb +0 -247
- data/lib/sequel/adapters/shared/informix.rb +0 -54
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +0 -152
- data/lib/sequel/adapters/shared/progress.rb +0 -40
- data/lib/sequel/adapters/swift/mysql.rb +0 -49
- data/lib/sequel/adapters/swift/postgres.rb +0 -47
- data/lib/sequel/adapters/swift/sqlite.rb +0 -49
- data/lib/sequel/adapters/swift.rb +0 -160
- data/lib/sequel/adapters/utils/pg_types.rb +0 -70
- data/lib/sequel/dataset/mutation.rb +0 -111
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -5
- data/lib/sequel/extensions/filter_having.rb +0 -63
- data/lib/sequel/extensions/hash_aliases.rb +0 -49
- data/lib/sequel/extensions/meta_def.rb +0 -35
- data/lib/sequel/extensions/query_literals.rb +0 -84
- data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -24
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -122
- data/lib/sequel/extensions/set_overrides.rb +0 -76
- data/lib/sequel/no_core_ext.rb +0 -3
- data/lib/sequel/plugins/association_autoreloading.rb +0 -9
- data/lib/sequel/plugins/identifier_columns.rb +0 -47
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -9
- data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -81
- data/lib/sequel/plugins/prepared_statements_associations.rb +0 -119
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -61
- data/lib/sequel/plugins/schema.rb +0 -82
- data/lib/sequel/plugins/scissors.rb +0 -35
- data/spec/adapter_spec.rb +0 -4
- data/spec/adapters/db2_spec.rb +0 -160
- data/spec/adapters/firebird_spec.rb +0 -411
- data/spec/adapters/informix_spec.rb +0 -100
- data/spec/adapters/mssql_spec.rb +0 -733
- data/spec/adapters/mysql_spec.rb +0 -1319
- data/spec/adapters/oracle_spec.rb +0 -313
- data/spec/adapters/postgres_spec.rb +0 -3790
- data/spec/adapters/spec_helper.rb +0 -49
- data/spec/adapters/sqlanywhere_spec.rb +0 -170
- data/spec/adapters/sqlite_spec.rb +0 -688
- data/spec/bin_spec.rb +0 -258
- data/spec/core/connection_pool_spec.rb +0 -1045
- data/spec/core/database_spec.rb +0 -2636
- data/spec/core/dataset_spec.rb +0 -5175
- data/spec/core/deprecated_spec.rb +0 -70
- data/spec/core/expression_filters_spec.rb +0 -1247
- data/spec/core/mock_adapter_spec.rb +0 -464
- data/spec/core/object_graph_spec.rb +0 -303
- data/spec/core/placeholder_literalizer_spec.rb +0 -163
- data/spec/core/schema_generator_spec.rb +0 -203
- data/spec/core/schema_spec.rb +0 -1676
- data/spec/core/spec_helper.rb +0 -34
- data/spec/core/version_spec.rb +0 -7
- data/spec/core_extensions_spec.rb +0 -699
- data/spec/core_model_spec.rb +0 -2
- data/spec/core_spec.rb +0 -1
- data/spec/extensions/accessed_columns_spec.rb +0 -51
- data/spec/extensions/active_model_spec.rb +0 -85
- data/spec/extensions/after_initialize_spec.rb +0 -24
- data/spec/extensions/arbitrary_servers_spec.rb +0 -109
- data/spec/extensions/association_dependencies_spec.rb +0 -117
- data/spec/extensions/association_pks_spec.rb +0 -405
- data/spec/extensions/association_proxies_spec.rb +0 -86
- data/spec/extensions/auto_validations_spec.rb +0 -192
- data/spec/extensions/before_after_save_spec.rb +0 -40
- data/spec/extensions/blacklist_security_spec.rb +0 -88
- data/spec/extensions/blank_spec.rb +0 -69
- data/spec/extensions/boolean_readers_spec.rb +0 -93
- data/spec/extensions/boolean_subsets_spec.rb +0 -47
- data/spec/extensions/caching_spec.rb +0 -270
- data/spec/extensions/class_table_inheritance_spec.rb +0 -444
- data/spec/extensions/column_conflicts_spec.rb +0 -60
- data/spec/extensions/column_select_spec.rb +0 -108
- data/spec/extensions/columns_introspection_spec.rb +0 -91
- data/spec/extensions/composition_spec.rb +0 -242
- data/spec/extensions/connection_expiration_spec.rb +0 -121
- data/spec/extensions/connection_validator_spec.rb +0 -127
- data/spec/extensions/constraint_validations_plugin_spec.rb +0 -288
- data/spec/extensions/constraint_validations_spec.rb +0 -389
- data/spec/extensions/core_refinements_spec.rb +0 -519
- data/spec/extensions/csv_serializer_spec.rb +0 -180
- data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
- data/spec/extensions/dataset_associations_spec.rb +0 -343
- data/spec/extensions/dataset_source_alias_spec.rb +0 -51
- data/spec/extensions/date_arithmetic_spec.rb +0 -167
- data/spec/extensions/defaults_setter_spec.rb +0 -102
- data/spec/extensions/delay_add_association_spec.rb +0 -74
- data/spec/extensions/dirty_spec.rb +0 -180
- data/spec/extensions/duplicate_columns_handler_spec.rb +0 -110
- data/spec/extensions/eager_each_spec.rb +0 -66
- data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
- data/spec/extensions/error_splitter_spec.rb +0 -18
- data/spec/extensions/error_sql_spec.rb +0 -20
- data/spec/extensions/eval_inspect_spec.rb +0 -73
- data/spec/extensions/filter_having_spec.rb +0 -40
- data/spec/extensions/force_encoding_spec.rb +0 -114
- data/spec/extensions/from_block_spec.rb +0 -21
- data/spec/extensions/graph_each_spec.rb +0 -119
- data/spec/extensions/hash_aliases_spec.rb +0 -24
- data/spec/extensions/hook_class_methods_spec.rb +0 -429
- data/spec/extensions/identifier_columns_spec.rb +0 -17
- data/spec/extensions/inflector_spec.rb +0 -183
- data/spec/extensions/input_transformer_spec.rb +0 -54
- data/spec/extensions/insert_returning_select_spec.rb +0 -46
- data/spec/extensions/instance_filters_spec.rb +0 -79
- data/spec/extensions/instance_hooks_spec.rb +0 -276
- data/spec/extensions/inverted_subsets_spec.rb +0 -33
- data/spec/extensions/json_serializer_spec.rb +0 -304
- data/spec/extensions/lazy_attributes_spec.rb +0 -170
- data/spec/extensions/list_spec.rb +0 -278
- data/spec/extensions/looser_typecasting_spec.rb +0 -43
- data/spec/extensions/many_through_many_spec.rb +0 -2172
- data/spec/extensions/meta_def_spec.rb +0 -21
- data/spec/extensions/migration_spec.rb +0 -728
- data/spec/extensions/modification_detection_spec.rb +0 -80
- data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -91
- data/spec/extensions/named_timezones_spec.rb +0 -108
- data/spec/extensions/nested_attributes_spec.rb +0 -697
- data/spec/extensions/no_auto_literal_strings_spec.rb +0 -65
- data/spec/extensions/null_dataset_spec.rb +0 -85
- data/spec/extensions/optimistic_locking_spec.rb +0 -128
- data/spec/extensions/pagination_spec.rb +0 -118
- data/spec/extensions/pg_array_associations_spec.rb +0 -736
- data/spec/extensions/pg_array_ops_spec.rb +0 -143
- data/spec/extensions/pg_array_spec.rb +0 -390
- data/spec/extensions/pg_enum_spec.rb +0 -92
- data/spec/extensions/pg_hstore_ops_spec.rb +0 -236
- data/spec/extensions/pg_hstore_spec.rb +0 -206
- data/spec/extensions/pg_inet_ops_spec.rb +0 -101
- data/spec/extensions/pg_inet_spec.rb +0 -52
- data/spec/extensions/pg_interval_spec.rb +0 -76
- data/spec/extensions/pg_json_ops_spec.rb +0 -275
- data/spec/extensions/pg_json_spec.rb +0 -218
- data/spec/extensions/pg_loose_count_spec.rb +0 -17
- data/spec/extensions/pg_range_ops_spec.rb +0 -58
- data/spec/extensions/pg_range_spec.rb +0 -473
- data/spec/extensions/pg_row_ops_spec.rb +0 -60
- data/spec/extensions/pg_row_plugin_spec.rb +0 -62
- data/spec/extensions/pg_row_spec.rb +0 -360
- data/spec/extensions/pg_static_cache_updater_spec.rb +0 -92
- data/spec/extensions/pg_typecast_on_load_spec.rb +0 -63
- data/spec/extensions/prepared_statements_associations_spec.rb +0 -159
- data/spec/extensions/prepared_statements_safe_spec.rb +0 -61
- data/spec/extensions/prepared_statements_spec.rb +0 -103
- data/spec/extensions/prepared_statements_with_pk_spec.rb +0 -31
- data/spec/extensions/pretty_table_spec.rb +0 -92
- data/spec/extensions/query_literals_spec.rb +0 -183
- data/spec/extensions/query_spec.rb +0 -102
- data/spec/extensions/rcte_tree_spec.rb +0 -392
- data/spec/extensions/round_timestamps_spec.rb +0 -43
- data/spec/extensions/schema_caching_spec.rb +0 -41
- data/spec/extensions/schema_dumper_spec.rb +0 -814
- data/spec/extensions/schema_spec.rb +0 -117
- data/spec/extensions/scissors_spec.rb +0 -26
- data/spec/extensions/select_remove_spec.rb +0 -38
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -101
- data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
- data/spec/extensions/serialization_spec.rb +0 -362
- data/spec/extensions/server_block_spec.rb +0 -90
- data/spec/extensions/server_logging_spec.rb +0 -45
- data/spec/extensions/set_overrides_spec.rb +0 -61
- data/spec/extensions/sharding_spec.rb +0 -198
- data/spec/extensions/shared_caching_spec.rb +0 -175
- data/spec/extensions/single_table_inheritance_spec.rb +0 -297
- data/spec/extensions/singular_table_names_spec.rb +0 -22
- data/spec/extensions/skip_create_refresh_spec.rb +0 -17
- data/spec/extensions/spec_helper.rb +0 -71
- data/spec/extensions/split_array_nil_spec.rb +0 -24
- data/spec/extensions/split_values_spec.rb +0 -22
- data/spec/extensions/sql_comments_spec.rb +0 -27
- data/spec/extensions/sql_expr_spec.rb +0 -60
- data/spec/extensions/static_cache_spec.rb +0 -361
- data/spec/extensions/string_agg_spec.rb +0 -85
- data/spec/extensions/string_date_time_spec.rb +0 -95
- data/spec/extensions/string_stripper_spec.rb +0 -68
- data/spec/extensions/subclasses_spec.rb +0 -66
- data/spec/extensions/subset_conditions_spec.rb +0 -38
- data/spec/extensions/table_select_spec.rb +0 -71
- data/spec/extensions/tactical_eager_loading_spec.rb +0 -136
- data/spec/extensions/thread_local_timezones_spec.rb +0 -67
- data/spec/extensions/timestamps_spec.rb +0 -175
- data/spec/extensions/to_dot_spec.rb +0 -154
- data/spec/extensions/touch_spec.rb +0 -203
- data/spec/extensions/tree_spec.rb +0 -274
- data/spec/extensions/typecast_on_load_spec.rb +0 -80
- data/spec/extensions/unlimited_update_spec.rb +0 -20
- data/spec/extensions/update_or_create_spec.rb +0 -87
- data/spec/extensions/update_primary_key_spec.rb +0 -100
- data/spec/extensions/update_refresh_spec.rb +0 -53
- data/spec/extensions/uuid_spec.rb +0 -106
- data/spec/extensions/validate_associated_spec.rb +0 -52
- data/spec/extensions/validation_class_methods_spec.rb +0 -1027
- data/spec/extensions/validation_helpers_spec.rb +0 -554
- data/spec/extensions/xml_serializer_spec.rb +0 -207
- data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
- data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
- data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
- data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
- data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
- data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
- data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
- data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
- data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
- data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
- data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
- data/spec/files/double_migration/001_create_sessions.rb +0 -9
- data/spec/files/double_migration/002_create_nodes.rb +0 -19
- data/spec/files/double_migration/003_3_create_users.rb +0 -4
- data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
- data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
- data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
- data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
- data/spec/files/empty_migration/001_create_sessions.rb +0 -9
- data/spec/files/empty_migration/002_create_nodes.rb +0 -0
- data/spec/files/empty_migration/003_3_create_users.rb +0 -4
- data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
- data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
- data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
- data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
- data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
- data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
- data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
- data/spec/files/reversible_migrations/001_reversible.rb +0 -5
- data/spec/files/reversible_migrations/002_reversible.rb +0 -5
- data/spec/files/reversible_migrations/003_reversible.rb +0 -5
- data/spec/files/reversible_migrations/004_reversible.rb +0 -5
- data/spec/files/reversible_migrations/005_reversible.rb +0 -10
- data/spec/files/reversible_migrations/006_reversible.rb +0 -10
- data/spec/files/reversible_migrations/007_reversible.rb +0 -10
- data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
- data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
- data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
- data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
- data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
- data/spec/guards_helper.rb +0 -55
- data/spec/integration/associations_test.rb +0 -2506
- data/spec/integration/database_test.rb +0 -113
- data/spec/integration/dataset_test.rb +0 -1858
- data/spec/integration/eager_loader_test.rb +0 -687
- data/spec/integration/migrator_test.rb +0 -262
- data/spec/integration/model_test.rb +0 -230
- data/spec/integration/plugin_test.rb +0 -2297
- data/spec/integration/prepared_statement_test.rb +0 -467
- data/spec/integration/schema_test.rb +0 -815
- data/spec/integration/spec_helper.rb +0 -56
- data/spec/integration/timezone_test.rb +0 -86
- data/spec/integration/transaction_test.rb +0 -406
- data/spec/integration/type_test.rb +0 -133
- data/spec/model/association_reflection_spec.rb +0 -565
- data/spec/model/associations_spec.rb +0 -4589
- data/spec/model/base_spec.rb +0 -759
- data/spec/model/class_dataset_methods_spec.rb +0 -150
- data/spec/model/dataset_methods_spec.rb +0 -149
- data/spec/model/eager_loading_spec.rb +0 -2197
- data/spec/model/hooks_spec.rb +0 -604
- data/spec/model/inflector_spec.rb +0 -26
- data/spec/model/model_spec.rb +0 -1097
- data/spec/model/plugins_spec.rb +0 -299
- data/spec/model/record_spec.rb +0 -2162
- data/spec/model/spec_helper.rb +0 -46
- data/spec/model/validations_spec.rb +0 -193
- data/spec/model_no_assoc_spec.rb +0 -1
- data/spec/model_spec.rb +0 -1
- data/spec/plugin_spec.rb +0 -1
- data/spec/sequel_coverage.rb +0 -15
- data/spec/spec_config.rb +0 -10
@@ -1,4589 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
|
-
|
3
|
-
describe Sequel::Model, "associate" do
|
4
|
-
it "should use explicit class if given a class, symbol, or string" do
|
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.must_equal ParParent
|
14
|
-
klass.association_reflection(:"par_parent1s").associated_class.must_equal ParParent
|
15
|
-
klass.association_reflection(:"par_parent2s").associated_class.must_equal ParParent
|
16
|
-
ensure
|
17
|
-
Object.send(:remove_const, :ParParent)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should default to associating to other models in the same scope" do
|
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
|
34
|
-
end
|
35
|
-
|
36
|
-
::AssociationModuleTest::Album.association_reflection(:artist).associated_class.must_equal ::AssociationModuleTest::Artist
|
37
|
-
::AssociationModuleTest::Album.association_reflection(:tags).associated_class.must_equal ::AssociationModuleTest::Tag
|
38
|
-
::AssociationModuleTest::Artist.association_reflection(:albums).associated_class.must_equal ::AssociationModuleTest::Album
|
39
|
-
::AssociationModuleTest::Tag.association_reflection(:albums).associated_class.must_equal ::AssociationModuleTest::Album
|
40
|
-
ensure
|
41
|
-
Object.send(:remove_const, :AssociationModuleTest)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
it "should add a model_object and association_reflection accessors to the dataset, and return it with the current model object" do
|
46
|
-
klass = Class.new(Sequel::Model(:nodes)) do
|
47
|
-
columns :id, :a_id
|
48
|
-
end
|
49
|
-
mod = Module.new do
|
50
|
-
def blah
|
51
|
-
filter{|o| o.__send__(association_reflection[:key]) > model_object.id*2}
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
klass.associate :many_to_one, :a, :class=>klass
|
56
|
-
klass.associate :one_to_many, :bs, :key=>:b_id, :class=>klass, :extend=>mod
|
57
|
-
klass.associate :many_to_many, :cs, :class=>klass
|
58
|
-
|
59
|
-
node = klass.load(:id=>1)
|
60
|
-
node.a_dataset.model_object.must_equal node
|
61
|
-
node.bs_dataset.model_object.must_equal node
|
62
|
-
node.cs_dataset.model_object.must_equal node
|
63
|
-
|
64
|
-
node.a_dataset.association_reflection.must_equal klass.association_reflection(:a)
|
65
|
-
node.bs_dataset.association_reflection.must_equal klass.association_reflection(:bs)
|
66
|
-
node.cs_dataset.association_reflection.must_equal klass.association_reflection(:cs)
|
67
|
-
|
68
|
-
node.bs_dataset.blah.sql.must_equal 'SELECT * FROM nodes WHERE ((nodes.b_id = 1) AND (b_id > 2))'
|
69
|
-
end
|
70
|
-
|
71
|
-
it "should allow extending the dataset with :extend option" do
|
72
|
-
klass = Class.new(Sequel::Model(:nodes)) do
|
73
|
-
columns :id, :a_id
|
74
|
-
end
|
75
|
-
mod = Module.new do
|
76
|
-
def blah
|
77
|
-
1
|
78
|
-
end
|
79
|
-
end
|
80
|
-
mod2 = Module.new do
|
81
|
-
def blar
|
82
|
-
2
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
klass.associate :many_to_one, :a, :class=>klass, :extend=>mod
|
87
|
-
klass.associate :one_to_many, :bs, :class=>klass, :extend=>[mod]
|
88
|
-
klass.associate :many_to_many, :cs, :class=>klass, :extend=>[mod, mod2]
|
89
|
-
|
90
|
-
node = klass.load(:id=>1)
|
91
|
-
node.a_dataset.blah.must_equal 1
|
92
|
-
node.bs_dataset.blah.must_equal 1
|
93
|
-
node.cs_dataset.blah.must_equal 1
|
94
|
-
node.cs_dataset.blar.must_equal 2
|
95
|
-
end
|
96
|
-
|
97
|
-
it "should clone an existing association with the :clone option" do
|
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}
|
105
|
-
|
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
|
-
klass.many_to_one :par3, :clone=>:par
|
110
|
-
|
111
|
-
klass.association_reflection(:par).associated_class.must_equal ParParent
|
112
|
-
klass.association_reflection(:par1s).associated_class.must_equal ParParent
|
113
|
-
klass.association_reflection(:par2s).associated_class.must_equal ParParent
|
114
|
-
|
115
|
-
klass.association_reflection(:par)[:order].must_equal :a
|
116
|
-
klass.association_reflection(:par).select.must_equal :b
|
117
|
-
klass.association_reflection(:par)[:block].call.must_equal 1
|
118
|
-
klass.association_reflection(:par)[:eager_block].call.must_equal 1
|
119
|
-
klass.association_reflection(:par1s)[:limit].must_equal 10
|
120
|
-
klass.association_reflection(:par1s)[:order].must_equal :b
|
121
|
-
klass.association_reflection(:par1s)[:block].must_equal nil
|
122
|
-
klass.association_reflection(:par2s)[:after_load].length.must_equal 1
|
123
|
-
klass.association_reflection(:par2s)[:order].must_equal :c
|
124
|
-
klass.association_reflection(:par2s)[:block].call.must_equal 3
|
125
|
-
|
126
|
-
klass.association_reflection(:par3)[:block].call.must_equal 1
|
127
|
-
klass.association_reflection(:par3)[:eager_block].call.must_equal 1
|
128
|
-
ensure
|
129
|
-
Object.send(:remove_const, :ParParent)
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
it "should raise an error if attempting to clone an association of differing type" do
|
134
|
-
c = Class.new(Sequel::Model(:c))
|
135
|
-
c.many_to_one :c
|
136
|
-
proc{c.one_to_many :cs, :clone=>:c}.must_raise(Sequel::Error)
|
137
|
-
end
|
138
|
-
|
139
|
-
it "should allow overriding the :instance_specific option" do
|
140
|
-
c = Class.new(Sequel::Model(:c))
|
141
|
-
c.many_to_one :c, :instance_specific=>true
|
142
|
-
c.association_reflection(:c)[:instance_specific].must_equal true
|
143
|
-
c.many_to_one :c, :instance_specific=>false do |ds| ds end
|
144
|
-
c.association_reflection(:c)[:instance_specific].must_equal false
|
145
|
-
end
|
146
|
-
|
147
|
-
it "should allow cloning of one_to_many to one_to_one associations and vice-versa" do
|
148
|
-
c = Class.new(Sequel::Model(:c))
|
149
|
-
c.one_to_one :c
|
150
|
-
c.one_to_many :cs, :clone=>:c
|
151
|
-
c.one_to_one :c2, :clone=>:cs
|
152
|
-
end
|
153
|
-
|
154
|
-
it "should allow cloning of many_to_many to one_through_one associations and vice-versa" do
|
155
|
-
c = Class.new(Sequel::Model(:c))
|
156
|
-
c.many_to_many :c
|
157
|
-
c.one_through_one :cs, :clone=>:c
|
158
|
-
c.many_to_many :c2, :clone=>:cs
|
159
|
-
end
|
160
|
-
|
161
|
-
it "should clear associations cache when refreshing object manually" do
|
162
|
-
c = Class.new(Sequel::Model(:c))
|
163
|
-
c.many_to_one :c
|
164
|
-
o = c.new
|
165
|
-
o.associations[:c] = 1
|
166
|
-
o.refresh
|
167
|
-
o.associations.must_equal({})
|
168
|
-
end
|
169
|
-
|
170
|
-
it "should not clear associations cache when refreshing object after save" do
|
171
|
-
c = Class.new(Sequel::Model(:c))
|
172
|
-
c.many_to_one :c
|
173
|
-
o = c.new
|
174
|
-
o.associations[:c] = 1
|
175
|
-
o.save
|
176
|
-
o.associations.must_equal(:c=>1)
|
177
|
-
end
|
178
|
-
|
179
|
-
it "should not clear associations cache when saving with insert_select" do
|
180
|
-
ds = Sequel::Model.db[:c]
|
181
|
-
def ds.supports_insert_select?() true end
|
182
|
-
def ds.insert_select(*) {:id=>1} end
|
183
|
-
c = Class.new(Sequel::Model(ds))
|
184
|
-
c.many_to_one :c
|
185
|
-
o = c.new
|
186
|
-
o.associations[:c] = 1
|
187
|
-
o.save
|
188
|
-
o.associations.must_equal(:c=>1)
|
189
|
-
end
|
190
|
-
|
191
|
-
end
|
192
|
-
|
193
|
-
describe Sequel::Model, "many_to_one" do
|
194
|
-
before do
|
195
|
-
@c2 = Class.new(Sequel::Model(:nodes)) do
|
196
|
-
unrestrict_primary_key
|
197
|
-
columns :id, :parent_id, :par_parent_id, :blah
|
198
|
-
end
|
199
|
-
@dataset = @c2.dataset
|
200
|
-
DB.reset
|
201
|
-
end
|
202
|
-
|
203
|
-
it "should raise an error if associated class does not have a primary key, and :primary_key is not specified" do
|
204
|
-
@c2.no_primary_key
|
205
|
-
@c2.many_to_one :parent, :class => @c2
|
206
|
-
d = @c2.new(:id => 1, :parent_id => 234)
|
207
|
-
proc{d.parent}.must_raise(Sequel::Error)
|
208
|
-
DB.sqls.must_equal []
|
209
|
-
end
|
210
|
-
|
211
|
-
it "should raise an error if associated class does not have a primary key, and :primary_key is not specified, with an association block" do
|
212
|
-
@c2.no_primary_key
|
213
|
-
@c2.many_to_one :parent, :class => @c2 do |ds| ds end
|
214
|
-
d = @c2.new(:id => 1, :parent_id => 234)
|
215
|
-
proc{d.parent}.must_raise(Sequel::Error)
|
216
|
-
DB.sqls.must_equal []
|
217
|
-
end
|
218
|
-
|
219
|
-
it "should use implicit key if omitted" do
|
220
|
-
@c2.many_to_one :parent, :class => @c2
|
221
|
-
|
222
|
-
d = @c2.new(:id => 1, :parent_id => 234)
|
223
|
-
p = d.parent
|
224
|
-
p.class.must_equal @c2
|
225
|
-
p.values.must_equal(:x => 1, :id => 1)
|
226
|
-
|
227
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE id = 234"]
|
228
|
-
end
|
229
|
-
|
230
|
-
it "should allow association with the same name as the key if :key_column is given" do
|
231
|
-
@c2.def_column_alias(:parent_id_id, :parent_id)
|
232
|
-
@c2.many_to_one :parent_id, :key_column=>:parent_id, :class => @c2
|
233
|
-
d = @c2.load(:id => 1, :parent_id => 234)
|
234
|
-
d.parent_id_dataset.sql.must_equal "SELECT * FROM nodes WHERE (nodes.id = 234) LIMIT 1"
|
235
|
-
d.parent_id.must_equal @c2.load(:x => 1, :id => 1)
|
236
|
-
d.parent_id_id.must_equal 234
|
237
|
-
d[:parent_id].must_equal 234
|
238
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE id = 234"]
|
239
|
-
|
240
|
-
d.parent_id_id = 3
|
241
|
-
d.parent_id_id.must_equal 3
|
242
|
-
d[:parent_id].must_equal 3
|
243
|
-
end
|
244
|
-
|
245
|
-
it "should use implicit class if omitted" do
|
246
|
-
begin
|
247
|
-
class ::ParParent < Sequel::Model; end
|
248
|
-
@c2.many_to_one :par_parent
|
249
|
-
@c2.new(:id => 1, :par_parent_id => 234).par_parent.class.must_equal ParParent
|
250
|
-
DB.sqls.must_equal ["SELECT * FROM par_parents WHERE id = 234"]
|
251
|
-
ensure
|
252
|
-
Object.send(:remove_const, :ParParent)
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
it "should use class inside module if given as a string" do
|
257
|
-
begin
|
258
|
-
module ::Par
|
259
|
-
class Parent < Sequel::Model; end
|
260
|
-
end
|
261
|
-
@c2.many_to_one :par_parent, :class=>"Par::Parent"
|
262
|
-
@c2.new(:id => 1, :par_parent_id => 234).par_parent.class.must_equal Par::Parent
|
263
|
-
DB.sqls.must_equal ["SELECT * FROM parents WHERE id = 234"]
|
264
|
-
ensure
|
265
|
-
Object.send(:remove_const, :Par)
|
266
|
-
end
|
267
|
-
end
|
268
|
-
|
269
|
-
it "should use explicit key if given" do
|
270
|
-
@c2.many_to_one :parent, :class => @c2, :key => :blah
|
271
|
-
|
272
|
-
d = @c2.new(:id => 1, :blah => 567)
|
273
|
-
p = d.parent
|
274
|
-
p.class.must_equal @c2
|
275
|
-
p.values.must_equal(:x => 1, :id => 1)
|
276
|
-
|
277
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE id = 567"]
|
278
|
-
end
|
279
|
-
|
280
|
-
it "should respect :qualify => false option" do
|
281
|
-
@c2.many_to_one :parent, :class => @c2, :key => :blah, :qualify=>false
|
282
|
-
@c2.new(:id => 1, :blah => 567).parent
|
283
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE id = 567"]
|
284
|
-
end
|
285
|
-
|
286
|
-
it "should use :primary_key option if given" do
|
287
|
-
@c2.many_to_one :parent, :class => @c2, :key => :blah, :primary_key => :pk
|
288
|
-
@c2.new(:id => 1, :blah => 567).parent
|
289
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE (nodes.pk = 567) LIMIT 1"]
|
290
|
-
end
|
291
|
-
|
292
|
-
it "should support composite keys" do
|
293
|
-
@c2.many_to_one :parent, :class => @c2, :key=>[:id, :parent_id], :primary_key=>[:parent_id, :id]
|
294
|
-
@c2.new(:id => 1, :parent_id => 234).parent
|
295
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE ((nodes.parent_id = 1) AND (nodes.id = 234)) LIMIT 1"]
|
296
|
-
end
|
297
|
-
|
298
|
-
it "should not issue query if not all keys have values" do
|
299
|
-
@c2.many_to_one :parent, :class => @c2, :key=>[:id, :parent_id], :primary_key=>[:parent_id, :id]
|
300
|
-
@c2.new(:id => 1, :parent_id => nil).parent.must_equal nil
|
301
|
-
DB.sqls.must_equal []
|
302
|
-
end
|
303
|
-
|
304
|
-
it "should raise an Error unless same number of composite keys used" do
|
305
|
-
proc{@c2.many_to_one :parent, :class => @c2, :primary_key=>[:parent_id, :id]}.must_raise(Sequel::Error)
|
306
|
-
proc{@c2.many_to_one :parent, :class => @c2, :key=>[:id, :parent_id], :primary_key=>:id}.must_raise(Sequel::Error)
|
307
|
-
proc{@c2.many_to_one :parent, :class => @c2, :key=>:id, :primary_key=>[:parent_id, :id]}.must_raise(Sequel::Error)
|
308
|
-
proc{@c2.many_to_one :parent, :class => @c2, :key=>[:id, :parent_id, :blah], :primary_key=>[:parent_id, :id]}.must_raise(Sequel::Error)
|
309
|
-
end
|
310
|
-
|
311
|
-
it "should use :select option if given" do
|
312
|
-
@c2.many_to_one :parent, :class => @c2, :key => :blah, :select=>[:id, :name]
|
313
|
-
@c2.new(:id => 1, :blah => 567).parent
|
314
|
-
DB.sqls.must_equal ["SELECT id, name FROM nodes WHERE (nodes.id = 567) LIMIT 1"]
|
315
|
-
end
|
316
|
-
|
317
|
-
it "should use :conditions option if given" do
|
318
|
-
@c2.many_to_one :parent, :class => @c2, :key => :blah, :conditions=>{:a=>32}
|
319
|
-
@c2.new(:id => 1, :blah => 567).parent
|
320
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE ((a = 32) AND (nodes.id = 567)) LIMIT 1"]
|
321
|
-
|
322
|
-
@c2.many_to_one :parent, :class => @c2, :key => :blah, :conditions=>:a
|
323
|
-
@c2.new(:id => 1, :blah => 567).parent
|
324
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE (a AND (nodes.id = 567)) LIMIT 1"]
|
325
|
-
end
|
326
|
-
|
327
|
-
it "should support :order, :limit (only for offset), and :dataset options, as well as a block" do
|
328
|
-
@c2.many_to_one :child_20, :class => @c2, :key=>:id, :dataset=>proc{model.filter(:parent_id=>pk)}, :limit=>[10,20], :order=>:name do |ds|
|
329
|
-
ds.filter{x > 1}
|
330
|
-
end
|
331
|
-
@c2.load(:id => 100).child_20
|
332
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE ((parent_id = 100) AND (x > 1)) ORDER BY name LIMIT 1 OFFSET 20"]
|
333
|
-
end
|
334
|
-
|
335
|
-
it "should return nil if key value is nil" do
|
336
|
-
@c2.many_to_one :parent, :class => @c2
|
337
|
-
@c2.new(:id => 1).parent.must_equal nil
|
338
|
-
DB.sqls.must_equal []
|
339
|
-
end
|
340
|
-
|
341
|
-
it "should cache negative lookup" do
|
342
|
-
@c2.many_to_one :parent, :class => @c2
|
343
|
-
@c2.dataset._fetch = []
|
344
|
-
d = @c2.new(:id => 1, :parent_id=>555)
|
345
|
-
DB.sqls.must_equal []
|
346
|
-
d.parent.must_equal nil
|
347
|
-
DB.sqls.must_equal ['SELECT * FROM nodes WHERE id = 555']
|
348
|
-
d.parent.must_equal nil
|
349
|
-
DB.sqls.must_equal []
|
350
|
-
end
|
351
|
-
|
352
|
-
it "should define a setter method" do
|
353
|
-
@c2.many_to_one :parent, :class => @c2
|
354
|
-
|
355
|
-
d = @c2.new(:id => 1)
|
356
|
-
d.parent = @c2.new(:id => 4321)
|
357
|
-
d.values.must_equal(:id => 1, :parent_id => 4321)
|
358
|
-
|
359
|
-
d.parent = nil
|
360
|
-
d.values.must_equal(:id => 1, :parent_id => nil)
|
361
|
-
|
362
|
-
e = @c2.new(:id => 6677)
|
363
|
-
d.parent = e
|
364
|
-
d.values.must_equal(:id => 1, :parent_id => 6677)
|
365
|
-
end
|
366
|
-
|
367
|
-
it "should have the setter method respect the :primary_key option" do
|
368
|
-
@c2.many_to_one :parent, :class => @c2, :primary_key=>:blah
|
369
|
-
|
370
|
-
d = @c2.new(:id => 1)
|
371
|
-
d.parent = @c2.new(:id => 4321, :blah=>444)
|
372
|
-
d.values.must_equal(:id => 1, :parent_id => 444)
|
373
|
-
|
374
|
-
d.parent = nil
|
375
|
-
d.values.must_equal(:id => 1, :parent_id => nil)
|
376
|
-
|
377
|
-
e = @c2.new(:id => 6677, :blah=>8)
|
378
|
-
d.parent = e
|
379
|
-
d.values.must_equal(:id => 1, :parent_id => 8)
|
380
|
-
end
|
381
|
-
|
382
|
-
it "should have the setter method respect composite keys" do
|
383
|
-
@c2.many_to_one :parent, :class => @c2, :key=>[:id, :parent_id], :primary_key=>[:parent_id, :id]
|
384
|
-
|
385
|
-
d = @c2.new(:id => 1, :parent_id=> 234)
|
386
|
-
d.parent = @c2.new(:id => 4, :parent_id=>52)
|
387
|
-
d.values.must_equal(:id => 52, :parent_id => 4)
|
388
|
-
|
389
|
-
d.parent = nil
|
390
|
-
d.values.must_equal(:id => nil, :parent_id => nil)
|
391
|
-
|
392
|
-
e = @c2.new(:id => 6677, :parent_id=>8)
|
393
|
-
d.parent = e
|
394
|
-
d.values.must_equal(:id => 8, :parent_id => 6677)
|
395
|
-
end
|
396
|
-
|
397
|
-
it "should not persist changes until saved" do
|
398
|
-
@c2.many_to_one :parent, :class => @c2
|
399
|
-
|
400
|
-
d = @c2.load(:id => 1)
|
401
|
-
DB.reset
|
402
|
-
d.parent = @c2.new(:id => 345)
|
403
|
-
DB.sqls.must_equal []
|
404
|
-
d.save_changes
|
405
|
-
DB.sqls.must_equal ['UPDATE nodes SET parent_id = 345 WHERE (id = 1)']
|
406
|
-
end
|
407
|
-
|
408
|
-
it "should populate cache when accessed" do
|
409
|
-
@c2.many_to_one :parent, :class => @c2
|
410
|
-
|
411
|
-
d = @c2.load(:id => 1)
|
412
|
-
d.parent_id = 234
|
413
|
-
d.associations[:parent].must_equal nil
|
414
|
-
@c2.dataset._fetch = {:id=>234}
|
415
|
-
e = d.parent
|
416
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE id = 234"]
|
417
|
-
d.associations[:parent].must_equal e
|
418
|
-
end
|
419
|
-
|
420
|
-
it "should populate cache when assigned" do
|
421
|
-
@c2.many_to_one :parent, :class => @c2
|
422
|
-
|
423
|
-
d = @c2.create(:id => 1)
|
424
|
-
DB.reset
|
425
|
-
d.associations[:parent].must_equal nil
|
426
|
-
d.parent = @c2.new(:id => 234)
|
427
|
-
e = d.parent
|
428
|
-
d.associations[:parent].must_equal e
|
429
|
-
DB.sqls.must_equal []
|
430
|
-
end
|
431
|
-
|
432
|
-
it "should use cache if available" do
|
433
|
-
@c2.many_to_one :parent, :class => @c2
|
434
|
-
|
435
|
-
d = @c2.create(:id => 1, :parent_id => 234)
|
436
|
-
DB.reset
|
437
|
-
d.associations[:parent] = 42
|
438
|
-
d.parent.must_equal 42
|
439
|
-
DB.sqls.must_equal []
|
440
|
-
end
|
441
|
-
|
442
|
-
it "should not use cache if asked to reload" do
|
443
|
-
@c2.many_to_one :parent, :class => @c2
|
444
|
-
|
445
|
-
d = @c2.create(:id => 1)
|
446
|
-
DB.reset
|
447
|
-
d.parent_id = 234
|
448
|
-
d.associations[:parent] = 42
|
449
|
-
d.parent(true).wont_equal 42
|
450
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE id = 234"]
|
451
|
-
d.parent(:reload=>true).wont_equal 42
|
452
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE id = 234"]
|
453
|
-
d.parent(Object.new).wont_equal 42
|
454
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE id = 234"]
|
455
|
-
end
|
456
|
-
|
457
|
-
it "should use a callback if given one as the argument" do
|
458
|
-
@c2.many_to_one :parent, :class => @c2
|
459
|
-
|
460
|
-
d = @c2.create(:id => 1)
|
461
|
-
DB.reset
|
462
|
-
d.parent_id = 234
|
463
|
-
d.associations[:parent] = 42
|
464
|
-
d.parent(proc{|ds| ds.filter{name > 'M'}}).wont_equal 42
|
465
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE ((nodes.id = 234) AND (name > 'M')) LIMIT 1"]
|
466
|
-
end
|
467
|
-
|
468
|
-
it "should use a block given to the association method as a callback" do
|
469
|
-
@c2.many_to_one :parent, :class => @c2
|
470
|
-
|
471
|
-
d = @c2.create(:id => 1)
|
472
|
-
DB.reset
|
473
|
-
d.parent_id = 234
|
474
|
-
d.associations[:parent] = 42
|
475
|
-
d.parent{|ds| ds.filter{name > 'M'}}.wont_equal 42
|
476
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE ((nodes.id = 234) AND (name > 'M')) LIMIT 1"]
|
477
|
-
end
|
478
|
-
|
479
|
-
it "should have the setter add to the reciprocal one_to_many cached association array if it exists" do
|
480
|
-
@c2.many_to_one :parent, :class => @c2
|
481
|
-
@c2.one_to_many :children, :class => @c2, :key=>:parent_id
|
482
|
-
@c2.dataset._fetch = []
|
483
|
-
|
484
|
-
d = @c2.new(:id => 1)
|
485
|
-
e = @c2.new(:id => 2)
|
486
|
-
DB.sqls.must_equal []
|
487
|
-
d.parent = e
|
488
|
-
e.children.wont_include(d)
|
489
|
-
DB.sqls.must_equal ['SELECT * FROM nodes WHERE (nodes.parent_id = 2)']
|
490
|
-
|
491
|
-
d = @c2.new(:id => 1)
|
492
|
-
e = @c2.new(:id => 2)
|
493
|
-
e.children.wont_include(d)
|
494
|
-
DB.sqls.must_equal ['SELECT * FROM nodes WHERE (nodes.parent_id = 2)']
|
495
|
-
d.parent = e
|
496
|
-
e.children.must_include(d)
|
497
|
-
DB.sqls.must_equal []
|
498
|
-
end
|
499
|
-
|
500
|
-
it "should have setter deal with a one_to_one reciprocal" do
|
501
|
-
@c2.many_to_one :parent, :class => @c2, :key=>:parent_id
|
502
|
-
@c2.one_to_one :child, :class => @c2, :key=>:parent_id
|
503
|
-
|
504
|
-
d = @c2.new(:id => 1)
|
505
|
-
e = @c2.new(:id => 2)
|
506
|
-
e.associations[:child] = nil
|
507
|
-
d.parent = e
|
508
|
-
e.child.must_equal d
|
509
|
-
d.parent = nil
|
510
|
-
e.child.must_equal nil
|
511
|
-
d.parent = e
|
512
|
-
e.child.must_equal d
|
513
|
-
|
514
|
-
f = @c2.new(:id => 3)
|
515
|
-
d.parent = nil
|
516
|
-
e.child.must_equal nil
|
517
|
-
e.associations[:child] = f
|
518
|
-
d.parent = e
|
519
|
-
e.child.must_equal d
|
520
|
-
end
|
521
|
-
|
522
|
-
it "should have the setter remove the object from the previous associated object's reciprocal one_to_many cached association array if it exists" do
|
523
|
-
@c2.many_to_one :parent, :class => @c2
|
524
|
-
@c2.one_to_many :children, :class => @c2, :key=>:parent_id
|
525
|
-
@c2.dataset._fetch = []
|
526
|
-
|
527
|
-
d = @c2.new(:id => 1)
|
528
|
-
e = @c2.new(:id => 2)
|
529
|
-
f = @c2.new(:id => 3)
|
530
|
-
e.children.wont_include(d)
|
531
|
-
f.children.wont_include(d)
|
532
|
-
DB.reset
|
533
|
-
d.parent = e
|
534
|
-
e.children.must_include(d)
|
535
|
-
d.parent = f
|
536
|
-
f.children.must_include(d)
|
537
|
-
e.children.wont_include(d)
|
538
|
-
d.parent = nil
|
539
|
-
f.children.wont_include(d)
|
540
|
-
DB.sqls.must_equal []
|
541
|
-
end
|
542
|
-
|
543
|
-
it "should have the setter not modify the reciprocal if set to same value as current" do
|
544
|
-
@c2.many_to_one :parent, :class => @c2
|
545
|
-
@c2.one_to_many :children, :class => @c2, :key=>:parent_id
|
546
|
-
|
547
|
-
c1 = @c2.load(:id => 1, :parent_id=>nil)
|
548
|
-
c2 = @c2.load(:id => 2, :parent_id=>1)
|
549
|
-
c3 = @c2.load(:id => 3, :parent_id=>1)
|
550
|
-
c1.associations[:children] = [c2, c3]
|
551
|
-
c2.associations[:parent] = c1
|
552
|
-
c2.parent = c1
|
553
|
-
c1.children.must_equal [c2, c3]
|
554
|
-
DB.sqls.must_equal []
|
555
|
-
end
|
556
|
-
|
557
|
-
it "should get all matching records and only return the first if :key option is set to nil" do
|
558
|
-
@c2.one_to_many :children, :class => @c2, :key=>:parent_id
|
559
|
-
@c2.many_to_one :first_grand_parent, :class => @c2, :key=>nil, :eager_graph=>:children, :dataset=>proc{model.filter(:children_id=>parent_id)}
|
560
|
-
@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}, {}]
|
561
|
-
p = @c2.new(:parent_id=>2)
|
562
|
-
fgp = p.first_grand_parent
|
563
|
-
DB.sqls.must_equal ["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)"]
|
564
|
-
fgp.values.must_equal(:id=>1, :parent_id=>0, :par_parent_id=>3, :blah=>4)
|
565
|
-
fgp.children.first.values.must_equal(:id=>2, :parent_id=>1, :par_parent_id=>5, :blah=>6)
|
566
|
-
end
|
567
|
-
|
568
|
-
it "should not create the setter method if :read_only option is used" do
|
569
|
-
@c2.many_to_one :parent, :class => @c2, :read_only=>true
|
570
|
-
@c2.instance_methods.collect{|x| x.to_s}.must_include('parent')
|
571
|
-
@c2.instance_methods.collect{|x| x.to_s}.wont_include('parent=')
|
572
|
-
end
|
573
|
-
|
574
|
-
it "should not add associations methods directly to class" do
|
575
|
-
@c2.many_to_one :parent, :class => @c2
|
576
|
-
@c2.instance_methods.collect{|x| x.to_s}.must_include('parent')
|
577
|
-
@c2.instance_methods.collect{|x| x.to_s}.must_include('parent=')
|
578
|
-
@c2.instance_methods(false).collect{|x| x.to_s}.wont_include('parent')
|
579
|
-
@c2.instance_methods(false).collect{|x| x.to_s}.wont_include('parent=')
|
580
|
-
end
|
581
|
-
|
582
|
-
it "should add associations methods to the :methods_module option" do
|
583
|
-
m = Module.new
|
584
|
-
@c2.many_to_one :parent, :class => @c2, :methods_module=>m
|
585
|
-
m.instance_methods.collect{|x| x.to_s}.must_include('parent')
|
586
|
-
m.instance_methods.collect{|x| x.to_s}.must_include('parent=')
|
587
|
-
@c2.instance_methods.collect{|x| x.to_s}.wont_include('parent')
|
588
|
-
@c2.instance_methods.collect{|x| x.to_s}.wont_include('parent=')
|
589
|
-
end
|
590
|
-
|
591
|
-
it "should add associations methods directly to class if :methods_module is the class itself" do
|
592
|
-
@c2.many_to_one :parent, :class => @c2, :methods_module=>@c2
|
593
|
-
@c2.instance_methods(false).collect{|x| x.to_s}.must_include('parent')
|
594
|
-
@c2.instance_methods(false).collect{|x| x.to_s}.must_include('parent=')
|
595
|
-
end
|
596
|
-
|
597
|
-
it "should raise an error if trying to set a model object that doesn't have a valid primary key" do
|
598
|
-
@c2.many_to_one :parent, :class => @c2
|
599
|
-
p = @c2.new
|
600
|
-
c = @c2.load(:id=>123)
|
601
|
-
proc{c.parent = p}.must_raise(Sequel::Error)
|
602
|
-
end
|
603
|
-
|
604
|
-
it "should make the change to the foreign_key value inside a _association= method" do
|
605
|
-
@c2.many_to_one :parent, :class => @c2
|
606
|
-
@c2.private_instance_methods.collect{|x| x.to_s}.sort.must_include("_parent=")
|
607
|
-
p = @c2.new
|
608
|
-
c = @c2.load(:id=>123)
|
609
|
-
def p._parent=(x)
|
610
|
-
@x = x
|
611
|
-
end
|
612
|
-
def p.parent_id=; raise; end
|
613
|
-
p.parent = c
|
614
|
-
p.instance_variable_get(:@x).must_equal c
|
615
|
-
end
|
616
|
-
|
617
|
-
it "should have the :setter option define the _association= method" do
|
618
|
-
@c2.many_to_one :parent, :class => @c2, :setter=>proc{|x| @x = x}
|
619
|
-
p = @c2.new
|
620
|
-
c = @c2.load(:id=>123)
|
621
|
-
def p.parent_id=; raise; end
|
622
|
-
p.parent = c
|
623
|
-
p.instance_variable_get(:@x).must_equal c
|
624
|
-
end
|
625
|
-
|
626
|
-
it "should support (before|after)_set callbacks" do
|
627
|
-
h = []
|
628
|
-
@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}
|
629
|
-
@c2.class_eval do
|
630
|
-
self::Foo = h
|
631
|
-
def []=(a, v)
|
632
|
-
a == :parent_id ? (model::Foo << (v ? 4 : 5)) : super
|
633
|
-
end
|
634
|
-
def blah(x)
|
635
|
-
model::Foo << (x ? x.pk : :x)
|
636
|
-
end
|
637
|
-
def blahr(x)
|
638
|
-
model::Foo << 6
|
639
|
-
end
|
640
|
-
end
|
641
|
-
p = @c2.load(:id=>10)
|
642
|
-
c = @c2.load(:id=>123)
|
643
|
-
h.must_equal []
|
644
|
-
p.parent = c
|
645
|
-
h.must_equal [10, -123, 123, 4, 3]
|
646
|
-
p.parent = nil
|
647
|
-
h.must_equal [10, -123, 123, 4, 3, 10, :y, :x, 5, 3]
|
648
|
-
end
|
649
|
-
|
650
|
-
it "should support after_load association callback" do
|
651
|
-
h = []
|
652
|
-
@c2.many_to_one :parent, :class => @c2, :after_load=>[proc{|x,y| h << [x.pk, y.pk]}, :al]
|
653
|
-
@c2.class_eval do
|
654
|
-
self::Foo = h
|
655
|
-
def al(v)
|
656
|
-
model::Foo << v.pk
|
657
|
-
end
|
658
|
-
dataset._fetch = {:id=>20}
|
659
|
-
end
|
660
|
-
p = @c2.load(:id=>10, :parent_id=>20)
|
661
|
-
parent = p.parent
|
662
|
-
h.must_equal [[10, 20], 20]
|
663
|
-
parent.pk.must_equal 20
|
664
|
-
end
|
665
|
-
|
666
|
-
it "should support after_load association callback that changes the cached object" do
|
667
|
-
@c2.many_to_one :parent, :class => @c2, :after_load=>:al
|
668
|
-
@c2.class_eval do
|
669
|
-
def al(v)
|
670
|
-
associations[:parent] = :foo
|
671
|
-
end
|
672
|
-
end
|
673
|
-
p = @c2.load(:id=>10, :parent_id=>20)
|
674
|
-
p.parent.must_equal :foo
|
675
|
-
p.associations[:parent].must_equal :foo
|
676
|
-
end
|
677
|
-
|
678
|
-
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
|
679
|
-
p = @c2.new
|
680
|
-
c = @c2.load(:id=>123)
|
681
|
-
p.raise_on_save_failure = false
|
682
|
-
@c2.many_to_one :parent, :class => @c2, :before_set=>:bs
|
683
|
-
def p.bs(x) false end
|
684
|
-
def p._parent=; raise; end
|
685
|
-
proc{p.parent = c}.must_raise(Sequel::HookFailed)
|
686
|
-
|
687
|
-
p.parent.must_equal nil
|
688
|
-
p.associations[:parent] = c
|
689
|
-
p.parent.must_equal c
|
690
|
-
proc{p.parent = nil}.must_raise(Sequel::HookFailed)
|
691
|
-
end
|
692
|
-
|
693
|
-
it "should raise error and not call internal add or remove method if before callback calls cancel_action, even if raise_on_save_failure is false" do
|
694
|
-
p = @c2.new
|
695
|
-
c = @c2.load(:id=>123)
|
696
|
-
p.raise_on_save_failure = false
|
697
|
-
@c2.many_to_one :parent, :class => @c2, :before_set=>:bs
|
698
|
-
def p.bs(x) cancel_action end
|
699
|
-
def p._parent=; raise; end
|
700
|
-
proc{p.parent = c}.must_raise(Sequel::HookFailed)
|
701
|
-
|
702
|
-
p.parent.must_equal nil
|
703
|
-
p.associations[:parent] = c
|
704
|
-
p.parent.must_equal c
|
705
|
-
proc{p.parent = nil}.must_raise(Sequel::HookFailed)
|
706
|
-
end
|
707
|
-
|
708
|
-
it "should raise an error if a callback is not a proc or symbol" do
|
709
|
-
@c2.many_to_one :parent, :class => @c2, :before_set=>Object.new
|
710
|
-
proc{@c2.new.parent = @c2.load(:id=>1)}.must_raise(Sequel::Error)
|
711
|
-
end
|
712
|
-
end
|
713
|
-
|
714
|
-
describe Sequel::Model, "one_to_one" do
|
715
|
-
before do
|
716
|
-
@c1 = Class.new(Sequel::Model(:attributes)) do
|
717
|
-
unrestrict_primary_key
|
718
|
-
columns :id, :node_id, :y
|
719
|
-
end
|
720
|
-
|
721
|
-
@c2 = Class.new(Sequel::Model(:nodes)) do
|
722
|
-
unrestrict_primary_key
|
723
|
-
attr_accessor :xxx
|
724
|
-
|
725
|
-
def self.name; 'Node'; end
|
726
|
-
def self.to_s; 'Node'; end
|
727
|
-
columns :id, :x, :parent_id, :par_parent_id, :blah, :node_id
|
728
|
-
end
|
729
|
-
@dataset = @c2.dataset
|
730
|
-
@dataset._fetch = {}
|
731
|
-
@c1.dataset._fetch = {}
|
732
|
-
DB.reset
|
733
|
-
end
|
734
|
-
|
735
|
-
it "should have the getter method return a single object" do
|
736
|
-
@c2.one_to_one :attribute, :class => @c1
|
737
|
-
att = @c2.new(:id => 1234).attribute
|
738
|
-
DB.sqls.must_equal ['SELECT * FROM attributes WHERE (attributes.node_id = 1234) LIMIT 1']
|
739
|
-
att.must_be_kind_of(@c1)
|
740
|
-
att.values.must_equal({})
|
741
|
-
end
|
742
|
-
|
743
|
-
it "should not add a setter method if the :read_only option is true" do
|
744
|
-
@c2.one_to_one :attribute, :class => @c1, :read_only=>true
|
745
|
-
im = @c2.instance_methods.collect{|x| x.to_s}
|
746
|
-
im.must_include('attribute')
|
747
|
-
im.wont_include('attribute=')
|
748
|
-
end
|
749
|
-
|
750
|
-
it "should add a setter method" do
|
751
|
-
@c2.one_to_one :attribute, :class => @c1
|
752
|
-
attrib = @c1.new(:id=>3)
|
753
|
-
@c1.dataset._fetch = @c1.instance_dataset._fetch = {:id=>3}
|
754
|
-
@c2.new(:id => 1234).attribute = attrib
|
755
|
-
sqls = DB.sqls
|
756
|
-
['INSERT INTO attributes (node_id, id) VALUES (1234, 3)',
|
757
|
-
'INSERT INTO attributes (id, node_id) VALUES (3, 1234)'].must_include(sqls.slice! 1)
|
758
|
-
sqls.must_equal ['UPDATE attributes SET node_id = NULL WHERE (node_id = 1234)', "SELECT * FROM attributes WHERE (id = 3) LIMIT 1"]
|
759
|
-
|
760
|
-
@c2.new(:id => 1234).attribute.must_equal attrib
|
761
|
-
attrib = @c1.load(:id=>3)
|
762
|
-
@c2.new(:id => 1234).attribute = attrib
|
763
|
-
DB.sqls.must_equal ["SELECT * FROM attributes WHERE (attributes.node_id = 1234) LIMIT 1",
|
764
|
-
'UPDATE attributes SET node_id = NULL WHERE ((node_id = 1234) AND (id != 3))',
|
765
|
-
"UPDATE attributes SET node_id = 1234 WHERE (id = 3)"]
|
766
|
-
end
|
767
|
-
|
768
|
-
it "should use a transaction in the setter method" do
|
769
|
-
@c2.one_to_one :attribute, :class => @c1
|
770
|
-
@c2.use_transactions = true
|
771
|
-
attrib = @c1.load(:id=>3)
|
772
|
-
@c2.new(:id => 1234).attribute = attrib
|
773
|
-
DB.sqls.must_equal ['BEGIN',
|
774
|
-
'UPDATE attributes SET node_id = NULL WHERE ((node_id = 1234) AND (id != 3))',
|
775
|
-
"UPDATE attributes SET node_id = 1234 WHERE (id = 3)",
|
776
|
-
'COMMIT']
|
777
|
-
end
|
778
|
-
|
779
|
-
it "should have setter method respect association filters" do
|
780
|
-
@c2.one_to_one :attribute, :class => @c1, :conditions=>{:a=>1} do |ds|
|
781
|
-
ds.filter(:b=>2)
|
782
|
-
end
|
783
|
-
attrib = @c1.load(:id=>3)
|
784
|
-
@c2.new(:id => 1234).attribute = attrib
|
785
|
-
DB.sqls.must_equal ['UPDATE attributes SET node_id = NULL WHERE ((a = 1) AND (node_id = 1234) AND (b = 2) AND (id != 3))',
|
786
|
-
"UPDATE attributes SET node_id = 1234 WHERE (id = 3)"]
|
787
|
-
end
|
788
|
-
|
789
|
-
it "should have the setter method respect the :primary_key option" do
|
790
|
-
@c2.one_to_one :attribute, :class => @c1, :primary_key=>:xxx
|
791
|
-
attrib = @c1.new(:id=>3)
|
792
|
-
@c1.dataset._fetch = @c1.instance_dataset._fetch = {:id=>3}
|
793
|
-
@c2.new(:id => 1234, :xxx=>5).attribute = attrib
|
794
|
-
sqls = DB.sqls
|
795
|
-
['INSERT INTO attributes (node_id, id) VALUES (5, 3)',
|
796
|
-
'INSERT INTO attributes (id, node_id) VALUES (3, 5)'].must_include(sqls.slice! 1)
|
797
|
-
sqls.must_equal ['UPDATE attributes SET node_id = NULL WHERE (node_id = 5)', "SELECT * FROM attributes WHERE (id = 3) LIMIT 1"]
|
798
|
-
|
799
|
-
@c2.new(:id => 321, :xxx=>5).attribute.must_equal attrib
|
800
|
-
attrib = @c1.load(:id=>3)
|
801
|
-
@c2.new(:id => 621, :xxx=>5).attribute = attrib
|
802
|
-
DB.sqls.must_equal ["SELECT * FROM attributes WHERE (attributes.node_id = 5) LIMIT 1",
|
803
|
-
'UPDATE attributes SET node_id = NULL WHERE ((node_id = 5) AND (id != 3))',
|
804
|
-
'UPDATE attributes SET node_id = 5 WHERE (id = 3)']
|
805
|
-
end
|
806
|
-
|
807
|
-
it "should have the setter method respect composite keys" do
|
808
|
-
@c2.one_to_one :attribute, :class => @c1, :key=>[:node_id, :y], :primary_key=>[:id, :x]
|
809
|
-
attrib = @c1.load(:id=>3, :y=>6)
|
810
|
-
@c1.dataset._fetch = {:id=>3, :y=>6}
|
811
|
-
@c2.load(:id => 1234, :x=>5).attribute = attrib
|
812
|
-
sqls = DB.sqls
|
813
|
-
sqls.last.must_match(/UPDATE attributes SET (node_id = 1234|y = 5), (node_id = 1234|y = 5) WHERE \(id = 3\)/)
|
814
|
-
sqls.first.must_match(/UPDATE attributes SET (node_id|y) = NULL, (node_id|y) = NULL WHERE \(\(node_id = 1234\) AND \(y = 5\) AND \(id != 3\)\)/)
|
815
|
-
sqls.length.must_equal 2
|
816
|
-
end
|
817
|
-
|
818
|
-
it "should use implicit key if omitted" do
|
819
|
-
@c2.one_to_one :parent, :class => @c2
|
820
|
-
|
821
|
-
d = @c2.new(:id => 234)
|
822
|
-
p = d.parent
|
823
|
-
p.class.must_equal @c2
|
824
|
-
p.values.must_equal({})
|
825
|
-
|
826
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE (nodes.node_id = 234) LIMIT 1"]
|
827
|
-
end
|
828
|
-
|
829
|
-
it "should use implicit class if omitted" do
|
830
|
-
begin
|
831
|
-
class ::ParParent < Sequel::Model; end
|
832
|
-
@c2.one_to_one :par_parent
|
833
|
-
@c2.new(:id => 234).par_parent.class.must_equal ParParent
|
834
|
-
DB.sqls.must_equal ["SELECT * FROM par_parents WHERE (par_parents.node_id = 234) LIMIT 1"]
|
835
|
-
ensure
|
836
|
-
Object.send(:remove_const, :ParParent)
|
837
|
-
end
|
838
|
-
end
|
839
|
-
|
840
|
-
it "should use class inside module if given as a string" do
|
841
|
-
begin
|
842
|
-
module ::Par
|
843
|
-
class Parent < Sequel::Model; end
|
844
|
-
end
|
845
|
-
@c2.one_to_one :par_parent, :class=>"Par::Parent"
|
846
|
-
@c2.new(:id => 234).par_parent.class.must_equal Par::Parent
|
847
|
-
DB.sqls.must_equal ["SELECT * FROM parents WHERE (parents.node_id = 234) LIMIT 1"]
|
848
|
-
ensure
|
849
|
-
Object.send(:remove_const, :Par)
|
850
|
-
end
|
851
|
-
end
|
852
|
-
|
853
|
-
it "should use explicit key if given" do
|
854
|
-
@c2.one_to_one :parent, :class => @c2, :key => :blah
|
855
|
-
|
856
|
-
d = @c2.new(:id => 234)
|
857
|
-
p = d.parent
|
858
|
-
p.class.must_equal @c2
|
859
|
-
p.values.must_equal({})
|
860
|
-
|
861
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE (nodes.blah = 234) LIMIT 1"]
|
862
|
-
end
|
863
|
-
|
864
|
-
it "should use :primary_key option if given" do
|
865
|
-
@c2.one_to_one :parent, :class => @c2, :key => :pk, :primary_key => :blah
|
866
|
-
@c2.new(:id => 1, :blah => 567).parent
|
867
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE (nodes.pk = 567) LIMIT 1"]
|
868
|
-
end
|
869
|
-
|
870
|
-
it "should support composite keys" do
|
871
|
-
@c2.one_to_one :parent, :class => @c2, :primary_key=>[:id, :parent_id], :key=>[:parent_id, :id]
|
872
|
-
@c2.new(:id => 1, :parent_id => 234).parent
|
873
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE ((nodes.parent_id = 1) AND (nodes.id = 234)) LIMIT 1"]
|
874
|
-
end
|
875
|
-
|
876
|
-
it "should not issue query if not all keys have values" do
|
877
|
-
@c2.one_to_one :parent, :class => @c2, :key=>[:id, :parent_id], :primary_key=>[:parent_id, :id]
|
878
|
-
@c2.new(:id => 1, :parent_id => nil).parent.must_equal nil
|
879
|
-
DB.sqls.must_equal []
|
880
|
-
end
|
881
|
-
|
882
|
-
it "should raise an Error unless same number of composite keys used" do
|
883
|
-
proc{@c2.one_to_one :parent, :class => @c2, :primary_key=>[:parent_id, :id]}.must_raise(Sequel::Error)
|
884
|
-
proc{@c2.one_to_one :parent, :class => @c2, :key=>[:id, :parent_id], :primary_key=>:id}.must_raise(Sequel::Error)
|
885
|
-
proc{@c2.one_to_one :parent, :class => @c2, :key=>:id, :primary_key=>[:parent_id, :id]}.must_raise(Sequel::Error)
|
886
|
-
proc{@c2.one_to_one :parent, :class => @c2, :key=>[:id, :parent_id, :blah], :primary_key=>[:parent_id, :id]}.must_raise(Sequel::Error)
|
887
|
-
end
|
888
|
-
|
889
|
-
it "should use :select option if given" do
|
890
|
-
@c2.one_to_one :parent, :class => @c2, :select=>[:id, :name]
|
891
|
-
@c2.new(:id => 567).parent
|
892
|
-
DB.sqls.must_equal ["SELECT id, name FROM nodes WHERE (nodes.node_id = 567) LIMIT 1"]
|
893
|
-
end
|
894
|
-
|
895
|
-
it "should use :conditions option if given" do
|
896
|
-
@c2.one_to_one :parent, :class => @c2, :conditions=>{:a=>32}
|
897
|
-
@c2.new(:id => 567).parent
|
898
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE ((a = 32) AND (nodes.node_id = 567)) LIMIT 1"]
|
899
|
-
|
900
|
-
@c2.one_to_one :parent, :class => @c2, :conditions=>:a
|
901
|
-
@c2.new(:id => 567).parent
|
902
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE (a AND (nodes.node_id = 567)) LIMIT 1"]
|
903
|
-
end
|
904
|
-
|
905
|
-
it "should support :order, :limit (only for offset), and :dataset options, as well as a block" do
|
906
|
-
@c2.one_to_one :child_20, :class => @c2, :key=>:id, :dataset=>proc{model.filter(:parent_id=>pk)}, :limit=>[10,20], :order=>:name do |ds|
|
907
|
-
ds.filter{x > 1}
|
908
|
-
end
|
909
|
-
@c2.load(:id => 100).child_20
|
910
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE ((parent_id = 100) AND (x > 1)) ORDER BY name LIMIT 1 OFFSET 20"]
|
911
|
-
end
|
912
|
-
|
913
|
-
it "should return nil if primary_key value is nil" do
|
914
|
-
@c2.one_to_one :parent, :class => @c2, :primary_key=>:node_id
|
915
|
-
|
916
|
-
@c2.new(:id => 1).parent.must_equal nil
|
917
|
-
DB.sqls.must_equal []
|
918
|
-
end
|
919
|
-
|
920
|
-
it "should cache negative lookup" do
|
921
|
-
@c2.one_to_one :parent, :class => @c2
|
922
|
-
@c2.dataset._fetch = []
|
923
|
-
d = @c2.new(:id => 555)
|
924
|
-
DB.sqls.must_equal []
|
925
|
-
d.parent.must_equal nil
|
926
|
-
DB.sqls.must_equal ['SELECT * FROM nodes WHERE (nodes.node_id = 555) LIMIT 1']
|
927
|
-
d.parent.must_equal nil
|
928
|
-
DB.sqls.must_equal []
|
929
|
-
end
|
930
|
-
|
931
|
-
it "should have the setter method respect the :key option" do
|
932
|
-
@c2.one_to_one :parent, :class => @c2, :key=>:blah
|
933
|
-
d = @c2.new(:id => 3)
|
934
|
-
e = @c2.new(:id => 4321, :blah=>444)
|
935
|
-
@c2.dataset._fetch = @c2.instance_dataset._fetch = {:id => 4321, :blah => 3}
|
936
|
-
d.parent = e
|
937
|
-
e.values.must_equal(:id => 4321, :blah => 3)
|
938
|
-
sqls = DB.sqls
|
939
|
-
["INSERT INTO nodes (blah, id) VALUES (3, 4321)",
|
940
|
-
"INSERT INTO nodes (id, blah) VALUES (4321, 3)"].must_include(sqls.slice! 1)
|
941
|
-
sqls.must_equal ["UPDATE nodes SET blah = NULL WHERE (blah = 3)", "SELECT * FROM nodes WHERE (id = 4321) LIMIT 1"]
|
942
|
-
end
|
943
|
-
|
944
|
-
it "should persist changes to associated object when the setter is called" do
|
945
|
-
@c2.one_to_one :parent, :class => @c2
|
946
|
-
d = @c2.load(:id => 1)
|
947
|
-
d.parent = @c2.load(:id => 3, :node_id=>345)
|
948
|
-
DB.sqls.must_equal ["UPDATE nodes SET node_id = NULL WHERE ((node_id = 1) AND (id != 3))",
|
949
|
-
"UPDATE nodes SET node_id = 1 WHERE (id = 3)"]
|
950
|
-
end
|
951
|
-
|
952
|
-
it "should populate cache when accessed" do
|
953
|
-
@c2.one_to_one :parent, :class => @c2
|
954
|
-
|
955
|
-
d = @c2.load(:id => 1)
|
956
|
-
d.associations[:parent].must_equal nil
|
957
|
-
@c2.dataset._fetch = {:id=>234}
|
958
|
-
e = d.parent
|
959
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE (nodes.node_id = 1) LIMIT 1"]
|
960
|
-
d.parent
|
961
|
-
DB.sqls.must_equal []
|
962
|
-
d.associations[:parent].must_equal e
|
963
|
-
end
|
964
|
-
|
965
|
-
it "should populate cache when assigned" do
|
966
|
-
@c2.one_to_one :parent, :class => @c2
|
967
|
-
|
968
|
-
d = @c2.load(:id => 1)
|
969
|
-
d.associations[:parent].must_equal nil
|
970
|
-
e = @c2.load(:id => 234)
|
971
|
-
d.parent = e
|
972
|
-
f = d.parent
|
973
|
-
d.associations[:parent].must_equal e
|
974
|
-
e.must_equal f
|
975
|
-
end
|
976
|
-
|
977
|
-
it "should use cache if available" do
|
978
|
-
@c2.one_to_one :parent, :class => @c2
|
979
|
-
d = @c2.load(:id => 1, :parent_id => 234)
|
980
|
-
d.associations[:parent] = 42
|
981
|
-
d.parent.must_equal 42
|
982
|
-
DB.sqls.must_equal []
|
983
|
-
end
|
984
|
-
|
985
|
-
it "should not use cache if asked to reload" do
|
986
|
-
@c2.one_to_one :parent, :class => @c2
|
987
|
-
d = @c2.load(:id => 1)
|
988
|
-
d.associations[:parent] = [42]
|
989
|
-
d.parent(true).wont_equal 42
|
990
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE (nodes.node_id = 1) LIMIT 1"]
|
991
|
-
end
|
992
|
-
|
993
|
-
it "should have the setter set the reciprocal many_to_one cached association" do
|
994
|
-
@c2.one_to_one :parent, :class => @c2, :key=>:parent_id
|
995
|
-
@c2.many_to_one :child, :class => @c2, :key=>:parent_id
|
996
|
-
|
997
|
-
d = @c2.load(:id => 1)
|
998
|
-
e = @c2.load(:id => 2)
|
999
|
-
d.parent = e
|
1000
|
-
e.child.must_equal d
|
1001
|
-
DB.sqls.must_equal ["UPDATE nodes SET parent_id = NULL WHERE ((parent_id = 1) AND (id != 2))",
|
1002
|
-
"UPDATE nodes SET parent_id = 1 WHERE (id = 2)"]
|
1003
|
-
d.parent = nil
|
1004
|
-
e.child.must_equal nil
|
1005
|
-
DB.sqls.must_equal ["UPDATE nodes SET parent_id = NULL WHERE (parent_id = 1)"]
|
1006
|
-
end
|
1007
|
-
|
1008
|
-
it "should have the setter remove the object from the previous associated object's reciprocal many_to_one cached association array if it exists" do
|
1009
|
-
@c2.one_to_one :parent, :class => @c2, :key=>:parent_id
|
1010
|
-
@c2.many_to_one :child, :class => @c2, :key=>:parent_id
|
1011
|
-
@c2.dataset._fetch = []
|
1012
|
-
|
1013
|
-
d = @c2.load(:id => 1)
|
1014
|
-
e = @c2.load(:id => 2)
|
1015
|
-
f = @c2.load(:id => 3)
|
1016
|
-
e.child.must_equal nil
|
1017
|
-
f.child.must_equal nil
|
1018
|
-
d.parent = e
|
1019
|
-
e.child.must_equal d
|
1020
|
-
d.parent = f
|
1021
|
-
f.child.must_equal d
|
1022
|
-
e.child.must_equal nil
|
1023
|
-
d.parent = nil
|
1024
|
-
f.child.must_equal nil
|
1025
|
-
end
|
1026
|
-
|
1027
|
-
it "should have the setter not modify the reciprocal if set to same value as current" do
|
1028
|
-
@c2.one_to_one :parent, :class => @c2, :key=>:parent_id
|
1029
|
-
@c2.many_to_one :child, :class => @c2, :key=>:parent_id
|
1030
|
-
|
1031
|
-
c1 = @c2.load(:id => 1, :parent_id=>nil)
|
1032
|
-
c2 = @c2.load(:id => 2, :parent_id=>1)
|
1033
|
-
c1.associations[:child] = c2
|
1034
|
-
c2.associations[:parent] = c1
|
1035
|
-
c2.parent = c1
|
1036
|
-
c1.child.must_equal c2
|
1037
|
-
DB.sqls.must_equal []
|
1038
|
-
end
|
1039
|
-
|
1040
|
-
it "should not add associations methods directly to class" do
|
1041
|
-
@c2.one_to_one :parent, :class => @c2
|
1042
|
-
@c2.instance_methods.collect{|x| x.to_s}.must_include('parent')
|
1043
|
-
@c2.instance_methods.collect{|x| x.to_s}.must_include('parent=')
|
1044
|
-
@c2.instance_methods(false).collect{|x| x.to_s}.wont_include('parent')
|
1045
|
-
@c2.instance_methods(false).collect{|x| x.to_s}.wont_include('parent=')
|
1046
|
-
end
|
1047
|
-
|
1048
|
-
it "should raise an error if the current model object that doesn't have a valid primary key" do
|
1049
|
-
@c2.one_to_one :parent, :class => @c2
|
1050
|
-
p = @c2.new
|
1051
|
-
c = @c2.load(:id=>123)
|
1052
|
-
proc{p.parent = c}.must_raise(Sequel::Error)
|
1053
|
-
end
|
1054
|
-
|
1055
|
-
it "should make the change to the foreign_key value inside a _association= method" do
|
1056
|
-
@c2.one_to_one :parent, :class => @c2
|
1057
|
-
@c2.private_instance_methods.collect{|x| x.to_s}.sort.must_include("_parent=")
|
1058
|
-
c = @c2.new
|
1059
|
-
p = @c2.load(:id=>123)
|
1060
|
-
def p._parent=(x)
|
1061
|
-
@x = x
|
1062
|
-
end
|
1063
|
-
def p.parent_id=; raise; end
|
1064
|
-
p.parent = c
|
1065
|
-
p.instance_variable_get(:@x).must_equal c
|
1066
|
-
end
|
1067
|
-
|
1068
|
-
it "should have a :setter option define the _association= method" do
|
1069
|
-
@c2.one_to_one :parent, :class => @c2, :setter=>proc{|x| @x = x}
|
1070
|
-
c = @c2.new
|
1071
|
-
p = @c2.load(:id=>123)
|
1072
|
-
def p.parent_id=; raise; end
|
1073
|
-
p.parent = c
|
1074
|
-
p.instance_variable_get(:@x).must_equal c
|
1075
|
-
end
|
1076
|
-
|
1077
|
-
it "should support (before|after)_set callbacks" do
|
1078
|
-
h = []
|
1079
|
-
@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}
|
1080
|
-
@c2.class_eval do
|
1081
|
-
self::Foo = h
|
1082
|
-
def blah(x)
|
1083
|
-
model::Foo << (x ? x.pk : :x)
|
1084
|
-
end
|
1085
|
-
def blahr(x)
|
1086
|
-
model::Foo << 6
|
1087
|
-
end
|
1088
|
-
end
|
1089
|
-
p = @c2.load(:id=>10)
|
1090
|
-
c = @c2.load(:id=>123)
|
1091
|
-
h.must_equal []
|
1092
|
-
p.parent = c
|
1093
|
-
h.must_equal [10, -123, 123, 3]
|
1094
|
-
p.parent = nil
|
1095
|
-
h.must_equal [10, -123, 123, 3, 10, :y, :x, 3]
|
1096
|
-
end
|
1097
|
-
|
1098
|
-
it "should support after_load association callback" do
|
1099
|
-
h = []
|
1100
|
-
@c2.one_to_one :parent, :class => @c2, :after_load=>[proc{|x,y| h << [x.pk, y.pk]}, :al]
|
1101
|
-
@c2.class_eval do
|
1102
|
-
self::Foo = h
|
1103
|
-
def al(v)
|
1104
|
-
model::Foo << v.pk
|
1105
|
-
end
|
1106
|
-
@dataset._fetch = {:id=>20}
|
1107
|
-
end
|
1108
|
-
p = @c2.load(:id=>10)
|
1109
|
-
parent = p.parent
|
1110
|
-
h.must_equal [[10, 20], 20]
|
1111
|
-
parent.pk.must_equal 20
|
1112
|
-
end
|
1113
|
-
|
1114
|
-
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
|
1115
|
-
p = @c2.load(:id=>321)
|
1116
|
-
c = @c2.load(:id=>123)
|
1117
|
-
p.raise_on_save_failure = false
|
1118
|
-
@c2.one_to_one :parent, :class => @c2, :before_set=>:bs
|
1119
|
-
def p.bs(x) false end
|
1120
|
-
def p._parent=; raise; end
|
1121
|
-
proc{p.parent = c}.must_raise(Sequel::HookFailed)
|
1122
|
-
|
1123
|
-
p.associations[:parent].must_equal nil
|
1124
|
-
p.associations[:parent] = c
|
1125
|
-
p.parent.must_equal c
|
1126
|
-
proc{p.parent = nil}.must_raise(Sequel::HookFailed)
|
1127
|
-
end
|
1128
|
-
|
1129
|
-
it "should not validate the associated object in setter if the :validate=>false option is used" do
|
1130
|
-
@c2.one_to_one :parent, :class => @c2, :validate=>false
|
1131
|
-
n = @c2.new(:id => 1234)
|
1132
|
-
a = @c2.new(:id => 2345)
|
1133
|
-
def a.validate() errors.add(:id, 'foo') end
|
1134
|
-
(n.parent = a).must_equal a
|
1135
|
-
end
|
1136
|
-
|
1137
|
-
it "should raise an error if a callback is not a proc or symbol" do
|
1138
|
-
@c2.one_to_one :parent, :class => @c2, :before_set=>Object.new
|
1139
|
-
proc{@c2.new.parent = @c2.load(:id=>1)}.must_raise(Sequel::Error)
|
1140
|
-
end
|
1141
|
-
|
1142
|
-
it "should work_correctly when used with associate" do
|
1143
|
-
@c2.associate :one_to_one, :parent, :class => @c2
|
1144
|
-
@c2.load(:id => 567).parent.must_equal @c2.load({})
|
1145
|
-
DB.sqls.must_equal ["SELECT * FROM nodes WHERE (nodes.node_id = 567) LIMIT 1"]
|
1146
|
-
end
|
1147
|
-
end
|
1148
|
-
|
1149
|
-
describe Sequel::Model, "one_to_many" do
|
1150
|
-
before do
|
1151
|
-
@c1 = Class.new(Sequel::Model(:attributes)) do
|
1152
|
-
unrestrict_primary_key
|
1153
|
-
columns :id, :node_id, :y, :z
|
1154
|
-
end
|
1155
|
-
|
1156
|
-
@c2 = Class.new(Sequel::Model(:nodes)) do
|
1157
|
-
def _refresh(ds); end
|
1158
|
-
unrestrict_primary_key
|
1159
|
-
attr_accessor :xxx
|
1160
|
-
|
1161
|
-
def self.name; 'Node'; end
|
1162
|
-
def self.to_s; 'Node'; end
|
1163
|
-
columns :id, :x
|
1164
|
-
end
|
1165
|
-
@dataset = @c2.dataset
|
1166
|
-
@dataset._fetch = {}
|
1167
|
-
@c1.dataset._fetch = proc{|sql| sql =~ /SELECT 1/ ? {:a=>1} : {}}
|
1168
|
-
DB.reset
|
1169
|
-
end
|
1170
|
-
|
1171
|
-
it "should raise an error if current class does not have a primary key, and :primary_key is not specified" do
|
1172
|
-
@c2.no_primary_key
|
1173
|
-
proc{@c2.one_to_many :attributes, :class => @c1}.must_raise(Sequel::Error)
|
1174
|
-
DB.sqls.must_equal []
|
1175
|
-
end
|
1176
|
-
|
1177
|
-
it "should use implicit key if omitted" do
|
1178
|
-
@c2.one_to_many :attributes, :class => @c1
|
1179
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT * FROM attributes WHERE (attributes.node_id = 1234)'
|
1180
|
-
end
|
1181
|
-
|
1182
|
-
it "should use implicit class if omitted" do
|
1183
|
-
begin
|
1184
|
-
class ::HistoricalValue < Sequel::Model; end
|
1185
|
-
@c2.one_to_many :historical_values
|
1186
|
-
|
1187
|
-
v = @c2.new(:id => 1234).historical_values_dataset
|
1188
|
-
v.must_be_kind_of(Sequel::Dataset)
|
1189
|
-
v.sql.must_equal 'SELECT * FROM historical_values WHERE (historical_values.node_id = 1234)'
|
1190
|
-
v.model.must_equal HistoricalValue
|
1191
|
-
ensure
|
1192
|
-
Object.send(:remove_const, :HistoricalValue)
|
1193
|
-
end
|
1194
|
-
end
|
1195
|
-
|
1196
|
-
it "should use class inside a module if given as a string" do
|
1197
|
-
begin
|
1198
|
-
module ::Historical
|
1199
|
-
class Value < Sequel::Model; end
|
1200
|
-
end
|
1201
|
-
@c2.one_to_many :historical_values, :class=>'Historical::Value'
|
1202
|
-
|
1203
|
-
v = @c2.new(:id => 1234).historical_values_dataset
|
1204
|
-
v.must_be_kind_of(Sequel::Dataset)
|
1205
|
-
v.sql.must_equal 'SELECT * FROM values WHERE (values.node_id = 1234)'
|
1206
|
-
v.model.must_equal Historical::Value
|
1207
|
-
ensure
|
1208
|
-
Object.send(:remove_const, :Historical)
|
1209
|
-
end
|
1210
|
-
end
|
1211
|
-
|
1212
|
-
it "should use a callback if given one as the argument" do
|
1213
|
-
@c2.one_to_many :attributes, :class => @c1, :key => :nodeid
|
1214
|
-
|
1215
|
-
d = @c2.load(:id => 1234)
|
1216
|
-
d.associations[:attributes] = []
|
1217
|
-
d.attributes(proc{|ds| ds.filter{name > 'M'}}).wont_equal []
|
1218
|
-
DB.sqls.must_equal ["SELECT * FROM attributes WHERE ((attributes.nodeid = 1234) AND (name > 'M'))"]
|
1219
|
-
end
|
1220
|
-
|
1221
|
-
it "should use explicit key if given" do
|
1222
|
-
@c2.one_to_many :attributes, :class => @c1, :key => :nodeid
|
1223
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT * FROM attributes WHERE (attributes.nodeid = 1234)'
|
1224
|
-
end
|
1225
|
-
|
1226
|
-
it "should support_composite keys" do
|
1227
|
-
@c2.one_to_many :attributes, :class => @c1, :key =>[:node_id, :id], :primary_key=>[:id, :x]
|
1228
|
-
@c2.load(:id => 1234, :x=>234).attributes_dataset.sql.must_equal 'SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (attributes.id = 234))'
|
1229
|
-
end
|
1230
|
-
|
1231
|
-
it "should not issue query if not all keys have values" do
|
1232
|
-
@c2.one_to_many :attributes, :class => @c1, :key =>[:node_id, :id], :primary_key=>[:id, :x]
|
1233
|
-
@c2.load(:id => 1234, :x=>nil).attributes.must_equal []
|
1234
|
-
DB.sqls.must_equal []
|
1235
|
-
end
|
1236
|
-
|
1237
|
-
it "should raise an Error unless same number of composite keys used" do
|
1238
|
-
proc{@c2.one_to_many :attributes, :class => @c1, :key=>[:node_id, :id]}.must_raise(Sequel::Error)
|
1239
|
-
proc{@c2.one_to_many :attributes, :class => @c1, :primary_key=>[:node_id, :id]}.must_raise(Sequel::Error)
|
1240
|
-
proc{@c2.one_to_many :attributes, :class => @c1, :key=>[:node_id, :id], :primary_key=>:id}.must_raise(Sequel::Error)
|
1241
|
-
proc{@c2.one_to_many :attributes, :class => @c1, :key=>:id, :primary_key=>[:node_id, :id]}.must_raise(Sequel::Error)
|
1242
|
-
proc{@c2.one_to_many :attributes, :class => @c1, :key=>[:node_id, :id, :x], :primary_key=>[:parent_id, :id]}.must_raise(Sequel::Error)
|
1243
|
-
end
|
1244
|
-
|
1245
|
-
it "should define an add_ method that works on existing records" do
|
1246
|
-
@c2.one_to_many :attributes, :class => @c1
|
1247
|
-
|
1248
|
-
n = @c2.load(:id => 1234)
|
1249
|
-
a = @c1.load(:id => 2345)
|
1250
|
-
a.must_equal n.add_attribute(a)
|
1251
|
-
a.values.must_equal(:node_id => 1234, :id => 2345)
|
1252
|
-
DB.sqls.must_equal ['UPDATE attributes SET node_id = 1234 WHERE (id = 2345)']
|
1253
|
-
end
|
1254
|
-
|
1255
|
-
it "should define an add_ method that works on new records" do
|
1256
|
-
@c2.one_to_many :attributes, :class => @c1
|
1257
|
-
|
1258
|
-
n = @c2.load(:id => 1234)
|
1259
|
-
a = @c1.new(:id => 234)
|
1260
|
-
@c1.dataset._fetch = @c1.instance_dataset._fetch = {:node_id => 1234, :id => 234}
|
1261
|
-
a.must_equal n.add_attribute(a)
|
1262
|
-
sqls = DB.sqls
|
1263
|
-
sqls.shift.must_match(/INSERT INTO attributes \((node_)?id, (node_)?id\) VALUES \(1?234, 1?234\)/)
|
1264
|
-
sqls.must_equal ["SELECT * FROM attributes WHERE (id = 234) LIMIT 1"]
|
1265
|
-
a.values.must_equal(:node_id => 1234, :id => 234)
|
1266
|
-
end
|
1267
|
-
|
1268
|
-
it "should define a remove_ method that works on existing records" do
|
1269
|
-
@c2.one_to_many :attributes, :class => @c1
|
1270
|
-
|
1271
|
-
n = @c2.load(:id => 1234)
|
1272
|
-
a = @c1.load(:id => 2345, :node_id => 1234)
|
1273
|
-
a.must_equal n.remove_attribute(a)
|
1274
|
-
a.values.must_equal(:node_id => nil, :id => 2345)
|
1275
|
-
DB.sqls.must_equal ["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)']
|
1276
|
-
end
|
1277
|
-
|
1278
|
-
it "should have the remove_ method raise an error if the passed object is not already associated" do
|
1279
|
-
@c2.one_to_many :attributes, :class => @c1
|
1280
|
-
|
1281
|
-
n = @c2.new(:id => 1234)
|
1282
|
-
a = @c1.load(:id => 2345, :node_id => 1234)
|
1283
|
-
@c1.dataset._fetch = []
|
1284
|
-
proc{n.remove_attribute(a)}.must_raise(Sequel::Error)
|
1285
|
-
DB.sqls.must_equal ["SELECT 1 AS one FROM attributes WHERE ((attributes.node_id = 1234) AND (id = 2345)) LIMIT 1"]
|
1286
|
-
end
|
1287
|
-
|
1288
|
-
it "should accept a hash for the add_ method and create a new record" do
|
1289
|
-
@c2.one_to_many :attributes, :class => @c1
|
1290
|
-
n = @c2.new(:id => 1234)
|
1291
|
-
DB.reset
|
1292
|
-
@c1.dataset._fetch = @c1.instance_dataset._fetch = {:node_id => 1234, :id => 234}
|
1293
|
-
n.add_attribute(:id => 234).must_equal @c1.load(:node_id => 1234, :id => 234)
|
1294
|
-
sqls = DB.sqls
|
1295
|
-
sqls.shift.must_match(/INSERT INTO attributes \((node_)?id, (node_)?id\) VALUES \(1?234, 1?234\)/)
|
1296
|
-
sqls.must_equal ["SELECT * FROM attributes WHERE (id = 234) LIMIT 1"]
|
1297
|
-
end
|
1298
|
-
|
1299
|
-
it "should accept a primary key for the add_ method" do
|
1300
|
-
@c2.one_to_many :attributes, :class => @c1
|
1301
|
-
n = @c2.new(:id => 1234)
|
1302
|
-
@c1.dataset._fetch = {:id=>234, :node_id=>nil}
|
1303
|
-
n.add_attribute(234).must_equal @c1.load(:node_id => 1234, :id => 234)
|
1304
|
-
DB.sqls.must_equal ["SELECT * FROM attributes WHERE id = 234", "UPDATE attributes SET node_id = 1234 WHERE (id = 234)"]
|
1305
|
-
end
|
1306
|
-
|
1307
|
-
it "should raise an error if the primary key passed to the add_ method does not match an existing record" do
|
1308
|
-
@c2.one_to_many :attributes, :class => @c1
|
1309
|
-
n = @c2.new(:id => 1234)
|
1310
|
-
@c1.dataset._fetch = []
|
1311
|
-
proc{n.add_attribute(234)}.must_raise(Sequel::NoMatchingRow)
|
1312
|
-
DB.sqls.must_equal ["SELECT * FROM attributes WHERE id = 234"]
|
1313
|
-
end
|
1314
|
-
|
1315
|
-
it "should raise an error in the add_ method if the passed associated object is not of the correct type" do
|
1316
|
-
@c2.one_to_many :attributes, :class => @c1
|
1317
|
-
proc{@c2.new(:id => 1234).add_attribute(@c2.new)}.must_raise(Sequel::Error)
|
1318
|
-
end
|
1319
|
-
|
1320
|
-
it "should accept a primary key for the remove_ method and remove an existing record" do
|
1321
|
-
@c2.one_to_many :attributes, :class => @c1
|
1322
|
-
n = @c2.new(:id => 1234)
|
1323
|
-
@c1.dataset._fetch = {:id=>234, :node_id=>1234}
|
1324
|
-
n.remove_attribute(234).must_equal @c1.load(:node_id => nil, :id => 234)
|
1325
|
-
DB.sqls.must_equal ['SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (attributes.id = 234)) LIMIT 1',
|
1326
|
-
'UPDATE attributes SET node_id = NULL WHERE (id = 234)']
|
1327
|
-
end
|
1328
|
-
|
1329
|
-
it "should raise an error in the remove_ method if the passed associated object is not of the correct type" do
|
1330
|
-
@c2.one_to_many :attributes, :class => @c1
|
1331
|
-
proc{@c2.new(:id => 1234).remove_attribute(@c2.new)}.must_raise(Sequel::Error)
|
1332
|
-
end
|
1333
|
-
|
1334
|
-
it "should have add_ method respect the :primary_key option" do
|
1335
|
-
@c2.one_to_many :attributes, :class => @c1, :primary_key=>:xxx
|
1336
|
-
|
1337
|
-
n = @c2.new(:id => 1234, :xxx=>5)
|
1338
|
-
a = @c1.load(:id => 2345)
|
1339
|
-
n.add_attribute(a).must_equal a
|
1340
|
-
DB.sqls.must_equal ['UPDATE attributes SET node_id = 5 WHERE (id = 2345)']
|
1341
|
-
end
|
1342
|
-
|
1343
|
-
it "should have add_ method not add the same object to the cached association array if the object is already in the array" do
|
1344
|
-
@c2.one_to_many :attributes, :class => @c1
|
1345
|
-
|
1346
|
-
n = @c2.new(:id => 1234)
|
1347
|
-
a = @c1.load(:id => 2345)
|
1348
|
-
n.associations[:attributes] = []
|
1349
|
-
a.must_equal n.add_attribute(a)
|
1350
|
-
a.must_equal n.add_attribute(a)
|
1351
|
-
a.values.must_equal(:node_id => 1234, :id => 2345)
|
1352
|
-
n.attributes.must_equal [a]
|
1353
|
-
DB.sqls.must_equal ['UPDATE attributes SET node_id = 1234 WHERE (id = 2345)'] * 2
|
1354
|
-
end
|
1355
|
-
|
1356
|
-
it "should have add_ method respect composite keys" do
|
1357
|
-
@c2.one_to_many :attributes, :class => @c1, :key =>[:node_id, :y], :primary_key=>[:id, :x]
|
1358
|
-
|
1359
|
-
n = @c2.load(:id => 1234, :x=>5)
|
1360
|
-
a = @c1.load(:id => 2345)
|
1361
|
-
n.add_attribute(a).must_equal a
|
1362
|
-
sqls = DB.sqls
|
1363
|
-
sqls.shift.must_match(/UPDATE attributes SET (node_id = 1234|y = 5), (node_id = 1234|y = 5) WHERE \(id = 2345\)/)
|
1364
|
-
sqls.must_equal []
|
1365
|
-
end
|
1366
|
-
|
1367
|
-
it "should have add_ method accept a composite key" do
|
1368
|
-
@c1.set_primary_key [:id, :z]
|
1369
|
-
@c2.one_to_many :attributes, :class => @c1, :key =>[:node_id, :y], :primary_key=>[:id, :x]
|
1370
|
-
@c1.dataset._fetch = {:id => 2345, :z => 8, :node_id => 1234, :y=>5}
|
1371
|
-
|
1372
|
-
n = @c2.load(:id => 1234, :x=>5)
|
1373
|
-
a = @c1.load(:id => 2345, :z => 8, :node_id => 1234, :y=>5)
|
1374
|
-
n.add_attribute([2345, 8]).must_equal a
|
1375
|
-
sqls = DB.sqls
|
1376
|
-
sqls.shift.must_match(/SELECT \* FROM attributes WHERE \(\((id|z) = (2345|8)\) AND \((id|z) = (2345|8)\)\) LIMIT 1/)
|
1377
|
-
sqls.shift.must_match(/UPDATE attributes SET (node_id|y) = (1234|5), (node_id|y) = (1234|5) WHERE \(\((id|z) = (2345|8)\) AND \((id|z) = (2345|8)\)\)/)
|
1378
|
-
sqls.must_equal []
|
1379
|
-
end
|
1380
|
-
|
1381
|
-
it "should have remove_ method respect composite keys" do
|
1382
|
-
@c2.one_to_many :attributes, :class => @c1, :key =>[:node_id, :y], :primary_key=>[:id, :x]
|
1383
|
-
|
1384
|
-
n = @c2.load(:id => 1234, :x=>5)
|
1385
|
-
a = @c1.load(:id => 2345, :node_id=>1234, :y=>5)
|
1386
|
-
n.remove_attribute(a).must_equal a
|
1387
|
-
sqls = DB.sqls
|
1388
|
-
sqls.pop.must_match(/UPDATE attributes SET (node_id|y) = NULL, (node_id|y) = NULL WHERE \(id = 2345\)/)
|
1389
|
-
sqls.must_equal ["SELECT 1 AS one FROM attributes WHERE ((attributes.node_id = 1234) AND (attributes.y = 5) AND (id = 2345)) LIMIT 1"]
|
1390
|
-
end
|
1391
|
-
|
1392
|
-
it "should accept a array of composite primary key values for the remove_ method and remove an existing record" do
|
1393
|
-
@c1.set_primary_key [:id, :y]
|
1394
|
-
@c2.one_to_many :attributes, :class => @c1, :key=>:node_id, :primary_key=>:id
|
1395
|
-
n = @c2.new(:id => 123)
|
1396
|
-
@c1.dataset._fetch = {:id=>234, :node_id=>123, :y=>5}
|
1397
|
-
n.remove_attribute([234, 5]).must_equal @c1.load(:node_id => nil, :y => 5, :id => 234)
|
1398
|
-
sqls = DB.sqls
|
1399
|
-
sqls.length.must_equal 2
|
1400
|
-
sqls.first.must_match(/SELECT \* FROM attributes WHERE \(\(attributes.node_id = 123\) AND \(attributes\.(id|y) = (234|5)\) AND \(attributes\.(id|y) = (234|5)\)\) LIMIT 1/)
|
1401
|
-
sqls.last.must_match(/UPDATE attributes SET node_id = NULL WHERE \(\((id|y) = (234|5)\) AND \((id|y) = (234|5)\)\)/)
|
1402
|
-
end
|
1403
|
-
|
1404
|
-
it "should raise an error in add_ and remove_ if the passed object returns false to save (is not valid)" do
|
1405
|
-
@c2.one_to_many :attributes, :class => @c1
|
1406
|
-
n = @c2.new(:id => 1234)
|
1407
|
-
a = @c1.new(:id => 2345)
|
1408
|
-
def a.validate() errors.add(:id, 'foo') end
|
1409
|
-
proc{n.add_attribute(a)}.must_raise(Sequel::ValidationFailed)
|
1410
|
-
proc{n.remove_attribute(a)}.must_raise(Sequel::ValidationFailed)
|
1411
|
-
end
|
1412
|
-
|
1413
|
-
it "should not validate the associated object in add_ and remove_ if the :validate=>false option is used" do
|
1414
|
-
@c2.one_to_many :attributes, :class => @c1, :validate=>false
|
1415
|
-
n = @c2.new(:id => 1234)
|
1416
|
-
a = @c1.new(:id => 2345)
|
1417
|
-
def a.validate() errors.add(:id, 'foo') end
|
1418
|
-
n.add_attribute(a).must_equal a
|
1419
|
-
n.remove_attribute(a).must_equal a
|
1420
|
-
end
|
1421
|
-
|
1422
|
-
it "should not raise exception in add_ and remove_ if the :raise_on_save_failure=>false option is used" do
|
1423
|
-
@c2.one_to_many :attributes, :class => @c1, :raise_on_save_failure=>false
|
1424
|
-
n = @c2.new(:id => 1234)
|
1425
|
-
a = @c1.new(:id => 2345)
|
1426
|
-
def a.validate() errors.add(:id, 'foo') end
|
1427
|
-
n.associations[:attributes] = []
|
1428
|
-
n.add_attribute(a).must_equal nil
|
1429
|
-
n.associations[:attributes].must_equal []
|
1430
|
-
n.remove_attribute(a).must_equal nil
|
1431
|
-
n.associations[:attributes].must_equal []
|
1432
|
-
end
|
1433
|
-
|
1434
|
-
it "should raise an error if the model object doesn't have a valid primary key" do
|
1435
|
-
@c2.one_to_many :attributes, :class => @c1
|
1436
|
-
a = @c2.new
|
1437
|
-
n = @c1.load(:id=>123)
|
1438
|
-
proc{a.attributes_dataset}.must_raise(Sequel::Error)
|
1439
|
-
proc{a.add_attribute(n)}.must_raise(Sequel::Error)
|
1440
|
-
proc{a.remove_attribute(n)}.must_raise(Sequel::Error)
|
1441
|
-
proc{a.remove_all_attributes}.must_raise(Sequel::Error)
|
1442
|
-
end
|
1443
|
-
|
1444
|
-
it "should use :primary_key option if given" do
|
1445
|
-
@c1.one_to_many :nodes, :class => @c2, :primary_key => :node_id, :key=>:id
|
1446
|
-
@c1.load(:id => 1234, :node_id=>4321).nodes_dataset.sql.must_equal "SELECT * FROM nodes WHERE (nodes.id = 4321)"
|
1447
|
-
end
|
1448
|
-
|
1449
|
-
it "should support a select option" do
|
1450
|
-
@c2.one_to_many :attributes, :class => @c1, :select => [:id, :name]
|
1451
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal "SELECT id, name FROM attributes WHERE (attributes.node_id = 1234)"
|
1452
|
-
end
|
1453
|
-
|
1454
|
-
it "should support a conditions option" do
|
1455
|
-
@c2.one_to_many :attributes, :class => @c1, :conditions => {:a=>32}
|
1456
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal "SELECT * FROM attributes WHERE ((a = 32) AND (attributes.node_id = 1234))"
|
1457
|
-
@c2.one_to_many :attributes, :class => @c1, :conditions => Sequel.~(:a)
|
1458
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal "SELECT * FROM attributes WHERE (NOT a AND (attributes.node_id = 1234))"
|
1459
|
-
end
|
1460
|
-
|
1461
|
-
it "should support an order option" do
|
1462
|
-
@c2.one_to_many :attributes, :class => @c1, :order => :kind
|
1463
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal "SELECT * FROM attributes WHERE (attributes.node_id = 1234) ORDER BY kind"
|
1464
|
-
end
|
1465
|
-
|
1466
|
-
it "should support an array for the order option" do
|
1467
|
-
@c2.one_to_many :attributes, :class => @c1, :order => [:kind1, :kind2]
|
1468
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal "SELECT * FROM attributes WHERE (attributes.node_id = 1234) ORDER BY kind1, kind2"
|
1469
|
-
end
|
1470
|
-
|
1471
|
-
it "should have a dataset method for the associated object dataset" do
|
1472
|
-
@c2.one_to_many :attributes, :class => @c1
|
1473
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT * FROM attributes WHERE (attributes.node_id = 1234)'
|
1474
|
-
end
|
1475
|
-
|
1476
|
-
it "should accept a block" do
|
1477
|
-
@c2.one_to_many :attributes, :class => @c1 do |ds|
|
1478
|
-
ds.filter(:xxx => nil)
|
1479
|
-
end
|
1480
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (xxx IS NULL))'
|
1481
|
-
end
|
1482
|
-
|
1483
|
-
it "should support :order option with block" do
|
1484
|
-
@c2.one_to_many :attributes, :class => @c1, :order => :kind do |ds|
|
1485
|
-
ds.filter(:xxx => nil)
|
1486
|
-
end
|
1487
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (xxx IS NULL)) ORDER BY kind'
|
1488
|
-
end
|
1489
|
-
|
1490
|
-
it "should have the block argument affect the _dataset method" do
|
1491
|
-
@c2.one_to_many :attributes, :class => @c1 do |ds|
|
1492
|
-
ds.filter(:xxx => 456)
|
1493
|
-
end
|
1494
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (xxx = 456))'
|
1495
|
-
end
|
1496
|
-
|
1497
|
-
it "should support a :dataset option that is used instead of the default" do
|
1498
|
-
c1 = @c1
|
1499
|
-
@c2.one_to_many :all_other_attributes, :class => @c1, :dataset=>proc{c1.exclude(:nodeid=>pk)}, :order=>:a, :limit=>10 do |ds|
|
1500
|
-
ds.filter(:xxx => 5)
|
1501
|
-
end
|
1502
|
-
@c2.new(:id => 1234).all_other_attributes_dataset.sql.must_equal 'SELECT * FROM attributes WHERE ((nodeid != 1234) AND (xxx = 5)) ORDER BY a LIMIT 10'
|
1503
|
-
@c2.new(:id => 1234).all_other_attributes.must_equal [@c1.load({})]
|
1504
|
-
DB.sqls.must_equal ['SELECT * FROM attributes WHERE ((nodeid != 1234) AND (xxx = 5)) ORDER BY a LIMIT 10']
|
1505
|
-
end
|
1506
|
-
|
1507
|
-
it "should support a :limit option" do
|
1508
|
-
@c2.one_to_many :attributes, :class => @c1 , :limit=>10
|
1509
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT * FROM attributes WHERE (attributes.node_id = 1234) LIMIT 10'
|
1510
|
-
@c2.one_to_many :attributes, :class => @c1 , :limit=>[10,10]
|
1511
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT * FROM attributes WHERE (attributes.node_id = 1234) LIMIT 10 OFFSET 10'
|
1512
|
-
end
|
1513
|
-
|
1514
|
-
it "should have the :eager option affect the _dataset method" do
|
1515
|
-
@c2.one_to_many :attributes, :class => @c2 , :eager=>:attributes
|
1516
|
-
@c2.new(:id => 1234).attributes_dataset.opts[:eager].must_equal(:attributes=>nil)
|
1517
|
-
end
|
1518
|
-
|
1519
|
-
it "should populate cache when accessed" do
|
1520
|
-
@c2.one_to_many :attributes, :class => @c1
|
1521
|
-
n = @c2.new(:id => 1234)
|
1522
|
-
n.associations.include?(:attributes).must_equal false
|
1523
|
-
atts = n.attributes
|
1524
|
-
atts.must_equal n.associations[:attributes]
|
1525
|
-
DB.sqls.must_equal ['SELECT * FROM attributes WHERE (attributes.node_id = 1234)']
|
1526
|
-
end
|
1527
|
-
|
1528
|
-
it "should use cache if available" do
|
1529
|
-
@c2.one_to_many :attributes, :class => @c1
|
1530
|
-
n = @c2.new(:id => 1234)
|
1531
|
-
n.associations[:attributes] = 42
|
1532
|
-
n.attributes.must_equal 42
|
1533
|
-
DB.sqls.must_equal []
|
1534
|
-
end
|
1535
|
-
|
1536
|
-
it "should not use cache if asked to reload" do
|
1537
|
-
@c2.one_to_many :attributes, :class => @c1
|
1538
|
-
n = @c2.new(:id => 1234)
|
1539
|
-
n.associations[:attributes] = 42
|
1540
|
-
n.attributes(true).wont_equal 42
|
1541
|
-
DB.sqls.must_equal ['SELECT * FROM attributes WHERE (attributes.node_id = 1234)']
|
1542
|
-
end
|
1543
|
-
|
1544
|
-
it "should add item to cache if it exists when calling add_" do
|
1545
|
-
@c2.one_to_many :attributes, :class => @c1
|
1546
|
-
n = @c2.new(:id => 1234)
|
1547
|
-
att = @c1.load(:id => 345)
|
1548
|
-
a = []
|
1549
|
-
n.associations[:attributes] = a
|
1550
|
-
n.add_attribute(att)
|
1551
|
-
a.must_equal [att]
|
1552
|
-
end
|
1553
|
-
|
1554
|
-
it "should set object to item's reciprocal cache when calling add_" do
|
1555
|
-
@c2.one_to_many :attributes, :class => @c1
|
1556
|
-
@c1.many_to_one :node, :class => @c2
|
1557
|
-
|
1558
|
-
n = @c2.new(:id => 1234)
|
1559
|
-
att = @c1.new(:id => 345)
|
1560
|
-
n.add_attribute(att)
|
1561
|
-
att.node.must_equal n
|
1562
|
-
end
|
1563
|
-
|
1564
|
-
it "should remove item from cache if it exists when calling remove_" do
|
1565
|
-
@c2.one_to_many :attributes, :class => @c1
|
1566
|
-
|
1567
|
-
n = @c2.load(:id => 1234)
|
1568
|
-
att = @c1.load(:id => 345)
|
1569
|
-
a = [att]
|
1570
|
-
n.associations[:attributes] = a
|
1571
|
-
n.remove_attribute(att)
|
1572
|
-
a.must_equal []
|
1573
|
-
end
|
1574
|
-
|
1575
|
-
it "should remove item's reciprocal cache calling remove_" do
|
1576
|
-
@c2.one_to_many :attributes, :class => @c1
|
1577
|
-
@c1.many_to_one :node, :class => @c2
|
1578
|
-
|
1579
|
-
n = @c2.new(:id => 1234)
|
1580
|
-
att = @c1.new(:id => 345)
|
1581
|
-
att.associations[:node] = n
|
1582
|
-
att.node.must_equal n
|
1583
|
-
n.remove_attribute(att)
|
1584
|
-
att.node.must_equal nil
|
1585
|
-
end
|
1586
|
-
|
1587
|
-
it "should not create the add_, remove_, or remove_all_ methods if :read_only option is used" do
|
1588
|
-
@c2.one_to_many :attributes, :class => @c1, :read_only=>true
|
1589
|
-
im = @c2.instance_methods.collect{|x| x.to_s}
|
1590
|
-
im.must_include('attributes')
|
1591
|
-
im.must_include('attributes_dataset')
|
1592
|
-
im.wont_include('add_attribute')
|
1593
|
-
im.wont_include('remove_attribute')
|
1594
|
-
im.wont_include('remove_all_attributes')
|
1595
|
-
end
|
1596
|
-
|
1597
|
-
it "should not add associations methods directly to class" do
|
1598
|
-
@c2.one_to_many :attributes, :class => @c1
|
1599
|
-
im = @c2.instance_methods.collect{|x| x.to_s}
|
1600
|
-
im.must_include('attributes')
|
1601
|
-
im.must_include('attributes_dataset')
|
1602
|
-
im.must_include('add_attribute')
|
1603
|
-
im.must_include('remove_attribute')
|
1604
|
-
im.must_include('remove_all_attributes')
|
1605
|
-
im2 = @c2.instance_methods(false).collect{|x| x.to_s}
|
1606
|
-
im2.wont_include('attributes')
|
1607
|
-
im2.wont_include('attributes_dataset')
|
1608
|
-
im2.wont_include('add_attribute')
|
1609
|
-
im2.wont_include('remove_attribute')
|
1610
|
-
im2.wont_include('remove_all_attributes')
|
1611
|
-
end
|
1612
|
-
|
1613
|
-
it "should populate the reciprocal many_to_one cache when loading the one_to_many association" do
|
1614
|
-
@c2.one_to_many :attributes, :class => @c1, :key => :node_id
|
1615
|
-
@c1.many_to_one :node, :class => @c2, :key => :node_id
|
1616
|
-
|
1617
|
-
n = @c2.new(:id => 1234)
|
1618
|
-
atts = n.attributes
|
1619
|
-
DB.sqls.must_equal ['SELECT * FROM attributes WHERE (attributes.node_id = 1234)']
|
1620
|
-
atts.must_equal [@c1.load({})]
|
1621
|
-
atts.map{|a| a.node}.must_equal [n]
|
1622
|
-
DB.sqls.must_equal []
|
1623
|
-
end
|
1624
|
-
|
1625
|
-
it "should use an explicit :reciprocal option if given" do
|
1626
|
-
@c2.one_to_many :attributes, :class => @c1, :key => :node_id, :reciprocal=>:wxyz
|
1627
|
-
|
1628
|
-
n = @c2.new(:id => 1234)
|
1629
|
-
atts = n.attributes
|
1630
|
-
DB.sqls.must_equal ['SELECT * FROM attributes WHERE (attributes.node_id = 1234)']
|
1631
|
-
atts.must_equal [@c1.load({})]
|
1632
|
-
atts.map{|a| a.associations[:wxyz]}.must_equal [n]
|
1633
|
-
DB.sqls.must_equal []
|
1634
|
-
end
|
1635
|
-
|
1636
|
-
it "should have an remove_all_ method that removes all associated objects" do
|
1637
|
-
@c2.one_to_many :attributes, :class => @c1
|
1638
|
-
@c2.new(:id => 1234).remove_all_attributes
|
1639
|
-
DB.sqls.must_equal ['UPDATE attributes SET node_id = NULL WHERE (node_id = 1234)']
|
1640
|
-
end
|
1641
|
-
|
1642
|
-
it "should have remove_all method respect association filters" do
|
1643
|
-
@c2.one_to_many :attributes, :class => @c1, :conditions=>{:a=>1} do |ds|
|
1644
|
-
ds.filter(:b=>2)
|
1645
|
-
end
|
1646
|
-
@c2.new(:id => 1234).remove_all_attributes
|
1647
|
-
DB.sqls.must_equal ['UPDATE attributes SET node_id = NULL WHERE ((a = 1) AND (node_id = 1234) AND (b = 2))']
|
1648
|
-
end
|
1649
|
-
|
1650
|
-
it "should have the remove_all_ method respect the :primary_key option" do
|
1651
|
-
@c2.one_to_many :attributes, :class => @c1, :primary_key=>:xxx
|
1652
|
-
@c2.new(:id => 1234, :xxx=>5).remove_all_attributes
|
1653
|
-
DB.sqls.must_equal ['UPDATE attributes SET node_id = NULL WHERE (node_id = 5)']
|
1654
|
-
end
|
1655
|
-
|
1656
|
-
it "should have the remove_all_ method respect composite keys" do
|
1657
|
-
@c2.one_to_many :attributes, :class => @c1, :key=>[:node_id, :y], :primary_key=>[:id, :x]
|
1658
|
-
@c2.new(:id => 1234, :x=>5).remove_all_attributes
|
1659
|
-
sqls = DB.sqls
|
1660
|
-
sqls.pop.must_match(/UPDATE attributes SET (node_id|y) = NULL, (node_id|y) = NULL WHERE \(\(node_id = 1234\) AND \(y = 5\)\)/)
|
1661
|
-
sqls.must_equal []
|
1662
|
-
end
|
1663
|
-
|
1664
|
-
it "remove_all should set the cache to []" do
|
1665
|
-
@c2.one_to_many :attributes, :class => @c1
|
1666
|
-
node = @c2.new(:id => 1234)
|
1667
|
-
node.remove_all_attributes
|
1668
|
-
node.associations[:attributes].must_equal []
|
1669
|
-
end
|
1670
|
-
|
1671
|
-
it "remove_all should return the array of previously associated items if the cache is populated" do
|
1672
|
-
@c2.one_to_many :attributes, :class => @c1
|
1673
|
-
attrib = @c1.new(:id=>3)
|
1674
|
-
node = @c2.new(:id => 1234)
|
1675
|
-
@c1.dataset._fetch = [[], [{:id=>3, :node_id=>1234}]]
|
1676
|
-
node.attributes.must_equal []
|
1677
|
-
node.add_attribute(attrib)
|
1678
|
-
node.associations[:attributes].must_equal [attrib]
|
1679
|
-
node.remove_all_attributes.must_equal [attrib]
|
1680
|
-
end
|
1681
|
-
|
1682
|
-
it "remove_all should return nil if the cache is not populated" do
|
1683
|
-
@c2.one_to_many :attributes, :class => @c1
|
1684
|
-
@c2.new(:id => 1234).remove_all_attributes.must_equal nil
|
1685
|
-
end
|
1686
|
-
|
1687
|
-
it "remove_all should remove the current item from all reciprocal association caches if they are populated" do
|
1688
|
-
@c2.one_to_many :attributes, :class => @c1
|
1689
|
-
@c1.many_to_one :node, :class => @c2
|
1690
|
-
@c2.dataset._fetch = []
|
1691
|
-
@c1.dataset._fetch = [[], [{:id=>3, :node_id=>1234}]]
|
1692
|
-
attrib = @c1.new(:id=>3)
|
1693
|
-
node = @c2.load(:id => 1234)
|
1694
|
-
node.attributes.must_equal []
|
1695
|
-
attrib.node.must_equal nil
|
1696
|
-
node.add_attribute(attrib)
|
1697
|
-
attrib.associations[:node].must_equal node
|
1698
|
-
node.remove_all_attributes
|
1699
|
-
attrib.associations.fetch(:node, 2).must_equal nil
|
1700
|
-
end
|
1701
|
-
|
1702
|
-
it "should call an _add_ method internally to add attributes" do
|
1703
|
-
@c2.one_to_many :attributes, :class => @c1
|
1704
|
-
@c2.private_instance_methods.collect{|x| x.to_s}.sort.must_include("_add_attribute")
|
1705
|
-
p = @c2.load(:id=>10)
|
1706
|
-
c = @c1.load(:id=>123)
|
1707
|
-
def p._add_attribute(x)
|
1708
|
-
@x = x
|
1709
|
-
end
|
1710
|
-
def c._node_id=; raise; end
|
1711
|
-
p.add_attribute(c)
|
1712
|
-
p.instance_variable_get(:@x).must_equal c
|
1713
|
-
end
|
1714
|
-
|
1715
|
-
it "should support an :adder option for defining the _add_ method" do
|
1716
|
-
@c2.one_to_many :attributes, :class => @c1, :adder=>proc{|x| @x = x}
|
1717
|
-
p = @c2.load(:id=>10)
|
1718
|
-
c = @c1.load(:id=>123)
|
1719
|
-
def c._node_id=; raise; end
|
1720
|
-
p.add_attribute(c)
|
1721
|
-
p.instance_variable_get(:@x).must_equal c
|
1722
|
-
end
|
1723
|
-
|
1724
|
-
it "should allow additional arguments given to the add_ method and pass them onwards to the _add_ method" do
|
1725
|
-
@c2.one_to_many :attributes, :class => @c1
|
1726
|
-
p = @c2.load(:id=>10)
|
1727
|
-
c = @c1.load(:id=>123)
|
1728
|
-
def p._add_attribute(x,*y)
|
1729
|
-
@x = x
|
1730
|
-
@y = y
|
1731
|
-
end
|
1732
|
-
def c._node_id=; raise; end
|
1733
|
-
p.add_attribute(c,:foo,:bar=>:baz)
|
1734
|
-
p.instance_variable_get(:@x).must_equal c
|
1735
|
-
p.instance_variable_get(:@y).must_equal [:foo,{:bar=>:baz}]
|
1736
|
-
end
|
1737
|
-
|
1738
|
-
it "should call a _remove_ method internally to remove attributes" do
|
1739
|
-
@c2.one_to_many :attributes, :class => @c1
|
1740
|
-
@c2.private_instance_methods.collect{|x| x.to_s}.sort.must_include("_remove_attribute")
|
1741
|
-
p = @c2.load(:id=>10)
|
1742
|
-
c = @c1.load(:id=>123)
|
1743
|
-
def p._remove_attribute(x)
|
1744
|
-
@x = x
|
1745
|
-
end
|
1746
|
-
def c._node_id=; raise; end
|
1747
|
-
p.remove_attribute(c)
|
1748
|
-
p.instance_variable_get(:@x).must_equal c
|
1749
|
-
end
|
1750
|
-
|
1751
|
-
it "should support a :remover option for defining the _remove_ method" do
|
1752
|
-
@c2.one_to_many :attributes, :class => @c1, :remover=>proc{|x| @x = x}
|
1753
|
-
p = @c2.load(:id=>10)
|
1754
|
-
c = @c1.load(:id=>123)
|
1755
|
-
def c._node_id=; raise; end
|
1756
|
-
p.remove_attribute(c)
|
1757
|
-
p.instance_variable_get(:@x).must_equal c
|
1758
|
-
end
|
1759
|
-
|
1760
|
-
it "should allow additional arguments given to the remove_ method and pass them onwards to the _remove_ method" do
|
1761
|
-
@c2.one_to_many :attributes, :class => @c1, :reciprocal=>nil
|
1762
|
-
p = @c2.load(:id=>10)
|
1763
|
-
c = @c1.load(:id=>123)
|
1764
|
-
def p._remove_attribute(x,*y)
|
1765
|
-
@x = x
|
1766
|
-
@y = y
|
1767
|
-
end
|
1768
|
-
def c._node_id=; raise; end
|
1769
|
-
p.remove_attribute(c,:foo,:bar=>:baz)
|
1770
|
-
p.instance_variable_get(:@x).must_equal c
|
1771
|
-
p.instance_variable_get(:@y).must_equal [:foo,{:bar=>:baz}]
|
1772
|
-
end
|
1773
|
-
|
1774
|
-
it "should allow additional arguments given to the remove_all_ method and pass them onwards to the _remove_all_ method" do
|
1775
|
-
@c2.one_to_many :attributes, :class => @c1
|
1776
|
-
p = @c2.load(:id=>10)
|
1777
|
-
c = @c1.load(:id=>123)
|
1778
|
-
def p._remove_all_attributes(*y)
|
1779
|
-
@y = y
|
1780
|
-
end
|
1781
|
-
def c._node_id=; raise; end
|
1782
|
-
p.remove_all_attributes(:foo,:bar=>:baz)
|
1783
|
-
p.instance_variable_get(:@y).must_equal [:foo,{:bar=>:baz}]
|
1784
|
-
end
|
1785
|
-
|
1786
|
-
it "should call a _remove_all_ method internally to remove attributes" do
|
1787
|
-
@c2.one_to_many :attributes, :class => @c1
|
1788
|
-
@c2.private_instance_methods.collect{|x| x.to_s}.sort.must_include("_remove_all_attributes")
|
1789
|
-
p = @c2.load(:id=>10)
|
1790
|
-
def p._remove_all_attributes
|
1791
|
-
@x = :foo
|
1792
|
-
end
|
1793
|
-
p.remove_all_attributes
|
1794
|
-
p.instance_variable_get(:@x).must_equal :foo
|
1795
|
-
end
|
1796
|
-
|
1797
|
-
it "should support a :clearer option for defining the _remove_all_ method" do
|
1798
|
-
@c2.one_to_many :attributes, :class => @c1, :clearer=>proc{@x = :foo}
|
1799
|
-
p = @c2.load(:id=>10)
|
1800
|
-
p.remove_all_attributes
|
1801
|
-
p.instance_variable_get(:@x).must_equal :foo
|
1802
|
-
end
|
1803
|
-
|
1804
|
-
it "should support (before|after)_(add|remove) callbacks" do
|
1805
|
-
h = []
|
1806
|
-
@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]
|
1807
|
-
@c2.class_eval do
|
1808
|
-
self::Foo = h
|
1809
|
-
def _add_attribute(v)
|
1810
|
-
model::Foo << 4
|
1811
|
-
end
|
1812
|
-
def _remove_attribute(v)
|
1813
|
-
model::Foo << 5
|
1814
|
-
end
|
1815
|
-
def blah(x)
|
1816
|
-
model::Foo << x.pk
|
1817
|
-
end
|
1818
|
-
def blahr(x)
|
1819
|
-
model::Foo << 6
|
1820
|
-
end
|
1821
|
-
end
|
1822
|
-
p = @c2.load(:id=>10)
|
1823
|
-
c = @c1.load(:id=>123)
|
1824
|
-
h.must_equal []
|
1825
|
-
p.add_attribute(c)
|
1826
|
-
h.must_equal [10, -123, 123, 4, 3]
|
1827
|
-
p.remove_attribute(c)
|
1828
|
-
h.must_equal [10, -123, 123, 4, 3, 123, 5, 6]
|
1829
|
-
end
|
1830
|
-
|
1831
|
-
it "should support after_load association callback" do
|
1832
|
-
h = []
|
1833
|
-
@c2.one_to_many :attributes, :class => @c1, :after_load=>[proc{|x,y| h << [x.pk, y.collect{|z|z.pk}]}, :al]
|
1834
|
-
@c2.class_eval do
|
1835
|
-
self::Foo = h
|
1836
|
-
def al(v)
|
1837
|
-
v.each{|x| model::Foo << x.pk}
|
1838
|
-
end
|
1839
|
-
end
|
1840
|
-
@c1.dataset._fetch = [{:id=>20}, {:id=>30}]
|
1841
|
-
p = @c2.load(:id=>10, :parent_id=>20)
|
1842
|
-
attributes = p.attributes
|
1843
|
-
h.must_equal [[10, [20, 30]], 20, 30]
|
1844
|
-
attributes.collect{|a| a.pk}.must_equal [20, 30]
|
1845
|
-
end
|
1846
|
-
|
1847
|
-
it "should raise error and not call internal add or remove method if before callback returns false if raise_on_save_failure is true" do
|
1848
|
-
p = @c2.load(:id=>10)
|
1849
|
-
c = @c1.load(:id=>123)
|
1850
|
-
@c2.one_to_many :attributes, :class => @c1, :before_add=>:ba, :before_remove=>:br
|
1851
|
-
def p.ba(c) false end
|
1852
|
-
def p._add_attribute; raise; end
|
1853
|
-
def p._remove_attribute; raise; end
|
1854
|
-
p.associations[:attributes] = []
|
1855
|
-
proc{p.add_attribute(c)}.must_raise(Sequel::HookFailed)
|
1856
|
-
p.attributes.must_equal []
|
1857
|
-
p.associations[:attributes] = [c]
|
1858
|
-
def p.br(c) false end
|
1859
|
-
proc{p.remove_attribute(c)}.must_raise(Sequel::HookFailed)
|
1860
|
-
p.attributes.must_equal [c]
|
1861
|
-
end
|
1862
|
-
|
1863
|
-
it "should return nil and not call internal add or remove method if before callback returns false if raise_on_save_failure is false" do
|
1864
|
-
p = @c2.load(:id=>10)
|
1865
|
-
c = @c1.load(:id=>123)
|
1866
|
-
p.raise_on_save_failure = false
|
1867
|
-
@c2.one_to_many :attributes, :class => @c1, :before_add=>:ba, :before_remove=>:br
|
1868
|
-
def p.ba(c) false end
|
1869
|
-
def p._add_attribute; raise; end
|
1870
|
-
def p._remove_attribute; raise; end
|
1871
|
-
p.associations[:attributes] = []
|
1872
|
-
p.add_attribute(c).must_equal nil
|
1873
|
-
p.attributes.must_equal []
|
1874
|
-
p.associations[:attributes] = [c]
|
1875
|
-
def p.br(c) false end
|
1876
|
-
p.remove_attribute(c).must_equal nil
|
1877
|
-
p.attributes.must_equal [c]
|
1878
|
-
end
|
1879
|
-
|
1880
|
-
it "should raise error and not call internal add or remove method if before callback calls cancel_action if raise_on_save_failure is true" do
|
1881
|
-
p = @c2.load(:id=>10)
|
1882
|
-
c = @c1.load(:id=>123)
|
1883
|
-
@c2.one_to_many :attributes, :class => @c1, :before_add=>:ba, :before_remove=>:br
|
1884
|
-
def p.ba(o); cancel_action; end
|
1885
|
-
def p._add_attribute; raise; end
|
1886
|
-
def p._remove_attribute; raise; end
|
1887
|
-
p.associations[:attributes] = []
|
1888
|
-
proc{p.add_attribute(c)}.must_raise(Sequel::HookFailed)
|
1889
|
-
p.attributes.must_equal []
|
1890
|
-
p.associations[:attributes] = [c]
|
1891
|
-
def p.br(o); cancel_action; end
|
1892
|
-
proc{p.remove_attribute(c)}.must_raise(Sequel::HookFailed)
|
1893
|
-
p.attributes.must_equal [c]
|
1894
|
-
end
|
1895
|
-
|
1896
|
-
it "should return nil and not call internal add or remove method if before callback calls cancel_action if raise_on_save_failure is false" do
|
1897
|
-
p = @c2.load(:id=>10)
|
1898
|
-
c = @c1.load(:id=>123)
|
1899
|
-
p.raise_on_save_failure = false
|
1900
|
-
@c2.one_to_many :attributes, :class => @c1, :before_add=>:ba, :before_remove=>:br
|
1901
|
-
def p.ba(o); cancel_action; end
|
1902
|
-
def p._add_attribute; raise; end
|
1903
|
-
def p._remove_attribute; raise; end
|
1904
|
-
p.associations[:attributes] = []
|
1905
|
-
p.add_attribute(c).must_equal nil
|
1906
|
-
p.attributes.must_equal []
|
1907
|
-
p.associations[:attributes] = [c]
|
1908
|
-
def p.br(o); cancel_action; end
|
1909
|
-
p.remove_attribute(c).must_equal nil
|
1910
|
-
p.attributes.must_equal [c]
|
1911
|
-
end
|
1912
|
-
end
|
1913
|
-
|
1914
|
-
describe Sequel::Model, "many_to_many" do
|
1915
|
-
before do
|
1916
|
-
@c1 = Class.new(Sequel::Model(:attributes)) do
|
1917
|
-
unrestrict_primary_key
|
1918
|
-
attr_accessor :yyy
|
1919
|
-
def self.name; 'Attribute'; end
|
1920
|
-
def self.to_s; 'Attribute'; end
|
1921
|
-
columns :id, :y, :z
|
1922
|
-
end
|
1923
|
-
|
1924
|
-
@c2 = Class.new(Sequel::Model(:nodes)) do
|
1925
|
-
unrestrict_primary_key
|
1926
|
-
attr_accessor :xxx
|
1927
|
-
|
1928
|
-
def self.name; 'Node'; end
|
1929
|
-
def self.to_s; 'Node'; end
|
1930
|
-
columns :id, :x
|
1931
|
-
end
|
1932
|
-
@dataset = @c2.dataset
|
1933
|
-
@c1.dataset.autoid = 1
|
1934
|
-
|
1935
|
-
[@c1, @c2].each{|c| c.dataset._fetch = {}}
|
1936
|
-
DB.reset
|
1937
|
-
end
|
1938
|
-
|
1939
|
-
it "should raise an error if current class does not have a primary key, and :left_primary_key is not specified" do
|
1940
|
-
@c2.no_primary_key
|
1941
|
-
proc{@c2.many_to_many :attributes, :class => @c1}.must_raise(Sequel::Error)
|
1942
|
-
DB.sqls.must_equal []
|
1943
|
-
end
|
1944
|
-
|
1945
|
-
it "should raise an error if associated class does not have a primary key, and :right_primary_key is not specified" do
|
1946
|
-
@c1.no_primary_key
|
1947
|
-
@c2.many_to_many :attributes, :class => @c1
|
1948
|
-
d = @c2.new(:id => 1234)
|
1949
|
-
proc{d.attributes}.must_raise(Sequel::Error)
|
1950
|
-
DB.sqls.must_equal []
|
1951
|
-
end
|
1952
|
-
|
1953
|
-
it "should use implicit key values and join table if omitted" do
|
1954
|
-
@c2.many_to_many :attributes, :class => @c1
|
1955
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
|
1956
|
-
end
|
1957
|
-
|
1958
|
-
it "should use implicit key values and join table if omitted" do
|
1959
|
-
@c2.one_through_one :attribute, :class => @c1
|
1960
|
-
@c2.new(:id => 1234).attribute_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 1'
|
1961
|
-
end
|
1962
|
-
|
1963
|
-
it "should use implicit class if omitted" do
|
1964
|
-
begin
|
1965
|
-
class ::Tag < Sequel::Model; end
|
1966
|
-
@c2.many_to_many :tags
|
1967
|
-
@c2.new(:id => 1234).tags_dataset.sql.must_equal 'SELECT tags.* FROM tags INNER JOIN nodes_tags ON (nodes_tags.tag_id = tags.id) WHERE (nodes_tags.node_id = 1234)'
|
1968
|
-
ensure
|
1969
|
-
Object.send(:remove_const, :Tag)
|
1970
|
-
end
|
1971
|
-
end
|
1972
|
-
|
1973
|
-
it "should use class inside module if given as a string" do
|
1974
|
-
begin
|
1975
|
-
module ::Historical
|
1976
|
-
class Tag < Sequel::Model; end
|
1977
|
-
end
|
1978
|
-
@c2.many_to_many :tags, :class=>'::Historical::Tag'
|
1979
|
-
@c2.new(:id => 1234).tags_dataset.sql.must_equal 'SELECT tags.* FROM tags INNER JOIN nodes_tags ON (nodes_tags.tag_id = tags.id) WHERE (nodes_tags.node_id = 1234)'
|
1980
|
-
ensure
|
1981
|
-
Object.send(:remove_const, :Historical)
|
1982
|
-
end
|
1983
|
-
end
|
1984
|
-
|
1985
|
-
it "should not override a selection consisting completely of qualified columns using Sequel::SQL::QualifiedIdentifier" do
|
1986
|
-
@c1.dataset = @c1.dataset.select(Sequel.qualify(:attributes, :id), Sequel.qualify(:attributes, :b))
|
1987
|
-
@c2.many_to_many :attributes, :class => @c1
|
1988
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT attributes.id, attributes.b FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
|
1989
|
-
end
|
1990
|
-
|
1991
|
-
it "should not override a selection consisting completely of qualified columns using symbols" do
|
1992
|
-
@c1.dataset = @c1.dataset.select(:attributes__id, :attributes__b)
|
1993
|
-
@c2.many_to_many :attributes, :class => @c1
|
1994
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT attributes.id, attributes.b FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
|
1995
|
-
end
|
1996
|
-
|
1997
|
-
it "should not override a selection consisting completely of qualified columns using Sequel::SQL::AliasedExpression" do
|
1998
|
-
@c1.dataset = @c1.dataset.select(Sequel.qualify(:attributes, :id).as(:a), Sequel.as(:attributes__b, :c))
|
1999
|
-
@c2.many_to_many :attributes, :class => @c1
|
2000
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT attributes.id AS a, attributes.b AS c FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
|
2001
|
-
end
|
2002
|
-
|
2003
|
-
it "should override a selection consisting of non qualified columns" do
|
2004
|
-
@c1.dataset = @c1.dataset.select{foo(:bar)}
|
2005
|
-
@c2.many_to_many :attributes, :class => @c1
|
2006
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
|
2007
|
-
end
|
2008
|
-
|
2009
|
-
it "should respect :eager_loader_predicate_key when lazily loading" do
|
2010
|
-
@c2.many_to_many :attributes, :class => @c1, :eager_loading_predicate_key=>Sequel.subscript(:attributes_nodes__node_id, 0)
|
2011
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id[0] = 1234)'
|
2012
|
-
end
|
2013
|
-
|
2014
|
-
it "should use explicit key values and join table if given" do
|
2015
|
-
@c2.many_to_many :attributes, :class => @c1, :left_key => :nodeid, :right_key => :attributeid, :join_table => :attribute2node
|
2016
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attribute2node ON (attribute2node.attributeid = attributes.id) WHERE (attribute2node.nodeid = 1234)'
|
2017
|
-
end
|
2018
|
-
|
2019
|
-
it "should support a conditions option" do
|
2020
|
-
@c2.many_to_many :attributes, :class => @c1, :conditions => {:a=>32}
|
2021
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((a = 32) AND (attributes_nodes.node_id = 1234))'
|
2022
|
-
|
2023
|
-
@c2.many_to_many :attributes, :class => @c1, :conditions => ['a = ?', 32]
|
2024
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((a = 32) AND (attributes_nodes.node_id = 1234))'
|
2025
|
-
@c2.new(:id => 1234).attributes.must_equal [@c1.load({})]
|
2026
|
-
end
|
2027
|
-
|
2028
|
-
it "should support an order option" do
|
2029
|
-
@c2.many_to_many :attributes, :class => @c1, :order => :blah
|
2030
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) ORDER BY blah'
|
2031
|
-
end
|
2032
|
-
|
2033
|
-
it "should support an array for the order option" do
|
2034
|
-
@c2.many_to_many :attributes, :class => @c1, :order => [:blah1, :blah2]
|
2035
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) ORDER BY blah1, blah2'
|
2036
|
-
end
|
2037
|
-
|
2038
|
-
it "should support :left_primary_key and :right_primary_key options" do
|
2039
|
-
@c2.many_to_many :attributes, :class => @c1, :left_primary_key=>:xxx, :right_primary_key=>:yyy
|
2040
|
-
@c2.new(:id => 1234, :xxx=>5).attributes_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.yyy) WHERE (attributes_nodes.node_id = 5)'
|
2041
|
-
end
|
2042
|
-
|
2043
|
-
it "should support composite keys" do
|
2044
|
-
@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]
|
2045
|
-
@c2.load(:id => 1234, :x=>5).attributes_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.r1 = attributes.id) AND (attributes_nodes.r2 = attributes.y)) WHERE ((attributes_nodes.l1 = 1234) AND (attributes_nodes.l2 = 5))'
|
2046
|
-
end
|
2047
|
-
|
2048
|
-
it "should not issue query if not all keys have values" do
|
2049
|
-
@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]
|
2050
|
-
@c2.load(:id => 1234, :x=>nil).attributes.must_equal []
|
2051
|
-
DB.sqls.must_equal []
|
2052
|
-
end
|
2053
|
-
|
2054
|
-
it "should raise an Error unless same number of composite keys used" do
|
2055
|
-
proc{@c2.many_to_many :attributes, :class => @c1, :left_key=>[:node_id, :id]}.must_raise(Sequel::Error)
|
2056
|
-
proc{@c2.many_to_many :attributes, :class => @c1, :left_primary_key=>[:node_id, :id]}.must_raise(Sequel::Error)
|
2057
|
-
proc{@c2.many_to_many :attributes, :class => @c1, :left_key=>[:node_id, :id], :left_primary_key=>:id}.must_raise(Sequel::Error)
|
2058
|
-
proc{@c2.many_to_many :attributes, :class => @c1, :left_key=>:id, :left_primary_key=>[:node_id, :id]}.must_raise(Sequel::Error)
|
2059
|
-
proc{@c2.many_to_many :attributes, :class => @c1, :left_key=>[:node_id, :id, :x], :left_primary_key=>[:parent_id, :id]}.must_raise(Sequel::Error)
|
2060
|
-
|
2061
|
-
proc{@c2.many_to_many :attributes, :class => @c1, :right_primary_key=>[:node_id, :id]}.must_raise(Sequel::Error)
|
2062
|
-
proc{@c2.many_to_many :attributes, :class => @c1, :right_key=>[:node_id, :id], :right_primary_key=>:id}.must_raise(Sequel::Error)
|
2063
|
-
proc{@c2.many_to_many :attributes, :class => @c1, :right_key=>:id, :left_primary_key=>[:node_id, :id]}.must_raise(Sequel::Error)
|
2064
|
-
proc{@c2.many_to_many :attributes, :class => @c1, :right_key=>[:node_id, :id, :x], :right_primary_key=>[:parent_id, :id]}.must_raise(Sequel::Error)
|
2065
|
-
end
|
2066
|
-
|
2067
|
-
it "should support a select option" do
|
2068
|
-
@c2.many_to_many :attributes, :class => @c1, :select => :blah
|
2069
|
-
|
2070
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT blah FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
|
2071
|
-
end
|
2072
|
-
|
2073
|
-
it "should support an array for the select option" do
|
2074
|
-
@c2.many_to_many :attributes, :class => @c1, :select => [Sequel::SQL::ColumnAll.new(:attributes), :attribute_nodes__blah2]
|
2075
|
-
|
2076
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT attributes.*, attribute_nodes.blah2 FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
|
2077
|
-
end
|
2078
|
-
|
2079
|
-
it "should accept a block" do
|
2080
|
-
@c2.many_to_many :attributes, :class => @c1 do |ds|
|
2081
|
-
ds.filter(:xxx => @xxx)
|
2082
|
-
end
|
2083
|
-
|
2084
|
-
n = @c2.new(:id => 1234)
|
2085
|
-
n.xxx = 555
|
2086
|
-
n.attributes_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((attributes_nodes.node_id = 1234) AND (xxx = 555))'
|
2087
|
-
end
|
2088
|
-
|
2089
|
-
it "should allow the :order option while accepting a block" do
|
2090
|
-
@c2.many_to_many :attributes, :class => @c1, :order=>[:blah1, :blah2] do |ds|
|
2091
|
-
ds.filter(:xxx => @xxx)
|
2092
|
-
end
|
2093
|
-
|
2094
|
-
n = @c2.new(:id => 1234)
|
2095
|
-
n.xxx = 555
|
2096
|
-
n.attributes_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((attributes_nodes.node_id = 1234) AND (xxx = 555)) ORDER BY blah1, blah2'
|
2097
|
-
end
|
2098
|
-
|
2099
|
-
it "should support a :dataset option that is used instead of the default" do
|
2100
|
-
c1 = @c1
|
2101
|
-
@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|
|
2102
|
-
ds.filter(:xxx => @xxx)
|
2103
|
-
end
|
2104
|
-
|
2105
|
-
n = @c2.new(:id => 1234)
|
2106
|
-
n.xxx = 555
|
2107
|
-
n.attributes_dataset.sql.must_equal 'SELECT * FROM attributes NATURAL JOIN an WHERE ((an.nodeid = 1234) AND (xxx = 555)) ORDER BY a LIMIT 10'
|
2108
|
-
n.attributes.must_equal [@c1.load({})]
|
2109
|
-
DB.sqls.must_equal ['SELECT * FROM attributes NATURAL JOIN an WHERE ((an.nodeid = 1234) AND (xxx = 555)) ORDER BY a LIMIT 10']
|
2110
|
-
end
|
2111
|
-
|
2112
|
-
it "should support a :dataset option that accepts the reflection as an argument" do
|
2113
|
-
@c2.many_to_many :attributes, :class => @c1, :dataset=>lambda{|opts| opts.associated_class.natural_join(:an).filter(:an__nodeid=>pk)}, :order=> :a, :limit=>10, :select=>nil do |ds|
|
2114
|
-
ds.filter(:xxx => @xxx)
|
2115
|
-
end
|
2116
|
-
|
2117
|
-
n = @c2.new(:id => 1234)
|
2118
|
-
n.xxx = 555
|
2119
|
-
n.attributes_dataset.sql.must_equal 'SELECT * FROM attributes NATURAL JOIN an WHERE ((an.nodeid = 1234) AND (xxx = 555)) ORDER BY a LIMIT 10'
|
2120
|
-
n.attributes.must_equal [@c1.load({})]
|
2121
|
-
DB.sqls.must_equal ['SELECT * FROM attributes NATURAL JOIN an WHERE ((an.nodeid = 1234) AND (xxx = 555)) ORDER BY a LIMIT 10']
|
2122
|
-
end
|
2123
|
-
|
2124
|
-
it "should support a :limit option" do
|
2125
|
-
@c2.many_to_many :attributes, :class => @c1 , :limit=>10
|
2126
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 10'
|
2127
|
-
@c2.many_to_many :attributes, :class => @c1 , :limit=>[10, 10]
|
2128
|
-
@c2.new(:id => 1234).attributes_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 10 OFFSET 10'
|
2129
|
-
end
|
2130
|
-
|
2131
|
-
it "should have the :eager option affect the _dataset method" do
|
2132
|
-
@c2.many_to_many :attributes, :class => @c2 , :eager=>:attributes
|
2133
|
-
@c2.new(:id => 1234).attributes_dataset.opts[:eager].must_equal(:attributes=>nil)
|
2134
|
-
end
|
2135
|
-
|
2136
|
-
it "should handle an aliased join table" do
|
2137
|
-
@c2.many_to_many :attributes, :class => @c1, :join_table => :attribute2node___attributes_nodes
|
2138
|
-
n = @c2.load(:id => 1234)
|
2139
|
-
a = @c1.load(:id => 2345)
|
2140
|
-
n.attributes_dataset.sql.must_equal "SELECT attributes.* FROM attributes INNER JOIN attribute2node AS attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)"
|
2141
|
-
a.must_equal n.add_attribute(a)
|
2142
|
-
a.must_equal n.remove_attribute(a)
|
2143
|
-
n.remove_all_attributes
|
2144
|
-
sqls = DB.sqls
|
2145
|
-
['INSERT INTO attribute2node (node_id, attribute_id) VALUES (1234, 2345)',
|
2146
|
-
'INSERT INTO attribute2node (attribute_id, node_id) VALUES (2345, 1234)'].must_include(sqls.shift)
|
2147
|
-
["DELETE FROM attribute2node WHERE ((node_id = 1234) AND (attribute_id = 2345))",
|
2148
|
-
"DELETE FROM attribute2node WHERE ((attribute_id = 2345) AND (node_id = 1234))"].must_include(sqls.shift)
|
2149
|
-
sqls.must_equal ["DELETE FROM attribute2node WHERE (node_id = 1234)"]
|
2150
|
-
end
|
2151
|
-
|
2152
|
-
it "should define an add_ method that works on existing records" do
|
2153
|
-
@c2.many_to_many :attributes, :class => @c1
|
2154
|
-
|
2155
|
-
n = @c2.load(:id => 1234)
|
2156
|
-
a = @c1.load(:id => 2345)
|
2157
|
-
n.add_attribute(a).must_equal a
|
2158
|
-
sqls = DB.sqls
|
2159
|
-
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 2345)',
|
2160
|
-
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (2345, 1234)'].must_include(sqls.shift)
|
2161
|
-
sqls.must_equal []
|
2162
|
-
end
|
2163
|
-
|
2164
|
-
it "should define an add_ method that works with a primary key" do
|
2165
|
-
@c2.many_to_many :attributes, :class => @c1
|
2166
|
-
|
2167
|
-
n = @c2.load(:id => 1234)
|
2168
|
-
a = @c1.load(:id => 2345)
|
2169
|
-
@c1.dataset._fetch = {:id=>2345}
|
2170
|
-
n.add_attribute(2345).must_equal a
|
2171
|
-
sqls = DB.sqls
|
2172
|
-
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 2345)',
|
2173
|
-
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (2345, 1234)'].must_include(sqls.pop)
|
2174
|
-
sqls.must_equal ["SELECT * FROM attributes WHERE id = 2345"]
|
2175
|
-
end
|
2176
|
-
|
2177
|
-
it "should raise an error if the primary key passed to the add_ method does not match an existing record" do
|
2178
|
-
@c2.many_to_many :attributes, :class => @c1
|
2179
|
-
|
2180
|
-
n = @c2.load(:id => 1234)
|
2181
|
-
@c1.dataset._fetch = []
|
2182
|
-
proc{n.add_attribute(2345)}.must_raise(Sequel::NoMatchingRow)
|
2183
|
-
DB.sqls.must_equal ["SELECT * FROM attributes WHERE id = 2345"]
|
2184
|
-
end
|
2185
|
-
|
2186
|
-
it "should allow passing a hash to the add_ method which creates a new record" do
|
2187
|
-
@c2.many_to_many :attributes, :class => @c1
|
2188
|
-
|
2189
|
-
n = @c2.load(:id => 1234)
|
2190
|
-
@c1.dataset._fetch = @c1.instance_dataset._fetch = {:id=>1}
|
2191
|
-
n.add_attribute(:id => 1).must_equal @c1.load(:id => 1)
|
2192
|
-
sqls = DB.sqls
|
2193
|
-
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 1)',
|
2194
|
-
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (1, 1234)'
|
2195
|
-
].must_include(sqls.pop)
|
2196
|
-
sqls.must_equal ['INSERT INTO attributes (id) VALUES (1)', "SELECT * FROM attributes WHERE (id = 1) LIMIT 1"]
|
2197
|
-
end
|
2198
|
-
|
2199
|
-
it "should define a remove_ method that works on existing records" do
|
2200
|
-
@c2.many_to_many :attributes, :class => @c1
|
2201
|
-
|
2202
|
-
n = @c2.new(:id => 1234)
|
2203
|
-
a = @c1.new(:id => 2345)
|
2204
|
-
n.remove_attribute(a).must_equal a
|
2205
|
-
DB.sqls.must_equal ['DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (attribute_id = 2345))']
|
2206
|
-
end
|
2207
|
-
|
2208
|
-
it "should raise an error in the add_ method if the passed associated object is not of the correct type" do
|
2209
|
-
@c2.many_to_many :attributes, :class => @c1
|
2210
|
-
proc{@c2.new(:id => 1234).add_attribute(@c2.new)}.must_raise(Sequel::Error)
|
2211
|
-
end
|
2212
|
-
|
2213
|
-
it "should accept a primary key for the remove_ method and remove an existing record" do
|
2214
|
-
@c2.many_to_many :attributes, :class => @c1
|
2215
|
-
n = @c2.new(:id => 1234)
|
2216
|
-
@c1.dataset._fetch = {:id=>234}
|
2217
|
-
n.remove_attribute(234).must_equal @c1.load(:id => 234)
|
2218
|
-
DB.sqls.must_equal ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((attributes_nodes.node_id = 1234) AND (attributes.id = 234)) LIMIT 1",
|
2219
|
-
"DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (attribute_id = 234))"]
|
2220
|
-
end
|
2221
|
-
|
2222
|
-
it "should raise an error in the remove_ method if the passed associated object is not of the correct type" do
|
2223
|
-
@c2.many_to_many :attributes, :class => @c1
|
2224
|
-
proc{@c2.new(:id => 1234).remove_attribute(@c2.new)}.must_raise(Sequel::Error)
|
2225
|
-
end
|
2226
|
-
|
2227
|
-
it "should have the add_ method respect the :left_primary_key and :right_primary_key options" do
|
2228
|
-
@c2.many_to_many :attributes, :class => @c1, :left_primary_key=>:xxx, :right_primary_key=>:yyy
|
2229
|
-
|
2230
|
-
n = @c2.load(:id => 1234).set(:xxx=>5)
|
2231
|
-
a = @c1.load(:id => 2345).set(:yyy=>8)
|
2232
|
-
n.add_attribute(a).must_equal a
|
2233
|
-
sqls = DB.sqls
|
2234
|
-
['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (5, 8)',
|
2235
|
-
'INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (8, 5)'
|
2236
|
-
].must_include(sqls.pop)
|
2237
|
-
sqls.must_equal []
|
2238
|
-
end
|
2239
|
-
|
2240
|
-
it "should have add_ method not add the same object to the cached association array if the object is already in the array" do
|
2241
|
-
@c2.many_to_many :attributes, :class => @c1
|
2242
|
-
|
2243
|
-
n = @c2.load(:id => 1234).set(:xxx=>5)
|
2244
|
-
a = @c1.load(:id => 2345).set(:yyy=>8)
|
2245
|
-
n.associations[:attributes] = []
|
2246
|
-
a.must_equal n.add_attribute(a)
|
2247
|
-
a.must_equal n.add_attribute(a)
|
2248
|
-
n.attributes.must_equal [a]
|
2249
|
-
end
|
2250
|
-
|
2251
|
-
it "should have the add_ method respect composite keys" do
|
2252
|
-
@c2.many_to_many :attributes, :class => @c1, :left_key=>[:l1, :l2], :right_key=>[:r1, :r2], :left_primary_key=>[:id, :x], :right_primary_key=>[:id, :z]
|
2253
|
-
n = @c2.load(:id => 1234, :x=>5)
|
2254
|
-
a = @c1.load(:id => 2345, :z=>8)
|
2255
|
-
a.must_equal n.add_attribute(a)
|
2256
|
-
sqls = DB.sqls
|
2257
|
-
m = /INSERT INTO attributes_nodes \((\w+), (\w+), (\w+), (\w+)\) VALUES \((\d+), (\d+), (\d+), (\d+)\)/.match(sqls.pop)
|
2258
|
-
sqls.must_equal []
|
2259
|
-
m.wont_equal nil
|
2260
|
-
map = {'l1'=>1234, 'l2'=>5, 'r1'=>2345, 'r2'=>8}
|
2261
|
-
%w[l1 l2 r1 r2].each do |x|
|
2262
|
-
v = false
|
2263
|
-
4.times do |i| i += 1
|
2264
|
-
if m[i] == x
|
2265
|
-
m[i+4].must_equal map[x].to_s
|
2266
|
-
v = true
|
2267
|
-
end
|
2268
|
-
end
|
2269
|
-
v.must_equal true
|
2270
|
-
end
|
2271
|
-
end
|
2272
|
-
|
2273
|
-
it "should have the add_ method respect composite keys" do
|
2274
|
-
@c2.many_to_many :attributes, :class => @c1, :left_key=>[:l1, :l2], :right_key=>[:r1, :r2], :left_primary_key=>[:id, :x], :right_primary_key=>[:id, :z]
|
2275
|
-
@c1.set_primary_key [:id, :z]
|
2276
|
-
n = @c2.load(:id => 1234, :x=>5)
|
2277
|
-
a = @c1.load(:id => 2345, :z=>8)
|
2278
|
-
@c1.dataset._fetch = {:id => 2345, :z=>8}
|
2279
|
-
n.add_attribute([2345, 8]).must_equal a
|
2280
|
-
sqls = DB.sqls
|
2281
|
-
sqls.shift.must_match(/SELECT \* FROM attributes WHERE \(\((id|z) = (8|2345)\) AND \((id|z) = (8|2345)\)\) LIMIT 1/)
|
2282
|
-
sqls.pop.must_match(/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)\)/)
|
2283
|
-
sqls.must_equal []
|
2284
|
-
end
|
2285
|
-
|
2286
|
-
it "should have the remove_ method respect the :left_primary_key and :right_primary_key options" do
|
2287
|
-
@c2.many_to_many :attributes, :class => @c1, :left_primary_key=>:xxx, :right_primary_key=>:yyy
|
2288
|
-
|
2289
|
-
n = @c2.new(:id => 1234, :xxx=>5)
|
2290
|
-
a = @c1.new(:id => 2345, :yyy=>8)
|
2291
|
-
n.remove_attribute(a).must_equal a
|
2292
|
-
DB.sqls.must_equal ['DELETE FROM attributes_nodes WHERE ((node_id = 5) AND (attribute_id = 8))']
|
2293
|
-
end
|
2294
|
-
|
2295
|
-
it "should have the remove_ method respect composite keys" do
|
2296
|
-
@c2.many_to_many :attributes, :class => @c1, :left_key=>[:l1, :l2], :right_key=>[:r1, :r2], :left_primary_key=>[:id, :x], :right_primary_key=>[:id, :z]
|
2297
|
-
n = @c2.load(:id => 1234, :x=>5)
|
2298
|
-
a = @c1.load(:id => 2345, :z=>8)
|
2299
|
-
a.must_equal n.remove_attribute(a)
|
2300
|
-
DB.sqls.must_equal ["DELETE FROM attributes_nodes WHERE ((l1 = 1234) AND (l2 = 5) AND (r1 = 2345) AND (r2 = 8))"]
|
2301
|
-
end
|
2302
|
-
|
2303
|
-
it "should accept a array of composite primary key values for the remove_ method and remove an existing record" do
|
2304
|
-
@c1.set_primary_key [:id, :y]
|
2305
|
-
@c2.many_to_many :attributes, :class => @c1
|
2306
|
-
n = @c2.new(:id => 1234)
|
2307
|
-
@c1.dataset._fetch = {:id=>234, :y=>8}
|
2308
|
-
@c1.load(:id => 234, :y=>8).must_equal n.remove_attribute([234, 8])
|
2309
|
-
sqls = DB.sqls
|
2310
|
-
["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((attributes_nodes.node_id = 1234) AND (attributes.id = 234) AND (attributes.y = 8)) LIMIT 1",
|
2311
|
-
"SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((attributes_nodes.node_id = 1234) AND (attributes.y = 8) AND (attributes.id = 234)) LIMIT 1"].must_include(sqls.shift)
|
2312
|
-
sqls.must_equal ["DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (attribute_id = 234))"]
|
2313
|
-
end
|
2314
|
-
|
2315
|
-
it "should raise an error if the model object doesn't have a valid primary key" do
|
2316
|
-
@c2.many_to_many :attributes, :class => @c1
|
2317
|
-
a = @c2.new
|
2318
|
-
n = @c1.load(:id=>123)
|
2319
|
-
proc{a.attributes_dataset}.must_raise(Sequel::Error)
|
2320
|
-
proc{a.add_attribute(n)}.must_raise(Sequel::Error)
|
2321
|
-
proc{a.remove_attribute(n)}.must_raise(Sequel::Error)
|
2322
|
-
proc{a.remove_all_attributes}.must_raise(Sequel::Error)
|
2323
|
-
end
|
2324
|
-
|
2325
|
-
it "should save the associated object first in add_ if passed a new model object" do
|
2326
|
-
@c2.many_to_many :attributes, :class => @c1
|
2327
|
-
n = @c1.new
|
2328
|
-
a = @c2.load(:id=>123)
|
2329
|
-
n.new?.must_equal true
|
2330
|
-
@c1.dataset._fetch = {:id=>1}
|
2331
|
-
a.add_attribute(n)
|
2332
|
-
n.new?.must_equal false
|
2333
|
-
end
|
2334
|
-
|
2335
|
-
it "should raise a ValidationFailed in add_ if the associated object is new and invalid" do
|
2336
|
-
@c2.many_to_many :attributes, :class => @c1
|
2337
|
-
n = @c1.new
|
2338
|
-
a = @c2.load(:id=>123)
|
2339
|
-
def n.validate() errors.add(:id, 'foo') end
|
2340
|
-
proc{a.add_attribute(n)}.must_raise(Sequel::ValidationFailed)
|
2341
|
-
end
|
2342
|
-
|
2343
|
-
it "should raise an Error in add_ if the associated object is new and invalid and raise_on_save_failure is false" do
|
2344
|
-
@c2.many_to_many :attributes, :class => @c1
|
2345
|
-
n = @c1.new
|
2346
|
-
n.raise_on_save_failure = false
|
2347
|
-
a = @c2.load(:id=>123)
|
2348
|
-
def n.validate() errors.add(:id, 'foo') end
|
2349
|
-
proc{a.add_attribute(n)}.must_raise(Sequel::Error)
|
2350
|
-
end
|
2351
|
-
|
2352
|
-
it "should not attempt to validate the associated object in add_ if the :validate=>false option is used" do
|
2353
|
-
@c2.many_to_many :attributes, :class => @c1, :validate=>false
|
2354
|
-
n = @c1.new
|
2355
|
-
a = @c2.load(:id=>123)
|
2356
|
-
def n.validate() errors.add(:id, 'foo') end
|
2357
|
-
@c1.dataset._fetch = {:id=>1}
|
2358
|
-
a.add_attribute(n)
|
2359
|
-
n.new?.must_equal false
|
2360
|
-
end
|
2361
|
-
|
2362
|
-
it "should raise an error if trying to remove a model object that doesn't have a valid primary key" do
|
2363
|
-
@c2.many_to_many :attributes, :class => @c1
|
2364
|
-
n = @c1.new
|
2365
|
-
a = @c2.load(:id=>123)
|
2366
|
-
proc{a.remove_attribute(n)}.must_raise(Sequel::Error)
|
2367
|
-
end
|
2368
|
-
|
2369
|
-
it "should provide an array with all members of the association" do
|
2370
|
-
@c2.many_to_many :attributes, :class => @c1
|
2371
|
-
|
2372
|
-
@c2.new(:id => 1234).attributes.must_equal [@c1.load({})]
|
2373
|
-
DB.sqls.must_equal ['SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)']
|
2374
|
-
end
|
2375
|
-
|
2376
|
-
it "should populate cache when accessed" do
|
2377
|
-
@c2.many_to_many :attributes, :class => @c1
|
2378
|
-
|
2379
|
-
n = @c2.new(:id => 1234)
|
2380
|
-
n.associations.include?(:attributes).must_equal false
|
2381
|
-
atts = n.attributes
|
2382
|
-
atts.must_equal n.associations[:attributes]
|
2383
|
-
end
|
2384
|
-
|
2385
|
-
it "should use cache if available" do
|
2386
|
-
@c2.many_to_many :attributes, :class => @c1
|
2387
|
-
|
2388
|
-
n = @c2.new(:id => 1234)
|
2389
|
-
n.associations[:attributes] = 42
|
2390
|
-
n.attributes.must_equal 42
|
2391
|
-
DB.sqls.must_equal []
|
2392
|
-
end
|
2393
|
-
|
2394
|
-
it "should not use cache if asked to reload" do
|
2395
|
-
@c2.many_to_many :attributes, :class => @c1
|
2396
|
-
|
2397
|
-
n = @c2.new(:id => 1234)
|
2398
|
-
n.associations[:attributes] = 42
|
2399
|
-
n.attributes(true).wont_equal 42
|
2400
|
-
DB.sqls.must_equal ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)"]
|
2401
|
-
end
|
2402
|
-
|
2403
|
-
it "should add item to cache if it exists when calling add_" do
|
2404
|
-
@c2.many_to_many :attributes, :class => @c1
|
2405
|
-
|
2406
|
-
n = @c2.new(:id => 1234)
|
2407
|
-
att = @c1.load(:id => 345)
|
2408
|
-
a = []
|
2409
|
-
n.associations[:attributes] = a
|
2410
|
-
n.add_attribute(att)
|
2411
|
-
a.must_equal [att]
|
2412
|
-
end
|
2413
|
-
|
2414
|
-
it "should add item to reciprocal's cache if it exists when calling add_" do
|
2415
|
-
@c2.many_to_many :attributes, :class => @c1
|
2416
|
-
@c1.many_to_many :nodes, :class => @c2
|
2417
|
-
|
2418
|
-
n = @c2.new(:id => 1234)
|
2419
|
-
att = @c1.load(:id => 345)
|
2420
|
-
att.associations[:nodes] = []
|
2421
|
-
n.add_attribute(att)
|
2422
|
-
att.nodes.must_equal [n]
|
2423
|
-
end
|
2424
|
-
|
2425
|
-
it "should remove item from cache if it exists when calling remove_" do
|
2426
|
-
@c2.many_to_many :attributes, :class => @c1
|
2427
|
-
|
2428
|
-
n = @c2.new(:id => 1234)
|
2429
|
-
att = @c1.load(:id => 345)
|
2430
|
-
a = [att]
|
2431
|
-
n.associations[:attributes] = a
|
2432
|
-
n.remove_attribute(att)
|
2433
|
-
a.must_equal []
|
2434
|
-
end
|
2435
|
-
|
2436
|
-
it "should remove item from reciprocal's if it exists when calling remove_" do
|
2437
|
-
@c2.many_to_many :attributes, :class => @c1
|
2438
|
-
@c1.many_to_many :nodes, :class => @c2
|
2439
|
-
|
2440
|
-
n = @c2.new(:id => 1234)
|
2441
|
-
att = @c1.new(:id => 345)
|
2442
|
-
att.associations[:nodes] = [n]
|
2443
|
-
n.remove_attribute(att)
|
2444
|
-
att.nodes.must_equal []
|
2445
|
-
end
|
2446
|
-
|
2447
|
-
it "should not create the add_, remove_, or remove_all_ methods if :read_only option is used" do
|
2448
|
-
@c2.many_to_many :attributes, :class => @c1, :read_only=>true
|
2449
|
-
im = @c2.instance_methods.collect{|x| x.to_s}
|
2450
|
-
im.must_include('attributes')
|
2451
|
-
im.must_include('attributes_dataset')
|
2452
|
-
im.wont_include('add_attribute')
|
2453
|
-
im.wont_include('remove_attribute')
|
2454
|
-
im.wont_include('remove_all_attributes')
|
2455
|
-
end
|
2456
|
-
|
2457
|
-
it "should not add associations methods directly to class" do
|
2458
|
-
@c2.many_to_many :attributes, :class => @c1
|
2459
|
-
im = @c2.instance_methods.collect{|x| x.to_s}
|
2460
|
-
im.must_include('attributes')
|
2461
|
-
im.must_include('attributes_dataset')
|
2462
|
-
im.must_include('add_attribute')
|
2463
|
-
im.must_include('remove_attribute')
|
2464
|
-
im.must_include('remove_all_attributes')
|
2465
|
-
im2 = @c2.instance_methods(false).collect{|x| x.to_s}
|
2466
|
-
im2.wont_include('attributes')
|
2467
|
-
im2.wont_include('attributes_dataset')
|
2468
|
-
im2.wont_include('add_attribute')
|
2469
|
-
im2.wont_include('remove_attribute')
|
2470
|
-
im2.wont_include('remove_all_attributes')
|
2471
|
-
end
|
2472
|
-
|
2473
|
-
it "should have an remove_all_ method that removes all associations" do
|
2474
|
-
@c2.many_to_many :attributes, :class => @c1
|
2475
|
-
@c2.new(:id => 1234).remove_all_attributes
|
2476
|
-
DB.sqls.must_equal ['DELETE FROM attributes_nodes WHERE (node_id = 1234)']
|
2477
|
-
end
|
2478
|
-
|
2479
|
-
it "should have the remove_all_ method respect the :left_primary_key option" do
|
2480
|
-
@c2.many_to_many :attributes, :class => @c1, :left_primary_key=>:xxx
|
2481
|
-
@c2.new(:id => 1234, :xxx=>5).remove_all_attributes
|
2482
|
-
DB.sqls.must_equal ['DELETE FROM attributes_nodes WHERE (node_id = 5)']
|
2483
|
-
end
|
2484
|
-
|
2485
|
-
it "should have the remove_all_ method respect composite keys" do
|
2486
|
-
@c2.many_to_many :attributes, :class => @c1, :left_primary_key=>[:id, :x], :left_key=>[:l1, :l2]
|
2487
|
-
@c2.load(:id => 1234, :x=>5).remove_all_attributes
|
2488
|
-
DB.sqls.must_equal ['DELETE FROM attributes_nodes WHERE ((l1 = 1234) AND (l2 = 5))']
|
2489
|
-
end
|
2490
|
-
|
2491
|
-
it "remove_all should set the cached instance variable to []" do
|
2492
|
-
@c2.many_to_many :attributes, :class => @c1
|
2493
|
-
node = @c2.new(:id => 1234)
|
2494
|
-
node.remove_all_attributes
|
2495
|
-
node.associations[:attributes].must_equal []
|
2496
|
-
end
|
2497
|
-
|
2498
|
-
it "remove_all should return the array of previously associated items if the cached instance variable exists" do
|
2499
|
-
@c2.many_to_many :attributes, :class => @c1
|
2500
|
-
attrib = @c1.load(:id=>3)
|
2501
|
-
node = @c2.load(:id => 1234)
|
2502
|
-
@c1.dataset._fetch = []
|
2503
|
-
node.attributes.must_equal []
|
2504
|
-
node.add_attribute(attrib)
|
2505
|
-
node.associations[:attributes].must_equal [attrib]
|
2506
|
-
node.remove_all_attributes.must_equal [attrib]
|
2507
|
-
end
|
2508
|
-
|
2509
|
-
it "remove_all should return nil if the cached instance variable does not exist" do
|
2510
|
-
@c2.many_to_many :attributes, :class => @c1
|
2511
|
-
@c2.new(:id => 1234).remove_all_attributes.must_equal nil
|
2512
|
-
end
|
2513
|
-
|
2514
|
-
it "remove_all should remove the current item from all reciprocal instance varaibles if it cached instance variable exists" do
|
2515
|
-
@c2.many_to_many :attributes, :class => @c1
|
2516
|
-
@c1.many_to_many :nodes, :class => @c2
|
2517
|
-
@c1.dataset._fetch = []
|
2518
|
-
@c2.dataset._fetch = []
|
2519
|
-
attrib = @c1.load(:id=>3)
|
2520
|
-
node = @c2.new(:id => 1234)
|
2521
|
-
node.attributes.must_equal []
|
2522
|
-
attrib.nodes.must_equal []
|
2523
|
-
node.add_attribute(attrib)
|
2524
|
-
attrib.associations[:nodes].must_equal [node]
|
2525
|
-
node.remove_all_attributes
|
2526
|
-
attrib.associations[:nodes].must_equal []
|
2527
|
-
end
|
2528
|
-
|
2529
|
-
it "add, remove, and remove_all methods should respect :join_table_block option" do
|
2530
|
-
@c2.many_to_many :attributes, :class => @c1, :join_table_block=>proc{|ds| ds.filter(:x=>123)}
|
2531
|
-
o = @c2.load(:id => 1234)
|
2532
|
-
o.add_attribute(@c1.load(:id=>44))
|
2533
|
-
o.remove_attribute(@c1.load(:id=>45))
|
2534
|
-
o.remove_all_attributes
|
2535
|
-
sqls = DB.sqls
|
2536
|
-
sqls.shift =~ /INSERT INTO attributes_nodes \((node_id|attribute_id), (node_id|attribute_id)\) VALUES \((1234|44), (1234|44)\)/
|
2537
|
-
sqls.must_equal ["DELETE FROM attributes_nodes WHERE ((x = 123) AND (node_id = 1234) AND (attribute_id = 45))",
|
2538
|
-
"DELETE FROM attributes_nodes WHERE ((x = 123) AND (node_id = 1234))"]
|
2539
|
-
end
|
2540
|
-
|
2541
|
-
it "should call an _add_ method internally to add attributes" do
|
2542
|
-
@c2.many_to_many :attributes, :class => @c1
|
2543
|
-
@c2.private_instance_methods.collect{|x| x.to_s}.sort.must_include("_add_attribute")
|
2544
|
-
p = @c2.load(:id=>10)
|
2545
|
-
c = @c1.load(:id=>123)
|
2546
|
-
def p._add_attribute(x)
|
2547
|
-
@x = x
|
2548
|
-
end
|
2549
|
-
p.add_attribute(c)
|
2550
|
-
p.instance_variable_get(:@x).must_equal c
|
2551
|
-
DB.sqls.must_equal []
|
2552
|
-
end
|
2553
|
-
|
2554
|
-
it "should support an :adder option for defining the _add_ method" do
|
2555
|
-
@c2.many_to_many :attributes, :class => @c1, :adder=>proc{|x| @x = x}
|
2556
|
-
p = @c2.load(:id=>10)
|
2557
|
-
c = @c1.load(:id=>123)
|
2558
|
-
p.add_attribute(c)
|
2559
|
-
p.instance_variable_get(:@x).must_equal c
|
2560
|
-
DB.sqls.must_equal []
|
2561
|
-
end
|
2562
|
-
|
2563
|
-
it "should allow additional arguments given to the add_ method and pass them onwards to the _add_ method" do
|
2564
|
-
@c2.many_to_many :attributes, :class => @c1
|
2565
|
-
p = @c2.load(:id=>10)
|
2566
|
-
c = @c1.load(:id=>123)
|
2567
|
-
def p._add_attribute(x,*y)
|
2568
|
-
@x = x
|
2569
|
-
@y = y
|
2570
|
-
end
|
2571
|
-
p.add_attribute(c,:foo,:bar=>:baz)
|
2572
|
-
p.instance_variable_get(:@x).must_equal c
|
2573
|
-
p.instance_variable_get(:@y).must_equal [:foo,{:bar=>:baz}]
|
2574
|
-
end
|
2575
|
-
|
2576
|
-
it "should call a _remove_ method internally to remove attributes" do
|
2577
|
-
@c2.many_to_many :attributes, :class => @c1
|
2578
|
-
@c2.private_instance_methods.collect{|x| x.to_s}.sort.must_include("_remove_attribute")
|
2579
|
-
p = @c2.load(:id=>10)
|
2580
|
-
c = @c1.load(:id=>123)
|
2581
|
-
def p._remove_attribute(x)
|
2582
|
-
@x = x
|
2583
|
-
end
|
2584
|
-
p.remove_attribute(c)
|
2585
|
-
p.instance_variable_get(:@x).must_equal c
|
2586
|
-
DB.sqls.must_equal []
|
2587
|
-
end
|
2588
|
-
|
2589
|
-
it "should support a :remover option for defining the _remove_ method" do
|
2590
|
-
@c2.many_to_many :attributes, :class => @c1, :remover=>proc{|x| @x = x}
|
2591
|
-
p = @c2.load(:id=>10)
|
2592
|
-
c = @c1.load(:id=>123)
|
2593
|
-
p.remove_attribute(c)
|
2594
|
-
p.instance_variable_get(:@x).must_equal c
|
2595
|
-
DB.sqls.must_equal []
|
2596
|
-
end
|
2597
|
-
|
2598
|
-
it "should allow additional arguments given to the remove_ method and pass them onwards to the _remove_ method" do
|
2599
|
-
@c2.many_to_many :attributes, :class => @c1
|
2600
|
-
p = @c2.load(:id=>10)
|
2601
|
-
c = @c1.load(:id=>123)
|
2602
|
-
def p._remove_attribute(x,*y)
|
2603
|
-
@x = x
|
2604
|
-
@y = y
|
2605
|
-
end
|
2606
|
-
p.remove_attribute(c,:foo,:bar=>:baz)
|
2607
|
-
p.instance_variable_get(:@x).must_equal c
|
2608
|
-
p.instance_variable_get(:@y).must_equal [:foo,{:bar=>:baz}]
|
2609
|
-
end
|
2610
|
-
|
2611
|
-
it "should allow additional arguments given to the remove_all_ method and pass them onwards to the _remove_all_ method" do
|
2612
|
-
@c2.many_to_many :attributes, :class => @c1
|
2613
|
-
p = @c2.load(:id=>10)
|
2614
|
-
def p._remove_all_attributes(*y)
|
2615
|
-
@y = y
|
2616
|
-
end
|
2617
|
-
p.remove_all_attributes(:foo,:bar=>:baz)
|
2618
|
-
p.instance_variable_get(:@y).must_equal [:foo,{:bar=>:baz}]
|
2619
|
-
end
|
2620
|
-
|
2621
|
-
it "should call a _remove_all_ method internally to remove attributes" do
|
2622
|
-
@c2.many_to_many :attributes, :class => @c1
|
2623
|
-
@c2.private_instance_methods.collect{|x| x.to_s}.sort.must_include("_remove_all_attributes")
|
2624
|
-
p = @c2.load(:id=>10)
|
2625
|
-
def p._remove_all_attributes
|
2626
|
-
@x = :foo
|
2627
|
-
end
|
2628
|
-
p.remove_all_attributes
|
2629
|
-
p.instance_variable_get(:@x).must_equal :foo
|
2630
|
-
DB.sqls.must_equal []
|
2631
|
-
end
|
2632
|
-
|
2633
|
-
it "should support a :clearer option for defining the _remove_all_ method" do
|
2634
|
-
@c2.many_to_many :attributes, :class => @c1, :clearer=>proc{@x = :foo}
|
2635
|
-
p = @c2.load(:id=>10)
|
2636
|
-
p.remove_all_attributes
|
2637
|
-
p.instance_variable_get(:@x).must_equal :foo
|
2638
|
-
DB.sqls.must_equal []
|
2639
|
-
end
|
2640
|
-
|
2641
|
-
it "should support (before|after)_(add|remove) callbacks" do
|
2642
|
-
h = []
|
2643
|
-
@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]
|
2644
|
-
@c2.class_eval do
|
2645
|
-
self::Foo = h
|
2646
|
-
def _add_attribute(v)
|
2647
|
-
model::Foo << 4
|
2648
|
-
end
|
2649
|
-
def _remove_attribute(v)
|
2650
|
-
model::Foo << 5
|
2651
|
-
end
|
2652
|
-
def blah(x)
|
2653
|
-
model::Foo << x.pk
|
2654
|
-
end
|
2655
|
-
def blahr(x)
|
2656
|
-
model::Foo << 6
|
2657
|
-
end
|
2658
|
-
end
|
2659
|
-
p = @c2.load(:id=>10)
|
2660
|
-
c = @c1.load(:id=>123)
|
2661
|
-
h.must_equal []
|
2662
|
-
p.add_attribute(c)
|
2663
|
-
h.must_equal [10, -123, 123, 4, 3]
|
2664
|
-
p.remove_attribute(c)
|
2665
|
-
h.must_equal [10, -123, 123, 4, 3, 123, 5, 6]
|
2666
|
-
end
|
2667
|
-
|
2668
|
-
it "should support after_load association callback" do
|
2669
|
-
h = []
|
2670
|
-
@c2.many_to_many :attributes, :class => @c1, :after_load=>[proc{|x,y| h << [x.pk, y.collect{|z|z.pk}]}, :al]
|
2671
|
-
@c2.class_eval do
|
2672
|
-
self::Foo = h
|
2673
|
-
def al(v)
|
2674
|
-
v.each{|x| model::Foo << x.pk}
|
2675
|
-
end
|
2676
|
-
end
|
2677
|
-
@c1.dataset._fetch = [{:id=>20}, {:id=>30}]
|
2678
|
-
p = @c2.load(:id=>10, :parent_id=>20)
|
2679
|
-
attributes = p.attributes
|
2680
|
-
h.must_equal [[10, [20, 30]], 20, 30]
|
2681
|
-
attributes.collect{|a| a.pk}.must_equal [20, 30]
|
2682
|
-
end
|
2683
|
-
|
2684
|
-
it "should raise error and not call internal add or remove method if before callback returns false if raise_on_save_failure is true" do
|
2685
|
-
p = @c2.load(:id=>10)
|
2686
|
-
c = @c1.load(:id=>123)
|
2687
|
-
@c2.many_to_many :attributes, :class => @c1, :before_add=>:ba, :before_remove=>:br
|
2688
|
-
def p.ba(c) false end
|
2689
|
-
def p._add_attribute; raise; end
|
2690
|
-
def p._remove_attribute; raise; end
|
2691
|
-
p.associations[:attributes] = []
|
2692
|
-
p.raise_on_save_failure = true
|
2693
|
-
proc{p.add_attribute(c)}.must_raise(Sequel::HookFailed)
|
2694
|
-
p.attributes.must_equal []
|
2695
|
-
p.associations[:attributes] = [c]
|
2696
|
-
def p.br(c) false end
|
2697
|
-
proc{p.remove_attribute(c)}.must_raise(Sequel::HookFailed)
|
2698
|
-
p.attributes.must_equal [c]
|
2699
|
-
end
|
2700
|
-
|
2701
|
-
it "should return nil and not call internal add or remove method if before callback returns false if raise_on_save_failure is false" do
|
2702
|
-
p = @c2.load(:id=>10)
|
2703
|
-
c = @c1.load(:id=>123)
|
2704
|
-
p.raise_on_save_failure = false
|
2705
|
-
@c2.many_to_many :attributes, :class => @c1, :before_add=>:ba, :before_remove=>:br
|
2706
|
-
def p.ba(c) false end
|
2707
|
-
def p._add_attribute; raise; end
|
2708
|
-
def p._remove_attribute; raise; end
|
2709
|
-
p.associations[:attributes] = []
|
2710
|
-
p.add_attribute(c).must_equal nil
|
2711
|
-
p.attributes.must_equal []
|
2712
|
-
p.associations[:attributes] = [c]
|
2713
|
-
def p.br(c) false end
|
2714
|
-
p.remove_attribute(c).must_equal nil
|
2715
|
-
p.attributes.must_equal [c]
|
2716
|
-
end
|
2717
|
-
|
2718
|
-
it "should raise error and not call internal add or remove method if before callback calls cancel_action if raise_on_save_failure is true" do
|
2719
|
-
p = @c2.load(:id=>10)
|
2720
|
-
c = @c1.load(:id=>123)
|
2721
|
-
@c2.many_to_many :attributes, :class => @c1, :before_add=>:ba, :before_remove=>:br
|
2722
|
-
def p.ba(o) cancel_action end
|
2723
|
-
def p._add_attribute; raise; end
|
2724
|
-
def p._remove_attribute; raise; end
|
2725
|
-
p.associations[:attributes] = []
|
2726
|
-
p.raise_on_save_failure = true
|
2727
|
-
proc{p.add_attribute(c)}.must_raise(Sequel::HookFailed)
|
2728
|
-
p.attributes.must_equal []
|
2729
|
-
p.associations[:attributes] = [c]
|
2730
|
-
def p.br(o) cancel_action end
|
2731
|
-
proc{p.remove_attribute(c)}.must_raise(Sequel::HookFailed)
|
2732
|
-
p.attributes.must_equal [c]
|
2733
|
-
end
|
2734
|
-
|
2735
|
-
it "should return nil and not call internal add or remove method if before callback calls cancel_action if raise_on_save_failure is false" do
|
2736
|
-
p = @c2.load(:id=>10)
|
2737
|
-
c = @c1.load(:id=>123)
|
2738
|
-
p.raise_on_save_failure = false
|
2739
|
-
@c2.many_to_many :attributes, :class => @c1, :before_add=>:ba, :before_remove=>:br
|
2740
|
-
def p.ba(o) cancel_action end
|
2741
|
-
def p._add_attribute; raise; end
|
2742
|
-
def p._remove_attribute; raise; end
|
2743
|
-
p.associations[:attributes] = []
|
2744
|
-
p.add_attribute(c).must_equal nil
|
2745
|
-
p.attributes.must_equal []
|
2746
|
-
p.associations[:attributes] = [c]
|
2747
|
-
def p.br(o) cancel_action end
|
2748
|
-
p.remove_attribute(c).must_equal nil
|
2749
|
-
p.attributes.must_equal [c]
|
2750
|
-
end
|
2751
|
-
|
2752
|
-
it "should support a :uniq option that removes duplicates from the association" do
|
2753
|
-
@c2.many_to_many :attributes, :class => @c1, :uniq=>true
|
2754
|
-
@c1.dataset._fetch = [{:id=>20}, {:id=>30}, {:id=>20}, {:id=>30}]
|
2755
|
-
@c2.load(:id=>10, :parent_id=>20).attributes.must_equal [@c1.load(:id=>20), @c1.load(:id=>30)]
|
2756
|
-
end
|
2757
|
-
|
2758
|
-
it "should support a :distinct option that uses the DISTINCT clause" do
|
2759
|
-
@c2.many_to_many :attributes, :class => @c1, :distinct=>true
|
2760
|
-
@c2.load(:id=>10).attributes_dataset.sql.must_equal "SELECT DISTINCT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 10)"
|
2761
|
-
end
|
2762
|
-
|
2763
|
-
it "should not apply association options when removing all associated records" do
|
2764
|
-
@c2.many_to_many :attributes, :class => @c1 do |ds|
|
2765
|
-
ds.filter(:name=>'John')
|
2766
|
-
end
|
2767
|
-
@c2.load(:id=>1).remove_all_attributes
|
2768
|
-
DB.sqls.must_equal ["DELETE FROM attributes_nodes WHERE (node_id = 1)"]
|
2769
|
-
end
|
2770
|
-
|
2771
|
-
it "should use assocation's dataset when grabbing a record to remove from the assocation by primary key" do
|
2772
|
-
@c2.many_to_many :attributes, :class => @c1 do |ds|
|
2773
|
-
ds.filter(:join_table_att=>3)
|
2774
|
-
end
|
2775
|
-
@c1.dataset._fetch = {:id=>2}
|
2776
|
-
@c2.load(:id=>1).remove_attribute(2)
|
2777
|
-
DB.sqls.must_equal ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((attributes_nodes.node_id = 1) AND (join_table_att = 3) AND (attributes.id = 2)) LIMIT 1",
|
2778
|
-
"DELETE FROM attributes_nodes WHERE ((node_id = 1) AND (attribute_id = 2))"]
|
2779
|
-
end
|
2780
|
-
end
|
2781
|
-
|
2782
|
-
describe Sequel::Model, "one_through_one" do
|
2783
|
-
before do
|
2784
|
-
@c1 = Class.new(Sequel::Model(:attributes)) do
|
2785
|
-
unrestrict_primary_key
|
2786
|
-
attr_accessor :yyy
|
2787
|
-
def self.name; 'Attribute'; end
|
2788
|
-
def self.to_s; 'Attribute'; end
|
2789
|
-
columns :id, :y, :z
|
2790
|
-
end
|
2791
|
-
|
2792
|
-
@c2 = Class.new(Sequel::Model(:nodes)) do
|
2793
|
-
unrestrict_primary_key
|
2794
|
-
attr_accessor :xxx
|
2795
|
-
|
2796
|
-
def self.name; 'Node'; end
|
2797
|
-
def self.to_s; 'Node'; end
|
2798
|
-
columns :id, :x
|
2799
|
-
end
|
2800
|
-
@dataset = @c2.dataset
|
2801
|
-
@c1.dataset.autoid = 1
|
2802
|
-
|
2803
|
-
[@c1, @c2].each{|c| c.dataset._fetch = {}}
|
2804
|
-
DB.reset
|
2805
|
-
end
|
2806
|
-
after do
|
2807
|
-
DB.fetch = {:id => 1, :x => 1}
|
2808
|
-
end
|
2809
|
-
|
2810
|
-
it "should use implicit key values and join table if omitted" do
|
2811
|
-
@c2.one_through_one :attribute, :class => @c1
|
2812
|
-
@c2.new(:id => 1234).attribute_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 1'
|
2813
|
-
end
|
2814
|
-
|
2815
|
-
it "should respect :eager_loader_predicate_key when lazily loading" do
|
2816
|
-
@c2.one_through_one :attribute, :class => @c1, :eager_loading_predicate_key=>Sequel.subscript(:attributes_nodes__node_id, 0)
|
2817
|
-
@c2.new(:id => 1234).attribute_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id[0] = 1234) LIMIT 1'
|
2818
|
-
end
|
2819
|
-
|
2820
|
-
it "should use explicit key values and join table if given" do
|
2821
|
-
@c2.one_through_one :attribute, :class => @c1, :left_key => :nodeid, :right_key => :attributeid, :join_table => :attribute2node
|
2822
|
-
@c2.new(:id => 1234).attribute_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attribute2node ON (attribute2node.attributeid = attributes.id) WHERE (attribute2node.nodeid = 1234) LIMIT 1'
|
2823
|
-
end
|
2824
|
-
|
2825
|
-
it "should support a conditions option" do
|
2826
|
-
@c2.one_through_one :attribute, :class => @c1, :conditions => {:a=>32}
|
2827
|
-
@c2.new(:id => 1234).attribute_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((a = 32) AND (attributes_nodes.node_id = 1234)) LIMIT 1'
|
2828
|
-
|
2829
|
-
@c2.one_through_one :attribute, :class => @c1, :conditions => ['a = ?', 32]
|
2830
|
-
@c2.new(:id => 1234).attribute_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((a = 32) AND (attributes_nodes.node_id = 1234)) LIMIT 1'
|
2831
|
-
@c2.new(:id => 1234).attribute.must_equal @c1.load({})
|
2832
|
-
end
|
2833
|
-
|
2834
|
-
it "should support an order option" do
|
2835
|
-
@c2.one_through_one :attribute, :class => @c1, :order => :blah
|
2836
|
-
@c2.new(:id => 1234).attribute_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) ORDER BY blah LIMIT 1'
|
2837
|
-
end
|
2838
|
-
|
2839
|
-
it "should support an array for the order option" do
|
2840
|
-
@c2.one_through_one :attribute, :class => @c1, :order => [:blah1, :blah2]
|
2841
|
-
@c2.new(:id => 1234).attribute_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) ORDER BY blah1, blah2 LIMIT 1'
|
2842
|
-
end
|
2843
|
-
|
2844
|
-
it "should support :left_primary_key and :right_primary_key options" do
|
2845
|
-
@c2.one_through_one :attribute, :class => @c1, :left_primary_key=>:xxx, :right_primary_key=>:yyy
|
2846
|
-
@c2.new(:id => 1234, :xxx=>5).attribute_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.yyy) WHERE (attributes_nodes.node_id = 5) LIMIT 1'
|
2847
|
-
end
|
2848
|
-
|
2849
|
-
it "should support composite keys" do
|
2850
|
-
@c2.one_through_one :attribute, :class => @c1, :left_key=>[:l1, :l2], :right_key=>[:r1, :r2], :left_primary_key=>[:id, :x], :right_primary_key=>[:id, :y]
|
2851
|
-
@c2.load(:id => 1234, :x=>5).attribute_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.r1 = attributes.id) AND (attributes_nodes.r2 = attributes.y)) WHERE ((attributes_nodes.l1 = 1234) AND (attributes_nodes.l2 = 5)) LIMIT 1'
|
2852
|
-
end
|
2853
|
-
|
2854
|
-
it "should not issue query if not all keys have values" do
|
2855
|
-
@c2.one_through_one :attribute, :class => @c1, :left_key=>[:l1, :l2], :right_key=>[:r1, :r2], :left_primary_key=>[:id, :x], :right_primary_key=>[:id, :y]
|
2856
|
-
@c2.load(:id => 1234, :x=>nil).attribute.must_equal nil
|
2857
|
-
DB.sqls.must_equal []
|
2858
|
-
end
|
2859
|
-
|
2860
|
-
it "should raise an Error unless same number of composite keys used" do
|
2861
|
-
proc{@c2.one_through_one :attribute, :class => @c1, :left_key=>[:node_id, :id]}.must_raise(Sequel::Error)
|
2862
|
-
proc{@c2.one_through_one :attribute, :class => @c1, :left_primary_key=>[:node_id, :id]}.must_raise(Sequel::Error)
|
2863
|
-
proc{@c2.one_through_one :attribute, :class => @c1, :left_key=>[:node_id, :id], :left_primary_key=>:id}.must_raise(Sequel::Error)
|
2864
|
-
proc{@c2.one_through_one :attribute, :class => @c1, :left_key=>:id, :left_primary_key=>[:node_id, :id]}.must_raise(Sequel::Error)
|
2865
|
-
proc{@c2.one_through_one :attribute, :class => @c1, :left_key=>[:node_id, :id, :x], :left_primary_key=>[:parent_id, :id]}.must_raise(Sequel::Error)
|
2866
|
-
|
2867
|
-
proc{@c2.one_through_one :attribute, :class => @c1, :right_primary_key=>[:node_id, :id]}.must_raise(Sequel::Error)
|
2868
|
-
proc{@c2.one_through_one :attribute, :class => @c1, :right_key=>[:node_id, :id], :right_primary_key=>:id}.must_raise(Sequel::Error)
|
2869
|
-
proc{@c2.one_through_one :attribute, :class => @c1, :right_key=>:id, :left_primary_key=>[:node_id, :id]}.must_raise(Sequel::Error)
|
2870
|
-
proc{@c2.one_through_one :attribute, :class => @c1, :right_key=>[:node_id, :id, :x], :right_primary_key=>[:parent_id, :id]}.must_raise(Sequel::Error)
|
2871
|
-
end
|
2872
|
-
|
2873
|
-
it "should support a select option" do
|
2874
|
-
@c2.one_through_one :attribute, :class => @c1, :select => :blah
|
2875
|
-
|
2876
|
-
@c2.new(:id => 1234).attribute_dataset.sql.must_equal 'SELECT blah FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 1'
|
2877
|
-
end
|
2878
|
-
|
2879
|
-
it "should support an array for the select option" do
|
2880
|
-
@c2.one_through_one :attribute, :class => @c1, :select => [Sequel::SQL::ColumnAll.new(:attributes), :attribute_nodes__blah2]
|
2881
|
-
|
2882
|
-
@c2.new(:id => 1234).attribute_dataset.sql.must_equal 'SELECT attributes.*, attribute_nodes.blah2 FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 1'
|
2883
|
-
end
|
2884
|
-
|
2885
|
-
it "should accept a block" do
|
2886
|
-
@c2.one_through_one :attribute, :class => @c1 do |ds|
|
2887
|
-
ds.filter(:xxx => @xxx)
|
2888
|
-
end
|
2889
|
-
|
2890
|
-
n = @c2.new(:id => 1234)
|
2891
|
-
n.xxx = 555
|
2892
|
-
n.attribute_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((attributes_nodes.node_id = 1234) AND (xxx = 555)) LIMIT 1'
|
2893
|
-
end
|
2894
|
-
|
2895
|
-
it "should allow the :order option while accepting a block" do
|
2896
|
-
@c2.one_through_one :attribute, :class => @c1, :order=>[:blah1, :blah2] do |ds|
|
2897
|
-
ds.filter(:xxx => @xxx)
|
2898
|
-
end
|
2899
|
-
|
2900
|
-
n = @c2.new(:id => 1234)
|
2901
|
-
n.xxx = 555
|
2902
|
-
n.attribute_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((attributes_nodes.node_id = 1234) AND (xxx = 555)) ORDER BY blah1, blah2 LIMIT 1'
|
2903
|
-
end
|
2904
|
-
|
2905
|
-
it "should support a :dataset option that is used instead of the default" do
|
2906
|
-
c1 = @c1
|
2907
|
-
@c2.one_through_one :attribute, :class => @c1, :dataset=>proc{c1.join_table(:natural, :an).filter(:an__nodeid=>pk)}, :order=> :a, :select=>nil do |ds|
|
2908
|
-
ds.filter(:xxx => @xxx)
|
2909
|
-
end
|
2910
|
-
|
2911
|
-
n = @c2.new(:id => 1234)
|
2912
|
-
n.xxx = 555
|
2913
|
-
n.attribute_dataset.sql.must_equal 'SELECT * FROM attributes NATURAL JOIN an WHERE ((an.nodeid = 1234) AND (xxx = 555)) ORDER BY a LIMIT 1'
|
2914
|
-
n.attribute.must_equal @c1.load({})
|
2915
|
-
DB.sqls.must_equal ['SELECT * FROM attributes NATURAL JOIN an WHERE ((an.nodeid = 1234) AND (xxx = 555)) ORDER BY a LIMIT 1']
|
2916
|
-
end
|
2917
|
-
|
2918
|
-
it "should support a :dataset option that accepts the reflection as an argument" do
|
2919
|
-
@c2.one_through_one :attribute, :class => @c1, :dataset=>lambda{|opts| opts.associated_class.natural_join(:an).filter(:an__nodeid=>pk)}, :order=> :a, :select=>nil do |ds|
|
2920
|
-
ds.filter(:xxx => @xxx)
|
2921
|
-
end
|
2922
|
-
|
2923
|
-
n = @c2.new(:id => 1234)
|
2924
|
-
n.xxx = 555
|
2925
|
-
n.attribute_dataset.sql.must_equal 'SELECT * FROM attributes NATURAL JOIN an WHERE ((an.nodeid = 1234) AND (xxx = 555)) ORDER BY a LIMIT 1'
|
2926
|
-
n.attribute.must_equal @c1.load({})
|
2927
|
-
DB.sqls.must_equal ['SELECT * FROM attributes NATURAL JOIN an WHERE ((an.nodeid = 1234) AND (xxx = 555)) ORDER BY a LIMIT 1']
|
2928
|
-
end
|
2929
|
-
|
2930
|
-
it "should support a :limit option to specify an offset" do
|
2931
|
-
@c2.one_through_one :attribute, :class => @c1 , :limit=>[nil, 10]
|
2932
|
-
@c2.new(:id => 1234).attribute_dataset.sql.must_equal 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 1 OFFSET 10'
|
2933
|
-
end
|
2934
|
-
|
2935
|
-
it "should have the :eager option affect the _dataset method" do
|
2936
|
-
@c2.one_through_one :attribute, :class => @c2 , :eager=>:attribute
|
2937
|
-
@c2.new(:id => 1234).attribute_dataset.opts[:eager].must_equal(:attribute=>nil)
|
2938
|
-
end
|
2939
|
-
|
2940
|
-
it "should handle an aliased join table" do
|
2941
|
-
@c2.one_through_one :attribute, :class => @c1, :join_table => :attribute2node___attributes_nodes
|
2942
|
-
n = @c2.load(:id => 1234)
|
2943
|
-
n.attribute_dataset.sql.must_equal "SELECT attributes.* FROM attributes INNER JOIN attribute2node AS attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 1"
|
2944
|
-
end
|
2945
|
-
|
2946
|
-
it "should raise an error if the model object doesn't have a valid primary key" do
|
2947
|
-
@c2.one_through_one :attribute, :class => @c1
|
2948
|
-
a = @c2.new
|
2949
|
-
proc{a.attribute_dataset}.must_raise(Sequel::Error)
|
2950
|
-
end
|
2951
|
-
|
2952
|
-
it "should provide an array with all members of the association" do
|
2953
|
-
@c2.one_through_one :attribute, :class => @c1
|
2954
|
-
|
2955
|
-
@c2.new(:id => 1234).attribute.must_equal @c1.load({})
|
2956
|
-
DB.sqls.must_equal ['SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 1']
|
2957
|
-
end
|
2958
|
-
|
2959
|
-
it "should populate cache when accessed" do
|
2960
|
-
@c2.one_through_one :attribute, :class => @c1
|
2961
|
-
|
2962
|
-
n = @c2.new(:id => 1234)
|
2963
|
-
n.associations.include?(:attribute).must_equal false
|
2964
|
-
atts = n.attribute
|
2965
|
-
atts.must_equal n.associations[:attribute]
|
2966
|
-
end
|
2967
|
-
|
2968
|
-
it "should use cache if available" do
|
2969
|
-
@c2.one_through_one :attribute, :class => @c1
|
2970
|
-
|
2971
|
-
n = @c2.new(:id => 1234)
|
2972
|
-
n.associations[:attribute] = 42
|
2973
|
-
n.attribute.must_equal 42
|
2974
|
-
DB.sqls.must_equal []
|
2975
|
-
end
|
2976
|
-
|
2977
|
-
it "should not use cache if asked to reload" do
|
2978
|
-
@c2.one_through_one :attribute, :class => @c1
|
2979
|
-
|
2980
|
-
n = @c2.new(:id => 1234)
|
2981
|
-
n.associations[:attribute] = 42
|
2982
|
-
n.attribute(true).wont_equal 42
|
2983
|
-
DB.sqls.must_equal ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 1"]
|
2984
|
-
end
|
2985
|
-
|
2986
|
-
it "should not add associations methods directly to class" do
|
2987
|
-
@c2.one_through_one :attribute, :class => @c1
|
2988
|
-
im = @c2.instance_methods.collect{|x| x.to_s}
|
2989
|
-
im.must_include('attribute')
|
2990
|
-
im.must_include('attribute_dataset')
|
2991
|
-
im2 = @c2.instance_methods(false).collect{|x| x.to_s}
|
2992
|
-
im2.wont_include('attribute')
|
2993
|
-
im2.wont_include('attribute_dataset')
|
2994
|
-
end
|
2995
|
-
|
2996
|
-
it "should support after_load association callback" do
|
2997
|
-
h = []
|
2998
|
-
@c2.one_through_one :attribute, :class => @c1, :after_load=>[proc{|x,y| h << [x.pk, y.pk]}, :al]
|
2999
|
-
@c2.class_eval do
|
3000
|
-
self::Foo = h
|
3001
|
-
def al(v)
|
3002
|
-
model::Foo << v.pk
|
3003
|
-
end
|
3004
|
-
end
|
3005
|
-
@c1.dataset._fetch = [{:id=>20}]
|
3006
|
-
p = @c2.load(:id=>10, :parent_id=>20)
|
3007
|
-
attribute = p.attribute
|
3008
|
-
h.must_equal [[10, 20], 20]
|
3009
|
-
attribute.pk.must_equal 20
|
3010
|
-
end
|
3011
|
-
|
3012
|
-
it "should support a :distinct option that uses the DISTINCT clause" do
|
3013
|
-
@c2.one_through_one :attribute, :class => @c1, :distinct=>true
|
3014
|
-
@c2.load(:id=>10).attribute_dataset.sql.must_equal "SELECT DISTINCT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 10) LIMIT 1"
|
3015
|
-
end
|
3016
|
-
|
3017
|
-
it "should not add a setter method if the :read_only option is true" do
|
3018
|
-
@c2.one_through_one :attribute, :class => @c1, :read_only=>true
|
3019
|
-
im = @c2.instance_methods.collect{|x| x.to_s}
|
3020
|
-
im.must_include('attribute')
|
3021
|
-
im.wont_include('attribute=')
|
3022
|
-
end
|
3023
|
-
|
3024
|
-
it "should add a setter method" do
|
3025
|
-
@c2.one_through_one :attribute, :class => @c1
|
3026
|
-
attrib = @c1.new(:id=>3)
|
3027
|
-
DB.fetch = []
|
3028
|
-
o = @c2.load(:id => 1234)
|
3029
|
-
o.attribute = nil
|
3030
|
-
DB.sqls.must_equal ["SELECT * FROM attributes_nodes WHERE (node_id = 1234) LIMIT 1"]
|
3031
|
-
|
3032
|
-
o.attribute = attrib
|
3033
|
-
sqls = DB.sqls
|
3034
|
-
["INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (3, 1234)",
|
3035
|
-
"INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 3)"].must_include(sqls.slice! 1)
|
3036
|
-
sqls.must_equal ["SELECT * FROM attributes_nodes WHERE (node_id = 1234) LIMIT 1"]
|
3037
|
-
|
3038
|
-
DB.fetch = {:node_id=>1234, :attribute_id=>5}
|
3039
|
-
o.attribute = nil
|
3040
|
-
DB.sqls.must_equal ["SELECT * FROM attributes_nodes WHERE (node_id = 1234) LIMIT 1",
|
3041
|
-
"DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (attribute_id = 5))"]
|
3042
|
-
|
3043
|
-
o.attribute = attrib
|
3044
|
-
DB.sqls.must_equal ["SELECT * FROM attributes_nodes WHERE (node_id = 1234) LIMIT 1",
|
3045
|
-
"UPDATE attributes_nodes SET attribute_id = 3 WHERE ((node_id = 1234) AND (attribute_id = 5))"]
|
3046
|
-
|
3047
|
-
@c2.load(:id => 1234).attribute = @c1.new(:id=>5)
|
3048
|
-
DB.sqls.must_equal ["SELECT * FROM attributes_nodes WHERE (node_id = 1234) LIMIT 1"]
|
3049
|
-
end
|
3050
|
-
|
3051
|
-
it "should use a transaction in the setter method" do
|
3052
|
-
@c2.one_through_one :attribute, :class => @c1
|
3053
|
-
@c2.use_transactions = true
|
3054
|
-
attrib = @c1.load(:id=>3)
|
3055
|
-
DB.fetch = []
|
3056
|
-
@c2.new(:id => 1234).attribute = nil
|
3057
|
-
DB.sqls.must_equal ['BEGIN',
|
3058
|
-
"SELECT * FROM attributes_nodes WHERE (node_id = 1234) LIMIT 1",
|
3059
|
-
'COMMIT']
|
3060
|
-
end
|
3061
|
-
|
3062
|
-
it "should have setter method respect :join_table_block option" do
|
3063
|
-
@c2.one_through_one :attribute, :class => @c1, :join_table_block=>proc{|ds| ds.where(:a)}
|
3064
|
-
attrib = @c1.new(:id=>3)
|
3065
|
-
DB.fetch = []
|
3066
|
-
o = @c2.new(:id => 1234)
|
3067
|
-
o.attribute = nil
|
3068
|
-
DB.sqls.must_equal ["SELECT * FROM attributes_nodes WHERE (a AND (node_id = 1234)) LIMIT 1"]
|
3069
|
-
|
3070
|
-
o.attribute = attrib
|
3071
|
-
sqls = DB.sqls
|
3072
|
-
["INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (3, 1234)",
|
3073
|
-
"INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 3)"].must_include(sqls.slice! 1)
|
3074
|
-
sqls.must_equal ["SELECT * FROM attributes_nodes WHERE (a AND (node_id = 1234)) LIMIT 1"]
|
3075
|
-
|
3076
|
-
DB.fetch = {:node_id=>1234, :attribute_id=>5}
|
3077
|
-
o.attribute = nil
|
3078
|
-
DB.sqls.must_equal ["SELECT * FROM attributes_nodes WHERE (a AND (node_id = 1234)) LIMIT 1",
|
3079
|
-
"DELETE FROM attributes_nodes WHERE (a AND (node_id = 1234) AND (attribute_id = 5))"]
|
3080
|
-
|
3081
|
-
o.attribute = attrib
|
3082
|
-
DB.sqls.must_equal ["SELECT * FROM attributes_nodes WHERE (a AND (node_id = 1234)) LIMIT 1",
|
3083
|
-
"UPDATE attributes_nodes SET attribute_id = 3 WHERE (a AND (node_id = 1234) AND (attribute_id = 5))"]
|
3084
|
-
end
|
3085
|
-
|
3086
|
-
it "should have the setter method respect the :left_primary_key and :right_primary_key option" do
|
3087
|
-
@c2.one_through_one :attribute, :class => @c1, :left_primary_key=>:xxx, :right_primary_key=>:yyy
|
3088
|
-
attrib = @c1.new(:id=>3, :yyy=>7)
|
3089
|
-
DB.fetch = []
|
3090
|
-
o = @c2.new(:id => 1234, :xxx=>5)
|
3091
|
-
o.attribute = nil
|
3092
|
-
DB.sqls.must_equal ["SELECT * FROM attributes_nodes WHERE (node_id = 5) LIMIT 1"]
|
3093
|
-
|
3094
|
-
o.attribute = attrib
|
3095
|
-
sqls = DB.sqls
|
3096
|
-
["INSERT INTO attributes_nodes (attribute_id, node_id) VALUES (7, 5)",
|
3097
|
-
"INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (5, 7)"].must_include(sqls.slice! 1)
|
3098
|
-
sqls.must_equal ["SELECT * FROM attributes_nodes WHERE (node_id = 5) LIMIT 1"]
|
3099
|
-
|
3100
|
-
DB.fetch = {:node_id=>1234, :attribute_id=>9}
|
3101
|
-
o.attribute = nil
|
3102
|
-
DB.sqls.must_equal ["SELECT * FROM attributes_nodes WHERE (node_id = 5) LIMIT 1",
|
3103
|
-
"DELETE FROM attributes_nodes WHERE ((node_id = 5) AND (attribute_id = 9))"]
|
3104
|
-
|
3105
|
-
o.attribute = attrib
|
3106
|
-
DB.sqls.must_equal ["SELECT * FROM attributes_nodes WHERE (node_id = 5) LIMIT 1",
|
3107
|
-
"UPDATE attributes_nodes SET attribute_id = 7 WHERE ((node_id = 5) AND (attribute_id = 9))"]
|
3108
|
-
end
|
3109
|
-
|
3110
|
-
it "should have the setter method respect composite keys" do
|
3111
|
-
@c2.one_through_one :attribute, :class => @c1, :left_key=>[:node_id, :y], :left_primary_key=>[:id, :x], :right_key=>[:attribute_id, :z], :right_primary_key=>[:id, :w]
|
3112
|
-
attrib = @c1.load(:id=>3, :w=>7)
|
3113
|
-
@c1.def_column_alias :w, :w
|
3114
|
-
DB.fetch = []
|
3115
|
-
o = @c2.new(:id => 1234, :x=>5)
|
3116
|
-
o.attribute = nil
|
3117
|
-
DB.sqls.must_equal ["SELECT * FROM attributes_nodes WHERE ((node_id = 1234) AND (y = 5)) LIMIT 1"]
|
3118
|
-
|
3119
|
-
o.attribute = attrib
|
3120
|
-
sqls = DB.sqls
|
3121
|
-
sqls.slice!(1).must_match(/\AINSERT INTO attributes_nodes \((attribute_id|z|node_id|y), (attribute_id|z|node_id|y), (attribute_id|z|node_id|y), (attribute_id|z|node_id|y)\) VALUES \((3|7|1234|5), (3|7|1234|5), (3|7|1234|5), (3|7|1234|5)\)\z/)
|
3122
|
-
sqls.must_equal ["SELECT * FROM attributes_nodes WHERE ((node_id = 1234) AND (y = 5)) LIMIT 1"]
|
3123
|
-
|
3124
|
-
DB.fetch = {:node_id=>1234, :attribute_id=>10, :y=>6, :z=>8}
|
3125
|
-
o.attribute = nil
|
3126
|
-
DB.sqls.must_equal ["SELECT * FROM attributes_nodes WHERE ((node_id = 1234) AND (y = 5)) LIMIT 1",
|
3127
|
-
"DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (y = 5) AND (attribute_id = 10) AND (z = 8))"]
|
3128
|
-
|
3129
|
-
o.attribute = attrib
|
3130
|
-
sqls = DB.sqls
|
3131
|
-
["UPDATE attributes_nodes SET attribute_id = 3, z = 7 WHERE ((node_id = 1234) AND (y = 5) AND (attribute_id = 10) AND (z = 8))",
|
3132
|
-
"UPDATE attributes_nodes SET z = 7, attribute_id = 3 WHERE ((node_id = 1234) AND (y = 5) AND (attribute_id = 10) AND (z = 8))"].must_include(sqls.slice!(1))
|
3133
|
-
sqls.must_equal ["SELECT * FROM attributes_nodes WHERE ((node_id = 1234) AND (y = 5)) LIMIT 1"]
|
3134
|
-
end
|
3135
|
-
|
3136
|
-
it "should raise an error if the current model object that doesn't have a valid primary key" do
|
3137
|
-
@c2.one_through_one :attribute, :class => @c1
|
3138
|
-
p = @c2.new
|
3139
|
-
c = @c2.load(:id=>123)
|
3140
|
-
proc{c.attribute = p}.must_raise(Sequel::Error)
|
3141
|
-
end
|
3142
|
-
|
3143
|
-
it "should raise an error if the associated object that doesn't have a valid primary key" do
|
3144
|
-
@c2.one_through_one :attribute, :class => @c1
|
3145
|
-
p = @c2.new
|
3146
|
-
c = @c2.load(:id=>123)
|
3147
|
-
proc{p.attribute = c}.must_raise(Sequel::Error)
|
3148
|
-
end
|
3149
|
-
|
3150
|
-
it "should make the change to the foreign_key value inside a _association= method" do
|
3151
|
-
@c2.one_through_one :attribute, :class => @c1
|
3152
|
-
@c2.private_instance_methods.collect{|x| x.to_s}.sort.must_include("_attribute=")
|
3153
|
-
attrib = @c1.new(:id=>3)
|
3154
|
-
o = @c2.new(:id => 1234)
|
3155
|
-
def o._attribute=(x)
|
3156
|
-
@x = x
|
3157
|
-
end
|
3158
|
-
o.attribute = attrib
|
3159
|
-
o.instance_variable_get(:@x).must_equal attrib
|
3160
|
-
end
|
3161
|
-
|
3162
|
-
it "should have a :setter option define the _association= method" do
|
3163
|
-
@c2.one_through_one :attribute, :class => @c1, :setter=>proc{|x| @x = x}
|
3164
|
-
attrib = @c1.new(:id=>3)
|
3165
|
-
o = @c2.new(:id => 1234)
|
3166
|
-
o.attribute = attrib
|
3167
|
-
o.instance_variable_get(:@x).must_equal attrib
|
3168
|
-
end
|
3169
|
-
|
3170
|
-
it "should support (before|after)_set callbacks" do
|
3171
|
-
h = []
|
3172
|
-
@c2.one_through_one :attribute, :class => @c1, :before_set=>[proc{|x,y| h << x.pk; h << (y ? -y.pk : :y)}, :blah], :after_set=>proc{h << :l}
|
3173
|
-
@c2.class_eval do
|
3174
|
-
self::Foo = h
|
3175
|
-
def blah(x)
|
3176
|
-
model::Foo << (x ? x.pk : :x)
|
3177
|
-
end
|
3178
|
-
end
|
3179
|
-
attrib = @c1.new(:id=>3)
|
3180
|
-
o = @c2.new(:id => 1234)
|
3181
|
-
h.must_equal []
|
3182
|
-
o.attribute = attrib
|
3183
|
-
h.must_equal [1234, -3, 3, :l]
|
3184
|
-
o.attribute = nil
|
3185
|
-
h.must_equal [1234, -3, 3, :l, 1234, :y, :x, :l]
|
3186
|
-
end
|
3187
|
-
end
|
3188
|
-
|
3189
|
-
describe "Filtering by associations" do
|
3190
|
-
before(:all) do
|
3191
|
-
db = Sequel.mock
|
3192
|
-
db.extend_datasets do
|
3193
|
-
def supports_window_functions?; true; end
|
3194
|
-
def supports_distinct_on?; true; end
|
3195
|
-
end
|
3196
|
-
@Album = Class.new(Sequel::Model(db[:albums]))
|
3197
|
-
artist = @Artist = Class.new(Sequel::Model(db[:artists]))
|
3198
|
-
tag = @Tag = Class.new(Sequel::Model(db[:tags]))
|
3199
|
-
track = @Track = Class.new(Sequel::Model(db[:tracks]))
|
3200
|
-
album_info = @AlbumInfo = Class.new(Sequel::Model(db[:album_infos]))
|
3201
|
-
@Artist.columns :id, :id1, :id2
|
3202
|
-
@Tag.columns :id, :tid1, :tid2
|
3203
|
-
@Track.columns :id, :album_id, :album_id1, :album_id2
|
3204
|
-
@AlbumInfo.columns :id, :album_id, :album_id1, :album_id2
|
3205
|
-
@Album.class_eval do
|
3206
|
-
columns :id, :id1, :id2, :artist_id, :artist_id1, :artist_id2
|
3207
|
-
b = lambda{|ds| ds.where(:name=>'B')}
|
3208
|
-
c = {:name=>'A'}
|
3209
|
-
|
3210
|
-
many_to_one :artist, :class=>artist, :key=>:artist_id
|
3211
|
-
one_to_many :tracks, :class=>track, :key=>:album_id
|
3212
|
-
one_to_one :track, :class=>track, :key=>:album_id
|
3213
|
-
one_to_one :album_info, :class=>album_info, :key=>:album_id
|
3214
|
-
many_to_many :tags, :class=>tag, :left_key=>:album_id, :join_table=>:albums_tags, :right_key=>:tag_id
|
3215
|
-
|
3216
|
-
many_to_one :a_artist, :clone=>:artist, :conditions=>c
|
3217
|
-
one_to_many :a_tracks, :clone=>:tracks, :conditions=>c
|
3218
|
-
one_to_one :a_album_info, :clone=>:album_info, :conditions=>c
|
3219
|
-
many_to_many :a_tags, :clone=>:tags, :conditions=>c
|
3220
|
-
|
3221
|
-
many_to_one :b_artist, :clone=>:artist, &b
|
3222
|
-
one_to_many :b_tracks, :clone=>:tracks, &b
|
3223
|
-
one_to_one :b_album_info, :clone=>:album_info, &b
|
3224
|
-
many_to_many :b_tags, :clone=>:tags, &b
|
3225
|
-
|
3226
|
-
one_to_many :l_tracks, :clone=>:tracks, :limit=>10
|
3227
|
-
one_to_one :l_track, :clone=>:tracks, :order=>:name
|
3228
|
-
many_to_many :l_tags, :clone=>:tags, :limit=>10
|
3229
|
-
one_through_one :l_tag, :clone=>:tags, :order=>:name
|
3230
|
-
|
3231
|
-
one_to_many :al_tracks, :clone=>:l_tracks, :conditions=>c
|
3232
|
-
one_to_one :al_track, :clone=>:l_track, :conditions=>c
|
3233
|
-
many_to_many :al_tags, :clone=>:l_tags, :conditions=>c
|
3234
|
-
one_through_one :al_tag, :clone=>:l_tag, :conditions=>c
|
3235
|
-
|
3236
|
-
many_to_one :cartist, :class=>artist, :key=>[:artist_id1, :artist_id2], :primary_key=>[:id1, :id2]
|
3237
|
-
one_to_many :ctracks, :class=>track, :key=>[:album_id1, :album_id2], :primary_key=>[:id1, :id2]
|
3238
|
-
one_to_one :calbum_info, :class=>album_info, :key=>[:album_id1, :album_id2], :primary_key=>[:id1, :id2]
|
3239
|
-
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
|
3240
|
-
|
3241
|
-
many_to_one :a_cartist, :clone=>:cartist, :conditions=>c
|
3242
|
-
one_to_many :a_ctracks, :clone=>:ctracks, :conditions=>c
|
3243
|
-
one_to_one :a_calbum_info, :clone=>:calbum_info, :conditions=>c
|
3244
|
-
many_to_many :a_ctags, :clone=>:ctags, :conditions=>c
|
3245
|
-
|
3246
|
-
many_to_one :b_cartist, :clone=>:cartist, &b
|
3247
|
-
one_to_many :b_ctracks, :clone=>:ctracks, &b
|
3248
|
-
one_to_one :b_calbum_info, :clone=>:calbum_info, &b
|
3249
|
-
many_to_many :b_ctags, :clone=>:ctags, &b
|
3250
|
-
|
3251
|
-
one_to_many :l_ctracks, :clone=>:ctracks, :limit=>10
|
3252
|
-
one_to_one :l_ctrack, :clone=>:ctracks, :order=>:name
|
3253
|
-
many_to_many :l_ctags, :clone=>:ctags, :limit=>10
|
3254
|
-
one_through_one :l_ctag, :clone=>:ctags, :order=>:name
|
3255
|
-
|
3256
|
-
one_to_many :al_ctracks, :clone=>:l_ctracks, :conditions=>c
|
3257
|
-
one_to_one :al_ctrack, :clone=>:l_ctrack, :conditions=>c
|
3258
|
-
many_to_many :al_ctags, :clone=>:l_ctags, :conditions=>c
|
3259
|
-
one_through_one :al_ctag, :clone=>:l_ctag, :conditions=>c
|
3260
|
-
end
|
3261
|
-
end
|
3262
|
-
after do
|
3263
|
-
@Album.default_eager_limit_strategy = true
|
3264
|
-
end
|
3265
|
-
|
3266
|
-
it "should be able to filter on many_to_one associations" do
|
3267
|
-
@Album.filter(:artist=>@Artist.load(:id=>3)).sql.must_equal 'SELECT * FROM albums WHERE (albums.artist_id = 3)'
|
3268
|
-
end
|
3269
|
-
|
3270
|
-
it "should be able to filter on one_to_many associations" do
|
3271
|
-
@Album.filter(:tracks=>@Track.load(:album_id=>3)).sql.must_equal 'SELECT * FROM albums WHERE (albums.id = 3)'
|
3272
|
-
end
|
3273
|
-
|
3274
|
-
it "should be able to filter on one_to_one associations" do
|
3275
|
-
@Album.filter(:album_info=>@AlbumInfo.load(:album_id=>3)).sql.must_equal 'SELECT * FROM albums WHERE (albums.id = 3)'
|
3276
|
-
end
|
3277
|
-
|
3278
|
-
it "should be able to filter on many_to_many associations" do
|
3279
|
-
@Album.filter(:tags=>@Tag.load(:id=>3)).sql.must_equal '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))))'
|
3280
|
-
end
|
3281
|
-
|
3282
|
-
it "should be able to filter on many_to_one associations with :conditions" do
|
3283
|
-
@Album.filter(:a_artist=>@Artist.load(:id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists WHERE ((name = 'A') AND (artists.id IS NOT NULL) AND (artists.id = 3))))"
|
3284
|
-
end
|
3285
|
-
|
3286
|
-
it "should be able to filter on one_to_many associations with :conditions" do
|
3287
|
-
@Album.filter(:a_tracks=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'A') AND (tracks.album_id IS NOT NULL) AND (tracks.id = 5))))"
|
3288
|
-
end
|
3289
|
-
|
3290
|
-
it "should be able to filter on one_to_one associations with :conditions" do
|
3291
|
-
@Album.filter(:a_album_info=>@AlbumInfo.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id = 5))))"
|
3292
|
-
end
|
3293
|
-
|
3294
|
-
it "should be able to filter on many_to_many associations with :conditions" do
|
3295
|
-
@Album.filter(:a_tags=>@Tag.load(:id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'A') AND (albums_tags.album_id IS NOT NULL) AND (tags.id = 3))))"
|
3296
|
-
end
|
3297
|
-
|
3298
|
-
it "should be able to filter on many_to_one associations with block" do
|
3299
|
-
@Album.filter(:b_artist=>@Artist.load(:id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists WHERE ((name = 'B') AND (artists.id IS NOT NULL) AND (artists.id = 3))))"
|
3300
|
-
end
|
3301
|
-
|
3302
|
-
it "should be able to filter on one_to_many associations with block" do
|
3303
|
-
@Album.filter(:b_tracks=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'B') AND (tracks.album_id IS NOT NULL) AND (tracks.id = 5))))"
|
3304
|
-
end
|
3305
|
-
|
3306
|
-
it "should be able to filter on one_to_one associations with block" do
|
3307
|
-
@Album.filter(:b_album_info=>@AlbumInfo.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'B') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id = 5))))"
|
3308
|
-
end
|
3309
|
-
|
3310
|
-
it "should be able to filter on many_to_many associations with block" do
|
3311
|
-
@Album.filter(:b_tags=>@Tag.load(:id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'B') AND (albums_tags.album_id IS NOT NULL) AND (tags.id = 3))))"
|
3312
|
-
end
|
3313
|
-
|
3314
|
-
it "should be able to filter on one_to_many associations with :limit" do
|
3315
|
-
@Album.filter(:l_tracks=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT id FROM (SELECT tracks.id, row_number() OVER (PARTITION BY tracks.album_id) AS x_sequel_row_number_x FROM tracks) AS t1 WHERE (x_sequel_row_number_x <= 10))) AND (tracks.id = 5))))"
|
3316
|
-
end
|
3317
|
-
|
3318
|
-
it "should be able to filter on one_to_one associations with :order" do
|
3319
|
-
@Album.filter(:l_track=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT DISTINCT ON (tracks.album_id) tracks.id FROM tracks ORDER BY tracks.album_id, name)) AND (tracks.id = 5))))"
|
3320
|
-
end
|
3321
|
-
|
3322
|
-
it "should be able to filter on one_to_one associations with :filter_limit_strategy" do
|
3323
|
-
@Album.one_to_one :l_track2, :clone=>:track, :filter_limit_strategy=>:window_function
|
3324
|
-
@Album.filter(:l_track2=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT id FROM (SELECT tracks.id, row_number() OVER (PARTITION BY tracks.album_id) AS x_sequel_row_number_x FROM tracks) AS t1 WHERE (x_sequel_row_number_x = 1))) AND (tracks.id = 5))))"
|
3325
|
-
end
|
3326
|
-
|
3327
|
-
it "should be able to filter on one_to_one associations with :eager_limit_strategy" do
|
3328
|
-
@Album.one_to_one :l_track2, :clone=>:track, :eager_limit_strategy=>:window_function
|
3329
|
-
@Album.filter(:l_track2=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT id FROM (SELECT tracks.id, row_number() OVER (PARTITION BY tracks.album_id) AS x_sequel_row_number_x FROM tracks) AS t1 WHERE (x_sequel_row_number_x = 1))) AND (tracks.id = 5))))"
|
3330
|
-
end
|
3331
|
-
|
3332
|
-
it "should be able to filter on one_to_one associations with :order and :filter_limit_strategy" do
|
3333
|
-
@Album.one_to_one :l_track2, :clone=>:l_track, :filter_limit_strategy=>:window_function
|
3334
|
-
@Album.filter(:l_track2=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT id FROM (SELECT tracks.id, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks) AS t1 WHERE (x_sequel_row_number_x = 1))) AND (tracks.id = 5))))"
|
3335
|
-
end
|
3336
|
-
|
3337
|
-
it "should be able to filter on one_to_one associations with :order and :eager_limit_strategy" do
|
3338
|
-
@Album.one_to_one :l_track2, :clone=>:l_track, :eager_limit_strategy=>:window_function
|
3339
|
-
@Album.filter(:l_track2=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT id FROM (SELECT tracks.id, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks) AS t1 WHERE (x_sequel_row_number_x = 1))) AND (tracks.id = 5))))"
|
3340
|
-
end
|
3341
|
-
|
3342
|
-
it "should be able to filter on one_to_one associations with :order and Model.default_eager_limit_strategy" do
|
3343
|
-
@Album.default_eager_limit_strategy = :window_function
|
3344
|
-
@Album.one_to_one :l_track2, :clone=>:l_track
|
3345
|
-
@Album.filter(:l_track2=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT id FROM (SELECT tracks.id, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks) AS t1 WHERE (x_sequel_row_number_x = 1))) AND (tracks.id = 5))))"
|
3346
|
-
end
|
3347
|
-
|
3348
|
-
it "should be able to filter on one_to_one associations with :order and :eager_limit_strategy=>:union" do
|
3349
|
-
@Album.one_to_one :l_track2, :clone=>:l_track, :eager_limit_strategy=>:union
|
3350
|
-
@Album.filter(:l_track2=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT DISTINCT ON (tracks.album_id) tracks.id FROM tracks ORDER BY tracks.album_id, name)) AND (tracks.id = 5))))"
|
3351
|
-
end
|
3352
|
-
|
3353
|
-
it "should be able to filter on one_to_one associations with :order and :eager_limit_strategy=>:ruby" do
|
3354
|
-
@Album.one_to_one :l_track2, :clone=>:l_track, :eager_limit_strategy=>:ruby
|
3355
|
-
@Album.filter(:l_track2=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT DISTINCT ON (tracks.album_id) tracks.id FROM tracks ORDER BY tracks.album_id, name)) AND (tracks.id = 5))))"
|
3356
|
-
end
|
3357
|
-
|
3358
|
-
it "should be able to filter on one_to_one associations with :filter_limit_strategy :correlated_subquery" do
|
3359
|
-
@Album.one_to_one :l_track2, :clone=>:track, :filter_limit_strategy=>:correlated_subquery
|
3360
|
-
@Album.filter(:l_track2=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT t1.id FROM tracks AS t1 WHERE (t1.album_id = tracks.album_id) LIMIT 1)) AND (tracks.id = 5))))"
|
3361
|
-
end
|
3362
|
-
|
3363
|
-
it "should be able to filter on many_to_many associations with :limit" do
|
3364
|
-
@Album.filter(:l_tags=>@Tag.load(:id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((albums_tags.album_id IS NOT NULL) AND ((albums_tags.album_id, tags.id) IN (SELECT b, c FROM (SELECT albums_tags.album_id AS b, tags.id AS c, row_number() OVER (PARTITION BY albums_tags.album_id) AS x_sequel_row_number_x FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id)) AS t1 WHERE (x_sequel_row_number_x <= 10))) AND (tags.id = 3))))"
|
3365
|
-
end
|
3366
|
-
|
3367
|
-
it "should be able to filter on one_through_one associations with :order" do
|
3368
|
-
@Album.filter(:l_tag=>@Tag.load(:id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((albums_tags.album_id IS NOT NULL) AND ((albums_tags.album_id, tags.id) IN (SELECT DISTINCT ON (albums_tags.album_id) albums_tags.album_id, tags.id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) ORDER BY albums_tags.album_id, name)) AND (tags.id = 3))))"
|
3369
|
-
end
|
3370
|
-
|
3371
|
-
it "should be able to filter on one_to_many associations with :limit and :conditions" do
|
3372
|
-
@Album.filter(:al_tracks=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'A') AND (tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT id FROM (SELECT tracks.id, row_number() OVER (PARTITION BY tracks.album_id) AS x_sequel_row_number_x FROM tracks WHERE (name = 'A')) AS t1 WHERE (x_sequel_row_number_x <= 10))) AND (tracks.id = 5))))"
|
3373
|
-
end
|
3374
|
-
|
3375
|
-
it "should be able to filter on one_to_one associations with :order and :conditions" do
|
3376
|
-
@Album.filter(:al_track=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'A') AND (tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT DISTINCT ON (tracks.album_id) tracks.id FROM tracks WHERE (name = 'A') ORDER BY tracks.album_id, name)) AND (tracks.id = 5))))"
|
3377
|
-
end
|
3378
|
-
|
3379
|
-
it "should be able to filter on many_to_many associations with :limit and :conditions" do
|
3380
|
-
@Album.filter(:al_tags=>@Tag.load(:id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'A') AND (albums_tags.album_id IS NOT NULL) AND ((albums_tags.album_id, tags.id) IN (SELECT b, c FROM (SELECT albums_tags.album_id AS b, tags.id AS c, row_number() OVER (PARTITION BY albums_tags.album_id) AS x_sequel_row_number_x FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE (name = 'A')) AS t1 WHERE (x_sequel_row_number_x <= 10))) AND (tags.id = 3))))"
|
3381
|
-
end
|
3382
|
-
|
3383
|
-
it "should be able to filter on one_through_one associations with :order and :conditions" do
|
3384
|
-
@Album.filter(:al_tag=>@Tag.load(:id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'A') AND (albums_tags.album_id IS NOT NULL) AND ((albums_tags.album_id, tags.id) IN (SELECT DISTINCT ON (albums_tags.album_id) albums_tags.album_id, tags.id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE (name = 'A') ORDER BY albums_tags.album_id, name)) AND (tags.id = 3))))"
|
3385
|
-
end
|
3386
|
-
|
3387
|
-
it "should be able to filter on many_to_one associations with composite keys" do
|
3388
|
-
@Album.filter(:cartist=>@Artist.load(:id1=>3, :id2=>4)).sql.must_equal 'SELECT * FROM albums WHERE ((albums.artist_id1 = 3) AND (albums.artist_id2 = 4))'
|
3389
|
-
end
|
3390
|
-
|
3391
|
-
it "should be able to filter on one_to_many associations with composite keys" do
|
3392
|
-
@Album.filter(:ctracks=>@Track.load(:album_id1=>3, :album_id2=>4)).sql.must_equal 'SELECT * FROM albums WHERE ((albums.id1 = 3) AND (albums.id2 = 4))'
|
3393
|
-
end
|
3394
|
-
|
3395
|
-
it "should be able to filter on one_to_one associations with composite keys" do
|
3396
|
-
@Album.filter(:calbum_info=>@AlbumInfo.load(:album_id1=>3, :album_id2=>4)).sql.must_equal 'SELECT * FROM albums WHERE ((albums.id1 = 3) AND (albums.id2 = 4))'
|
3397
|
-
end
|
3398
|
-
|
3399
|
-
it "should be able to filter on many_to_many associations with composite keys" do
|
3400
|
-
@Album.filter(:ctags=>@Tag.load(:tid1=>3, :tid2=>4)).sql.must_equal '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))))'
|
3401
|
-
end
|
3402
|
-
|
3403
|
-
it "should be able to filter on many_to_one associations with :conditions and composite keys" do
|
3404
|
-
@Album.filter(:a_cartist=>@Artist.load(:id=>5, :id1=>3, :id2=>4)).sql.must_equal "SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'A') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id = 5))))"
|
3405
|
-
end
|
3406
|
-
|
3407
|
-
it "should be able to filter on one_to_many associations with :conditions and composite keys" do
|
3408
|
-
@Album.filter(:a_ctracks=>@Track.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'A') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id = 5))))"
|
3409
|
-
end
|
3410
|
-
|
3411
|
-
it "should be able to filter on one_to_one associations with :conditions and composite keys" do
|
3412
|
-
@Album.filter(:a_calbum_info=>@AlbumInfo.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id = 5))))"
|
3413
|
-
end
|
3414
|
-
|
3415
|
-
it "should be able to filter on many_to_many associations with block and composite keys" do
|
3416
|
-
@Album.filter(:a_ctags=>@Tag.load(:id=>5, :tid1=>3, :tid2=>4)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'A') AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL) AND (tags.id = 5))))"
|
3417
|
-
end
|
3418
|
-
|
3419
|
-
it "should be able to filter on many_to_one associations with block and composite keys" do
|
3420
|
-
@Album.filter(:b_cartist=>@Artist.load(:id=>5, :id1=>3, :id2=>4)).sql.must_equal "SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'B') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id = 5))))"
|
3421
|
-
end
|
3422
|
-
|
3423
|
-
it "should be able to filter on one_to_many associations with block and composite keys" do
|
3424
|
-
@Album.filter(:b_ctracks=>@Track.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'B') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id = 5))))"
|
3425
|
-
end
|
3426
|
-
|
3427
|
-
it "should be able to filter on one_to_one associations with block and composite keys" do
|
3428
|
-
@Album.filter(:b_calbum_info=>@AlbumInfo.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'B') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id = 5))))"
|
3429
|
-
end
|
3430
|
-
|
3431
|
-
it "should be able to filter on many_to_many associations with block and composite keys" do
|
3432
|
-
@Album.filter(:b_ctags=>@Tag.load(:id=>5, :tid1=>3, :tid2=>4)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'B') AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL) AND (tags.id = 5))))"
|
3433
|
-
end
|
3434
|
-
|
3435
|
-
it "should be able to filter on one_to_many associations with :limit and composite keys" do
|
3436
|
-
@Album.filter(:l_ctracks=>@Track.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (SELECT id FROM (SELECT tracks.id, row_number() OVER (PARTITION BY tracks.album_id1, tracks.album_id2) AS x_sequel_row_number_x FROM tracks) AS t1 WHERE (x_sequel_row_number_x <= 10))) AND (tracks.id = 5))))"
|
3437
|
-
end
|
3438
|
-
|
3439
|
-
it "should be able to filter on one_to_many associations with composite keys and :filter_limit_strategy :correlated_subquery" do
|
3440
|
-
@Album.one_to_one :l_ctracks2, :clone=>:l_ctracks, :filter_limit_strategy=>:correlated_subquery
|
3441
|
-
@Album.filter(:l_ctracks2=>@Track.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (SELECT t1.id FROM tracks AS t1 WHERE ((t1.album_id1 = tracks.album_id1) AND (t1.album_id2 = tracks.album_id2)) LIMIT 1)) AND (tracks.id = 5))))"
|
3442
|
-
end
|
3443
|
-
|
3444
|
-
it "should be able to filter on one_to_one associations with :order and composite keys" do
|
3445
|
-
@Album.filter(:l_ctrack=>@Track.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (SELECT DISTINCT ON (tracks.album_id1, tracks.album_id2) tracks.id FROM tracks ORDER BY tracks.album_id1, tracks.album_id2, name)) AND (tracks.id = 5))))"
|
3446
|
-
end
|
3447
|
-
|
3448
|
-
it "should be able to filter on many_to_many associations with :limit and composite keys" do
|
3449
|
-
@Album.filter(:l_ctags=>@Tag.load(:id=>5, :tid1=>3, :tid2=>4)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL) AND ((albums_tags.album_id1, albums_tags.album_id2, tags.id) IN (SELECT b, c, d FROM (SELECT albums_tags.album_id1 AS b, albums_tags.album_id2 AS c, tags.id AS d, row_number() OVER (PARTITION BY albums_tags.album_id1, albums_tags.album_id2) AS x_sequel_row_number_x FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2))) AS t1 WHERE (x_sequel_row_number_x <= 10))) AND (tags.id = 5))))"
|
3450
|
-
end
|
3451
|
-
|
3452
|
-
it "should be able to filter on one_through_one associations with :order and composite keys" do
|
3453
|
-
@Album.filter(:l_ctag=>@Tag.load(:id=>5, :tid1=>3, :tid2=>4)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL) AND ((albums_tags.album_id1, albums_tags.album_id2, tags.id) IN (SELECT DISTINCT ON (albums_tags.album_id1, albums_tags.album_id2) albums_tags.album_id1, albums_tags.album_id2, tags.id FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) ORDER BY albums_tags.album_id1, albums_tags.album_id2, name)) AND (tags.id = 5))))"
|
3454
|
-
end
|
3455
|
-
|
3456
|
-
it "should be able to filter on one_to_many associations with :limit and :conditions and composite keys" do
|
3457
|
-
@Album.filter(:al_ctracks=>@Track.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'A') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (SELECT id FROM (SELECT tracks.id, row_number() OVER (PARTITION BY tracks.album_id1, tracks.album_id2) AS x_sequel_row_number_x FROM tracks WHERE (name = 'A')) AS t1 WHERE (x_sequel_row_number_x <= 10))) AND (tracks.id = 5))))"
|
3458
|
-
end
|
3459
|
-
|
3460
|
-
it "should be able to filter on one_to_one associations with :order and :conditions and composite keys" do
|
3461
|
-
@Album.filter(:al_ctrack=>@Track.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'A') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (SELECT DISTINCT ON (tracks.album_id1, tracks.album_id2) tracks.id FROM tracks WHERE (name = 'A') ORDER BY tracks.album_id1, tracks.album_id2, name)) AND (tracks.id = 5))))"
|
3462
|
-
end
|
3463
|
-
|
3464
|
-
it "should be able to filter on many_to_many associations with :limit and :conditions and composite keys" do
|
3465
|
-
@Album.filter(:al_ctags=>@Tag.load(:id=>5, :tid1=>3, :tid2=>4)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'A') AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL) AND ((albums_tags.album_id1, albums_tags.album_id2, tags.id) IN (SELECT b, c, d FROM (SELECT albums_tags.album_id1 AS b, albums_tags.album_id2 AS c, tags.id AS d, row_number() OVER (PARTITION BY albums_tags.album_id1, albums_tags.album_id2) AS x_sequel_row_number_x FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE (name = 'A')) AS t1 WHERE (x_sequel_row_number_x <= 10))) AND (tags.id = 5))))"
|
3466
|
-
end
|
3467
|
-
|
3468
|
-
it "should be able to filter on one_through_one associations with :order and :conditions and composite keys" do
|
3469
|
-
@Album.filter(:al_ctag=>@Tag.load(:id=>5, :tid1=>3, :tid2=>4)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'A') AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL) AND ((albums_tags.album_id1, albums_tags.album_id2, tags.id) IN (SELECT DISTINCT ON (albums_tags.album_id1, albums_tags.album_id2) albums_tags.album_id1, albums_tags.album_id2, tags.id FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE (name = 'A') ORDER BY albums_tags.album_id1, albums_tags.album_id2, name)) AND (tags.id = 5))))"
|
3470
|
-
end
|
3471
|
-
|
3472
|
-
it "should work inside a complex filter" do
|
3473
|
-
artist = @Artist.load(:id=>3)
|
3474
|
-
@Album.filter{foo & {:artist=>artist}}.sql.must_equal 'SELECT * FROM albums WHERE (foo AND (albums.artist_id = 3))'
|
3475
|
-
track = @Track.load(:album_id=>4)
|
3476
|
-
@Album.filter{foo & [[:artist, artist], [:tracks, track]]}.sql.must_equal 'SELECT * FROM albums WHERE (foo AND (albums.artist_id = 3) AND (albums.id = 4))'
|
3477
|
-
end
|
3478
|
-
|
3479
|
-
it "should raise for an invalid association name" do
|
3480
|
-
proc{@Album.filter(:foo=>@Artist.load(:id=>3)).sql}.must_raise(Sequel::Error)
|
3481
|
-
end
|
3482
|
-
|
3483
|
-
it "should raise for an invalid association type" do
|
3484
|
-
@Album.many_to_many :iatags, :clone=>:tags
|
3485
|
-
@Album.association_reflection(:iatags)[:type] = :foo
|
3486
|
-
proc{@Album.filter(:iatags=>@Tag.load(:id=>3)).sql}.must_raise(Sequel::Error)
|
3487
|
-
end
|
3488
|
-
|
3489
|
-
it "should raise for an invalid associated object class " do
|
3490
|
-
proc{@Album.filter(:tags=>@Artist.load(:id=>3)).sql}.must_raise(Sequel::Error)
|
3491
|
-
end
|
3492
|
-
|
3493
|
-
it "should raise for an invalid associated object class when multiple objects are used" do
|
3494
|
-
proc{@Album.filter(:tags=>[@Tag.load(:id=>3), @Artist.load(:id=>3)]).sql}.must_raise(Sequel::Error)
|
3495
|
-
end
|
3496
|
-
|
3497
|
-
it "should correctly handle case when a multiple value association is used" do
|
3498
|
-
proc{@Album.filter(:tags=>[@Tag.load(:id=>3), @Artist.load(:id=>3)]).sql}.must_raise(Sequel::Error)
|
3499
|
-
end
|
3500
|
-
|
3501
|
-
it "should not affect non-association IN/NOT IN filtering with an empty array" do
|
3502
|
-
@Album.filter(:tag_id=>[]).sql.must_equal 'SELECT * FROM albums WHERE (1 = 0)'
|
3503
|
-
@Album.exclude(:tag_id=>[]).sql.must_equal 'SELECT * FROM albums WHERE (1 = 1)'
|
3504
|
-
end
|
3505
|
-
|
3506
|
-
it "should work correctly in subclasses" do
|
3507
|
-
c = Class.new(@Album)
|
3508
|
-
c.many_to_one :sartist, :class=>@Artist
|
3509
|
-
c.filter(:sartist=>@Artist.load(:id=>3)).sql.must_equal 'SELECT * FROM albums WHERE (albums.sartist_id = 3)'
|
3510
|
-
end
|
3511
|
-
|
3512
|
-
it "should be able to exclude on many_to_one associations" do
|
3513
|
-
@Album.exclude(:artist=>@Artist.load(:id=>3)).sql.must_equal 'SELECT * FROM albums WHERE ((albums.artist_id != 3) OR (albums.artist_id IS NULL))'
|
3514
|
-
end
|
3515
|
-
|
3516
|
-
it "should be able to exclude on one_to_many associations" do
|
3517
|
-
@Album.exclude(:tracks=>@Track.load(:album_id=>3)).sql.must_equal 'SELECT * FROM albums WHERE ((albums.id != 3) OR (albums.id IS NULL))'
|
3518
|
-
end
|
3519
|
-
|
3520
|
-
it "should be able to exclude on one_to_one associations" do
|
3521
|
-
@Album.exclude(:album_info=>@AlbumInfo.load(:album_id=>3)).sql.must_equal 'SELECT * FROM albums WHERE ((albums.id != 3) OR (albums.id IS NULL))'
|
3522
|
-
end
|
3523
|
-
|
3524
|
-
it "should be able to exclude on many_to_many associations" do
|
3525
|
-
@Album.exclude(:tags=>@Tag.load(:id=>3)).sql.must_equal '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))'
|
3526
|
-
end
|
3527
|
-
|
3528
|
-
it "should be able to exclude on many_to_one associations with :conditions" do
|
3529
|
-
@Album.exclude(:a_artist=>@Artist.load(:id=>3)).sql.must_equal "SELECT * FROM albums WHERE ((albums.artist_id NOT IN (SELECT artists.id FROM artists WHERE ((name = 'A') AND (artists.id IS NOT NULL) AND (artists.id = 3)))) OR (albums.artist_id IS NULL))"
|
3530
|
-
end
|
3531
|
-
|
3532
|
-
it "should be able to exclude on one_to_many associations with :conditions" do
|
3533
|
-
@Album.exclude(:a_tracks=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'A') AND (tracks.album_id IS NOT NULL) AND (tracks.id = 5)))) OR (albums.id IS NULL))"
|
3534
|
-
end
|
3535
|
-
|
3536
|
-
it "should be able to exclude on one_to_one associations with :conditions" do
|
3537
|
-
@Album.exclude(:a_album_info=>@AlbumInfo.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id = 5)))) OR (albums.id IS NULL))"
|
3538
|
-
end
|
3539
|
-
|
3540
|
-
it "should be able to exclude on many_to_many associations with :conditions" do
|
3541
|
-
@Album.exclude(:a_tags=>@Tag.load(:id=>3)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'A') AND (albums_tags.album_id IS NOT NULL) AND (tags.id = 3)))) OR (albums.id IS NULL))"
|
3542
|
-
end
|
3543
|
-
|
3544
|
-
it "should be able to exclude on many_to_one associations with block" do
|
3545
|
-
@Album.exclude(:b_artist=>@Artist.load(:id=>3)).sql.must_equal "SELECT * FROM albums WHERE ((albums.artist_id NOT IN (SELECT artists.id FROM artists WHERE ((name = 'B') AND (artists.id IS NOT NULL) AND (artists.id = 3)))) OR (albums.artist_id IS NULL))"
|
3546
|
-
end
|
3547
|
-
|
3548
|
-
it "should be able to exclude on one_to_many associations with block" do
|
3549
|
-
@Album.exclude(:b_tracks=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'B') AND (tracks.album_id IS NOT NULL) AND (tracks.id = 5)))) OR (albums.id IS NULL))"
|
3550
|
-
end
|
3551
|
-
|
3552
|
-
it "should be able to exclude on one_to_one associations with block" do
|
3553
|
-
@Album.exclude(:b_album_info=>@AlbumInfo.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'B') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id = 5)))) OR (albums.id IS NULL))"
|
3554
|
-
end
|
3555
|
-
|
3556
|
-
it "should be able to exclude on many_to_many associations with block" do
|
3557
|
-
@Album.exclude(:b_tags=>@Tag.load(:id=>3)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'B') AND (albums_tags.album_id IS NOT NULL) AND (tags.id = 3)))) OR (albums.id IS NULL))"
|
3558
|
-
end
|
3559
|
-
|
3560
|
-
it "should be able to exclude on many_to_one associations with composite keys" do
|
3561
|
-
@Album.exclude(:cartist=>@Artist.load(:id1=>3, :id2=>4)).sql.must_equal '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))'
|
3562
|
-
end
|
3563
|
-
|
3564
|
-
it "should be able to exclude on one_to_many associations with composite keys" do
|
3565
|
-
@Album.exclude(:ctracks=>@Track.load(:album_id1=>3, :album_id2=>4)).sql.must_equal 'SELECT * FROM albums WHERE ((albums.id1 != 3) OR (albums.id2 != 4) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
3566
|
-
end
|
3567
|
-
|
3568
|
-
it "should be able to exclude on one_to_one associations with composite keys" do
|
3569
|
-
@Album.exclude(:calbum_info=>@AlbumInfo.load(:album_id1=>3, :album_id2=>4)).sql.must_equal 'SELECT * FROM albums WHERE ((albums.id1 != 3) OR (albums.id2 != 4) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
3570
|
-
end
|
3571
|
-
|
3572
|
-
it "should be able to exclude on many_to_many associations with composite keys" do
|
3573
|
-
@Album.exclude(:ctags=>@Tag.load(:tid1=>3, :tid2=>4)).sql.must_equal '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))'
|
3574
|
-
end
|
3575
|
-
|
3576
|
-
it "should be able to exclude on many_to_one associations with :conditions and composite keys" do
|
3577
|
-
@Album.exclude(:a_cartist=>@Artist.load(:id=>5, :id1=>3, :id2=>4)).sql.must_equal "SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'A') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id = 5)))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))"
|
3578
|
-
end
|
3579
|
-
|
3580
|
-
it "should be able to exclude on one_to_many associations with :conditions and composite keys" do
|
3581
|
-
@Album.exclude(:a_ctracks=>@Track.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'A') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id = 5)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
3582
|
-
end
|
3583
|
-
|
3584
|
-
it "should be able to exclude on one_to_one associations with :conditions and composite keys" do
|
3585
|
-
@Album.exclude(:a_calbum_info=>@AlbumInfo.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id = 5)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
3586
|
-
end
|
3587
|
-
|
3588
|
-
it "should be able to exclude on many_to_many associations with block and composite keys" do
|
3589
|
-
@Album.exclude(:a_ctags=>@Tag.load(:id=>5, :tid1=>3, :tid2=>4)).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'A') AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL) AND (tags.id = 5)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
3590
|
-
end
|
3591
|
-
|
3592
|
-
it "should be able to exclude on many_to_one associations with block and composite keys" do
|
3593
|
-
@Album.exclude(:b_cartist=>@Artist.load(:id=>5, :id1=>3, :id2=>4)).sql.must_equal "SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'B') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id = 5)))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))"
|
3594
|
-
end
|
3595
|
-
|
3596
|
-
it "should be able to exclude on one_to_many associations with block and composite keys" do
|
3597
|
-
@Album.exclude(:b_ctracks=>@Track.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'B') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id = 5)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
3598
|
-
end
|
3599
|
-
|
3600
|
-
it "should be able to exclude on one_to_one associations with block and composite keys" do
|
3601
|
-
@Album.exclude(:b_calbum_info=>@AlbumInfo.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'B') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id = 5)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
3602
|
-
end
|
3603
|
-
|
3604
|
-
it "should be able to exclude on many_to_many associations with block and composite keys" do
|
3605
|
-
@Album.exclude(:b_ctags=>@Tag.load(:id=>5, :tid1=>3, :tid2=>4)).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'B') AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL) AND (tags.id = 5)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
3606
|
-
end
|
3607
|
-
|
3608
|
-
it "should be able to filter on multiple many_to_one associations" do
|
3609
|
-
@Album.filter(:artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.must_equal 'SELECT * FROM albums WHERE (albums.artist_id IN (3, 4))'
|
3610
|
-
end
|
3611
|
-
|
3612
|
-
it "should be able to filter on multiple one_to_many associations" do
|
3613
|
-
@Album.filter(:tracks=>[@Track.load(:album_id=>3), @Track.load(:album_id=>4)]).sql.must_equal 'SELECT * FROM albums WHERE (albums.id IN (3, 4))'
|
3614
|
-
end
|
3615
|
-
|
3616
|
-
it "should be able to filter on multiple one_to_one associations" do
|
3617
|
-
@Album.filter(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.load(:album_id=>4)]).sql.must_equal 'SELECT * FROM albums WHERE (albums.id IN (3, 4))'
|
3618
|
-
end
|
3619
|
-
|
3620
|
-
it "should be able to filter on multiple many_to_many associations" do
|
3621
|
-
@Album.filter(:tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.must_equal '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))))'
|
3622
|
-
end
|
3623
|
-
|
3624
|
-
it "should be able to filter on multiple many_to_one associations with :conditions" do
|
3625
|
-
@Album.filter(:a_artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.must_equal "SELECT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists WHERE ((name = 'A') AND (artists.id IS NOT NULL) AND (artists.id IN (3, 4)))))"
|
3626
|
-
end
|
3627
|
-
|
3628
|
-
it "should be able to filter on multiple one_to_many associations with :conditions" do
|
3629
|
-
@Album.filter(:a_tracks=>[@Track.load(:id=>5, :album_id=>3), @Track.load(:id=>6, :album_id=>4)]).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'A') AND (tracks.album_id IS NOT NULL) AND (tracks.id IN (5, 6)))))"
|
3630
|
-
end
|
3631
|
-
|
3632
|
-
it "should be able to filter on multiple one_to_one associations with :conditions" do
|
3633
|
-
@Album.filter(:a_album_info=>[@AlbumInfo.load(:id=>5, :album_id=>3), @AlbumInfo.load(:id=>6, :album_id=>4)]).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id IN (5, 6)))))"
|
3634
|
-
end
|
3635
|
-
|
3636
|
-
it "should be able to filter on multiple many_to_many associations with :conditions" do
|
3637
|
-
@Album.filter(:a_tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'A') AND (albums_tags.album_id IS NOT NULL) AND (tags.id IN (3, 4)))))"
|
3638
|
-
end
|
3639
|
-
|
3640
|
-
it "should be able to filter on multiple many_to_one associations with block" do
|
3641
|
-
@Album.filter(:b_artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.must_equal "SELECT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists WHERE ((name = 'B') AND (artists.id IS NOT NULL) AND (artists.id IN (3, 4)))))"
|
3642
|
-
end
|
3643
|
-
|
3644
|
-
it "should be able to filter on multiple one_to_many associations with block" do
|
3645
|
-
@Album.filter(:b_tracks=>[@Track.load(:id=>5, :album_id=>3), @Track.load(:id=>6, :album_id=>4)]).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'B') AND (tracks.album_id IS NOT NULL) AND (tracks.id IN (5, 6)))))"
|
3646
|
-
end
|
3647
|
-
|
3648
|
-
it "should be able to filter on multiple one_to_one associations with block" do
|
3649
|
-
@Album.filter(:b_album_info=>[@AlbumInfo.load(:id=>5, :album_id=>3), @AlbumInfo.load(:id=>6, :album_id=>4)]).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'B') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id IN (5, 6)))))"
|
3650
|
-
end
|
3651
|
-
|
3652
|
-
it "should be able to filter on multiple many_to_many associations with block" do
|
3653
|
-
@Album.filter(:b_tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'B') AND (albums_tags.album_id IS NOT NULL) AND (tags.id IN (3, 4)))))"
|
3654
|
-
end
|
3655
|
-
|
3656
|
-
it "should be able to filter on multiple many_to_one associations with composite keys" do
|
3657
|
-
@Album.filter(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>5, :id2=>6)]).sql.must_equal 'SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN ((3, 4), (5, 6)))'
|
3658
|
-
end
|
3659
|
-
|
3660
|
-
it "should be able to filter on multiple one_to_many associations with composite keys" do
|
3661
|
-
@Album.filter(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.load(:album_id1=>5, :album_id2=>6)]).sql.must_equal 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN ((3, 4), (5, 6)))'
|
3662
|
-
end
|
3663
|
-
|
3664
|
-
it "should be able to filter on multiple one_to_one associations with composite keys" do
|
3665
|
-
@Album.filter(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.load(:album_id1=>5, :album_id2=>6)]).sql.must_equal 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN ((3, 4), (5, 6)))'
|
3666
|
-
end
|
3667
|
-
|
3668
|
-
it "should be able to filter on multiple many_to_many associations with composite keys" do
|
3669
|
-
@Album.filter(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5, :tid2=>6)]).sql.must_equal '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))))'
|
3670
|
-
end
|
3671
|
-
|
3672
|
-
it "should be able to filter on multiple many_to_one associations with :conditions and composite keys" do
|
3673
|
-
@Album.filter(:a_cartist=>[@Artist.load(:id=>7, :id1=>3, :id2=>4), @Artist.load(:id=>8, :id1=>5, :id2=>6)]).sql.must_equal "SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'A') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id IN (7, 8)))))"
|
3674
|
-
end
|
3675
|
-
|
3676
|
-
it "should be able to filter on multiple one_to_many associations with :conditions and composite keys" do
|
3677
|
-
@Album.filter(:a_ctracks=>[@Track.load(:id=>7, :album_id1=>3, :album_id2=>4), @Track.load(:id=>8, :album_id1=>5, :album_id2=>6)]).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'A') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (7, 8)))))"
|
3678
|
-
end
|
3679
|
-
|
3680
|
-
it "should be able to filter on multiple one_to_one associations with :conditions and composite keys" do
|
3681
|
-
@Album.filter(:a_calbum_info=>[@AlbumInfo.load(:id=>7, :album_id1=>3, :album_id2=>4), @AlbumInfo.load(:id=>8, :album_id1=>5, :album_id2=>6)]).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id IN (7, 8)))))"
|
3682
|
-
end
|
3683
|
-
|
3684
|
-
it "should be able to filter on multiple many_to_many associations with block and composite keys" do
|
3685
|
-
@Album.filter(:a_ctags=>[@Tag.load(:id=>7, :tid1=>3, :tid2=>4), @Tag.load(:id=>8, :tid1=>5, :tid2=>6)]).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'A') AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL) AND (tags.id IN (7, 8)))))"
|
3686
|
-
end
|
3687
|
-
|
3688
|
-
it "should be able to filter on multiple many_to_one associations with block and composite keys" do
|
3689
|
-
@Album.filter(:b_cartist=>[@Artist.load(:id=>7, :id1=>3, :id2=>4), @Artist.load(:id=>8, :id1=>5, :id2=>6)]).sql.must_equal "SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'B') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id IN (7, 8)))))"
|
3690
|
-
end
|
3691
|
-
|
3692
|
-
it "should be able to filter on multiple one_to_many associations with block and composite keys" do
|
3693
|
-
@Album.filter(:b_ctracks=>[@Track.load(:id=>7, :album_id1=>3, :album_id2=>4), @Track.load(:id=>8, :album_id1=>5, :album_id2=>6)]).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'B') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (7, 8)))))"
|
3694
|
-
end
|
3695
|
-
|
3696
|
-
it "should be able to filter on multiple one_to_one associations with block and composite keys" do
|
3697
|
-
@Album.filter(:b_calbum_info=>[@AlbumInfo.load(:id=>7, :album_id1=>3, :album_id2=>4), @AlbumInfo.load(:id=>8, :album_id1=>5, :album_id2=>6)]).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'B') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id IN (7, 8)))))"
|
3698
|
-
end
|
3699
|
-
|
3700
|
-
it "should be able to filter on multiple many_to_many associations with block and composite keys" do
|
3701
|
-
@Album.filter(:b_ctags=>[@Tag.load(:id=>7, :tid1=>3, :tid2=>4), @Tag.load(:id=>8, :tid1=>5, :tid2=>6)]).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'B') AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL) AND (tags.id IN (7, 8)))))"
|
3702
|
-
end
|
3703
|
-
|
3704
|
-
it "should be able to exclude on multiple many_to_one associations" do
|
3705
|
-
@Album.exclude(:artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.must_equal 'SELECT * FROM albums WHERE ((albums.artist_id NOT IN (3, 4)) OR (albums.artist_id IS NULL))'
|
3706
|
-
end
|
3707
|
-
|
3708
|
-
it "should be able to exclude on multiple one_to_many associations" do
|
3709
|
-
@Album.exclude(:tracks=>[@Track.load(:album_id=>3), @Track.load(:album_id=>4)]).sql.must_equal 'SELECT * FROM albums WHERE ((albums.id NOT IN (3, 4)) OR (albums.id IS NULL))'
|
3710
|
-
end
|
3711
|
-
|
3712
|
-
it "should be able to exclude on multiple one_to_one associations" do
|
3713
|
-
@Album.exclude(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.load(:album_id=>4)]).sql.must_equal 'SELECT * FROM albums WHERE ((albums.id NOT IN (3, 4)) OR (albums.id IS NULL))'
|
3714
|
-
end
|
3715
|
-
|
3716
|
-
it "should be able to exclude on multiple many_to_many associations" do
|
3717
|
-
@Album.exclude(:tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.must_equal '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))'
|
3718
|
-
end
|
3719
|
-
|
3720
|
-
it "should be able to exclude on multiple many_to_one associations with :conditions" do
|
3721
|
-
@Album.exclude(:a_artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.must_equal "SELECT * FROM albums WHERE ((albums.artist_id NOT IN (SELECT artists.id FROM artists WHERE ((name = 'A') AND (artists.id IS NOT NULL) AND (artists.id IN (3, 4))))) OR (albums.artist_id IS NULL))"
|
3722
|
-
end
|
3723
|
-
|
3724
|
-
it "should be able to exclude on multiple one_to_many associations with :conditions" do
|
3725
|
-
@Album.exclude(:a_tracks=>[@Track.load(:id=>5, :album_id=>3), @Track.load(:id=>6, :album_id=>4)]).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'A') AND (tracks.album_id IS NOT NULL) AND (tracks.id IN (5, 6))))) OR (albums.id IS NULL))"
|
3726
|
-
end
|
3727
|
-
|
3728
|
-
it "should be able to exclude on multiple one_to_one associations with :conditions" do
|
3729
|
-
@Album.exclude(:a_album_info=>[@AlbumInfo.load(:id=>5, :album_id=>3), @AlbumInfo.load(:id=>6, :album_id=>4)]).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id IN (5, 6))))) OR (albums.id IS NULL))"
|
3730
|
-
end
|
3731
|
-
|
3732
|
-
it "should be able to exclude on multiple many_to_many associations with :conditions" do
|
3733
|
-
@Album.exclude(:a_tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'A') AND (albums_tags.album_id IS NOT NULL) AND (tags.id IN (3, 4))))) OR (albums.id IS NULL))"
|
3734
|
-
end
|
3735
|
-
|
3736
|
-
it "should be able to exclude on multiple many_to_one associations with block" do
|
3737
|
-
@Album.exclude(:b_artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.must_equal "SELECT * FROM albums WHERE ((albums.artist_id NOT IN (SELECT artists.id FROM artists WHERE ((name = 'B') AND (artists.id IS NOT NULL) AND (artists.id IN (3, 4))))) OR (albums.artist_id IS NULL))"
|
3738
|
-
end
|
3739
|
-
|
3740
|
-
it "should be able to exclude on multiple one_to_many associations with block" do
|
3741
|
-
@Album.exclude(:b_tracks=>[@Track.load(:id=>5, :album_id=>3), @Track.load(:id=>6, :album_id=>4)]).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'B') AND (tracks.album_id IS NOT NULL) AND (tracks.id IN (5, 6))))) OR (albums.id IS NULL))"
|
3742
|
-
end
|
3743
|
-
|
3744
|
-
it "should be able to exclude on multiple one_to_one associations with block" do
|
3745
|
-
@Album.exclude(:b_album_info=>[@AlbumInfo.load(:id=>5, :album_id=>3), @AlbumInfo.load(:id=>6, :album_id=>4)]).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'B') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id IN (5, 6))))) OR (albums.id IS NULL))"
|
3746
|
-
end
|
3747
|
-
|
3748
|
-
it "should be able to exclude on multiple many_to_many associations with block" do
|
3749
|
-
@Album.exclude(:b_tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'B') AND (albums_tags.album_id IS NOT NULL) AND (tags.id IN (3, 4))))) OR (albums.id IS NULL))"
|
3750
|
-
end
|
3751
|
-
|
3752
|
-
it "should be able to exclude on multiple many_to_one associations with composite keys" do
|
3753
|
-
@Album.exclude(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>5, :id2=>6)]).sql.must_equal '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))'
|
3754
|
-
end
|
3755
|
-
|
3756
|
-
it "should be able to exclude on multiple one_to_many associations with composite keys" do
|
3757
|
-
@Album.exclude(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.load(:album_id1=>5, :album_id2=>6)]).sql.must_equal 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4), (5, 6))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
3758
|
-
end
|
3759
|
-
|
3760
|
-
it "should be able to exclude on multiple one_to_one associations with composite keys" do
|
3761
|
-
@Album.exclude(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.load(:album_id1=>5, :album_id2=>6)]).sql.must_equal 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4), (5, 6))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
3762
|
-
end
|
3763
|
-
|
3764
|
-
it "should be able to exclude on multiple many_to_many associations with composite keys" do
|
3765
|
-
@Album.exclude(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5, :tid2=>6)]).sql.must_equal '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))'
|
3766
|
-
end
|
3767
|
-
|
3768
|
-
it "should be able to exclude on multiple many_to_one associations with :conditions and composite keys" do
|
3769
|
-
@Album.exclude(:a_cartist=>[@Artist.load(:id=>7, :id1=>3, :id2=>4), @Artist.load(:id=>8, :id1=>5, :id2=>6)]).sql.must_equal "SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'A') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id IN (7, 8))))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))"
|
3770
|
-
end
|
3771
|
-
|
3772
|
-
it "should be able to exclude on multiple one_to_many associations with :conditions and composite keys" do
|
3773
|
-
@Album.exclude(:a_ctracks=>[@Track.load(:id=>7, :album_id1=>3, :album_id2=>4), @Track.load(:id=>8, :album_id1=>5, :album_id2=>6)]).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'A') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (7, 8))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
3774
|
-
end
|
3775
|
-
|
3776
|
-
it "should be able to exclude on multiple one_to_one associations with :conditions and composite keys" do
|
3777
|
-
@Album.exclude(:a_calbum_info=>[@AlbumInfo.load(:id=>7, :album_id1=>3, :album_id2=>4), @AlbumInfo.load(:id=>8, :album_id1=>5, :album_id2=>6)]).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id IN (7, 8))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
3778
|
-
end
|
3779
|
-
|
3780
|
-
it "should be able to exclude on multiple many_to_many associations with :conditions and composite keys" do
|
3781
|
-
@Album.exclude(:a_ctags=>[@Tag.load(:id=>7, :tid1=>3, :tid2=>4), @Tag.load(:id=>8, :tid1=>5, :tid2=>6)]).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'A') AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL) AND (tags.id IN (7, 8))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
3782
|
-
end
|
3783
|
-
|
3784
|
-
it "should be able to exclude on multiple many_to_one associations with block and composite keys" do
|
3785
|
-
@Album.exclude(:b_cartist=>[@Artist.load(:id=>7, :id1=>3, :id2=>4), @Artist.load(:id=>8, :id1=>5, :id2=>6)]).sql.must_equal "SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'B') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id IN (7, 8))))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))"
|
3786
|
-
end
|
3787
|
-
|
3788
|
-
it "should be able to exclude on multiple one_to_many associations with block and composite keys" do
|
3789
|
-
@Album.exclude(:b_ctracks=>[@Track.load(:id=>7, :album_id1=>3, :album_id2=>4), @Track.load(:id=>8, :album_id1=>5, :album_id2=>6)]).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'B') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (7, 8))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
3790
|
-
end
|
3791
|
-
|
3792
|
-
it "should be able to exclude on multiple one_to_one associations with block and composite keys" do
|
3793
|
-
@Album.exclude(:b_calbum_info=>[@AlbumInfo.load(:id=>7, :album_id1=>3, :album_id2=>4), @AlbumInfo.load(:id=>8, :album_id1=>5, :album_id2=>6)]).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'B') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id IN (7, 8))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
3794
|
-
end
|
3795
|
-
|
3796
|
-
it "should be able to exclude on multiple many_to_many associations with block and composite keys" do
|
3797
|
-
@Album.exclude(:b_ctags=>[@Tag.load(:id=>7, :tid1=>3, :tid2=>4), @Tag.load(:id=>8, :tid1=>5, :tid2=>6)]).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'B') AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL) AND (tags.id IN (7, 8))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
3798
|
-
end
|
3799
|
-
|
3800
|
-
it "should be able to handle NULL values when filtering many_to_one associations" do
|
3801
|
-
@Album.filter(:artist=>@Artist.new).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3802
|
-
end
|
3803
|
-
|
3804
|
-
it "should be able to handle NULL values when filtering one_to_many associations" do
|
3805
|
-
@Album.filter(:tracks=>@Track.new).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3806
|
-
end
|
3807
|
-
|
3808
|
-
it "should be able to handle NULL values when filtering one_to_one associations" do
|
3809
|
-
@Album.filter(:album_info=>@AlbumInfo.new).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3810
|
-
end
|
3811
|
-
|
3812
|
-
it "should be able to handle NULL values when filtering many_to_many associations" do
|
3813
|
-
@Album.filter(:tags=>@Tag.new).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3814
|
-
end
|
3815
|
-
|
3816
|
-
it "should be able to handle filtering with NULL values for many_to_one associations with composite keys" do
|
3817
|
-
@Album.filter(:cartist=>@Artist.load(:id2=>4)).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3818
|
-
@Album.filter(:cartist=>@Artist.load(:id1=>3)).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3819
|
-
@Album.filter(:cartist=>@Artist.new).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3820
|
-
end
|
3821
|
-
|
3822
|
-
it "should be able to filter with NULL values for one_to_many associations with composite keys" do
|
3823
|
-
@Album.filter(:ctracks=>@Track.load(:album_id2=>4)).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3824
|
-
@Album.filter(:ctracks=>@Track.load(:album_id1=>3)).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3825
|
-
@Album.filter(:ctracks=>@Track.new).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3826
|
-
end
|
3827
|
-
|
3828
|
-
it "should be able to filter with NULL values for one_to_one associations with composite keys" do
|
3829
|
-
@Album.filter(:calbum_info=>@AlbumInfo.load(:album_id2=>4)).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3830
|
-
@Album.filter(:calbum_info=>@AlbumInfo.load(:album_id1=>3)).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3831
|
-
@Album.filter(:calbum_info=>@AlbumInfo.new).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3832
|
-
end
|
3833
|
-
|
3834
|
-
it "should be able to filter with NULL values for many_to_many associations with composite keys" do
|
3835
|
-
@Album.filter(:ctags=>@Tag.load(:tid1=>3)).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3836
|
-
@Album.filter(:ctags=>@Tag.load(:tid2=>4)).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3837
|
-
@Album.filter(:ctags=>@Tag.new).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3838
|
-
end
|
3839
|
-
|
3840
|
-
it "should be able to handle NULL values when excluding many_to_one associations" do
|
3841
|
-
@Album.exclude(:artist=>@Artist.new).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3842
|
-
end
|
3843
|
-
|
3844
|
-
it "should be able to handle NULL values when excluding one_to_many associations" do
|
3845
|
-
@Album.exclude(:tracks=>@Track.new).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3846
|
-
end
|
3847
|
-
|
3848
|
-
it "should be able to handle NULL values when excluding one_to_one associations" do
|
3849
|
-
@Album.exclude(:album_info=>@AlbumInfo.new).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3850
|
-
end
|
3851
|
-
|
3852
|
-
it "should be able to handle NULL values when excluding many_to_many associations" do
|
3853
|
-
@Album.exclude(:tags=>@Tag.new).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3854
|
-
end
|
3855
|
-
|
3856
|
-
it "should be able to handle excluding with NULL values for many_to_one associations with composite keys" do
|
3857
|
-
@Album.exclude(:cartist=>@Artist.load(:id2=>4)).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3858
|
-
@Album.exclude(:cartist=>@Artist.load(:id1=>3)).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3859
|
-
@Album.exclude(:cartist=>@Artist.new).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3860
|
-
end
|
3861
|
-
|
3862
|
-
it "should be able to excluding with NULL values for one_to_many associations with composite keys" do
|
3863
|
-
@Album.exclude(:ctracks=>@Track.load(:album_id2=>4)).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3864
|
-
@Album.exclude(:ctracks=>@Track.load(:album_id1=>3)).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3865
|
-
@Album.exclude(:ctracks=>@Track.new).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3866
|
-
end
|
3867
|
-
|
3868
|
-
it "should be able to excluding with NULL values for one_to_one associations with composite keys" do
|
3869
|
-
@Album.exclude(:calbum_info=>@AlbumInfo.load(:album_id2=>4)).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3870
|
-
@Album.exclude(:calbum_info=>@AlbumInfo.load(:album_id1=>3)).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3871
|
-
@Album.exclude(:calbum_info=>@AlbumInfo.new).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3872
|
-
end
|
3873
|
-
|
3874
|
-
it "should be able to excluding with NULL values for many_to_many associations with composite keys" do
|
3875
|
-
@Album.exclude(:ctags=>@Tag.load(:tid1=>3)).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3876
|
-
@Album.exclude(:ctags=>@Tag.load(:tid2=>4)).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3877
|
-
@Album.exclude(:ctags=>@Tag.new).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3878
|
-
end
|
3879
|
-
|
3880
|
-
it "should be able to handle NULL values when filtering multiple many_to_one associations" do
|
3881
|
-
@Album.filter(:artist=>[@Artist.load(:id=>3), @Artist.new]).sql.must_equal 'SELECT * FROM albums WHERE (albums.artist_id IN (3))'
|
3882
|
-
@Album.filter(:artist=>[@Artist.new, @Artist.new]).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3883
|
-
end
|
3884
|
-
|
3885
|
-
it "should be able to handle NULL values when filtering multiple one_to_many associations" do
|
3886
|
-
@Album.filter(:tracks=>[@Track.load(:album_id=>3), @Track.new]).sql.must_equal 'SELECT * FROM albums WHERE (albums.id IN (3))'
|
3887
|
-
@Album.filter(:tracks=>[@Track.new, @Track.new]).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3888
|
-
end
|
3889
|
-
|
3890
|
-
it "should be able to handle NULL values when filtering multiple one_to_one associations" do
|
3891
|
-
@Album.filter(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.new]).sql.must_equal 'SELECT * FROM albums WHERE (albums.id IN (3))'
|
3892
|
-
@Album.filter(:album_info=>[@AlbumInfo.new, @AlbumInfo.new]).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3893
|
-
end
|
3894
|
-
|
3895
|
-
it "should be able to handle NULL values when filtering multiple many_to_many associations" do
|
3896
|
-
@Album.filter(:tags=>[@Tag.load(:id=>3), @Tag.new]).sql.must_equal '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))))'
|
3897
|
-
@Album.filter(:tags=>[@Tag.new, @Tag.new]).sql.must_equal 'SELECT * FROM albums WHERE \'f\''
|
3898
|
-
end
|
3899
|
-
|
3900
|
-
it "should be able to handle NULL values when filtering multiple many_to_one associations with composite keys" do
|
3901
|
-
@Album.filter(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>3)]).sql.must_equal 'SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN ((3, 4)))'
|
3902
|
-
@Album.filter(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.new]).sql.must_equal 'SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN ((3, 4)))'
|
3903
|
-
end
|
3904
|
-
|
3905
|
-
it "should be able handle NULL values when filtering multiple one_to_many associations with composite keys" do
|
3906
|
-
@Album.filter(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.load(:album_id1=>3)]).sql.must_equal 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN ((3, 4)))'
|
3907
|
-
@Album.filter(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.new]).sql.must_equal 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN ((3, 4)))'
|
3908
|
-
end
|
3909
|
-
|
3910
|
-
it "should be able to handle NULL values when filtering multiple one_to_one associations with composite keys" do
|
3911
|
-
@Album.filter(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.load(:album_id1=>5)]).sql.must_equal 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN ((3, 4)))'
|
3912
|
-
@Album.filter(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.new]).sql.must_equal 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN ((3, 4)))'
|
3913
|
-
end
|
3914
|
-
|
3915
|
-
it "should be able to handle NULL values when filtering multiple many_to_many associations with composite keys" do
|
3916
|
-
@Album.filter(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5)]).sql.must_equal '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))))'
|
3917
|
-
@Album.filter(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.new]).sql.must_equal '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))))'
|
3918
|
-
end
|
3919
|
-
|
3920
|
-
it "should be able to handle NULL values when excluding multiple many_to_one associations" do
|
3921
|
-
@Album.exclude(:artist=>[@Artist.load(:id=>3), @Artist.new]).sql.must_equal 'SELECT * FROM albums WHERE ((albums.artist_id NOT IN (3)) OR (albums.artist_id IS NULL))'
|
3922
|
-
@Album.exclude(:artist=>[@Artist.new, @Artist.new]).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3923
|
-
end
|
3924
|
-
|
3925
|
-
it "should be able to handle NULL values when excluding multiple one_to_many associations" do
|
3926
|
-
@Album.exclude(:tracks=>[@Track.load(:album_id=>3), @Track.new]).sql.must_equal 'SELECT * FROM albums WHERE ((albums.id NOT IN (3)) OR (albums.id IS NULL))'
|
3927
|
-
@Album.exclude(:tracks=>[@Track.new, @Track.new]).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3928
|
-
end
|
3929
|
-
|
3930
|
-
it "should be able to handle NULL values when excluding multiple one_to_one associations" do
|
3931
|
-
@Album.exclude(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.new]).sql.must_equal 'SELECT * FROM albums WHERE ((albums.id NOT IN (3)) OR (albums.id IS NULL))'
|
3932
|
-
@Album.exclude(:album_info=>[@AlbumInfo.new, @AlbumInfo.new]).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3933
|
-
end
|
3934
|
-
|
3935
|
-
it "should be able to handle NULL values when excluding multiple many_to_many associations" do
|
3936
|
-
@Album.exclude(:tags=>[@Tag.load(:id=>3), @Tag.new]).sql.must_equal '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))'
|
3937
|
-
@Album.exclude(:tags=>[@Tag.new, @Tag.new]).sql.must_equal 'SELECT * FROM albums WHERE \'t\''
|
3938
|
-
end
|
3939
|
-
|
3940
|
-
it "should be able to handle NULL values when excluding multiple many_to_one associations with composite keys" do
|
3941
|
-
@Album.exclude(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>3)]).sql.must_equal '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))'
|
3942
|
-
@Album.exclude(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.new]).sql.must_equal '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))'
|
3943
|
-
end
|
3944
|
-
|
3945
|
-
it "should be able handle NULL values when excluding multiple one_to_many associations with composite keys" do
|
3946
|
-
@Album.exclude(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.load(:album_id1=>3)]).sql.must_equal 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
3947
|
-
@Album.exclude(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.new]).sql.must_equal 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
3948
|
-
end
|
3949
|
-
|
3950
|
-
it "should be able to handle NULL values when excluding multiple one_to_one associations with composite keys" do
|
3951
|
-
@Album.exclude(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.load(:album_id1=>5)]).sql.must_equal 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
3952
|
-
@Album.exclude(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.new]).sql.must_equal 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
|
3953
|
-
end
|
3954
|
-
|
3955
|
-
it "should be able to handle NULL values when excluding multiple many_to_many associations with composite keys" do
|
3956
|
-
@Album.exclude(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5)]).sql.must_equal '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))'
|
3957
|
-
@Album.exclude(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.new]).sql.must_equal '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))'
|
3958
|
-
end
|
3959
|
-
|
3960
|
-
it "should be able to filter on many_to_one association datasets" do
|
3961
|
-
@Album.filter(:artist=>@Artist.filter(:x=>1)).sql.must_equal 'SELECT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists WHERE ((x = 1) AND (artists.id IS NOT NULL))))'
|
3962
|
-
end
|
3963
|
-
|
3964
|
-
it "should be able to filter on one_to_many association datasets" do
|
3965
|
-
@Album.filter(:tracks=>@Track.filter(:x=>1)).sql.must_equal 'SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((x = 1) AND (tracks.album_id IS NOT NULL))))'
|
3966
|
-
end
|
3967
|
-
|
3968
|
-
it "should be able to filter on one_to_one association datasets" do
|
3969
|
-
@Album.filter(:album_info=>@AlbumInfo.filter(:x=>1)).sql.must_equal '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))))'
|
3970
|
-
end
|
3971
|
-
|
3972
|
-
it "should be able to filter on many_to_many association datasets" do
|
3973
|
-
@Album.filter(:tags=>@Tag.filter(:x=>1)).sql.must_equal '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))))'
|
3974
|
-
end
|
3975
|
-
|
3976
|
-
it "should be able to filter on many_to_one association datasets with :conditions" do
|
3977
|
-
@Album.filter(:a_artist=>@Artist.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists WHERE ((name = 'A') AND (artists.id IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (x = 1))))))"
|
3978
|
-
end
|
3979
|
-
|
3980
|
-
it "should be able to filter on one_to_many association datasets with :conditions" do
|
3981
|
-
@Album.filter(:a_tracks=>@Track.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'A') AND (tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT tracks.id FROM tracks WHERE (x = 1))))))"
|
3982
|
-
end
|
3983
|
-
|
3984
|
-
it "should be able to filter on one_to_one association datasets with :conditions" do
|
3985
|
-
@Album.filter(:a_album_info=>@AlbumInfo.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id IN (SELECT album_infos.id FROM album_infos WHERE (x = 1))))))"
|
3986
|
-
end
|
3987
|
-
|
3988
|
-
it "should be able to filter on many_to_many association datasets with :conditions" do
|
3989
|
-
@Album.filter(:a_tags=>@Tag.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'A') AND (albums_tags.album_id IS NOT NULL) AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1))))))"
|
3990
|
-
end
|
3991
|
-
|
3992
|
-
it "should be able to filter on many_to_one association datasets with block" do
|
3993
|
-
@Album.filter(:b_artist=>@Artist.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists WHERE ((name = 'B') AND (artists.id IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (x = 1))))))"
|
3994
|
-
end
|
3995
|
-
|
3996
|
-
it "should be able to filter on one_to_many association datasets with block" do
|
3997
|
-
@Album.filter(:b_tracks=>@Track.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'B') AND (tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT tracks.id FROM tracks WHERE (x = 1))))))"
|
3998
|
-
end
|
3999
|
-
|
4000
|
-
it "should be able to filter on one_to_one association datasets with block" do
|
4001
|
-
@Album.filter(:b_album_info=>@AlbumInfo.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'B') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id IN (SELECT album_infos.id FROM album_infos WHERE (x = 1))))))"
|
4002
|
-
end
|
4003
|
-
|
4004
|
-
it "should be able to filter on many_to_many association datasets with block" do
|
4005
|
-
@Album.filter(:b_tags=>@Tag.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'B') AND (albums_tags.album_id IS NOT NULL) AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1))))))"
|
4006
|
-
end
|
4007
|
-
|
4008
|
-
it "should be able to filter on many_to_one association datasets with composite keys" do
|
4009
|
-
@Album.filter(:cartist=>@Artist.filter(:x=>1)).sql.must_equal '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))))'
|
4010
|
-
end
|
4011
|
-
|
4012
|
-
it "should be able to filter on one_to_many association datasets with composite keys" do
|
4013
|
-
@Album.filter(:ctracks=>@Track.filter(:x=>1)).sql.must_equal '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))))'
|
4014
|
-
end
|
4015
|
-
|
4016
|
-
it "should be able to filter on one_to_one association datasets with composite keys" do
|
4017
|
-
@Album.filter(:calbum_info=>@AlbumInfo.filter(:x=>1)).sql.must_equal '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))))'
|
4018
|
-
end
|
4019
|
-
|
4020
|
-
it "should be able to filter on many_to_many association datasets with composite keys" do
|
4021
|
-
@Album.filter(:ctags=>@Tag.filter(:x=>1)).sql.must_equal '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))))'
|
4022
|
-
end
|
4023
|
-
|
4024
|
-
it "should be able to filter on many_to_one association datasets with :conditions and composite keys" do
|
4025
|
-
@Album.filter(:a_cartist=>@Artist.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'A') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (x = 1))))))"
|
4026
|
-
end
|
4027
|
-
|
4028
|
-
it "should be able to filter on one_to_many association datasets with :conditions and composite keys" do
|
4029
|
-
@Album.filter(:a_ctracks=>@Track.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'A') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (SELECT tracks.id FROM tracks WHERE (x = 1))))))"
|
4030
|
-
end
|
4031
|
-
|
4032
|
-
it "should be able to filter on one_to_one association datasets with :conditions and composite keys" do
|
4033
|
-
@Album.filter(:a_calbum_info=>@AlbumInfo.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id IN (SELECT album_infos.id FROM album_infos WHERE (x = 1))))))"
|
4034
|
-
end
|
4035
|
-
|
4036
|
-
it "should be able to filter on many_to_many association datasets with :conditions and composite keys" do
|
4037
|
-
@Album.filter(:a_ctags=>@Tag.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'A') AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL) AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1))))))"
|
4038
|
-
end
|
4039
|
-
|
4040
|
-
it "should be able to filter on many_to_one association datasets with block and composite keys" do
|
4041
|
-
@Album.filter(:b_cartist=>@Artist.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'B') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (x = 1))))))"
|
4042
|
-
end
|
4043
|
-
|
4044
|
-
it "should be able to filter on one_to_many association datasets with block and composite keys" do
|
4045
|
-
@Album.filter(:b_ctracks=>@Track.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'B') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (SELECT tracks.id FROM tracks WHERE (x = 1))))))"
|
4046
|
-
end
|
4047
|
-
|
4048
|
-
it "should be able to filter on one_to_one association datasets with block and composite keys" do
|
4049
|
-
@Album.filter(:b_calbum_info=>@AlbumInfo.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'B') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id IN (SELECT album_infos.id FROM album_infos WHERE (x = 1))))))"
|
4050
|
-
end
|
4051
|
-
|
4052
|
-
it "should be able to filter on many_to_many association datasets with block and composite keys" do
|
4053
|
-
@Album.filter(:b_ctags=>@Tag.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'B') AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL) AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1))))))"
|
4054
|
-
end
|
4055
|
-
|
4056
|
-
it "should be able to exclude on many_to_one association datasets" do
|
4057
|
-
@Album.exclude(:artist=>@Artist.filter(:x=>1)).sql.must_equal '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))'
|
4058
|
-
end
|
4059
|
-
|
4060
|
-
it "should be able to exclude on one_to_many association datasets" do
|
4061
|
-
@Album.exclude(:tracks=>@Track.filter(:x=>1)).sql.must_equal '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))'
|
4062
|
-
end
|
4063
|
-
|
4064
|
-
it "should be able to exclude on one_to_one association datasets" do
|
4065
|
-
@Album.exclude(:album_info=>@AlbumInfo.filter(:x=>1)).sql.must_equal '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))'
|
4066
|
-
end
|
4067
|
-
|
4068
|
-
it "should be able to exclude on many_to_many association datasets" do
|
4069
|
-
@Album.exclude(:tags=>@Tag.filter(:x=>1)).sql.must_equal '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))'
|
4070
|
-
end
|
4071
|
-
|
4072
|
-
it "should be able to exclude on many_to_one association datasets with :conditions" do
|
4073
|
-
@Album.exclude(:a_artist=>@Artist.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE ((albums.artist_id NOT IN (SELECT artists.id FROM artists WHERE ((name = 'A') AND (artists.id IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (x = 1)))))) OR (albums.artist_id IS NULL))"
|
4074
|
-
end
|
4075
|
-
|
4076
|
-
it "should be able to exclude on one_to_many association datasets with :conditions" do
|
4077
|
-
@Album.exclude(:a_tracks=>@Track.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'A') AND (tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT tracks.id FROM tracks WHERE (x = 1)))))) OR (albums.id IS NULL))"
|
4078
|
-
end
|
4079
|
-
|
4080
|
-
it "should be able to exclude on one_to_one association datasets with :conditions" do
|
4081
|
-
@Album.exclude(:a_album_info=>@AlbumInfo.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id IN (SELECT album_infos.id FROM album_infos WHERE (x = 1)))))) OR (albums.id IS NULL))"
|
4082
|
-
end
|
4083
|
-
|
4084
|
-
it "should be able to exclude on many_to_many association datasets with :conditions" do
|
4085
|
-
@Album.exclude(:a_tags=>@Tag.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'A') AND (albums_tags.album_id IS NOT NULL) AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1)))))) OR (albums.id IS NULL))"
|
4086
|
-
end
|
4087
|
-
|
4088
|
-
it "should be able to exclude on many_to_one association datasets with block" do
|
4089
|
-
@Album.exclude(:b_artist=>@Artist.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE ((albums.artist_id NOT IN (SELECT artists.id FROM artists WHERE ((name = 'B') AND (artists.id IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (x = 1)))))) OR (albums.artist_id IS NULL))"
|
4090
|
-
end
|
4091
|
-
|
4092
|
-
it "should be able to exclude on one_to_many association datasets with block" do
|
4093
|
-
@Album.exclude(:b_tracks=>@Track.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'B') AND (tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT tracks.id FROM tracks WHERE (x = 1)))))) OR (albums.id IS NULL))"
|
4094
|
-
end
|
4095
|
-
|
4096
|
-
it "should be able to exclude on one_to_one association datasets with block" do
|
4097
|
-
@Album.exclude(:b_album_info=>@AlbumInfo.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'B') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id IN (SELECT album_infos.id FROM album_infos WHERE (x = 1)))))) OR (albums.id IS NULL))"
|
4098
|
-
end
|
4099
|
-
|
4100
|
-
it "should be able to exclude on many_to_many association datasets with block" do
|
4101
|
-
@Album.exclude(:b_tags=>@Tag.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'B') AND (albums_tags.album_id IS NOT NULL) AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1)))))) OR (albums.id IS NULL))"
|
4102
|
-
end
|
4103
|
-
|
4104
|
-
it "should be able to exclude on many_to_one association datasets with composite keys" do
|
4105
|
-
@Album.exclude(:cartist=>@Artist.filter(:x=>1)).sql.must_equal '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))'
|
4106
|
-
end
|
4107
|
-
|
4108
|
-
it "should be able to exclude on one_to_many association datasets with composite keys" do
|
4109
|
-
@Album.exclude(:ctracks=>@Track.filter(:x=>1)).sql.must_equal '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))'
|
4110
|
-
end
|
4111
|
-
|
4112
|
-
it "should be able to exclude on one_to_one association datasets with composite keys" do
|
4113
|
-
@Album.exclude(:calbum_info=>@AlbumInfo.filter(:x=>1)).sql.must_equal '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))'
|
4114
|
-
end
|
4115
|
-
|
4116
|
-
it "should be able to exclude on many_to_many association datasets with composite keys" do
|
4117
|
-
@Album.exclude(:ctags=>@Tag.filter(:x=>1)).sql.must_equal '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))'
|
4118
|
-
end
|
4119
|
-
|
4120
|
-
it "should be able to exclude on many_to_one association datasets with :conditions and composite keys" do
|
4121
|
-
@Album.exclude(:a_cartist=>@Artist.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'A') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (x = 1)))))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))"
|
4122
|
-
end
|
4123
|
-
|
4124
|
-
it "should be able to exclude on one_to_many association datasets with :conditions and composite keys" do
|
4125
|
-
@Album.exclude(:a_ctracks=>@Track.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'A') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (SELECT tracks.id FROM tracks WHERE (x = 1)))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
4126
|
-
end
|
4127
|
-
|
4128
|
-
it "should be able to exclude on one_to_one association datasets with :conditions and composite keys" do
|
4129
|
-
@Album.exclude(:a_calbum_info=>@AlbumInfo.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id IN (SELECT album_infos.id FROM album_infos WHERE (x = 1)))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
4130
|
-
end
|
4131
|
-
|
4132
|
-
it "should be able to exclude on many_to_many association datasets with :conditions and composite keys" do
|
4133
|
-
@Album.exclude(:a_ctags=>@Tag.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'A') AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL) AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1)))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
4134
|
-
end
|
4135
|
-
|
4136
|
-
it "should be able to exclude on many_to_one association datasets with block and composite keys" do
|
4137
|
-
@Album.exclude(:b_cartist=>@Artist.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'B') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (x = 1)))))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))"
|
4138
|
-
end
|
4139
|
-
|
4140
|
-
it "should be able to exclude on one_to_many association datasets with block and composite keys" do
|
4141
|
-
@Album.exclude(:b_ctracks=>@Track.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'B') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (SELECT tracks.id FROM tracks WHERE (x = 1)))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
4142
|
-
end
|
4143
|
-
|
4144
|
-
it "should be able to exclude on one_to_one association datasets with block and composite keys" do
|
4145
|
-
@Album.exclude(:b_calbum_info=>@AlbumInfo.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'B') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id IN (SELECT album_infos.id FROM album_infos WHERE (x = 1)))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
4146
|
-
end
|
4147
|
-
|
4148
|
-
it "should be able to exclude on many_to_many association datasets with block and composite keys" do
|
4149
|
-
@Album.exclude(:b_ctags=>@Tag.filter(:x=>1)).sql.must_equal "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'B') AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL) AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1)))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
|
4150
|
-
end
|
4151
|
-
|
4152
|
-
it "should do a regular IN query if the dataset for a different model is used" do
|
4153
|
-
@Album.filter(:artist=>@Album.select(:x)).sql.must_equal 'SELECT * FROM albums WHERE (artist IN (SELECT x FROM albums))'
|
4154
|
-
end
|
4155
|
-
|
4156
|
-
it "should do a regular IN query if a non-model dataset is used" do
|
4157
|
-
@Album.filter(:artist=>@Album.db.from(:albums).select(:x)).sql.must_equal 'SELECT * FROM albums WHERE (artist IN (SELECT x FROM albums))'
|
4158
|
-
end
|
4159
|
-
end
|
4160
|
-
|
4161
|
-
describe "Sequel::Model Associations with clashing column names" do
|
4162
|
-
before do
|
4163
|
-
@db = Sequel.mock(:fetch=>{:id=>1, :object_id=>2})
|
4164
|
-
@Foo = Class.new(Sequel::Model(@db[:foos]))
|
4165
|
-
@Bar = Class.new(Sequel::Model(@db[:bars]))
|
4166
|
-
@Foo.columns :id, :object_id
|
4167
|
-
@Bar.columns :id, :object_id
|
4168
|
-
@Foo.def_column_alias(:obj_id, :object_id)
|
4169
|
-
@Bar.def_column_alias(:obj_id, :object_id)
|
4170
|
-
@Foo.one_to_many :bars, :primary_key=>:obj_id, :primary_key_column=>:object_id, :key=>:object_id, :key_method=>:obj_id, :class=>@Bar
|
4171
|
-
@Foo.one_to_one :bar, :primary_key=>:obj_id, :primary_key_column=>:object_id, :key=>:object_id, :key_method=>:obj_id, :class=>@Bar
|
4172
|
-
@Bar.many_to_one :foo, :key=>:obj_id, :key_column=>:object_id, :primary_key=>:object_id, :primary_key_method=>:obj_id, :class=>@Foo
|
4173
|
-
@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, :class=>@Bar
|
4174
|
-
@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, :class=>@Foo
|
4175
|
-
@foo = @Foo.load(:id=>1, :object_id=>2)
|
4176
|
-
@bar = @Bar.load(:id=>1, :object_id=>2)
|
4177
|
-
@db.sqls
|
4178
|
-
end
|
4179
|
-
|
4180
|
-
it "should have working regular association methods" do
|
4181
|
-
@Bar.first.foo.must_equal @foo
|
4182
|
-
@db.sqls.must_equal ["SELECT * FROM bars LIMIT 1", "SELECT * FROM foos WHERE (foos.object_id = 2) LIMIT 1"]
|
4183
|
-
@Foo.first.bars.must_equal [@bar]
|
4184
|
-
@db.sqls.must_equal ["SELECT * FROM foos LIMIT 1", "SELECT * FROM bars WHERE (bars.object_id = 2)"]
|
4185
|
-
@Foo.first.bar.must_equal @bar
|
4186
|
-
@db.sqls.must_equal ["SELECT * FROM foos LIMIT 1", "SELECT * FROM bars WHERE (bars.object_id = 2) LIMIT 1"]
|
4187
|
-
@Foo.first.mtmbars.must_equal [@bar]
|
4188
|
-
@db.sqls.must_equal ["SELECT * FROM foos LIMIT 1", "SELECT bars.* FROM bars INNER JOIN bars_foos ON (bars_foos.object_id = bars.object_id) WHERE (bars_foos.foo_id = 2)"]
|
4189
|
-
@Bar.first.mtmfoos.must_equal [@foo]
|
4190
|
-
@db.sqls.must_equal ["SELECT * FROM bars LIMIT 1", "SELECT foos.* FROM foos INNER JOIN bars_foos ON (bars_foos.foo_id = foos.object_id) WHERE (bars_foos.object_id = 2)"]
|
4191
|
-
end
|
4192
|
-
|
4193
|
-
it "should have working eager loading methods" do
|
4194
|
-
@Bar.eager(:foo).all.map{|o| [o, o.foo]}.must_equal [[@bar, @foo]]
|
4195
|
-
@db.sqls.must_equal ["SELECT * FROM bars", "SELECT * FROM foos WHERE (foos.object_id IN (2))"]
|
4196
|
-
@Foo.eager(:bars).all.map{|o| [o, o.bars]}.must_equal [[@foo, [@bar]]]
|
4197
|
-
@db.sqls.must_equal ["SELECT * FROM foos", "SELECT * FROM bars WHERE (bars.object_id IN (2))"]
|
4198
|
-
@Foo.eager(:bar).all.map{|o| [o, o.bar]}.must_equal [[@foo, @bar]]
|
4199
|
-
@db.sqls.must_equal ["SELECT * FROM foos", "SELECT * FROM bars WHERE (bars.object_id IN (2))"]
|
4200
|
-
@db.fetch = [[{:id=>1, :object_id=>2}], [{:id=>1, :object_id=>2, :x_foreign_key_x=>2}]]
|
4201
|
-
@Foo.eager(:mtmbars).all.map{|o| [o, o.mtmbars]}.must_equal [[@foo, [@bar]]]
|
4202
|
-
@db.sqls.must_equal ["SELECT * FROM foos", "SELECT bars.*, bars_foos.foo_id AS x_foreign_key_x FROM bars INNER JOIN bars_foos ON (bars_foos.object_id = bars.object_id) WHERE (bars_foos.foo_id IN (2))"]
|
4203
|
-
@db.fetch = [[{:id=>1, :object_id=>2}], [{:id=>1, :object_id=>2, :x_foreign_key_x=>2}]]
|
4204
|
-
@Bar.eager(:mtmfoos).all.map{|o| [o, o.mtmfoos]}.must_equal [[@bar, [@foo]]]
|
4205
|
-
@db.sqls.must_equal ["SELECT * FROM bars", "SELECT foos.*, bars_foos.object_id AS x_foreign_key_x FROM foos INNER JOIN bars_foos ON (bars_foos.foo_id = foos.object_id) WHERE (bars_foos.object_id IN (2))"]
|
4206
|
-
end
|
4207
|
-
|
4208
|
-
it "should have working eager graphing methods" do
|
4209
|
-
@db.fetch = {:id=>1, :object_id=>2, :foo_id=>1, :foo_object_id=>2}
|
4210
|
-
@Bar.eager_graph(:foo).all.map{|o| [o, o.foo]}.must_equal [[@bar, @foo]]
|
4211
|
-
@db.sqls.must_equal ["SELECT bars.id, bars.object_id, foo.id AS foo_id, foo.object_id AS foo_object_id FROM bars LEFT OUTER JOIN foos AS foo ON (foo.object_id = bars.object_id)"]
|
4212
|
-
@db.fetch = {:id=>1, :object_id=>2, :bars_id=>1, :bars_object_id=>2}
|
4213
|
-
@Foo.eager_graph(:bars).all.map{|o| [o, o.bars]}.must_equal [[@foo, [@bar]]]
|
4214
|
-
@db.sqls.must_equal ["SELECT foos.id, foos.object_id, bars.id AS bars_id, bars.object_id AS bars_object_id FROM foos LEFT OUTER JOIN bars ON (bars.object_id = foos.object_id)"]
|
4215
|
-
@db.fetch = {:id=>1, :object_id=>2, :bar_id=>1, :bar_object_id=>2}
|
4216
|
-
@Foo.eager_graph(:bar).all.map{|o| [o, o.bar]}.must_equal [[@foo, @bar]]
|
4217
|
-
@db.sqls.must_equal ["SELECT foos.id, foos.object_id, bar.id AS bar_id, bar.object_id AS bar_object_id FROM foos LEFT OUTER JOIN bars AS bar ON (bar.object_id = foos.object_id)"]
|
4218
|
-
@db.fetch = {:id=>1, :object_id=>2, :mtmfoos_id=>1, :mtmfoos_object_id=>2}
|
4219
|
-
@Bar.eager_graph(:mtmfoos).all.map{|o| [o, o.mtmfoos]}.must_equal [[@bar, [@foo]]]
|
4220
|
-
@db.sqls.must_equal ["SELECT bars.id, bars.object_id, mtmfoos.id AS mtmfoos_id, mtmfoos.object_id AS mtmfoos_object_id FROM bars LEFT OUTER JOIN bars_foos ON (bars_foos.object_id = bars.object_id) LEFT OUTER JOIN foos AS mtmfoos ON (mtmfoos.object_id = bars_foos.foo_id)"]
|
4221
|
-
@db.fetch = {:id=>1, :object_id=>2, :mtmbars_id=>1, :mtmbars_object_id=>2}
|
4222
|
-
@Foo.eager_graph(:mtmbars).all.map{|o| [o, o.mtmbars]}.must_equal [[@foo, [@bar]]]
|
4223
|
-
@db.sqls.must_equal ["SELECT foos.id, foos.object_id, mtmbars.id AS mtmbars_id, mtmbars.object_id AS mtmbars_object_id FROM foos LEFT OUTER JOIN bars_foos ON (bars_foos.foo_id = foos.object_id) LEFT OUTER JOIN bars AS mtmbars ON (mtmbars.object_id = bars_foos.object_id)"]
|
4224
|
-
end
|
4225
|
-
|
4226
|
-
it "should have working filter by associations with model instances" do
|
4227
|
-
@Bar.first(:foo=>@foo).must_equal @bar
|
4228
|
-
@db.sqls.must_equal ["SELECT * FROM bars WHERE (bars.object_id = 2) LIMIT 1"]
|
4229
|
-
@Foo.first(:bars=>@bar).must_equal @foo
|
4230
|
-
@db.sqls.must_equal ["SELECT * FROM foos WHERE (foos.object_id = 2) LIMIT 1"]
|
4231
|
-
@Foo.first(:bar=>@bar).must_equal @foo
|
4232
|
-
@db.sqls.must_equal ["SELECT * FROM foos WHERE (foos.object_id = 2) LIMIT 1"]
|
4233
|
-
@Foo.first(:mtmbars=>@bar).must_equal @foo
|
4234
|
-
@db.sqls.must_equal ["SELECT * FROM foos WHERE (foos.object_id IN (SELECT bars_foos.foo_id FROM bars_foos WHERE ((bars_foos.object_id = 2) AND (bars_foos.foo_id IS NOT NULL)))) LIMIT 1"]
|
4235
|
-
@Bar.first(:mtmfoos=>@foo).must_equal @bar
|
4236
|
-
@db.sqls.must_equal ["SELECT * FROM bars WHERE (bars.object_id IN (SELECT bars_foos.object_id FROM bars_foos WHERE ((bars_foos.foo_id = 2) AND (bars_foos.object_id IS NOT NULL)))) LIMIT 1"]
|
4237
|
-
end
|
4238
|
-
|
4239
|
-
it "should have working filter by associations for associations with :conditions with model instances" do
|
4240
|
-
@Bar.many_to_one :foo, :clone=>:foo, :conditions=>{:name=>'A'}
|
4241
|
-
@Foo.one_to_many :bars, :clone=>:bars, :conditions=>{:name=>'A'}
|
4242
|
-
@Foo.one_to_one :bar, :clone=>:bars
|
4243
|
-
@Foo.many_to_many :mtmbars, :clone=>:mtmbars, :conditions=>{:name=>'A'}
|
4244
|
-
@Bar.many_to_many :mtmfoos, :clone=>:mtmfoos, :conditions=>{:name=>'A'}
|
4245
|
-
|
4246
|
-
@Bar.where(:foo=>@foo).sql.must_equal "SELECT * FROM bars WHERE (bars.object_id IN (SELECT foos.object_id FROM foos WHERE ((name = 'A') AND (foos.object_id IS NOT NULL) AND (foos.id = 1))))"
|
4247
|
-
@Foo.where(:bars=>@bar).sql.must_equal "SELECT * FROM foos WHERE (foos.object_id IN (SELECT bars.object_id FROM bars WHERE ((name = 'A') AND (bars.object_id IS NOT NULL) AND (bars.id = 1))))"
|
4248
|
-
@Foo.where(:bar=>@bar).sql.must_equal "SELECT * FROM foos WHERE (foos.object_id IN (SELECT bars.object_id FROM bars WHERE ((name = 'A') AND (bars.object_id IS NOT NULL) AND (bars.id = 1))))"
|
4249
|
-
@Foo.where(:mtmbars=>@bar).sql.must_equal "SELECT * FROM foos WHERE (foos.object_id IN (SELECT bars_foos.foo_id FROM bars INNER JOIN bars_foos ON (bars_foos.object_id = bars.object_id) WHERE ((name = 'A') AND (bars_foos.foo_id IS NOT NULL) AND (bars.id = 1))))"
|
4250
|
-
@Bar.where(:mtmfoos=>@foo).sql.must_equal "SELECT * FROM bars WHERE (bars.object_id IN (SELECT bars_foos.object_id FROM foos INNER JOIN bars_foos ON (bars_foos.foo_id = foos.object_id) WHERE ((name = 'A') AND (bars_foos.object_id IS NOT NULL) AND (foos.id = 1))))"
|
4251
|
-
end
|
4252
|
-
|
4253
|
-
it "should have working filter by associations for associations with block with model instances" do
|
4254
|
-
b = lambda{|ds| ds.where(:name=>'A')}
|
4255
|
-
@Bar.many_to_one :foo, :clone=>:foo, &b
|
4256
|
-
@Foo.one_to_many :bars, :clone=>:bars, &b
|
4257
|
-
@Foo.one_to_one :bar, :clone=>:bars
|
4258
|
-
@Foo.many_to_many :mtmbars, :clone=>:mtmbars, &b
|
4259
|
-
@Bar.many_to_many :mtmfoos, :clone=>:mtmfoos, &b
|
4260
|
-
|
4261
|
-
@Bar.where(:foo=>@foo).sql.must_equal "SELECT * FROM bars WHERE (bars.object_id IN (SELECT foos.object_id FROM foos WHERE ((name = 'A') AND (foos.object_id IS NOT NULL) AND (foos.id = 1))))"
|
4262
|
-
@Foo.where(:bars=>@bar).sql.must_equal "SELECT * FROM foos WHERE (foos.object_id IN (SELECT bars.object_id FROM bars WHERE ((name = 'A') AND (bars.object_id IS NOT NULL) AND (bars.id = 1))))"
|
4263
|
-
@Foo.where(:bar=>@bar).sql.must_equal "SELECT * FROM foos WHERE (foos.object_id IN (SELECT bars.object_id FROM bars WHERE ((name = 'A') AND (bars.object_id IS NOT NULL) AND (bars.id = 1))))"
|
4264
|
-
@Foo.where(:mtmbars=>@bar).sql.must_equal "SELECT * FROM foos WHERE (foos.object_id IN (SELECT bars_foos.foo_id FROM bars INNER JOIN bars_foos ON (bars_foos.object_id = bars.object_id) WHERE ((name = 'A') AND (bars_foos.foo_id IS NOT NULL) AND (bars.id = 1))))"
|
4265
|
-
@Bar.where(:mtmfoos=>@foo).sql.must_equal "SELECT * FROM bars WHERE (bars.object_id IN (SELECT bars_foos.object_id FROM foos INNER JOIN bars_foos ON (bars_foos.foo_id = foos.object_id) WHERE ((name = 'A') AND (bars_foos.object_id IS NOT NULL) AND (foos.id = 1))))"
|
4266
|
-
end
|
4267
|
-
|
4268
|
-
it "should have working modification methods" do
|
4269
|
-
b = @Bar.load(:id=>2, :object_id=>3)
|
4270
|
-
f = @Foo.load(:id=>2, :object_id=>3)
|
4271
|
-
@db.numrows = 1
|
4272
|
-
|
4273
|
-
@bar.foo = f
|
4274
|
-
@bar.obj_id.must_equal 3
|
4275
|
-
@foo.bar = @bar
|
4276
|
-
@bar.obj_id.must_equal 2
|
4277
|
-
|
4278
|
-
@foo.add_bar(b)
|
4279
|
-
@db.fetch = [[{:id=>1, :object_id=>2}, {:id=>2, :object_id=>2}], [{:id=>1, :object_id=>2}]]
|
4280
|
-
@foo.bars.must_equal [@bar, b]
|
4281
|
-
@foo.remove_bar(b)
|
4282
|
-
@foo.bars.must_equal [@bar]
|
4283
|
-
@foo.remove_all_bars
|
4284
|
-
@foo.bars.must_equal []
|
4285
|
-
|
4286
|
-
@db.fetch = [[{:id=>1, :object_id=>2}], [], [{:id=>2, :object_id=>2}]]
|
4287
|
-
@bar = @Bar.load(:id=>1, :object_id=>2)
|
4288
|
-
@foo.mtmbars.must_equal [@bar]
|
4289
|
-
@foo.remove_all_mtmbars
|
4290
|
-
@foo.mtmbars.must_equal []
|
4291
|
-
@foo.add_mtmbar(b)
|
4292
|
-
@foo.mtmbars.must_equal [b]
|
4293
|
-
@foo.remove_mtmbar(b)
|
4294
|
-
@foo.mtmbars.must_equal []
|
4295
|
-
|
4296
|
-
@db.fetch = [[{:id=>2, :object_id=>3}], [], [{:id=>2, :object_id=>3}]]
|
4297
|
-
@bar.add_mtmfoo(f)
|
4298
|
-
@bar.mtmfoos.must_equal [f]
|
4299
|
-
@bar.remove_all_mtmfoos
|
4300
|
-
@bar.mtmfoos.must_equal []
|
4301
|
-
@bar.add_mtmfoo(f)
|
4302
|
-
@bar.mtmfoos.must_equal [f]
|
4303
|
-
@bar.remove_mtmfoo(f)
|
4304
|
-
@bar.mtmfoos.must_equal []
|
4305
|
-
end
|
4306
|
-
end
|
4307
|
-
|
4308
|
-
describe "Sequel::Model Associations with non-column expression keys" do
|
4309
|
-
before do
|
4310
|
-
@db = Sequel.mock(:fetch=>{:id=>1, :object_ids=>[2]})
|
4311
|
-
@Foo = Class.new(Sequel::Model(@db[:foos]))
|
4312
|
-
@Bar = Class.new(Sequel::Model(@db[:bars]))
|
4313
|
-
@Foo.columns :id, :object_ids
|
4314
|
-
@Bar.columns :id, :object_ids
|
4315
|
-
m = Module.new{def obj_id; object_ids[0]; end}
|
4316
|
-
@Foo.include m
|
4317
|
-
@Bar.include m
|
4318
|
-
|
4319
|
-
@Foo.one_to_many :bars, :primary_key=>:obj_id, :primary_key_column=>Sequel.subscript(:object_ids, 0), :key=>Sequel.subscript(:object_ids, 0), :key_method=>:obj_id, :class=>@Bar
|
4320
|
-
@Foo.one_to_one :bar, :primary_key=>:obj_id, :primary_key_column=>Sequel.subscript(:object_ids, 0), :key=>Sequel.subscript(:object_ids, 0), :key_method=>:obj_id, :class=>@Bar
|
4321
|
-
@Bar.many_to_one :foo, :key=>:obj_id, :key_column=>Sequel.subscript(:object_ids, 0), :primary_key=>Sequel.subscript(:object_ids, 0), :primary_key_method=>:obj_id, :class=>@Foo
|
4322
|
-
@Foo.many_to_many :mtmbars, :join_table=>:bars_foos, :left_primary_key=>:obj_id, :left_primary_key_column=>Sequel.subscript(:object_ids, 0), :right_primary_key=>Sequel.subscript(:object_ids, 0), :right_primary_key_method=>:obj_id, :left_key=>Sequel.subscript(:foo_ids, 0), :right_key=>Sequel.subscript(:bar_ids, 0), :class=>@Bar
|
4323
|
-
@Bar.many_to_many :mtmfoos, :join_table=>:bars_foos, :left_primary_key=>:obj_id, :left_primary_key_column=>Sequel.subscript(:object_ids, 0), :right_primary_key=>Sequel.subscript(:object_ids, 0), :right_primary_key_method=>:obj_id, :left_key=>Sequel.subscript(:bar_ids, 0), :right_key=>Sequel.subscript(:foo_ids, 0), :class=>@Foo, :reciprocal=>nil
|
4324
|
-
@foo = @Foo.load(:id=>1, :object_ids=>[2])
|
4325
|
-
@bar = @Bar.load(:id=>1, :object_ids=>[2])
|
4326
|
-
@db.sqls
|
4327
|
-
end
|
4328
|
-
|
4329
|
-
it "should have working regular association methods" do
|
4330
|
-
@Bar.first.foo.must_equal @foo
|
4331
|
-
@db.sqls.must_equal ["SELECT * FROM bars LIMIT 1", "SELECT * FROM foos WHERE (foos.object_ids[0] = 2) LIMIT 1"]
|
4332
|
-
@Foo.first.bars.must_equal [@bar]
|
4333
|
-
@db.sqls.must_equal ["SELECT * FROM foos LIMIT 1", "SELECT * FROM bars WHERE (bars.object_ids[0] = 2)"]
|
4334
|
-
@Foo.first.bar.must_equal @bar
|
4335
|
-
@db.sqls.must_equal ["SELECT * FROM foos LIMIT 1", "SELECT * FROM bars WHERE (bars.object_ids[0] = 2) LIMIT 1"]
|
4336
|
-
@Foo.first.mtmbars.must_equal [@bar]
|
4337
|
-
@db.sqls.must_equal ["SELECT * FROM foos LIMIT 1", "SELECT bars.* FROM bars INNER JOIN bars_foos ON (bars_foos.bar_ids[0] = bars.object_ids[0]) WHERE (bars_foos.foo_ids[0] = 2)"]
|
4338
|
-
@Bar.first.mtmfoos.must_equal [@foo]
|
4339
|
-
@db.sqls.must_equal ["SELECT * FROM bars LIMIT 1", "SELECT foos.* FROM foos INNER JOIN bars_foos ON (bars_foos.foo_ids[0] = foos.object_ids[0]) WHERE (bars_foos.bar_ids[0] = 2)"]
|
4340
|
-
end
|
4341
|
-
|
4342
|
-
it "should have working eager loading methods" do
|
4343
|
-
@Bar.eager(:foo).all.map{|o| [o, o.foo]}.must_equal [[@bar, @foo]]
|
4344
|
-
@db.sqls.must_equal ["SELECT * FROM bars", "SELECT * FROM foos WHERE (foos.object_ids[0] IN (2))"]
|
4345
|
-
@Foo.eager(:bars).all.map{|o| [o, o.bars]}.must_equal [[@foo, [@bar]]]
|
4346
|
-
@db.sqls.must_equal ["SELECT * FROM foos", "SELECT * FROM bars WHERE (bars.object_ids[0] IN (2))"]
|
4347
|
-
@Foo.eager(:bar).all.map{|o| [o, o.bar]}.must_equal [[@foo, @bar]]
|
4348
|
-
@db.sqls.must_equal ["SELECT * FROM foos", "SELECT * FROM bars WHERE (bars.object_ids[0] IN (2))"]
|
4349
|
-
@db.fetch = [[{:id=>1, :object_ids=>[2]}], [{:id=>1, :object_ids=>[2], :x_foreign_key_x=>2}]]
|
4350
|
-
@Foo.eager(:mtmbars).all.map{|o| [o, o.mtmbars]}.must_equal [[@foo, [@bar]]]
|
4351
|
-
@db.sqls.must_equal ["SELECT * FROM foos", "SELECT bars.*, bars_foos.foo_ids[0] AS x_foreign_key_x FROM bars INNER JOIN bars_foos ON (bars_foos.bar_ids[0] = bars.object_ids[0]) WHERE (bars_foos.foo_ids[0] IN (2))"]
|
4352
|
-
@db.fetch = [[{:id=>1, :object_ids=>[2]}], [{:id=>1, :object_ids=>[2], :x_foreign_key_x=>2}]]
|
4353
|
-
@Bar.eager(:mtmfoos).all.map{|o| [o, o.mtmfoos]}.must_equal [[@bar, [@foo]]]
|
4354
|
-
@db.sqls.must_equal ["SELECT * FROM bars", "SELECT foos.*, bars_foos.bar_ids[0] AS x_foreign_key_x FROM foos INNER JOIN bars_foos ON (bars_foos.foo_ids[0] = foos.object_ids[0]) WHERE (bars_foos.bar_ids[0] IN (2))"]
|
4355
|
-
end
|
4356
|
-
|
4357
|
-
it "should have working eager graphing methods" do
|
4358
|
-
@db.fetch = {:id=>1, :object_ids=>[2], :foo_id=>1, :foo_object_ids=>[2]}
|
4359
|
-
@Bar.eager_graph(:foo).all.map{|o| [o, o.foo]}.must_equal [[@bar, @foo]]
|
4360
|
-
@db.sqls.must_equal ["SELECT bars.id, bars.object_ids, foo.id AS foo_id, foo.object_ids AS foo_object_ids FROM bars LEFT OUTER JOIN foos AS foo ON (foo.object_ids[0] = bars.object_ids[0])"]
|
4361
|
-
@db.fetch = {:id=>1, :object_ids=>[2], :bars_id=>1, :bars_object_ids=>[2]}
|
4362
|
-
@Foo.eager_graph(:bars).all.map{|o| [o, o.bars]}.must_equal [[@foo, [@bar]]]
|
4363
|
-
@db.sqls.must_equal ["SELECT foos.id, foos.object_ids, bars.id AS bars_id, bars.object_ids AS bars_object_ids FROM foos LEFT OUTER JOIN bars ON (bars.object_ids[0] = foos.object_ids[0])"]
|
4364
|
-
@db.fetch = {:id=>1, :object_ids=>[2], :bar_id=>1, :bar_object_ids=>[2]}
|
4365
|
-
@Foo.eager_graph(:bar).all.map{|o| [o, o.bar]}.must_equal [[@foo, @bar]]
|
4366
|
-
@db.sqls.must_equal ["SELECT foos.id, foos.object_ids, bar.id AS bar_id, bar.object_ids AS bar_object_ids FROM foos LEFT OUTER JOIN bars AS bar ON (bar.object_ids[0] = foos.object_ids[0])"]
|
4367
|
-
@db.fetch = {:id=>1, :object_ids=>[2], :mtmfoos_id=>1, :mtmfoos_object_ids=>[2]}
|
4368
|
-
@Bar.eager_graph(:mtmfoos).all.map{|o| [o, o.mtmfoos]}.must_equal [[@bar, [@foo]]]
|
4369
|
-
@db.sqls.must_equal ["SELECT bars.id, bars.object_ids, mtmfoos.id AS mtmfoos_id, mtmfoos.object_ids AS mtmfoos_object_ids FROM bars LEFT OUTER JOIN bars_foos ON (bars_foos.bar_ids[0] = bars.object_ids[0]) LEFT OUTER JOIN foos AS mtmfoos ON (mtmfoos.object_ids[0] = bars_foos.foo_ids[0])"]
|
4370
|
-
@db.fetch = {:id=>1, :object_ids=>[2], :mtmbars_id=>1, :mtmbars_object_ids=>[2]}
|
4371
|
-
@Foo.eager_graph(:mtmbars).all.map{|o| [o, o.mtmbars]}.must_equal [[@foo, [@bar]]]
|
4372
|
-
@db.sqls.must_equal ["SELECT foos.id, foos.object_ids, mtmbars.id AS mtmbars_id, mtmbars.object_ids AS mtmbars_object_ids FROM foos LEFT OUTER JOIN bars_foos ON (bars_foos.foo_ids[0] = foos.object_ids[0]) LEFT OUTER JOIN bars AS mtmbars ON (mtmbars.object_ids[0] = bars_foos.bar_ids[0])"]
|
4373
|
-
end
|
4374
|
-
|
4375
|
-
it "should have working filter by associations with model instances" do
|
4376
|
-
@Bar.first(:foo=>@foo).must_equal @bar
|
4377
|
-
@db.sqls.must_equal ["SELECT * FROM bars WHERE (bars.object_ids[0] = 2) LIMIT 1"]
|
4378
|
-
@Foo.first(:bars=>@bar).must_equal @foo
|
4379
|
-
@db.sqls.must_equal ["SELECT * FROM foos WHERE (foos.object_ids[0] = 2) LIMIT 1"]
|
4380
|
-
@Foo.first(:bar=>@bar).must_equal @foo
|
4381
|
-
@db.sqls.must_equal ["SELECT * FROM foos WHERE (foos.object_ids[0] = 2) LIMIT 1"]
|
4382
|
-
@Foo.first(:mtmbars=>@bar).must_equal @foo
|
4383
|
-
@db.sqls.must_equal ["SELECT * FROM foos WHERE (foos.object_ids[0] IN (SELECT bars_foos.foo_ids[0] FROM bars_foos WHERE ((bars_foos.bar_ids[0] = 2) AND (bars_foos.foo_ids[0] IS NOT NULL)))) LIMIT 1"]
|
4384
|
-
@Bar.first(:mtmfoos=>@foo).must_equal @bar
|
4385
|
-
@db.sqls.must_equal ["SELECT * FROM bars WHERE (bars.object_ids[0] IN (SELECT bars_foos.bar_ids[0] FROM bars_foos WHERE ((bars_foos.foo_ids[0] = 2) AND (bars_foos.bar_ids[0] IS NOT NULL)))) LIMIT 1"]
|
4386
|
-
end
|
4387
|
-
|
4388
|
-
it "should have working filter by associations for associations with :conditions with model instances" do
|
4389
|
-
@Bar.many_to_one :foo, :clone=>:foo, :conditions=>{:name=>'A'}
|
4390
|
-
@Foo.one_to_many :bars, :clone=>:bars, :conditions=>{:name=>'A'}
|
4391
|
-
@Foo.one_to_one :bar, :clone=>:bars
|
4392
|
-
@Foo.many_to_many :mtmbars, :clone=>:mtmbars, :conditions=>{:name=>'A'}
|
4393
|
-
@Bar.many_to_many :mtmfoos, :clone=>:mtmfoos, :conditions=>{:name=>'A'}
|
4394
|
-
|
4395
|
-
@Bar.where(:foo=>@foo).sql.must_equal "SELECT * FROM bars WHERE (bars.object_ids[0] IN (SELECT foos.object_ids[0] FROM foos WHERE ((name = 'A') AND (foos.object_ids[0] IS NOT NULL) AND (foos.id = 1))))"
|
4396
|
-
@Foo.where(:bars=>@bar).sql.must_equal "SELECT * FROM foos WHERE (foos.object_ids[0] IN (SELECT bars.object_ids[0] FROM bars WHERE ((name = 'A') AND (bars.object_ids[0] IS NOT NULL) AND (bars.id = 1))))"
|
4397
|
-
@Foo.where(:bar=>@bar).sql.must_equal "SELECT * FROM foos WHERE (foos.object_ids[0] IN (SELECT bars.object_ids[0] FROM bars WHERE ((name = 'A') AND (bars.object_ids[0] IS NOT NULL) AND (bars.id = 1))))"
|
4398
|
-
@Foo.where(:mtmbars=>@bar).sql.must_equal "SELECT * FROM foos WHERE (foos.object_ids[0] IN (SELECT bars_foos.foo_ids[0] FROM bars INNER JOIN bars_foos ON (bars_foos.bar_ids[0] = bars.object_ids[0]) WHERE ((name = 'A') AND (bars_foos.foo_ids[0] IS NOT NULL) AND (bars.id = 1))))"
|
4399
|
-
@Bar.where(:mtmfoos=>@foo).sql.must_equal "SELECT * FROM bars WHERE (bars.object_ids[0] IN (SELECT bars_foos.bar_ids[0] FROM foos INNER JOIN bars_foos ON (bars_foos.foo_ids[0] = foos.object_ids[0]) WHERE ((name = 'A') AND (bars_foos.bar_ids[0] IS NOT NULL) AND (foos.id = 1))))"
|
4400
|
-
end
|
4401
|
-
|
4402
|
-
it "should have working filter by associations for associations with block with model instances" do
|
4403
|
-
b = lambda{|ds| ds.where(:name=>'A')}
|
4404
|
-
@Bar.many_to_one :foo, :clone=>:foo, &b
|
4405
|
-
@Foo.one_to_many :bars, :clone=>:bars, &b
|
4406
|
-
@Foo.one_to_one :bar, :clone=>:bars
|
4407
|
-
@Foo.many_to_many :mtmbars, :clone=>:mtmbars, &b
|
4408
|
-
@Bar.many_to_many :mtmfoos, :clone=>:mtmfoos, &b
|
4409
|
-
|
4410
|
-
@Bar.where(:foo=>@foo).sql.must_equal "SELECT * FROM bars WHERE (bars.object_ids[0] IN (SELECT foos.object_ids[0] FROM foos WHERE ((name = 'A') AND (foos.object_ids[0] IS NOT NULL) AND (foos.id = 1))))"
|
4411
|
-
@Foo.where(:bars=>@bar).sql.must_equal "SELECT * FROM foos WHERE (foos.object_ids[0] IN (SELECT bars.object_ids[0] FROM bars WHERE ((name = 'A') AND (bars.object_ids[0] IS NOT NULL) AND (bars.id = 1))))"
|
4412
|
-
@Foo.where(:bar=>@bar).sql.must_equal "SELECT * FROM foos WHERE (foos.object_ids[0] IN (SELECT bars.object_ids[0] FROM bars WHERE ((name = 'A') AND (bars.object_ids[0] IS NOT NULL) AND (bars.id = 1))))"
|
4413
|
-
@Foo.where(:mtmbars=>@bar).sql.must_equal "SELECT * FROM foos WHERE (foos.object_ids[0] IN (SELECT bars_foos.foo_ids[0] FROM bars INNER JOIN bars_foos ON (bars_foos.bar_ids[0] = bars.object_ids[0]) WHERE ((name = 'A') AND (bars_foos.foo_ids[0] IS NOT NULL) AND (bars.id = 1))))"
|
4414
|
-
@Bar.where(:mtmfoos=>@foo).sql.must_equal "SELECT * FROM bars WHERE (bars.object_ids[0] IN (SELECT bars_foos.bar_ids[0] FROM foos INNER JOIN bars_foos ON (bars_foos.foo_ids[0] = foos.object_ids[0]) WHERE ((name = 'A') AND (bars_foos.bar_ids[0] IS NOT NULL) AND (foos.id = 1))))"
|
4415
|
-
end
|
4416
|
-
|
4417
|
-
it "should have working filter by associations with model datasets" do
|
4418
|
-
@Bar.first(:foo=>@Foo.where(:id=>@foo.id)).must_equal @bar
|
4419
|
-
@db.sqls.must_equal ["SELECT * FROM bars WHERE (bars.object_ids[0] IN (SELECT foos.object_ids[0] FROM foos WHERE ((id = 1) AND (foos.object_ids[0] IS NOT NULL)))) LIMIT 1"]
|
4420
|
-
@Foo.first(:bars=>@Bar.where(:id=>@bar.id)).must_equal @foo
|
4421
|
-
@db.sqls.must_equal ["SELECT * FROM foos WHERE (foos.object_ids[0] IN (SELECT bars.object_ids[0] FROM bars WHERE ((id = 1) AND (bars.object_ids[0] IS NOT NULL)))) LIMIT 1"]
|
4422
|
-
@Foo.first(:bar=>@Bar.where(:id=>@bar.id)).must_equal @foo
|
4423
|
-
@db.sqls.must_equal ["SELECT * FROM foos WHERE (foos.object_ids[0] IN (SELECT bars.object_ids[0] FROM bars WHERE ((id = 1) AND (bars.object_ids[0] IS NOT NULL)))) LIMIT 1"]
|
4424
|
-
@Foo.first(:mtmbars=>@Bar.where(:id=>@bar.id)).must_equal @foo
|
4425
|
-
@db.sqls.must_equal ["SELECT * FROM foos WHERE (foos.object_ids[0] IN (SELECT bars_foos.foo_ids[0] FROM bars_foos WHERE ((bars_foos.bar_ids[0] IN (SELECT bars.object_ids[0] FROM bars WHERE ((id = 1) AND (bars.object_ids[0] IS NOT NULL)))) AND (bars_foos.foo_ids[0] IS NOT NULL)))) LIMIT 1"]
|
4426
|
-
@Bar.first(:mtmfoos=>@Foo.where(:id=>@foo.id)).must_equal @bar
|
4427
|
-
@db.sqls.must_equal ["SELECT * FROM bars WHERE (bars.object_ids[0] IN (SELECT bars_foos.bar_ids[0] FROM bars_foos WHERE ((bars_foos.foo_ids[0] IN (SELECT foos.object_ids[0] FROM foos WHERE ((id = 1) AND (foos.object_ids[0] IS NOT NULL)))) AND (bars_foos.bar_ids[0] IS NOT NULL)))) LIMIT 1"]
|
4428
|
-
end
|
4429
|
-
end
|
4430
|
-
|
4431
|
-
describe Sequel::Model, "#refresh" do
|
4432
|
-
before do
|
4433
|
-
@c = Class.new(Sequel::Model(:items)) do
|
4434
|
-
unrestrict_primary_key
|
4435
|
-
columns :id, :x
|
4436
|
-
end
|
4437
|
-
DB.reset
|
4438
|
-
end
|
4439
|
-
|
4440
|
-
it "should remove cached associations" do
|
4441
|
-
@c.many_to_one :node, :class=>@c
|
4442
|
-
@m = @c.new(:id => 555)
|
4443
|
-
@m.associations[:node] = 15
|
4444
|
-
@m.reload
|
4445
|
-
@m.associations.must_equal({})
|
4446
|
-
end
|
4447
|
-
end
|
4448
|
-
|
4449
|
-
describe "Model#freeze" do
|
4450
|
-
before do
|
4451
|
-
class ::Album < Sequel::Model
|
4452
|
-
columns :id
|
4453
|
-
class B < Sequel::Model
|
4454
|
-
columns :id, :album_id
|
4455
|
-
many_to_one :album, :class=>Album
|
4456
|
-
end
|
4457
|
-
one_to_one :b, :key=>:album_id, :class=>B
|
4458
|
-
end
|
4459
|
-
@o = Album.load(:id=>1).freeze
|
4460
|
-
DB.sqls
|
4461
|
-
end
|
4462
|
-
after do
|
4463
|
-
Object.send(:remove_const, :Album)
|
4464
|
-
end
|
4465
|
-
|
4466
|
-
it "should freeze the object's associations" do
|
4467
|
-
@o.associations.frozen?.must_equal true
|
4468
|
-
end
|
4469
|
-
|
4470
|
-
it "should not break associations getters" do
|
4471
|
-
Album::B.dataset._fetch = {:album_id=>1, :id=>2}
|
4472
|
-
@o.b.must_equal Album::B.load(:id=>2, :album_id=>1)
|
4473
|
-
@o.associations[:b].must_equal nil
|
4474
|
-
|
4475
|
-
@o = @o.dup
|
4476
|
-
@o.b.must_equal Album::B.load(:id=>2, :album_id=>1)
|
4477
|
-
@o.associations[:b].must_equal Album::B.load(:id=>2, :album_id=>1)
|
4478
|
-
end
|
4479
|
-
|
4480
|
-
it "should not break reciprocal associations" do
|
4481
|
-
b = Album::B.load(:id=>2, :album_id=>nil)
|
4482
|
-
b.album = @o
|
4483
|
-
@o.associations[:b].must_equal nil
|
4484
|
-
|
4485
|
-
@o = @o.dup
|
4486
|
-
b = Album::B.load(:id=>2, :album_id=>nil)
|
4487
|
-
b.album = @o
|
4488
|
-
@o.associations[:b].must_equal Album::B.load(:id=>2, :album_id=>1)
|
4489
|
-
end
|
4490
|
-
end
|
4491
|
-
|
4492
|
-
describe "association autoreloading" do
|
4493
|
-
before do
|
4494
|
-
@c = Class.new(Sequel::Model)
|
4495
|
-
@Artist = Class.new(@c).set_dataset(:artists)
|
4496
|
-
@Artist.dataset._fetch = {:id=>2, :name=>'Ar'}
|
4497
|
-
@Album = Class.new(@c).set_dataset(:albums)
|
4498
|
-
@Artist.columns :id, :name
|
4499
|
-
@Album.columns :id, :name, :artist_id
|
4500
|
-
@Album.db_schema[:artist_id][:type] = :integer
|
4501
|
-
@Album.many_to_one :artist, :class=>@Artist
|
4502
|
-
DB.reset
|
4503
|
-
end
|
4504
|
-
|
4505
|
-
it "should reload many_to_one association when foreign key is modified" do
|
4506
|
-
album = @Album.load(:id => 1, :name=>'Al', :artist_id=>2)
|
4507
|
-
album.artist
|
4508
|
-
DB.sqls.must_equal ['SELECT * FROM artists WHERE id = 2']
|
4509
|
-
|
4510
|
-
album.artist_id = 1
|
4511
|
-
album.artist
|
4512
|
-
DB.sqls.must_equal ['SELECT * FROM artists WHERE id = 1']
|
4513
|
-
end
|
4514
|
-
|
4515
|
-
it "should handle multiple many_to_one association with the same foreign key" do
|
4516
|
-
@Album.many_to_one :artist2, :key=>:artist_id, :class=>@Artist
|
4517
|
-
album = @Album.load(:id => 1, :name=>'Al', :artist_id=>2)
|
4518
|
-
album.artist
|
4519
|
-
album.artist2
|
4520
|
-
DB.sqls.must_equal ['SELECT * FROM artists WHERE id = 2'] * 2
|
4521
|
-
|
4522
|
-
album.artist
|
4523
|
-
album.artist2
|
4524
|
-
DB.sqls.must_equal []
|
4525
|
-
|
4526
|
-
album.artist_id = 1
|
4527
|
-
album.artist
|
4528
|
-
album.artist2
|
4529
|
-
DB.sqls.must_equal ['SELECT * FROM artists WHERE id = 1'] * 2
|
4530
|
-
end
|
4531
|
-
|
4532
|
-
it "should not reload when value has not changed" do
|
4533
|
-
album = @Album.load(:id => 1, :name=>'Al', :artist_id=>2)
|
4534
|
-
album.artist
|
4535
|
-
DB.sqls.must_equal ['SELECT * FROM artists WHERE id = 2']
|
4536
|
-
|
4537
|
-
album.artist_id = 2
|
4538
|
-
album.artist
|
4539
|
-
DB.sqls.must_equal []
|
4540
|
-
|
4541
|
-
album.artist_id = "2"
|
4542
|
-
album.artist
|
4543
|
-
DB.sqls.must_equal []
|
4544
|
-
end
|
4545
|
-
|
4546
|
-
it "should reload all associations which use the foreign key" do
|
4547
|
-
@Album.many_to_one :other_artist, :key => :artist_id, :foreign_key => :id, :class => @Artist
|
4548
|
-
album = @Album.load(:id => 1, :name=>'Al', :artist_id=>2)
|
4549
|
-
album.artist
|
4550
|
-
album.other_artist
|
4551
|
-
DB.reset
|
4552
|
-
|
4553
|
-
album.artist_id = 1
|
4554
|
-
album.artist
|
4555
|
-
DB.sqls.must_equal ['SELECT * FROM artists WHERE id = 1']
|
4556
|
-
|
4557
|
-
album.other_artist
|
4558
|
-
DB.sqls.must_equal ['SELECT * FROM artists WHERE id = 1']
|
4559
|
-
end
|
4560
|
-
|
4561
|
-
it "should work with composite keys" do
|
4562
|
-
@Album.many_to_one :composite_artist, :key => [:artist_id, :name], :primary_key => [:id, :name], :class => @Artist
|
4563
|
-
album = @Album.load(:id => 1, :name=>'Al', :artist_id=>2)
|
4564
|
-
album.composite_artist
|
4565
|
-
DB.reset
|
4566
|
-
|
4567
|
-
album.artist_id = 1
|
4568
|
-
album.composite_artist
|
4569
|
-
DB.sqls.must_equal ["SELECT * FROM artists WHERE ((artists.id = 1) AND (artists.name = 'Al')) LIMIT 1"]
|
4570
|
-
|
4571
|
-
album.name = 'Al2'
|
4572
|
-
album.composite_artist
|
4573
|
-
DB.sqls.must_equal ["SELECT * FROM artists WHERE ((artists.id = 1) AND (artists.name = 'Al2')) LIMIT 1"]
|
4574
|
-
end
|
4575
|
-
|
4576
|
-
it "should work with subclasses" do
|
4577
|
-
salbum = Class.new(@Album)
|
4578
|
-
oartist = Class.new(@c).set_dataset(:oartist)
|
4579
|
-
oartist.columns :id, :name
|
4580
|
-
salbum.many_to_one :artist2, :class=>oartist, :key=>:artist_id
|
4581
|
-
album = salbum.load(:id => 1, :name=>'Al', :artist_id=>2)
|
4582
|
-
album.artist
|
4583
|
-
DB.sqls.must_equal ['SELECT * FROM artists WHERE id = 2']
|
4584
|
-
|
4585
|
-
album.artist_id = 1
|
4586
|
-
album.artist
|
4587
|
-
DB.sqls.must_equal ['SELECT * FROM artists WHERE id = 1']
|
4588
|
-
end
|
4589
|
-
end
|