sequel 3.21.0 → 3.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +1131 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +106 -65
- data/Rakefile +59 -27
- data/bin/sequel +50 -26
- data/doc/active_record.rdoc +68 -52
- data/doc/advanced_associations.rdoc +201 -75
- data/doc/association_basics.rdoc +327 -79
- data/doc/bin_sequel.rdoc +144 -0
- data/doc/cheat_sheet.rdoc +21 -21
- data/doc/core_extensions.rdoc +374 -0
- data/doc/dataset_basics.rdoc +10 -10
- data/doc/dataset_filtering.rdoc +54 -42
- data/doc/mass_assignment.rdoc +56 -0
- data/doc/migration.rdoc +89 -557
- data/doc/model_hooks.rdoc +80 -29
- data/doc/object_model.rdoc +576 -0
- data/doc/opening_databases.rdoc +121 -53
- data/doc/prepared_statements.rdoc +41 -15
- data/doc/querying.rdoc +137 -56
- data/doc/reflection.rdoc +36 -10
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/release_notes/3.30.0.txt +135 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/doc/release_notes/3.32.0.txt +202 -0
- data/doc/release_notes/3.33.0.txt +157 -0
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/release_notes/3.35.0.txt +144 -0
- data/doc/release_notes/3.36.0.txt +245 -0
- data/doc/release_notes/3.37.0.txt +338 -0
- data/doc/release_notes/3.38.0.txt +234 -0
- data/doc/release_notes/3.39.0.txt +237 -0
- data/doc/release_notes/3.40.0.txt +73 -0
- data/doc/release_notes/3.41.0.txt +155 -0
- data/doc/schema_modification.rdoc +585 -0
- data/doc/sharding.rdoc +99 -8
- data/doc/sql.rdoc +154 -112
- data/doc/testing.rdoc +169 -0
- data/doc/thread_safety.rdoc +17 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +78 -43
- data/lib/sequel/adapters/ado/access.rb +334 -0
- data/lib/sequel/adapters/ado/mssql.rb +18 -12
- data/lib/sequel/adapters/ado.rb +69 -21
- data/lib/sequel/adapters/amalgalite.rb +17 -14
- data/lib/sequel/adapters/cubrid.rb +143 -0
- data/lib/sequel/adapters/db2.rb +178 -85
- data/lib/sequel/adapters/dbi.rb +19 -21
- data/lib/sequel/adapters/do/mysql.rb +17 -11
- data/lib/sequel/adapters/do/postgres.rb +2 -61
- data/lib/sequel/adapters/do/sqlite.rb +0 -10
- data/lib/sequel/adapters/do.rb +20 -39
- data/lib/sequel/adapters/firebird.rb +33 -210
- data/lib/sequel/adapters/ibmdb.rb +452 -0
- data/lib/sequel/adapters/informix.rb +6 -29
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/cubrid.rb +52 -0
- data/lib/sequel/adapters/jdbc/db2.rb +78 -0
- data/lib/sequel/adapters/jdbc/derby.rb +325 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
- data/lib/sequel/adapters/jdbc/h2.rb +68 -31
- data/lib/sequel/adapters/jdbc/hsqldb.rb +189 -0
- data/lib/sequel/adapters/jdbc/informix.rb +21 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +16 -28
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
- data/lib/sequel/adapters/jdbc/progress.rb +21 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
- data/lib/sequel/adapters/jdbc/sqlserver.rb +72 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +308 -114
- data/lib/sequel/adapters/mock.rb +372 -0
- data/lib/sequel/adapters/mysql.rb +130 -230
- data/lib/sequel/adapters/mysql2.rb +64 -63
- data/lib/sequel/adapters/odbc/mssql.rb +17 -9
- data/lib/sequel/adapters/odbc.rb +29 -10
- data/lib/sequel/adapters/openbase.rb +7 -11
- data/lib/sequel/adapters/oracle.rb +364 -57
- data/lib/sequel/adapters/postgres.rb +379 -145
- data/lib/sequel/adapters/shared/access.rb +236 -11
- data/lib/sequel/adapters/shared/cubrid.rb +216 -0
- data/lib/sequel/adapters/shared/db2.rb +353 -0
- data/lib/sequel/adapters/shared/firebird.rb +231 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +412 -116
- data/lib/sequel/adapters/shared/mysql.rb +396 -89
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +166 -0
- data/lib/sequel/adapters/shared/oracle.rb +262 -45
- data/lib/sequel/adapters/shared/postgres.rb +688 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +317 -96
- data/lib/sequel/adapters/sqlite.rb +109 -46
- data/lib/sequel/adapters/swift/mysql.rb +10 -12
- data/lib/sequel/adapters/swift/postgres.rb +13 -79
- data/lib/sequel/adapters/swift/sqlite.rb +9 -6
- data/lib/sequel/adapters/swift.rb +31 -27
- data/lib/sequel/adapters/tinytds.rb +177 -25
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
- data/lib/sequel/adapters/utils/pg_types.rb +81 -0
- data/lib/sequel/adapters/utils/split_alter_table.rb +36 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +194 -0
- data/lib/sequel/connection_pool/sharded_single.rb +23 -13
- data/lib/sequel/connection_pool/sharded_threaded.rb +64 -13
- data/lib/sequel/connection_pool/single.rb +11 -3
- data/lib/sequel/connection_pool/threaded.rb +69 -20
- data/lib/sequel/connection_pool.rb +20 -18
- data/lib/sequel/core.rb +143 -11
- data/lib/sequel/database/connecting.rb +66 -29
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +63 -2
- data/lib/sequel/database/logging.rb +7 -2
- data/lib/sequel/database/misc.rb +192 -51
- data/lib/sequel/database/query.rb +299 -114
- data/lib/sequel/database/schema_generator.rb +103 -36
- data/lib/sequel/database/schema_methods.rb +310 -69
- data/lib/sequel/dataset/actions.rb +344 -90
- data/lib/sequel/dataset/features.rb +101 -8
- data/lib/sequel/dataset/graph.rb +42 -15
- data/lib/sequel/dataset/misc.rb +52 -25
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +68 -30
- data/lib/sequel/dataset/query.rb +322 -68
- data/lib/sequel/dataset/sql.rb +716 -293
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/_pretty_table.rb +83 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
- data/lib/sequel/extensions/blank.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +72 -0
- data/lib/sequel/extensions/connection_validator.rb +109 -0
- data/lib/sequel/extensions/constraint_validations.rb +451 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
- data/lib/sequel/extensions/eval_inspect.rb +173 -0
- data/lib/sequel/extensions/inflector.rb +4 -0
- data/lib/sequel/extensions/looser_typecasting.rb +5 -4
- data/lib/sequel/extensions/migration.rb +100 -11
- data/lib/sequel/extensions/named_timezones.rb +9 -0
- data/lib/sequel/extensions/null_dataset.rb +94 -0
- data/lib/sequel/extensions/pagination.rb +4 -0
- data/lib/sequel/extensions/pg_array.rb +539 -0
- data/lib/sequel/extensions/pg_array_ops.rb +263 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
- data/lib/sequel/extensions/pg_hstore.rb +334 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
- data/lib/sequel/extensions/pg_inet.rb +113 -0
- data/lib/sequel/extensions/pg_interval.rb +191 -0
- data/lib/sequel/extensions/pg_json.rb +212 -0
- data/lib/sequel/extensions/pg_range.rb +513 -0
- data/lib/sequel/extensions/pg_range_ops.rb +150 -0
- data/lib/sequel/extensions/pg_row.rb +576 -0
- data/lib/sequel/extensions/pg_row_ops.rb +182 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
- data/lib/sequel/extensions/pretty_table.rb +17 -72
- data/lib/sequel/extensions/query.rb +8 -4
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +282 -76
- data/lib/sequel/extensions/select_remove.rb +39 -0
- data/lib/sequel/extensions/server_block.rb +140 -0
- data/lib/sequel/extensions/split_array_nil.rb +65 -0
- data/lib/sequel/extensions/sql_expr.rb +8 -110
- data/lib/sequel/extensions/string_date_time.rb +4 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
- data/lib/sequel/extensions/to_dot.rb +99 -83
- data/lib/sequel/model/associations.rb +1263 -409
- data/lib/sequel/model/base.rb +624 -171
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +24 -2
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model.rb +30 -11
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +137 -16
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +44 -12
- data/lib/sequel/plugins/constraint_validations.rb +198 -0
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +72 -0
- data/lib/sequel/plugins/dirty.rb +214 -0
- data/lib/sequel/plugins/eager_each.rb +59 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +134 -15
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +77 -6
- data/lib/sequel/plugins/list.rb +13 -2
- data/lib/sequel/plugins/many_through_many.rb +103 -51
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +150 -66
- data/lib/sequel/plugins/optimistic_locking.rb +8 -0
- data/lib/sequel/plugins/pg_row.rb +121 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
- data/lib/sequel/plugins/prepared_statements.rb +168 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +31 -17
- data/lib/sequel/plugins/schema.rb +8 -3
- data/lib/sequel/plugins/serialization.rb +98 -49
- data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- data/lib/sequel/plugins/single_table_inheritance.rb +57 -12
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/subclasses.rb +29 -3
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/touch.rb +18 -6
- data/lib/sequel/plugins/tree.rb +3 -3
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +2 -1
- data/lib/sequel/plugins/validation_helpers.rb +57 -4
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +721 -141
- data/lib/sequel/timezones.rb +67 -40
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/firebird_spec.rb +53 -39
- data/spec/adapters/mssql_spec.rb +261 -66
- data/spec/adapters/mysql_spec.rb +597 -352
- data/spec/adapters/oracle_spec.rb +92 -117
- data/spec/adapters/postgres_spec.rb +2103 -341
- data/spec/adapters/spec_helper.rb +16 -6
- data/spec/adapters/sqlite_spec.rb +237 -76
- data/spec/core/connection_pool_spec.rb +270 -141
- data/spec/core/database_spec.rb +980 -524
- data/spec/core/dataset_spec.rb +1658 -1243
- data/spec/core/expression_filters_spec.rb +741 -334
- data/spec/core/mock_adapter_spec.rb +453 -0
- data/spec/core/object_graph_spec.rb +88 -129
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +556 -53
- data/spec/core/spec_helper.rb +7 -48
- data/spec/core_extensions_spec.rb +626 -0
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/arbitrary_servers_spec.rb +110 -0
- data/spec/extensions/association_autoreloading_spec.rb +18 -10
- data/spec/extensions/association_dependencies_spec.rb +15 -25
- data/spec/extensions/association_pks_spec.rb +227 -33
- data/spec/extensions/association_proxies_spec.rb +4 -4
- data/spec/extensions/boolean_readers_spec.rb +25 -25
- data/spec/extensions/caching_spec.rb +47 -51
- data/spec/extensions/class_table_inheritance_spec.rb +31 -83
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/connection_validator_spec.rb +118 -0
- data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
- data/spec/extensions/constraint_validations_spec.rb +316 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +88 -0
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/eval_inspect_spec.rb +67 -0
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +97 -128
- data/spec/extensions/identity_map_spec.rb +142 -24
- data/spec/extensions/inflector_spec.rb +0 -4
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +72 -0
- data/spec/extensions/json_serializer_spec.rb +49 -12
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +49 -40
- data/spec/extensions/looser_typecasting_spec.rb +7 -7
- data/spec/extensions/many_through_many_spec.rb +368 -254
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +140 -35
- data/spec/extensions/named_timezones_spec.rb +29 -11
- data/spec/extensions/nested_attributes_spec.rb +268 -89
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +24 -21
- data/spec/extensions/pg_array_ops_spec.rb +112 -0
- data/spec/extensions/pg_array_spec.rb +324 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
- data/spec/extensions/pg_hstore_spec.rb +200 -0
- data/spec/extensions/pg_inet_spec.rb +47 -0
- data/spec/extensions/pg_interval_spec.rb +72 -0
- data/spec/extensions/pg_json_spec.rb +99 -0
- data/spec/extensions/pg_range_ops_spec.rb +56 -0
- data/spec/extensions/pg_range_spec.rb +395 -0
- data/spec/extensions/pg_row_ops_spec.rb +58 -0
- data/spec/extensions/pg_row_plugin_spec.rb +49 -0
- data/spec/extensions/pg_row_spec.rb +340 -0
- data/spec/extensions/pg_statement_cache_spec.rb +208 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
- data/spec/extensions/prepared_statements_spec.rb +87 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +7 -6
- data/spec/extensions/query_literals_spec.rb +167 -0
- data/spec/extensions/query_spec.rb +9 -3
- data/spec/extensions/rcte_tree_spec.rb +50 -43
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +434 -49
- data/spec/extensions/schema_spec.rb +30 -49
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +86 -48
- data/spec/extensions/server_block_spec.rb +90 -0
- data/spec/extensions/sharding_spec.rb +69 -143
- data/spec/extensions/single_table_inheritance_spec.rb +65 -29
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +34 -67
- data/spec/extensions/split_array_nil_spec.rb +24 -0
- data/spec/extensions/sql_expr_spec.rb +29 -60
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/subclasses_spec.rb +14 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +8 -11
- data/spec/extensions/touch_spec.rb +53 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +9 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +77 -68
- data/spec/extensions/validation_helpers_spec.rb +48 -37
- data/spec/extensions/xml_serializer_spec.rb +29 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
- data/spec/integration/associations_test.rb +659 -21
- data/spec/integration/database_test.rb +25 -5
- data/spec/integration/dataset_test.rb +729 -141
- data/spec/integration/eager_loader_test.rb +38 -54
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +81 -2
- data/spec/integration/plugin_test.rb +871 -160
- data/spec/integration/prepared_statement_test.rb +272 -128
- data/spec/integration/schema_test.rb +377 -57
- data/spec/integration/spec_helper.rb +49 -32
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +40 -8
- data/spec/model/association_reflection_spec.rb +207 -8
- data/spec/model/associations_spec.rb +1206 -693
- data/spec/model/base_spec.rb +334 -100
- data/spec/model/dataset_methods_spec.rb +45 -27
- data/spec/model/eager_loading_spec.rb +828 -692
- data/spec/model/hooks_spec.rb +355 -67
- data/spec/model/model_spec.rb +251 -179
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +506 -232
- data/spec/model/spec_helper.rb +16 -77
- data/spec/model/validations_spec.rb +38 -2
- data/spec/rcov.opts +2 -0
- metadata +223 -81
- data/spec/core/core_sql_spec.rb +0 -451
|
@@ -1,85 +1,83 @@
|
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
2
|
|
|
3
3
|
describe "NestedAttributes plugin" do
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
ds_mod = Module.new do
|
|
10
|
-
def empty?; false; end
|
|
11
|
-
define_method(:insert) do |h|
|
|
12
|
-
x = ii.call
|
|
13
|
-
mods << [:i, first_source, h, x]
|
|
14
|
-
x
|
|
15
|
-
end
|
|
16
|
-
define_method(:insert_select) do |h|
|
|
17
|
-
x = ii.call
|
|
18
|
-
mods << [:is, first_source, h, x]
|
|
19
|
-
h.merge(:id=>x)
|
|
20
|
-
end
|
|
21
|
-
define_method(:update) do |h|
|
|
22
|
-
mods << [:u, first_source, h, literal(opts[:where])]
|
|
23
|
-
1
|
|
24
|
-
end
|
|
25
|
-
define_method(:delete) do
|
|
26
|
-
mods << [:d, first_source, literal(opts[:where])]
|
|
27
|
-
1
|
|
28
|
-
end
|
|
4
|
+
def check_sqls(should, is)
|
|
5
|
+
if should.is_a?(Array)
|
|
6
|
+
should.should include(is)
|
|
7
|
+
else
|
|
8
|
+
should.should == is
|
|
29
9
|
end
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def check_sql_array(*shoulds)
|
|
13
|
+
sqls = @db.sqls
|
|
14
|
+
sqls.length.should == 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))
|
|
37
21
|
@c.plugin :nested_attributes
|
|
38
22
|
@Artist = Class.new(@c).set_dataset(:artists)
|
|
39
23
|
@Album = Class.new(@c).set_dataset(:albums)
|
|
40
24
|
@Tag = Class.new(@c).set_dataset(:tags)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
|
44
30
|
@Artist.columns :id, :name
|
|
45
31
|
@Album.columns :id, :name, :artist_id
|
|
46
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
|
|
47
36
|
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id
|
|
37
|
+
@Artist.one_to_many :concerts, :class=>@Concert, :key=>:artist_id
|
|
48
38
|
@Artist.one_to_one :first_album, :class=>@Album, :key=>:artist_id
|
|
49
39
|
@Album.many_to_one :artist, :class=>@Artist
|
|
50
40
|
@Album.many_to_many :tags, :class=>@Tag, :left_key=>:album_id, :right_key=>:tag_id, :join_table=>:at
|
|
51
41
|
@Artist.nested_attributes :albums, :first_album, :destroy=>true, :remove=>true
|
|
42
|
+
@Artist.nested_attributes :concerts, :destroy=>true, :remove=>true
|
|
52
43
|
@Album.nested_attributes :artist, :tags, :destroy=>true, :remove=>true
|
|
44
|
+
@db.sqls
|
|
53
45
|
end
|
|
54
46
|
|
|
55
47
|
it "should support creating new many_to_one objects" do
|
|
56
48
|
a = @Album.new({:name=>'Al', :artist_attributes=>{:name=>'Ar'}})
|
|
57
|
-
@
|
|
49
|
+
@db.sqls.should == []
|
|
58
50
|
a.save
|
|
59
|
-
|
|
51
|
+
check_sql_array("INSERT INTO artists (name) VALUES ('Ar')",
|
|
52
|
+
["INSERT INTO albums (name, artist_id) VALUES ('Al', 1)", "INSERT INTO albums (artist_id, name) VALUES (1, 'Al')"])
|
|
60
53
|
end
|
|
61
54
|
|
|
62
55
|
it "should support creating new one_to_one objects" do
|
|
63
56
|
a = @Artist.new(:name=>'Ar')
|
|
64
57
|
a.id = 1
|
|
65
58
|
a.first_album_attributes = {:name=>'Al'}
|
|
66
|
-
@
|
|
59
|
+
@db.sqls.should == []
|
|
67
60
|
a.save
|
|
68
|
-
|
|
61
|
+
check_sql_array(["INSERT INTO artists (name, id) VALUES ('Ar', 1)", "INSERT INTO artists (id, name) VALUES (1, 'Ar')"],
|
|
62
|
+
"UPDATE albums SET artist_id = NULL WHERE (artist_id = 1)",
|
|
63
|
+
["INSERT INTO albums (artist_id, name) VALUES (1, 'Al')", "INSERT INTO albums (name, artist_id) VALUES ('Al', 1)"])
|
|
69
64
|
end
|
|
70
65
|
|
|
71
66
|
it "should support creating new one_to_many objects" do
|
|
72
67
|
a = @Artist.new({:name=>'Ar', :albums_attributes=>[{:name=>'Al'}]})
|
|
73
|
-
@
|
|
68
|
+
@db.sqls.should == []
|
|
74
69
|
a.save
|
|
75
|
-
|
|
70
|
+
check_sql_array("INSERT INTO artists (name) VALUES ('Ar')",
|
|
71
|
+
["INSERT INTO albums (artist_id, name) VALUES (1, 'Al')", "INSERT INTO albums (name, artist_id) VALUES ('Al', 1)"])
|
|
76
72
|
end
|
|
77
73
|
|
|
78
74
|
it "should support creating new many_to_many objects" do
|
|
79
75
|
a = @Album.new({:name=>'Al', :tags_attributes=>[{:name=>'T'}]})
|
|
80
|
-
@
|
|
76
|
+
@db.sqls.should == []
|
|
81
77
|
a.save
|
|
82
|
-
|
|
78
|
+
check_sql_array("INSERT INTO albums (name) VALUES ('Al')",
|
|
79
|
+
"INSERT INTO tags (name) VALUES ('T')",
|
|
80
|
+
["INSERT INTO at (album_id, tag_id) VALUES (1, 2)", "INSERT INTO at (tag_id, album_id) VALUES (2, 1)"])
|
|
83
81
|
end
|
|
84
82
|
|
|
85
83
|
it "should add new objects to the cached association array as soon as the *_attributes= method is called" do
|
|
@@ -88,14 +86,64 @@ describe "NestedAttributes plugin" do
|
|
|
88
86
|
a.albums.first.tags.should == [@Tag.new(:name=>'T')]
|
|
89
87
|
end
|
|
90
88
|
|
|
89
|
+
it "should support creating new objects with composite primary keys" do
|
|
90
|
+
insert = nil
|
|
91
|
+
@Concert.class_eval do
|
|
92
|
+
define_method :_insert do
|
|
93
|
+
insert = values
|
|
94
|
+
end
|
|
95
|
+
def before_create # Have to define the CPK somehow.
|
|
96
|
+
self.tour = 'To'
|
|
97
|
+
self.date = '2004-04-05'
|
|
98
|
+
super
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
a = @Artist.new({:name=>'Ar', :concerts_attributes=>[{:playlist=>'Pl'}]})
|
|
102
|
+
@db.sqls.should == []
|
|
103
|
+
a.save
|
|
104
|
+
@db.sqls.should == ["INSERT INTO artists (name) VALUES ('Ar')"]
|
|
105
|
+
insert.should == {:tour=>'To', :date=>'2004-04-05', :artist_id=>1, :playlist=>'Pl'}
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "should support creating new objects with specific primary keys if :unmatched_pk => :create is set" do
|
|
109
|
+
@Artist.nested_attributes :albums, :unmatched_pk=>:create
|
|
110
|
+
insert = nil
|
|
111
|
+
@Album.class_eval do
|
|
112
|
+
unrestrict_primary_key
|
|
113
|
+
define_method :_insert do
|
|
114
|
+
insert = values
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
a = @Artist.new({:name=>'Ar', :albums_attributes=>[{:id=>7, :name=>'Al'}]})
|
|
118
|
+
@db.sqls.should == []
|
|
119
|
+
a.save
|
|
120
|
+
@db.sqls.should == ["INSERT INTO artists (name) VALUES ('Ar')"]
|
|
121
|
+
insert.should == {:artist_id=>1, :name=>'Al', :id=>7}
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "should support creating new objects with specific composite primary keys if :unmatched_pk => :create is set" do
|
|
125
|
+
insert = nil
|
|
126
|
+
@Artist.nested_attributes :concerts, :unmatched_pk=>:create
|
|
127
|
+
@Concert.class_eval do
|
|
128
|
+
define_method :_insert do
|
|
129
|
+
insert = values
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
a = @Artist.new({:name=>'Ar', :concerts_attributes=>[{:tour=>'To', :date=>'2004-04-05', :playlist=>'Pl'}]})
|
|
133
|
+
@db.sqls.should == []
|
|
134
|
+
a.save
|
|
135
|
+
@db.sqls.should == ["INSERT INTO artists (name) VALUES ('Ar')"]
|
|
136
|
+
insert.should == {:tour=>'To', :date=>'2004-04-05', :artist_id=>1, :playlist=>'Pl'}
|
|
137
|
+
end
|
|
138
|
+
|
|
91
139
|
it "should support updating many_to_one objects" do
|
|
92
140
|
al = @Album.load(:id=>10, :name=>'Al')
|
|
93
141
|
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
94
142
|
al.associations[:artist] = ar
|
|
95
143
|
al.set(:artist_attributes=>{:id=>'20', :name=>'Ar2'})
|
|
96
|
-
@
|
|
144
|
+
@db.sqls.should == []
|
|
97
145
|
al.save
|
|
98
|
-
@
|
|
146
|
+
@db.sqls.should == ["UPDATE albums SET name = 'Al' WHERE (id = 10)", "UPDATE artists SET name = 'Ar2' WHERE (id = 20)"]
|
|
99
147
|
end
|
|
100
148
|
|
|
101
149
|
it "should support updating one_to_one objects" do
|
|
@@ -103,9 +151,9 @@ describe "NestedAttributes plugin" do
|
|
|
103
151
|
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
104
152
|
ar.associations[:first_album] = al
|
|
105
153
|
ar.set(:first_album_attributes=>{:id=>10, :name=>'Al2'})
|
|
106
|
-
@
|
|
154
|
+
@db.sqls.should == []
|
|
107
155
|
ar.save
|
|
108
|
-
@
|
|
156
|
+
@db.sqls.should == ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "UPDATE albums SET name = 'Al2' WHERE (id = 10)"]
|
|
109
157
|
end
|
|
110
158
|
|
|
111
159
|
it "should support updating one_to_many objects" do
|
|
@@ -113,9 +161,19 @@ describe "NestedAttributes plugin" do
|
|
|
113
161
|
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
114
162
|
ar.associations[:albums] = [al]
|
|
115
163
|
ar.set(:albums_attributes=>[{:id=>10, :name=>'Al2'}])
|
|
116
|
-
@
|
|
164
|
+
@db.sqls.should == []
|
|
117
165
|
ar.save
|
|
118
|
-
@
|
|
166
|
+
@db.sqls.should == ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "UPDATE albums SET name = 'Al2' WHERE (id = 10)"]
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
it "should support updating one_to_many objects with _delete/_remove flags set to false" do
|
|
170
|
+
al = @Album.load(:id=>10, :name=>'Al')
|
|
171
|
+
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
172
|
+
ar.associations[:albums] = [al]
|
|
173
|
+
ar.set(:albums_attributes=>[{:id=>10, :name=>'Al2', :_delete => 'f', :_remove => '0'}])
|
|
174
|
+
@db.sqls.should == []
|
|
175
|
+
ar.save
|
|
176
|
+
@db.sqls.should == ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "UPDATE albums SET name = 'Al2' WHERE (id = 10)"]
|
|
119
177
|
end
|
|
120
178
|
|
|
121
179
|
it "should support updating many_to_many objects" do
|
|
@@ -123,19 +181,39 @@ describe "NestedAttributes plugin" do
|
|
|
123
181
|
t = @Tag.load(:id=>20, :name=>'T')
|
|
124
182
|
a.associations[:tags] = [t]
|
|
125
183
|
a.set(:tags_attributes=>[{:id=>20, :name=>'T2'}])
|
|
126
|
-
@
|
|
184
|
+
@db.sqls.should == []
|
|
127
185
|
a.save
|
|
128
|
-
@
|
|
186
|
+
@db.sqls.should == ["UPDATE albums SET name = 'Al' WHERE (id = 10)", "UPDATE tags SET name = 'T2' WHERE (id = 20)"]
|
|
129
187
|
end
|
|
130
188
|
|
|
189
|
+
it "should support updating many_to_many objects with _delete/_remove flags set to false" do
|
|
190
|
+
a = @Album.load(:id=>10, :name=>'Al')
|
|
191
|
+
t = @Tag.load(:id=>20, :name=>'T')
|
|
192
|
+
a.associations[:tags] = [t]
|
|
193
|
+
a.set(:tags_attributes=>[{:id=>20, :name=>'T2', '_delete' => false, '_remove' => 'F'}])
|
|
194
|
+
@db.sqls.should == []
|
|
195
|
+
a.save
|
|
196
|
+
@db.sqls.should == ["UPDATE albums SET name = 'Al' WHERE (id = 10)", "UPDATE tags SET name = 'T2' WHERE (id = 20)"]
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
it "should support updating objects with composite primary keys" do
|
|
200
|
+
ar = @Artist.load(:id=>10, :name=>'Ar')
|
|
201
|
+
co = @Concert.load(:tour=>'To', :date=>'2004-04-05', :playlist=>'Pl')
|
|
202
|
+
ar.associations[:concerts] = [co]
|
|
203
|
+
ar.set(:concerts_attributes=>[{:tour=>'To', :date=>'2004-04-05', :playlist=>'Pl2'}])
|
|
204
|
+
@db.sqls.should == []
|
|
205
|
+
ar.save
|
|
206
|
+
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'))"])
|
|
207
|
+
end
|
|
208
|
+
|
|
131
209
|
it "should support removing many_to_one objects" do
|
|
132
210
|
al = @Album.load(:id=>10, :name=>'Al')
|
|
133
211
|
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
134
212
|
al.associations[:artist] = ar
|
|
135
213
|
al.set(:artist_attributes=>{:id=>'20', :_remove=>'1'})
|
|
136
|
-
@
|
|
214
|
+
@db.sqls.should == []
|
|
137
215
|
al.save
|
|
138
|
-
|
|
216
|
+
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)"])
|
|
139
217
|
end
|
|
140
218
|
|
|
141
219
|
it "should support removing one_to_one objects" do
|
|
@@ -143,10 +221,9 @@ describe "NestedAttributes plugin" do
|
|
|
143
221
|
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
144
222
|
ar.associations[:first_album] = al
|
|
145
223
|
ar.set(:first_album_attributes=>{:id=>10, :_remove=>'t'})
|
|
146
|
-
@
|
|
224
|
+
@db.sqls.should == []
|
|
147
225
|
ar.save
|
|
148
|
-
@
|
|
149
|
-
|
|
226
|
+
@db.sqls.should == ["UPDATE albums SET artist_id = NULL WHERE (artist_id = 20)", "UPDATE artists SET name = 'Ar' WHERE (id = 20)"]
|
|
150
227
|
end
|
|
151
228
|
|
|
152
229
|
it "should support removing one_to_many objects" do
|
|
@@ -154,9 +231,12 @@ describe "NestedAttributes plugin" do
|
|
|
154
231
|
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
155
232
|
ar.associations[:albums] = [al]
|
|
156
233
|
ar.set(:albums_attributes=>[{:id=>10, :_remove=>'t'}])
|
|
157
|
-
@
|
|
234
|
+
@db.sqls.should == []
|
|
235
|
+
@Album.dataset._fetch = {:id=>1}
|
|
158
236
|
ar.save
|
|
159
|
-
|
|
237
|
+
check_sql_array("SELECT 1 AS one FROM albums WHERE ((albums.artist_id = 20) AND (id = 10)) LIMIT 1",
|
|
238
|
+
["UPDATE albums SET artist_id = NULL, name = 'Al' WHERE (id = 10)", "UPDATE albums SET name = 'Al', artist_id = NULL WHERE (id = 10)"],
|
|
239
|
+
"UPDATE artists SET name = 'Ar' WHERE (id = 20)")
|
|
160
240
|
end
|
|
161
241
|
|
|
162
242
|
it "should support removing many_to_many objects" do
|
|
@@ -164,19 +244,33 @@ describe "NestedAttributes plugin" do
|
|
|
164
244
|
t = @Tag.load(:id=>20, :name=>'T')
|
|
165
245
|
a.associations[:tags] = [t]
|
|
166
246
|
a.set(:tags_attributes=>[{:id=>20, :_remove=>true}])
|
|
167
|
-
@
|
|
247
|
+
@db.sqls.should == []
|
|
168
248
|
a.save
|
|
169
|
-
@
|
|
249
|
+
@db.sqls.should == ["DELETE FROM at WHERE ((album_id = 10) AND (tag_id = 20))", "UPDATE albums SET name = 'Al' WHERE (id = 10)"]
|
|
170
250
|
end
|
|
171
251
|
|
|
252
|
+
it "should support removing objects with composite primary keys" do
|
|
253
|
+
ar = @Artist.load(:id=>10, :name=>'Ar')
|
|
254
|
+
co = @Concert.load(:tour=>'To', :date=>'2004-04-05', :playlist=>'Pl')
|
|
255
|
+
ar.associations[:concerts] = [co]
|
|
256
|
+
ar.set(:concerts_attributes=>[{:tour=>'To', :date=>'2004-04-05', :_remove=>'t'}])
|
|
257
|
+
@db.sqls.should == []
|
|
258
|
+
@Concert.dataset._fetch = {:id=>1}
|
|
259
|
+
ar.save
|
|
260
|
+
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"],
|
|
261
|
+
["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'))"],
|
|
262
|
+
"UPDATE artists SET name = 'Ar' WHERE (id = 10)")
|
|
263
|
+
end
|
|
264
|
+
|
|
172
265
|
it "should support destroying many_to_one objects" do
|
|
173
266
|
al = @Album.load(:id=>10, :name=>'Al')
|
|
174
267
|
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
175
268
|
al.associations[:artist] = ar
|
|
176
269
|
al.set(:artist_attributes=>{:id=>'20', :_delete=>'1'})
|
|
177
|
-
@
|
|
270
|
+
@db.sqls.should == []
|
|
178
271
|
al.save
|
|
179
|
-
|
|
272
|
+
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)"],
|
|
273
|
+
"DELETE FROM artists WHERE (id = 20)")
|
|
180
274
|
end
|
|
181
275
|
|
|
182
276
|
it "should support destroying one_to_one objects" do
|
|
@@ -184,9 +278,9 @@ describe "NestedAttributes plugin" do
|
|
|
184
278
|
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
185
279
|
ar.associations[:first_album] = al
|
|
186
280
|
ar.set(:first_album_attributes=>{:id=>10, :_delete=>'t'})
|
|
187
|
-
@
|
|
281
|
+
@db.sqls.should == []
|
|
188
282
|
ar.save
|
|
189
|
-
@
|
|
283
|
+
@db.sqls.should == ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "DELETE FROM albums WHERE (id = 10)"]
|
|
190
284
|
end
|
|
191
285
|
|
|
192
286
|
it "should support destroying one_to_many objects" do
|
|
@@ -194,9 +288,9 @@ describe "NestedAttributes plugin" do
|
|
|
194
288
|
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
195
289
|
ar.associations[:albums] = [al]
|
|
196
290
|
ar.set(:albums_attributes=>[{:id=>10, :_delete=>'t'}])
|
|
197
|
-
@
|
|
291
|
+
@db.sqls.should == []
|
|
198
292
|
ar.save
|
|
199
|
-
@
|
|
293
|
+
@db.sqls.should == ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "DELETE FROM albums WHERE (id = 10)"]
|
|
200
294
|
end
|
|
201
295
|
|
|
202
296
|
it "should support destroying many_to_many objects" do
|
|
@@ -204,19 +298,29 @@ describe "NestedAttributes plugin" do
|
|
|
204
298
|
t = @Tag.load(:id=>20, :name=>'T')
|
|
205
299
|
a.associations[:tags] = [t]
|
|
206
300
|
a.set(:tags_attributes=>[{:id=>20, :_delete=>true}])
|
|
207
|
-
@
|
|
301
|
+
@db.sqls.should == []
|
|
208
302
|
a.save
|
|
209
|
-
@
|
|
303
|
+
@db.sqls.should == ["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)"]
|
|
210
304
|
end
|
|
211
305
|
|
|
306
|
+
it "should support destroying objects with composite primary keys" do
|
|
307
|
+
ar = @Artist.load(:id=>10, :name=>'Ar')
|
|
308
|
+
co = @Concert.load(:tour=>'To', :date=>'2004-04-05', :playlist=>'Pl')
|
|
309
|
+
ar.associations[:concerts] = [co]
|
|
310
|
+
ar.set(:concerts_attributes=>[{:tour=>'To', :date=>'2004-04-05', :_delete=>'t'}])
|
|
311
|
+
@db.sqls.should == []
|
|
312
|
+
ar.save
|
|
313
|
+
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'))"])
|
|
314
|
+
end
|
|
315
|
+
|
|
212
316
|
it "should support both string and symbol keys in nested attribute hashes" do
|
|
213
317
|
a = @Album.load(:id=>10, :name=>'Al')
|
|
214
318
|
t = @Tag.load(:id=>20, :name=>'T')
|
|
215
319
|
a.associations[:tags] = [t]
|
|
216
320
|
a.set('tags_attributes'=>[{'id'=>20, '_delete'=>true}])
|
|
217
|
-
@
|
|
321
|
+
@db.sqls.should == []
|
|
218
322
|
a.save
|
|
219
|
-
@
|
|
323
|
+
@db.sqls.should == ["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)"]
|
|
220
324
|
end
|
|
221
325
|
|
|
222
326
|
it "should support using a hash instead of an array for to_many nested attributes" do
|
|
@@ -224,9 +328,9 @@ describe "NestedAttributes plugin" do
|
|
|
224
328
|
t = @Tag.load(:id=>20, :name=>'T')
|
|
225
329
|
a.associations[:tags] = [t]
|
|
226
330
|
a.set('tags_attributes'=>{'1'=>{'id'=>20, '_delete'=>true}})
|
|
227
|
-
@
|
|
331
|
+
@db.sqls.should == []
|
|
228
332
|
a.save
|
|
229
|
-
@
|
|
333
|
+
@db.sqls.should == ["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)"]
|
|
230
334
|
end
|
|
231
335
|
|
|
232
336
|
it "should only allow destroying associated objects if :destroy option is used in the nested_attributes call" do
|
|
@@ -263,11 +367,41 @@ describe "NestedAttributes plugin" do
|
|
|
263
367
|
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
264
368
|
ar.associations[:albums] = [al]
|
|
265
369
|
ar.set(:albums_attributes=>[{:id=>30, :_delete=>'t'}])
|
|
266
|
-
@
|
|
370
|
+
@db.sqls.should == []
|
|
267
371
|
ar.save
|
|
268
|
-
@
|
|
372
|
+
@db.sqls.should == ["UPDATE artists SET name = 'Ar' WHERE (id = 20)"]
|
|
269
373
|
end
|
|
270
374
|
|
|
375
|
+
it "should not raise an Error if an unmatched primary key is given, if the :unmatched_pk=>:ignore option is used" do
|
|
376
|
+
@Artist.nested_attributes :albums, :unmatched_pk=>:ignore
|
|
377
|
+
al = @Album.load(:id=>10, :name=>'Al')
|
|
378
|
+
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
379
|
+
ar.associations[:albums] = [al]
|
|
380
|
+
ar.set(:albums_attributes=>[{:id=>30, :_delete=>'t'}])
|
|
381
|
+
@db.sqls.should == []
|
|
382
|
+
ar.save
|
|
383
|
+
@db.sqls.should == ["UPDATE artists SET name = 'Ar' WHERE (id = 20)"]
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
it "should raise an Error if a composite primary key is given in a nested attribute hash, but no matching associated object exists" do
|
|
387
|
+
ar = @Artist.load(:id=>10, :name=>'Ar')
|
|
388
|
+
co = @Concert.load(:tour=>'To', :date=>'2004-04-05', :playlist=>'Pl')
|
|
389
|
+
ar.associations[:concerts] = [co]
|
|
390
|
+
proc{ar.set(:concerts_attributes=>[{:tour=>'To', :date=>'2004-04-04', :_delete=>'t'}])}.should raise_error(Sequel::Error)
|
|
391
|
+
proc{ar.set(:concerts_attributes=>[{:tour=>'To', :date=>'2004-04-05', :_delete=>'t'}])}.should_not raise_error(Sequel::Error)
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
it "should not raise an Error if an unmatched composite primary key is given, if the :strict=>false option is used" do
|
|
395
|
+
@Artist.nested_attributes :concerts, :strict=>false
|
|
396
|
+
ar = @Artist.load(:id=>10, :name=>'Ar')
|
|
397
|
+
co = @Concert.load(:tour=>'To', :date=>'2004-04-05', :playlist=>'Pl')
|
|
398
|
+
ar.associations[:concerts] = [co]
|
|
399
|
+
ar.set(:concerts_attributes=>[{:tour=>'To', :date=>'2004-04-06', :_delete=>'t'}])
|
|
400
|
+
@db.sqls.should == []
|
|
401
|
+
ar.save
|
|
402
|
+
@db.sqls.should == ["UPDATE artists SET name = 'Ar' WHERE (id = 10)"]
|
|
403
|
+
end
|
|
404
|
+
|
|
271
405
|
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
|
|
272
406
|
@Artist.class_eval do
|
|
273
407
|
def validate
|
|
@@ -276,10 +410,10 @@ describe "NestedAttributes plugin" do
|
|
|
276
410
|
end
|
|
277
411
|
end
|
|
278
412
|
a = @Album.new(:name=>'Al', :artist_attributes=>{:name=>'Ar'})
|
|
279
|
-
@
|
|
413
|
+
@db.sqls.should == []
|
|
280
414
|
proc{a.save}.should raise_error(Sequel::ValidationFailed)
|
|
281
415
|
a.errors.full_messages.should == ['artist name cannot be Ar']
|
|
282
|
-
@
|
|
416
|
+
@db.sqls.should == []
|
|
283
417
|
# Should preserve attributes
|
|
284
418
|
a.artist.name.should == 'Ar'
|
|
285
419
|
end
|
|
@@ -294,9 +428,10 @@ describe "NestedAttributes plugin" do
|
|
|
294
428
|
end
|
|
295
429
|
end
|
|
296
430
|
a = @Album.new(:name=>'Al', :artist_attributes=>{:name=>'Ar'})
|
|
297
|
-
@
|
|
431
|
+
@db.sqls.should == []
|
|
298
432
|
a.save
|
|
299
|
-
|
|
433
|
+
check_sql_array("INSERT INTO artists (name) VALUES ('Ar')",
|
|
434
|
+
["INSERT INTO albums (artist_id, name) VALUES (1, 'Al')", "INSERT INTO albums (name, artist_id) VALUES ('Al', 1)"])
|
|
300
435
|
end
|
|
301
436
|
|
|
302
437
|
it "should not attempt to validate nested attributes if the :validate=>false option is passed to save" do
|
|
@@ -307,23 +442,25 @@ describe "NestedAttributes plugin" do
|
|
|
307
442
|
end
|
|
308
443
|
end
|
|
309
444
|
a = @Album.new(:name=>'Al', :artist_attributes=>{:name=>'Ar'})
|
|
310
|
-
@
|
|
445
|
+
@db.sqls.should == []
|
|
311
446
|
a.save(:validate=>false)
|
|
312
|
-
|
|
447
|
+
check_sql_array("INSERT INTO artists (name) VALUES ('Ar')",
|
|
448
|
+
["INSERT INTO albums (artist_id, name) VALUES (1, 'Al')", "INSERT INTO albums (name, artist_id) VALUES ('Al', 1)"])
|
|
313
449
|
end
|
|
314
450
|
|
|
315
451
|
it "should not accept nested attributes unless explicitly specified" do
|
|
316
452
|
@Artist.many_to_many :tags, :class=>@Tag, :left_key=>:album_id, :right_key=>:tag_id, :join_table=>:at
|
|
317
453
|
proc{@Artist.create({:name=>'Ar', :tags_attributes=>[{:name=>'T'}]})}.should raise_error(Sequel::Error)
|
|
318
|
-
@
|
|
454
|
+
@db.sqls.should == []
|
|
319
455
|
end
|
|
320
456
|
|
|
321
457
|
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
|
|
322
458
|
al = @Album.load(:id=>10, :name=>'Al')
|
|
323
459
|
ar = @Artist.load(:id=>20, :name=>'Ar')
|
|
324
460
|
al.associations[:artist] = ar
|
|
461
|
+
@db.sqls.should == []
|
|
325
462
|
al.update(:artist_attributes=>{:id=>'20', :name=>'Ar2'})
|
|
326
|
-
@
|
|
463
|
+
@db.sqls.should == ["UPDATE artists SET name = 'Ar2' WHERE (id = 20)"]
|
|
327
464
|
end
|
|
328
465
|
|
|
329
466
|
it "should have a :limit option limiting the amount of entries" do
|
|
@@ -331,19 +468,40 @@ describe "NestedAttributes plugin" do
|
|
|
331
468
|
arr = [{:name=>'T'}]
|
|
332
469
|
proc{@Album.new({:name=>'Al', :tags_attributes=>arr*3})}.should raise_error(Sequel::Error)
|
|
333
470
|
a = @Album.new({:name=>'Al', :tags_attributes=>arr*2})
|
|
334
|
-
@
|
|
471
|
+
@db.sqls.should == []
|
|
335
472
|
a.save
|
|
336
|
-
|
|
473
|
+
check_sql_array("INSERT INTO albums (name) VALUES ('Al')",
|
|
474
|
+
"INSERT INTO tags (name) VALUES ('T')",
|
|
475
|
+
["INSERT INTO at (album_id, tag_id) VALUES (1, 2)", "INSERT INTO at (tag_id, album_id) VALUES (2, 1)"],
|
|
476
|
+
"INSERT INTO tags (name) VALUES ('T')",
|
|
477
|
+
["INSERT INTO at (album_id, tag_id) VALUES (1, 4)", "INSERT INTO at (tag_id, album_id) VALUES (4, 1)"])
|
|
337
478
|
end
|
|
338
479
|
|
|
339
480
|
it "should accept a block that each hash gets passed to determine if it should be processed" do
|
|
340
481
|
@Album.nested_attributes(:tags){|h| h[:name].empty?}
|
|
341
482
|
a = @Album.new({:name=>'Al', :tags_attributes=>[{:name=>'T'}, {:name=>''}, {:name=>'T2'}]})
|
|
342
|
-
@
|
|
483
|
+
@db.sqls.should == []
|
|
343
484
|
a.save
|
|
344
|
-
|
|
485
|
+
check_sql_array("INSERT INTO albums (name) VALUES ('Al')",
|
|
486
|
+
"INSERT INTO tags (name) VALUES ('T')",
|
|
487
|
+
["INSERT INTO at (album_id, tag_id) VALUES (1, 2)", "INSERT INTO at (tag_id, album_id) VALUES (2, 1)"],
|
|
488
|
+
"INSERT INTO tags (name) VALUES ('T2')",
|
|
489
|
+
["INSERT INTO at (album_id, tag_id) VALUES (1, 4)", "INSERT INTO at (tag_id, album_id) VALUES (4, 1)"])
|
|
345
490
|
end
|
|
346
491
|
|
|
492
|
+
it "should accept a :transform block that returns a changed attributes hash" do
|
|
493
|
+
@Album.nested_attributes :tags, :transform=>proc{|parent, hash| hash[:name] << parent.name; hash }
|
|
494
|
+
a = @Album.new(:name => 'Al')
|
|
495
|
+
a.set(:tags_attributes=>[{:name=>'T'}, {:name=>'T2'}])
|
|
496
|
+
@db.sqls.should == []
|
|
497
|
+
a.save
|
|
498
|
+
check_sql_array("INSERT INTO albums (name) VALUES ('Al')",
|
|
499
|
+
"INSERT INTO tags (name) VALUES ('TAl')",
|
|
500
|
+
["INSERT INTO at (album_id, tag_id) VALUES (1, 2)", "INSERT INTO at (tag_id, album_id) VALUES (2, 1)"],
|
|
501
|
+
"INSERT INTO tags (name) VALUES ('T2Al')",
|
|
502
|
+
["INSERT INTO at (album_id, tag_id) VALUES (1, 4)", "INSERT INTO at (tag_id, album_id) VALUES (4, 1)"])
|
|
503
|
+
end
|
|
504
|
+
|
|
347
505
|
it "should return objects created/modified in the internal methods" do
|
|
348
506
|
@Album.nested_attributes :tags, :remove=>true, :strict=>false
|
|
349
507
|
objs = []
|
|
@@ -355,7 +513,7 @@ describe "NestedAttributes plugin" do
|
|
|
355
513
|
a = @Album.new(:name=>'Al')
|
|
356
514
|
a.associations[:tags] = [@Tag.load(:id=>6, :name=>'A'), @Tag.load(:id=>7, :name=>'A2')]
|
|
357
515
|
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}]
|
|
358
|
-
objs.should == [[@Tag.load(:id=>6, :name=>'T'), :update], [@Tag.load(:id=>7, :name=>'A2'), :remove], [@Tag.new(:name=>'T3'), :create]
|
|
516
|
+
objs.should == [[@Tag.load(:id=>6, :name=>'T'), :update], [@Tag.load(:id=>7, :name=>'A2'), :remove], [@Tag.new(:name=>'T3'), :create]]
|
|
359
517
|
end
|
|
360
518
|
|
|
361
519
|
it "should raise an error if updating modifies the associated objects keys" do
|
|
@@ -387,9 +545,30 @@ describe "NestedAttributes plugin" do
|
|
|
387
545
|
t = @Tag.load(:id=>30, :name=>'T', :number=>10)
|
|
388
546
|
al.associations[:tags] = [t]
|
|
389
547
|
al.set(:tags_attributes=>[{:id=>30, :name=>'T2'}, {:name=>'T3'}])
|
|
390
|
-
@
|
|
548
|
+
@db.sqls.should == []
|
|
549
|
+
al.save
|
|
550
|
+
check_sql_array("UPDATE albums SET name = 'Al' WHERE (id = 10)",
|
|
551
|
+
"UPDATE tags SET name = 'T2' WHERE (id = 30)",
|
|
552
|
+
"INSERT INTO tags (name) VALUES ('T3')",
|
|
553
|
+
["INSERT INTO at (album_id, tag_id) VALUES (10, 1)", "INSERT INTO at (tag_id, album_id) VALUES (1, 10)"])
|
|
554
|
+
proc{al.set(:tags_attributes=>[{:id=>30, :name=>'T2', :number=>3}])}.should raise_error(Sequel::Error)
|
|
555
|
+
proc{al.set(:tags_attributes=>[{:name=>'T2', :number=>3}])}.should raise_error(Sequel::Error)
|
|
556
|
+
end
|
|
557
|
+
|
|
558
|
+
it "should accept a proc for the :fields option that accepts the associated object and returns an array of fields" do
|
|
559
|
+
@Tag.columns :id, :name, :number
|
|
560
|
+
@Album.nested_attributes :tags, :destroy=>true, :remove=>true, :fields=>proc{|object| object.is_a?(@Tag) ? [:name] : []}
|
|
561
|
+
|
|
562
|
+
al = @Album.load(:id=>10, :name=>'Al')
|
|
563
|
+
t = @Tag.load(:id=>30, :name=>'T', :number=>10)
|
|
564
|
+
al.associations[:tags] = [t]
|
|
565
|
+
al.set(:tags_attributes=>[{:id=>30, :name=>'T2'}, {:name=>'T3'}])
|
|
566
|
+
@db.sqls.should == []
|
|
391
567
|
al.save
|
|
392
|
-
|
|
568
|
+
check_sql_array("UPDATE albums SET name = 'Al' WHERE (id = 10)",
|
|
569
|
+
"UPDATE tags SET name = 'T2' WHERE (id = 30)",
|
|
570
|
+
"INSERT INTO tags (name) VALUES ('T3')",
|
|
571
|
+
["INSERT INTO at (album_id, tag_id) VALUES (10, 1)", "INSERT INTO at (tag_id, album_id) VALUES (1, 10)"])
|
|
393
572
|
proc{al.set(:tags_attributes=>[{:id=>30, :name=>'T2', :number=>3}])}.should raise_error(Sequel::Error)
|
|
394
573
|
proc{al.set(:tags_attributes=>[{:name=>'T2', :number=>3}])}.should raise_error(Sequel::Error)
|
|
395
574
|
end
|