ibm_db 4.0.0-x86-mingw32 → 5.0.2-x86-mingw32

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 (570) hide show
  1. checksums.yaml +5 -5
  2. data/MANIFEST +14 -14
  3. data/README +208 -208
  4. data/ext/Makefile +269 -0
  5. data/ext/Makefile.nt32 +181 -181
  6. data/ext/Makefile.nt32.191 +212 -212
  7. data/ext/extconf.rb +322 -291
  8. data/ext/gil_release_version +3 -0
  9. data/ext/ibm_db.c +11879 -11887
  10. data/ext/mkmf.log +110 -0
  11. data/ext/ruby_ibm_db.h +241 -241
  12. data/ext/ruby_ibm_db_cli.c +866 -866
  13. data/ext/ruby_ibm_db_cli.h +500 -500
  14. data/ext/unicode_support_version +3 -0
  15. data/init.rb +41 -41
  16. data/lib/IBM_DB.rb +27 -27
  17. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3533 -3452
  18. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -5
  19. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  20. data/lib/mswin32/ibm_db.rb +90 -90
  21. data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
  22. data/test/active_record/connection_adapters/fake_adapter.rb +49 -49
  23. data/test/assets/example.log +1 -1
  24. data/test/assets/test.txt +1 -1
  25. data/test/cases/adapter_test.rb +351 -351
  26. data/test/cases/adapters/mysql2/active_schema_test.rb +193 -193
  27. data/test/cases/adapters/mysql2/bind_parameter_test.rb +50 -50
  28. data/test/cases/adapters/mysql2/boolean_test.rb +100 -100
  29. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +63 -63
  30. data/test/cases/adapters/mysql2/charset_collation_test.rb +54 -54
  31. data/test/cases/adapters/mysql2/connection_test.rb +210 -210
  32. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +45 -45
  33. data/test/cases/adapters/mysql2/enum_test.rb +26 -26
  34. data/test/cases/adapters/mysql2/explain_test.rb +21 -21
  35. data/test/cases/adapters/mysql2/json_test.rb +195 -195
  36. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +83 -83
  37. data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -152
  38. data/test/cases/adapters/mysql2/schema_migrations_test.rb +59 -59
  39. data/test/cases/adapters/mysql2/schema_test.rb +126 -126
  40. data/test/cases/adapters/mysql2/sp_test.rb +36 -36
  41. data/test/cases/adapters/mysql2/sql_types_test.rb +14 -14
  42. data/test/cases/adapters/mysql2/table_options_test.rb +42 -42
  43. data/test/cases/adapters/mysql2/unsigned_type_test.rb +66 -66
  44. data/test/cases/adapters/postgresql/active_schema_test.rb +98 -98
  45. data/test/cases/adapters/postgresql/array_test.rb +339 -339
  46. data/test/cases/adapters/postgresql/bit_string_test.rb +82 -82
  47. data/test/cases/adapters/postgresql/bytea_test.rb +134 -134
  48. data/test/cases/adapters/postgresql/case_insensitive_test.rb +26 -26
  49. data/test/cases/adapters/postgresql/change_schema_test.rb +38 -38
  50. data/test/cases/adapters/postgresql/cidr_test.rb +25 -25
  51. data/test/cases/adapters/postgresql/citext_test.rb +78 -78
  52. data/test/cases/adapters/postgresql/collation_test.rb +53 -53
  53. data/test/cases/adapters/postgresql/composite_test.rb +132 -132
  54. data/test/cases/adapters/postgresql/connection_test.rb +257 -257
  55. data/test/cases/adapters/postgresql/datatype_test.rb +92 -92
  56. data/test/cases/adapters/postgresql/domain_test.rb +47 -47
  57. data/test/cases/adapters/postgresql/enum_test.rb +91 -91
  58. data/test/cases/adapters/postgresql/explain_test.rb +20 -20
  59. data/test/cases/adapters/postgresql/extension_migration_test.rb +63 -63
  60. data/test/cases/adapters/postgresql/full_text_test.rb +44 -44
  61. data/test/cases/adapters/postgresql/geometric_test.rb +378 -378
  62. data/test/cases/adapters/postgresql/hstore_test.rb +382 -382
  63. data/test/cases/adapters/postgresql/infinity_test.rb +69 -69
  64. data/test/cases/adapters/postgresql/integer_test.rb +25 -25
  65. data/test/cases/adapters/postgresql/json_test.rb +237 -237
  66. data/test/cases/adapters/postgresql/ltree_test.rb +53 -53
  67. data/test/cases/adapters/postgresql/money_test.rb +96 -96
  68. data/test/cases/adapters/postgresql/network_test.rb +94 -94
  69. data/test/cases/adapters/postgresql/numbers_test.rb +49 -49
  70. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +405 -405
  71. data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -22
  72. data/test/cases/adapters/postgresql/quoting_test.rb +44 -44
  73. data/test/cases/adapters/postgresql/range_test.rb +343 -343
  74. data/test/cases/adapters/postgresql/referential_integrity_test.rb +111 -111
  75. data/test/cases/adapters/postgresql/rename_table_test.rb +34 -34
  76. data/test/cases/adapters/postgresql/schema_authorization_test.rb +119 -119
  77. data/test/cases/adapters/postgresql/schema_test.rb +597 -597
  78. data/test/cases/adapters/postgresql/serial_test.rb +154 -154
  79. data/test/cases/adapters/postgresql/statement_pool_test.rb +41 -41
  80. data/test/cases/adapters/postgresql/timestamp_test.rb +90 -90
  81. data/test/cases/adapters/postgresql/type_lookup_test.rb +33 -33
  82. data/test/cases/adapters/postgresql/utils_test.rb +62 -62
  83. data/test/cases/adapters/postgresql/uuid_test.rb +294 -294
  84. data/test/cases/adapters/postgresql/xml_test.rb +54 -54
  85. data/test/cases/adapters/sqlite3/collation_test.rb +53 -53
  86. data/test/cases/adapters/sqlite3/copy_table_test.rb +98 -98
  87. data/test/cases/adapters/sqlite3/explain_test.rb +21 -21
  88. data/test/cases/adapters/sqlite3/quoting_test.rb +101 -101
  89. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +441 -441
  90. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -24
  91. data/test/cases/adapters/sqlite3/statement_pool_test.rb +20 -20
  92. data/test/cases/aggregations_test.rb +168 -168
  93. data/test/cases/ar_schema_test.rb +146 -146
  94. data/test/cases/associations/association_scope_test.rb +16 -16
  95. data/test/cases/associations/belongs_to_associations_test.rb +1141 -1141
  96. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +41 -41
  97. data/test/cases/associations/callbacks_test.rb +190 -190
  98. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
  99. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
  100. data/test/cases/associations/eager_load_nested_include_test.rb +126 -126
  101. data/test/cases/associations/eager_singularization_test.rb +148 -148
  102. data/test/cases/associations/eager_test.rb +1514 -1514
  103. data/test/cases/associations/extension_test.rb +87 -87
  104. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1004 -1004
  105. data/test/cases/associations/has_many_associations_test.rb +2501 -2501
  106. data/test/cases/associations/has_many_through_associations_test.rb +1271 -1271
  107. data/test/cases/associations/has_one_associations_test.rb +707 -707
  108. data/test/cases/associations/has_one_through_associations_test.rb +383 -383
  109. data/test/cases/associations/inner_join_association_test.rb +139 -139
  110. data/test/cases/associations/inverse_associations_test.rb +733 -733
  111. data/test/cases/associations/join_model_test.rb +777 -777
  112. data/test/cases/associations/left_outer_join_association_test.rb +88 -88
  113. data/test/cases/associations/nested_through_associations_test.rb +579 -579
  114. data/test/cases/associations/required_test.rb +102 -102
  115. data/test/cases/associations_test.rb +385 -385
  116. data/test/cases/attribute_decorators_test.rb +126 -125
  117. data/test/cases/attribute_methods/read_test.rb +60 -60
  118. data/test/cases/attribute_methods_test.rb +1009 -1009
  119. data/test/cases/attribute_set_test.rb +270 -270
  120. data/test/cases/attribute_test.rb +246 -246
  121. data/test/cases/attributes_test.rb +253 -253
  122. data/test/cases/autosave_association_test.rb +1708 -1708
  123. data/test/cases/base_test.rb +1713 -1713
  124. data/test/cases/batches_test.rb +489 -489
  125. data/test/cases/binary_test.rb +44 -44
  126. data/test/cases/bind_parameter_test.rb +110 -110
  127. data/test/cases/cache_key_test.rb +26 -25
  128. data/test/cases/calculations_test.rb +798 -798
  129. data/test/cases/callbacks_test.rb +636 -636
  130. data/test/cases/clone_test.rb +40 -40
  131. data/test/cases/coders/json_test.rb +15 -15
  132. data/test/cases/coders/yaml_column_test.rb +63 -63
  133. data/test/cases/collection_cache_key_test.rb +115 -115
  134. data/test/cases/column_alias_test.rb +17 -17
  135. data/test/cases/column_definition_test.rb +92 -92
  136. data/test/cases/comment_test.rb +145 -143
  137. data/test/cases/connection_adapters/adapter_leasing_test.rb +56 -56
  138. data/test/cases/connection_adapters/connection_handler_test.rb +160 -160
  139. data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
  140. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +255 -255
  141. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +69 -69
  142. data/test/cases/connection_adapters/quoting_test.rb +13 -13
  143. data/test/cases/connection_adapters/schema_cache_test.rb +61 -61
  144. data/test/cases/connection_adapters/type_lookup_test.rb +118 -118
  145. data/test/cases/connection_management_test.rb +112 -112
  146. data/test/cases/connection_pool_test.rb +521 -521
  147. data/test/cases/connection_specification/resolver_test.rb +131 -131
  148. data/test/cases/core_test.rb +112 -112
  149. data/test/cases/counter_cache_test.rb +214 -214
  150. data/test/cases/custom_locking_test.rb +17 -17
  151. data/test/cases/database_statements_test.rb +34 -34
  152. data/test/cases/date_test.rb +44 -44
  153. data/test/cases/date_time_precision_test.rb +107 -106
  154. data/test/cases/date_time_test.rb +61 -61
  155. data/test/cases/defaults_test.rb +219 -218
  156. data/test/cases/dirty_test.rb +763 -763
  157. data/test/cases/disconnected_test.rb +30 -30
  158. data/test/cases/dup_test.rb +157 -157
  159. data/test/cases/enum_test.rb +444 -444
  160. data/test/cases/errors_test.rb +16 -16
  161. data/test/cases/explain_subscriber_test.rb +64 -64
  162. data/test/cases/explain_test.rb +87 -87
  163. data/test/cases/finder_respond_to_test.rb +60 -60
  164. data/test/cases/finder_test.rb +1294 -1294
  165. data/test/cases/fixture_set/file_test.rb +156 -156
  166. data/test/cases/fixtures_test.rb +988 -988
  167. data/test/cases/forbidden_attributes_protection_test.rb +165 -165
  168. data/test/cases/habtm_destroy_order_test.rb +61 -61
  169. data/test/cases/helper.rb +204 -204
  170. data/test/cases/hot_compatibility_test.rb +142 -142
  171. data/test/cases/i18n_test.rb +45 -45
  172. data/test/cases/inheritance_test.rb +606 -606
  173. data/test/cases/integration_test.rb +155 -155
  174. data/test/cases/invalid_connection_test.rb +24 -24
  175. data/test/cases/invertible_migration_test.rb +387 -387
  176. data/test/cases/json_serialization_test.rb +311 -311
  177. data/test/cases/locking_test.rb +493 -493
  178. data/test/cases/log_subscriber_test.rb +225 -225
  179. data/test/cases/migration/change_schema_test.rb +458 -458
  180. data/test/cases/migration/change_table_test.rb +256 -256
  181. data/test/cases/migration/column_attributes_test.rb +176 -176
  182. data/test/cases/migration/column_positioning_test.rb +56 -56
  183. data/test/cases/migration/columns_test.rb +310 -310
  184. data/test/cases/migration/command_recorder_test.rb +350 -350
  185. data/test/cases/migration/compatibility_test.rb +118 -118
  186. data/test/cases/migration/create_join_table_test.rb +157 -157
  187. data/test/cases/migration/foreign_key_test.rb +362 -360
  188. data/test/cases/migration/helper.rb +39 -39
  189. data/test/cases/migration/index_test.rb +218 -218
  190. data/test/cases/migration/logger_test.rb +36 -36
  191. data/test/cases/migration/pending_migrations_test.rb +52 -52
  192. data/test/cases/migration/references_foreign_key_test.rb +221 -216
  193. data/test/cases/migration/references_index_test.rb +101 -101
  194. data/test/cases/migration/references_statements_test.rb +136 -136
  195. data/test/cases/migration/rename_table_test.rb +93 -93
  196. data/test/cases/migration_test.rb +1157 -1157
  197. data/test/cases/migrator_test.rb +471 -470
  198. data/test/cases/mixin_test.rb +68 -68
  199. data/test/cases/modules_test.rb +172 -172
  200. data/test/cases/multiparameter_attributes_test.rb +372 -372
  201. data/test/cases/multiple_db_test.rb +122 -122
  202. data/test/cases/nested_attributes_test.rb +1098 -1098
  203. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
  204. data/test/cases/persistence_test.rb +1001 -1001
  205. data/test/cases/pooled_connections_test.rb +81 -81
  206. data/test/cases/primary_keys_test.rb +376 -376
  207. data/test/cases/query_cache_test.rb +446 -446
  208. data/test/cases/quoting_test.rb +202 -202
  209. data/test/cases/readonly_test.rb +119 -119
  210. data/test/cases/reaper_test.rb +85 -85
  211. data/test/cases/reflection_test.rb +509 -509
  212. data/test/cases/relation/delegation_test.rb +63 -63
  213. data/test/cases/relation/merging_test.rb +157 -157
  214. data/test/cases/relation/mutation_test.rb +183 -183
  215. data/test/cases/relation/or_test.rb +92 -92
  216. data/test/cases/relation/predicate_builder_test.rb +16 -16
  217. data/test/cases/relation/record_fetch_warning_test.rb +40 -40
  218. data/test/cases/relation/where_chain_test.rb +105 -105
  219. data/test/cases/relation/where_clause_test.rb +182 -182
  220. data/test/cases/relation/where_test.rb +322 -322
  221. data/test/cases/relation_test.rb +328 -328
  222. data/test/cases/relations_test.rb +2026 -2026
  223. data/test/cases/reload_models_test.rb +22 -22
  224. data/test/cases/result_test.rb +90 -90
  225. data/test/cases/sanitize_test.rb +176 -176
  226. data/test/cases/schema_dumper_test.rb +457 -457
  227. data/test/cases/schema_loading_test.rb +52 -52
  228. data/test/cases/scoping/default_scoping_test.rb +528 -528
  229. data/test/cases/scoping/named_scoping_test.rb +561 -561
  230. data/test/cases/scoping/relation_scoping_test.rb +400 -400
  231. data/test/cases/secure_token_test.rb +32 -32
  232. data/test/cases/serialization_test.rb +104 -104
  233. data/test/cases/serialized_attribute_test.rb +364 -364
  234. data/test/cases/statement_cache_test.rb +136 -136
  235. data/test/cases/store_test.rb +195 -195
  236. data/test/cases/suppressor_test.rb +63 -63
  237. data/test/cases/tasks/database_tasks_test.rb +462 -462
  238. data/test/cases/tasks/mysql_rake_test.rb +345 -345
  239. data/test/cases/tasks/postgresql_rake_test.rb +304 -304
  240. data/test/cases/tasks/sqlite_rake_test.rb +220 -220
  241. data/test/cases/test_case.rb +131 -131
  242. data/test/cases/test_fixtures_test.rb +36 -36
  243. data/test/cases/time_precision_test.rb +103 -102
  244. data/test/cases/timestamp_test.rb +501 -501
  245. data/test/cases/touch_later_test.rb +121 -121
  246. data/test/cases/transaction_callbacks_test.rb +518 -518
  247. data/test/cases/transaction_isolation_test.rb +106 -106
  248. data/test/cases/transactions_test.rb +835 -834
  249. data/test/cases/type/adapter_specific_registry_test.rb +133 -133
  250. data/test/cases/type/date_time_test.rb +14 -14
  251. data/test/cases/type/integer_test.rb +27 -27
  252. data/test/cases/type/string_test.rb +22 -22
  253. data/test/cases/type/type_map_test.rb +177 -177
  254. data/test/cases/type_test.rb +39 -39
  255. data/test/cases/types_test.rb +24 -24
  256. data/test/cases/unconnected_test.rb +33 -33
  257. data/test/cases/validations/absence_validation_test.rb +73 -73
  258. data/test/cases/validations/association_validation_test.rb +97 -97
  259. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
  260. data/test/cases/validations/i18n_validation_test.rb +86 -86
  261. data/test/cases/validations/length_validation_test.rb +79 -79
  262. data/test/cases/validations/presence_validation_test.rb +103 -103
  263. data/test/cases/validations/uniqueness_validation_test.rb +548 -548
  264. data/test/cases/validations_repair_helper.rb +19 -19
  265. data/test/cases/validations_test.rb +194 -194
  266. data/test/cases/view_test.rb +216 -216
  267. data/test/cases/yaml_serialization_test.rb +121 -121
  268. data/test/config.example.yml +97 -97
  269. data/test/config.rb +5 -5
  270. data/test/connections/native_ibm_db/connection.rb +44 -0
  271. data/test/fixtures/accounts.yml +29 -29
  272. data/test/fixtures/admin/accounts.yml +2 -2
  273. data/test/fixtures/admin/users.yml +10 -10
  274. data/test/fixtures/author_addresses.yml +17 -17
  275. data/test/fixtures/author_favorites.yml +3 -3
  276. data/test/fixtures/authors.yml +23 -23
  277. data/test/fixtures/bad_posts.yml +9 -9
  278. data/test/fixtures/binaries.yml +133 -133
  279. data/test/fixtures/books.yml +31 -31
  280. data/test/fixtures/bulbs.yml +5 -5
  281. data/test/fixtures/cars.yml +9 -9
  282. data/test/fixtures/categories.yml +19 -19
  283. data/test/fixtures/categories/special_categories.yml +9 -9
  284. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -4
  285. data/test/fixtures/categories_ordered.yml +7 -7
  286. data/test/fixtures/categories_posts.yml +31 -31
  287. data/test/fixtures/categorizations.yml +23 -23
  288. data/test/fixtures/clubs.yml +8 -8
  289. data/test/fixtures/collections.yml +3 -3
  290. data/test/fixtures/colleges.yml +3 -3
  291. data/test/fixtures/comments.yml +65 -65
  292. data/test/fixtures/companies.yml +67 -67
  293. data/test/fixtures/computers.yml +10 -10
  294. data/test/fixtures/content.yml +3 -3
  295. data/test/fixtures/content_positions.yml +3 -3
  296. data/test/fixtures/courses.yml +8 -8
  297. data/test/fixtures/customers.yml +25 -25
  298. data/test/fixtures/dashboards.yml +6 -6
  299. data/test/fixtures/dead_parrots.yml +5 -5
  300. data/test/fixtures/developers.yml +22 -22
  301. data/test/fixtures/developers_projects.yml +16 -16
  302. data/test/fixtures/dog_lovers.yml +7 -7
  303. data/test/fixtures/dogs.yml +4 -4
  304. data/test/fixtures/doubloons.yml +3 -3
  305. data/test/fixtures/edges.yml +5 -5
  306. data/test/fixtures/entrants.yml +14 -14
  307. data/test/fixtures/essays.yml +6 -6
  308. data/test/fixtures/faces.yml +11 -11
  309. data/test/fixtures/fk_test_has_fk.yml +3 -3
  310. data/test/fixtures/fk_test_has_pk.yml +1 -1
  311. data/test/fixtures/friendships.yml +4 -4
  312. data/test/fixtures/funny_jokes.yml +10 -10
  313. data/test/fixtures/interests.yml +33 -33
  314. data/test/fixtures/items.yml +3 -3
  315. data/test/fixtures/jobs.yml +7 -7
  316. data/test/fixtures/legacy_things.yml +3 -3
  317. data/test/fixtures/live_parrots.yml +4 -4
  318. data/test/fixtures/mateys.yml +4 -4
  319. data/test/fixtures/member_details.yml +8 -8
  320. data/test/fixtures/member_types.yml +6 -6
  321. data/test/fixtures/members.yml +11 -11
  322. data/test/fixtures/memberships.yml +34 -34
  323. data/test/fixtures/men.yml +5 -5
  324. data/test/fixtures/minimalistics.yml +2 -2
  325. data/test/fixtures/minivans.yml +5 -5
  326. data/test/fixtures/mixed_case_monkeys.yml +6 -6
  327. data/test/fixtures/mixins.yml +29 -29
  328. data/test/fixtures/movies.yml +7 -7
  329. data/test/fixtures/naked/yml/accounts.yml +1 -1
  330. data/test/fixtures/naked/yml/companies.yml +1 -1
  331. data/test/fixtures/naked/yml/courses.yml +1 -1
  332. data/test/fixtures/naked/yml/parrots.yml +2 -2
  333. data/test/fixtures/naked/yml/trees.yml +3 -3
  334. data/test/fixtures/nodes.yml +29 -29
  335. data/test/fixtures/organizations.yml +5 -5
  336. data/test/fixtures/other_comments.yml +6 -6
  337. data/test/fixtures/other_dogs.yml +2 -2
  338. data/test/fixtures/other_posts.yml +7 -7
  339. data/test/fixtures/other_topics.yml +42 -42
  340. data/test/fixtures/owners.yml +9 -9
  341. data/test/fixtures/parrots.yml +27 -27
  342. data/test/fixtures/parrots_pirates.yml +7 -7
  343. data/test/fixtures/people.yml +24 -24
  344. data/test/fixtures/peoples_treasures.yml +3 -3
  345. data/test/fixtures/pets.yml +19 -19
  346. data/test/fixtures/pirates.yml +12 -15
  347. data/test/fixtures/posts.yml +80 -80
  348. data/test/fixtures/price_estimates.yml +16 -16
  349. data/test/fixtures/products.yml +4 -4
  350. data/test/fixtures/projects.yml +7 -7
  351. data/test/fixtures/ratings.yml +14 -14
  352. data/test/fixtures/readers.yml +11 -11
  353. data/test/fixtures/references.yml +17 -17
  354. data/test/fixtures/reserved_words/distinct.yml +5 -5
  355. data/test/fixtures/reserved_words/distinct_select.yml +11 -11
  356. data/test/fixtures/reserved_words/group.yml +14 -14
  357. data/test/fixtures/reserved_words/select.yml +8 -8
  358. data/test/fixtures/reserved_words/values.yml +7 -7
  359. data/test/fixtures/ships.yml +6 -6
  360. data/test/fixtures/speedometers.yml +8 -8
  361. data/test/fixtures/sponsors.yml +12 -12
  362. data/test/fixtures/string_key_objects.yml +7 -7
  363. data/test/fixtures/subscribers.yml +10 -10
  364. data/test/fixtures/subscriptions.yml +12 -12
  365. data/test/fixtures/taggings.yml +78 -78
  366. data/test/fixtures/tags.yml +11 -11
  367. data/test/fixtures/tasks.yml +7 -7
  368. data/test/fixtures/teapots.yml +3 -3
  369. data/test/fixtures/to_be_linked/accounts.yml +2 -2
  370. data/test/fixtures/to_be_linked/users.yml +10 -10
  371. data/test/fixtures/topics.yml +49 -49
  372. data/test/fixtures/toys.yml +14 -14
  373. data/test/fixtures/traffic_lights.yml +9 -9
  374. data/test/fixtures/treasures.yml +10 -10
  375. data/test/fixtures/trees.yml +3 -3
  376. data/test/fixtures/uuid_children.yml +3 -3
  377. data/test/fixtures/uuid_parents.yml +2 -2
  378. data/test/fixtures/variants.yml +4 -4
  379. data/test/fixtures/vegetables.yml +19 -19
  380. data/test/fixtures/vertices.yml +3 -3
  381. data/test/fixtures/warehouse_things.yml +2 -2
  382. data/test/fixtures/zines.yml +5 -5
  383. data/test/migrations/10_urban/9_add_expressions.rb +11 -11
  384. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -15
  385. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -12
  386. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -9
  387. data/test/migrations/missing/1_people_have_last_names.rb +9 -9
  388. data/test/migrations/missing/3_we_need_reminders.rb +12 -12
  389. data/test/migrations/missing/4_innocent_jointable.rb +12 -12
  390. data/test/migrations/rename/1_we_need_things.rb +11 -11
  391. data/test/migrations/rename/2_rename_things.rb +9 -9
  392. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -9
  393. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -9
  394. data/test/migrations/to_copy2/1_create_articles.rb +7 -7
  395. data/test/migrations/to_copy2/2_create_comments.rb +7 -7
  396. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -9
  397. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -9
  398. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -9
  399. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -7
  400. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -7
  401. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -9
  402. data/test/migrations/valid/2_we_need_reminders.rb +12 -12
  403. data/test/migrations/valid/3_innocent_jointable.rb +12 -12
  404. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -9
  405. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -12
  406. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -12
  407. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -9
  408. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -12
  409. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -12
  410. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -8
  411. data/test/models/admin.rb +5 -5
  412. data/test/models/admin/account.rb +3 -3
  413. data/test/models/admin/user.rb +40 -40
  414. data/test/models/aircraft.rb +5 -5
  415. data/test/models/arunit2_model.rb +3 -3
  416. data/test/models/author.rb +209 -209
  417. data/test/models/auto_id.rb +4 -4
  418. data/test/models/autoloadable/extra_firm.rb +2 -2
  419. data/test/models/binary.rb +2 -2
  420. data/test/models/bird.rb +12 -12
  421. data/test/models/book.rb +23 -23
  422. data/test/models/boolean.rb +2 -2
  423. data/test/models/bulb.rb +52 -52
  424. data/test/models/cake_designer.rb +3 -3
  425. data/test/models/car.rb +29 -29
  426. data/test/models/carrier.rb +2 -2
  427. data/test/models/cat.rb +10 -10
  428. data/test/models/categorization.rb +19 -19
  429. data/test/models/category.rb +35 -35
  430. data/test/models/chef.rb +8 -8
  431. data/test/models/citation.rb +3 -3
  432. data/test/models/club.rb +25 -25
  433. data/test/models/college.rb +10 -10
  434. data/test/models/column.rb +3 -3
  435. data/test/models/column_name.rb +3 -3
  436. data/test/models/comment.rb +76 -76
  437. data/test/models/company.rb +230 -230
  438. data/test/models/company_in_module.rb +98 -98
  439. data/test/models/computer.rb +3 -3
  440. data/test/models/contact.rb +41 -41
  441. data/test/models/content.rb +40 -40
  442. data/test/models/contract.rb +20 -20
  443. data/test/models/country.rb +7 -7
  444. data/test/models/course.rb +6 -6
  445. data/test/models/customer.rb +83 -83
  446. data/test/models/customer_carrier.rb +14 -14
  447. data/test/models/dashboard.rb +3 -3
  448. data/test/models/default.rb +2 -2
  449. data/test/models/department.rb +4 -4
  450. data/test/models/developer.rb +274 -274
  451. data/test/models/dog.rb +5 -5
  452. data/test/models/dog_lover.rb +5 -5
  453. data/test/models/doubloon.rb +12 -12
  454. data/test/models/drink_designer.rb +3 -3
  455. data/test/models/edge.rb +5 -5
  456. data/test/models/electron.rb +5 -5
  457. data/test/models/engine.rb +4 -4
  458. data/test/models/entrant.rb +3 -3
  459. data/test/models/essay.rb +5 -5
  460. data/test/models/event.rb +3 -3
  461. data/test/models/eye.rb +37 -37
  462. data/test/models/face.rb +9 -9
  463. data/test/models/friendship.rb +6 -6
  464. data/test/models/guid.rb +2 -2
  465. data/test/models/guitar.rb +4 -4
  466. data/test/models/hotel.rb +11 -11
  467. data/test/models/image.rb +3 -3
  468. data/test/models/interest.rb +5 -5
  469. data/test/models/invoice.rb +4 -4
  470. data/test/models/item.rb +7 -7
  471. data/test/models/job.rb +7 -7
  472. data/test/models/joke.rb +7 -7
  473. data/test/models/keyboard.rb +3 -3
  474. data/test/models/legacy_thing.rb +3 -3
  475. data/test/models/lesson.rb +11 -11
  476. data/test/models/line_item.rb +3 -3
  477. data/test/models/liquid.rb +4 -4
  478. data/test/models/man.rb +11 -11
  479. data/test/models/matey.rb +4 -4
  480. data/test/models/member.rb +42 -42
  481. data/test/models/member_detail.rb +8 -8
  482. data/test/models/member_type.rb +3 -3
  483. data/test/models/membership.rb +35 -35
  484. data/test/models/mentor.rb +2 -2
  485. data/test/models/minimalistic.rb +2 -2
  486. data/test/models/minivan.rb +9 -9
  487. data/test/models/mixed_case_monkey.rb +3 -3
  488. data/test/models/mocktail_designer.rb +2 -2
  489. data/test/models/molecule.rb +6 -6
  490. data/test/models/movie.rb +5 -5
  491. data/test/models/node.rb +5 -5
  492. data/test/models/non_primary_key.rb +2 -2
  493. data/test/models/notification.rb +3 -3
  494. data/test/models/order.rb +4 -4
  495. data/test/models/organization.rb +14 -14
  496. data/test/models/other_dog.rb +5 -5
  497. data/test/models/owner.rb +37 -37
  498. data/test/models/parrot.rb +28 -28
  499. data/test/models/person.rb +142 -142
  500. data/test/models/personal_legacy_thing.rb +4 -4
  501. data/test/models/pet.rb +18 -18
  502. data/test/models/pet_treasure.rb +6 -6
  503. data/test/models/pirate.rb +92 -92
  504. data/test/models/possession.rb +3 -3
  505. data/test/models/post.rb +273 -273
  506. data/test/models/price_estimate.rb +4 -4
  507. data/test/models/professor.rb +5 -5
  508. data/test/models/project.rb +40 -40
  509. data/test/models/publisher.rb +2 -2
  510. data/test/models/publisher/article.rb +4 -4
  511. data/test/models/publisher/magazine.rb +3 -3
  512. data/test/models/rating.rb +4 -4
  513. data/test/models/reader.rb +23 -23
  514. data/test/models/recipe.rb +3 -3
  515. data/test/models/record.rb +2 -2
  516. data/test/models/reference.rb +22 -22
  517. data/test/models/reply.rb +61 -61
  518. data/test/models/ship.rb +39 -39
  519. data/test/models/ship_part.rb +8 -8
  520. data/test/models/shop.rb +17 -17
  521. data/test/models/shop_account.rb +6 -6
  522. data/test/models/speedometer.rb +6 -6
  523. data/test/models/sponsor.rb +7 -7
  524. data/test/models/string_key_object.rb +3 -3
  525. data/test/models/student.rb +4 -4
  526. data/test/models/subject.rb +16 -16
  527. data/test/models/subscriber.rb +8 -8
  528. data/test/models/subscription.rb +4 -4
  529. data/test/models/tag.rb +13 -13
  530. data/test/models/tagging.rb +13 -13
  531. data/test/models/task.rb +5 -5
  532. data/test/models/topic.rb +118 -118
  533. data/test/models/toy.rb +6 -6
  534. data/test/models/traffic_light.rb +4 -4
  535. data/test/models/treasure.rb +14 -14
  536. data/test/models/treaty.rb +7 -7
  537. data/test/models/tree.rb +3 -3
  538. data/test/models/tuning_peg.rb +4 -4
  539. data/test/models/tyre.rb +11 -11
  540. data/test/models/user.rb +14 -14
  541. data/test/models/uuid_child.rb +3 -3
  542. data/test/models/uuid_item.rb +6 -6
  543. data/test/models/uuid_parent.rb +3 -3
  544. data/test/models/vegetables.rb +24 -24
  545. data/test/models/vehicle.rb +6 -6
  546. data/test/models/vertex.rb +9 -9
  547. data/test/models/warehouse_thing.rb +5 -5
  548. data/test/models/wheel.rb +3 -3
  549. data/test/models/without_table.rb +3 -3
  550. data/test/models/zine.rb +3 -3
  551. data/test/schema/i5/ibm_db_specific_schema.rb +137 -0
  552. data/test/schema/ids/ibm_db_specific_schema.rb +140 -0
  553. data/test/schema/luw/ibm_db_specific_schema.rb +137 -0
  554. data/test/schema/mysql2_specific_schema.rb +68 -68
  555. data/test/schema/oracle_specific_schema.rb +40 -40
  556. data/test/schema/postgresql_specific_schema.rb +114 -114
  557. data/test/schema/schema.rb +1057 -1057
  558. data/test/schema/schema.rb.original +1057 -1057
  559. data/test/schema/sqlite_specific_schema.rb +18 -18
  560. data/test/schema/zOS/ibm_db_specific_schema.rb +208 -0
  561. data/test/support/config.rb +43 -43
  562. data/test/support/connection.rb +23 -23
  563. data/test/support/connection_helper.rb +14 -14
  564. data/test/support/ddl_helper.rb +8 -8
  565. data/test/support/schema_dumping_helper.rb +20 -20
  566. data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -22
  567. data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -182
  568. metadata +24 -13
  569. data/test/fixtures/author_addresses.original +0 -11
  570. data/test/fixtures/authors.original +0 -17
@@ -1,103 +1,103 @@
1
- require "cases/helper"
2
- require 'models/man'
3
- require 'models/face'
4
- require 'models/interest'
5
- require 'models/speedometer'
6
- require 'models/dashboard'
7
-
8
- class PresenceValidationTest < ActiveRecord::TestCase
9
- class Boy < Man; end
10
-
11
- repair_validations(Boy)
12
-
13
- def test_validates_presence_of_non_association
14
- Boy.validates_presence_of(:name)
15
- b = Boy.new
16
- assert b.invalid?
17
-
18
- b.name = "Alex"
19
- assert b.valid?
20
- end
21
-
22
- def test_validates_presence_of_has_one
23
- Boy.validates_presence_of(:face)
24
- b = Boy.new
25
- assert b.invalid?, "should not be valid if has_one association missing"
26
- assert_equal 1, b.errors[:face].size, "validates_presence_of should only add one error"
27
- end
28
-
29
- def test_validates_presence_of_has_one_marked_for_destruction
30
- Boy.validates_presence_of(:face)
31
- b = Boy.new
32
- f = Face.new
33
- b.face = f
34
- assert b.valid?
35
-
36
- f.mark_for_destruction
37
- assert b.invalid?
38
- end
39
-
40
- def test_validates_presence_of_has_many_marked_for_destruction
41
- Boy.validates_presence_of(:interests)
42
- b = Boy.new
43
- b.interests << [i1 = Interest.new, i2 = Interest.new]
44
- assert b.valid?
45
-
46
- i1.mark_for_destruction
47
- assert b.valid?
48
-
49
- i2.mark_for_destruction
50
- assert b.invalid?
51
- end
52
-
53
- def test_validates_presence_doesnt_convert_to_array
54
- speedometer = Class.new(Speedometer)
55
- speedometer.validates_presence_of :dashboard
56
-
57
- dash = Dashboard.new
58
-
59
- # dashboard has to_a method
60
- def dash.to_a; ['(/)', '(\)']; end
61
-
62
- s = speedometer.new
63
- s.dashboard = dash
64
-
65
- assert_nothing_raised { s.valid? }
66
- end
67
-
68
- def test_validates_presence_of_virtual_attribute_on_model
69
- repair_validations(Interest) do
70
- Interest.send(:attr_accessor, :abbreviation)
71
- Interest.validates_presence_of(:topic)
72
- Interest.validates_presence_of(:abbreviation)
73
-
74
- interest = Interest.create!(topic: 'Thought Leadering', abbreviation: 'tl')
75
- assert interest.valid?
76
-
77
- interest.abbreviation = ''
78
-
79
- assert interest.invalid?
80
- end
81
- end
82
-
83
- def test_validations_run_on_persisted_record
84
- repair_validations(Interest) do
85
- interest = Interest.new
86
- interest.save!
87
- assert_predicate interest, :valid?
88
-
89
- Interest.validates_presence_of(:topic)
90
-
91
- assert_not_predicate interest, :valid?
92
- end
93
- end
94
-
95
- def test_validates_presence_with_on_context
96
- repair_validations(Interest) do
97
- Interest.validates_presence_of(:topic, on: :required_name)
98
- interest = Interest.new
99
- interest.save!
100
- assert_not interest.valid?(:required_name)
101
- end
102
- end
103
- end
1
+ require "cases/helper"
2
+ require 'models/man'
3
+ require 'models/face'
4
+ require 'models/interest'
5
+ require 'models/speedometer'
6
+ require 'models/dashboard'
7
+
8
+ class PresenceValidationTest < ActiveRecord::TestCase
9
+ class Boy < Man; end
10
+
11
+ repair_validations(Boy)
12
+
13
+ def test_validates_presence_of_non_association
14
+ Boy.validates_presence_of(:name)
15
+ b = Boy.new
16
+ assert b.invalid?
17
+
18
+ b.name = "Alex"
19
+ assert b.valid?
20
+ end
21
+
22
+ def test_validates_presence_of_has_one
23
+ Boy.validates_presence_of(:face)
24
+ b = Boy.new
25
+ assert b.invalid?, "should not be valid if has_one association missing"
26
+ assert_equal 1, b.errors[:face].size, "validates_presence_of should only add one error"
27
+ end
28
+
29
+ def test_validates_presence_of_has_one_marked_for_destruction
30
+ Boy.validates_presence_of(:face)
31
+ b = Boy.new
32
+ f = Face.new
33
+ b.face = f
34
+ assert b.valid?
35
+
36
+ f.mark_for_destruction
37
+ assert b.invalid?
38
+ end
39
+
40
+ def test_validates_presence_of_has_many_marked_for_destruction
41
+ Boy.validates_presence_of(:interests)
42
+ b = Boy.new
43
+ b.interests << [i1 = Interest.new, i2 = Interest.new]
44
+ assert b.valid?
45
+
46
+ i1.mark_for_destruction
47
+ assert b.valid?
48
+
49
+ i2.mark_for_destruction
50
+ assert b.invalid?
51
+ end
52
+
53
+ def test_validates_presence_doesnt_convert_to_array
54
+ speedometer = Class.new(Speedometer)
55
+ speedometer.validates_presence_of :dashboard
56
+
57
+ dash = Dashboard.new
58
+
59
+ # dashboard has to_a method
60
+ def dash.to_a; ['(/)', '(\)']; end
61
+
62
+ s = speedometer.new
63
+ s.dashboard = dash
64
+
65
+ assert_nothing_raised { s.valid? }
66
+ end
67
+
68
+ def test_validates_presence_of_virtual_attribute_on_model
69
+ repair_validations(Interest) do
70
+ Interest.send(:attr_accessor, :abbreviation)
71
+ Interest.validates_presence_of(:topic)
72
+ Interest.validates_presence_of(:abbreviation)
73
+
74
+ interest = Interest.create!(topic: 'Thought Leadering', abbreviation: 'tl')
75
+ assert interest.valid?
76
+
77
+ interest.abbreviation = ''
78
+
79
+ assert interest.invalid?
80
+ end
81
+ end
82
+
83
+ def test_validations_run_on_persisted_record
84
+ repair_validations(Interest) do
85
+ interest = Interest.new
86
+ interest.save!
87
+ assert_predicate interest, :valid?
88
+
89
+ Interest.validates_presence_of(:topic)
90
+
91
+ assert_not_predicate interest, :valid?
92
+ end
93
+ end
94
+
95
+ def test_validates_presence_with_on_context
96
+ repair_validations(Interest) do
97
+ Interest.validates_presence_of(:topic, on: :required_name)
98
+ interest = Interest.new
99
+ interest.save!
100
+ assert_not interest.valid?(:required_name)
101
+ end
102
+ end
103
+ end
@@ -1,548 +1,548 @@
1
- require "cases/helper"
2
- require "models/topic"
3
- require "models/reply"
4
- require "models/warehouse_thing"
5
- require "models/guid"
6
- require "models/event"
7
- require "models/dashboard"
8
- require "models/uuid_item"
9
- require "models/author"
10
- require "models/person"
11
- require "models/essay"
12
-
13
- class Wizard < ActiveRecord::Base
14
- self.abstract_class = true
15
-
16
- validates_uniqueness_of :name
17
- end
18
-
19
- class IneptWizard < Wizard
20
- validates_uniqueness_of :city
21
- end
22
-
23
- class Conjurer < IneptWizard
24
- end
25
-
26
- class Thaumaturgist < IneptWizard
27
- end
28
-
29
- class ReplyTitle; end
30
-
31
- class ReplyWithTitleObject < Reply
32
- validates_uniqueness_of :content, :scope => :title
33
-
34
- def title; ReplyTitle.new; end
35
- end
36
-
37
- class TopicWithUniqEvent < Topic
38
- belongs_to :event, foreign_key: :parent_id
39
- validates :event, uniqueness: true
40
- end
41
-
42
- class BigIntTest < ActiveRecord::Base
43
- INT_MAX_VALUE = 2147483647
44
- self.table_name = 'cars'
45
- validates :engines_count, uniqueness: true, inclusion: { in: 0..INT_MAX_VALUE }
46
- end
47
-
48
- class BigIntReverseTest < ActiveRecord::Base
49
- INT_MAX_VALUE = 2147483647
50
- self.table_name = 'cars'
51
- validates :engines_count, inclusion: { in: 0..INT_MAX_VALUE }
52
- validates :engines_count, uniqueness: true
53
- end
54
-
55
- class CoolTopic < Topic
56
- validates_uniqueness_of :id
57
- end
58
-
59
- class TopicWithAfterCreate < Topic
60
- after_create :set_author
61
-
62
- def set_author
63
- update_attributes!(:author_name => "#{title} #{id}")
64
- end
65
- end
66
-
67
- class UniquenessValidationTest < ActiveRecord::TestCase
68
- INT_MAX_VALUE = 2147483647
69
-
70
- fixtures :topics, 'warehouse_things'
71
-
72
- repair_validations(Topic, Reply)
73
-
74
- def test_validate_uniqueness
75
- Topic.validates_uniqueness_of(:title)
76
-
77
- t = Topic.new("title" => "I'm uniqué!")
78
- assert t.save, "Should save t as unique"
79
-
80
- t.content = "Remaining unique"
81
- assert t.save, "Should still save t as unique"
82
-
83
- t2 = Topic.new("title" => "I'm uniqué!")
84
- assert !t2.valid?, "Shouldn't be valid"
85
- assert !t2.save, "Shouldn't save t2 as unique"
86
- assert_equal ["has already been taken"], t2.errors[:title]
87
-
88
- t2.title = "Now I am really also unique"
89
- assert t2.save, "Should now save t2 as unique"
90
- end
91
-
92
- def test_validate_uniqueness_with_alias_attribute
93
- Topic.alias_attribute :new_title, :title
94
- Topic.validates_uniqueness_of(:new_title)
95
-
96
- topic = Topic.new(new_title: 'abc')
97
- assert topic.valid?
98
- end
99
-
100
- def test_validates_uniqueness_with_nil_value
101
- Topic.validates_uniqueness_of(:title)
102
-
103
- t = Topic.new("title" => nil)
104
- assert t.save, "Should save t as unique"
105
-
106
- t2 = Topic.new("title" => nil)
107
- assert !t2.valid?, "Shouldn't be valid"
108
- assert !t2.save, "Shouldn't save t2 as unique"
109
- assert_equal ["has already been taken"], t2.errors[:title]
110
- end
111
-
112
- def test_validates_uniqueness_with_validates
113
- Topic.validates :title, :uniqueness => true
114
- Topic.create!('title' => 'abc')
115
-
116
- t2 = Topic.new('title' => 'abc')
117
- assert !t2.valid?
118
- assert t2.errors[:title]
119
- end
120
-
121
- def test_validate_uniqueness_when_integer_out_of_range
122
- entry = BigIntTest.create(engines_count: INT_MAX_VALUE + 1)
123
- assert_equal entry.errors[:engines_count], ['is not included in the list']
124
- end
125
-
126
- def test_validate_uniqueness_when_integer_out_of_range_show_order_does_not_matter
127
- entry = BigIntReverseTest.create(engines_count: INT_MAX_VALUE + 1)
128
- assert_equal entry.errors[:engines_count], ['is not included in the list']
129
- end
130
-
131
- def test_validates_uniqueness_with_newline_chars
132
- Topic.validates_uniqueness_of(:title, :case_sensitive => false)
133
-
134
- t = Topic.new("title" => "new\nline")
135
- assert t.save, "Should save t as unique"
136
- end
137
-
138
- def test_validate_uniqueness_with_scope
139
- Reply.validates_uniqueness_of(:content, :scope => "parent_id")
140
-
141
- t = Topic.create("title" => "I'm unique!")
142
-
143
- r1 = t.replies.create "title" => "r1", "content" => "hello world"
144
- assert r1.valid?, "Saving r1"
145
-
146
- r2 = t.replies.create "title" => "r2", "content" => "hello world"
147
- assert !r2.valid?, "Saving r2 first time"
148
-
149
- r2.content = "something else"
150
- assert r2.save, "Saving r2 second time"
151
-
152
- t2 = Topic.create("title" => "I'm unique too!")
153
- r3 = t2.replies.create "title" => "r3", "content" => "hello world"
154
- assert r3.valid?, "Saving r3"
155
- end
156
-
157
- def test_validate_uniqueness_with_object_scope
158
- Reply.validates_uniqueness_of(:content, :scope => :topic)
159
-
160
- t = Topic.create("title" => "I'm unique!")
161
-
162
- r1 = t.replies.create "title" => "r1", "content" => "hello world"
163
- assert r1.valid?, "Saving r1"
164
-
165
- r2 = t.replies.create "title" => "r2", "content" => "hello world"
166
- assert !r2.valid?, "Saving r2 first time"
167
- end
168
-
169
- def test_validate_uniqueness_with_polymorphic_object_scope
170
- Essay.validates_uniqueness_of(:name, scope: :writer)
171
-
172
- a = Author.create(name: "Sergey")
173
- p = Person.create(first_name: "Sergey")
174
-
175
- e1 = a.essays.create(name: "Essay")
176
- assert e1.valid?, "Saving e1"
177
-
178
- e2 = p.essays.create(name: "Essay")
179
- assert e2.valid?, "Saving e2"
180
- end
181
-
182
- def test_validate_uniqueness_with_composed_attribute_scope
183
- r1 = ReplyWithTitleObject.create "title" => "r1", "content" => "hello world"
184
- assert r1.valid?, "Saving r1"
185
-
186
- r2 = ReplyWithTitleObject.create "title" => "r1", "content" => "hello world"
187
- assert !r2.valid?, "Saving r2 first time"
188
- end
189
-
190
- def test_validate_uniqueness_with_object_arg
191
- Reply.validates_uniqueness_of(:topic)
192
-
193
- t = Topic.create("title" => "I'm unique!")
194
-
195
- r1 = t.replies.create "title" => "r1", "content" => "hello world"
196
- assert r1.valid?, "Saving r1"
197
-
198
- r2 = t.replies.create "title" => "r2", "content" => "hello world"
199
- assert !r2.valid?, "Saving r2 first time"
200
- end
201
-
202
- def test_validate_uniqueness_scoped_to_defining_class
203
- t = Topic.create("title" => "What, me worry?")
204
-
205
- r1 = t.unique_replies.create "title" => "r1", "content" => "a barrel of fun"
206
- assert r1.valid?, "Saving r1"
207
-
208
- r2 = t.silly_unique_replies.create "title" => "r2", "content" => "a barrel of fun"
209
- assert !r2.valid?, "Saving r2"
210
-
211
- # Should succeed as validates_uniqueness_of only applies to
212
- # UniqueReply and its subclasses
213
- r3 = t.replies.create "title" => "r2", "content" => "a barrel of fun"
214
- assert r3.valid?, "Saving r3"
215
- end
216
-
217
- def test_validate_uniqueness_with_scope_array
218
- Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id])
219
-
220
- t = Topic.create("title" => "The earth is actually flat!")
221
-
222
- r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply"
223
- assert r1.valid?, "Saving r1"
224
-
225
- r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..."
226
- assert !r2.valid?, "Saving r2. Double reply by same author."
227
-
228
- r2.author_email_address = "jeremy_alt_email@rubyonrails.com"
229
- assert r2.save, "Saving r2 the second time."
230
-
231
- r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic"
232
- assert !r3.valid?, "Saving r3"
233
-
234
- r3.author_name = "jj"
235
- assert r3.save, "Saving r3 the second time."
236
-
237
- r3.author_name = "jeremy"
238
- assert !r3.save, "Saving r3 the third time."
239
- end
240
-
241
- def test_validate_case_insensitive_uniqueness
242
- Topic.validates_uniqueness_of(:title, :parent_id, :case_sensitive => false, :allow_nil => true)
243
-
244
- t = Topic.new("title" => "I'm unique!", :parent_id => 2)
245
- assert t.save, "Should save t as unique"
246
-
247
- t.content = "Remaining unique"
248
- assert t.save, "Should still save t as unique"
249
-
250
- t2 = Topic.new("title" => "I'm UNIQUE!", :parent_id => 1)
251
- assert !t2.valid?, "Shouldn't be valid"
252
- assert !t2.save, "Shouldn't save t2 as unique"
253
- assert t2.errors[:title].any?
254
- assert t2.errors[:parent_id].any?
255
- assert_equal ["has already been taken"], t2.errors[:title]
256
-
257
- t2.title = "I'm truly UNIQUE!"
258
- assert !t2.valid?, "Shouldn't be valid"
259
- assert !t2.save, "Shouldn't save t2 as unique"
260
- assert t2.errors[:title].empty?
261
- assert t2.errors[:parent_id].any?
262
-
263
- t2.parent_id = 4
264
- assert t2.save, "Should now save t2 as unique"
265
-
266
- t2.parent_id = nil
267
- t2.title = nil
268
- assert t2.valid?, "should validate with nil"
269
- assert t2.save, "should save with nil"
270
-
271
- t_utf8 = Topic.new("title" => "Я тоже уникальный!")
272
- assert t_utf8.save, "Should save t_utf8 as unique"
273
-
274
- # If database hasn't UTF-8 character set, this test fails
275
- if Topic.all.merge!(:select => 'LOWER(title) AS title').find(t_utf8.id).title == "я тоже уникальный!"
276
- t2_utf8 = Topic.new("title" => "я тоже УНИКАЛЬНЫЙ!")
277
- assert !t2_utf8.valid?, "Shouldn't be valid"
278
- assert !t2_utf8.save, "Shouldn't save t2_utf8 as unique"
279
- end
280
- end
281
-
282
- def test_validate_case_sensitive_uniqueness_with_special_sql_like_chars
283
- Topic.validates_uniqueness_of(:title, :case_sensitive => true)
284
-
285
- t = Topic.new("title" => "I'm unique!")
286
- assert t.save, "Should save t as unique"
287
-
288
- t2 = Topic.new("title" => "I'm %")
289
- assert t2.save, "Should save t2 as unique"
290
-
291
- t3 = Topic.new("title" => "I'm uniqu_!")
292
- assert t3.save, "Should save t3 as unique"
293
- end
294
-
295
- def test_validate_case_insensitive_uniqueness_with_special_sql_like_chars
296
- Topic.validates_uniqueness_of(:title, :case_sensitive => false)
297
-
298
- t = Topic.new("title" => "I'm unique!")
299
- assert t.save, "Should save t as unique"
300
-
301
- t2 = Topic.new("title" => "I'm %")
302
- assert t2.save, "Should save t2 as unique"
303
-
304
- t3 = Topic.new("title" => "I'm uniqu_!")
305
- assert t3.save, "Should save t3 as unique"
306
- end
307
-
308
- def test_validate_case_sensitive_uniqueness
309
- Topic.validates_uniqueness_of(:title, :case_sensitive => true, :allow_nil => true)
310
-
311
- t = Topic.new("title" => "I'm unique!")
312
- assert t.save, "Should save t as unique"
313
-
314
- t.content = "Remaining unique"
315
- assert t.save, "Should still save t as unique"
316
-
317
- t2 = Topic.new("title" => "I'M UNIQUE!")
318
- assert t2.valid?, "Should be valid"
319
- assert t2.save, "Should save t2 as unique"
320
- assert t2.errors[:title].empty?
321
- assert t2.errors[:parent_id].empty?
322
- assert_not_equal ["has already been taken"], t2.errors[:title]
323
-
324
- t3 = Topic.new("title" => "I'M uNiQUe!")
325
- assert t3.valid?, "Should be valid"
326
- assert t3.save, "Should save t2 as unique"
327
- assert t3.errors[:title].empty?
328
- assert t3.errors[:parent_id].empty?
329
- assert_not_equal ["has already been taken"], t3.errors[:title]
330
- end
331
-
332
- def test_validate_case_sensitive_uniqueness_with_attribute_passed_as_integer
333
- Topic.validates_uniqueness_of(:title, :case_sensitive => true)
334
- Topic.create!('title' => 101)
335
-
336
- t2 = Topic.new('title' => 101)
337
- assert !t2.valid?
338
- assert t2.errors[:title]
339
- end
340
-
341
- def test_validate_uniqueness_with_non_standard_table_names
342
- i1 = WarehouseThing.create(:value => 1000)
343
- assert !i1.valid?, "i1 should not be valid"
344
- assert i1.errors[:value].any?, "Should not be empty"
345
- end
346
-
347
- def test_validates_uniqueness_inside_scoping
348
- Topic.validates_uniqueness_of(:title)
349
-
350
- Topic.where(:author_name => "David").scoping do
351
- t1 = Topic.new("title" => "I'm unique!", "author_name" => "Mary")
352
- assert t1.save
353
- t2 = Topic.new("title" => "I'm unique!", "author_name" => "David")
354
- assert !t2.valid?
355
- end
356
- end
357
-
358
- def test_validate_uniqueness_with_columns_which_are_sql_keywords
359
- repair_validations(Guid) do
360
- Guid.validates_uniqueness_of :key
361
- g = Guid.new
362
- g.key = "foo"
363
- assert_nothing_raised { !g.valid? }
364
- end
365
- end
366
-
367
- def test_validate_uniqueness_with_limit
368
- if current_adapter?(:SQLite3Adapter)
369
- # Event.title has limit 5, but SQLite doesn't truncate.
370
- e1 = Event.create(title: "abcdefgh")
371
- assert e1.valid?, "Could not create an event with a unique 8 characters title"
372
-
373
- e2 = Event.create(title: "abcdefgh")
374
- assert_not e2.valid?, "Created an event whose title is not unique"
375
- elsif current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter, :OracleAdapter, :SQLServerAdapter)
376
- assert_raise(ActiveRecord::ValueTooLong) do
377
- Event.create(title: "abcdefgh")
378
- end
379
- else
380
- assert_raise(ActiveRecord::StatementInvalid) do
381
- Event.create(title: "abcdefgh")
382
- end
383
- end
384
- end
385
-
386
- def test_validate_uniqueness_with_limit_and_utf8
387
- if current_adapter?(:SQLite3Adapter)
388
- # Event.title has limit 5, but does SQLite doesn't truncate.
389
- e1 = Event.create(title: "一二三四五六七八")
390
- assert e1.valid?, "Could not create an event with a unique 8 characters title"
391
-
392
- e2 = Event.create(title: "一二三四五六七八")
393
- assert_not e2.valid?, "Created an event whose title is not unique"
394
- elsif current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter, :OracleAdapter, :SQLServerAdapter)
395
- assert_raise(ActiveRecord::ValueTooLong) do
396
- Event.create(title: "一二三四五六七八")
397
- end
398
- else
399
- assert_raise(ActiveRecord::StatementInvalid) do
400
- Event.create(title: "一二三四五六七八")
401
- end
402
- end
403
- end
404
-
405
- def test_validate_straight_inheritance_uniqueness
406
- w1 = IneptWizard.create(:name => "Rincewind", :city => "Ankh-Morpork")
407
- assert w1.valid?, "Saving w1"
408
-
409
- # Should use validation from base class (which is abstract)
410
- w2 = IneptWizard.new(:name => "Rincewind", :city => "Quirm")
411
- assert !w2.valid?, "w2 shouldn't be valid"
412
- assert w2.errors[:name].any?, "Should have errors for name"
413
- assert_equal ["has already been taken"], w2.errors[:name], "Should have uniqueness message for name"
414
-
415
- w3 = Conjurer.new(:name => "Rincewind", :city => "Quirm")
416
- assert !w3.valid?, "w3 shouldn't be valid"
417
- assert w3.errors[:name].any?, "Should have errors for name"
418
- assert_equal ["has already been taken"], w3.errors[:name], "Should have uniqueness message for name"
419
-
420
- w4 = Conjurer.create(:name => "The Amazing Bonko", :city => "Quirm")
421
- assert w4.valid?, "Saving w4"
422
-
423
- w5 = Thaumaturgist.new(:name => "The Amazing Bonko", :city => "Lancre")
424
- assert !w5.valid?, "w5 shouldn't be valid"
425
- assert w5.errors[:name].any?, "Should have errors for name"
426
- assert_equal ["has already been taken"], w5.errors[:name], "Should have uniqueness message for name"
427
-
428
- w6 = Thaumaturgist.new(:name => "Mustrum Ridcully", :city => "Quirm")
429
- assert !w6.valid?, "w6 shouldn't be valid"
430
- assert w6.errors[:city].any?, "Should have errors for city"
431
- assert_equal ["has already been taken"], w6.errors[:city], "Should have uniqueness message for city"
432
- end
433
-
434
- def test_validate_uniqueness_with_conditions
435
- Topic.validates_uniqueness_of :title, conditions: -> { where(approved: true) }
436
- Topic.create("title" => "I'm a topic", "approved" => true)
437
- Topic.create("title" => "I'm an unapproved topic", "approved" => false)
438
-
439
- t3 = Topic.new("title" => "I'm a topic", "approved" => true)
440
- assert !t3.valid?, "t3 shouldn't be valid"
441
-
442
- t4 = Topic.new("title" => "I'm an unapproved topic", "approved" => false)
443
- assert t4.valid?, "t4 should be valid"
444
- end
445
-
446
- def test_validate_uniqueness_with_non_callable_conditions_is_not_supported
447
- assert_raises(ArgumentError) {
448
- Topic.validates_uniqueness_of :title, conditions: Topic.where(approved: true)
449
- }
450
- end
451
-
452
- def test_validate_uniqueness_on_existing_relation
453
- event = Event.create
454
- assert TopicWithUniqEvent.create(event: event).valid?
455
-
456
- topic = TopicWithUniqEvent.new(event: event)
457
- assert_not topic.valid?
458
- assert_equal ['has already been taken'], topic.errors[:event]
459
- end
460
-
461
- def test_validate_uniqueness_on_empty_relation
462
- topic = TopicWithUniqEvent.new
463
- assert topic.valid?
464
- end
465
-
466
- def test_validate_uniqueness_of_custom_primary_key
467
- klass = Class.new(ActiveRecord::Base) do
468
- self.table_name = "keyboards"
469
- self.primary_key = :key_number
470
-
471
- validates_uniqueness_of :key_number
472
-
473
- def self.name
474
- "Keyboard"
475
- end
476
- end
477
-
478
- klass.create!(key_number: 10)
479
- key2 = klass.create!(key_number: 11)
480
-
481
- key2.key_number = 10
482
- assert_not key2.valid?
483
- end
484
-
485
- def test_validate_uniqueness_without_primary_key
486
- klass = Class.new(ActiveRecord::Base) do
487
- self.table_name = "dashboards"
488
-
489
- validates_uniqueness_of :dashboard_id
490
-
491
- def self.name; "Dashboard" end
492
- end
493
-
494
- abc = klass.create!(dashboard_id: "abc")
495
- assert klass.new(dashboard_id: "xyz").valid?
496
- assert_not klass.new(dashboard_id: "abc").valid?
497
-
498
- abc.dashboard_id = "def"
499
-
500
- e = assert_raises ActiveRecord::UnknownPrimaryKey do
501
- abc.save!
502
- end
503
- assert_match(/\AUnknown primary key for table dashboards in model/, e.message)
504
- assert_match(/Can not validate uniqueness for persisted record without primary key.\z/, e.message)
505
- end
506
-
507
- def test_validate_uniqueness_ignores_itself_when_primary_key_changed
508
- Topic.validates_uniqueness_of(:title)
509
-
510
- t = Topic.new("title" => "This is a unique title")
511
- assert t.save, "Should save t as unique"
512
-
513
- t.id += 1
514
- assert t.valid?, "Should be valid"
515
- assert t.save, "Should still save t as unique"
516
- end
517
-
518
- def test_validate_uniqueness_with_after_create_performing_save
519
- TopicWithAfterCreate.validates_uniqueness_of(:title)
520
- topic = TopicWithAfterCreate.create!(:title => "Title1")
521
- assert topic.author_name.start_with?("Title1")
522
-
523
- topic2 = TopicWithAfterCreate.new(:title => "Title1")
524
- refute topic2.valid?
525
- assert_equal(["has already been taken"], topic2.errors[:title])
526
- end
527
-
528
- def test_validate_uniqueness_uuid
529
- skip unless current_adapter?(:PostgreSQLAdapter)
530
- item = UuidItem.create!(uuid: SecureRandom.uuid, title: 'item1')
531
- item.update(title: 'item1-title2')
532
- assert_empty item.errors
533
-
534
- item2 = UuidValidatingItem.create!(uuid: SecureRandom.uuid, title: 'item2')
535
- item2.update(title: 'item2-title2')
536
- assert_empty item2.errors
537
- end
538
-
539
- def test_validate_uniqueness_regular_id
540
- item = CoolTopic.create!(title: 'MyItem')
541
- assert_empty item.errors
542
-
543
- item2 = CoolTopic.new(id: item.id, title: 'MyItem2')
544
- refute item2.valid?
545
-
546
- assert_equal(["has already been taken"], item2.errors[:id])
547
- end
548
- end
1
+ require "cases/helper"
2
+ require "models/topic"
3
+ require "models/reply"
4
+ require "models/warehouse_thing"
5
+ require "models/guid"
6
+ require "models/event"
7
+ require "models/dashboard"
8
+ require "models/uuid_item"
9
+ require "models/author"
10
+ require "models/person"
11
+ require "models/essay"
12
+
13
+ class Wizard < ActiveRecord::Base
14
+ self.abstract_class = true
15
+
16
+ validates_uniqueness_of :name
17
+ end
18
+
19
+ class IneptWizard < Wizard
20
+ validates_uniqueness_of :city
21
+ end
22
+
23
+ class Conjurer < IneptWizard
24
+ end
25
+
26
+ class Thaumaturgist < IneptWizard
27
+ end
28
+
29
+ class ReplyTitle; end
30
+
31
+ class ReplyWithTitleObject < Reply
32
+ validates_uniqueness_of :content, :scope => :title
33
+
34
+ def title; ReplyTitle.new; end
35
+ end
36
+
37
+ class TopicWithUniqEvent < Topic
38
+ belongs_to :event, foreign_key: :parent_id
39
+ validates :event, uniqueness: true
40
+ end
41
+
42
+ class BigIntTest < ActiveRecord::Base
43
+ INT_MAX_VALUE = 2147483647
44
+ self.table_name = 'cars'
45
+ validates :engines_count, uniqueness: true, inclusion: { in: 0..INT_MAX_VALUE }
46
+ end
47
+
48
+ class BigIntReverseTest < ActiveRecord::Base
49
+ INT_MAX_VALUE = 2147483647
50
+ self.table_name = 'cars'
51
+ validates :engines_count, inclusion: { in: 0..INT_MAX_VALUE }
52
+ validates :engines_count, uniqueness: true
53
+ end
54
+
55
+ class CoolTopic < Topic
56
+ validates_uniqueness_of :id
57
+ end
58
+
59
+ class TopicWithAfterCreate < Topic
60
+ after_create :set_author
61
+
62
+ def set_author
63
+ update_attributes!(:author_name => "#{title} #{id}")
64
+ end
65
+ end
66
+
67
+ class UniquenessValidationTest < ActiveRecord::TestCase
68
+ INT_MAX_VALUE = 2147483647
69
+
70
+ fixtures :topics, 'warehouse_things'
71
+
72
+ repair_validations(Topic, Reply)
73
+
74
+ def test_validate_uniqueness
75
+ Topic.validates_uniqueness_of(:title)
76
+
77
+ t = Topic.new("title" => "I'm uniqué!")
78
+ assert t.save, "Should save t as unique"
79
+
80
+ t.content = "Remaining unique"
81
+ assert t.save, "Should still save t as unique"
82
+
83
+ t2 = Topic.new("title" => "I'm uniqué!")
84
+ assert !t2.valid?, "Shouldn't be valid"
85
+ assert !t2.save, "Shouldn't save t2 as unique"
86
+ assert_equal ["has already been taken"], t2.errors[:title]
87
+
88
+ t2.title = "Now I am really also unique"
89
+ assert t2.save, "Should now save t2 as unique"
90
+ end
91
+
92
+ def test_validate_uniqueness_with_alias_attribute
93
+ Topic.alias_attribute :new_title, :title
94
+ Topic.validates_uniqueness_of(:new_title)
95
+
96
+ topic = Topic.new(new_title: 'abc')
97
+ assert topic.valid?
98
+ end
99
+
100
+ def test_validates_uniqueness_with_nil_value
101
+ Topic.validates_uniqueness_of(:title)
102
+
103
+ t = Topic.new("title" => nil)
104
+ assert t.save, "Should save t as unique"
105
+
106
+ t2 = Topic.new("title" => nil)
107
+ assert !t2.valid?, "Shouldn't be valid"
108
+ assert !t2.save, "Shouldn't save t2 as unique"
109
+ assert_equal ["has already been taken"], t2.errors[:title]
110
+ end
111
+
112
+ def test_validates_uniqueness_with_validates
113
+ Topic.validates :title, :uniqueness => true
114
+ Topic.create!('title' => 'abc')
115
+
116
+ t2 = Topic.new('title' => 'abc')
117
+ assert !t2.valid?
118
+ assert t2.errors[:title]
119
+ end
120
+
121
+ def test_validate_uniqueness_when_integer_out_of_range
122
+ entry = BigIntTest.create(engines_count: INT_MAX_VALUE + 1)
123
+ assert_equal entry.errors[:engines_count], ['is not included in the list']
124
+ end
125
+
126
+ def test_validate_uniqueness_when_integer_out_of_range_show_order_does_not_matter
127
+ entry = BigIntReverseTest.create(engines_count: INT_MAX_VALUE + 1)
128
+ assert_equal entry.errors[:engines_count], ['is not included in the list']
129
+ end
130
+
131
+ def test_validates_uniqueness_with_newline_chars
132
+ Topic.validates_uniqueness_of(:title, :case_sensitive => false)
133
+
134
+ t = Topic.new("title" => "new\nline")
135
+ assert t.save, "Should save t as unique"
136
+ end
137
+
138
+ def test_validate_uniqueness_with_scope
139
+ Reply.validates_uniqueness_of(:content, :scope => "parent_id")
140
+
141
+ t = Topic.create("title" => "I'm unique!")
142
+
143
+ r1 = t.replies.create "title" => "r1", "content" => "hello world"
144
+ assert r1.valid?, "Saving r1"
145
+
146
+ r2 = t.replies.create "title" => "r2", "content" => "hello world"
147
+ assert !r2.valid?, "Saving r2 first time"
148
+
149
+ r2.content = "something else"
150
+ assert r2.save, "Saving r2 second time"
151
+
152
+ t2 = Topic.create("title" => "I'm unique too!")
153
+ r3 = t2.replies.create "title" => "r3", "content" => "hello world"
154
+ assert r3.valid?, "Saving r3"
155
+ end
156
+
157
+ def test_validate_uniqueness_with_object_scope
158
+ Reply.validates_uniqueness_of(:content, :scope => :topic)
159
+
160
+ t = Topic.create("title" => "I'm unique!")
161
+
162
+ r1 = t.replies.create "title" => "r1", "content" => "hello world"
163
+ assert r1.valid?, "Saving r1"
164
+
165
+ r2 = t.replies.create "title" => "r2", "content" => "hello world"
166
+ assert !r2.valid?, "Saving r2 first time"
167
+ end
168
+
169
+ def test_validate_uniqueness_with_polymorphic_object_scope
170
+ Essay.validates_uniqueness_of(:name, scope: :writer)
171
+
172
+ a = Author.create(name: "Sergey")
173
+ p = Person.create(first_name: "Sergey")
174
+
175
+ e1 = a.essays.create(name: "Essay")
176
+ assert e1.valid?, "Saving e1"
177
+
178
+ e2 = p.essays.create(name: "Essay")
179
+ assert e2.valid?, "Saving e2"
180
+ end
181
+
182
+ def test_validate_uniqueness_with_composed_attribute_scope
183
+ r1 = ReplyWithTitleObject.create "title" => "r1", "content" => "hello world"
184
+ assert r1.valid?, "Saving r1"
185
+
186
+ r2 = ReplyWithTitleObject.create "title" => "r1", "content" => "hello world"
187
+ assert !r2.valid?, "Saving r2 first time"
188
+ end
189
+
190
+ def test_validate_uniqueness_with_object_arg
191
+ Reply.validates_uniqueness_of(:topic)
192
+
193
+ t = Topic.create("title" => "I'm unique!")
194
+
195
+ r1 = t.replies.create "title" => "r1", "content" => "hello world"
196
+ assert r1.valid?, "Saving r1"
197
+
198
+ r2 = t.replies.create "title" => "r2", "content" => "hello world"
199
+ assert !r2.valid?, "Saving r2 first time"
200
+ end
201
+
202
+ def test_validate_uniqueness_scoped_to_defining_class
203
+ t = Topic.create("title" => "What, me worry?")
204
+
205
+ r1 = t.unique_replies.create "title" => "r1", "content" => "a barrel of fun"
206
+ assert r1.valid?, "Saving r1"
207
+
208
+ r2 = t.silly_unique_replies.create "title" => "r2", "content" => "a barrel of fun"
209
+ assert !r2.valid?, "Saving r2"
210
+
211
+ # Should succeed as validates_uniqueness_of only applies to
212
+ # UniqueReply and its subclasses
213
+ r3 = t.replies.create "title" => "r2", "content" => "a barrel of fun"
214
+ assert r3.valid?, "Saving r3"
215
+ end
216
+
217
+ def test_validate_uniqueness_with_scope_array
218
+ Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id])
219
+
220
+ t = Topic.create("title" => "The earth is actually flat!")
221
+
222
+ r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply"
223
+ assert r1.valid?, "Saving r1"
224
+
225
+ r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..."
226
+ assert !r2.valid?, "Saving r2. Double reply by same author."
227
+
228
+ r2.author_email_address = "jeremy_alt_email@rubyonrails.com"
229
+ assert r2.save, "Saving r2 the second time."
230
+
231
+ r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic"
232
+ assert !r3.valid?, "Saving r3"
233
+
234
+ r3.author_name = "jj"
235
+ assert r3.save, "Saving r3 the second time."
236
+
237
+ r3.author_name = "jeremy"
238
+ assert !r3.save, "Saving r3 the third time."
239
+ end
240
+
241
+ def test_validate_case_insensitive_uniqueness
242
+ Topic.validates_uniqueness_of(:title, :parent_id, :case_sensitive => false, :allow_nil => true)
243
+
244
+ t = Topic.new("title" => "I'm unique!", :parent_id => 2)
245
+ assert t.save, "Should save t as unique"
246
+
247
+ t.content = "Remaining unique"
248
+ assert t.save, "Should still save t as unique"
249
+
250
+ t2 = Topic.new("title" => "I'm UNIQUE!", :parent_id => 1)
251
+ assert !t2.valid?, "Shouldn't be valid"
252
+ assert !t2.save, "Shouldn't save t2 as unique"
253
+ assert t2.errors[:title].any?
254
+ assert t2.errors[:parent_id].any?
255
+ assert_equal ["has already been taken"], t2.errors[:title]
256
+
257
+ t2.title = "I'm truly UNIQUE!"
258
+ assert !t2.valid?, "Shouldn't be valid"
259
+ assert !t2.save, "Shouldn't save t2 as unique"
260
+ assert t2.errors[:title].empty?
261
+ assert t2.errors[:parent_id].any?
262
+
263
+ t2.parent_id = 4
264
+ assert t2.save, "Should now save t2 as unique"
265
+
266
+ t2.parent_id = nil
267
+ t2.title = nil
268
+ assert t2.valid?, "should validate with nil"
269
+ assert t2.save, "should save with nil"
270
+
271
+ t_utf8 = Topic.new("title" => "Я тоже уникальный!")
272
+ assert t_utf8.save, "Should save t_utf8 as unique"
273
+
274
+ # If database hasn't UTF-8 character set, this test fails
275
+ if Topic.all.merge!(:select => 'LOWER(title) AS title').find(t_utf8.id).title == "я тоже уникальный!"
276
+ t2_utf8 = Topic.new("title" => "я тоже УНИКАЛЬНЫЙ!")
277
+ assert !t2_utf8.valid?, "Shouldn't be valid"
278
+ assert !t2_utf8.save, "Shouldn't save t2_utf8 as unique"
279
+ end
280
+ end
281
+
282
+ def test_validate_case_sensitive_uniqueness_with_special_sql_like_chars
283
+ Topic.validates_uniqueness_of(:title, :case_sensitive => true)
284
+
285
+ t = Topic.new("title" => "I'm unique!")
286
+ assert t.save, "Should save t as unique"
287
+
288
+ t2 = Topic.new("title" => "I'm %")
289
+ assert t2.save, "Should save t2 as unique"
290
+
291
+ t3 = Topic.new("title" => "I'm uniqu_!")
292
+ assert t3.save, "Should save t3 as unique"
293
+ end
294
+
295
+ def test_validate_case_insensitive_uniqueness_with_special_sql_like_chars
296
+ Topic.validates_uniqueness_of(:title, :case_sensitive => false)
297
+
298
+ t = Topic.new("title" => "I'm unique!")
299
+ assert t.save, "Should save t as unique"
300
+
301
+ t2 = Topic.new("title" => "I'm %")
302
+ assert t2.save, "Should save t2 as unique"
303
+
304
+ t3 = Topic.new("title" => "I'm uniqu_!")
305
+ assert t3.save, "Should save t3 as unique"
306
+ end
307
+
308
+ def test_validate_case_sensitive_uniqueness
309
+ Topic.validates_uniqueness_of(:title, :case_sensitive => true, :allow_nil => true)
310
+
311
+ t = Topic.new("title" => "I'm unique!")
312
+ assert t.save, "Should save t as unique"
313
+
314
+ t.content = "Remaining unique"
315
+ assert t.save, "Should still save t as unique"
316
+
317
+ t2 = Topic.new("title" => "I'M UNIQUE!")
318
+ assert t2.valid?, "Should be valid"
319
+ assert t2.save, "Should save t2 as unique"
320
+ assert t2.errors[:title].empty?
321
+ assert t2.errors[:parent_id].empty?
322
+ assert_not_equal ["has already been taken"], t2.errors[:title]
323
+
324
+ t3 = Topic.new("title" => "I'M uNiQUe!")
325
+ assert t3.valid?, "Should be valid"
326
+ assert t3.save, "Should save t2 as unique"
327
+ assert t3.errors[:title].empty?
328
+ assert t3.errors[:parent_id].empty?
329
+ assert_not_equal ["has already been taken"], t3.errors[:title]
330
+ end
331
+
332
+ def test_validate_case_sensitive_uniqueness_with_attribute_passed_as_integer
333
+ Topic.validates_uniqueness_of(:title, :case_sensitive => true)
334
+ Topic.create!('title' => 101)
335
+
336
+ t2 = Topic.new('title' => 101)
337
+ assert !t2.valid?
338
+ assert t2.errors[:title]
339
+ end
340
+
341
+ def test_validate_uniqueness_with_non_standard_table_names
342
+ i1 = WarehouseThing.create(:value => 1000)
343
+ assert !i1.valid?, "i1 should not be valid"
344
+ assert i1.errors[:value].any?, "Should not be empty"
345
+ end
346
+
347
+ def test_validates_uniqueness_inside_scoping
348
+ Topic.validates_uniqueness_of(:title)
349
+
350
+ Topic.where(:author_name => "David").scoping do
351
+ t1 = Topic.new("title" => "I'm unique!", "author_name" => "Mary")
352
+ assert t1.save
353
+ t2 = Topic.new("title" => "I'm unique!", "author_name" => "David")
354
+ assert !t2.valid?
355
+ end
356
+ end
357
+
358
+ def test_validate_uniqueness_with_columns_which_are_sql_keywords
359
+ repair_validations(Guid) do
360
+ Guid.validates_uniqueness_of :key
361
+ g = Guid.new
362
+ g.key = "foo"
363
+ assert_nothing_raised { !g.valid? }
364
+ end
365
+ end
366
+
367
+ def test_validate_uniqueness_with_limit
368
+ if current_adapter?(:SQLite3Adapter)
369
+ # Event.title has limit 5, but SQLite doesn't truncate.
370
+ e1 = Event.create(title: "abcdefgh")
371
+ assert e1.valid?, "Could not create an event with a unique 8 characters title"
372
+
373
+ e2 = Event.create(title: "abcdefgh")
374
+ assert_not e2.valid?, "Created an event whose title is not unique"
375
+ elsif current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter, :OracleAdapter, :SQLServerAdapter)
376
+ assert_raise(ActiveRecord::ValueTooLong) do
377
+ Event.create(title: "abcdefgh")
378
+ end
379
+ else
380
+ assert_raise(ActiveRecord::StatementInvalid) do
381
+ Event.create(title: "abcdefgh")
382
+ end
383
+ end
384
+ end
385
+
386
+ def test_validate_uniqueness_with_limit_and_utf8
387
+ if current_adapter?(:SQLite3Adapter)
388
+ # Event.title has limit 5, but does SQLite doesn't truncate.
389
+ e1 = Event.create(title: "一二三四五六七八")
390
+ assert e1.valid?, "Could not create an event with a unique 8 characters title"
391
+
392
+ e2 = Event.create(title: "一二三四五六七八")
393
+ assert_not e2.valid?, "Created an event whose title is not unique"
394
+ elsif current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter, :OracleAdapter, :SQLServerAdapter)
395
+ assert_raise(ActiveRecord::ValueTooLong) do
396
+ Event.create(title: "一二三四五六七八")
397
+ end
398
+ else
399
+ assert_raise(ActiveRecord::StatementInvalid) do
400
+ Event.create(title: "一二三四五六七八")
401
+ end
402
+ end
403
+ end
404
+
405
+ def test_validate_straight_inheritance_uniqueness
406
+ w1 = IneptWizard.create(:name => "Rincewind", :city => "Ankh-Morpork")
407
+ assert w1.valid?, "Saving w1"
408
+
409
+ # Should use validation from base class (which is abstract)
410
+ w2 = IneptWizard.new(:name => "Rincewind", :city => "Quirm")
411
+ assert !w2.valid?, "w2 shouldn't be valid"
412
+ assert w2.errors[:name].any?, "Should have errors for name"
413
+ assert_equal ["has already been taken"], w2.errors[:name], "Should have uniqueness message for name"
414
+
415
+ w3 = Conjurer.new(:name => "Rincewind", :city => "Quirm")
416
+ assert !w3.valid?, "w3 shouldn't be valid"
417
+ assert w3.errors[:name].any?, "Should have errors for name"
418
+ assert_equal ["has already been taken"], w3.errors[:name], "Should have uniqueness message for name"
419
+
420
+ w4 = Conjurer.create(:name => "The Amazing Bonko", :city => "Quirm")
421
+ assert w4.valid?, "Saving w4"
422
+
423
+ w5 = Thaumaturgist.new(:name => "The Amazing Bonko", :city => "Lancre")
424
+ assert !w5.valid?, "w5 shouldn't be valid"
425
+ assert w5.errors[:name].any?, "Should have errors for name"
426
+ assert_equal ["has already been taken"], w5.errors[:name], "Should have uniqueness message for name"
427
+
428
+ w6 = Thaumaturgist.new(:name => "Mustrum Ridcully", :city => "Quirm")
429
+ assert !w6.valid?, "w6 shouldn't be valid"
430
+ assert w6.errors[:city].any?, "Should have errors for city"
431
+ assert_equal ["has already been taken"], w6.errors[:city], "Should have uniqueness message for city"
432
+ end
433
+
434
+ def test_validate_uniqueness_with_conditions
435
+ Topic.validates_uniqueness_of :title, conditions: -> { where(approved: true) }
436
+ Topic.create("title" => "I'm a topic", "approved" => true)
437
+ Topic.create("title" => "I'm an unapproved topic", "approved" => false)
438
+
439
+ t3 = Topic.new("title" => "I'm a topic", "approved" => true)
440
+ assert !t3.valid?, "t3 shouldn't be valid"
441
+
442
+ t4 = Topic.new("title" => "I'm an unapproved topic", "approved" => false)
443
+ assert t4.valid?, "t4 should be valid"
444
+ end
445
+
446
+ def test_validate_uniqueness_with_non_callable_conditions_is_not_supported
447
+ assert_raises(ArgumentError) {
448
+ Topic.validates_uniqueness_of :title, conditions: Topic.where(approved: true)
449
+ }
450
+ end
451
+
452
+ def test_validate_uniqueness_on_existing_relation
453
+ event = Event.create
454
+ assert TopicWithUniqEvent.create(event: event).valid?
455
+
456
+ topic = TopicWithUniqEvent.new(event: event)
457
+ assert_not topic.valid?
458
+ assert_equal ['has already been taken'], topic.errors[:event]
459
+ end
460
+
461
+ def test_validate_uniqueness_on_empty_relation
462
+ topic = TopicWithUniqEvent.new
463
+ assert topic.valid?
464
+ end
465
+
466
+ def test_validate_uniqueness_of_custom_primary_key
467
+ klass = Class.new(ActiveRecord::Base) do
468
+ self.table_name = "keyboards"
469
+ self.primary_key = :key_number
470
+
471
+ validates_uniqueness_of :key_number
472
+
473
+ def self.name
474
+ "Keyboard"
475
+ end
476
+ end
477
+
478
+ klass.create!(key_number: 10)
479
+ key2 = klass.create!(key_number: 11)
480
+
481
+ key2.key_number = 10
482
+ assert_not key2.valid?
483
+ end
484
+
485
+ def test_validate_uniqueness_without_primary_key
486
+ klass = Class.new(ActiveRecord::Base) do
487
+ self.table_name = "dashboards"
488
+
489
+ validates_uniqueness_of :dashboard_id
490
+
491
+ def self.name; "Dashboard" end
492
+ end
493
+
494
+ abc = klass.create!(dashboard_id: "abc")
495
+ assert klass.new(dashboard_id: "xyz").valid?
496
+ assert_not klass.new(dashboard_id: "abc").valid?
497
+
498
+ abc.dashboard_id = "def"
499
+
500
+ e = assert_raises ActiveRecord::UnknownPrimaryKey do
501
+ abc.save!
502
+ end
503
+ assert_match(/\AUnknown primary key for table dashboards in model/, e.message)
504
+ assert_match(/Can not validate uniqueness for persisted record without primary key.\z/, e.message)
505
+ end
506
+
507
+ def test_validate_uniqueness_ignores_itself_when_primary_key_changed
508
+ Topic.validates_uniqueness_of(:title)
509
+
510
+ t = Topic.new("title" => "This is a unique title")
511
+ assert t.save, "Should save t as unique"
512
+
513
+ t.id += 1
514
+ assert t.valid?, "Should be valid"
515
+ assert t.save, "Should still save t as unique"
516
+ end
517
+
518
+ def test_validate_uniqueness_with_after_create_performing_save
519
+ TopicWithAfterCreate.validates_uniqueness_of(:title)
520
+ topic = TopicWithAfterCreate.create!(:title => "Title1")
521
+ assert topic.author_name.start_with?("Title1")
522
+
523
+ topic2 = TopicWithAfterCreate.new(:title => "Title1")
524
+ refute topic2.valid?
525
+ assert_equal(["has already been taken"], topic2.errors[:title])
526
+ end
527
+
528
+ def test_validate_uniqueness_uuid
529
+ skip unless current_adapter?(:PostgreSQLAdapter)
530
+ item = UuidItem.create!(uuid: SecureRandom.uuid, title: 'item1')
531
+ item.update(title: 'item1-title2')
532
+ assert_empty item.errors
533
+
534
+ item2 = UuidValidatingItem.create!(uuid: SecureRandom.uuid, title: 'item2')
535
+ item2.update(title: 'item2-title2')
536
+ assert_empty item2.errors
537
+ end
538
+
539
+ def test_validate_uniqueness_regular_id
540
+ item = CoolTopic.create!(title: 'MyItem')
541
+ assert_empty item.errors
542
+
543
+ item2 = CoolTopic.new(id: item.id, title: 'MyItem2')
544
+ refute item2.valid?
545
+
546
+ assert_equal(["has already been taken"], item2.errors[:id])
547
+ end
548
+ end