ibm_db 3.0.0-x86-mingw32 → 3.0.1-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 (465) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +4 -0
  3. data/MANIFEST +14 -14
  4. data/README +225 -225
  5. data/ext/Makefile.nt32 +181 -181
  6. data/ext/Makefile.nt32.191 +212 -212
  7. data/ext/OLD/extconf.rb +264 -0
  8. data/ext/{extconf_MacOS.rb → OLD/extconf_MacOS.rb} +269 -269
  9. data/ext/extconf.rb +291 -264
  10. data/ext/ibm_db.c +2 -2
  11. data/ext/ruby_ibm_db.h +241 -241
  12. data/ext/ruby_ibm_db_cli.h +500 -500
  13. data/init.rb +41 -41
  14. data/lib/IBM_DB.rb +27 -27
  15. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +4 -4
  16. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +1 -1
  17. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  18. data/lib/mswin32/ibm_db.rb +115 -115
  19. data/test/active_record/connection_adapters/fake_adapter.rb +46 -0
  20. data/test/assets/example.log +1 -0
  21. data/test/assets/flowers.jpg +0 -0
  22. data/test/assets/test.txt +1 -0
  23. data/test/cases/adapter_test.rb +261 -207
  24. data/test/cases/aggregations_test.rb +158 -0
  25. data/test/cases/ar_schema_test.rb +161 -0
  26. data/test/cases/associations/association_scope_test.rb +21 -0
  27. data/test/cases/associations/belongs_to_associations_test.rb +1029 -711
  28. data/test/cases/associations/callbacks_test.rb +192 -0
  29. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -181
  30. data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +26 -0
  31. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -0
  32. data/test/cases/associations/eager_load_nested_include_test.rb +128 -0
  33. data/test/cases/associations/eager_singularization_test.rb +148 -0
  34. data/test/cases/associations/eager_test.rb +1411 -0
  35. data/test/cases/associations/extension_test.rb +82 -0
  36. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +932 -851
  37. data/test/cases/associations/has_many_associations_test.rb +2162 -0
  38. data/test/cases/associations/has_many_through_associations_test.rb +1204 -0
  39. data/test/cases/associations/has_one_associations_test.rb +610 -0
  40. data/test/cases/associations/has_one_through_associations_test.rb +380 -0
  41. data/test/cases/associations/inner_join_association_test.rb +139 -0
  42. data/test/cases/associations/inverse_associations_test.rb +693 -0
  43. data/test/cases/associations/join_model_test.rb +754 -743
  44. data/test/cases/associations/nested_through_associations_test.rb +579 -0
  45. data/test/cases/associations/required_test.rb +82 -0
  46. data/test/cases/associations_test.rb +380 -0
  47. data/test/cases/attribute_decorators_test.rb +125 -0
  48. data/test/cases/attribute_methods/read_test.rb +60 -0
  49. data/test/cases/attribute_methods/serialization_test.rb +29 -0
  50. data/test/cases/attribute_methods_test.rb +952 -822
  51. data/test/cases/attribute_set_test.rb +200 -0
  52. data/test/cases/attribute_test.rb +180 -0
  53. data/test/cases/attributes_test.rb +136 -0
  54. data/test/cases/autosave_association_test.rb +1595 -0
  55. data/test/cases/base_test.rb +1638 -2133
  56. data/test/cases/batches_test.rb +212 -0
  57. data/test/cases/binary_test.rb +52 -0
  58. data/test/cases/bind_parameter_test.rb +100 -0
  59. data/test/cases/calculations_test.rb +646 -482
  60. data/test/cases/callbacks_test.rb +543 -0
  61. data/test/cases/clone_test.rb +40 -0
  62. data/test/cases/coders/yaml_column_test.rb +63 -0
  63. data/test/cases/column_alias_test.rb +17 -0
  64. data/test/cases/column_definition_test.rb +123 -0
  65. data/test/cases/connection_adapters/adapter_leasing_test.rb +54 -0
  66. data/test/cases/connection_adapters/connection_handler_test.rb +53 -0
  67. data/test/cases/connection_adapters/connection_specification_test.rb +12 -0
  68. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +293 -0
  69. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +65 -0
  70. data/test/cases/connection_adapters/quoting_test.rb +13 -0
  71. data/test/cases/connection_adapters/schema_cache_test.rb +56 -0
  72. data/test/cases/connection_adapters/type_lookup_test.rb +110 -0
  73. data/test/cases/connection_management_test.rb +122 -0
  74. data/test/cases/connection_pool_test.rb +346 -0
  75. data/test/cases/connection_specification/resolver_test.rb +116 -0
  76. data/test/cases/core_test.rb +112 -0
  77. data/test/cases/counter_cache_test.rb +209 -0
  78. data/test/cases/custom_locking_test.rb +17 -0
  79. data/test/cases/database_statements_test.rb +19 -0
  80. data/test/cases/date_time_test.rb +61 -0
  81. data/test/cases/defaults_test.rb +223 -0
  82. data/test/cases/dirty_test.rb +775 -0
  83. data/test/cases/disconnected_test.rb +28 -0
  84. data/test/cases/dup_test.rb +157 -0
  85. data/test/cases/enum_test.rb +290 -0
  86. data/test/cases/explain_subscriber_test.rb +64 -0
  87. data/test/cases/explain_test.rb +76 -0
  88. data/test/cases/finder_respond_to_test.rb +60 -0
  89. data/test/cases/finder_test.rb +1166 -0
  90. data/test/cases/fixture_set/file_test.rb +138 -0
  91. data/test/cases/fixtures_test.rb +897 -0
  92. data/test/cases/forbidden_attributes_protection_test.rb +99 -0
  93. data/test/cases/habtm_destroy_order_test.rb +61 -0
  94. data/test/cases/helper.rb +210 -0
  95. data/test/cases/hot_compatibility_test.rb +54 -0
  96. data/test/cases/i18n_test.rb +45 -0
  97. data/test/cases/inheritance_test.rb +375 -0
  98. data/test/cases/integration_test.rb +139 -0
  99. data/test/cases/invalid_connection_test.rb +22 -0
  100. data/test/cases/invalid_date_test.rb +32 -0
  101. data/test/cases/invertible_migration_test.rb +295 -0
  102. data/test/cases/json_serialization_test.rb +302 -0
  103. data/test/cases/locking_test.rb +477 -0
  104. data/test/cases/log_subscriber_test.rb +136 -0
  105. data/test/cases/migration/change_schema_test - Copy.rb +448 -0
  106. data/test/cases/migration/change_schema_test.rb +472 -0
  107. data/test/cases/migration/change_table_test.rb +224 -0
  108. data/test/cases/migration/column_attributes_test.rb +192 -0
  109. data/test/cases/migration/column_positioning_test.rb +56 -0
  110. data/test/cases/migration/columns_test.rb +304 -0
  111. data/test/cases/migration/command_recorder_test.rb +305 -0
  112. data/test/cases/migration/create_join_table_test.rb +148 -0
  113. data/test/cases/migration/foreign_key_test - Changed.rb +325 -0
  114. data/test/cases/migration/foreign_key_test.rb +360 -0
  115. data/test/cases/migration/helper.rb +39 -0
  116. data/test/cases/migration/index_test.rb +216 -0
  117. data/test/cases/migration/logger_test.rb +36 -0
  118. data/test/cases/migration/pending_migrations_test.rb +53 -0
  119. data/test/cases/migration/references_foreign_key_test.rb +214 -0
  120. data/test/cases/migration/references_index_test.rb +101 -0
  121. data/test/cases/migration/references_statements_test.rb +116 -0
  122. data/test/cases/migration/rename_table_test.rb +93 -0
  123. data/test/cases/migration/table_and_index_test.rb +24 -0
  124. data/test/cases/migration_test.rb +959 -2408
  125. data/test/cases/migrator_test.rb +388 -0
  126. data/test/cases/mixin_test.rb +70 -0
  127. data/test/cases/modules_test.rb +173 -0
  128. data/test/cases/multiparameter_attributes_test.rb +350 -0
  129. data/test/cases/multiple_db_test.rb +115 -0
  130. data/test/cases/nested_attributes_test.rb +1057 -0
  131. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -0
  132. data/test/cases/persistence_test.rb +909 -642
  133. data/test/cases/pooled_connections_test.rb +81 -0
  134. data/test/cases/primary_keys_test.rb +237 -0
  135. data/test/cases/query_cache_test.rb +326 -257
  136. data/test/cases/quoting_test.rb +156 -0
  137. data/test/cases/readonly_test.rb +118 -0
  138. data/test/cases/reaper_test.rb +85 -0
  139. data/test/cases/reflection_test.rb +454 -0
  140. data/test/cases/relation/delegation_test.rb +68 -0
  141. data/test/cases/relation/merging_test.rb +161 -0
  142. data/test/cases/relation/mutation_test.rb +165 -0
  143. data/test/cases/relation/predicate_builder_test.rb +14 -0
  144. data/test/cases/relation/where_chain_test.rb +181 -0
  145. data/test/cases/relation/where_test.rb +300 -0
  146. data/test/cases/relation/where_test2.rb +36 -0
  147. data/test/cases/relation_test.rb +297 -0
  148. data/test/cases/relations_test.rb +1815 -1182
  149. data/test/cases/reload_models_test.rb +22 -0
  150. data/test/cases/result_test.rb +80 -0
  151. data/test/cases/sanitize_test.rb +83 -0
  152. data/test/cases/schema_dumper_test.rb +463 -256
  153. data/test/cases/scoping/default_scoping_test.rb +454 -0
  154. data/test/cases/scoping/named_scoping_test.rb +524 -0
  155. data/test/cases/scoping/relation_scoping_test.rb +357 -0
  156. data/test/cases/serialization_test.rb +104 -0
  157. data/test/cases/serialized_attribute_test.rb +277 -0
  158. data/test/cases/statement_cache_test.rb +98 -0
  159. data/test/cases/store_test.rb +194 -0
  160. data/test/cases/tasks/database_tasks_test.rb +396 -0
  161. data/test/cases/tasks/mysql_rake_test.rb +311 -0
  162. data/test/cases/tasks/postgresql_rake_test.rb +245 -0
  163. data/test/cases/tasks/sqlite_rake_test.rb +193 -0
  164. data/test/cases/test_case.rb +123 -0
  165. data/test/cases/timestamp_test.rb +468 -0
  166. data/test/cases/transaction_callbacks_test.rb +452 -300
  167. data/test/cases/transaction_isolation_test.rb +106 -0
  168. data/test/cases/transactions_test.rb +817 -0
  169. data/test/cases/type/decimal_test.rb +51 -0
  170. data/test/cases/type/integer_test.rb +121 -0
  171. data/test/cases/type/string_test.rb +36 -0
  172. data/test/cases/type/type_map_test.rb +177 -0
  173. data/test/cases/type/unsigned_integer_test.rb +18 -0
  174. data/test/cases/types_test.rb +141 -0
  175. data/test/cases/unconnected_test.rb +33 -0
  176. data/test/cases/validations/association_validation_test.rb +86 -0
  177. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -0
  178. data/test/cases/validations/i18n_validation_test.rb +90 -0
  179. data/test/cases/validations/length_validation_test.rb +47 -0
  180. data/test/cases/validations/presence_validation_test.rb +68 -0
  181. data/test/cases/validations/uniqueness_validation_test.rb +434 -299
  182. data/test/cases/validations_repair_helper.rb +23 -0
  183. data/test/cases/validations_test.rb +165 -0
  184. data/test/cases/view_test.rb +113 -0
  185. data/test/cases/xml_serialization_test.rb +457 -408
  186. data/test/cases/yaml_serialization_test.rb +86 -0
  187. data/test/config.rb +5 -0
  188. data/test/config.yml +154 -154
  189. data/test/connections/native_ibm_db/connection.rb +43 -43
  190. data/test/fixtures/accounts.yml +29 -0
  191. data/test/fixtures/admin/accounts.yml +2 -0
  192. data/test/fixtures/admin/randomly_named_a9.yml +7 -0
  193. data/test/fixtures/admin/randomly_named_b0.yml +7 -0
  194. data/test/fixtures/admin/users.yml +10 -0
  195. data/test/fixtures/all/admin +1 -0
  196. data/test/fixtures/all/developers.yml +0 -0
  197. data/test/fixtures/all/people.yml +0 -0
  198. data/test/fixtures/all/tasks.yml +0 -0
  199. data/test/fixtures/author_addresses.yml +18 -0
  200. data/test/fixtures/author_favorites.yml +4 -0
  201. data/test/fixtures/authors.yml +23 -0
  202. data/test/fixtures/binaries.yml +133 -0
  203. data/test/fixtures/books.yml +11 -0
  204. data/test/fixtures/bulbs.yml +5 -0
  205. data/test/fixtures/cars.yml +9 -0
  206. data/test/fixtures/categories.yml +19 -0
  207. data/test/fixtures/categories/special_categories.yml +9 -0
  208. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
  209. data/test/fixtures/categories_ordered.yml +7 -0
  210. data/test/fixtures/categories_posts.yml +31 -0
  211. data/test/fixtures/categorizations.yml +23 -0
  212. data/test/fixtures/clubs.yml +8 -0
  213. data/test/fixtures/collections.yml +3 -0
  214. data/test/fixtures/colleges.yml +3 -0
  215. data/test/fixtures/comments.yml +65 -0
  216. data/test/fixtures/companies.yml +67 -0
  217. data/test/fixtures/computers.yml +10 -0
  218. data/test/fixtures/courses.yml +8 -0
  219. data/test/fixtures/customers.yml +26 -0
  220. data/test/fixtures/dashboards.yml +6 -0
  221. data/test/fixtures/developers.yml +22 -0
  222. data/test/fixtures/developers_projects.yml +17 -0
  223. data/test/fixtures/dog_lovers.yml +7 -0
  224. data/test/fixtures/dogs.yml +4 -0
  225. data/test/fixtures/doubloons.yml +3 -0
  226. data/test/fixtures/edges.yml +5 -0
  227. data/test/fixtures/entrants.yml +14 -0
  228. data/test/fixtures/essays.yml +6 -0
  229. data/test/fixtures/faces.yml +11 -0
  230. data/test/fixtures/fk_test_has_fk.yml +3 -0
  231. data/test/fixtures/fk_test_has_pk.yml +2 -0
  232. data/test/fixtures/friendships.yml +4 -0
  233. data/test/fixtures/funny_jokes.yml +10 -0
  234. data/test/fixtures/interests.yml +33 -0
  235. data/test/fixtures/items.yml +3 -0
  236. data/test/fixtures/jobs.yml +7 -0
  237. data/test/fixtures/legacy_things.yml +3 -0
  238. data/test/fixtures/mateys.yml +4 -0
  239. data/test/fixtures/member_details.yml +8 -0
  240. data/test/fixtures/member_types.yml +6 -0
  241. data/test/fixtures/members.yml +11 -0
  242. data/test/fixtures/memberships.yml +34 -0
  243. data/test/fixtures/men.yml +5 -0
  244. data/test/fixtures/minimalistics.yml +2 -0
  245. data/test/fixtures/minivans.yml +5 -0
  246. data/test/fixtures/mixed_case_monkeys.yml +6 -0
  247. data/test/fixtures/mixins.yml +29 -0
  248. data/test/fixtures/movies.yml +7 -0
  249. data/test/fixtures/naked/csv/accounts.csv +1 -0
  250. data/test/fixtures/naked/yml/accounts.yml +1 -0
  251. data/test/fixtures/naked/yml/companies.yml +1 -0
  252. data/test/fixtures/naked/yml/courses.yml +1 -0
  253. data/test/fixtures/organizations.yml +5 -0
  254. data/test/fixtures/other_topics.yml +42 -0
  255. data/test/fixtures/owners.yml +9 -0
  256. data/test/fixtures/parrots.yml +27 -0
  257. data/test/fixtures/parrots_pirates.yml +7 -0
  258. data/test/fixtures/people.yml +24 -0
  259. data/test/fixtures/peoples_treasures.yml +3 -0
  260. data/test/fixtures/pets.yml +19 -0
  261. data/test/fixtures/pirates.yml +12 -0
  262. data/test/fixtures/posts.yml +80 -0
  263. data/test/fixtures/price_estimates.yml +7 -0
  264. data/test/fixtures/products.yml +4 -0
  265. data/test/fixtures/projects.yml +7 -0
  266. data/test/fixtures/randomly_named_a9.yml +7 -0
  267. data/test/fixtures/ratings.yml +14 -0
  268. data/test/fixtures/readers.yml +11 -0
  269. data/test/fixtures/references.yml +17 -0
  270. data/test/fixtures/reserved_words/distinct.yml +5 -0
  271. data/test/fixtures/reserved_words/distinct_select.yml +11 -0
  272. data/test/fixtures/reserved_words/group.yml +14 -0
  273. data/test/fixtures/reserved_words/select.yml +8 -0
  274. data/test/fixtures/reserved_words/values.yml +7 -0
  275. data/test/fixtures/ships.yml +6 -0
  276. data/test/fixtures/speedometers.yml +8 -0
  277. data/test/fixtures/sponsors.yml +12 -0
  278. data/test/fixtures/string_key_objects.yml +7 -0
  279. data/test/fixtures/subscribers.yml +11 -0
  280. data/test/fixtures/subscriptions.yml +12 -0
  281. data/test/fixtures/taggings.yml +78 -0
  282. data/test/fixtures/tags.yml +11 -0
  283. data/test/fixtures/tasks.yml +7 -0
  284. data/test/fixtures/teapots.yml +3 -0
  285. data/test/fixtures/to_be_linked/accounts.yml +2 -0
  286. data/test/fixtures/to_be_linked/users.yml +10 -0
  287. data/test/fixtures/topics.yml +49 -0
  288. data/test/fixtures/toys.yml +14 -0
  289. data/test/fixtures/traffic_lights.yml +10 -0
  290. data/test/fixtures/treasures.yml +10 -0
  291. data/test/fixtures/uuid_children.yml +3 -0
  292. data/test/fixtures/uuid_parents.yml +2 -0
  293. data/test/fixtures/variants.yml +4 -0
  294. data/test/fixtures/vegetables.yml +20 -0
  295. data/test/fixtures/vertices.yml +4 -0
  296. data/test/fixtures/warehouse_things.yml +3 -0
  297. data/test/fixtures/zines.yml +5 -0
  298. data/test/ibm_db_test.rb +24 -24
  299. data/test/migrations/10_urban/9_add_expressions.rb +11 -0
  300. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -0
  301. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -0
  302. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -0
  303. data/test/migrations/missing/1_people_have_last_names.rb +9 -0
  304. data/test/migrations/missing/3_we_need_reminders.rb +12 -0
  305. data/test/migrations/missing/4_innocent_jointable.rb +12 -0
  306. data/test/migrations/rename/1_we_need_things.rb +11 -0
  307. data/test/migrations/rename/2_rename_things.rb +9 -0
  308. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -0
  309. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -0
  310. data/test/migrations/to_copy2/1_create_articles.rb +7 -0
  311. data/test/migrations/to_copy2/2_create_comments.rb +7 -0
  312. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -0
  313. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -0
  314. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -0
  315. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -0
  316. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -0
  317. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -0
  318. data/test/migrations/valid/2_we_need_reminders.rb +12 -0
  319. data/test/migrations/valid/3_innocent_jointable.rb +12 -0
  320. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -0
  321. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -0
  322. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -0
  323. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -0
  324. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -0
  325. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -0
  326. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -0
  327. data/test/models/admin.rb +5 -0
  328. data/test/models/admin/account.rb +3 -0
  329. data/test/models/admin/randomly_named_c1.rb +3 -0
  330. data/test/models/admin/user.rb +40 -0
  331. data/test/models/aircraft.rb +4 -0
  332. data/test/models/arunit2_model.rb +3 -0
  333. data/test/models/author.rb +212 -0
  334. data/test/models/auto_id.rb +4 -0
  335. data/test/models/autoloadable/extra_firm.rb +2 -0
  336. data/test/models/binary.rb +2 -0
  337. data/test/models/bird.rb +12 -0
  338. data/test/models/book.rb +18 -0
  339. data/test/models/boolean.rb +2 -0
  340. data/test/models/bulb.rb +51 -0
  341. data/test/models/cake_designer.rb +3 -0
  342. data/test/models/car.rb +26 -0
  343. data/test/models/carrier.rb +2 -0
  344. data/test/models/categorization.rb +19 -0
  345. data/test/models/category.rb +35 -0
  346. data/test/models/chef.rb +3 -0
  347. data/test/models/citation.rb +3 -0
  348. data/test/models/club.rb +23 -0
  349. data/test/models/college.rb +10 -0
  350. data/test/models/column.rb +3 -0
  351. data/test/models/column_name.rb +3 -0
  352. data/test/models/comment.rb +64 -0
  353. data/test/models/company.rb +225 -0
  354. data/test/models/company_in_module.rb +98 -0
  355. data/test/models/computer.rb +3 -0
  356. data/test/models/contact.rb +41 -0
  357. data/test/models/contract.rb +20 -0
  358. data/test/models/country.rb +7 -0
  359. data/test/models/course.rb +6 -0
  360. data/test/models/customer.rb +77 -0
  361. data/test/models/customer_carrier.rb +14 -0
  362. data/test/models/dashboard.rb +3 -0
  363. data/test/models/default.rb +2 -0
  364. data/test/models/department.rb +4 -0
  365. data/test/models/developer.rb +252 -0
  366. data/test/models/dog.rb +5 -0
  367. data/test/models/dog_lover.rb +5 -0
  368. data/test/models/doubloon.rb +12 -0
  369. data/test/models/drink_designer.rb +3 -0
  370. data/test/models/edge.rb +5 -0
  371. data/test/models/electron.rb +5 -0
  372. data/test/models/engine.rb +4 -0
  373. data/test/models/entrant.rb +3 -0
  374. data/test/models/essay.rb +5 -0
  375. data/test/models/event.rb +3 -0
  376. data/test/models/eye.rb +37 -0
  377. data/test/models/face.rb +9 -0
  378. data/test/models/friendship.rb +6 -0
  379. data/test/models/guid.rb +2 -0
  380. data/test/models/hotel.rb +6 -0
  381. data/test/models/image.rb +3 -0
  382. data/test/models/interest.rb +5 -0
  383. data/test/models/invoice.rb +4 -0
  384. data/test/models/item.rb +7 -0
  385. data/test/models/job.rb +7 -0
  386. data/test/models/joke.rb +7 -0
  387. data/test/models/keyboard.rb +3 -0
  388. data/test/models/legacy_thing.rb +3 -0
  389. data/test/models/lesson.rb +11 -0
  390. data/test/models/line_item.rb +3 -0
  391. data/test/models/liquid.rb +4 -0
  392. data/test/models/man.rb +11 -0
  393. data/test/models/matey.rb +4 -0
  394. data/test/models/member.rb +41 -0
  395. data/test/models/member_detail.rb +7 -0
  396. data/test/models/member_type.rb +3 -0
  397. data/test/models/membership.rb +35 -0
  398. data/test/models/minimalistic.rb +2 -0
  399. data/test/models/minivan.rb +9 -0
  400. data/test/models/mixed_case_monkey.rb +3 -0
  401. data/test/models/molecule.rb +6 -0
  402. data/test/models/movie.rb +5 -0
  403. data/test/models/order.rb +4 -0
  404. data/test/models/organization.rb +14 -0
  405. data/test/models/owner.rb +34 -0
  406. data/test/models/parrot.rb +29 -0
  407. data/test/models/person.rb +143 -0
  408. data/test/models/personal_legacy_thing.rb +4 -0
  409. data/test/models/pet.rb +15 -0
  410. data/test/models/pirate.rb +92 -0
  411. data/test/models/possession.rb +3 -0
  412. data/test/models/post.rb +264 -0
  413. data/test/models/price_estimate.rb +4 -0
  414. data/test/models/professor.rb +5 -0
  415. data/test/models/project.rb +29 -0
  416. data/test/models/publisher.rb +2 -0
  417. data/test/models/publisher/article.rb +4 -0
  418. data/test/models/publisher/magazine.rb +3 -0
  419. data/test/models/randomly_named_c1.rb +3 -0
  420. data/test/models/rating.rb +4 -0
  421. data/test/models/reader.rb +23 -0
  422. data/test/models/record.rb +2 -0
  423. data/test/models/reference.rb +22 -0
  424. data/test/models/reply.rb +61 -0
  425. data/test/models/ship.rb +33 -0
  426. data/test/models/ship_part.rb +8 -0
  427. data/test/models/shop.rb +17 -0
  428. data/test/models/shop_account.rb +6 -0
  429. data/test/models/speedometer.rb +6 -0
  430. data/test/models/sponsor.rb +7 -0
  431. data/test/models/string_key_object.rb +3 -0
  432. data/test/models/student.rb +4 -0
  433. data/test/models/subject.rb +16 -0
  434. data/test/models/subscriber.rb +8 -0
  435. data/test/models/subscription.rb +4 -0
  436. data/test/models/tag.rb +7 -0
  437. data/test/models/tagging.rb +13 -0
  438. data/test/models/task.rb +5 -0
  439. data/test/models/topic.rb +124 -0
  440. data/test/models/toy.rb +6 -0
  441. data/test/models/traffic_light.rb +4 -0
  442. data/test/models/treasure.rb +14 -0
  443. data/test/models/treaty.rb +7 -0
  444. data/test/models/tyre.rb +11 -0
  445. data/test/models/uuid_child.rb +3 -0
  446. data/test/models/uuid_parent.rb +3 -0
  447. data/test/models/vegetables.rb +24 -0
  448. data/test/models/vehicle.rb +7 -0
  449. data/test/models/vertex.rb +9 -0
  450. data/test/models/warehouse_thing.rb +5 -5
  451. data/test/models/wheel.rb +3 -0
  452. data/test/models/without_table.rb +3 -0
  453. data/test/models/zine.rb +3 -0
  454. data/test/schema/mysql2_specific_schema.rb +58 -0
  455. data/test/schema/mysql_specific_schema.rb +70 -0
  456. data/test/schema/oracle_specific_schema.rb +43 -0
  457. data/test/schema/postgresql_specific_schema.rb +202 -0
  458. data/test/schema/schema.rb +938 -751
  459. data/test/schema/sqlite_specific_schema.rb +22 -0
  460. data/test/support/config.rb +43 -0
  461. data/test/support/connection.rb +22 -0
  462. data/test/support/connection_helper.rb +14 -0
  463. data/test/support/ddl_helper.rb +8 -0
  464. data/test/support/schema_dumping_helper.rb +20 -0
  465. metadata +444 -18
@@ -0,0 +1,33 @@
1
+ require "cases/helper"
2
+
3
+ class TestRecord < ActiveRecord::Base
4
+ end
5
+
6
+ class TestUnconnectedAdapter < ActiveRecord::TestCase
7
+ self.use_transactional_fixtures = false
8
+
9
+ def setup
10
+ @underlying = ActiveRecord::Base.connection
11
+ @specification = ActiveRecord::Base.remove_connection
12
+ end
13
+
14
+ teardown do
15
+ @underlying = nil
16
+ ActiveRecord::Base.establish_connection(@specification)
17
+ load_schema if in_memory_db?
18
+ end
19
+
20
+ def test_connection_no_longer_established
21
+ assert_raise(ActiveRecord::ConnectionNotEstablished) do
22
+ TestRecord.find(1)
23
+ end
24
+
25
+ assert_raise(ActiveRecord::ConnectionNotEstablished) do
26
+ TestRecord.new.save
27
+ end
28
+ end
29
+
30
+ def test_underlying_adapter_no_longer_active
31
+ assert !@underlying.active?, "Removed adapter should no longer be active"
32
+ end
33
+ end
@@ -0,0 +1,86 @@
1
+ require "cases/helper"
2
+ require 'models/topic'
3
+ require 'models/reply'
4
+ require 'models/man'
5
+ require 'models/interest'
6
+
7
+ class AssociationValidationTest < ActiveRecord::TestCase
8
+ fixtures :topics
9
+
10
+ repair_validations(Topic, Reply)
11
+
12
+ def test_validates_associated_many
13
+ Topic.validates_associated(:replies)
14
+ Reply.validates_presence_of(:content)
15
+ t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
16
+ t.replies << [r = Reply.new("title" => "A reply"), r2 = Reply.new("title" => "Another reply", "content" => "non-empty"), r3 = Reply.new("title" => "Yet another reply"), r4 = Reply.new("title" => "The last reply", "content" => "non-empty")]
17
+ assert !t.valid?
18
+ assert t.errors[:replies].any?
19
+ assert_equal 1, r.errors.count # make sure all associated objects have been validated
20
+ assert_equal 0, r2.errors.count
21
+ assert_equal 1, r3.errors.count
22
+ assert_equal 0, r4.errors.count
23
+ r.content = r3.content = "non-empty"
24
+ assert t.valid?
25
+ end
26
+
27
+ def test_validates_associated_one
28
+ Reply.validates :topic, :associated => true
29
+ Topic.validates_presence_of( :content )
30
+ r = Reply.new("title" => "A reply", "content" => "with content!")
31
+ r.topic = Topic.create("title" => "uhohuhoh")
32
+ assert !r.valid?
33
+ assert r.errors[:topic].any?
34
+ r.topic.content = "non-empty"
35
+ assert r.valid?
36
+ end
37
+
38
+ def test_validates_associated_marked_for_destruction
39
+ Topic.validates_associated(:replies)
40
+ Reply.validates_presence_of(:content)
41
+ t = Topic.new
42
+ t.replies << Reply.new
43
+ assert t.invalid?
44
+ t.replies.first.mark_for_destruction
45
+ assert t.valid?
46
+ end
47
+
48
+ def test_validates_associated_with_custom_message_using_quotes
49
+ Reply.validates_associated :topic, :message=> "This string contains 'single' and \"double\" quotes"
50
+ Topic.validates_presence_of :content
51
+ r = Reply.create("title" => "A reply", "content" => "with content!")
52
+ r.topic = Topic.create("title" => "uhohuhoh")
53
+ assert !r.valid?
54
+ assert_equal ["This string contains 'single' and \"double\" quotes"], r.errors[:topic]
55
+ end
56
+
57
+ def test_validates_associated_missing
58
+ Reply.validates_presence_of(:topic)
59
+ r = Reply.create("title" => "A reply", "content" => "with content!")
60
+ assert !r.valid?
61
+ assert r.errors[:topic].any?
62
+
63
+ r.topic = Topic.first
64
+ assert r.valid?
65
+ end
66
+
67
+ def test_validates_presence_of_belongs_to_association__parent_is_new_record
68
+ repair_validations(Interest) do
69
+ # Note that Interest and Man have the :inverse_of option set
70
+ Interest.validates_presence_of(:man)
71
+ man = Man.new(:name => 'John')
72
+ interest = man.interests.build(:topic => 'Airplanes')
73
+ assert interest.valid?, "Expected interest to be valid, but was not. Interest should have a man object associated"
74
+ end
75
+ end
76
+
77
+ def test_validates_presence_of_belongs_to_association__existing_parent
78
+ repair_validations(Interest) do
79
+ Interest.validates_presence_of(:man)
80
+ man = Man.create!(:name => 'John')
81
+ interest = man.interests.build(:topic => 'Airplanes')
82
+ assert interest.valid?, "Expected interest to be valid, but was not. Interest should have a man object associated"
83
+ end
84
+ end
85
+
86
+ end
@@ -0,0 +1,84 @@
1
+ require "cases/helper"
2
+ require 'models/topic'
3
+
4
+ class I18nGenerateMessageValidationTest < ActiveRecord::TestCase
5
+ def setup
6
+ Topic.clear_validators!
7
+ @topic = Topic.new
8
+ I18n.backend = I18n::Backend::Simple.new
9
+ end
10
+
11
+ def reset_i18n_load_path
12
+ @old_load_path, @old_backend = I18n.load_path.dup, I18n.backend
13
+ I18n.load_path.clear
14
+ I18n.backend = I18n::Backend::Simple.new
15
+ yield
16
+ ensure
17
+ I18n.load_path.replace @old_load_path
18
+ I18n.backend = @old_backend
19
+ end
20
+
21
+ # validates_associated: generate_message(attr_name, :invalid, :message => custom_message, :value => value)
22
+ def test_generate_message_invalid_with_default_message
23
+ assert_equal 'is invalid', @topic.errors.generate_message(:title, :invalid, :value => 'title')
24
+ end
25
+
26
+ def test_generate_message_invalid_with_custom_message
27
+ assert_equal 'custom message title', @topic.errors.generate_message(:title, :invalid, :message => 'custom message %{value}', :value => 'title')
28
+ end
29
+
30
+ # validates_uniqueness_of: generate_message(attr_name, :taken, :message => custom_message)
31
+ def test_generate_message_taken_with_default_message
32
+ assert_equal "has already been taken", @topic.errors.generate_message(:title, :taken, :value => 'title')
33
+ end
34
+
35
+ def test_generate_message_taken_with_custom_message
36
+ assert_equal 'custom message title', @topic.errors.generate_message(:title, :taken, :message => 'custom message %{value}', :value => 'title')
37
+ end
38
+
39
+ # ActiveRecord#RecordInvalid exception
40
+
41
+ test "RecordInvalid exception can be localized" do
42
+ topic = Topic.new
43
+ topic.errors.add(:title, :invalid)
44
+ topic.errors.add(:title, :blank)
45
+ assert_equal "Validation failed: Title is invalid, Title can't be blank", ActiveRecord::RecordInvalid.new(topic).message
46
+ end
47
+
48
+ test "RecordInvalid exception translation falls back to the :errors namespace" do
49
+ reset_i18n_load_path do
50
+ I18n.backend.store_translations 'en', :errors => {:messages => {:record_invalid => 'fallback message'}}
51
+ topic = Topic.new
52
+ topic.errors.add(:title, :blank)
53
+ assert_equal "fallback message", ActiveRecord::RecordInvalid.new(topic).message
54
+ end
55
+ end
56
+
57
+ test "translation for 'taken' can be overridden" do
58
+ reset_i18n_load_path do
59
+ I18n.backend.store_translations "en", {errors: {attributes: {title: {taken: "Custom taken message" }}}}
60
+ assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title')
61
+ end
62
+ end
63
+
64
+ test "translation for 'taken' can be overridden in activerecord scope" do
65
+ reset_i18n_load_path do
66
+ I18n.backend.store_translations "en", {activerecord: {errors: {messages: {taken: "Custom taken message" }}}}
67
+ assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title')
68
+ end
69
+ end
70
+
71
+ test "translation for 'taken' can be overridden in activerecord model scope" do
72
+ reset_i18n_load_path do
73
+ I18n.backend.store_translations "en", {activerecord: {errors: {models: {topic: {taken: "Custom taken message" }}}}}
74
+ assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title')
75
+ end
76
+ end
77
+
78
+ test "translation for 'taken' can be overridden in activerecord attributes scope" do
79
+ reset_i18n_load_path do
80
+ I18n.backend.store_translations "en", {activerecord: {errors: {models: {topic: {attributes: {title: {taken: "Custom taken message" }}}}}}}
81
+ assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title')
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,90 @@
1
+ require "cases/helper"
2
+ require 'models/topic'
3
+ require 'models/reply'
4
+
5
+ class I18nValidationTest < ActiveRecord::TestCase
6
+ repair_validations(Topic, Reply)
7
+
8
+ def setup
9
+ repair_validations(Topic, Reply)
10
+ Reply.validates_presence_of(:title)
11
+ @topic = Topic.new
12
+ @old_load_path, @old_backend = I18n.load_path.dup, I18n.backend
13
+ I18n.load_path.clear
14
+ I18n.backend = I18n::Backend::Simple.new
15
+ I18n.backend.store_translations('en', :errors => {:messages => {:custom => nil}})
16
+ end
17
+
18
+ teardown do
19
+ I18n.load_path.replace @old_load_path
20
+ I18n.backend = @old_backend
21
+ end
22
+
23
+ def unique_topic
24
+ @unique ||= Topic.create :title => 'unique!'
25
+ end
26
+
27
+ def replied_topic
28
+ @replied_topic ||= begin
29
+ topic = Topic.create(:title => "topic")
30
+ topic.replies << Reply.new
31
+ topic
32
+ end
33
+ end
34
+
35
+ # A set of common cases for ActiveModel::Validations message generation that
36
+ # are used to generate tests to keep things DRY
37
+ #
38
+ COMMON_CASES = [
39
+ # [ case, validation_options, generate_message_options]
40
+ [ "given no options", {}, {}],
41
+ [ "given custom message", {:message => "custom"}, {:message => "custom"}],
42
+ [ "given if condition", {:if => lambda { true }}, {}],
43
+ [ "given unless condition", {:unless => lambda { false }}, {}],
44
+ [ "given option that is not reserved", {:format => "jpg"}, {:format => "jpg" }]
45
+ # TODO Add :on case, but below doesn't work, because then the validation isn't run for some reason
46
+ # even when using .save instead .valid?
47
+ # [ "given on condition", {on: :save}, {}]
48
+ ]
49
+
50
+ # validates_uniqueness_of w/ mocha
51
+
52
+ COMMON_CASES.each do |name, validation_options, generate_message_options|
53
+ test "validates_uniqueness_of on generated message #{name}" do
54
+ Topic.validates_uniqueness_of :title, validation_options
55
+ @topic.title = unique_topic.title
56
+ @topic.errors.expects(:generate_message).with(:title, :taken, generate_message_options.merge(:value => 'unique!'))
57
+ @topic.valid?
58
+ end
59
+ end
60
+
61
+ # validates_associated w/ mocha
62
+
63
+ COMMON_CASES.each do |name, validation_options, generate_message_options|
64
+ test "validates_associated on generated message #{name}" do
65
+ Topic.validates_associated :replies, validation_options
66
+ replied_topic.errors.expects(:generate_message).with(:replies, :invalid, generate_message_options.merge(:value => replied_topic.replies))
67
+ replied_topic.save
68
+ end
69
+ end
70
+
71
+ # validates_associated w/o mocha
72
+
73
+ def test_validates_associated_finds_custom_model_key_translation
74
+ I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:replies => {:invalid => 'custom message'}}}}}}
75
+ I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:invalid => 'global message'}}}
76
+
77
+ Topic.validates_associated :replies
78
+ replied_topic.valid?
79
+ assert_equal ['custom message'], replied_topic.errors[:replies].uniq
80
+ end
81
+
82
+ def test_validates_associated_finds_global_default_translation
83
+ I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:invalid => 'global message'}}}
84
+
85
+ Topic.validates_associated :replies
86
+ replied_topic.valid?
87
+ assert_equal ['global message'], replied_topic.errors[:replies]
88
+ end
89
+
90
+ end
@@ -0,0 +1,47 @@
1
+ # -*- coding: utf-8 -*-
2
+ require "cases/helper"
3
+ require 'models/owner'
4
+ require 'models/pet'
5
+
6
+ class LengthValidationTest < ActiveRecord::TestCase
7
+ fixtures :owners
8
+ repair_validations(Owner)
9
+
10
+ def test_validates_size_of_association
11
+ repair_validations Owner do
12
+ assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
13
+ o = Owner.new('name' => 'nopets')
14
+ assert !o.save
15
+ assert o.errors[:pets].any?
16
+ o.pets.build('name' => 'apet')
17
+ assert o.valid?
18
+ end
19
+ end
20
+
21
+ def test_validates_size_of_association_using_within
22
+ repair_validations Owner do
23
+ assert_nothing_raised { Owner.validates_size_of :pets, :within => 1..2 }
24
+ o = Owner.new('name' => 'nopets')
25
+ assert !o.save
26
+ assert o.errors[:pets].any?
27
+
28
+ o.pets.build('name' => 'apet')
29
+ assert o.valid?
30
+
31
+ 2.times { o.pets.build('name' => 'apet') }
32
+ assert !o.save
33
+ assert o.errors[:pets].any?
34
+ end
35
+ end
36
+
37
+ def test_validates_size_of_association_utf8
38
+ repair_validations Owner do
39
+ assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
40
+ o = Owner.new('name' => 'あいうえおかきくけこ')
41
+ assert !o.save
42
+ assert o.errors[:pets].any?
43
+ o.pets.build('name' => 'あいうえおかきくけこ')
44
+ assert o.valid?
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,68 @@
1
+ # encoding: utf-8
2
+ require "cases/helper"
3
+ require 'models/man'
4
+ require 'models/face'
5
+ require 'models/interest'
6
+ require 'models/speedometer'
7
+ require 'models/dashboard'
8
+
9
+ class PresenceValidationTest < ActiveRecord::TestCase
10
+ class Boy < Man; end
11
+
12
+ repair_validations(Boy)
13
+
14
+ def test_validates_presence_of_non_association
15
+ Boy.validates_presence_of(:name)
16
+ b = Boy.new
17
+ assert b.invalid?
18
+
19
+ b.name = "Alex"
20
+ assert b.valid?
21
+ end
22
+
23
+ def test_validates_presence_of_has_one
24
+ Boy.validates_presence_of(:face)
25
+ b = Boy.new
26
+ assert b.invalid?, "should not be valid if has_one association missing"
27
+ assert_equal 1, b.errors[:face].size, "validates_presence_of should only add one error"
28
+ end
29
+
30
+ def test_validates_presence_of_has_one_marked_for_destruction
31
+ Boy.validates_presence_of(:face)
32
+ b = Boy.new
33
+ f = Face.new
34
+ b.face = f
35
+ assert b.valid?
36
+
37
+ f.mark_for_destruction
38
+ assert b.invalid?
39
+ end
40
+
41
+ def test_validates_presence_of_has_many_marked_for_destruction
42
+ Boy.validates_presence_of(:interests)
43
+ b = Boy.new
44
+ b.interests << [i1 = Interest.new, i2 = Interest.new]
45
+ assert b.valid?
46
+
47
+ i1.mark_for_destruction
48
+ assert b.valid?
49
+
50
+ i2.mark_for_destruction
51
+ assert b.invalid?
52
+ end
53
+
54
+ def test_validates_presence_doesnt_convert_to_array
55
+ speedometer = Class.new(Speedometer)
56
+ speedometer.validates_presence_of :dashboard
57
+
58
+ dash = Dashboard.new
59
+
60
+ # dashboard has to_a method
61
+ def dash.to_a; ['(/)', '(\)']; end
62
+
63
+ s = speedometer.new
64
+ s.dashboard = dash
65
+
66
+ assert_nothing_raised { s.valid? }
67
+ end
68
+ end
@@ -1,299 +1,434 @@
1
- # encoding: utf-8
2
- require "cases/helper"
3
- require 'models/topic'
4
- require 'models/reply'
5
- require 'models/warehouse_thing'
6
- require 'models/guid'
7
- require 'models/event'
8
-
9
- class Wizard < ActiveRecord::Base
10
- self.abstract_class = true
11
-
12
- validates_uniqueness_of :name
13
- end
14
-
15
- class IneptWizard < Wizard
16
- validates_uniqueness_of :city
17
- end
18
-
19
- class Conjurer < IneptWizard
20
- end
21
-
22
- class Thaumaturgist < IneptWizard
23
- end
24
-
25
- class UniquenessValidationTest < ActiveRecord::TestCase
26
- fixtures :topics, 'warehouse_things', :developers
27
-
28
- repair_validations(Topic, Reply)
29
-
30
- def test_validate_uniqueness
31
- Topic.validates_uniqueness_of(:title)
32
-
33
- t = Topic.new("title" => "I'm uniqué!")
34
- assert t.save, "Should save t as unique"
35
-
36
- t.content = "Remaining unique"
37
- assert t.save, "Should still save t as unique"
38
-
39
- t2 = Topic.new("title" => "I'm uniqué!")
40
- assert !t2.valid?, "Shouldn't be valid"
41
- assert !t2.save, "Shouldn't save t2 as unique"
42
- assert_equal ["has already been taken"], t2.errors[:title]
43
-
44
- t2.title = "Now Im really also unique"
45
- assert t2.save, "Should now save t2 as unique"
46
- end
47
-
48
- def test_validates_uniqueness_with_validates
49
- Topic.validates :title, :uniqueness => true
50
- Topic.create!('title' => 'abc')
51
-
52
- t2 = Topic.new('title' => 'abc')
53
- assert !t2.valid?
54
- assert t2.errors[:title]
55
- end
56
-
57
- def test_validates_uniqueness_with_newline_chars
58
- Topic.validates_uniqueness_of(:title, :case_sensitive => false)
59
-
60
- t = Topic.new("title" => "new\nline")
61
- assert t.save, "Should save t as unique"
62
- end
63
-
64
- def test_validate_uniqueness_with_scope
65
- Reply.validates_uniqueness_of(:content, :scope => "parent_id")
66
-
67
- t = Topic.create("title" => "I'm unique!")
68
-
69
- r1 = t.replies.create "title" => "r1", "content" => "hello world"
70
- assert r1.valid?, "Saving r1"
71
-
72
- r2 = t.replies.create "title" => "r2", "content" => "hello world"
73
- assert !r2.valid?, "Saving r2 first time"
74
-
75
- r2.content = "something else"
76
- assert r2.save, "Saving r2 second time"
77
-
78
- t2 = Topic.create("title" => "I'm unique too!")
79
- r3 = t2.replies.create "title" => "r3", "content" => "hello world"
80
- assert r3.valid?, "Saving r3"
81
- end
82
-
83
- def test_validate_uniqueness_scoped_to_defining_class
84
- t = Topic.create("title" => "What, me worry?")
85
-
86
- r1 = t.unique_replies.create "title" => "r1", "content" => "a barrel of fun"
87
- assert r1.valid?, "Saving r1"
88
-
89
- r2 = t.silly_unique_replies.create "title" => "r2", "content" => "a barrel of fun"
90
- assert !r2.valid?, "Saving r2"
91
-
92
- # Should succeed as validates_uniqueness_of only applies to
93
- # UniqueReply and its subclasses
94
- r3 = t.replies.create "title" => "r2", "content" => "a barrel of fun"
95
- assert r3.valid?, "Saving r3"
96
- end
97
-
98
- def test_validate_uniqueness_with_scope_array
99
- Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id])
100
-
101
- t = Topic.create("title" => "The earth is actually flat!")
102
-
103
- r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply"
104
- assert r1.valid?, "Saving r1"
105
-
106
- r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..."
107
- assert !r2.valid?, "Saving r2. Double reply by same author."
108
-
109
- r2.author_email_address = "jeremy_alt_email@rubyonrails.com"
110
- assert r2.save, "Saving r2 the second time."
111
-
112
- r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic"
113
- assert !r3.valid?, "Saving r3"
114
-
115
- r3.author_name = "jj"
116
- assert r3.save, "Saving r3 the second time."
117
-
118
- r3.author_name = "jeremy"
119
- assert !r3.save, "Saving r3 the third time."
120
- end
121
-
122
- def test_validate_case_insensitive_uniqueness
123
- Topic.validates_uniqueness_of(:title, :parent_id, :case_sensitive => false, :allow_nil => true)
124
-
125
- t = Topic.new("title" => "I'm unique!", :parent_id => 2)
126
- assert t.save, "Should save t as unique"
127
-
128
- t.content = "Remaining unique"
129
- assert t.save, "Should still save t as unique"
130
-
131
- t2 = Topic.new("title" => "I'm UNIQUE!", :parent_id => 1)
132
- assert !t2.valid?, "Shouldn't be valid"
133
- assert !t2.save, "Shouldn't save t2 as unique"
134
- assert t2.errors[:title].any?
135
- assert t2.errors[:parent_id].any?
136
- assert_equal ["has already been taken"], t2.errors[:title]
137
-
138
- t2.title = "I'm truly UNIQUE!"
139
- assert !t2.valid?, "Shouldn't be valid"
140
- assert !t2.save, "Shouldn't save t2 as unique"
141
- assert t2.errors[:title].empty?
142
- assert t2.errors[:parent_id].any?
143
-
144
- t2.parent_id = 4
145
- assert t2.save, "Should now save t2 as unique"
146
-
147
- t2.parent_id = nil
148
- t2.title = nil
149
- assert t2.valid?, "should validate with nil"
150
- assert t2.save, "should save with nil"
151
-
152
- with_kcode('UTF8') do
153
- t_utf8 = Topic.new("title" => "Я тоже уникальный!")
154
- assert t_utf8.save, "Should save t_utf8 as unique"
155
-
156
- # If database hasn't UTF-8 character set, this test fails
157
- if Topic.find(t_utf8, :select => 'LOWER(title) AS title').title == "я тоже уникальный!"
158
- t2_utf8 = Topic.new("title" => "я тоже УНИКАЛЬНЫЙ!")
159
- assert !t2_utf8.valid?, "Shouldn't be valid"
160
- assert !t2_utf8.save, "Shouldn't save t2_utf8 as unique"
161
- end
162
- end
163
- end
164
-
165
- def test_validate_case_sensitive_uniqueness_with_special_sql_like_chars
166
- Topic.validates_uniqueness_of(:title, :case_sensitive => true)
167
-
168
- t = Topic.new("title" => "I'm unique!")
169
- assert t.save, "Should save t as unique"
170
-
171
- t2 = Topic.new("title" => "I'm %")
172
- assert t2.save, "Should save t2 as unique"
173
-
174
- t3 = Topic.new("title" => "I'm uniqu_!")
175
- assert t3.save, "Should save t3 as unique"
176
- end
177
-
178
- def test_validate_case_insensitive_uniqueness_with_special_sql_like_chars
179
- Topic.validates_uniqueness_of(:title, :case_sensitive => false)
180
-
181
- t = Topic.new("title" => "I'm unique!")
182
- assert t.save, "Should save t as unique"
183
-
184
- t2 = Topic.new("title" => "I'm %")
185
- assert t2.save, "Should save t2 as unique"
186
-
187
- t3 = Topic.new("title" => "I'm uniqu_!")
188
- assert t3.save, "Should save t3 as unique"
189
- end
190
-
191
- def test_validate_case_sensitive_uniqueness
192
- Topic.validates_uniqueness_of(:title, :case_sensitive => true, :allow_nil => true)
193
-
194
- t = Topic.new("title" => "I'm unique!")
195
- assert t.save, "Should save t as unique"
196
-
197
- t.content = "Remaining unique"
198
- assert t.save, "Should still save t as unique"
199
-
200
- t2 = Topic.new("title" => "I'M UNIQUE!")
201
- assert t2.valid?, "Should be valid"
202
- assert t2.save, "Should save t2 as unique"
203
- assert t2.errors[:title].empty?
204
- assert t2.errors[:parent_id].empty?
205
- assert_not_equal ["has already been taken"], t2.errors[:title]
206
-
207
- t3 = Topic.new("title" => "I'M uNiQUe!")
208
- assert t3.valid?, "Should be valid"
209
- assert t3.save, "Should save t2 as unique"
210
- assert t3.errors[:title].empty?
211
- assert t3.errors[:parent_id].empty?
212
- assert_not_equal ["has already been taken"], t3.errors[:title]
213
- end
214
-
215
- def test_validate_case_sensitive_uniqueness_with_attribute_passed_as_integer
216
- Topic.validates_uniqueness_of(:title, :case_sensitve => true)
217
- Topic.create!('title' => 101)
218
-
219
- t2 = Topic.new('title' => 101)
220
- assert !t2.valid?
221
- assert t2.errors[:title]
222
- end
223
-
224
- def test_validate_uniqueness_with_non_standard_table_names
225
- i1 = WarehouseThing.create(:value => 1000)
226
- assert !i1.valid?, "i1 should not be valid"
227
- assert i1.errors[:value].any?, "Should not be empty"
228
- end
229
-
230
- def test_validates_uniqueness_inside_with_scope
231
- Topic.validates_uniqueness_of(:title)
232
-
233
- Topic.send(:with_scope, :find => { :conditions => { :author_name => "David" } }) do
234
- t1 = Topic.new("title" => "I'm unique!", "author_name" => "Mary")
235
- assert t1.save
236
- t2 = Topic.new("title" => "I'm unique!", "author_name" => "David")
237
- assert !t2.valid?
238
- end
239
- end
240
-
241
- def test_validate_uniqueness_with_columns_which_are_sql_keywords
242
- repair_validations(Guid) do
243
- Guid.validates_uniqueness_of :key
244
- g = Guid.new
245
- g.key = "foo"
246
- assert_nothing_raised { !g.valid? }
247
- end
248
- end
249
-
250
- def test_validate_uniqueness_with_limit
251
- # Event.title is limited to 5 characters
252
- e1 = Event.create(:title => "abcde")
253
- assert e1.valid?, "Could not create an event with a unique, 5 character title"
254
- e2 = Event.create(:title => "abcdefgh")
255
- assert !e2.valid?, "Created an event whose title, with limit taken into account, is not unique"
256
- end
257
-
258
- def test_validate_uniqueness_with_limit_and_utf8
259
- unless current_adapter?(:IBM_DBAdapter)
260
- # Limit for the varchar field is number of bytes and not characters for DB2. Hence the below test cases is expected to fail.
261
- with_kcode('UTF8') do
262
- # Event.title is limited to 5 characters
263
- e1 = Event.create(:title => "一二三四五")
264
- assert e1.valid?, "Could not create an event with a unique, 5 character title"
265
- e2 = Event.create(:title => "一二三四五六七八")
266
- assert !e2.valid?, "Created an event whose title, with limit taken into account, is not unique"
267
- end
268
- end
269
- end
270
-
271
- def test_validate_straight_inheritance_uniqueness
272
- w1 = IneptWizard.create(:name => "Rincewind", :city => "Ankh-Morpork")
273
- assert w1.valid?, "Saving w1"
274
-
275
- # Should use validation from base class (which is abstract)
276
- w2 = IneptWizard.new(:name => "Rincewind", :city => "Quirm")
277
- assert !w2.valid?, "w2 shouldn't be valid"
278
- assert w2.errors[:name].any?, "Should have errors for name"
279
- assert_equal ["has already been taken"], w2.errors[:name], "Should have uniqueness message for name"
280
-
281
- w3 = Conjurer.new(:name => "Rincewind", :city => "Quirm")
282
- assert !w3.valid?, "w3 shouldn't be valid"
283
- assert w3.errors[:name].any?, "Should have errors for name"
284
- assert_equal ["has already been taken"], w3.errors[:name], "Should have uniqueness message for name"
285
-
286
- w4 = Conjurer.create(:name => "The Amazing Bonko", :city => "Quirm")
287
- assert w4.valid?, "Saving w4"
288
-
289
- w5 = Thaumaturgist.new(:name => "The Amazing Bonko", :city => "Lancre")
290
- assert !w5.valid?, "w5 shouldn't be valid"
291
- assert w5.errors[:name].any?, "Should have errors for name"
292
- assert_equal ["has already been taken"], w5.errors[:name], "Should have uniqueness message for name"
293
-
294
- w6 = Thaumaturgist.new(:name => "Mustrum Ridcully", :city => "Quirm")
295
- assert !w6.valid?, "w6 shouldn't be valid"
296
- assert w6.errors[:city].any?, "Should have errors for city"
297
- assert_equal ["has already been taken"], w6.errors[:city], "Should have uniqueness message for city"
298
- end
299
- end
1
+ # encoding: utf-8
2
+ require "cases/helper"
3
+ require 'models/topic'
4
+ require 'models/reply'
5
+ require 'models/warehouse_thing'
6
+ require 'models/guid'
7
+ require 'models/event'
8
+
9
+ class Wizard < ActiveRecord::Base
10
+ self.abstract_class = true
11
+
12
+ validates_uniqueness_of :name
13
+ end
14
+
15
+ class IneptWizard < Wizard
16
+ validates_uniqueness_of :city
17
+ end
18
+
19
+ class Conjurer < IneptWizard
20
+ end
21
+
22
+ class Thaumaturgist < IneptWizard
23
+ end
24
+
25
+ class ReplyTitle; end
26
+
27
+ class ReplyWithTitleObject < Reply
28
+ validates_uniqueness_of :content, :scope => :title
29
+
30
+ def title; ReplyTitle.new; end
31
+ end
32
+
33
+ class Employee < ActiveRecord::Base
34
+ self.table_name = 'postgresql_arrays'
35
+ validates_uniqueness_of :nicknames
36
+ end
37
+
38
+ class TopicWithUniqEvent < Topic
39
+ belongs_to :event, foreign_key: :parent_id
40
+ validates :event, uniqueness: true
41
+ end
42
+
43
+ class BigIntTest < ActiveRecord::Base
44
+ INT_MAX_VALUE = 2147483647
45
+ self.table_name = 'cars'
46
+ validates :engines_count, uniqueness: true, inclusion: { in: 0..INT_MAX_VALUE }
47
+ end
48
+
49
+ class BigIntReverseTest < ActiveRecord::Base
50
+ INT_MAX_VALUE = 2147483647
51
+ self.table_name = 'cars'
52
+ validates :engines_count, inclusion: { in: 0..INT_MAX_VALUE }
53
+ validates :engines_count, uniqueness: true
54
+ end
55
+
56
+ class UniquenessValidationTest < ActiveRecord::TestCase
57
+ INT_MAX_VALUE = 2147483647
58
+
59
+ fixtures :topics, 'warehouse_things'
60
+
61
+ repair_validations(Topic, Reply)
62
+
63
+ def test_validate_uniqueness
64
+ Topic.validates_uniqueness_of(:title)
65
+
66
+ t = Topic.new("title" => "I'm uniqué!")
67
+ assert t.save, "Should save t as unique"
68
+
69
+ t.content = "Remaining unique"
70
+ assert t.save, "Should still save t as unique"
71
+
72
+ t2 = Topic.new("title" => "I'm uniqué!")
73
+ assert !t2.valid?, "Shouldn't be valid"
74
+ assert !t2.save, "Shouldn't save t2 as unique"
75
+ assert_equal ["has already been taken"], t2.errors[:title]
76
+
77
+ t2.title = "Now I am really also unique"
78
+ assert t2.save, "Should now save t2 as unique"
79
+ end
80
+
81
+ def test_validate_uniqueness_with_alias_attribute
82
+ Topic.alias_attribute :new_title, :title
83
+ Topic.validates_uniqueness_of(:new_title)
84
+
85
+ topic = Topic.new(new_title: 'abc')
86
+ assert topic.valid?
87
+ end
88
+
89
+ def test_validates_uniqueness_with_nil_value
90
+ Topic.validates_uniqueness_of(:title)
91
+
92
+ t = Topic.new("title" => nil)
93
+ assert t.save, "Should save t as unique"
94
+
95
+ t2 = Topic.new("title" => nil)
96
+ assert !t2.valid?, "Shouldn't be valid"
97
+ assert !t2.save, "Shouldn't save t2 as unique"
98
+ assert_equal ["has already been taken"], t2.errors[:title]
99
+ end
100
+
101
+ def test_validates_uniqueness_with_validates
102
+ Topic.validates :title, :uniqueness => true
103
+ Topic.create!('title' => 'abc')
104
+
105
+ t2 = Topic.new('title' => 'abc')
106
+ assert !t2.valid?
107
+ assert t2.errors[:title]
108
+ end
109
+
110
+ def test_validate_uniqueness_when_integer_out_of_range
111
+ entry = BigIntTest.create(engines_count: INT_MAX_VALUE + 1)
112
+ assert_equal entry.errors[:engines_count], ['is not included in the list']
113
+ end
114
+
115
+ def test_validate_uniqueness_when_integer_out_of_range_show_order_does_not_matter
116
+ entry = BigIntReverseTest.create(engines_count: INT_MAX_VALUE + 1)
117
+ assert_equal entry.errors[:engines_count], ['is not included in the list']
118
+ end
119
+
120
+ def test_validates_uniqueness_with_newline_chars
121
+ Topic.validates_uniqueness_of(:title, :case_sensitive => false)
122
+
123
+ t = Topic.new("title" => "new\nline")
124
+ assert t.save, "Should save t as unique"
125
+ end
126
+
127
+ def test_validate_uniqueness_with_scope
128
+ Reply.validates_uniqueness_of(:content, :scope => "parent_id")
129
+
130
+ t = Topic.create("title" => "I'm unique!")
131
+
132
+ r1 = t.replies.create "title" => "r1", "content" => "hello world"
133
+ assert r1.valid?, "Saving r1"
134
+
135
+ r2 = t.replies.create "title" => "r2", "content" => "hello world"
136
+ assert !r2.valid?, "Saving r2 first time"
137
+
138
+ r2.content = "something else"
139
+ assert r2.save, "Saving r2 second time"
140
+
141
+ t2 = Topic.create("title" => "I'm unique too!")
142
+ r3 = t2.replies.create "title" => "r3", "content" => "hello world"
143
+ assert r3.valid?, "Saving r3"
144
+ end
145
+
146
+ def test_validate_uniqueness_with_object_scope
147
+ Reply.validates_uniqueness_of(:content, :scope => :topic)
148
+
149
+ t = Topic.create("title" => "I'm unique!")
150
+
151
+ r1 = t.replies.create "title" => "r1", "content" => "hello world"
152
+ assert r1.valid?, "Saving r1"
153
+
154
+ r2 = t.replies.create "title" => "r2", "content" => "hello world"
155
+ assert !r2.valid?, "Saving r2 first time"
156
+ end
157
+
158
+ def test_validate_uniqueness_with_composed_attribute_scope
159
+ r1 = ReplyWithTitleObject.create "title" => "r1", "content" => "hello world"
160
+ assert r1.valid?, "Saving r1"
161
+
162
+ r2 = ReplyWithTitleObject.create "title" => "r1", "content" => "hello world"
163
+ assert !r2.valid?, "Saving r2 first time"
164
+ end
165
+
166
+ def test_validate_uniqueness_with_object_arg
167
+ Reply.validates_uniqueness_of(:topic)
168
+
169
+ t = Topic.create("title" => "I'm unique!")
170
+
171
+ r1 = t.replies.create "title" => "r1", "content" => "hello world"
172
+ assert r1.valid?, "Saving r1"
173
+
174
+ r2 = t.replies.create "title" => "r2", "content" => "hello world"
175
+ assert !r2.valid?, "Saving r2 first time"
176
+ end
177
+
178
+ def test_validate_uniqueness_scoped_to_defining_class
179
+ t = Topic.create("title" => "What, me worry?")
180
+
181
+ r1 = t.unique_replies.create "title" => "r1", "content" => "a barrel of fun"
182
+ assert r1.valid?, "Saving r1"
183
+
184
+ r2 = t.silly_unique_replies.create "title" => "r2", "content" => "a barrel of fun"
185
+ assert !r2.valid?, "Saving r2"
186
+
187
+ # Should succeed as validates_uniqueness_of only applies to
188
+ # UniqueReply and its subclasses
189
+ r3 = t.replies.create "title" => "r2", "content" => "a barrel of fun"
190
+ assert r3.valid?, "Saving r3"
191
+ end
192
+
193
+ def test_validate_uniqueness_with_scope_array
194
+ Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id])
195
+
196
+ t = Topic.create("title" => "The earth is actually flat!")
197
+
198
+ r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply"
199
+ assert r1.valid?, "Saving r1"
200
+
201
+ r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..."
202
+ assert !r2.valid?, "Saving r2. Double reply by same author."
203
+
204
+ r2.author_email_address = "jeremy_alt_email@rubyonrails.com"
205
+ assert r2.save, "Saving r2 the second time."
206
+
207
+ r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic"
208
+ assert !r3.valid?, "Saving r3"
209
+
210
+ r3.author_name = "jj"
211
+ assert r3.save, "Saving r3 the second time."
212
+
213
+ r3.author_name = "jeremy"
214
+ assert !r3.save, "Saving r3 the third time."
215
+ end
216
+
217
+ def test_validate_case_insensitive_uniqueness
218
+ Topic.validates_uniqueness_of(:title, :parent_id, :case_sensitive => false, :allow_nil => true)
219
+
220
+ t = Topic.new("title" => "I'm unique!", :parent_id => 2)
221
+ assert t.save, "Should save t as unique"
222
+
223
+ t.content = "Remaining unique"
224
+ assert t.save, "Should still save t as unique"
225
+
226
+ t2 = Topic.new("title" => "I'm UNIQUE!", :parent_id => 1)
227
+ assert !t2.valid?, "Shouldn't be valid"
228
+ assert !t2.save, "Shouldn't save t2 as unique"
229
+ assert t2.errors[:title].any?
230
+ assert t2.errors[:parent_id].any?
231
+ assert_equal ["has already been taken"], t2.errors[:title]
232
+
233
+ t2.title = "I'm truly UNIQUE!"
234
+ assert !t2.valid?, "Shouldn't be valid"
235
+ assert !t2.save, "Shouldn't save t2 as unique"
236
+ assert t2.errors[:title].empty?
237
+ assert t2.errors[:parent_id].any?
238
+
239
+ t2.parent_id = 4
240
+ assert t2.save, "Should now save t2 as unique"
241
+
242
+ t2.parent_id = nil
243
+ t2.title = nil
244
+ assert t2.valid?, "should validate with nil"
245
+ assert t2.save, "should save with nil"
246
+
247
+ t_utf8 = Topic.new("title" => "Я тоже уникальный!")
248
+ assert t_utf8.save, "Should save t_utf8 as unique"
249
+
250
+ # If database hasn't UTF-8 character set, this test fails
251
+ if Topic.all.merge!(:select => 'LOWER(title) AS title').find(t_utf8.id).title == тоже уникальный!"
252
+ t2_utf8 = Topic.new("title" => "я тоже УНИКАЛЬНЫЙ!")
253
+ assert !t2_utf8.valid?, "Shouldn't be valid"
254
+ assert !t2_utf8.save, "Shouldn't save t2_utf8 as unique"
255
+ end
256
+ end
257
+
258
+ def test_validate_case_sensitive_uniqueness_with_special_sql_like_chars
259
+ Topic.validates_uniqueness_of(:title, :case_sensitive => true)
260
+
261
+ t = Topic.new("title" => "I'm unique!")
262
+ assert t.save, "Should save t as unique"
263
+
264
+ t2 = Topic.new("title" => "I'm %")
265
+ assert t2.save, "Should save t2 as unique"
266
+
267
+ t3 = Topic.new("title" => "I'm uniqu_!")
268
+ assert t3.save, "Should save t3 as unique"
269
+ end
270
+
271
+ def test_validate_case_insensitive_uniqueness_with_special_sql_like_chars
272
+ Topic.validates_uniqueness_of(:title, :case_sensitive => false)
273
+
274
+ t = Topic.new("title" => "I'm unique!")
275
+ assert t.save, "Should save t as unique"
276
+
277
+ t2 = Topic.new("title" => "I'm %")
278
+ assert t2.save, "Should save t2 as unique"
279
+
280
+ t3 = Topic.new("title" => "I'm uniqu_!")
281
+ assert t3.save, "Should save t3 as unique"
282
+ end
283
+
284
+ def test_validate_case_sensitive_uniqueness
285
+ Topic.validates_uniqueness_of(:title, :case_sensitive => true, :allow_nil => true)
286
+
287
+ t = Topic.new("title" => "I'm unique!")
288
+ assert t.save, "Should save t as unique"
289
+
290
+ t.content = "Remaining unique"
291
+ assert t.save, "Should still save t as unique"
292
+
293
+ t2 = Topic.new("title" => "I'M UNIQUE!")
294
+ assert t2.valid?, "Should be valid"
295
+ assert t2.save, "Should save t2 as unique"
296
+ assert t2.errors[:title].empty?
297
+ assert t2.errors[:parent_id].empty?
298
+ assert_not_equal ["has already been taken"], t2.errors[:title]
299
+
300
+ t3 = Topic.new("title" => "I'M uNiQUe!")
301
+ assert t3.valid?, "Should be valid"
302
+ assert t3.save, "Should save t2 as unique"
303
+ assert t3.errors[:title].empty?
304
+ assert t3.errors[:parent_id].empty?
305
+ assert_not_equal ["has already been taken"], t3.errors[:title]
306
+ end
307
+
308
+ def test_validate_case_sensitive_uniqueness_with_attribute_passed_as_integer
309
+ Topic.validates_uniqueness_of(:title, :case_sensitive => true)
310
+ Topic.create!('title' => 101)
311
+
312
+ t2 = Topic.new('title' => 101)
313
+ assert !t2.valid?
314
+ assert t2.errors[:title]
315
+ end
316
+
317
+ def test_validate_uniqueness_with_non_standard_table_names
318
+ i1 = WarehouseThing.create(:value => 1000)
319
+ assert !i1.valid?, "i1 should not be valid"
320
+ assert i1.errors[:value].any?, "Should not be empty"
321
+ end
322
+
323
+ def test_validates_uniqueness_inside_scoping
324
+ Topic.validates_uniqueness_of(:title)
325
+
326
+ Topic.where(:author_name => "David").scoping do
327
+ t1 = Topic.new("title" => "I'm unique!", "author_name" => "Mary")
328
+ assert t1.save
329
+ t2 = Topic.new("title" => "I'm unique!", "author_name" => "David")
330
+ assert !t2.valid?
331
+ end
332
+ end
333
+
334
+ def test_validate_uniqueness_with_columns_which_are_sql_keywords
335
+ repair_validations(Guid) do
336
+ Guid.validates_uniqueness_of :key
337
+ g = Guid.new
338
+ g.key = "foo"
339
+ assert_nothing_raised { !g.valid? }
340
+ end
341
+ end
342
+
343
+ def test_validate_uniqueness_with_limit
344
+ # Event.title is limited to 5 characters
345
+ e1 = Event.create(:title => "abcde")
346
+ assert e1.valid?, "Could not create an event with a unique, 5 character title"
347
+ e2 = Event.create(:title => "abcdefgh")
348
+ assert !e2.valid?, "Created an event whose title, with limit taken into account, is not unique"
349
+ end
350
+
351
+ def test_validate_uniqueness_with_limit_and_utf8
352
+ unless current_adapter?(:IBM_DBAdapter)
353
+ # Limit for the varchar field is number of bytes and not characters for DB2. Hence the below test cases is expected to fail.
354
+ # Event.title is limited to 5 characters
355
+ e1 = Event.create(:title => "一二三四五")
356
+ assert e1.valid?, "Could not create an event with a unique, 5 character title"
357
+ e2 = Event.create(:title => "一二三四五六七八")
358
+ assert !e2.valid?, "Created an event whose title, with limit taken into account, is not unique"
359
+ end
360
+ end
361
+
362
+ def test_validate_straight_inheritance_uniqueness
363
+ w1 = IneptWizard.create(:name => "Rincewind", :city => "Ankh-Morpork")
364
+ assert w1.valid?, "Saving w1"
365
+
366
+ # Should use validation from base class (which is abstract)
367
+ w2 = IneptWizard.new(:name => "Rincewind", :city => "Quirm")
368
+ assert !w2.valid?, "w2 shouldn't be valid"
369
+ assert w2.errors[:name].any?, "Should have errors for name"
370
+ assert_equal ["has already been taken"], w2.errors[:name], "Should have uniqueness message for name"
371
+
372
+ w3 = Conjurer.new(:name => "Rincewind", :city => "Quirm")
373
+ assert !w3.valid?, "w3 shouldn't be valid"
374
+ assert w3.errors[:name].any?, "Should have errors for name"
375
+ assert_equal ["has already been taken"], w3.errors[:name], "Should have uniqueness message for name"
376
+
377
+ w4 = Conjurer.create(:name => "The Amazing Bonko", :city => "Quirm")
378
+ assert w4.valid?, "Saving w4"
379
+
380
+ w5 = Thaumaturgist.new(:name => "The Amazing Bonko", :city => "Lancre")
381
+ assert !w5.valid?, "w5 shouldn't be valid"
382
+ assert w5.errors[:name].any?, "Should have errors for name"
383
+ assert_equal ["has already been taken"], w5.errors[:name], "Should have uniqueness message for name"
384
+
385
+ w6 = Thaumaturgist.new(:name => "Mustrum Ridcully", :city => "Quirm")
386
+ assert !w6.valid?, "w6 shouldn't be valid"
387
+ assert w6.errors[:city].any?, "Should have errors for city"
388
+ assert_equal ["has already been taken"], w6.errors[:city], "Should have uniqueness message for city"
389
+ end
390
+
391
+ def test_validate_uniqueness_with_conditions
392
+ Topic.validates_uniqueness_of :title, conditions: -> { where(approved: true) }
393
+ Topic.create("title" => "I'm a topic", "approved" => true)
394
+ Topic.create("title" => "I'm an unapproved topic", "approved" => false)
395
+
396
+ t3 = Topic.new("title" => "I'm a topic", "approved" => true)
397
+ assert !t3.valid?, "t3 shouldn't be valid"
398
+
399
+ t4 = Topic.new("title" => "I'm an unapproved topic", "approved" => false)
400
+ assert t4.valid?, "t4 should be valid"
401
+ end
402
+
403
+ def test_validate_uniqueness_with_non_callable_conditions_is_not_supported
404
+ assert_raises(ArgumentError) {
405
+ Topic.validates_uniqueness_of :title, conditions: Topic.where(approved: true)
406
+ }
407
+ end
408
+
409
+ if current_adapter? :PostgreSQLAdapter
410
+ def test_validate_uniqueness_with_array_column
411
+ e1 = Employee.create("nicknames" => ["john", "johnny"], "commission_by_quarter" => [1000, 1200])
412
+ assert e1.persisted?, "Saving e1"
413
+
414
+ e2 = Employee.create("nicknames" => ["john", "johnny"], "commission_by_quarter" => [2200])
415
+ assert !e2.persisted?, "e2 shouldn't be valid"
416
+ assert e2.errors[:nicknames].any?, "Should have errors for nicknames"
417
+ assert_equal ["has already been taken"], e2.errors[:nicknames], "Should have uniqueness message for nicknames"
418
+ end
419
+ end
420
+
421
+ def test_validate_uniqueness_on_existing_relation
422
+ event = Event.create
423
+ assert TopicWithUniqEvent.create(event: event).valid?
424
+
425
+ topic = TopicWithUniqEvent.new(event: event)
426
+ assert_not topic.valid?
427
+ assert_equal ['has already been taken'], topic.errors[:event]
428
+ end
429
+
430
+ def test_validate_uniqueness_on_empty_relation
431
+ topic = TopicWithUniqEvent.new
432
+ assert topic.valid?
433
+ end
434
+ end