sequel 5.29.0 → 5.30.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +8 -1922
- data/doc/release_notes/5.30.0.txt +20 -0
- data/lib/sequel/adapters/shared/sqlite.rb +7 -1
- data/lib/sequel/database/transactions.rb +5 -9
- data/lib/sequel/version.rb +1 -1
- metadata +4 -368
- data/Rakefile +0 -151
- 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.37.0.txt +0 -50
- data/doc/release_notes/4.38.0.txt +0 -67
- data/doc/release_notes/4.39.0.txt +0 -127
- data/doc/release_notes/4.4.0.txt +0 -92
- data/doc/release_notes/4.40.0.txt +0 -179
- data/doc/release_notes/4.41.0.txt +0 -77
- data/doc/release_notes/4.42.0.txt +0 -221
- data/doc/release_notes/4.43.0.txt +0 -87
- data/doc/release_notes/4.44.0.txt +0 -125
- data/doc/release_notes/4.45.0.txt +0 -370
- data/doc/release_notes/4.46.0.txt +0 -404
- data/doc/release_notes/4.47.0.txt +0 -56
- data/doc/release_notes/4.48.0.txt +0 -293
- data/doc/release_notes/4.49.0.txt +0 -222
- 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/spec/adapter_spec.rb +0 -4
- data/spec/adapters/db2_spec.rb +0 -170
- data/spec/adapters/mssql_spec.rb +0 -828
- data/spec/adapters/mysql_spec.rb +0 -1060
- data/spec/adapters/oracle_spec.rb +0 -371
- data/spec/adapters/postgres_spec.rb +0 -4476
- data/spec/adapters/spec_helper.rb +0 -44
- data/spec/adapters/sqlanywhere_spec.rb +0 -97
- data/spec/adapters/sqlite_spec.rb +0 -652
- data/spec/bin_spec.rb +0 -278
- data/spec/core/connection_pool_spec.rb +0 -1250
- data/spec/core/database_spec.rb +0 -2915
- data/spec/core/dataset_spec.rb +0 -5544
- data/spec/core/deprecated_spec.rb +0 -70
- data/spec/core/expression_filters_spec.rb +0 -1498
- data/spec/core/mock_adapter_spec.rb +0 -722
- data/spec/core/object_graph_spec.rb +0 -336
- data/spec/core/placeholder_literalizer_spec.rb +0 -166
- data/spec/core/schema_generator_spec.rb +0 -214
- data/spec/core/schema_spec.rb +0 -1844
- data/spec/core/spec_helper.rb +0 -24
- data/spec/core/version_spec.rb +0 -14
- data/spec/core_extensions_spec.rb +0 -763
- data/spec/core_model_spec.rb +0 -2
- data/spec/core_spec.rb +0 -1
- data/spec/deprecation_helper.rb +0 -30
- data/spec/extensions/accessed_columns_spec.rb +0 -51
- data/spec/extensions/active_model_spec.rb +0 -99
- data/spec/extensions/after_initialize_spec.rb +0 -28
- data/spec/extensions/any_not_empty_spec.rb +0 -23
- data/spec/extensions/arbitrary_servers_spec.rb +0 -109
- data/spec/extensions/association_dependencies_spec.rb +0 -125
- data/spec/extensions/association_multi_add_remove_spec.rb +0 -1041
- data/spec/extensions/association_pks_spec.rb +0 -423
- data/spec/extensions/association_proxies_spec.rb +0 -100
- data/spec/extensions/auto_literal_strings_spec.rb +0 -205
- data/spec/extensions/auto_validations_spec.rb +0 -229
- data/spec/extensions/blacklist_security_spec.rb +0 -95
- 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 -273
- data/spec/extensions/caller_logging_spec.rb +0 -52
- data/spec/extensions/class_table_inheritance_spec.rb +0 -750
- data/spec/extensions/column_conflicts_spec.rb +0 -75
- data/spec/extensions/column_select_spec.rb +0 -129
- data/spec/extensions/columns_introspection_spec.rb +0 -90
- data/spec/extensions/columns_updated_spec.rb +0 -35
- data/spec/extensions/composition_spec.rb +0 -248
- data/spec/extensions/connection_expiration_spec.rb +0 -151
- data/spec/extensions/connection_validator_spec.rb +0 -144
- data/spec/extensions/constant_sql_override_spec.rb +0 -24
- data/spec/extensions/constraint_validations_plugin_spec.rb +0 -300
- data/spec/extensions/constraint_validations_spec.rb +0 -439
- data/spec/extensions/core_refinements_spec.rb +0 -528
- data/spec/extensions/csv_serializer_spec.rb +0 -183
- data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
- data/spec/extensions/dataset_associations_spec.rb +0 -365
- data/spec/extensions/dataset_source_alias_spec.rb +0 -51
- data/spec/extensions/date_arithmetic_spec.rb +0 -181
- data/spec/extensions/datetime_parse_to_time_spec.rb +0 -169
- data/spec/extensions/def_dataset_method_spec.rb +0 -100
- data/spec/extensions/defaults_setter_spec.rb +0 -150
- data/spec/extensions/delay_add_association_spec.rb +0 -73
- data/spec/extensions/dirty_spec.rb +0 -222
- data/spec/extensions/duplicate_columns_handler_spec.rb +0 -104
- data/spec/extensions/eager_each_spec.rb +0 -62
- data/spec/extensions/eager_graph_eager_spec.rb +0 -100
- data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
- data/spec/extensions/empty_failure_backtraces_spec.rb +0 -60
- data/spec/extensions/error_splitter_spec.rb +0 -18
- data/spec/extensions/error_sql_spec.rb +0 -20
- data/spec/extensions/escaped_like_spec.rb +0 -40
- data/spec/extensions/eval_inspect_spec.rb +0 -81
- data/spec/extensions/exclude_or_null_spec.rb +0 -15
- data/spec/extensions/finder_spec.rb +0 -260
- data/spec/extensions/force_encoding_spec.rb +0 -126
- data/spec/extensions/freeze_datasets_spec.rb +0 -31
- data/spec/extensions/graph_each_spec.rb +0 -113
- data/spec/extensions/hook_class_methods_spec.rb +0 -402
- data/spec/extensions/identifier_mangling_spec.rb +0 -201
- data/spec/extensions/implicit_subquery_spec.rb +0 -58
- data/spec/extensions/index_caching_spec.rb +0 -66
- data/spec/extensions/inflector_spec.rb +0 -183
- data/spec/extensions/input_transformer_spec.rb +0 -69
- data/spec/extensions/insert_conflict_spec.rb +0 -103
- data/spec/extensions/insert_returning_select_spec.rb +0 -72
- data/spec/extensions/instance_filters_spec.rb +0 -79
- data/spec/extensions/instance_hooks_spec.rb +0 -246
- data/spec/extensions/integer64_spec.rb +0 -22
- data/spec/extensions/inverted_subsets_spec.rb +0 -33
- data/spec/extensions/json_serializer_spec.rb +0 -346
- data/spec/extensions/lazy_attributes_spec.rb +0 -183
- data/spec/extensions/list_spec.rb +0 -291
- data/spec/extensions/looser_typecasting_spec.rb +0 -43
- data/spec/extensions/many_through_many_spec.rb +0 -2177
- data/spec/extensions/migration_spec.rb +0 -864
- data/spec/extensions/modification_detection_spec.rb +0 -93
- data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -92
- data/spec/extensions/named_timezones_spec.rb +0 -218
- data/spec/extensions/nested_attributes_spec.rb +0 -815
- data/spec/extensions/null_dataset_spec.rb +0 -85
- data/spec/extensions/optimistic_locking_spec.rb +0 -127
- data/spec/extensions/pagination_spec.rb +0 -116
- data/spec/extensions/pg_array_associations_spec.rb +0 -802
- data/spec/extensions/pg_array_ops_spec.rb +0 -144
- data/spec/extensions/pg_array_spec.rb +0 -398
- data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -209
- data/spec/extensions/pg_enum_spec.rb +0 -118
- data/spec/extensions/pg_extended_date_support_spec.rb +0 -126
- data/spec/extensions/pg_hstore_ops_spec.rb +0 -238
- data/spec/extensions/pg_hstore_spec.rb +0 -219
- data/spec/extensions/pg_inet_ops_spec.rb +0 -102
- data/spec/extensions/pg_inet_spec.rb +0 -72
- data/spec/extensions/pg_interval_spec.rb +0 -103
- data/spec/extensions/pg_json_ops_spec.rb +0 -356
- data/spec/extensions/pg_json_spec.rb +0 -451
- data/spec/extensions/pg_loose_count_spec.rb +0 -23
- data/spec/extensions/pg_range_ops_spec.rb +0 -60
- data/spec/extensions/pg_range_spec.rb +0 -600
- data/spec/extensions/pg_row_ops_spec.rb +0 -61
- data/spec/extensions/pg_row_plugin_spec.rb +0 -60
- data/spec/extensions/pg_row_spec.rb +0 -363
- data/spec/extensions/pg_static_cache_updater_spec.rb +0 -93
- data/spec/extensions/pg_timestamptz_spec.rb +0 -17
- data/spec/extensions/prepared_statements_safe_spec.rb +0 -66
- data/spec/extensions/prepared_statements_spec.rb +0 -177
- data/spec/extensions/pretty_table_spec.rb +0 -123
- data/spec/extensions/query_spec.rb +0 -94
- data/spec/extensions/rcte_tree_spec.rb +0 -387
- data/spec/extensions/round_timestamps_spec.rb +0 -39
- data/spec/extensions/s_spec.rb +0 -60
- data/spec/extensions/schema_caching_spec.rb +0 -64
- data/spec/extensions/schema_dumper_spec.rb +0 -870
- data/spec/extensions/select_remove_spec.rb +0 -38
- data/spec/extensions/sequel_4_dataset_methods_spec.rb +0 -121
- data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
- data/spec/extensions/serialization_spec.rb +0 -365
- data/spec/extensions/server_block_spec.rb +0 -135
- data/spec/extensions/server_logging_spec.rb +0 -45
- data/spec/extensions/sharding_spec.rb +0 -197
- data/spec/extensions/shared_caching_spec.rb +0 -151
- data/spec/extensions/single_table_inheritance_spec.rb +0 -347
- data/spec/extensions/singular_table_names_spec.rb +0 -22
- data/spec/extensions/skip_create_refresh_spec.rb +0 -18
- data/spec/extensions/spec_helper.rb +0 -70
- data/spec/extensions/split_array_nil_spec.rb +0 -24
- data/spec/extensions/split_values_spec.rb +0 -57
- data/spec/extensions/sql_comments_spec.rb +0 -33
- data/spec/extensions/sql_expr_spec.rb +0 -59
- data/spec/extensions/static_cache_cache_spec.rb +0 -35
- data/spec/extensions/static_cache_spec.rb +0 -471
- data/spec/extensions/string_agg_spec.rb +0 -90
- 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 -79
- data/spec/extensions/subset_conditions_spec.rb +0 -38
- data/spec/extensions/symbol_aref_refinement_spec.rb +0 -28
- data/spec/extensions/symbol_as_refinement_spec.rb +0 -21
- data/spec/extensions/synchronize_sql_spec.rb +0 -124
- data/spec/extensions/table_select_spec.rb +0 -83
- data/spec/extensions/tactical_eager_loading_spec.rb +0 -402
- data/spec/extensions/thread_local_timezones_spec.rb +0 -67
- data/spec/extensions/throw_failures_spec.rb +0 -74
- data/spec/extensions/timestamps_spec.rb +0 -209
- data/spec/extensions/to_dot_spec.rb +0 -153
- data/spec/extensions/touch_spec.rb +0 -226
- data/spec/extensions/tree_spec.rb +0 -334
- data/spec/extensions/typecast_on_load_spec.rb +0 -86
- data/spec/extensions/unlimited_update_spec.rb +0 -21
- data/spec/extensions/update_or_create_spec.rb +0 -83
- data/spec/extensions/update_primary_key_spec.rb +0 -105
- data/spec/extensions/update_refresh_spec.rb +0 -59
- data/spec/extensions/uuid_spec.rb +0 -101
- data/spec/extensions/validate_associated_spec.rb +0 -52
- data/spec/extensions/validation_class_methods_spec.rb +0 -1040
- data/spec/extensions/validation_contexts_spec.rb +0 -31
- data/spec/extensions/validation_helpers_spec.rb +0 -525
- data/spec/extensions/whitelist_security_spec.rb +0 -157
- data/spec/extensions/xml_serializer_spec.rb +0 -213
- 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 -59
- data/spec/integration/associations_test.rb +0 -2597
- data/spec/integration/database_test.rb +0 -113
- data/spec/integration/dataset_test.rb +0 -2037
- data/spec/integration/eager_loader_test.rb +0 -687
- data/spec/integration/migrator_test.rb +0 -262
- data/spec/integration/model_test.rb +0 -203
- data/spec/integration/plugin_test.rb +0 -2423
- data/spec/integration/prepared_statement_test.rb +0 -405
- data/spec/integration/schema_test.rb +0 -903
- data/spec/integration/spec_helper.rb +0 -71
- data/spec/integration/timezone_test.rb +0 -86
- data/spec/integration/transaction_test.rb +0 -603
- data/spec/integration/type_test.rb +0 -127
- data/spec/model/association_reflection_spec.rb +0 -803
- data/spec/model/associations_spec.rb +0 -4738
- data/spec/model/base_spec.rb +0 -875
- data/spec/model/class_dataset_methods_spec.rb +0 -146
- data/spec/model/dataset_methods_spec.rb +0 -198
- data/spec/model/eager_loading_spec.rb +0 -2377
- data/spec/model/hooks_spec.rb +0 -370
- data/spec/model/inflector_spec.rb +0 -26
- data/spec/model/model_spec.rb +0 -956
- data/spec/model/plugins_spec.rb +0 -429
- data/spec/model/record_spec.rb +0 -2118
- data/spec/model/spec_helper.rb +0 -46
- data/spec/model/validations_spec.rb +0 -220
- 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/sequel_warning.rb +0 -5
- data/spec/spec_config.rb +0 -12
@@ -1,687 +0,0 @@
|
|
1
|
-
require_relative "spec_helper"
|
2
|
-
|
3
|
-
describe "Eagerly loading a tree structure" do
|
4
|
-
before(:all) do
|
5
|
-
DB.instance_variable_get(:@schemas).clear
|
6
|
-
DB.create_table!(:nodes) do
|
7
|
-
primary_key :id
|
8
|
-
foreign_key :parent_id, :nodes
|
9
|
-
end
|
10
|
-
class ::Node < Sequel::Model
|
11
|
-
many_to_one :parent
|
12
|
-
one_to_many :children, :key=>:parent_id
|
13
|
-
|
14
|
-
# Only useful when eager loading
|
15
|
-
many_to_one :ancestors, :eager_loader_key=>nil, :eager_loader=>(proc do |eo|
|
16
|
-
# Handle cases where the root node has the same parent_id as primary_key
|
17
|
-
# and also when it is NULL
|
18
|
-
non_root_nodes = eo[:rows].reject do |n|
|
19
|
-
if [nil, n.pk].include?(n.parent_id)
|
20
|
-
# Make sure root nodes have their parent association set to nil
|
21
|
-
n.associations[:parent] = nil
|
22
|
-
true
|
23
|
-
else
|
24
|
-
false
|
25
|
-
end
|
26
|
-
end
|
27
|
-
unless non_root_nodes.empty?
|
28
|
-
id_map = {}
|
29
|
-
# Create an map of parent_ids to nodes that have that parent id
|
30
|
-
non_root_nodes.each{|n| (id_map[n.parent_id] ||= []) << n}
|
31
|
-
# Doesn't cause an infinte loop, because when only the root node
|
32
|
-
# is left, this is not called.
|
33
|
-
Node.filter(Node.primary_key=>id_map.keys.sort).eager(:ancestors).all do |node|
|
34
|
-
# Populate the parent association for each node
|
35
|
-
id_map[node.pk].each{|n| n.associations[:parent] = node}
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end)
|
39
|
-
many_to_one :descendants, :eager_loader_key=>nil, :eager_loader=>(proc do |eo|
|
40
|
-
id_map = {}
|
41
|
-
eo[:rows].each do |n|
|
42
|
-
# Initialize an empty array of child associations for each parent node
|
43
|
-
n.associations[:children] = []
|
44
|
-
# Populate identity map of nodes
|
45
|
-
id_map[n.pk] = n
|
46
|
-
end
|
47
|
-
# Doesn't cause an infinite loop, because the :eager_loader is not called
|
48
|
-
# if no records are returned. Exclude id = parent_id to avoid infinite loop
|
49
|
-
# if the root note is one of the returned records and it has parent_id = id
|
50
|
-
# instead of parent_id = NULL.
|
51
|
-
Node.filter(:parent_id=>id_map.keys.sort).exclude(:id=>:parent_id).eager(:descendants).all do |node|
|
52
|
-
# Get the parent from the identity map
|
53
|
-
parent = id_map[node.parent_id]
|
54
|
-
# Set the child's parent association to the parent
|
55
|
-
node.associations[:parent] = parent
|
56
|
-
# Add the child association to the array of children in the parent
|
57
|
-
parent.associations[:children] << node
|
58
|
-
end
|
59
|
-
end)
|
60
|
-
end
|
61
|
-
|
62
|
-
Node.insert(:parent_id=>1)
|
63
|
-
Node.insert(:parent_id=>1)
|
64
|
-
Node.insert(:parent_id=>1)
|
65
|
-
Node.insert(:parent_id=>2)
|
66
|
-
Node.insert(:parent_id=>4)
|
67
|
-
Node.insert(:parent_id=>5)
|
68
|
-
Node.insert(:parent_id=>6)
|
69
|
-
end
|
70
|
-
after(:all) do
|
71
|
-
DB.drop_table :nodes
|
72
|
-
Object.send(:remove_const, :Node)
|
73
|
-
end
|
74
|
-
|
75
|
-
it "#descendants should get all descendants in one call" do
|
76
|
-
nodes = Node.filter(:id=>1).eager(:descendants).all
|
77
|
-
nodes.length.must_equal 1
|
78
|
-
node = nodes.first
|
79
|
-
node.pk.must_equal 1
|
80
|
-
node.children.length.must_equal 2
|
81
|
-
node.children.collect{|x| x.pk}.sort.must_equal [2, 3]
|
82
|
-
node.children.collect{|x| x.parent}.must_equal [node, node]
|
83
|
-
node = nodes.first.children.find{|x| x.pk == 2}
|
84
|
-
node.children.length.must_equal 1
|
85
|
-
node.children.first.pk.must_equal 4
|
86
|
-
node.children.first.parent.must_equal node
|
87
|
-
node = node.children.first
|
88
|
-
node.children.length.must_equal 1
|
89
|
-
node.children.first.pk.must_equal 5
|
90
|
-
node.children.first.parent.must_equal node
|
91
|
-
node = node.children.first
|
92
|
-
node.children.length.must_equal 1
|
93
|
-
node.children.first.pk.must_equal 6
|
94
|
-
node.children.first.parent.must_equal node
|
95
|
-
node = node.children.first
|
96
|
-
node.children.length.must_equal 1
|
97
|
-
node.children.first.pk.must_equal 7
|
98
|
-
node.children.first.parent.must_equal node
|
99
|
-
end
|
100
|
-
|
101
|
-
it "#ancestors should get all ancestors in one call" do
|
102
|
-
nodes = Node.filter(:id=>[7,3]).order(:id).eager(:ancestors).all
|
103
|
-
nodes.length.must_equal 2
|
104
|
-
nodes.collect{|x| x.pk}.must_equal [3, 7]
|
105
|
-
nodes.first.parent.pk.must_equal 1
|
106
|
-
nodes.first.parent.parent.must_be_nil
|
107
|
-
node = nodes.last
|
108
|
-
node.parent.pk.must_equal 6
|
109
|
-
node = node.parent
|
110
|
-
node.parent.pk.must_equal 5
|
111
|
-
node = node.parent
|
112
|
-
node.parent.pk.must_equal 4
|
113
|
-
node = node.parent
|
114
|
-
node.parent.pk.must_equal 2
|
115
|
-
node = node.parent
|
116
|
-
node.parent.pk.must_equal 1
|
117
|
-
node.parent.parent.must_be_nil
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
describe "Association Extensions" do
|
122
|
-
before do
|
123
|
-
module ::FindOrCreate
|
124
|
-
def find_or_create(vals)
|
125
|
-
first(vals) || model.create(vals.merge(:author_id=>model_object.pk))
|
126
|
-
end
|
127
|
-
def find_or_create_by_name(name)
|
128
|
-
first(:name=>name) || model.create(:name=>name, :author_id=>model_object.pk)
|
129
|
-
end
|
130
|
-
end
|
131
|
-
DB.instance_variable_get(:@schemas).clear
|
132
|
-
DB.create_table!(:authors) do
|
133
|
-
primary_key :id
|
134
|
-
end
|
135
|
-
class ::Author < Sequel::Model
|
136
|
-
one_to_many :authorships, :extend=>FindOrCreate
|
137
|
-
end
|
138
|
-
DB.create_table!(:authorships) do
|
139
|
-
primary_key :id
|
140
|
-
foreign_key :author_id, :authors
|
141
|
-
String :name
|
142
|
-
end
|
143
|
-
class ::Authorship < Sequel::Model
|
144
|
-
many_to_one :author
|
145
|
-
end
|
146
|
-
@author = Author.create
|
147
|
-
end
|
148
|
-
after do
|
149
|
-
DB.drop_table :authorships, :authors
|
150
|
-
Object.send(:remove_const, :Author)
|
151
|
-
Object.send(:remove_const, :Authorship)
|
152
|
-
end
|
153
|
-
|
154
|
-
it "should allow methods to be called on the dataset method" do
|
155
|
-
Authorship.count.must_equal 0
|
156
|
-
authorship = @author.authorships_dataset.find_or_create_by_name('Bob')
|
157
|
-
Authorship.count.must_equal 1
|
158
|
-
Authorship.first.must_equal authorship
|
159
|
-
authorship.name.must_equal 'Bob'
|
160
|
-
authorship.author_id.must_equal @author.id
|
161
|
-
@author.authorships_dataset.find_or_create_by_name('Bob').must_equal authorship
|
162
|
-
Authorship.count.must_equal 1
|
163
|
-
authorship2 = @author.authorships_dataset.find_or_create(:name=>'Jim')
|
164
|
-
Authorship.count.must_equal 2
|
165
|
-
Authorship.order(:name).map(:name).must_equal ['Bob', 'Jim']
|
166
|
-
authorship2.name.must_equal 'Jim'
|
167
|
-
authorship2.author_id.must_equal @author.id
|
168
|
-
@author.authorships_dataset.find_or_create(:name=>'Jim').must_equal authorship2
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
describe "has_many :through has_many and has_one :through belongs_to" do
|
173
|
-
before(:all) do
|
174
|
-
DB.instance_variable_get(:@schemas).clear
|
175
|
-
DB.create_table!(:firms) do
|
176
|
-
primary_key :id
|
177
|
-
end
|
178
|
-
class ::Firm < Sequel::Model
|
179
|
-
one_to_many :clients
|
180
|
-
one_to_many :invoices, :read_only=>true, \
|
181
|
-
:dataset=>proc{Invoice.eager_graph(:client).filter(Sequel[:client][:firm_id]=>pk)}, \
|
182
|
-
:after_load=>(proc do |firm, invs|
|
183
|
-
invs.each do |inv|
|
184
|
-
inv.client.associations[:firm] = inv.associations[:firm] = firm
|
185
|
-
end
|
186
|
-
end), \
|
187
|
-
:eager_loader=>(proc do |eo|
|
188
|
-
id_map = eo[:id_map]
|
189
|
-
eo[:rows].each{|firm| firm.associations[:invoices] = []}
|
190
|
-
Invoice.eager_graph(:client).filter(Sequel[:client][:firm_id]=>id_map.keys).all do |inv|
|
191
|
-
id_map[inv.client.firm_id].each do |firm|
|
192
|
-
firm.associations[:invoices] << inv
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end)
|
196
|
-
end
|
197
|
-
|
198
|
-
DB.create_table!(:clients) do
|
199
|
-
primary_key :id
|
200
|
-
foreign_key :firm_id, :firms
|
201
|
-
end
|
202
|
-
class ::Client < Sequel::Model
|
203
|
-
many_to_one :firm
|
204
|
-
one_to_many :invoices
|
205
|
-
end
|
206
|
-
|
207
|
-
DB.create_table!(:invoices) do
|
208
|
-
primary_key :id
|
209
|
-
foreign_key :client_id, :clients
|
210
|
-
end
|
211
|
-
class ::Invoice < Sequel::Model
|
212
|
-
many_to_one :client
|
213
|
-
many_to_one :firm, :key=>nil, :read_only=>true, \
|
214
|
-
:dataset=>proc{Firm.eager_graph(:clients).filter(Sequel[:clients][:id]=>client_id)}, \
|
215
|
-
:after_load=>(proc do |inv, firm|
|
216
|
-
# Delete the cached associations from firm, because it only has the
|
217
|
-
# client with this invoice, instead of all clients of the firm
|
218
|
-
if c = firm.associations.delete(:clients)
|
219
|
-
firm.associations[:invoice_client] = c.first
|
220
|
-
end
|
221
|
-
inv.associations[:client] ||= firm.associations[:invoice_client]
|
222
|
-
end), \
|
223
|
-
:eager_loader=>(proc do |eo|
|
224
|
-
id_map = {}
|
225
|
-
eo[:rows].each do |inv|
|
226
|
-
inv.associations[:firm] = nil
|
227
|
-
(id_map[inv.client_id] ||= []) << inv
|
228
|
-
end
|
229
|
-
Firm.eager_graph(:clients).filter(Sequel[:clients][:id]=>id_map.keys).all do |firm|
|
230
|
-
# Delete the cached associations from firm, because it only has the
|
231
|
-
# clients related the invoices being eagerly loaded, instead of all
|
232
|
-
# clients of the firm.
|
233
|
-
firm.associations[:clients].each do |client|
|
234
|
-
id_map[client.pk].each do |inv|
|
235
|
-
inv.associations[:firm] = firm
|
236
|
-
inv.associations[:client] = client
|
237
|
-
end
|
238
|
-
end
|
239
|
-
end
|
240
|
-
end)
|
241
|
-
end
|
242
|
-
@firm1 = Firm.create
|
243
|
-
@firm2 = Firm.create
|
244
|
-
@client1 = Client.create(:firm => @firm1)
|
245
|
-
@client2 = Client.create(:firm => @firm1)
|
246
|
-
@client3 = Client.create(:firm => @firm2)
|
247
|
-
@invoice1 = Invoice.create(:client => @client1)
|
248
|
-
@invoice2 = Invoice.create(:client => @client1)
|
249
|
-
@invoice3 = Invoice.create(:client => @client2)
|
250
|
-
@invoice4 = Invoice.create(:client => @client3)
|
251
|
-
@invoice5 = Invoice.create(:client => @client3)
|
252
|
-
end
|
253
|
-
after(:all) do
|
254
|
-
DB.drop_table :invoices, :clients, :firms
|
255
|
-
Object.send(:remove_const, :Firm)
|
256
|
-
Object.send(:remove_const, :Client)
|
257
|
-
Object.send(:remove_const, :Invoice)
|
258
|
-
end
|
259
|
-
|
260
|
-
it "should return has_many :through has_many records for a single object" do
|
261
|
-
invs = @firm1.invoices.sort_by{|x| x.pk}
|
262
|
-
invs.must_equal [@invoice1, @invoice2, @invoice3]
|
263
|
-
invs[0].client.must_equal @client1
|
264
|
-
invs[1].client.must_equal @client1
|
265
|
-
invs[2].client.must_equal @client2
|
266
|
-
invs.collect{|i| i.firm}.must_equal [@firm1, @firm1, @firm1]
|
267
|
-
invs.collect{|i| i.client.firm}.must_equal [@firm1, @firm1, @firm1]
|
268
|
-
end
|
269
|
-
|
270
|
-
it "should eagerly load has_many :through has_many records for multiple objects" do
|
271
|
-
firms = Firm.order(:id).eager(:invoices).all
|
272
|
-
firms.must_equal [@firm1, @firm2]
|
273
|
-
firm1, firm2 = firms
|
274
|
-
invs1 = firm1.invoices.sort_by{|x| x.pk}
|
275
|
-
invs2 = firm2.invoices.sort_by{|x| x.pk}
|
276
|
-
invs1.must_equal [@invoice1, @invoice2, @invoice3]
|
277
|
-
invs2.must_equal [@invoice4, @invoice5]
|
278
|
-
invs1[0].client.must_equal @client1
|
279
|
-
invs1[1].client.must_equal @client1
|
280
|
-
invs1[2].client.must_equal @client2
|
281
|
-
invs2[0].client.must_equal @client3
|
282
|
-
invs2[1].client.must_equal @client3
|
283
|
-
invs1.collect{|i| i.firm}.must_equal [@firm1, @firm1, @firm1]
|
284
|
-
invs2.collect{|i| i.firm}.must_equal [@firm2, @firm2]
|
285
|
-
invs1.collect{|i| i.client.firm}.must_equal [@firm1, @firm1, @firm1]
|
286
|
-
invs2.collect{|i| i.client.firm}.must_equal [@firm2, @firm2]
|
287
|
-
end
|
288
|
-
|
289
|
-
it "should return has_one :through belongs_to records for a single object" do
|
290
|
-
firm = @invoice1.firm
|
291
|
-
firm.must_equal @firm1
|
292
|
-
@invoice1.client.must_equal @client1
|
293
|
-
@invoice1.client.firm.must_equal @firm1
|
294
|
-
firm.associations[:clients].must_be_nil
|
295
|
-
end
|
296
|
-
|
297
|
-
it "should eagerly load has_one :through belongs_to records for multiple objects" do
|
298
|
-
invs = Invoice.order(:id).eager(:firm).all
|
299
|
-
invs.must_equal [@invoice1, @invoice2, @invoice3, @invoice4, @invoice5]
|
300
|
-
invs[0].firm.must_equal @firm1
|
301
|
-
invs[0].client.must_equal @client1
|
302
|
-
invs[0].client.firm.must_equal @firm1
|
303
|
-
invs[0].firm.associations[:clients].must_be_nil
|
304
|
-
invs[1].firm.must_equal @firm1
|
305
|
-
invs[1].client.must_equal @client1
|
306
|
-
invs[1].client.firm.must_equal @firm1
|
307
|
-
invs[1].firm.associations[:clients].must_be_nil
|
308
|
-
invs[2].firm.must_equal @firm1
|
309
|
-
invs[2].client.must_equal @client2
|
310
|
-
invs[2].client.firm.must_equal @firm1
|
311
|
-
invs[2].firm.associations[:clients].must_be_nil
|
312
|
-
invs[3].firm.must_equal @firm2
|
313
|
-
invs[3].client.must_equal @client3
|
314
|
-
invs[3].client.firm.must_equal @firm2
|
315
|
-
invs[3].firm.associations[:clients].must_be_nil
|
316
|
-
invs[4].firm.must_equal @firm2
|
317
|
-
invs[4].client.must_equal @client3
|
318
|
-
invs[4].client.firm.must_equal @firm2
|
319
|
-
invs[4].firm.associations[:clients].must_be_nil
|
320
|
-
end
|
321
|
-
end
|
322
|
-
|
323
|
-
describe "Polymorphic Associations" do
|
324
|
-
before(:all) do
|
325
|
-
DB.instance_variable_get(:@schemas).clear
|
326
|
-
DB.create_table!(:assets) do
|
327
|
-
primary_key :id
|
328
|
-
Integer :attachable_id
|
329
|
-
String :attachable_type
|
330
|
-
end
|
331
|
-
class ::Asset < Sequel::Model
|
332
|
-
m = method(:constantize)
|
333
|
-
many_to_one :attachable, :reciprocal=>:assets, :reciprocal_type=>:one_to_many,
|
334
|
-
:setter=>(proc do |attachable|
|
335
|
-
self[:attachable_id] = (attachable.pk if attachable)
|
336
|
-
self[:attachable_type] = (attachable.class.name if attachable)
|
337
|
-
end),
|
338
|
-
:dataset=>(proc do
|
339
|
-
klass = m.call(attachable_type)
|
340
|
-
klass.where(klass.primary_key=>attachable_id)
|
341
|
-
end),
|
342
|
-
:eager_loader=>(proc do |eo|
|
343
|
-
id_map = {}
|
344
|
-
eo[:rows].each do |asset|
|
345
|
-
asset.associations[:attachable] = nil
|
346
|
-
((id_map[asset.attachable_type] ||= {})[asset.attachable_id] ||= []) << asset
|
347
|
-
end
|
348
|
-
id_map.each do |klass_name, idmap|
|
349
|
-
klass = m.call(klass_name)
|
350
|
-
klass.where(klass.primary_key=>idmap.keys).all do |attach|
|
351
|
-
idmap[attach.pk].each do |asset|
|
352
|
-
asset.associations[:attachable] = attach
|
353
|
-
end
|
354
|
-
end
|
355
|
-
end
|
356
|
-
end)
|
357
|
-
end
|
358
|
-
|
359
|
-
DB.create_table!(:posts) do
|
360
|
-
primary_key :id
|
361
|
-
end
|
362
|
-
class ::Post < Sequel::Model
|
363
|
-
one_to_many :assets, :key=>:attachable_id, :reciprocal=>:attachable, :conditions=>{:attachable_type=>'Post'},
|
364
|
-
:adder=>proc{|asset| asset.update(:attachable_id=>pk, :attachable_type=>'Post')},
|
365
|
-
:remover=>proc{|asset| asset.update(:attachable_id=>nil, :attachable_type=>nil)},
|
366
|
-
:clearer=>proc{assets_dataset.update(:attachable_id=>nil, :attachable_type=>nil)}
|
367
|
-
end
|
368
|
-
|
369
|
-
DB.create_table!(:notes) do
|
370
|
-
primary_key :id
|
371
|
-
end
|
372
|
-
class ::Note < Sequel::Model
|
373
|
-
one_to_many :assets, :key=>:attachable_id, :reciprocal=>:attachable, :conditions=>{:attachable_type=>'Note'},
|
374
|
-
:adder=>proc{|asset| asset.update(:attachable_id=>pk, :attachable_type=>'Note')},
|
375
|
-
:remover=>proc{|asset| asset.update(:attachable_id=>nil, :attachable_type=>nil)},
|
376
|
-
:clearer=>proc{assets_dataset.update(:attachable_id=>nil, :attachable_type=>nil)}
|
377
|
-
end
|
378
|
-
end
|
379
|
-
before do
|
380
|
-
[:assets, :posts, :notes].each{|t| DB[t].delete}
|
381
|
-
@post = Post.create
|
382
|
-
Note.create
|
383
|
-
@note = Note.create
|
384
|
-
@asset1 = Asset.create(:attachable=>@post)
|
385
|
-
@asset2 = Asset.create(:attachable=>@note)
|
386
|
-
@asset1.associations.clear
|
387
|
-
@asset2.associations.clear
|
388
|
-
end
|
389
|
-
after(:all) do
|
390
|
-
DB.drop_table :assets, :posts, :notes
|
391
|
-
Object.send(:remove_const, :Asset)
|
392
|
-
Object.send(:remove_const, :Post)
|
393
|
-
Object.send(:remove_const, :Note)
|
394
|
-
end
|
395
|
-
|
396
|
-
it "should load the correct associated object for a single object" do
|
397
|
-
@asset1.attachable.must_equal @post
|
398
|
-
@asset2.attachable.must_equal @note
|
399
|
-
end
|
400
|
-
|
401
|
-
it "should eagerly load the correct associated object for a group of objects" do
|
402
|
-
assets = Asset.order(:id).eager(:attachable).all
|
403
|
-
assets.must_equal [@asset1, @asset2]
|
404
|
-
assets[0].attachable.must_equal @post
|
405
|
-
assets[1].attachable.must_equal @note
|
406
|
-
end
|
407
|
-
|
408
|
-
it "should set items correctly" do
|
409
|
-
@asset1.attachable = @note
|
410
|
-
@asset2.attachable = @post
|
411
|
-
@asset1.attachable.must_equal @note
|
412
|
-
@asset1.attachable_id.must_equal @note.pk
|
413
|
-
@asset1.attachable_type.must_equal 'Note'
|
414
|
-
@asset2.attachable.must_equal @post
|
415
|
-
@asset2.attachable_id.must_equal @post.pk
|
416
|
-
@asset2.attachable_type.must_equal 'Post'
|
417
|
-
@asset1.attachable = nil
|
418
|
-
@asset1.attachable.must_be_nil
|
419
|
-
@asset1.attachable_id.must_be_nil
|
420
|
-
@asset1.attachable_type.must_be_nil
|
421
|
-
end
|
422
|
-
|
423
|
-
it "should add items correctly" do
|
424
|
-
@post.assets.must_equal [@asset1]
|
425
|
-
@post.add_asset(@asset2)
|
426
|
-
@post.assets.must_equal [@asset1, @asset2]
|
427
|
-
@asset2.attachable.must_equal @post
|
428
|
-
@asset2.attachable_id.must_equal @post.pk
|
429
|
-
@asset2.attachable_type.must_equal 'Post'
|
430
|
-
end
|
431
|
-
|
432
|
-
it "should remove items correctly" do
|
433
|
-
@note.assets.must_equal [@asset2]
|
434
|
-
@note.remove_asset(@asset2)
|
435
|
-
@note.assets.must_equal []
|
436
|
-
@asset2.attachable.must_be_nil
|
437
|
-
@asset2.attachable_id.must_be_nil
|
438
|
-
@asset2.attachable_type.must_be_nil
|
439
|
-
end
|
440
|
-
|
441
|
-
it "should remove all items correctly" do
|
442
|
-
@post.remove_all_assets
|
443
|
-
@note.remove_all_assets
|
444
|
-
@asset1.reload.attachable.must_be_nil
|
445
|
-
@asset2.reload.attachable.must_be_nil
|
446
|
-
end
|
447
|
-
end
|
448
|
-
|
449
|
-
describe "many_to_one/one_to_many not referencing primary key" do
|
450
|
-
before(:all) do
|
451
|
-
DB.instance_variable_get(:@schemas).clear
|
452
|
-
DB.create_table!(:clients) do
|
453
|
-
primary_key :id
|
454
|
-
String :name
|
455
|
-
end
|
456
|
-
class ::Client < Sequel::Model
|
457
|
-
one_to_many :invoices, :reciprocal=>:client,
|
458
|
-
:adder=>(proc do |invoice|
|
459
|
-
invoice.client_name = name
|
460
|
-
invoice.save
|
461
|
-
end),
|
462
|
-
:remover=>(proc do |invoice|
|
463
|
-
invoice.client_name = nil
|
464
|
-
invoice.save
|
465
|
-
end),
|
466
|
-
:clearer=>proc{invoices_dataset.update(:client_name=>nil)},
|
467
|
-
:dataset=>proc{Invoice.filter(:client_name=>name)},
|
468
|
-
:eager_loader=>(proc do |eo|
|
469
|
-
id_map = {}
|
470
|
-
eo[:rows].each do |client|
|
471
|
-
id_map[client.name] = client
|
472
|
-
client.associations[:invoices] = []
|
473
|
-
end
|
474
|
-
Invoice.filter(:client_name=>id_map.keys.sort).all do |inv|
|
475
|
-
inv.associations[:client] = client = id_map[inv.client_name]
|
476
|
-
client.associations[:invoices] << inv
|
477
|
-
end
|
478
|
-
end)
|
479
|
-
end
|
480
|
-
|
481
|
-
DB.create_table!(:invoices) do
|
482
|
-
primary_key :id
|
483
|
-
String :client_name
|
484
|
-
end
|
485
|
-
class ::Invoice < Sequel::Model
|
486
|
-
many_to_one :client, :key=>:client_name,
|
487
|
-
:setter=>proc{|client| self.client_name = (client.name if client)},
|
488
|
-
:dataset=>proc{Client.filter(:name=>client_name)},
|
489
|
-
:eager_loader=>(proc do |eo|
|
490
|
-
id_map = eo[:id_map]
|
491
|
-
eo[:rows].each{|inv| inv.associations[:client] = nil}
|
492
|
-
Client.filter(:name=>id_map.keys).all do |client|
|
493
|
-
id_map[client.name].each{|inv| inv.associations[:client] = client}
|
494
|
-
end
|
495
|
-
end)
|
496
|
-
end
|
497
|
-
end
|
498
|
-
before do
|
499
|
-
Client.dataset.delete
|
500
|
-
Invoice.dataset.delete
|
501
|
-
@client1 = Client.create(:name=>'X')
|
502
|
-
@client2 = Client.create(:name=>'Y')
|
503
|
-
@invoice1 = Invoice.create(:client_name=>'X')
|
504
|
-
@invoice2 = Invoice.create(:client_name=>'X')
|
505
|
-
end
|
506
|
-
after(:all) do
|
507
|
-
DB.drop_table :invoices, :clients
|
508
|
-
Object.send(:remove_const, :Client)
|
509
|
-
Object.send(:remove_const, :Invoice)
|
510
|
-
end
|
511
|
-
|
512
|
-
it "should load all associated one_to_many objects for a single object" do
|
513
|
-
invs = @client1.invoices
|
514
|
-
invs.sort_by{|x| x.pk}.must_equal [@invoice1, @invoice2]
|
515
|
-
invs[0].client.must_equal @client1
|
516
|
-
invs[1].client.must_equal @client1
|
517
|
-
end
|
518
|
-
|
519
|
-
it "should load the associated many_to_one object for a single object" do
|
520
|
-
client = @invoice1.client
|
521
|
-
client.must_equal @client1
|
522
|
-
end
|
523
|
-
|
524
|
-
it "should eagerly load all associated one_to_many objects for a group of objects" do
|
525
|
-
clients = Client.order(:id).eager(:invoices).all
|
526
|
-
clients.must_equal [@client1, @client2]
|
527
|
-
clients[1].invoices.must_equal []
|
528
|
-
invs = clients[0].invoices.sort_by{|x| x.pk}
|
529
|
-
invs.must_equal [@invoice1, @invoice2]
|
530
|
-
invs[0].client.must_equal @client1
|
531
|
-
invs[1].client.must_equal @client1
|
532
|
-
end
|
533
|
-
|
534
|
-
it "should eagerly load the associated many_to_one object for a group of objects" do
|
535
|
-
invoices = Invoice.order(:id).eager(:client).all
|
536
|
-
invoices.must_equal [@invoice1, @invoice2]
|
537
|
-
invoices[0].client.must_equal @client1
|
538
|
-
invoices[1].client.must_equal @client1
|
539
|
-
end
|
540
|
-
|
541
|
-
it "should set the associated object correctly" do
|
542
|
-
@invoice1.client = @client2
|
543
|
-
@invoice1.client.must_equal @client2
|
544
|
-
@invoice1.client_name.must_equal 'Y'
|
545
|
-
@invoice1.client = nil
|
546
|
-
@invoice1.client_name.must_be_nil
|
547
|
-
end
|
548
|
-
|
549
|
-
it "should add the associated object correctly" do
|
550
|
-
@client2.invoices.must_equal []
|
551
|
-
@client2.add_invoice(@invoice1)
|
552
|
-
@client2.invoices.must_equal [@invoice1]
|
553
|
-
@invoice1.client_name.must_equal 'Y'
|
554
|
-
@invoice1.client = nil
|
555
|
-
@invoice1.client_name.must_be_nil
|
556
|
-
end
|
557
|
-
|
558
|
-
it "should remove the associated object correctly" do
|
559
|
-
invs = @client1.invoices.sort_by{|x| x.pk}
|
560
|
-
invs.must_equal [@invoice1, @invoice2]
|
561
|
-
@client1.remove_invoice(@invoice1)
|
562
|
-
@client1.invoices.must_equal [@invoice2]
|
563
|
-
@invoice1.client_name.must_be_nil
|
564
|
-
@invoice1.client.must_be_nil
|
565
|
-
end
|
566
|
-
|
567
|
-
it "should remove all associated objects correctly" do
|
568
|
-
@client1.remove_all_invoices
|
569
|
-
@invoice1.refresh.client.must_be_nil
|
570
|
-
@invoice1.client_name.must_be_nil
|
571
|
-
@invoice2.refresh.client.must_be_nil
|
572
|
-
@invoice2.client_name.must_be_nil
|
573
|
-
end
|
574
|
-
end
|
575
|
-
|
576
|
-
describe "statistics associations" do
|
577
|
-
before(:all) do
|
578
|
-
DB.create_table!(:projects) do
|
579
|
-
primary_key :id
|
580
|
-
String :name
|
581
|
-
end
|
582
|
-
class ::Project < Sequel::Model
|
583
|
-
many_to_one :ticket_hours, :read_only=>true, :key=>:id, :class=>:Ticket,
|
584
|
-
:dataset=>proc{Ticket.filter(:project_id=>id).select{sum(hours).as(hours)}},
|
585
|
-
:eager_loader=>(proc do |eo|
|
586
|
-
eo[:rows].each{|p| p.associations[:ticket_hours] = nil}
|
587
|
-
Ticket.filter(:project_id=>eo[:id_map].keys).
|
588
|
-
select_group(:project_id).
|
589
|
-
select_append{sum(hours).as(hours)}.
|
590
|
-
all do |t|
|
591
|
-
p = eo[:id_map][t.values.delete(:project_id)].first
|
592
|
-
p.associations[:ticket_hours] = t
|
593
|
-
end
|
594
|
-
end)
|
595
|
-
def ticket_hours
|
596
|
-
if s = super
|
597
|
-
s[:hours]
|
598
|
-
end
|
599
|
-
end
|
600
|
-
end
|
601
|
-
|
602
|
-
DB.create_table!(:tickets) do
|
603
|
-
primary_key :id
|
604
|
-
foreign_key :project_id, :projects
|
605
|
-
Integer :hours
|
606
|
-
end
|
607
|
-
class ::Ticket < Sequel::Model
|
608
|
-
many_to_one :project
|
609
|
-
end
|
610
|
-
|
611
|
-
@project1 = Project.create(:name=>'X')
|
612
|
-
@project2 = Project.create(:name=>'Y')
|
613
|
-
@ticket1 = Ticket.create(:project=>@project1, :hours=>1)
|
614
|
-
@ticket2 = Ticket.create(:project=>@project1, :hours=>10)
|
615
|
-
@ticket3 = Ticket.create(:project=>@project2, :hours=>2)
|
616
|
-
@ticket4 = Ticket.create(:project=>@project2, :hours=>20)
|
617
|
-
end
|
618
|
-
after(:all) do
|
619
|
-
DB.drop_table :tickets, :projects
|
620
|
-
Object.send(:remove_const, :Project)
|
621
|
-
Object.send(:remove_const, :Ticket)
|
622
|
-
end
|
623
|
-
|
624
|
-
it "should give the correct sum of ticket hours for each project" do
|
625
|
-
@project1.ticket_hours.to_i.must_equal 11
|
626
|
-
@project2.ticket_hours.to_i.must_equal 22
|
627
|
-
end
|
628
|
-
|
629
|
-
it "should give the correct sum of ticket hours for each project when eager loading" do
|
630
|
-
p1, p2 = Project.order(:name).eager(:ticket_hours).all
|
631
|
-
p1.ticket_hours.to_i.must_equal 11
|
632
|
-
p2.ticket_hours.to_i.must_equal 22
|
633
|
-
end
|
634
|
-
end
|
635
|
-
|
636
|
-
describe "one to one associations" do
|
637
|
-
before(:all) do
|
638
|
-
DB.create_table!(:books) do
|
639
|
-
primary_key :id
|
640
|
-
end
|
641
|
-
class ::Book < Sequel::Model
|
642
|
-
one_to_one :first_page, :class=>:Page, :conditions=>{:page_number=>1}, :reciprocal=>nil
|
643
|
-
one_to_one :second_page, :class=>:Page, :conditions=>{:page_number=>2}, :reciprocal=>nil
|
644
|
-
end
|
645
|
-
|
646
|
-
DB.create_table!(:pages) do
|
647
|
-
primary_key :id
|
648
|
-
foreign_key :book_id, :books
|
649
|
-
Integer :page_number
|
650
|
-
end
|
651
|
-
class ::Page < Sequel::Model
|
652
|
-
many_to_one :book, :reciprocal=>nil
|
653
|
-
end
|
654
|
-
|
655
|
-
@book1 = Book.create
|
656
|
-
@book2 = Book.create
|
657
|
-
@page1 = Page.create(:book=>@book1, :page_number=>1)
|
658
|
-
@page2 = Page.create(:book=>@book1, :page_number=>2)
|
659
|
-
@page3 = Page.create(:book=>@book2, :page_number=>1)
|
660
|
-
@page4 = Page.create(:book=>@book2, :page_number=>2)
|
661
|
-
end
|
662
|
-
after(:all) do
|
663
|
-
DB.drop_table :pages, :books
|
664
|
-
Object.send(:remove_const, :Book)
|
665
|
-
Object.send(:remove_const, :Page)
|
666
|
-
end
|
667
|
-
|
668
|
-
it "should be eager loadable" do
|
669
|
-
bk1, bk2 = Book.filter(Sequel[:books][:id]=>[1,2]).eager(:first_page).all
|
670
|
-
bk1.first_page.must_equal @page1
|
671
|
-
bk2.first_page.must_equal @page3
|
672
|
-
end
|
673
|
-
|
674
|
-
it "should be eager graphable" do
|
675
|
-
bk1, bk2 = Book.filter(Sequel[:books][:id]=>[1,2]).eager_graph(:first_page).all
|
676
|
-
bk1.first_page.must_equal @page1
|
677
|
-
bk2.first_page.must_equal @page3
|
678
|
-
end
|
679
|
-
|
680
|
-
it "should be eager graphable two at once" do
|
681
|
-
bk1, bk2 = Book.filter(Sequel[:books][:id]=>[1,2]).eager_graph(:first_page, :second_page).all
|
682
|
-
bk1.first_page.must_equal @page1
|
683
|
-
bk1.second_page.must_equal @page2
|
684
|
-
bk2.first_page.must_equal @page3
|
685
|
-
bk2.second_page.must_equal @page4
|
686
|
-
end
|
687
|
-
end
|