Package not found. Please check the package name and try again.
sequel 5.29.0 → 5.30.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 +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,93 +0,0 @@
|
|
|
1
|
-
require_relative "spec_helper"
|
|
2
|
-
require 'yaml'
|
|
3
|
-
|
|
4
|
-
describe "serialization_modification_detection plugin" do
|
|
5
|
-
before do
|
|
6
|
-
@ds = Sequel.mock(:fetch=>{:id=>1, :a=>'a'.dup, :b=>1, :c=>['a'.dup], :d=>{'b'=>'c'.dup}}, :numrows=>1, :autoid=>1)[:items]
|
|
7
|
-
@c = Class.new(Sequel::Model(@ds))
|
|
8
|
-
@c.plugin :modification_detection
|
|
9
|
-
@c.columns :a, :b, :c, :d
|
|
10
|
-
@o = @c.first
|
|
11
|
-
@ds.db.sqls
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
it "should detect setting new column values on new objects" do
|
|
15
|
-
@o = @c.new
|
|
16
|
-
@o.changed_columns.must_equal []
|
|
17
|
-
@o.a = 'c'
|
|
18
|
-
@o.changed_columns.must_equal [:a]
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
it "should only detect columns that have been changed" do
|
|
22
|
-
@o.changed_columns.must_equal []
|
|
23
|
-
@o.a << 'b'
|
|
24
|
-
@o.changed_columns.must_equal [:a]
|
|
25
|
-
@o.a.replace('a')
|
|
26
|
-
@o.changed_columns.must_equal []
|
|
27
|
-
|
|
28
|
-
@o.values[:b] = 2
|
|
29
|
-
@o.changed_columns.must_equal [:b]
|
|
30
|
-
@o.values[:b] = 1
|
|
31
|
-
@o.changed_columns.must_equal []
|
|
32
|
-
|
|
33
|
-
@o.c[0] << 'b'
|
|
34
|
-
@o.d['b'] << 'b'
|
|
35
|
-
@o.changed_columns.sort_by{|c| c.to_s}.must_equal [:c, :d]
|
|
36
|
-
@o.c[0] = 'a'
|
|
37
|
-
@o.changed_columns.must_equal [:d]
|
|
38
|
-
@o.d['b'] = 'c'
|
|
39
|
-
@o.changed_columns.must_equal []
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
it "should detect columns that have been changed on frozen objects" do
|
|
43
|
-
@o.freeze
|
|
44
|
-
@o.a << 'b'
|
|
45
|
-
@o.changed_columns.must_equal [:a]
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
it "should not list a column twice" do
|
|
49
|
-
@o.a = 'b'.dup
|
|
50
|
-
@o.a << 'a'
|
|
51
|
-
@o.changed_columns.must_equal [:a]
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
it "should report correct changed_columns after updating" do
|
|
55
|
-
@o.a << 'a'
|
|
56
|
-
@o.save_changes
|
|
57
|
-
@o.changed_columns.must_equal []
|
|
58
|
-
|
|
59
|
-
@o.values[:b] = 2
|
|
60
|
-
@o.save_changes
|
|
61
|
-
@o.changed_columns.must_equal []
|
|
62
|
-
|
|
63
|
-
@o.c[0] << 'b'
|
|
64
|
-
@o.save_changes
|
|
65
|
-
@o.changed_columns.must_equal []
|
|
66
|
-
|
|
67
|
-
@o.d['b'] << 'a'
|
|
68
|
-
@o.save_changes
|
|
69
|
-
@o.changed_columns.must_equal []
|
|
70
|
-
|
|
71
|
-
@ds.db.sqls.must_equal ["UPDATE items SET a = 'aa' WHERE (id = 1)",
|
|
72
|
-
"UPDATE items SET b = 2 WHERE (id = 1)",
|
|
73
|
-
"UPDATE items SET c = ('ab') WHERE (id = 1)",
|
|
74
|
-
"UPDATE items SET d = ('b' = 'ca') WHERE (id = 1)"]
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
it "should report correct changed_columns after creating new object" do
|
|
78
|
-
o = @c.create
|
|
79
|
-
o.changed_columns.must_equal []
|
|
80
|
-
o.a << 'a'
|
|
81
|
-
o.changed_columns.must_equal [:a]
|
|
82
|
-
@ds.db.sqls.must_equal ["INSERT INTO items DEFAULT VALUES", "SELECT * FROM items WHERE (id = 1) LIMIT 1"]
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
it "should report correct changed_columns after refreshing existing object" do
|
|
86
|
-
@o.a << 'a'
|
|
87
|
-
@o.changed_columns.must_equal [:a]
|
|
88
|
-
@o.refresh
|
|
89
|
-
@o.changed_columns.must_equal []
|
|
90
|
-
@o.a << 'a'
|
|
91
|
-
@o.changed_columns.must_equal [:a]
|
|
92
|
-
end
|
|
93
|
-
end
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
require_relative "spec_helper"
|
|
2
|
-
|
|
3
|
-
describe "MSSSQL optimistic locking plugin" do
|
|
4
|
-
before do
|
|
5
|
-
@db = Sequel.mock(:host=>'mssql')
|
|
6
|
-
@ds = @db[:items].with_quote_identifiers(false).with_extend{def input_identifier(v); v.to_s end}
|
|
7
|
-
@c = Class.new(Sequel::Model(@ds))
|
|
8
|
-
@c.columns :id, :name, :timestamp
|
|
9
|
-
@c.plugin :mssql_optimistic_locking
|
|
10
|
-
@o = @c.load(:id=>1, :name=>'a', :timestamp=>'1234')
|
|
11
|
-
@db.sqls
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
it "should not include the lock column when updating" do
|
|
15
|
-
@db.fetch = [[{:timestamp=>'2345'}]]
|
|
16
|
-
@o.save
|
|
17
|
-
@db.sqls.must_equal ["UPDATE TOP (1) items SET name = 'a' OUTPUT inserted.timestamp WHERE ((id = 1) AND (timestamp = 0x31323334))"]
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
it "should automatically update lock column using new value from database" do
|
|
21
|
-
@db.fetch = [[{:timestamp=>'2345'}]]
|
|
22
|
-
@o.save
|
|
23
|
-
@o.timestamp.must_equal '2345'
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
it "should raise error when updating stale object" do
|
|
27
|
-
@db.fetch = []
|
|
28
|
-
@o.timestamp = '2345'
|
|
29
|
-
proc{@o.save}.must_raise(Sequel::NoExistingObject)
|
|
30
|
-
@o.timestamp.must_equal '2345'
|
|
31
|
-
@db.sqls.must_equal ["UPDATE TOP (1) items SET name = 'a' OUTPUT inserted.timestamp WHERE ((id = 1) AND (timestamp = 0x32333435))"]
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
it "should raise error when destroying stale object" do
|
|
35
|
-
@db.numrows = 0
|
|
36
|
-
@o.timestamp = '2345'
|
|
37
|
-
proc{@o.destroy}.must_raise(Sequel::NoExistingObject)
|
|
38
|
-
@db.sqls.must_equal ["DELETE TOP (1) FROM items WHERE ((id = 1) AND (timestamp = 0x32333435))"]
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
it "should allow refresh after failed save" do
|
|
42
|
-
@db.fetch = []
|
|
43
|
-
@o.timestamp = '2345'
|
|
44
|
-
proc{@o.save}.must_raise(Sequel::NoExistingObject)
|
|
45
|
-
@db.fetch = {:id=>1, :name=>'a', :timestamp=>'2345'}
|
|
46
|
-
@o.refresh
|
|
47
|
-
@db.sqls
|
|
48
|
-
@o.save
|
|
49
|
-
@db.sqls.must_equal ["UPDATE TOP (1) items SET name = 'a' OUTPUT inserted.timestamp WHERE ((id = 1) AND (timestamp = 0x32333435))"]
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it "should allow changing the lock column via model.lock_column=" do
|
|
53
|
-
@c = Class.new(Sequel::Model(@ds))
|
|
54
|
-
@c.columns :id, :name, :lv
|
|
55
|
-
@c.plugin :mssql_optimistic_locking
|
|
56
|
-
@c.lock_column = :lv
|
|
57
|
-
@o = @c.load(:id=>1, :name=>'a', :lv=>'1234')
|
|
58
|
-
@db.sqls
|
|
59
|
-
@db.fetch = []
|
|
60
|
-
proc{@o.save}.must_raise(Sequel::NoExistingObject)
|
|
61
|
-
@o.lv.must_equal '1234'
|
|
62
|
-
@db.sqls.must_equal ["UPDATE TOP (1) items SET name = 'a' OUTPUT inserted.lv WHERE ((id = 1) AND (lv = 0x31323334))"]
|
|
63
|
-
@o = @c.load(:id=>1, :name=>'a', :lv=>'1234')
|
|
64
|
-
@db.fetch = {:lv=>'2345'}
|
|
65
|
-
@o.save
|
|
66
|
-
@o.lv.must_equal '2345'
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
it "should allow changing the lock column via plugin option" do
|
|
70
|
-
@c = Class.new(Sequel::Model(@ds))
|
|
71
|
-
@c.columns :id, :name, :lv
|
|
72
|
-
@c.plugin :mssql_optimistic_locking, :lock_column=>:lv
|
|
73
|
-
@o = @c.load(:id=>1, :name=>'a', :lv=>'1234')
|
|
74
|
-
@db.sqls
|
|
75
|
-
@db.fetch = []
|
|
76
|
-
proc{@o.save}.must_raise(Sequel::NoExistingObject)
|
|
77
|
-
@o.lv.must_equal '1234'
|
|
78
|
-
@db.sqls.must_equal ["UPDATE TOP (1) items SET name = 'a' OUTPUT inserted.lv WHERE ((id = 1) AND (lv = 0x31323334))"]
|
|
79
|
-
@o = @c.load(:id=>1, :name=>'a', :lv=>'1234')
|
|
80
|
-
@db.fetch = {:lv=>'2345'}
|
|
81
|
-
@o.save
|
|
82
|
-
@o.lv.must_equal '2345'
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
it "should work when subclassing" do
|
|
86
|
-
c = Class.new(@c)
|
|
87
|
-
o = c.load(:id=>1, :name=>'a', :timestamp=>'1234')
|
|
88
|
-
@db.fetch = [[{:timestamp=>'2345'}]]
|
|
89
|
-
o.save
|
|
90
|
-
@db.sqls.must_equal ["UPDATE TOP (1) items SET name = 'a' OUTPUT inserted.timestamp WHERE ((id = 1) AND (timestamp = 0x31323334))"]
|
|
91
|
-
end
|
|
92
|
-
end
|
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
require_relative "spec_helper"
|
|
2
|
-
|
|
3
|
-
begin
|
|
4
|
-
require 'tzinfo'
|
|
5
|
-
rescue LoadError
|
|
6
|
-
warn "Skipping test of named_timezones extension: can't load tzinfo"
|
|
7
|
-
else
|
|
8
|
-
Sequel.extension :thread_local_timezones
|
|
9
|
-
Sequel.extension :named_timezones
|
|
10
|
-
Sequel.datetime_class = Time
|
|
11
|
-
|
|
12
|
-
describe "Sequel named_timezones extension with DateTime class" do
|
|
13
|
-
before do
|
|
14
|
-
@tz_in = TZInfo::Timezone.get('America/Los_Angeles')
|
|
15
|
-
@tz_out = TZInfo::Timezone.get('America/New_York')
|
|
16
|
-
@db = Sequel.mock
|
|
17
|
-
@dt = DateTime.civil(2009,6,1,10,20,30,0)
|
|
18
|
-
Sequel.application_timezone = 'America/Los_Angeles'
|
|
19
|
-
Sequel.database_timezone = 'America/New_York'
|
|
20
|
-
Sequel.datetime_class = DateTime
|
|
21
|
-
end
|
|
22
|
-
after do
|
|
23
|
-
Sequel.tzinfo_disambiguator = nil
|
|
24
|
-
Sequel.default_timezone = nil
|
|
25
|
-
Sequel.datetime_class = Time
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
it "should convert string arguments to *_timezone= to TZInfo::Timezone instances" do
|
|
29
|
-
Sequel.application_timezone.must_equal @tz_in
|
|
30
|
-
Sequel.database_timezone.must_equal @tz_out
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
it "should convert string arguments for Database#timezone= to TZInfo::Timezone instances for database-specific timezones" do
|
|
34
|
-
@db.extension :named_timezones
|
|
35
|
-
@db.timezone = 'America/Los_Angeles'
|
|
36
|
-
@db.timezone.must_equal @tz_in
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it "should accept TZInfo::Timezone instances in *_timezone=" do
|
|
40
|
-
Sequel.application_timezone = @tz_in
|
|
41
|
-
Sequel.database_timezone = @tz_out
|
|
42
|
-
Sequel.application_timezone.must_equal @tz_in
|
|
43
|
-
Sequel.database_timezone.must_equal @tz_out
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
it "should convert datetimes going into the database to named database_timezone" do
|
|
47
|
-
ds = @db[:a].with_extend do
|
|
48
|
-
def supports_timestamp_timezones?; true; end
|
|
49
|
-
def supports_timestamp_usecs?; false; end
|
|
50
|
-
end
|
|
51
|
-
ds.insert([@dt, DateTime.civil(2009,6,1,3,20,30,-7/24.0), DateTime.civil(2009,6,1,6,20,30,-1/6.0)])
|
|
52
|
-
@db.sqls.must_equal ["INSERT INTO a VALUES ('2009-06-01 06:20:30-0400', '2009-06-01 06:20:30-0400', '2009-06-01 06:20:30-0400')"]
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
it "should convert datetimes coming out of the database from database_timezone to application_timezone" do
|
|
56
|
-
dt = Sequel.database_to_application_timestamp('2009-06-01 06:20:30-0400')
|
|
57
|
-
dt.must_be_instance_of DateTime
|
|
58
|
-
dt.must_equal @dt
|
|
59
|
-
dt.offset.must_equal(-7/24.0)
|
|
60
|
-
|
|
61
|
-
dt = Sequel.database_to_application_timestamp('2009-06-01 10:20:30+0000')
|
|
62
|
-
dt.must_be_instance_of DateTime
|
|
63
|
-
dt.must_equal @dt
|
|
64
|
-
dt.offset.must_equal(-7/24.0)
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
it "should raise an error for ambiguous timezones by default" do
|
|
68
|
-
proc{Sequel.database_to_application_timestamp('2004-10-31T01:30:00')}.must_raise(Sequel::InvalidValue)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
it "should support tzinfo_disambiguator= to handle ambiguous timezones automatically" do
|
|
72
|
-
Sequel.tzinfo_disambiguator = proc{|datetime, periods| periods.first}
|
|
73
|
-
dt = Sequel.database_to_application_timestamp('2004-10-31T01:30:00')
|
|
74
|
-
dt.must_equal DateTime.parse('2004-10-30T22:30:00-07:00')
|
|
75
|
-
dt.offset.must_equal(-7/24.0)
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
it "should assume datetimes coming out of the database that don't have an offset as coming from database_timezone" do
|
|
79
|
-
dt = Sequel.database_to_application_timestamp('2009-06-01 06:20:30')
|
|
80
|
-
dt.must_be_instance_of DateTime
|
|
81
|
-
dt.must_equal @dt
|
|
82
|
-
dt.offset.must_equal(-7/24.0)
|
|
83
|
-
|
|
84
|
-
dt = Sequel.database_to_application_timestamp('2009-06-01 10:20:30')
|
|
85
|
-
dt.must_be_instance_of DateTime
|
|
86
|
-
dt.must_equal(@dt + 1/6.0)
|
|
87
|
-
dt.offset.must_equal(-7/24.0)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
it "should work with the thread_local_timezones extension" do
|
|
91
|
-
q, q1, q2 = Queue.new, Queue.new, Queue.new
|
|
92
|
-
tz1, tz2 = nil, nil
|
|
93
|
-
t1 = Thread.new do
|
|
94
|
-
Sequel.thread_application_timezone = 'America/New_York'
|
|
95
|
-
q2.push nil
|
|
96
|
-
q.pop
|
|
97
|
-
tz1 = Sequel.application_timezone
|
|
98
|
-
end
|
|
99
|
-
t2 = Thread.new do
|
|
100
|
-
Sequel.thread_application_timezone = 'America/Los_Angeles'
|
|
101
|
-
q2.push nil
|
|
102
|
-
q1.pop
|
|
103
|
-
tz2 = Sequel.application_timezone
|
|
104
|
-
end
|
|
105
|
-
q2.pop
|
|
106
|
-
q2.pop
|
|
107
|
-
q.push nil
|
|
108
|
-
q1.push nil
|
|
109
|
-
t1.join
|
|
110
|
-
t2.join
|
|
111
|
-
tz1.must_equal @tz_out
|
|
112
|
-
tz2.must_equal @tz_in
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
describe "Sequel named_timezones extension with Time class" do
|
|
117
|
-
before do
|
|
118
|
-
@tz_in = TZInfo::Timezone.get('America/Los_Angeles')
|
|
119
|
-
@tz_out = TZInfo::Timezone.get('America/New_York')
|
|
120
|
-
@db = Sequel.mock
|
|
121
|
-
Sequel.application_timezone = 'America/Los_Angeles'
|
|
122
|
-
Sequel.database_timezone = 'America/New_York'
|
|
123
|
-
end
|
|
124
|
-
after do
|
|
125
|
-
Sequel.tzinfo_disambiguator = nil
|
|
126
|
-
Sequel.default_timezone = nil
|
|
127
|
-
Sequel.datetime_class = Time
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
it "should convert string arguments to *_timezone= to TZInfo::Timezone instances" do
|
|
131
|
-
Sequel.application_timezone.must_equal @tz_in
|
|
132
|
-
Sequel.database_timezone.must_equal @tz_out
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
it "should convert string arguments for Database#timezone= to TZInfo::Timezone instances for database-specific timezones" do
|
|
136
|
-
@db.extension :named_timezones
|
|
137
|
-
@db.timezone = 'America/Los_Angeles'
|
|
138
|
-
@db.timezone.must_equal @tz_in
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
it "should accept TZInfo::Timezone instances in *_timezone=" do
|
|
142
|
-
Sequel.application_timezone = @tz_in
|
|
143
|
-
Sequel.database_timezone = @tz_out
|
|
144
|
-
Sequel.application_timezone.must_equal @tz_in
|
|
145
|
-
Sequel.database_timezone.must_equal @tz_out
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
it "should convert datetimes going into the database to named database_timezone" do
|
|
149
|
-
ds = @db[:a].with_extend do
|
|
150
|
-
def supports_timestamp_timezones?; true; end
|
|
151
|
-
def supports_timestamp_usecs?; false; end
|
|
152
|
-
end
|
|
153
|
-
ds.insert([Time.new(2009,6,1,3,20,30, RUBY_VERSION >= '2.6' ? @tz_in : -25200), Time.new(2009,6,1,3,20,30,-25200), Time.new(2009,6,1,6,20,30,-14400)])
|
|
154
|
-
@db.sqls.must_equal ["INSERT INTO a VALUES ('2009-06-01 06:20:30-0400', '2009-06-01 06:20:30-0400', '2009-06-01 06:20:30-0400')"]
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
it "should convert datetimes coming out of the database from database_timezone to application_timezone" do
|
|
158
|
-
dt = Sequel.database_to_application_timestamp('2009-06-01 06:20:30-0400')
|
|
159
|
-
dt.must_be_instance_of Time
|
|
160
|
-
dt.must_equal Time.new(2009,6,1,3,20,30,-25200)
|
|
161
|
-
dt.utc_offset.must_equal(-25200)
|
|
162
|
-
|
|
163
|
-
dt = Sequel.database_to_application_timestamp('2009-06-01 10:20:30+0000')
|
|
164
|
-
dt.must_be_instance_of Time
|
|
165
|
-
dt.must_equal Time.new(2009,6,1,3,20,30,-25200)
|
|
166
|
-
dt.utc_offset.must_equal(-25200)
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
it "should raise an error for ambiguous timezones by default" do
|
|
170
|
-
proc{Sequel.database_to_application_timestamp('2004-10-31T01:30:00')}.must_raise(Sequel::InvalidValue)
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
it "should support tzinfo_disambiguator= to handle ambiguous timezones automatically" do
|
|
174
|
-
Sequel.tzinfo_disambiguator = proc{|datetime, periods| periods.first}
|
|
175
|
-
Sequel.database_to_application_timestamp('2004-10-31T01:30:00').must_equal Time.new(2004, 10, 30, 22, 30, 0, -25200)
|
|
176
|
-
dt = Sequel.database_to_application_timestamp('2004-10-31T01:30:00')
|
|
177
|
-
dt.must_equal Time.new(2004, 10, 30, 22, 30, 0, -25200)
|
|
178
|
-
dt.utc_offset.must_equal(-25200)
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
it "should assume datetimes coming out of the database that don't have an offset as coming from database_timezone" do
|
|
182
|
-
dt = Sequel.database_to_application_timestamp('2009-06-01 06:20:30')
|
|
183
|
-
dt.must_be_instance_of Time
|
|
184
|
-
dt.must_equal Time.new(2009,6,1,3,20,30, -25200)
|
|
185
|
-
dt.utc_offset.must_equal(-25200)
|
|
186
|
-
|
|
187
|
-
dt = Sequel.database_to_application_timestamp('2009-06-01 10:20:30')
|
|
188
|
-
dt.must_be_instance_of Time
|
|
189
|
-
dt.must_equal Time.new(2009,6,1,7,20,30, -25200)
|
|
190
|
-
dt.utc_offset.must_equal(-25200)
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
it "should work with the thread_local_timezones extension" do
|
|
194
|
-
q, q1, q2 = Queue.new, Queue.new, Queue.new
|
|
195
|
-
tz1, tz2 = nil, nil
|
|
196
|
-
t1 = Thread.new do
|
|
197
|
-
Sequel.thread_application_timezone = 'America/New_York'
|
|
198
|
-
q2.push nil
|
|
199
|
-
q.pop
|
|
200
|
-
tz1 = Sequel.application_timezone
|
|
201
|
-
end
|
|
202
|
-
t2 = Thread.new do
|
|
203
|
-
Sequel.thread_application_timezone = 'America/Los_Angeles'
|
|
204
|
-
q2.push nil
|
|
205
|
-
q1.pop
|
|
206
|
-
tz2 = Sequel.application_timezone
|
|
207
|
-
end
|
|
208
|
-
q2.pop
|
|
209
|
-
q2.pop
|
|
210
|
-
q.push nil
|
|
211
|
-
q1.push nil
|
|
212
|
-
t1.join
|
|
213
|
-
t2.join
|
|
214
|
-
tz1.must_equal @tz_out
|
|
215
|
-
tz2.must_equal @tz_in
|
|
216
|
-
end
|
|
217
|
-
end
|
|
218
|
-
end
|
|
@@ -1,815 +0,0 @@
|
|
|
1
|
-
require_relative "spec_helper"
|
|
2
|
-
|
|
3
|
-
describe "NestedAttributes plugin" do
|
|
4
|
-
def check_sqls(should, is)
|
|
5
|
-
if should.is_a?(Array)
|
|
6
|
-
should.must_include(is)
|
|
7
|
-
else
|
|
8
|
-
is.must_equal should
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def check_sql_array(*shoulds)
|
|
13
|
-
sqls = @db.sqls
|
|
14
|
-
sqls.length.must_equal shoulds.length
|
|
15
|
-
shoulds.zip(sqls){|s, i| check_sqls(s, i)}
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
before do
|
|
19
|
-
@db = Sequel.mock(:autoid=>1, :numrows=>1)
|
|
20
|
-
@c = Class.new(Sequel::Model(@db))
|
|
21
|
-
@c.plugin :nested_attributes
|
|
22
|
-
@Artist = Class.new(@c).set_dataset(:artists)
|
|
23
|
-
@Album = Class.new(@c).set_dataset(:albums)
|
|
24
|
-
@Tag = Class.new(@c).set_dataset(:tags)
|
|
25
|
-
@Concert = Class.new(@c).set_dataset(:concerts)
|
|
26
|
-
@Artist.plugin :skip_create_refresh
|
|
27
|
-
@Album.plugin :skip_create_refresh
|
|
28
|
-
@Tag.plugin :skip_create_refresh
|
|
29
|
-
@Concert.plugin :skip_create_refresh
|
|
30
|
-
@Artist.columns :id, :name
|
|
31
|
-
@Album.columns :id, :name, :artist_id
|
|
32
|
-
@Tag.columns :id, :name
|
|
33
|
-
@Concert.columns :tour, :date, :artist_id, :playlist
|
|
34
|
-
@Concert.set_primary_key([:tour, :date])
|
|
35
|
-
@Concert.unrestrict_primary_key
|
|
36
|
-
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id
|
|
37
|
-
@Artist.one_to_many :concerts, :class=>@Concert, :key=>:artist_id
|
|
38
|
-
@Artist.one_to_one :first_album, :class=>@Album, :key=>:artist_id
|
|
39
|
-
@Artist.one_to_one :first_concert, :class=>@Concert, :key=>:artist_id
|
|
40
|
-
@Concert.one_to_many :albums, :class=>@Album, :key=>:artist_id, :primary_key=>:artist_id
|
|
41
|
-
@Album.many_to_one :artist, :class=>@Artist, :reciprocal=>:albums
|
|
42
|
-
@Album.many_to_many :tags, :class=>@Tag, :left_key=>:album_id, :right_key=>:tag_id, :join_table=>:at
|
|
43
|
-
@Tag.many_to_many :albums, :class=>@Album, :left_key=>:tag_id, :right_key=>:album_id, :join_table=>:at
|
|
44
|
-
@Artist.nested_attributes :albums, :first_album, :destroy=>true, :remove=>true
|
|
45
|
-
@Artist.nested_attributes :concerts, :destroy=>true, :remove=>true
|
|
46
|
-
@Album.nested_attributes :artist, :tags, :destroy=>true, :remove=>true
|
|
47
|
-
@Artist.nested_attributes :first_concert
|
|
48
|
-
@Concert.nested_attributes :albums
|
|
49
|
-
@db.sqls
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it "should not modify options hash when loading plugin" do
|
|
53
|
-
h = {}
|
|
54
|
-
@Concert.nested_attributes :albums, h
|
|
55
|
-
h.must_equal({})
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
it "should support creating new many_to_one objects" do
|
|
59
|
-
a = @Album.new({:name=>'Al', :artist_attributes=>{:name=>'Ar'}})
|
|
60
|
-
@db.sqls.must_equal []
|
|
61
|
-
a.save
|
|
62
|
-
check_sql_array("INSERT INTO artists (name) VALUES ('Ar')",
|
|
63
|
-
["INSERT INTO albums (name, artist_id) VALUES ('Al', 1)", "INSERT INTO albums (artist_id, name) VALUES (1, 'Al')"])
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
it "should support creating new one_to_one objects" do
|
|
67
|
-
a = @Artist.new(:name=>'Ar')
|
|
68
|
-
a.id = 1
|
|
69
|
-
a.first_album_attributes = {:name=>'Al'}
|
|
70
|
-
@db.sqls.must_equal []
|
|
71
|
-
a.save
|
|
72
|
-
check_sql_array(["INSERT INTO artists (name, id) VALUES ('Ar', 1)", "INSERT INTO artists (id, name) VALUES (1, 'Ar')"],
|
|
73
|
-
"UPDATE albums SET artist_id = NULL WHERE (artist_id = 1)",
|
|
74
|
-
["INSERT INTO albums (artist_id, name) VALUES (1, 'Al')", "INSERT INTO albums (name, artist_id) VALUES ('Al', 1)"])
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
it "should support creating new one_to_many objects" do
|
|
78
|
-
a = @Artist.new({:name=>'Ar', :albums_attributes=>[{:name=>'Al'}]})
|
|
79
|
-
@db.sqls.must_equal []
|
|
80
|
-
a.save
|
|
81
|
-
check_sql_array("INSERT INTO artists (name) VALUES ('Ar')",
|
|
82
|
-
["INSERT INTO albums (artist_id, name) VALUES (1, 'Al')", "INSERT INTO albums (name, artist_id) VALUES ('Al', 1)"])
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
it "should support creating new one_to_many and one_to_one objects with presence validations on the foreign key" do
|
|
86
|
-
@Album.class_eval do
|
|
87
|
-
plugin :validation_helpers
|
|
88
|
-
def validate
|
|
89
|
-
validates_integer :artist_id
|
|
90
|
-
super
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
a = @Artist.new({:name=>'Ar', :albums_attributes=>[{:name=>'Al'}]})
|
|
94
|
-
@db.sqls.must_equal []
|
|
95
|
-
a.save
|
|
96
|
-
check_sql_array("INSERT INTO artists (name) VALUES ('Ar')",
|
|
97
|
-
["INSERT INTO albums (artist_id, name) VALUES (1, 'Al')", "INSERT INTO albums (name, artist_id) VALUES ('Al', 1)"])
|
|
98
|
-
|
|
99
|
-
a = @Artist.new(:name=>'Ar')
|
|
100
|
-
a.id = 1
|
|
101
|
-
a.first_album_attributes = {:name=>'Al'}
|
|
102
|
-
@db.sqls.must_equal []
|
|
103
|
-
a.save
|
|
104
|
-
check_sql_array(["INSERT INTO artists (name, id) VALUES ('Ar', 1)", "INSERT INTO artists (id, name) VALUES (1, 'Ar')"],
|
|
105
|
-
"UPDATE albums SET artist_id = NULL WHERE (artist_id = 1)",
|
|
106
|
-
["INSERT INTO albums (artist_id, name) VALUES (1, 'Al')", "INSERT INTO albums (name, artist_id) VALUES ('Al', 1)"])
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
it "should support creating new one_to_many and one_to_one objects with composite keys with presence validations on the foreign key" do
|
|
110
|
-
insert = nil
|
|
111
|
-
@Album.class_eval do
|
|
112
|
-
plugin :validation_helpers
|
|
113
|
-
def validate
|
|
114
|
-
validates_integer :artist_id
|
|
115
|
-
super
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
@Concert.class_eval do
|
|
119
|
-
define_method :_insert do
|
|
120
|
-
insert = values.dup
|
|
121
|
-
end
|
|
122
|
-
def before_create # Have to define the CPK somehow.
|
|
123
|
-
self.tour = 'To'
|
|
124
|
-
self.date = '2004-04-05'
|
|
125
|
-
super
|
|
126
|
-
end
|
|
127
|
-
def after_create
|
|
128
|
-
super
|
|
129
|
-
self.artist_id = 3
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
c = @Concert.new(:playlist=>'Pl')
|
|
134
|
-
@db.sqls.must_equal []
|
|
135
|
-
c.albums_attributes = [{:name=>'Al'}]
|
|
136
|
-
c.save
|
|
137
|
-
insert.must_equal(:tour=>'To', :date=>'2004-04-05', :playlist=>'Pl')
|
|
138
|
-
check_sql_array(["INSERT INTO albums (name, artist_id) VALUES ('Al', 3)", "INSERT INTO albums (artist_id, name) VALUES (3, 'Al')"])
|
|
139
|
-
|
|
140
|
-
@Concert.class_eval do
|
|
141
|
-
plugin :validation_helpers
|
|
142
|
-
def validate
|
|
143
|
-
validates_integer :artist_id
|
|
144
|
-
super
|
|
145
|
-
end
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
a = @Artist.new(:name=>'Ar')
|
|
149
|
-
a.id = 1
|
|
150
|
-
a.first_concert_attributes = {:playlist=>'Pl'}
|
|
151
|
-
@db.sqls.must_equal []
|
|
152
|
-
a.save
|
|
153
|
-
check_sql_array(["INSERT INTO artists (name, id) VALUES ('Ar', 1)", "INSERT INTO artists (id, name) VALUES (1, 'Ar')"],
|
|
154
|
-
"UPDATE concerts SET artist_id = NULL WHERE (artist_id = 1)")
|
|
155
|
-
insert.must_equal(:tour=>'To', :date=>'2004-04-05', :artist_id=>1, :playlist=>'Pl')
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
it "should should not remove existing values from object when validating" do
|
|
159
|
-
@Artist.one_to_one :first_album, :class=>@Album, :key=>:id
|
|
160
|
-
@Artist.nested_attributes :first_album
|
|
161
|
-
@db.fetch = {:id=>1}
|
|
162
|
-
a = @Artist.load(:id=>1)
|
|
163
|
-
a.set(:first_album_attributes=>{:id=>1, :name=>'Ar'})
|
|
164
|
-
a.first_album.values.must_equal(:id=>1, :name=>'Ar')
|
|
165
|
-
@db.sqls.must_equal ["SELECT * FROM albums WHERE (albums.id = 1) LIMIT 1"]
|
|
166
|
-
a.save_changes
|
|
167
|
-
check_sql_array("UPDATE albums SET name = 'Ar' WHERE (id = 1)")
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
it "should support creating new many_to_many objects" do
|
|
171
|
-
a = @Album.new({:name=>'Al', :tags_attributes=>[{:name=>'T'}]})
|
|
172
|
-
@db.sqls.must_equal []
|
|
173
|
-
a.save
|
|
174
|
-
check_sql_array("INSERT INTO albums (name) VALUES ('Al')",
|
|
175
|
-
"INSERT INTO tags (name) VALUES ('T')",
|
|
176
|
-
["INSERT INTO at (album_id, tag_id) VALUES (1, 2)", "INSERT INTO at (tag_id, album_id) VALUES (2, 1)"])
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
it "should add new objects to the cached association array as soon as the *_attributes= method is called" do
|
|
180
|
-
a = @Artist.new({:name=>'Ar', :first_album_attributes=>{:name=>'B'}, :albums_attributes=>[{:name=>'Al', :tags_attributes=>[{:name=>'T'}]}]})
|
|
181
|
-
a.albums.must_equal [@Album.new(:name=>'Al')]
|
|
182
|
-
a.albums.first.artist.must_equal a
|
|
183
|
-
a.albums.first.tags.must_equal [@Tag.new(:name=>'T')]
|
|
184
|
-
a.first_album.must_equal @Album.new(:name=>'B')
|
|
185
|
-
a.first_album.artist.must_equal a
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
it "should support creating new objects with composite primary keys" do
|
|
189
|
-
insert = nil
|
|
190
|
-
@Concert.class_eval do
|
|
191
|
-
define_method :_insert do
|
|
192
|
-
insert = values.dup
|
|
193
|
-
end
|
|
194
|
-
def before_create # Have to define the CPK somehow.
|
|
195
|
-
self.tour = 'To'
|
|
196
|
-
self.date = '2004-04-05'
|
|
197
|
-
super
|
|
198
|
-
end
|
|
199
|
-
end
|
|
200
|
-
a = @Artist.new({:name=>'Ar', :concerts_attributes=>[{:playlist=>'Pl'}]})
|
|
201
|
-
@db.sqls.must_equal []
|
|
202
|
-
a.save
|
|
203
|
-
@db.sqls.must_equal ["INSERT INTO artists (name) VALUES ('Ar')"]
|
|
204
|
-
insert.must_equal(:tour=>'To', :date=>'2004-04-05', :artist_id=>1, :playlist=>'Pl')
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
it "should support creating new objects with specific primary keys if :unmatched_pk => :create is set" do
|
|
208
|
-
@Artist.nested_attributes :albums, :unmatched_pk=>:create
|
|
209
|
-
insert = nil
|
|
210
|
-
@Album.class_eval do
|
|
211
|
-
unrestrict_primary_key
|
|
212
|
-
define_method :_insert do
|
|
213
|
-
insert = values.dup
|
|
214
|
-
end
|
|
215
|
-
end
|
|
216
|
-
a = @Artist.new({:name=>'Ar', :albums_attributes=>[{:id=>7, :name=>'Al'}]})
|
|
217
|
-
@db.sqls.must_equal []
|
|
218
|
-
a.save
|
|
219
|
-
@db.sqls.must_equal ["INSERT INTO artists (name) VALUES ('Ar')"]
|
|
220
|
-
insert.must_equal(:artist_id=>1, :name=>'Al', :id=>7)
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
it "should support creating new objects with specific composite primary keys if :unmatched_pk => :create is set" do
|
|
224
|
-
insert = nil
|
|
225
|
-
@Artist.nested_attributes :concerts, :unmatched_pk=>:create
|
|
226
|
-
@Concert.class_eval do
|
|
227
|
-
define_method :_insert do
|
|
228
|
-
insert = values.dup
|
|
229
|
-
end
|
|
230
|
-
end
|
|
231
|
-
a = @Artist.new({:name=>'Ar', :concerts_attributes=>[{:tour=>'To', :date=>'2004-04-05', :playlist=>'Pl'}]})
|
|
232
|
-
@db.sqls.must_equal []
|
|
233
|
-
a.save
|
|
234
|
-
@db.sqls.must_equal ["INSERT INTO artists (name) VALUES ('Ar')"]
|
|
235
|
-
insert.must_equal(:tour=>'To', :date=>'2004-04-05', :artist_id=>1, :playlist=>'Pl')
|
|
236
|
-
end
|
|
237
|
-
|
|
238
|
-
it "should support updating many_to_one objects" do
|
|
239
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
240
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
241
|
-
al.associations[:artist] = ar
|
|
242
|
-
al.set(:artist_attributes=>{:id=>'20', :name=>'Ar2'})
|
|
243
|
-
@db.sqls.must_equal []
|
|
244
|
-
al.save
|
|
245
|
-
@db.sqls.must_equal ["UPDATE albums SET name = 'Al' WHERE (id = 10)", "UPDATE artists SET name = 'Ar2' WHERE (id = 20)"]
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
it "should support updating one_to_one objects" do
|
|
249
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
250
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
251
|
-
ar.associations[:first_album] = al
|
|
252
|
-
ar.set(:first_album_attributes=>{:id=>10, :name=>'Al2'})
|
|
253
|
-
@db.sqls.must_equal []
|
|
254
|
-
ar.save
|
|
255
|
-
@db.sqls.must_equal ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "UPDATE albums SET name = 'Al2' WHERE (id = 10)"]
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
it "should support updating one_to_many objects" do
|
|
259
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
260
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
261
|
-
ar.associations[:albums] = [al]
|
|
262
|
-
ar.set(:albums_attributes=>[{:id=>10, :name=>'Al2'}])
|
|
263
|
-
@db.sqls.must_equal []
|
|
264
|
-
ar.save
|
|
265
|
-
@db.sqls.must_equal ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "UPDATE albums SET name = 'Al2' WHERE (id = 10)"]
|
|
266
|
-
end
|
|
267
|
-
|
|
268
|
-
it "should support updating one_to_many objects with _delete/_remove flags set to false" do
|
|
269
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
270
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
271
|
-
ar.associations[:albums] = [al]
|
|
272
|
-
ar.set(:albums_attributes=>[{:id=>10, :name=>'Al2', :_delete => 'f', :_remove => '0'}])
|
|
273
|
-
@db.sqls.must_equal []
|
|
274
|
-
ar.save
|
|
275
|
-
@db.sqls.must_equal ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "UPDATE albums SET name = 'Al2' WHERE (id = 10)"]
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
it "should support updating many_to_many objects" do
|
|
279
|
-
a = @Album.load(:id=>10, :name=>'Al')
|
|
280
|
-
t = @Tag.load(:id=>20, :name=>'T')
|
|
281
|
-
a.associations[:tags] = [t]
|
|
282
|
-
a.set(:tags_attributes=>[{:id=>20, :name=>'T2'}])
|
|
283
|
-
@db.sqls.must_equal []
|
|
284
|
-
a.save
|
|
285
|
-
@db.sqls.must_equal ["UPDATE albums SET name = 'Al' WHERE (id = 10)", "UPDATE tags SET name = 'T2' WHERE (id = 20)"]
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
it "should support updating many_to_many objects with _delete/_remove flags set to false" do
|
|
289
|
-
a = @Album.load(:id=>10, :name=>'Al')
|
|
290
|
-
t = @Tag.load(:id=>20, :name=>'T')
|
|
291
|
-
a.associations[:tags] = [t]
|
|
292
|
-
a.set(:tags_attributes=>[{:id=>20, :name=>'T2', '_delete' => false, '_remove' => 'F'}])
|
|
293
|
-
@db.sqls.must_equal []
|
|
294
|
-
a.save
|
|
295
|
-
@db.sqls.must_equal ["UPDATE albums SET name = 'Al' WHERE (id = 10)", "UPDATE tags SET name = 'T2' WHERE (id = 20)"]
|
|
296
|
-
end
|
|
297
|
-
|
|
298
|
-
it "should support updating objects with composite primary keys" do
|
|
299
|
-
ar = @Artist.load(:id=>10, :name=>'Ar')
|
|
300
|
-
co = @Concert.load(:tour=>'To', :date=>'2004-04-05', :playlist=>'Pl')
|
|
301
|
-
ar.associations[:concerts] = [co]
|
|
302
|
-
ar.set(:concerts_attributes=>[{:tour=>'To', :date=>'2004-04-05', :playlist=>'Pl2'}])
|
|
303
|
-
@db.sqls.must_equal []
|
|
304
|
-
ar.save
|
|
305
|
-
check_sql_array("UPDATE artists SET name = 'Ar' WHERE (id = 10)", ["UPDATE concerts SET playlist = 'Pl2' WHERE ((tour = 'To') AND (date = '2004-04-05'))", "UPDATE concerts SET playlist = 'Pl2' WHERE ((date = '2004-04-05') AND (tour = 'To'))"])
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
it "should support removing many_to_one objects" do
|
|
309
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
310
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
311
|
-
al.associations[:artist] = ar
|
|
312
|
-
al.set(:artist_attributes=>{:id=>'20', :_remove=>'1'})
|
|
313
|
-
@db.sqls.must_equal []
|
|
314
|
-
al.save
|
|
315
|
-
check_sql_array(["UPDATE albums SET artist_id = NULL, name = 'Al' WHERE (id = 10)", "UPDATE albums SET name = 'Al', artist_id = NULL WHERE (id = 10)"])
|
|
316
|
-
end
|
|
317
|
-
|
|
318
|
-
it "should support removing one_to_one objects" do
|
|
319
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
320
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
321
|
-
ar.associations[:first_album] = al
|
|
322
|
-
ar.set(:first_album_attributes=>{:id=>10, :_remove=>'t'})
|
|
323
|
-
@db.sqls.must_equal []
|
|
324
|
-
ar.save
|
|
325
|
-
@db.sqls.must_equal ["UPDATE albums SET artist_id = NULL WHERE (artist_id = 20)", "UPDATE artists SET name = 'Ar' WHERE (id = 20)"]
|
|
326
|
-
end
|
|
327
|
-
|
|
328
|
-
it "should support removing one_to_many objects" do
|
|
329
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
330
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
331
|
-
ar.associations[:albums] = [al]
|
|
332
|
-
ar.set(:albums_attributes=>[{:id=>10, :_remove=>'t'}])
|
|
333
|
-
ar.associations[:albums].must_equal []
|
|
334
|
-
@db.sqls.must_equal []
|
|
335
|
-
@Album.dataset = @Album.dataset.with_fetch(:id=>1)
|
|
336
|
-
ar.save
|
|
337
|
-
check_sql_array("SELECT 1 AS one FROM albums WHERE ((albums.artist_id = 20) AND (id = 10)) LIMIT 1",
|
|
338
|
-
["UPDATE albums SET artist_id = NULL, name = 'Al' WHERE (id = 10)", "UPDATE albums SET name = 'Al', artist_id = NULL WHERE (id = 10)"],
|
|
339
|
-
"UPDATE artists SET name = 'Ar' WHERE (id = 20)")
|
|
340
|
-
end
|
|
341
|
-
|
|
342
|
-
it "should support removing many_to_many objects" do
|
|
343
|
-
a = @Album.load(:id=>10, :name=>'Al')
|
|
344
|
-
t = @Tag.load(:id=>20, :name=>'T')
|
|
345
|
-
a.associations[:tags] = [t]
|
|
346
|
-
a.set(:tags_attributes=>[{:id=>20, :_remove=>true}])
|
|
347
|
-
a.associations[:tags].must_equal []
|
|
348
|
-
@db.sqls.must_equal []
|
|
349
|
-
a.save
|
|
350
|
-
@db.sqls.must_equal ["DELETE FROM at WHERE ((album_id = 10) AND (tag_id = 20))", "UPDATE albums SET name = 'Al' WHERE (id = 10)"]
|
|
351
|
-
end
|
|
352
|
-
|
|
353
|
-
it "should support removing objects with composite primary keys" do
|
|
354
|
-
ar = @Artist.load(:id=>10, :name=>'Ar')
|
|
355
|
-
co = @Concert.load(:tour=>'To', :date=>'2004-04-05', :playlist=>'Pl')
|
|
356
|
-
ar.associations[:concerts] = [co]
|
|
357
|
-
ar.set(:concerts_attributes=>[{:tour=>'To', :date=>'2004-04-05', :_remove=>'t'}])
|
|
358
|
-
@db.sqls.must_equal []
|
|
359
|
-
@Concert.dataset = @Concert.dataset.with_fetch(:id=>1)
|
|
360
|
-
ar.save
|
|
361
|
-
check_sql_array(["SELECT 1 AS one FROM concerts WHERE ((concerts.artist_id = 10) AND (tour = 'To') AND (date = '2004-04-05')) LIMIT 1", "SELECT 1 AS one FROM concerts WHERE ((concerts.artist_id = 10) AND (date = '2004-04-05') AND (tour = 'To')) LIMIT 1"],
|
|
362
|
-
["UPDATE concerts SET artist_id = NULL, playlist = 'Pl' WHERE ((tour = 'To') AND (date = '2004-04-05'))", "UPDATE concerts SET playlist = 'Pl', artist_id = NULL WHERE ((tour = 'To') AND (date = '2004-04-05'))", "UPDATE concerts SET artist_id = NULL, playlist = 'Pl' WHERE ((date = '2004-04-05') AND (tour = 'To'))", "UPDATE concerts SET playlist = 'Pl', artist_id = NULL WHERE ((date = '2004-04-05') AND (tour = 'To'))"],
|
|
363
|
-
"UPDATE artists SET name = 'Ar' WHERE (id = 10)")
|
|
364
|
-
end
|
|
365
|
-
|
|
366
|
-
it "should support destroying many_to_one objects" do
|
|
367
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
368
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
369
|
-
al.associations[:artist] = ar
|
|
370
|
-
al.set(:artist_attributes=>{:id=>'20', :_delete=>'1'})
|
|
371
|
-
@db.sqls.must_equal []
|
|
372
|
-
al.save
|
|
373
|
-
check_sql_array(["UPDATE albums SET artist_id = NULL, name = 'Al' WHERE (id = 10)", "UPDATE albums SET name = 'Al', artist_id = NULL WHERE (id = 10)"],
|
|
374
|
-
"DELETE FROM artists WHERE (id = 20)")
|
|
375
|
-
end
|
|
376
|
-
|
|
377
|
-
it "should support destroying one_to_one objects" do
|
|
378
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
379
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
380
|
-
ar.associations[:first_album] = al
|
|
381
|
-
ar.set(:first_album_attributes=>{:id=>10, :_delete=>'t'})
|
|
382
|
-
@db.sqls.must_equal []
|
|
383
|
-
ar.save
|
|
384
|
-
@db.sqls.must_equal ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "DELETE FROM albums WHERE (id = 10)"]
|
|
385
|
-
end
|
|
386
|
-
|
|
387
|
-
it "should support destroying one_to_many objects" do
|
|
388
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
389
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
390
|
-
ar.associations[:albums] = [al]
|
|
391
|
-
ar.set(:albums_attributes=>[{:id=>10, :_delete=>'t'}])
|
|
392
|
-
@db.sqls.must_equal []
|
|
393
|
-
ar.save
|
|
394
|
-
@db.sqls.must_equal ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "DELETE FROM albums WHERE (id = 10)"]
|
|
395
|
-
end
|
|
396
|
-
|
|
397
|
-
it "should support destroying many_to_many objects" do
|
|
398
|
-
a = @Album.load(:id=>10, :name=>'Al')
|
|
399
|
-
t = @Tag.load(:id=>20, :name=>'T')
|
|
400
|
-
a.associations[:tags] = [t]
|
|
401
|
-
a.set(:tags_attributes=>[{:id=>20, :_delete=>true}])
|
|
402
|
-
@db.sqls.must_equal []
|
|
403
|
-
a.save
|
|
404
|
-
@db.sqls.must_equal ["DELETE FROM at WHERE ((album_id = 10) AND (tag_id = 20))", "UPDATE albums SET name = 'Al' WHERE (id = 10)", "DELETE FROM tags WHERE (id = 20)"]
|
|
405
|
-
end
|
|
406
|
-
|
|
407
|
-
it "should support destroying objects with composite primary keys" do
|
|
408
|
-
ar = @Artist.load(:id=>10, :name=>'Ar')
|
|
409
|
-
co = @Concert.load(:tour=>'To', :date=>'2004-04-05', :playlist=>'Pl')
|
|
410
|
-
ar.associations[:concerts] = [co]
|
|
411
|
-
ar.set(:concerts_attributes=>[{:tour=>'To', :date=>'2004-04-05', :_delete=>'t'}])
|
|
412
|
-
@db.sqls.must_equal []
|
|
413
|
-
ar.save
|
|
414
|
-
check_sql_array("UPDATE artists SET name = 'Ar' WHERE (id = 10)", ["DELETE FROM concerts WHERE ((tour = 'To') AND (date = '2004-04-05'))", "DELETE FROM concerts WHERE ((date = '2004-04-05') AND (tour = 'To'))"])
|
|
415
|
-
end
|
|
416
|
-
|
|
417
|
-
it "should support both string and symbol keys in nested attribute hashes" do
|
|
418
|
-
a = @Album.load(:id=>10, :name=>'Al')
|
|
419
|
-
t = @Tag.load(:id=>20, :name=>'T')
|
|
420
|
-
a.associations[:tags] = [t]
|
|
421
|
-
a.set('tags_attributes'=>[{'id'=>20, '_delete'=>true}])
|
|
422
|
-
@db.sqls.must_equal []
|
|
423
|
-
a.save
|
|
424
|
-
@db.sqls.must_equal ["DELETE FROM at WHERE ((album_id = 10) AND (tag_id = 20))", "UPDATE albums SET name = 'Al' WHERE (id = 10)", "DELETE FROM tags WHERE (id = 20)"]
|
|
425
|
-
end
|
|
426
|
-
|
|
427
|
-
it "should support using a hash instead of an array for to_many nested attributes" do
|
|
428
|
-
a = @Album.load(:id=>10, :name=>'Al')
|
|
429
|
-
t = @Tag.load(:id=>20, :name=>'T')
|
|
430
|
-
a.associations[:tags] = [t]
|
|
431
|
-
a.set('tags_attributes'=>{'1'=>{'id'=>20, '_delete'=>true}})
|
|
432
|
-
@db.sqls.must_equal []
|
|
433
|
-
a.save
|
|
434
|
-
@db.sqls.must_equal ["DELETE FROM at WHERE ((album_id = 10) AND (tag_id = 20))", "UPDATE albums SET name = 'Al' WHERE (id = 10)", "DELETE FROM tags WHERE (id = 20)"]
|
|
435
|
-
end
|
|
436
|
-
|
|
437
|
-
it "should only allow destroying associated objects if :destroy option is used in the nested_attributes call" do
|
|
438
|
-
a = @Album.load(:id=>10, :name=>'Al')
|
|
439
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
440
|
-
a.associations[:artist] = ar
|
|
441
|
-
@Album.nested_attributes :artist
|
|
442
|
-
proc{a.set(:artist_attributes=>{:id=>'20', :_delete=>'1'})}.must_raise(Sequel::MassAssignmentRestriction)
|
|
443
|
-
@Album.nested_attributes :artist, :destroy=>true
|
|
444
|
-
a.set(:artist_attributes=>{:id=>'20', :_delete=>'1'})
|
|
445
|
-
end
|
|
446
|
-
|
|
447
|
-
it "should only allow removing associated objects if :remove option is used in the nested_attributes call" do
|
|
448
|
-
a = @Album.load(:id=>10, :name=>'Al')
|
|
449
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
450
|
-
a.associations[:artist] = ar
|
|
451
|
-
@Album.nested_attributes :artist
|
|
452
|
-
proc{a.set(:artist_attributes=>{:id=>'20', :_remove=>'1'})}.must_raise(Sequel::MassAssignmentRestriction)
|
|
453
|
-
@Album.nested_attributes :artist, :remove=>true
|
|
454
|
-
a.set(:artist_attributes=>{:id=>'20', :_remove=>'1'})
|
|
455
|
-
end
|
|
456
|
-
|
|
457
|
-
it "should raise an Error if a primary key is given in a nested attribute hash, but no matching associated object exists" do
|
|
458
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
459
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
460
|
-
ar.associations[:albums] = [al]
|
|
461
|
-
proc{ar.set(:albums_attributes=>[{:id=>30, :_delete=>'t'}])}.must_raise(Sequel::Error)
|
|
462
|
-
ar.set(:albums_attributes=>[{:id=>10, :_delete=>'t'}])
|
|
463
|
-
end
|
|
464
|
-
|
|
465
|
-
it "should not raise an Error if an unmatched primary key is given, if the :unmatched_pk=>:ignore option is used" do
|
|
466
|
-
@Artist.nested_attributes :albums, :unmatched_pk=>:ignore
|
|
467
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
468
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
469
|
-
ar.associations[:albums] = [al]
|
|
470
|
-
ar.set(:albums_attributes=>[{:id=>30, :_delete=>'t'}])
|
|
471
|
-
@db.sqls.must_equal []
|
|
472
|
-
ar.save
|
|
473
|
-
@db.sqls.must_equal ["UPDATE artists SET name = 'Ar' WHERE (id = 20)"]
|
|
474
|
-
end
|
|
475
|
-
|
|
476
|
-
it "should raise an Error if a composite primary key is given in a nested attribute hash, but no matching associated object exists" do
|
|
477
|
-
ar = @Artist.load(:id=>10, :name=>'Ar')
|
|
478
|
-
co = @Concert.load(:tour=>'To', :date=>'2004-04-05', :playlist=>'Pl')
|
|
479
|
-
ar.associations[:concerts] = [co]
|
|
480
|
-
proc{ar.set(:concerts_attributes=>[{:tour=>'To', :date=>'2004-04-04', :_delete=>'t'}])}.must_raise(Sequel::Error)
|
|
481
|
-
ar.set(:concerts_attributes=>[{:tour=>'To', :date=>'2004-04-05', :_delete=>'t'}])
|
|
482
|
-
end
|
|
483
|
-
|
|
484
|
-
it "should not raise an Error if an unmatched composite primary key is given, if the :unmatched_pk=>:ignore option is used" do
|
|
485
|
-
@Artist.nested_attributes :concerts, :unmatched_pk=>:ignore
|
|
486
|
-
ar = @Artist.load(:id=>10, :name=>'Ar')
|
|
487
|
-
co = @Concert.load(:tour=>'To', :date=>'2004-04-05', :playlist=>'Pl')
|
|
488
|
-
ar.associations[:concerts] = [co]
|
|
489
|
-
ar.set(:concerts_attributes=>[{:tour=>'To', :date=>'2004-04-06', :_delete=>'t'}])
|
|
490
|
-
@db.sqls.must_equal []
|
|
491
|
-
ar.save
|
|
492
|
-
@db.sqls.must_equal ["UPDATE artists SET name = 'Ar' WHERE (id = 10)"]
|
|
493
|
-
end
|
|
494
|
-
|
|
495
|
-
it "should raise a NoExistingObject error if object to be updated no longer exists, if the :require_modification=>true option is used" do
|
|
496
|
-
@Artist.nested_attributes :albums, :require_modification=>true, :destroy=>true
|
|
497
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
498
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
499
|
-
ar.associations[:albums] = [al]
|
|
500
|
-
ar.set(:albums_attributes=>[{:id=>10, :name=>'L'}])
|
|
501
|
-
@db.sqls.must_equal []
|
|
502
|
-
@db.numrows = [1, 0]
|
|
503
|
-
proc{ar.save}.must_raise Sequel::NoExistingObject
|
|
504
|
-
@db.sqls.must_equal ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "UPDATE albums SET name = 'L' WHERE (id = 10)"]
|
|
505
|
-
end
|
|
506
|
-
|
|
507
|
-
it "should not raise an Error if object to be updated no longer exists, if the :require_modification=>false option is used" do
|
|
508
|
-
@Artist.nested_attributes :albums, :require_modification=>false, :destroy=>true
|
|
509
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
510
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
511
|
-
ar.associations[:albums] = [al]
|
|
512
|
-
ar.set(:albums_attributes=>[{:id=>10, :name=>'L'}])
|
|
513
|
-
@db.sqls.must_equal []
|
|
514
|
-
@db.numrows = [1, 0]
|
|
515
|
-
ar.save
|
|
516
|
-
@db.sqls.must_equal ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "UPDATE albums SET name = 'L' WHERE (id = 10)"]
|
|
517
|
-
end
|
|
518
|
-
|
|
519
|
-
it "should raise a NoExistingObject error if object to be deleted no longer exists, if the :require_modification=>true option is used" do
|
|
520
|
-
@Artist.nested_attributes :albums, :require_modification=>true, :destroy=>true
|
|
521
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
522
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
523
|
-
ar.associations[:albums] = [al]
|
|
524
|
-
ar.set(:albums_attributes=>[{:id=>10, :_delete=>'t'}])
|
|
525
|
-
@db.sqls.must_equal []
|
|
526
|
-
@db.numrows = [1, 0]
|
|
527
|
-
proc{ar.save}.must_raise Sequel::NoExistingObject
|
|
528
|
-
@db.sqls.must_equal ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "DELETE FROM albums WHERE (id = 10)"]
|
|
529
|
-
end
|
|
530
|
-
|
|
531
|
-
it "should not raise an Error if object to be deleted no longer exists, if the :require_modification=>false option is used" do
|
|
532
|
-
@Artist.nested_attributes :albums, :require_modification=>false, :destroy=>true
|
|
533
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
534
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
535
|
-
ar.associations[:albums] = [al]
|
|
536
|
-
ar.set(:albums_attributes=>[{:id=>10, :_delete=>'t'}])
|
|
537
|
-
@db.sqls.must_equal []
|
|
538
|
-
@db.numrows = [1, 0]
|
|
539
|
-
ar.save
|
|
540
|
-
@db.sqls.must_equal ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "DELETE FROM albums WHERE (id = 10)"]
|
|
541
|
-
end
|
|
542
|
-
|
|
543
|
-
it "should not attempt to validate nested attributes twice for one_to_many associations when creating them" do
|
|
544
|
-
@Artist.nested_attributes :albums
|
|
545
|
-
validated = []
|
|
546
|
-
@Album.class_eval do
|
|
547
|
-
define_method(:validate) do
|
|
548
|
-
super()
|
|
549
|
-
validated << self
|
|
550
|
-
end
|
|
551
|
-
end
|
|
552
|
-
a = @Artist.new(:name=>'Ar', :albums_attributes=>[{:name=>'Al'}])
|
|
553
|
-
@db.sqls.must_equal []
|
|
554
|
-
validated.length.must_equal 0
|
|
555
|
-
a.save
|
|
556
|
-
validated.length.must_equal 1
|
|
557
|
-
check_sql_array("INSERT INTO artists (name) VALUES ('Ar')",
|
|
558
|
-
["INSERT INTO albums (artist_id, name) VALUES (1, 'Al')", "INSERT INTO albums (name, artist_id) VALUES ('Al', 1)"])
|
|
559
|
-
end
|
|
560
|
-
|
|
561
|
-
it "should not attempt to validate nested attributes twice for one_to_one associations when creating them" do
|
|
562
|
-
@Artist.nested_attributes :first_album
|
|
563
|
-
validated = []
|
|
564
|
-
@Album.class_eval do
|
|
565
|
-
define_method(:validate) do
|
|
566
|
-
super()
|
|
567
|
-
validated << self
|
|
568
|
-
end
|
|
569
|
-
end
|
|
570
|
-
a = @Artist.new(:name=>'Ar', :first_album_attributes=>{:name=>'Al'})
|
|
571
|
-
@db.sqls.must_equal []
|
|
572
|
-
validated.length.must_equal 0
|
|
573
|
-
a.save
|
|
574
|
-
validated.length.must_equal 1
|
|
575
|
-
check_sql_array("INSERT INTO artists (name) VALUES ('Ar')",
|
|
576
|
-
"UPDATE albums SET artist_id = NULL WHERE (artist_id = 1)",
|
|
577
|
-
"INSERT INTO albums (name, artist_id) VALUES ('Al', 1)")
|
|
578
|
-
end
|
|
579
|
-
|
|
580
|
-
it "should not clear reciprocal association before saving new one_to_one associated object" do
|
|
581
|
-
@Artist.one_to_one :first_album, :clone=>:first_album, :reciprocal=>:artist
|
|
582
|
-
@Artist.nested_attributes :first_album
|
|
583
|
-
assoc = []
|
|
584
|
-
@Album.class_eval do
|
|
585
|
-
define_method(:after_save) do
|
|
586
|
-
super()
|
|
587
|
-
assoc << associations[:artist]
|
|
588
|
-
end
|
|
589
|
-
end
|
|
590
|
-
a = @Artist.new(:name=>'Ar', :first_album_attributes=>{:name=>'Al'})
|
|
591
|
-
@db.sqls.must_equal []
|
|
592
|
-
assoc.must_be_empty
|
|
593
|
-
a.save
|
|
594
|
-
assoc.length.must_equal 1
|
|
595
|
-
assoc.first.must_be_kind_of(@Artist)
|
|
596
|
-
check_sql_array("INSERT INTO artists (name) VALUES ('Ar')",
|
|
597
|
-
"UPDATE albums SET artist_id = NULL WHERE (artist_id = 1)",
|
|
598
|
-
"INSERT INTO albums (name, artist_id) VALUES ('Al', 1)")
|
|
599
|
-
end
|
|
600
|
-
|
|
601
|
-
it "should not save if nested attribute is not valid and should include nested attribute validation errors in the main object's validation errors" do
|
|
602
|
-
@Artist.class_eval do
|
|
603
|
-
def validate
|
|
604
|
-
super
|
|
605
|
-
errors.add(:name, 'cannot be Ar') if name == 'Ar'
|
|
606
|
-
end
|
|
607
|
-
end
|
|
608
|
-
a = @Album.new(:name=>'Al', :artist_attributes=>{:name=>'Ar'})
|
|
609
|
-
@db.sqls.must_equal []
|
|
610
|
-
proc{a.save}.must_raise(Sequel::ValidationFailed)
|
|
611
|
-
a.errors.full_messages.must_equal ['artist name cannot be Ar']
|
|
612
|
-
@db.sqls.must_equal []
|
|
613
|
-
# Should preserve attributes
|
|
614
|
-
a.artist.name.must_equal 'Ar'
|
|
615
|
-
end
|
|
616
|
-
|
|
617
|
-
it "should not attempt to validate nested attributes if the :validate=>false association option is used" do
|
|
618
|
-
@Album.many_to_one :artist, :class=>@Artist, :validate=>false, :reciprocal=>nil
|
|
619
|
-
@Album.nested_attributes :artist, :tags, :destroy=>true, :remove=>true
|
|
620
|
-
@Artist.class_eval do
|
|
621
|
-
def validate
|
|
622
|
-
super
|
|
623
|
-
errors.add(:name, 'cannot be Ar') if name == 'Ar'
|
|
624
|
-
end
|
|
625
|
-
end
|
|
626
|
-
a = @Album.new(:name=>'Al', :artist_attributes=>{:name=>'Ar'})
|
|
627
|
-
@db.sqls.must_equal []
|
|
628
|
-
a.save
|
|
629
|
-
check_sql_array("INSERT INTO artists (name) VALUES ('Ar')",
|
|
630
|
-
["INSERT INTO albums (artist_id, name) VALUES (1, 'Al')", "INSERT INTO albums (name, artist_id) VALUES ('Al', 1)"])
|
|
631
|
-
end
|
|
632
|
-
|
|
633
|
-
it "should not attempt to validate nested attributes if the :validate=>false option is passed to save" do
|
|
634
|
-
@Artist.class_eval do
|
|
635
|
-
def validate
|
|
636
|
-
super
|
|
637
|
-
errors.add(:name, 'cannot be Ar') if name == 'Ar'
|
|
638
|
-
end
|
|
639
|
-
end
|
|
640
|
-
a = @Album.new(:name=>'Al', :artist_attributes=>{:name=>'Ar'})
|
|
641
|
-
@db.sqls.must_equal []
|
|
642
|
-
a.save(:validate=>false)
|
|
643
|
-
check_sql_array("INSERT INTO artists (name) VALUES ('Ar')",
|
|
644
|
-
["INSERT INTO albums (artist_id, name) VALUES (1, 'Al')", "INSERT INTO albums (name, artist_id) VALUES ('Al', 1)"])
|
|
645
|
-
end
|
|
646
|
-
|
|
647
|
-
it "should not accept nested attributes unless explicitly specified" do
|
|
648
|
-
@Artist.many_to_many :tags, :class=>@Tag, :left_key=>:album_id, :right_key=>:tag_id, :join_table=>:at
|
|
649
|
-
proc{@Artist.create({:name=>'Ar', :tags_attributes=>[{:name=>'T'}]})}.must_raise(Sequel::MassAssignmentRestriction)
|
|
650
|
-
@db.sqls.must_equal []
|
|
651
|
-
end
|
|
652
|
-
|
|
653
|
-
it "should save when save_changes or update is called if nested attribute associated objects changed but there are no changes to the main object" do
|
|
654
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
655
|
-
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
656
|
-
al.associations[:artist] = ar
|
|
657
|
-
@db.sqls.must_equal []
|
|
658
|
-
al.update(:artist_attributes=>{:id=>'20', :name=>'Ar2'})
|
|
659
|
-
@db.sqls.must_equal ["UPDATE artists SET name = 'Ar2' WHERE (id = 20)"]
|
|
660
|
-
end
|
|
661
|
-
|
|
662
|
-
it "should have a :limit option limiting the amount of entries" do
|
|
663
|
-
@Album.nested_attributes :tags, :limit=>2
|
|
664
|
-
arr = [{:name=>'T'}]
|
|
665
|
-
proc{@Album.new({:name=>'Al', :tags_attributes=>arr*3})}.must_raise(Sequel::Error)
|
|
666
|
-
a = @Album.new({:name=>'Al', :tags_attributes=>arr*2})
|
|
667
|
-
@db.sqls.must_equal []
|
|
668
|
-
a.save
|
|
669
|
-
check_sql_array("INSERT INTO albums (name) VALUES ('Al')",
|
|
670
|
-
"INSERT INTO tags (name) VALUES ('T')",
|
|
671
|
-
["INSERT INTO at (album_id, tag_id) VALUES (1, 2)", "INSERT INTO at (tag_id, album_id) VALUES (2, 1)"],
|
|
672
|
-
"INSERT INTO tags (name) VALUES ('T')",
|
|
673
|
-
["INSERT INTO at (album_id, tag_id) VALUES (1, 4)", "INSERT INTO at (tag_id, album_id) VALUES (4, 1)"])
|
|
674
|
-
end
|
|
675
|
-
|
|
676
|
-
it "should accept a block that each hash gets passed to determine if it should be processed" do
|
|
677
|
-
@Album.nested_attributes(:tags){|h| h[:name].empty?}
|
|
678
|
-
a = @Album.new({:name=>'Al', :tags_attributes=>[{:name=>'T'}, {:name=>''}, {:name=>'T2'}]})
|
|
679
|
-
@db.sqls.must_equal []
|
|
680
|
-
a.save
|
|
681
|
-
check_sql_array("INSERT INTO albums (name) VALUES ('Al')",
|
|
682
|
-
"INSERT INTO tags (name) VALUES ('T')",
|
|
683
|
-
["INSERT INTO at (album_id, tag_id) VALUES (1, 2)", "INSERT INTO at (tag_id, album_id) VALUES (2, 1)"],
|
|
684
|
-
"INSERT INTO tags (name) VALUES ('T2')",
|
|
685
|
-
["INSERT INTO at (album_id, tag_id) VALUES (1, 4)", "INSERT INTO at (tag_id, album_id) VALUES (4, 1)"])
|
|
686
|
-
end
|
|
687
|
-
|
|
688
|
-
it "should accept a :transform block that returns a changed attributes hash" do
|
|
689
|
-
@Album.nested_attributes :tags, :transform=>proc{|parent, hash| hash[:name] << parent.name; hash }
|
|
690
|
-
a = @Album.new(:name => 'Al')
|
|
691
|
-
a.set(:tags_attributes=>[{:name=>'T'.dup}, {:name=>'T2'.dup}])
|
|
692
|
-
@db.sqls.must_equal []
|
|
693
|
-
a.save
|
|
694
|
-
check_sql_array("INSERT INTO albums (name) VALUES ('Al')",
|
|
695
|
-
"INSERT INTO tags (name) VALUES ('TAl')",
|
|
696
|
-
["INSERT INTO at (album_id, tag_id) VALUES (1, 2)", "INSERT INTO at (tag_id, album_id) VALUES (2, 1)"],
|
|
697
|
-
"INSERT INTO tags (name) VALUES ('T2Al')",
|
|
698
|
-
["INSERT INTO at (album_id, tag_id) VALUES (1, 4)", "INSERT INTO at (tag_id, album_id) VALUES (4, 1)"])
|
|
699
|
-
end
|
|
700
|
-
|
|
701
|
-
it "should return objects created/modified in the internal methods" do
|
|
702
|
-
@Album.nested_attributes :tags, :remove=>true, :unmatched_pk=>:ignore
|
|
703
|
-
objs = []
|
|
704
|
-
@Album.class_eval do
|
|
705
|
-
define_method(:nested_attributes_create){|*a| objs << [super(*a), :create]}
|
|
706
|
-
define_method(:nested_attributes_remove){|*a| objs << [super(*a), :remove]}
|
|
707
|
-
define_method(:nested_attributes_update){|*a| objs << [super(*a), :update]}
|
|
708
|
-
end
|
|
709
|
-
a = @Album.new(:name=>'Al')
|
|
710
|
-
a.associations[:tags] = [@Tag.load(:id=>6, :name=>'A'), @Tag.load(:id=>7, :name=>'A2')]
|
|
711
|
-
a.tags_attributes = [{:id=>6, :name=>'T'}, {:id=>7, :name=>'T2', :_remove=>true}, {:name=>'T3'}, {:id=>8, :name=>'T4'}, {:id=>9, :name=>'T5', :_remove=>true}]
|
|
712
|
-
objs.must_equal [[@Tag.load(:id=>6, :name=>'T'), :update], [@Tag.load(:id=>7, :name=>'A2'), :remove], [@Tag.new(:name=>'T3'), :create]]
|
|
713
|
-
end
|
|
714
|
-
|
|
715
|
-
it "should raise an error if updating modifies the associated objects keys" do
|
|
716
|
-
@Artist.columns :id, :name, :artist_id
|
|
717
|
-
@Album.columns :id, :name, :artist_id
|
|
718
|
-
@Tag.columns :id, :name, :tag_id
|
|
719
|
-
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id, :primary_key=>:artist_id
|
|
720
|
-
@Album.many_to_one :artist, :class=>@Artist, :primary_key=>:artist_id
|
|
721
|
-
@Album.many_to_many :tags, :class=>@Tag, :left_key=>:album_id, :right_key=>:tag_id, :join_table=>:at, :right_primary_key=>:tag_id
|
|
722
|
-
@Artist.nested_attributes :albums, :destroy=>true, :remove=>true
|
|
723
|
-
@Album.nested_attributes :artist, :tags, :destroy=>true, :remove=>true
|
|
724
|
-
|
|
725
|
-
al = @Album.load(:id=>10, :name=>'Al', :artist_id=>25)
|
|
726
|
-
ar = @Artist.load(:id=>20, :name=>'Ar', :artist_id=>25)
|
|
727
|
-
t = @Tag.load(:id=>30, :name=>'T', :tag_id=>15)
|
|
728
|
-
al.associations[:artist] = ar
|
|
729
|
-
al.associations[:tags] = [t]
|
|
730
|
-
ar.associations[:albums] = [al]
|
|
731
|
-
proc{ar.set(:albums_attributes=>[{:id=>10, :name=>'Al2', :artist_id=>'3'}])}.must_raise(Sequel::Error)
|
|
732
|
-
proc{al.set(:artist_attributes=>{:id=>20, :name=>'Ar2', :artist_id=>'3'})}.must_raise(Sequel::Error)
|
|
733
|
-
proc{al.set(:tags_attributes=>[{:id=>30, :name=>'T2', :tag_id=>'3'}])}.must_raise(Sequel::Error)
|
|
734
|
-
end
|
|
735
|
-
|
|
736
|
-
it "should accept a :fields option and only allow modification of those fields" do
|
|
737
|
-
@Tag.columns :id, :name, :number
|
|
738
|
-
@Album.nested_attributes :tags, :destroy=>true, :remove=>true, :fields=>[:name]
|
|
739
|
-
|
|
740
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
741
|
-
t = @Tag.load(:id=>30, :name=>'T', :number=>10)
|
|
742
|
-
al.associations[:tags] = [t]
|
|
743
|
-
al.set(:tags_attributes=>[{:id=>30, :name=>'T2'}, {:name=>'T3'}])
|
|
744
|
-
@db.sqls.must_equal []
|
|
745
|
-
al.save
|
|
746
|
-
check_sql_array("UPDATE albums SET name = 'Al' WHERE (id = 10)",
|
|
747
|
-
"UPDATE tags SET name = 'T2' WHERE (id = 30)",
|
|
748
|
-
"INSERT INTO tags (name) VALUES ('T3')",
|
|
749
|
-
["INSERT INTO at (album_id, tag_id) VALUES (10, 1)", "INSERT INTO at (tag_id, album_id) VALUES (1, 10)"])
|
|
750
|
-
al.set(:tags_attributes=>[{:id=>30, :name=>'T3', :number=>3}])
|
|
751
|
-
al.tags.first.name.must_equal 'T3'
|
|
752
|
-
al.tags.first.number.must_equal 10
|
|
753
|
-
al.set(:tags_attributes=>[{:name=>'T4', :number=>3}])
|
|
754
|
-
al.tags.last.name.must_equal 'T4'
|
|
755
|
-
al.tags.last.number.must_be_nil
|
|
756
|
-
end
|
|
757
|
-
|
|
758
|
-
it "should accept a proc for the :fields option that accepts the associated object and returns an array of fields" do
|
|
759
|
-
@Tag.columns :id, :name, :number
|
|
760
|
-
@Album.nested_attributes :tags, :destroy=>true, :remove=>true, :fields=>proc{|object| object.is_a?(@Tag) ? [:name] : []}
|
|
761
|
-
|
|
762
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
763
|
-
t = @Tag.load(:id=>30, :name=>'T', :number=>10)
|
|
764
|
-
al.associations[:tags] = [t]
|
|
765
|
-
al.set(:tags_attributes=>[{:id=>30, :name=>'T2'}, {:name=>'T3'}])
|
|
766
|
-
@db.sqls.must_equal []
|
|
767
|
-
al.save
|
|
768
|
-
check_sql_array("UPDATE albums SET name = 'Al' WHERE (id = 10)",
|
|
769
|
-
"UPDATE tags SET name = 'T2' WHERE (id = 30)",
|
|
770
|
-
"INSERT INTO tags (name) VALUES ('T3')",
|
|
771
|
-
["INSERT INTO at (album_id, tag_id) VALUES (10, 1)", "INSERT INTO at (tag_id, album_id) VALUES (1, 10)"])
|
|
772
|
-
al.set_nested_attributes(:tags, [{:id=>30, :name=>'T3', :number=>3}], :fields=>[:name])
|
|
773
|
-
al.tags.first.name.must_equal 'T3'
|
|
774
|
-
al.tags.first.number.must_equal 10
|
|
775
|
-
al.set_nested_attributes(:tags, [{:name=>'T4', :number=>3}], :fields=>[:name])
|
|
776
|
-
al.tags.last.name.must_equal 'T4'
|
|
777
|
-
al.tags.last.number.must_be_nil
|
|
778
|
-
end
|
|
779
|
-
|
|
780
|
-
it "should allow per-call options via the set_nested_attributes method" do
|
|
781
|
-
@Tag.columns :id, :name, :number
|
|
782
|
-
@Album.nested_attributes :tags
|
|
783
|
-
|
|
784
|
-
al = @Album.load(:id=>10, :name=>'Al')
|
|
785
|
-
t = @Tag.load(:id=>30, :name=>'T', :number=>10)
|
|
786
|
-
al.associations[:tags] = [t]
|
|
787
|
-
al.set_nested_attributes(:tags, [{:id=>30, :name=>'T2'}, {:name=>'T3'}], :fields=>[:name])
|
|
788
|
-
@db.sqls.must_equal []
|
|
789
|
-
al.save
|
|
790
|
-
check_sql_array("UPDATE albums SET name = 'Al' WHERE (id = 10)",
|
|
791
|
-
"UPDATE tags SET name = 'T2' WHERE (id = 30)",
|
|
792
|
-
"INSERT INTO tags (name) VALUES ('T3')",
|
|
793
|
-
["INSERT INTO at (album_id, tag_id) VALUES (10, 1)", "INSERT INTO at (tag_id, album_id) VALUES (1, 10)"])
|
|
794
|
-
al.set_nested_attributes(:tags, [{:id=>30, :name=>'T3', :number=>3}], :fields=>[:name])
|
|
795
|
-
al.tags.first.name.must_equal 'T3'
|
|
796
|
-
al.tags.first.number.must_equal 10
|
|
797
|
-
al.set_nested_attributes(:tags, [{:name=>'T4', :number=>3}], :fields=>[:name])
|
|
798
|
-
al.tags.last.name.must_equal 'T4'
|
|
799
|
-
al.tags.last.number.must_be_nil
|
|
800
|
-
end
|
|
801
|
-
|
|
802
|
-
it "should have set_nested_attributes method raise error if called with a bad association" do
|
|
803
|
-
proc{@Album.load(:id=>10, :name=>'Al').set_nested_attributes(:tags2, [{:id=>30, :name=>'T2', :number=>3}], :fields=>[:name])}.must_raise(Sequel::Error)
|
|
804
|
-
end
|
|
805
|
-
|
|
806
|
-
it "should have set_nested_attributes method raise error if called with an association that doesn't support nested attributes" do
|
|
807
|
-
@Tag.columns :id, :name, :number
|
|
808
|
-
proc{@Album.load(:id=>10, :name=>'Al').set_nested_attributes(:tags, [{:id=>30, :name=>'T2', :number=>3}], :fields=>[:name])}.must_raise(Sequel::Error)
|
|
809
|
-
end
|
|
810
|
-
|
|
811
|
-
it "should not allow modifying ensted attributes after freezing" do
|
|
812
|
-
@Artist.freeze
|
|
813
|
-
proc{@Artist.nested_attributes :albums}.must_raise RuntimeError, TypeError
|
|
814
|
-
end
|
|
815
|
-
end
|