sequel 5.20.0 → 5.49.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.
Files changed (511) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +398 -1922
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +7 -7
  5. data/doc/advanced_associations.rdoc +4 -4
  6. data/doc/association_basics.rdoc +80 -16
  7. data/doc/cheat_sheet.rdoc +6 -5
  8. data/doc/code_order.rdoc +10 -12
  9. data/doc/dataset_filtering.rdoc +17 -2
  10. data/doc/fork_safety.rdoc +84 -0
  11. data/doc/migration.rdoc +11 -5
  12. data/doc/model_dataset_method_design.rdoc +1 -1
  13. data/doc/model_plugins.rdoc +1 -1
  14. data/doc/opening_databases.rdoc +10 -2
  15. data/doc/postgresql.rdoc +82 -3
  16. data/doc/querying.rdoc +4 -4
  17. data/doc/release_notes/5.21.0.txt +87 -0
  18. data/doc/release_notes/5.22.0.txt +48 -0
  19. data/doc/release_notes/5.23.0.txt +56 -0
  20. data/doc/release_notes/5.24.0.txt +56 -0
  21. data/doc/release_notes/5.25.0.txt +32 -0
  22. data/doc/release_notes/5.26.0.txt +35 -0
  23. data/doc/release_notes/5.27.0.txt +21 -0
  24. data/doc/release_notes/5.28.0.txt +16 -0
  25. data/doc/release_notes/5.29.0.txt +22 -0
  26. data/doc/release_notes/5.30.0.txt +20 -0
  27. data/doc/release_notes/5.31.0.txt +148 -0
  28. data/doc/release_notes/5.32.0.txt +46 -0
  29. data/doc/release_notes/5.33.0.txt +24 -0
  30. data/doc/release_notes/5.34.0.txt +40 -0
  31. data/doc/release_notes/5.35.0.txt +56 -0
  32. data/doc/release_notes/5.36.0.txt +60 -0
  33. data/doc/release_notes/5.37.0.txt +30 -0
  34. data/doc/release_notes/5.38.0.txt +28 -0
  35. data/doc/release_notes/5.39.0.txt +19 -0
  36. data/doc/release_notes/5.40.0.txt +40 -0
  37. data/doc/release_notes/5.41.0.txt +25 -0
  38. data/doc/release_notes/5.42.0.txt +136 -0
  39. data/doc/release_notes/5.43.0.txt +98 -0
  40. data/doc/release_notes/5.44.0.txt +32 -0
  41. data/doc/release_notes/5.45.0.txt +34 -0
  42. data/doc/release_notes/5.46.0.txt +87 -0
  43. data/doc/release_notes/5.47.0.txt +59 -0
  44. data/doc/release_notes/5.48.0.txt +14 -0
  45. data/doc/release_notes/5.49.0.txt +59 -0
  46. data/doc/sharding.rdoc +2 -0
  47. data/doc/sql.rdoc +13 -1
  48. data/doc/testing.rdoc +20 -7
  49. data/doc/transactions.rdoc +0 -8
  50. data/doc/validations.rdoc +1 -1
  51. data/doc/virtual_rows.rdoc +1 -1
  52. data/lib/sequel/adapters/ado/access.rb +1 -1
  53. data/lib/sequel/adapters/ado.rb +43 -35
  54. data/lib/sequel/adapters/ibmdb.rb +2 -2
  55. data/lib/sequel/adapters/jdbc/mysql.rb +6 -6
  56. data/lib/sequel/adapters/jdbc/postgresql.rb +11 -17
  57. data/lib/sequel/adapters/jdbc/sqlite.rb +29 -0
  58. data/lib/sequel/adapters/jdbc.rb +24 -6
  59. data/lib/sequel/adapters/mysql.rb +1 -1
  60. data/lib/sequel/adapters/mysql2.rb +2 -3
  61. data/lib/sequel/adapters/odbc.rb +8 -6
  62. data/lib/sequel/adapters/oracle.rb +5 -4
  63. data/lib/sequel/adapters/postgres.rb +15 -9
  64. data/lib/sequel/adapters/shared/access.rb +6 -6
  65. data/lib/sequel/adapters/shared/mssql.rb +66 -21
  66. data/lib/sequel/adapters/shared/mysql.rb +27 -10
  67. data/lib/sequel/adapters/shared/oracle.rb +29 -23
  68. data/lib/sequel/adapters/shared/postgres.rb +271 -32
  69. data/lib/sequel/adapters/shared/sqlanywhere.rb +9 -9
  70. data/lib/sequel/adapters/shared/sqlite.rb +161 -19
  71. data/lib/sequel/adapters/sqlanywhere.rb +1 -1
  72. data/lib/sequel/adapters/sqlite.rb +1 -1
  73. data/lib/sequel/adapters/tinytds.rb +15 -2
  74. data/lib/sequel/adapters/utils/mysql_mysql2.rb +4 -1
  75. data/lib/sequel/ast_transformer.rb +6 -0
  76. data/lib/sequel/connection_pool/sharded_single.rb +4 -1
  77. data/lib/sequel/connection_pool/sharded_threaded.rb +12 -12
  78. data/lib/sequel/connection_pool/single.rb +1 -1
  79. data/lib/sequel/connection_pool/threaded.rb +2 -2
  80. data/lib/sequel/core.rb +333 -319
  81. data/lib/sequel/database/connecting.rb +3 -4
  82. data/lib/sequel/database/logging.rb +7 -1
  83. data/lib/sequel/database/misc.rb +31 -12
  84. data/lib/sequel/database/query.rb +3 -1
  85. data/lib/sequel/database/schema_generator.rb +53 -51
  86. data/lib/sequel/database/schema_methods.rb +38 -23
  87. data/lib/sequel/database/transactions.rb +17 -18
  88. data/lib/sequel/dataset/actions.rb +14 -9
  89. data/lib/sequel/dataset/features.rb +16 -0
  90. data/lib/sequel/dataset/misc.rb +2 -2
  91. data/lib/sequel/dataset/placeholder_literalizer.rb +3 -7
  92. data/lib/sequel/dataset/prepared_statements.rb +2 -0
  93. data/lib/sequel/dataset/query.rb +26 -9
  94. data/lib/sequel/dataset/sql.rb +76 -25
  95. data/lib/sequel/dataset.rb +4 -2
  96. data/lib/sequel/deprecated.rb +3 -1
  97. data/lib/sequel/exceptions.rb +2 -0
  98. data/lib/sequel/extensions/_pretty_table.rb +1 -2
  99. data/lib/sequel/extensions/any_not_empty.rb +45 -0
  100. data/lib/sequel/extensions/async_thread_pool.rb +438 -0
  101. data/lib/sequel/extensions/blank.rb +8 -0
  102. data/lib/sequel/extensions/columns_introspection.rb +1 -2
  103. data/lib/sequel/extensions/connection_expiration.rb +2 -2
  104. data/lib/sequel/extensions/connection_validator.rb +2 -2
  105. data/lib/sequel/extensions/core_refinements.rb +2 -0
  106. data/lib/sequel/extensions/date_arithmetic.rb +36 -24
  107. data/lib/sequel/extensions/duplicate_columns_handler.rb +3 -1
  108. data/lib/sequel/extensions/eval_inspect.rb +2 -0
  109. data/lib/sequel/extensions/exclude_or_null.rb +68 -0
  110. data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
  111. data/lib/sequel/extensions/index_caching.rb +9 -7
  112. data/lib/sequel/extensions/inflector.rb +9 -1
  113. data/lib/sequel/extensions/integer64.rb +2 -0
  114. data/lib/sequel/extensions/migration.rb +11 -3
  115. data/lib/sequel/extensions/named_timezones.rb +56 -8
  116. data/lib/sequel/extensions/pagination.rb +1 -1
  117. data/lib/sequel/extensions/pg_array.rb +5 -0
  118. data/lib/sequel/extensions/pg_array_ops.rb +14 -6
  119. data/lib/sequel/extensions/pg_enum.rb +11 -3
  120. data/lib/sequel/extensions/pg_extended_date_support.rb +2 -2
  121. data/lib/sequel/extensions/pg_hstore.rb +6 -0
  122. data/lib/sequel/extensions/pg_hstore_ops.rb +54 -2
  123. data/lib/sequel/extensions/pg_inet.rb +15 -5
  124. data/lib/sequel/extensions/pg_interval.rb +36 -8
  125. data/lib/sequel/extensions/pg_json.rb +387 -123
  126. data/lib/sequel/extensions/pg_json_ops.rb +238 -0
  127. data/lib/sequel/extensions/pg_loose_count.rb +3 -1
  128. data/lib/sequel/extensions/pg_range.rb +17 -9
  129. data/lib/sequel/extensions/pg_range_ops.rb +2 -0
  130. data/lib/sequel/extensions/pg_row.rb +4 -2
  131. data/lib/sequel/extensions/pg_row_ops.rb +24 -0
  132. data/lib/sequel/extensions/pg_timestamptz.rb +2 -0
  133. data/lib/sequel/extensions/query.rb +3 -0
  134. data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
  135. data/lib/sequel/extensions/s.rb +2 -0
  136. data/lib/sequel/extensions/schema_dumper.rb +24 -7
  137. data/lib/sequel/extensions/server_block.rb +18 -7
  138. data/lib/sequel/extensions/sql_comments.rb +2 -2
  139. data/lib/sequel/extensions/string_agg.rb +1 -1
  140. data/lib/sequel/extensions/symbol_aref_refinement.rb +2 -0
  141. data/lib/sequel/extensions/symbol_as_refinement.rb +2 -0
  142. data/lib/sequel/extensions/to_dot.rb +9 -3
  143. data/lib/sequel/model/associations.rb +356 -117
  144. data/lib/sequel/model/base.rb +107 -68
  145. data/lib/sequel/model/errors.rb +10 -1
  146. data/lib/sequel/model/inflections.rb +1 -1
  147. data/lib/sequel/model/plugins.rb +9 -3
  148. data/lib/sequel/model.rb +3 -1
  149. data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
  150. data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
  151. data/lib/sequel/plugins/association_pks.rb +60 -18
  152. data/lib/sequel/plugins/association_proxies.rb +8 -2
  153. data/lib/sequel/plugins/async_thread_pool.rb +39 -0
  154. data/lib/sequel/plugins/auto_validations.rb +39 -5
  155. data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
  156. data/lib/sequel/plugins/blacklist_security.rb +1 -2
  157. data/lib/sequel/plugins/boolean_subsets.rb +4 -1
  158. data/lib/sequel/plugins/caching.rb +3 -0
  159. data/lib/sequel/plugins/class_table_inheritance.rb +33 -28
  160. data/lib/sequel/plugins/column_encryption.rb +728 -0
  161. data/lib/sequel/plugins/composition.rb +7 -2
  162. data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
  163. data/lib/sequel/plugins/constraint_validations.rb +2 -1
  164. data/lib/sequel/plugins/csv_serializer.rb +28 -9
  165. data/lib/sequel/plugins/dataset_associations.rb +4 -1
  166. data/lib/sequel/plugins/dirty.rb +60 -22
  167. data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
  168. data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
  169. data/lib/sequel/plugins/insert_conflict.rb +72 -0
  170. data/lib/sequel/plugins/instance_specific_default.rb +113 -0
  171. data/lib/sequel/plugins/json_serializer.rb +57 -35
  172. data/lib/sequel/plugins/lazy_attributes.rb +1 -1
  173. data/lib/sequel/plugins/many_through_many.rb +108 -9
  174. data/lib/sequel/plugins/nested_attributes.rb +15 -3
  175. data/lib/sequel/plugins/pg_array_associations.rb +58 -41
  176. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +91 -30
  177. data/lib/sequel/plugins/prepared_statements.rb +15 -12
  178. data/lib/sequel/plugins/prepared_statements_safe.rb +1 -3
  179. data/lib/sequel/plugins/rcte_tree.rb +43 -35
  180. data/lib/sequel/plugins/serialization.rb +8 -3
  181. data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
  182. data/lib/sequel/plugins/sharding.rb +11 -5
  183. data/lib/sequel/plugins/single_table_inheritance.rb +22 -15
  184. data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
  185. data/lib/sequel/plugins/static_cache.rb +9 -4
  186. data/lib/sequel/plugins/static_cache_cache.rb +53 -0
  187. data/lib/sequel/plugins/string_stripper.rb +1 -1
  188. data/lib/sequel/plugins/subclasses.rb +2 -0
  189. data/lib/sequel/plugins/throw_failures.rb +1 -1
  190. data/lib/sequel/plugins/timestamps.rb +1 -1
  191. data/lib/sequel/plugins/tree.rb +9 -4
  192. data/lib/sequel/plugins/typecast_on_load.rb +3 -2
  193. data/lib/sequel/plugins/unused_associations.rb +521 -0
  194. data/lib/sequel/plugins/update_or_create.rb +1 -1
  195. data/lib/sequel/plugins/validation_class_methods.rb +5 -1
  196. data/lib/sequel/plugins/validation_helpers.rb +18 -11
  197. data/lib/sequel/plugins/xml_serializer.rb +1 -1
  198. data/lib/sequel/sql.rb +20 -5
  199. data/lib/sequel/timezones.rb +63 -17
  200. data/lib/sequel/version.rb +1 -1
  201. metadata +113 -381
  202. data/Rakefile +0 -151
  203. data/doc/release_notes/4.0.0.txt +0 -262
  204. data/doc/release_notes/4.1.0.txt +0 -85
  205. data/doc/release_notes/4.10.0.txt +0 -226
  206. data/doc/release_notes/4.11.0.txt +0 -147
  207. data/doc/release_notes/4.12.0.txt +0 -105
  208. data/doc/release_notes/4.13.0.txt +0 -169
  209. data/doc/release_notes/4.14.0.txt +0 -68
  210. data/doc/release_notes/4.15.0.txt +0 -56
  211. data/doc/release_notes/4.16.0.txt +0 -36
  212. data/doc/release_notes/4.17.0.txt +0 -38
  213. data/doc/release_notes/4.18.0.txt +0 -36
  214. data/doc/release_notes/4.19.0.txt +0 -45
  215. data/doc/release_notes/4.2.0.txt +0 -129
  216. data/doc/release_notes/4.20.0.txt +0 -79
  217. data/doc/release_notes/4.21.0.txt +0 -94
  218. data/doc/release_notes/4.22.0.txt +0 -72
  219. data/doc/release_notes/4.23.0.txt +0 -65
  220. data/doc/release_notes/4.24.0.txt +0 -99
  221. data/doc/release_notes/4.25.0.txt +0 -181
  222. data/doc/release_notes/4.26.0.txt +0 -44
  223. data/doc/release_notes/4.27.0.txt +0 -78
  224. data/doc/release_notes/4.28.0.txt +0 -57
  225. data/doc/release_notes/4.29.0.txt +0 -41
  226. data/doc/release_notes/4.3.0.txt +0 -40
  227. data/doc/release_notes/4.30.0.txt +0 -37
  228. data/doc/release_notes/4.31.0.txt +0 -57
  229. data/doc/release_notes/4.32.0.txt +0 -132
  230. data/doc/release_notes/4.33.0.txt +0 -88
  231. data/doc/release_notes/4.34.0.txt +0 -86
  232. data/doc/release_notes/4.35.0.txt +0 -130
  233. data/doc/release_notes/4.36.0.txt +0 -116
  234. data/doc/release_notes/4.37.0.txt +0 -50
  235. data/doc/release_notes/4.38.0.txt +0 -67
  236. data/doc/release_notes/4.39.0.txt +0 -127
  237. data/doc/release_notes/4.4.0.txt +0 -92
  238. data/doc/release_notes/4.40.0.txt +0 -179
  239. data/doc/release_notes/4.41.0.txt +0 -77
  240. data/doc/release_notes/4.42.0.txt +0 -221
  241. data/doc/release_notes/4.43.0.txt +0 -87
  242. data/doc/release_notes/4.44.0.txt +0 -125
  243. data/doc/release_notes/4.45.0.txt +0 -370
  244. data/doc/release_notes/4.46.0.txt +0 -404
  245. data/doc/release_notes/4.47.0.txt +0 -56
  246. data/doc/release_notes/4.48.0.txt +0 -293
  247. data/doc/release_notes/4.49.0.txt +0 -222
  248. data/doc/release_notes/4.5.0.txt +0 -34
  249. data/doc/release_notes/4.6.0.txt +0 -30
  250. data/doc/release_notes/4.7.0.txt +0 -103
  251. data/doc/release_notes/4.8.0.txt +0 -175
  252. data/doc/release_notes/4.9.0.txt +0 -190
  253. data/spec/adapter_spec.rb +0 -4
  254. data/spec/adapters/db2_spec.rb +0 -170
  255. data/spec/adapters/mssql_spec.rb +0 -804
  256. data/spec/adapters/mysql_spec.rb +0 -1065
  257. data/spec/adapters/oracle_spec.rb +0 -371
  258. data/spec/adapters/postgres_spec.rb +0 -4125
  259. data/spec/adapters/spec_helper.rb +0 -44
  260. data/spec/adapters/sqlanywhere_spec.rb +0 -97
  261. data/spec/adapters/sqlite_spec.rb +0 -652
  262. data/spec/bin_spec.rb +0 -278
  263. data/spec/core/connection_pool_spec.rb +0 -1250
  264. data/spec/core/database_spec.rb +0 -2865
  265. data/spec/core/dataset_spec.rb +0 -5515
  266. data/spec/core/deprecated_spec.rb +0 -70
  267. data/spec/core/expression_filters_spec.rb +0 -1455
  268. data/spec/core/mock_adapter_spec.rb +0 -722
  269. data/spec/core/object_graph_spec.rb +0 -336
  270. data/spec/core/placeholder_literalizer_spec.rb +0 -166
  271. data/spec/core/schema_generator_spec.rb +0 -214
  272. data/spec/core/schema_spec.rb +0 -1826
  273. data/spec/core/spec_helper.rb +0 -24
  274. data/spec/core/version_spec.rb +0 -14
  275. data/spec/core_extensions_spec.rb +0 -763
  276. data/spec/core_model_spec.rb +0 -2
  277. data/spec/core_spec.rb +0 -1
  278. data/spec/deprecation_helper.rb +0 -30
  279. data/spec/extensions/accessed_columns_spec.rb +0 -51
  280. data/spec/extensions/active_model_spec.rb +0 -99
  281. data/spec/extensions/after_initialize_spec.rb +0 -28
  282. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  283. data/spec/extensions/association_dependencies_spec.rb +0 -125
  284. data/spec/extensions/association_pks_spec.rb +0 -423
  285. data/spec/extensions/association_proxies_spec.rb +0 -100
  286. data/spec/extensions/auto_literal_strings_spec.rb +0 -205
  287. data/spec/extensions/auto_validations_spec.rb +0 -229
  288. data/spec/extensions/blacklist_security_spec.rb +0 -95
  289. data/spec/extensions/blank_spec.rb +0 -69
  290. data/spec/extensions/boolean_readers_spec.rb +0 -93
  291. data/spec/extensions/boolean_subsets_spec.rb +0 -47
  292. data/spec/extensions/caching_spec.rb +0 -273
  293. data/spec/extensions/caller_logging_spec.rb +0 -52
  294. data/spec/extensions/class_table_inheritance_spec.rb +0 -750
  295. data/spec/extensions/column_conflicts_spec.rb +0 -75
  296. data/spec/extensions/column_select_spec.rb +0 -129
  297. data/spec/extensions/columns_introspection_spec.rb +0 -90
  298. data/spec/extensions/columns_updated_spec.rb +0 -35
  299. data/spec/extensions/composition_spec.rb +0 -248
  300. data/spec/extensions/connection_expiration_spec.rb +0 -151
  301. data/spec/extensions/connection_validator_spec.rb +0 -144
  302. data/spec/extensions/constant_sql_override_spec.rb +0 -24
  303. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -300
  304. data/spec/extensions/constraint_validations_spec.rb +0 -439
  305. data/spec/extensions/core_refinements_spec.rb +0 -528
  306. data/spec/extensions/csv_serializer_spec.rb +0 -183
  307. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  308. data/spec/extensions/dataset_associations_spec.rb +0 -365
  309. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  310. data/spec/extensions/date_arithmetic_spec.rb +0 -181
  311. data/spec/extensions/datetime_parse_to_time_spec.rb +0 -169
  312. data/spec/extensions/def_dataset_method_spec.rb +0 -100
  313. data/spec/extensions/defaults_setter_spec.rb +0 -150
  314. data/spec/extensions/delay_add_association_spec.rb +0 -73
  315. data/spec/extensions/dirty_spec.rb +0 -189
  316. data/spec/extensions/duplicate_columns_handler_spec.rb +0 -104
  317. data/spec/extensions/eager_each_spec.rb +0 -62
  318. data/spec/extensions/eager_graph_eager_spec.rb +0 -100
  319. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  320. data/spec/extensions/error_splitter_spec.rb +0 -18
  321. data/spec/extensions/error_sql_spec.rb +0 -20
  322. data/spec/extensions/escaped_like_spec.rb +0 -40
  323. data/spec/extensions/eval_inspect_spec.rb +0 -81
  324. data/spec/extensions/finder_spec.rb +0 -260
  325. data/spec/extensions/force_encoding_spec.rb +0 -126
  326. data/spec/extensions/freeze_datasets_spec.rb +0 -31
  327. data/spec/extensions/graph_each_spec.rb +0 -113
  328. data/spec/extensions/hook_class_methods_spec.rb +0 -402
  329. data/spec/extensions/identifier_mangling_spec.rb +0 -201
  330. data/spec/extensions/implicit_subquery_spec.rb +0 -58
  331. data/spec/extensions/index_caching_spec.rb +0 -66
  332. data/spec/extensions/inflector_spec.rb +0 -183
  333. data/spec/extensions/input_transformer_spec.rb +0 -69
  334. data/spec/extensions/insert_returning_select_spec.rb +0 -72
  335. data/spec/extensions/instance_filters_spec.rb +0 -79
  336. data/spec/extensions/instance_hooks_spec.rb +0 -246
  337. data/spec/extensions/integer64_spec.rb +0 -22
  338. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  339. data/spec/extensions/json_serializer_spec.rb +0 -336
  340. data/spec/extensions/lazy_attributes_spec.rb +0 -183
  341. data/spec/extensions/list_spec.rb +0 -291
  342. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  343. data/spec/extensions/many_through_many_spec.rb +0 -2177
  344. data/spec/extensions/migration_spec.rb +0 -864
  345. data/spec/extensions/modification_detection_spec.rb +0 -93
  346. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -92
  347. data/spec/extensions/named_timezones_spec.rb +0 -111
  348. data/spec/extensions/nested_attributes_spec.rb +0 -767
  349. data/spec/extensions/null_dataset_spec.rb +0 -85
  350. data/spec/extensions/optimistic_locking_spec.rb +0 -127
  351. data/spec/extensions/pagination_spec.rb +0 -116
  352. data/spec/extensions/pg_array_associations_spec.rb +0 -802
  353. data/spec/extensions/pg_array_ops_spec.rb +0 -144
  354. data/spec/extensions/pg_array_spec.rb +0 -398
  355. data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -172
  356. data/spec/extensions/pg_enum_spec.rb +0 -118
  357. data/spec/extensions/pg_extended_date_support_spec.rb +0 -126
  358. data/spec/extensions/pg_hstore_ops_spec.rb +0 -238
  359. data/spec/extensions/pg_hstore_spec.rb +0 -219
  360. data/spec/extensions/pg_inet_ops_spec.rb +0 -102
  361. data/spec/extensions/pg_inet_spec.rb +0 -72
  362. data/spec/extensions/pg_interval_spec.rb +0 -103
  363. data/spec/extensions/pg_json_ops_spec.rb +0 -289
  364. data/spec/extensions/pg_json_spec.rb +0 -262
  365. data/spec/extensions/pg_loose_count_spec.rb +0 -23
  366. data/spec/extensions/pg_range_ops_spec.rb +0 -60
  367. data/spec/extensions/pg_range_spec.rb +0 -519
  368. data/spec/extensions/pg_row_ops_spec.rb +0 -61
  369. data/spec/extensions/pg_row_plugin_spec.rb +0 -60
  370. data/spec/extensions/pg_row_spec.rb +0 -363
  371. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -93
  372. data/spec/extensions/pg_timestamptz_spec.rb +0 -17
  373. data/spec/extensions/prepared_statements_safe_spec.rb +0 -66
  374. data/spec/extensions/prepared_statements_spec.rb +0 -177
  375. data/spec/extensions/pretty_table_spec.rb +0 -123
  376. data/spec/extensions/query_spec.rb +0 -94
  377. data/spec/extensions/rcte_tree_spec.rb +0 -381
  378. data/spec/extensions/round_timestamps_spec.rb +0 -39
  379. data/spec/extensions/s_spec.rb +0 -60
  380. data/spec/extensions/schema_caching_spec.rb +0 -64
  381. data/spec/extensions/schema_dumper_spec.rb +0 -870
  382. data/spec/extensions/select_remove_spec.rb +0 -38
  383. data/spec/extensions/sequel_4_dataset_methods_spec.rb +0 -121
  384. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  385. data/spec/extensions/serialization_spec.rb +0 -365
  386. data/spec/extensions/server_block_spec.rb +0 -97
  387. data/spec/extensions/server_logging_spec.rb +0 -45
  388. data/spec/extensions/sharding_spec.rb +0 -189
  389. data/spec/extensions/shared_caching_spec.rb +0 -151
  390. data/spec/extensions/single_table_inheritance_spec.rb +0 -347
  391. data/spec/extensions/singular_table_names_spec.rb +0 -22
  392. data/spec/extensions/skip_create_refresh_spec.rb +0 -18
  393. data/spec/extensions/spec_helper.rb +0 -63
  394. data/spec/extensions/split_array_nil_spec.rb +0 -24
  395. data/spec/extensions/split_values_spec.rb +0 -57
  396. data/spec/extensions/sql_comments_spec.rb +0 -33
  397. data/spec/extensions/sql_expr_spec.rb +0 -59
  398. data/spec/extensions/static_cache_spec.rb +0 -471
  399. data/spec/extensions/string_agg_spec.rb +0 -90
  400. data/spec/extensions/string_date_time_spec.rb +0 -95
  401. data/spec/extensions/string_stripper_spec.rb +0 -68
  402. data/spec/extensions/subclasses_spec.rb +0 -79
  403. data/spec/extensions/subset_conditions_spec.rb +0 -38
  404. data/spec/extensions/symbol_aref_refinement_spec.rb +0 -28
  405. data/spec/extensions/symbol_as_refinement_spec.rb +0 -21
  406. data/spec/extensions/synchronize_sql_spec.rb +0 -124
  407. data/spec/extensions/table_select_spec.rb +0 -83
  408. data/spec/extensions/tactical_eager_loading_spec.rb +0 -402
  409. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  410. data/spec/extensions/throw_failures_spec.rb +0 -74
  411. data/spec/extensions/timestamps_spec.rb +0 -209
  412. data/spec/extensions/to_dot_spec.rb +0 -153
  413. data/spec/extensions/touch_spec.rb +0 -226
  414. data/spec/extensions/tree_spec.rb +0 -334
  415. data/spec/extensions/typecast_on_load_spec.rb +0 -86
  416. data/spec/extensions/unlimited_update_spec.rb +0 -21
  417. data/spec/extensions/update_or_create_spec.rb +0 -83
  418. data/spec/extensions/update_primary_key_spec.rb +0 -105
  419. data/spec/extensions/update_refresh_spec.rb +0 -59
  420. data/spec/extensions/uuid_spec.rb +0 -101
  421. data/spec/extensions/validate_associated_spec.rb +0 -52
  422. data/spec/extensions/validation_class_methods_spec.rb +0 -1040
  423. data/spec/extensions/validation_contexts_spec.rb +0 -31
  424. data/spec/extensions/validation_helpers_spec.rb +0 -525
  425. data/spec/extensions/whitelist_security_spec.rb +0 -157
  426. data/spec/extensions/xml_serializer_spec.rb +0 -213
  427. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  428. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  429. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  430. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  431. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  432. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  433. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  434. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  435. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  436. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  437. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  438. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  439. data/spec/files/double_migration/001_create_sessions.rb +0 -9
  440. data/spec/files/double_migration/002_create_nodes.rb +0 -19
  441. data/spec/files/double_migration/003_3_create_users.rb +0 -4
  442. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  443. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  444. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  445. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  446. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  447. data/spec/files/empty_migration/001_create_sessions.rb +0 -9
  448. data/spec/files/empty_migration/002_create_nodes.rb +0 -0
  449. data/spec/files/empty_migration/003_3_create_users.rb +0 -4
  450. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  451. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  452. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  453. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  454. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  455. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  456. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  457. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  458. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  459. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  460. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  461. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  462. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  463. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  464. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  465. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  466. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  467. data/spec/files/reversible_migrations/006_reversible.rb +0 -10
  468. data/spec/files/reversible_migrations/007_reversible.rb +0 -10
  469. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  470. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  471. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  472. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  473. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  474. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  475. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  476. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  477. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  478. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  479. data/spec/guards_helper.rb +0 -59
  480. data/spec/integration/associations_test.rb +0 -2597
  481. data/spec/integration/database_test.rb +0 -113
  482. data/spec/integration/dataset_test.rb +0 -1981
  483. data/spec/integration/eager_loader_test.rb +0 -687
  484. data/spec/integration/migrator_test.rb +0 -262
  485. data/spec/integration/model_test.rb +0 -203
  486. data/spec/integration/plugin_test.rb +0 -2396
  487. data/spec/integration/prepared_statement_test.rb +0 -405
  488. data/spec/integration/schema_test.rb +0 -889
  489. data/spec/integration/spec_helper.rb +0 -65
  490. data/spec/integration/timezone_test.rb +0 -86
  491. data/spec/integration/transaction_test.rb +0 -603
  492. data/spec/integration/type_test.rb +0 -127
  493. data/spec/model/association_reflection_spec.rb +0 -803
  494. data/spec/model/associations_spec.rb +0 -4738
  495. data/spec/model/base_spec.rb +0 -875
  496. data/spec/model/class_dataset_methods_spec.rb +0 -146
  497. data/spec/model/dataset_methods_spec.rb +0 -198
  498. data/spec/model/eager_loading_spec.rb +0 -2377
  499. data/spec/model/hooks_spec.rb +0 -370
  500. data/spec/model/inflector_spec.rb +0 -26
  501. data/spec/model/model_spec.rb +0 -956
  502. data/spec/model/plugins_spec.rb +0 -429
  503. data/spec/model/record_spec.rb +0 -2118
  504. data/spec/model/spec_helper.rb +0 -46
  505. data/spec/model/validations_spec.rb +0 -220
  506. data/spec/model_no_assoc_spec.rb +0 -1
  507. data/spec/model_spec.rb +0 -1
  508. data/spec/plugin_spec.rb +0 -1
  509. data/spec/sequel_coverage.rb +0 -15
  510. data/spec/sequel_warning.rb +0 -4
  511. data/spec/spec_config.rb +0 -12
@@ -1,767 +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 not attempt to validate nested attributes twice for one_to_many associations when creating them" do
496
- @Artist.nested_attributes :albums
497
- validated = []
498
- @Album.class_eval do
499
- define_method(:validate) do
500
- super()
501
- validated << self
502
- end
503
- end
504
- a = @Artist.new(:name=>'Ar', :albums_attributes=>[{:name=>'Al'}])
505
- @db.sqls.must_equal []
506
- validated.length.must_equal 0
507
- a.save
508
- validated.length.must_equal 1
509
- check_sql_array("INSERT INTO artists (name) VALUES ('Ar')",
510
- ["INSERT INTO albums (artist_id, name) VALUES (1, 'Al')", "INSERT INTO albums (name, artist_id) VALUES ('Al', 1)"])
511
- end
512
-
513
- it "should not attempt to validate nested attributes twice for one_to_one associations when creating them" do
514
- @Artist.nested_attributes :first_album
515
- validated = []
516
- @Album.class_eval do
517
- define_method(:validate) do
518
- super()
519
- validated << self
520
- end
521
- end
522
- a = @Artist.new(:name=>'Ar', :first_album_attributes=>{:name=>'Al'})
523
- @db.sqls.must_equal []
524
- validated.length.must_equal 0
525
- a.save
526
- validated.length.must_equal 1
527
- check_sql_array("INSERT INTO artists (name) VALUES ('Ar')",
528
- "UPDATE albums SET artist_id = NULL WHERE (artist_id = 1)",
529
- "INSERT INTO albums (name, artist_id) VALUES ('Al', 1)")
530
- end
531
-
532
- it "should not clear reciprocal association before saving new one_to_one associated object" do
533
- @Artist.one_to_one :first_album, :clone=>:first_album, :reciprocal=>:artist
534
- @Artist.nested_attributes :first_album
535
- assoc = []
536
- @Album.class_eval do
537
- define_method(:after_save) do
538
- super()
539
- assoc << associations[:artist]
540
- end
541
- end
542
- a = @Artist.new(:name=>'Ar', :first_album_attributes=>{:name=>'Al'})
543
- @db.sqls.must_equal []
544
- assoc.must_be_empty
545
- a.save
546
- assoc.length.must_equal 1
547
- assoc.first.must_be_kind_of(@Artist)
548
- check_sql_array("INSERT INTO artists (name) VALUES ('Ar')",
549
- "UPDATE albums SET artist_id = NULL WHERE (artist_id = 1)",
550
- "INSERT INTO albums (name, artist_id) VALUES ('Al', 1)")
551
- end
552
-
553
- 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
554
- @Artist.class_eval do
555
- def validate
556
- super
557
- errors.add(:name, 'cannot be Ar') if name == 'Ar'
558
- end
559
- end
560
- a = @Album.new(:name=>'Al', :artist_attributes=>{:name=>'Ar'})
561
- @db.sqls.must_equal []
562
- proc{a.save}.must_raise(Sequel::ValidationFailed)
563
- a.errors.full_messages.must_equal ['artist name cannot be Ar']
564
- @db.sqls.must_equal []
565
- # Should preserve attributes
566
- a.artist.name.must_equal 'Ar'
567
- end
568
-
569
- it "should not attempt to validate nested attributes if the :validate=>false association option is used" do
570
- @Album.many_to_one :artist, :class=>@Artist, :validate=>false, :reciprocal=>nil
571
- @Album.nested_attributes :artist, :tags, :destroy=>true, :remove=>true
572
- @Artist.class_eval do
573
- def validate
574
- super
575
- errors.add(:name, 'cannot be Ar') if name == 'Ar'
576
- end
577
- end
578
- a = @Album.new(:name=>'Al', :artist_attributes=>{:name=>'Ar'})
579
- @db.sqls.must_equal []
580
- a.save
581
- check_sql_array("INSERT INTO artists (name) VALUES ('Ar')",
582
- ["INSERT INTO albums (artist_id, name) VALUES (1, 'Al')", "INSERT INTO albums (name, artist_id) VALUES ('Al', 1)"])
583
- end
584
-
585
- it "should not attempt to validate nested attributes if the :validate=>false option is passed to save" do
586
- @Artist.class_eval do
587
- def validate
588
- super
589
- errors.add(:name, 'cannot be Ar') if name == 'Ar'
590
- end
591
- end
592
- a = @Album.new(:name=>'Al', :artist_attributes=>{:name=>'Ar'})
593
- @db.sqls.must_equal []
594
- a.save(:validate=>false)
595
- check_sql_array("INSERT INTO artists (name) VALUES ('Ar')",
596
- ["INSERT INTO albums (artist_id, name) VALUES (1, 'Al')", "INSERT INTO albums (name, artist_id) VALUES ('Al', 1)"])
597
- end
598
-
599
- it "should not accept nested attributes unless explicitly specified" do
600
- @Artist.many_to_many :tags, :class=>@Tag, :left_key=>:album_id, :right_key=>:tag_id, :join_table=>:at
601
- proc{@Artist.create({:name=>'Ar', :tags_attributes=>[{:name=>'T'}]})}.must_raise(Sequel::MassAssignmentRestriction)
602
- @db.sqls.must_equal []
603
- end
604
-
605
- 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
606
- al = @Album.load(:id=>10, :name=>'Al')
607
- ar = @Artist.load(:id=>20, :name=>'Ar')
608
- al.associations[:artist] = ar
609
- @db.sqls.must_equal []
610
- al.update(:artist_attributes=>{:id=>'20', :name=>'Ar2'})
611
- @db.sqls.must_equal ["UPDATE artists SET name = 'Ar2' WHERE (id = 20)"]
612
- end
613
-
614
- it "should have a :limit option limiting the amount of entries" do
615
- @Album.nested_attributes :tags, :limit=>2
616
- arr = [{:name=>'T'}]
617
- proc{@Album.new({:name=>'Al', :tags_attributes=>arr*3})}.must_raise(Sequel::Error)
618
- a = @Album.new({:name=>'Al', :tags_attributes=>arr*2})
619
- @db.sqls.must_equal []
620
- a.save
621
- check_sql_array("INSERT INTO albums (name) VALUES ('Al')",
622
- "INSERT INTO tags (name) VALUES ('T')",
623
- ["INSERT INTO at (album_id, tag_id) VALUES (1, 2)", "INSERT INTO at (tag_id, album_id) VALUES (2, 1)"],
624
- "INSERT INTO tags (name) VALUES ('T')",
625
- ["INSERT INTO at (album_id, tag_id) VALUES (1, 4)", "INSERT INTO at (tag_id, album_id) VALUES (4, 1)"])
626
- end
627
-
628
- it "should accept a block that each hash gets passed to determine if it should be processed" do
629
- @Album.nested_attributes(:tags){|h| h[:name].empty?}
630
- a = @Album.new({:name=>'Al', :tags_attributes=>[{:name=>'T'}, {:name=>''}, {:name=>'T2'}]})
631
- @db.sqls.must_equal []
632
- a.save
633
- check_sql_array("INSERT INTO albums (name) VALUES ('Al')",
634
- "INSERT INTO tags (name) VALUES ('T')",
635
- ["INSERT INTO at (album_id, tag_id) VALUES (1, 2)", "INSERT INTO at (tag_id, album_id) VALUES (2, 1)"],
636
- "INSERT INTO tags (name) VALUES ('T2')",
637
- ["INSERT INTO at (album_id, tag_id) VALUES (1, 4)", "INSERT INTO at (tag_id, album_id) VALUES (4, 1)"])
638
- end
639
-
640
- it "should accept a :transform block that returns a changed attributes hash" do
641
- @Album.nested_attributes :tags, :transform=>proc{|parent, hash| hash[:name] << parent.name; hash }
642
- a = @Album.new(:name => 'Al')
643
- a.set(:tags_attributes=>[{:name=>'T'.dup}, {:name=>'T2'.dup}])
644
- @db.sqls.must_equal []
645
- a.save
646
- check_sql_array("INSERT INTO albums (name) VALUES ('Al')",
647
- "INSERT INTO tags (name) VALUES ('TAl')",
648
- ["INSERT INTO at (album_id, tag_id) VALUES (1, 2)", "INSERT INTO at (tag_id, album_id) VALUES (2, 1)"],
649
- "INSERT INTO tags (name) VALUES ('T2Al')",
650
- ["INSERT INTO at (album_id, tag_id) VALUES (1, 4)", "INSERT INTO at (tag_id, album_id) VALUES (4, 1)"])
651
- end
652
-
653
- it "should return objects created/modified in the internal methods" do
654
- @Album.nested_attributes :tags, :remove=>true, :unmatched_pk=>:ignore
655
- objs = []
656
- @Album.class_eval do
657
- define_method(:nested_attributes_create){|*a| objs << [super(*a), :create]}
658
- define_method(:nested_attributes_remove){|*a| objs << [super(*a), :remove]}
659
- define_method(:nested_attributes_update){|*a| objs << [super(*a), :update]}
660
- end
661
- a = @Album.new(:name=>'Al')
662
- a.associations[:tags] = [@Tag.load(:id=>6, :name=>'A'), @Tag.load(:id=>7, :name=>'A2')]
663
- 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}]
664
- objs.must_equal [[@Tag.load(:id=>6, :name=>'T'), :update], [@Tag.load(:id=>7, :name=>'A2'), :remove], [@Tag.new(:name=>'T3'), :create]]
665
- end
666
-
667
- it "should raise an error if updating modifies the associated objects keys" do
668
- @Artist.columns :id, :name, :artist_id
669
- @Album.columns :id, :name, :artist_id
670
- @Tag.columns :id, :name, :tag_id
671
- @Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id, :primary_key=>:artist_id
672
- @Album.many_to_one :artist, :class=>@Artist, :primary_key=>:artist_id
673
- @Album.many_to_many :tags, :class=>@Tag, :left_key=>:album_id, :right_key=>:tag_id, :join_table=>:at, :right_primary_key=>:tag_id
674
- @Artist.nested_attributes :albums, :destroy=>true, :remove=>true
675
- @Album.nested_attributes :artist, :tags, :destroy=>true, :remove=>true
676
-
677
- al = @Album.load(:id=>10, :name=>'Al', :artist_id=>25)
678
- ar = @Artist.load(:id=>20, :name=>'Ar', :artist_id=>25)
679
- t = @Tag.load(:id=>30, :name=>'T', :tag_id=>15)
680
- al.associations[:artist] = ar
681
- al.associations[:tags] = [t]
682
- ar.associations[:albums] = [al]
683
- proc{ar.set(:albums_attributes=>[{:id=>10, :name=>'Al2', :artist_id=>'3'}])}.must_raise(Sequel::Error)
684
- proc{al.set(:artist_attributes=>{:id=>20, :name=>'Ar2', :artist_id=>'3'})}.must_raise(Sequel::Error)
685
- proc{al.set(:tags_attributes=>[{:id=>30, :name=>'T2', :tag_id=>'3'}])}.must_raise(Sequel::Error)
686
- end
687
-
688
- it "should accept a :fields option and only allow modification of those fields" do
689
- @Tag.columns :id, :name, :number
690
- @Album.nested_attributes :tags, :destroy=>true, :remove=>true, :fields=>[:name]
691
-
692
- al = @Album.load(:id=>10, :name=>'Al')
693
- t = @Tag.load(:id=>30, :name=>'T', :number=>10)
694
- al.associations[:tags] = [t]
695
- al.set(:tags_attributes=>[{:id=>30, :name=>'T2'}, {:name=>'T3'}])
696
- @db.sqls.must_equal []
697
- al.save
698
- check_sql_array("UPDATE albums SET name = 'Al' WHERE (id = 10)",
699
- "UPDATE tags SET name = 'T2' WHERE (id = 30)",
700
- "INSERT INTO tags (name) VALUES ('T3')",
701
- ["INSERT INTO at (album_id, tag_id) VALUES (10, 1)", "INSERT INTO at (tag_id, album_id) VALUES (1, 10)"])
702
- al.set(:tags_attributes=>[{:id=>30, :name=>'T3', :number=>3}])
703
- al.tags.first.name.must_equal 'T3'
704
- al.tags.first.number.must_equal 10
705
- al.set(:tags_attributes=>[{:name=>'T4', :number=>3}])
706
- al.tags.last.name.must_equal 'T4'
707
- al.tags.last.number.must_be_nil
708
- end
709
-
710
- it "should accept a proc for the :fields option that accepts the associated object and returns an array of fields" do
711
- @Tag.columns :id, :name, :number
712
- @Album.nested_attributes :tags, :destroy=>true, :remove=>true, :fields=>proc{|object| object.is_a?(@Tag) ? [:name] : []}
713
-
714
- al = @Album.load(:id=>10, :name=>'Al')
715
- t = @Tag.load(:id=>30, :name=>'T', :number=>10)
716
- al.associations[:tags] = [t]
717
- al.set(:tags_attributes=>[{:id=>30, :name=>'T2'}, {:name=>'T3'}])
718
- @db.sqls.must_equal []
719
- al.save
720
- check_sql_array("UPDATE albums SET name = 'Al' WHERE (id = 10)",
721
- "UPDATE tags SET name = 'T2' WHERE (id = 30)",
722
- "INSERT INTO tags (name) VALUES ('T3')",
723
- ["INSERT INTO at (album_id, tag_id) VALUES (10, 1)", "INSERT INTO at (tag_id, album_id) VALUES (1, 10)"])
724
- al.set_nested_attributes(:tags, [{:id=>30, :name=>'T3', :number=>3}], :fields=>[:name])
725
- al.tags.first.name.must_equal 'T3'
726
- al.tags.first.number.must_equal 10
727
- al.set_nested_attributes(:tags, [{:name=>'T4', :number=>3}], :fields=>[:name])
728
- al.tags.last.name.must_equal 'T4'
729
- al.tags.last.number.must_be_nil
730
- end
731
-
732
- it "should allow per-call options via the set_nested_attributes method" do
733
- @Tag.columns :id, :name, :number
734
- @Album.nested_attributes :tags
735
-
736
- al = @Album.load(:id=>10, :name=>'Al')
737
- t = @Tag.load(:id=>30, :name=>'T', :number=>10)
738
- al.associations[:tags] = [t]
739
- al.set_nested_attributes(:tags, [{:id=>30, :name=>'T2'}, {:name=>'T3'}], :fields=>[:name])
740
- @db.sqls.must_equal []
741
- al.save
742
- check_sql_array("UPDATE albums SET name = 'Al' WHERE (id = 10)",
743
- "UPDATE tags SET name = 'T2' WHERE (id = 30)",
744
- "INSERT INTO tags (name) VALUES ('T3')",
745
- ["INSERT INTO at (album_id, tag_id) VALUES (10, 1)", "INSERT INTO at (tag_id, album_id) VALUES (1, 10)"])
746
- al.set_nested_attributes(:tags, [{:id=>30, :name=>'T3', :number=>3}], :fields=>[:name])
747
- al.tags.first.name.must_equal 'T3'
748
- al.tags.first.number.must_equal 10
749
- al.set_nested_attributes(:tags, [{:name=>'T4', :number=>3}], :fields=>[:name])
750
- al.tags.last.name.must_equal 'T4'
751
- al.tags.last.number.must_be_nil
752
- end
753
-
754
- it "should have set_nested_attributes method raise error if called with a bad association" do
755
- proc{@Album.load(:id=>10, :name=>'Al').set_nested_attributes(:tags2, [{:id=>30, :name=>'T2', :number=>3}], :fields=>[:name])}.must_raise(Sequel::Error)
756
- end
757
-
758
- it "should have set_nested_attributes method raise error if called with an association that doesn't support nested attributes" do
759
- @Tag.columns :id, :name, :number
760
- proc{@Album.load(:id=>10, :name=>'Al').set_nested_attributes(:tags, [{:id=>30, :name=>'T2', :number=>3}], :fields=>[:name])}.must_raise(Sequel::Error)
761
- end
762
-
763
- it "should not allow modifying ensted attributes after freezing" do
764
- @Artist.freeze
765
- proc{@Artist.nested_attributes :albums}.must_raise RuntimeError, TypeError
766
- end
767
- end