ibm_db 3.0.5-x86-mingw32 → 4.0.0-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 (586) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +4 -0
  3. data/LICENSE +1 -1
  4. data/MANIFEST +14 -14
  5. data/ParameterizedQueries README +6 -6
  6. data/README +208 -225
  7. data/ext/Makefile.nt32 +181 -181
  8. data/ext/Makefile.nt32.191 +212 -212
  9. data/ext/extconf.rb +291 -291
  10. data/ext/ibm_db.c +11887 -11887
  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/init.rb +41 -41
  15. data/lib/IBM_DB.rb +27 -27
  16. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3452 -3177
  17. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -2
  18. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  19. data/lib/mswin32/ibm_db.rb +91 -123
  20. data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
  21. data/test/active_record/connection_adapters/fake_adapter.rb +49 -46
  22. data/test/assets/example.log +1 -1
  23. data/test/assets/test.txt +1 -1
  24. data/test/cases/adapter_test.rb +351 -276
  25. data/test/cases/adapters/mysql2/active_schema_test.rb +193 -0
  26. data/test/cases/adapters/mysql2/bind_parameter_test.rb +50 -0
  27. data/test/cases/adapters/mysql2/boolean_test.rb +100 -0
  28. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +63 -0
  29. data/test/cases/adapters/mysql2/charset_collation_test.rb +54 -0
  30. data/test/cases/adapters/mysql2/connection_test.rb +210 -0
  31. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +45 -0
  32. data/test/cases/adapters/mysql2/enum_test.rb +26 -0
  33. data/test/cases/adapters/mysql2/explain_test.rb +21 -0
  34. data/test/cases/adapters/mysql2/json_test.rb +195 -0
  35. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +83 -0
  36. data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -0
  37. data/test/cases/adapters/mysql2/schema_migrations_test.rb +59 -0
  38. data/test/cases/adapters/mysql2/schema_test.rb +126 -0
  39. data/test/cases/adapters/mysql2/sp_test.rb +36 -0
  40. data/test/cases/adapters/mysql2/sql_types_test.rb +14 -0
  41. data/test/cases/adapters/mysql2/table_options_test.rb +42 -0
  42. data/test/cases/adapters/mysql2/unsigned_type_test.rb +66 -0
  43. data/test/cases/adapters/postgresql/active_schema_test.rb +98 -0
  44. data/test/cases/adapters/postgresql/array_test.rb +339 -0
  45. data/test/cases/adapters/postgresql/bit_string_test.rb +82 -0
  46. data/test/cases/adapters/postgresql/bytea_test.rb +134 -0
  47. data/test/cases/adapters/postgresql/case_insensitive_test.rb +26 -0
  48. data/test/cases/adapters/postgresql/change_schema_test.rb +38 -0
  49. data/test/cases/adapters/postgresql/cidr_test.rb +25 -0
  50. data/test/cases/adapters/postgresql/citext_test.rb +78 -0
  51. data/test/cases/adapters/postgresql/collation_test.rb +53 -0
  52. data/test/cases/adapters/postgresql/composite_test.rb +132 -0
  53. data/test/cases/adapters/postgresql/connection_test.rb +257 -0
  54. data/test/cases/adapters/postgresql/datatype_test.rb +92 -0
  55. data/test/cases/adapters/postgresql/domain_test.rb +47 -0
  56. data/test/cases/adapters/postgresql/enum_test.rb +91 -0
  57. data/test/cases/adapters/postgresql/explain_test.rb +20 -0
  58. data/test/cases/adapters/postgresql/extension_migration_test.rb +63 -0
  59. data/test/cases/adapters/postgresql/full_text_test.rb +44 -0
  60. data/test/cases/adapters/postgresql/geometric_test.rb +378 -0
  61. data/test/cases/adapters/postgresql/hstore_test.rb +382 -0
  62. data/test/cases/adapters/postgresql/infinity_test.rb +69 -0
  63. data/test/cases/adapters/postgresql/integer_test.rb +25 -0
  64. data/test/cases/adapters/postgresql/json_test.rb +237 -0
  65. data/test/cases/adapters/postgresql/ltree_test.rb +53 -0
  66. data/test/cases/adapters/postgresql/money_test.rb +96 -0
  67. data/test/cases/adapters/postgresql/network_test.rb +94 -0
  68. data/test/cases/adapters/postgresql/numbers_test.rb +49 -0
  69. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +405 -0
  70. data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -0
  71. data/test/cases/adapters/postgresql/quoting_test.rb +44 -0
  72. data/test/cases/adapters/postgresql/range_test.rb +343 -0
  73. data/test/cases/adapters/postgresql/referential_integrity_test.rb +111 -0
  74. data/test/cases/adapters/postgresql/rename_table_test.rb +34 -0
  75. data/test/cases/adapters/postgresql/schema_authorization_test.rb +119 -0
  76. data/test/cases/adapters/postgresql/schema_test.rb +597 -0
  77. data/test/cases/adapters/postgresql/serial_test.rb +154 -0
  78. data/test/cases/adapters/postgresql/statement_pool_test.rb +41 -0
  79. data/test/cases/adapters/postgresql/timestamp_test.rb +90 -0
  80. data/test/cases/adapters/postgresql/type_lookup_test.rb +33 -0
  81. data/test/cases/adapters/postgresql/utils_test.rb +62 -0
  82. data/test/cases/adapters/postgresql/uuid_test.rb +294 -0
  83. data/test/cases/adapters/postgresql/xml_test.rb +54 -0
  84. data/test/cases/adapters/sqlite3/collation_test.rb +53 -0
  85. data/test/cases/adapters/sqlite3/copy_table_test.rb +98 -0
  86. data/test/cases/adapters/sqlite3/explain_test.rb +21 -0
  87. data/test/cases/adapters/sqlite3/quoting_test.rb +101 -0
  88. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +441 -0
  89. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -0
  90. data/test/cases/adapters/sqlite3/statement_pool_test.rb +20 -0
  91. data/test/cases/aggregations_test.rb +168 -158
  92. data/test/cases/ar_schema_test.rb +146 -161
  93. data/test/cases/associations/association_scope_test.rb +16 -21
  94. data/test/cases/associations/belongs_to_associations_test.rb +1141 -1029
  95. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +41 -0
  96. data/test/cases/associations/callbacks_test.rb +190 -192
  97. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
  98. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
  99. data/test/cases/associations/eager_load_nested_include_test.rb +126 -128
  100. data/test/cases/associations/eager_singularization_test.rb +148 -148
  101. data/test/cases/associations/eager_test.rb +1514 -1429
  102. data/test/cases/associations/extension_test.rb +87 -82
  103. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1004 -972
  104. data/test/cases/associations/has_many_associations_test.rb +2501 -2182
  105. data/test/cases/associations/has_many_through_associations_test.rb +1271 -1204
  106. data/test/cases/associations/has_one_associations_test.rb +707 -610
  107. data/test/cases/associations/has_one_through_associations_test.rb +383 -380
  108. data/test/cases/associations/inner_join_association_test.rb +139 -139
  109. data/test/cases/associations/inverse_associations_test.rb +733 -706
  110. data/test/cases/associations/join_model_test.rb +777 -754
  111. data/test/cases/associations/left_outer_join_association_test.rb +88 -0
  112. data/test/cases/associations/nested_through_associations_test.rb +579 -579
  113. data/test/cases/associations/required_test.rb +102 -82
  114. data/test/cases/associations_test.rb +385 -380
  115. data/test/cases/attribute_decorators_test.rb +125 -125
  116. data/test/cases/attribute_methods/read_test.rb +60 -60
  117. data/test/cases/attribute_methods_test.rb +1009 -952
  118. data/test/cases/attribute_set_test.rb +270 -210
  119. data/test/cases/attribute_test.rb +246 -180
  120. data/test/cases/attributes_test.rb +253 -136
  121. data/test/cases/autosave_association_test.rb +1708 -1595
  122. data/test/cases/base_test.rb +1713 -1664
  123. data/test/cases/batches_test.rb +489 -212
  124. data/test/cases/binary_test.rb +44 -52
  125. data/test/cases/bind_parameter_test.rb +110 -100
  126. data/test/cases/cache_key_test.rb +25 -0
  127. data/test/cases/calculations_test.rb +798 -646
  128. data/test/cases/callbacks_test.rb +636 -543
  129. data/test/cases/clone_test.rb +40 -40
  130. data/test/cases/coders/json_test.rb +15 -0
  131. data/test/cases/coders/yaml_column_test.rb +63 -63
  132. data/test/cases/collection_cache_key_test.rb +115 -0
  133. data/test/cases/column_alias_test.rb +17 -17
  134. data/test/cases/column_definition_test.rb +92 -123
  135. data/test/cases/comment_test.rb +143 -0
  136. data/test/cases/connection_adapters/adapter_leasing_test.rb +56 -54
  137. data/test/cases/connection_adapters/connection_handler_test.rb +160 -53
  138. data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
  139. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +255 -293
  140. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +69 -65
  141. data/test/cases/connection_adapters/quoting_test.rb +13 -13
  142. data/test/cases/connection_adapters/schema_cache_test.rb +61 -56
  143. data/test/cases/connection_adapters/type_lookup_test.rb +118 -110
  144. data/test/cases/connection_management_test.rb +112 -122
  145. data/test/cases/connection_pool_test.rb +521 -346
  146. data/test/cases/connection_specification/resolver_test.rb +131 -116
  147. data/test/cases/core_test.rb +112 -112
  148. data/test/cases/counter_cache_test.rb +214 -209
  149. data/test/cases/custom_locking_test.rb +17 -17
  150. data/test/cases/database_statements_test.rb +34 -19
  151. data/test/cases/{invalid_date_test.rb → date_test.rb} +44 -32
  152. data/test/cases/date_time_precision_test.rb +106 -0
  153. data/test/cases/date_time_test.rb +61 -61
  154. data/test/cases/defaults_test.rb +218 -223
  155. data/test/cases/dirty_test.rb +763 -785
  156. data/test/cases/disconnected_test.rb +30 -28
  157. data/test/cases/dup_test.rb +157 -157
  158. data/test/cases/enum_test.rb +444 -290
  159. data/test/cases/errors_test.rb +16 -0
  160. data/test/cases/explain_subscriber_test.rb +64 -64
  161. data/test/cases/explain_test.rb +87 -76
  162. data/test/cases/finder_respond_to_test.rb +60 -60
  163. data/test/cases/finder_test.rb +1294 -1169
  164. data/test/cases/fixture_set/file_test.rb +156 -138
  165. data/test/cases/fixtures_test.rb +988 -908
  166. data/test/cases/forbidden_attributes_protection_test.rb +165 -99
  167. data/test/cases/habtm_destroy_order_test.rb +61 -61
  168. data/test/cases/helper.rb +204 -210
  169. data/test/cases/hot_compatibility_test.rb +142 -54
  170. data/test/cases/i18n_test.rb +45 -45
  171. data/test/cases/inheritance_test.rb +606 -375
  172. data/test/cases/integration_test.rb +155 -139
  173. data/test/cases/invalid_connection_test.rb +24 -22
  174. data/test/cases/invertible_migration_test.rb +387 -295
  175. data/test/cases/json_serialization_test.rb +311 -302
  176. data/test/cases/locking_test.rb +493 -477
  177. data/test/cases/log_subscriber_test.rb +225 -136
  178. data/test/cases/migration/change_schema_test.rb +458 -512
  179. data/test/cases/migration/change_table_test.rb +256 -224
  180. data/test/cases/migration/column_attributes_test.rb +176 -192
  181. data/test/cases/migration/column_positioning_test.rb +56 -56
  182. data/test/cases/migration/columns_test.rb +310 -304
  183. data/test/cases/migration/command_recorder_test.rb +350 -305
  184. data/test/cases/migration/compatibility_test.rb +118 -0
  185. data/test/cases/migration/create_join_table_test.rb +157 -148
  186. data/test/cases/migration/foreign_key_test.rb +360 -328
  187. data/test/cases/migration/helper.rb +39 -39
  188. data/test/cases/migration/index_test.rb +218 -216
  189. data/test/cases/migration/logger_test.rb +36 -36
  190. data/test/cases/migration/pending_migrations_test.rb +52 -53
  191. data/test/cases/migration/references_foreign_key_test.rb +216 -169
  192. data/test/cases/migration/references_index_test.rb +101 -101
  193. data/test/cases/migration/references_statements_test.rb +136 -116
  194. data/test/cases/migration/rename_table_test.rb +93 -93
  195. data/test/cases/migration_test.rb +1157 -959
  196. data/test/cases/migrator_test.rb +470 -388
  197. data/test/cases/mixin_test.rb +68 -70
  198. data/test/cases/modules_test.rb +172 -173
  199. data/test/cases/multiparameter_attributes_test.rb +372 -350
  200. data/test/cases/multiple_db_test.rb +122 -115
  201. data/test/cases/nested_attributes_test.rb +1098 -1070
  202. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
  203. data/test/cases/persistence_test.rb +1001 -909
  204. data/test/cases/pooled_connections_test.rb +81 -81
  205. data/test/cases/primary_keys_test.rb +376 -237
  206. data/test/cases/query_cache_test.rb +446 -326
  207. data/test/cases/quoting_test.rb +202 -156
  208. data/test/cases/readonly_test.rb +119 -118
  209. data/test/cases/reaper_test.rb +85 -85
  210. data/test/cases/reflection_test.rb +509 -463
  211. data/test/cases/relation/delegation_test.rb +63 -68
  212. data/test/cases/relation/merging_test.rb +157 -161
  213. data/test/cases/relation/mutation_test.rb +183 -165
  214. data/test/cases/relation/or_test.rb +92 -0
  215. data/test/cases/relation/predicate_builder_test.rb +16 -14
  216. data/test/cases/relation/record_fetch_warning_test.rb +40 -0
  217. data/test/cases/relation/where_chain_test.rb +105 -181
  218. data/test/cases/relation/where_clause_test.rb +182 -0
  219. data/test/cases/relation/where_test.rb +322 -300
  220. data/test/cases/relation_test.rb +328 -319
  221. data/test/cases/relations_test.rb +2026 -1815
  222. data/test/cases/reload_models_test.rb +22 -22
  223. data/test/cases/result_test.rb +90 -80
  224. data/test/cases/sanitize_test.rb +176 -83
  225. data/test/cases/schema_dumper_test.rb +457 -463
  226. data/test/cases/schema_loading_test.rb +52 -0
  227. data/test/cases/scoping/default_scoping_test.rb +528 -454
  228. data/test/cases/scoping/named_scoping_test.rb +561 -524
  229. data/test/cases/scoping/relation_scoping_test.rb +400 -357
  230. data/test/cases/secure_token_test.rb +32 -0
  231. data/test/cases/serialization_test.rb +104 -104
  232. data/test/cases/serialized_attribute_test.rb +364 -277
  233. data/test/cases/statement_cache_test.rb +136 -98
  234. data/test/cases/store_test.rb +195 -194
  235. data/test/cases/suppressor_test.rb +63 -0
  236. data/test/cases/tasks/database_tasks_test.rb +462 -398
  237. data/test/cases/tasks/mysql_rake_test.rb +345 -324
  238. data/test/cases/tasks/postgresql_rake_test.rb +304 -250
  239. data/test/cases/tasks/sqlite_rake_test.rb +220 -193
  240. data/test/cases/test_case.rb +131 -123
  241. data/test/cases/test_fixtures_test.rb +36 -0
  242. data/test/cases/time_precision_test.rb +102 -0
  243. data/test/cases/timestamp_test.rb +501 -467
  244. data/test/cases/touch_later_test.rb +121 -0
  245. data/test/cases/transaction_callbacks_test.rb +518 -452
  246. data/test/cases/transaction_isolation_test.rb +106 -106
  247. data/test/cases/transactions_test.rb +834 -817
  248. data/test/cases/type/adapter_specific_registry_test.rb +133 -0
  249. data/test/cases/type/date_time_test.rb +14 -0
  250. data/test/cases/type/integer_test.rb +27 -121
  251. data/test/cases/type/string_test.rb +22 -36
  252. data/test/cases/type/type_map_test.rb +177 -177
  253. data/test/cases/type_test.rb +39 -0
  254. data/test/cases/types_test.rb +24 -141
  255. data/test/cases/unconnected_test.rb +33 -33
  256. data/test/cases/validations/absence_validation_test.rb +73 -0
  257. data/test/cases/validations/association_validation_test.rb +97 -86
  258. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
  259. data/test/cases/validations/i18n_validation_test.rb +86 -90
  260. data/test/cases/validations/length_validation_test.rb +79 -47
  261. data/test/cases/validations/presence_validation_test.rb +103 -68
  262. data/test/cases/validations/uniqueness_validation_test.rb +548 -457
  263. data/test/cases/validations_repair_helper.rb +19 -23
  264. data/test/cases/validations_test.rb +194 -165
  265. data/test/cases/view_test.rb +216 -119
  266. data/test/cases/yaml_serialization_test.rb +121 -126
  267. data/test/config.example.yml +97 -0
  268. data/test/config.rb +5 -5
  269. data/test/fixtures/accounts.yml +29 -29
  270. data/test/fixtures/admin/accounts.yml +2 -2
  271. data/test/fixtures/admin/users.yml +10 -10
  272. data/test/fixtures/author_addresses.original +11 -0
  273. data/test/fixtures/author_addresses.yml +17 -17
  274. data/test/fixtures/author_favorites.yml +3 -3
  275. data/test/fixtures/authors.original +17 -0
  276. data/test/fixtures/authors.yml +23 -23
  277. data/test/fixtures/bad_posts.yml +9 -0
  278. data/test/fixtures/binaries.yml +133 -133
  279. data/test/fixtures/books.yml +31 -11
  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 -0
  295. data/test/fixtures/content_positions.yml +3 -0
  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 -0
  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 -0
  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 -0
  333. data/test/fixtures/naked/yml/trees.yml +3 -0
  334. data/test/fixtures/nodes.yml +29 -0
  335. data/test/fixtures/organizations.yml +5 -5
  336. data/test/fixtures/other_comments.yml +6 -0
  337. data/test/fixtures/other_dogs.yml +2 -0
  338. data/test/fixtures/other_posts.yml +7 -0
  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 +15 -12
  347. data/test/fixtures/posts.yml +80 -80
  348. data/test/fixtures/price_estimates.yml +16 -7
  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 -0
  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/randomly_named_c1.rb +6 -2
  414. data/test/models/admin/user.rb +40 -40
  415. data/test/models/aircraft.rb +5 -4
  416. data/test/models/arunit2_model.rb +3 -3
  417. data/test/models/author.rb +209 -212
  418. data/test/models/auto_id.rb +4 -4
  419. data/test/models/autoloadable/extra_firm.rb +2 -2
  420. data/test/models/binary.rb +2 -2
  421. data/test/models/bird.rb +12 -12
  422. data/test/models/book.rb +23 -18
  423. data/test/models/boolean.rb +2 -2
  424. data/test/models/bulb.rb +52 -51
  425. data/test/models/cake_designer.rb +3 -3
  426. data/test/models/car.rb +29 -26
  427. data/test/models/carrier.rb +2 -2
  428. data/test/models/cat.rb +10 -0
  429. data/test/models/categorization.rb +19 -19
  430. data/test/models/category.rb +35 -35
  431. data/test/models/chef.rb +8 -7
  432. data/test/models/citation.rb +3 -3
  433. data/test/models/club.rb +25 -23
  434. data/test/models/college.rb +10 -10
  435. data/test/models/column.rb +3 -3
  436. data/test/models/column_name.rb +3 -3
  437. data/test/models/comment.rb +76 -64
  438. data/test/models/company.rb +230 -228
  439. data/test/models/company_in_module.rb +98 -98
  440. data/test/models/computer.rb +3 -3
  441. data/test/models/contact.rb +41 -41
  442. data/test/models/content.rb +40 -0
  443. data/test/models/contract.rb +20 -20
  444. data/test/models/country.rb +7 -7
  445. data/test/models/course.rb +6 -6
  446. data/test/models/customer.rb +83 -77
  447. data/test/models/customer_carrier.rb +14 -14
  448. data/test/models/dashboard.rb +3 -3
  449. data/test/models/default.rb +2 -2
  450. data/test/models/department.rb +4 -4
  451. data/test/models/developer.rb +274 -255
  452. data/test/models/dog.rb +5 -5
  453. data/test/models/dog_lover.rb +5 -5
  454. data/test/models/doubloon.rb +12 -12
  455. data/test/models/drink_designer.rb +3 -3
  456. data/test/models/edge.rb +5 -5
  457. data/test/models/electron.rb +5 -5
  458. data/test/models/engine.rb +4 -4
  459. data/test/models/entrant.rb +3 -3
  460. data/test/models/essay.rb +5 -5
  461. data/test/models/event.rb +3 -3
  462. data/test/models/eye.rb +37 -37
  463. data/test/models/face.rb +9 -9
  464. data/test/models/friendship.rb +6 -6
  465. data/test/models/guid.rb +2 -2
  466. data/test/models/guitar.rb +4 -0
  467. data/test/models/hotel.rb +11 -9
  468. data/test/models/image.rb +3 -3
  469. data/test/models/interest.rb +5 -5
  470. data/test/models/invoice.rb +4 -4
  471. data/test/models/item.rb +7 -7
  472. data/test/models/job.rb +7 -7
  473. data/test/models/joke.rb +7 -7
  474. data/test/models/keyboard.rb +3 -3
  475. data/test/models/legacy_thing.rb +3 -3
  476. data/test/models/lesson.rb +11 -11
  477. data/test/models/line_item.rb +3 -3
  478. data/test/models/liquid.rb +4 -4
  479. data/test/models/man.rb +11 -11
  480. data/test/models/matey.rb +4 -4
  481. data/test/models/member.rb +42 -41
  482. data/test/models/member_detail.rb +8 -7
  483. data/test/models/member_type.rb +3 -3
  484. data/test/models/membership.rb +35 -35
  485. data/test/models/mentor.rb +3 -0
  486. data/test/models/minimalistic.rb +2 -2
  487. data/test/models/minivan.rb +9 -9
  488. data/test/models/mixed_case_monkey.rb +3 -3
  489. data/test/models/mocktail_designer.rb +2 -0
  490. data/test/models/molecule.rb +6 -6
  491. data/test/models/movie.rb +5 -5
  492. data/test/models/node.rb +5 -0
  493. data/test/models/non_primary_key.rb +2 -0
  494. data/test/models/notification.rb +3 -0
  495. data/test/models/order.rb +4 -4
  496. data/test/models/organization.rb +14 -14
  497. data/test/models/other_dog.rb +5 -0
  498. data/test/models/owner.rb +37 -34
  499. data/test/models/parrot.rb +28 -29
  500. data/test/models/person.rb +142 -143
  501. data/test/models/personal_legacy_thing.rb +4 -4
  502. data/test/models/pet.rb +18 -15
  503. data/test/models/pet_treasure.rb +6 -0
  504. data/test/models/pirate.rb +92 -92
  505. data/test/models/possession.rb +3 -3
  506. data/test/models/post.rb +273 -264
  507. data/test/models/price_estimate.rb +4 -4
  508. data/test/models/professor.rb +5 -5
  509. data/test/models/project.rb +40 -31
  510. data/test/models/publisher.rb +2 -2
  511. data/test/models/publisher/article.rb +4 -4
  512. data/test/models/publisher/magazine.rb +3 -3
  513. data/test/models/randomly_named_c1.rb +1 -1
  514. data/test/models/rating.rb +4 -4
  515. data/test/models/reader.rb +23 -23
  516. data/test/models/recipe.rb +3 -0
  517. data/test/models/record.rb +2 -2
  518. data/test/models/reference.rb +22 -22
  519. data/test/models/reply.rb +61 -61
  520. data/test/models/ship.rb +39 -33
  521. data/test/models/ship_part.rb +8 -8
  522. data/test/models/shop.rb +17 -17
  523. data/test/models/shop_account.rb +6 -6
  524. data/test/models/speedometer.rb +6 -6
  525. data/test/models/sponsor.rb +7 -7
  526. data/test/models/string_key_object.rb +3 -3
  527. data/test/models/student.rb +4 -4
  528. data/test/models/subject.rb +16 -16
  529. data/test/models/subscriber.rb +8 -8
  530. data/test/models/subscription.rb +4 -4
  531. data/test/models/tag.rb +13 -7
  532. data/test/models/tagging.rb +13 -13
  533. data/test/models/task.rb +5 -5
  534. data/test/models/topic.rb +118 -124
  535. data/test/models/toy.rb +6 -6
  536. data/test/models/traffic_light.rb +4 -4
  537. data/test/models/treasure.rb +14 -14
  538. data/test/models/treaty.rb +7 -7
  539. data/test/models/tree.rb +3 -0
  540. data/test/models/tuning_peg.rb +4 -0
  541. data/test/models/tyre.rb +11 -11
  542. data/test/models/user.rb +14 -0
  543. data/test/models/uuid_child.rb +3 -3
  544. data/test/models/uuid_item.rb +6 -0
  545. data/test/models/uuid_parent.rb +3 -3
  546. data/test/models/vegetables.rb +24 -24
  547. data/test/models/vehicle.rb +6 -6
  548. data/test/models/vertex.rb +9 -9
  549. data/test/models/warehouse_thing.rb +5 -5
  550. data/test/models/wheel.rb +3 -3
  551. data/test/models/without_table.rb +3 -3
  552. data/test/models/zine.rb +3 -3
  553. data/test/schema/mysql2_specific_schema.rb +68 -58
  554. data/test/schema/oracle_specific_schema.rb +40 -43
  555. data/test/schema/postgresql_specific_schema.rb +114 -202
  556. data/test/schema/schema.rb +1057 -952
  557. data/test/schema/schema.rb.original +1057 -0
  558. data/test/schema/sqlite_specific_schema.rb +18 -22
  559. data/test/support/config.rb +43 -43
  560. data/test/support/connection.rb +23 -22
  561. data/test/support/connection_helper.rb +14 -14
  562. data/test/support/ddl_helper.rb +8 -8
  563. data/test/support/schema_dumping_helper.rb +20 -20
  564. data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -0
  565. data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -0
  566. metadata +129 -28
  567. data/lib/mswin32/rb19x/ibm_db.so +0 -0
  568. data/lib/mswin32/rb21x/i386/ibm_db.so +0 -0
  569. data/lib/mswin32/rb22x/i386/ibm_db.so +0 -0
  570. data/lib/mswin32/rb23x/i386/ibm_db.so +0 -0
  571. data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +0 -26
  572. data/test/cases/attribute_methods/serialization_test.rb +0 -29
  573. data/test/cases/migration/change_schema_test - Copy.rb +0 -448
  574. data/test/cases/migration/foreign_key_test - Changed.rb +0 -325
  575. data/test/cases/migration/table_and_index_test.rb +0 -24
  576. data/test/cases/relation/where_test2.rb +0 -36
  577. data/test/cases/type/decimal_test.rb +0 -56
  578. data/test/cases/type/unsigned_integer_test.rb +0 -18
  579. data/test/cases/xml_serialization_test.rb +0 -457
  580. data/test/connections/native_ibm_db/connection.rb +0 -44
  581. data/test/fixtures/naked/csv/accounts.csv +0 -1
  582. data/test/schema/i5/ibm_db_specific_schema.rb +0 -137
  583. data/test/schema/ids/ibm_db_specific_schema.rb +0 -140
  584. data/test/schema/luw/ibm_db_specific_schema.rb +0 -137
  585. data/test/schema/mysql_specific_schema.rb +0 -70
  586. data/test/schema/zOS/ibm_db_specific_schema.rb +0 -208
@@ -1,93 +1,93 @@
1
- require "cases/migration/helper"
2
-
3
- module ActiveRecord
4
- class Migration
5
- class RenameTableTest < ActiveRecord::TestCase
6
- include ActiveRecord::Migration::TestHelper
7
-
8
- self.use_transactional_fixtures = false
9
-
10
- def setup
11
- super
12
- add_column 'test_models', :url, :string
13
- remove_column 'test_models', :created_at
14
- remove_column 'test_models', :updated_at
15
- end
16
-
17
- def teardown
18
- rename_table :octopi, :test_models if connection.table_exists? :octopi
19
- super
20
- end
21
-
22
- if current_adapter?(:SQLite3Adapter)
23
- def test_rename_table_for_sqlite_should_work_with_reserved_words
24
- renamed = false
25
-
26
- add_column :test_models, :url, :string
27
- connection.rename_table :references, :old_references
28
- connection.rename_table :test_models, :references
29
-
30
- renamed = true
31
-
32
- # Using explicit id in insert for compatibility across all databases
33
- connection.execute "INSERT INTO 'references' (url, created_at, updated_at) VALUES ('http://rubyonrails.com', 0, 0)"
34
- assert_equal 'http://rubyonrails.com', connection.select_value("SELECT url FROM 'references' WHERE id=1")
35
- ensure
36
- return unless renamed
37
- connection.rename_table :references, :test_models
38
- connection.rename_table :old_references, :references
39
- end
40
- end
41
-
42
- def test_rename_table
43
- rename_table :test_models, :octopi
44
-
45
- connection.execute "INSERT INTO octopi (#{connection.quote_column_name('id')}, #{connection.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')"
46
-
47
- assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', connection.select_value("SELECT url FROM octopi WHERE id=1")
48
- end
49
-
50
- def test_rename_table_with_an_index
51
- add_index :test_models, :url
52
-
53
- rename_table :test_models, :octopi
54
-
55
- connection.execute "INSERT INTO octopi (#{connection.quote_column_name('id')}, #{connection.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')"
56
-
57
- assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', connection.select_value("SELECT url FROM octopi WHERE id=1")
58
- index = connection.indexes(:octopi).first
59
- assert index.columns.include?("url")
60
- assert_equal 'index_octopi_on_url', index.name
61
- end
62
-
63
- def test_rename_table_does_not_rename_custom_named_index
64
- add_index :test_models, :url, name: 'special_url_idx'
65
-
66
- rename_table :test_models, :octopi
67
-
68
- assert_equal ['special_url_idx'], connection.indexes(:octopi).map(&:name)
69
- end
70
-
71
- if current_adapter?(:PostgreSQLAdapter)
72
- def test_rename_table_for_postgresql_should_also_rename_default_sequence
73
- rename_table :test_models, :octopi
74
-
75
- pk, seq = connection.pk_and_sequence_for('octopi')
76
-
77
- assert_equal ConnectionAdapters::PostgreSQL::Name.new("public", "octopi_#{pk}_seq"), seq
78
- end
79
-
80
- def test_renaming_table_doesnt_attempt_to_rename_non_existent_sequences
81
- enable_extension!('uuid-ossp', connection)
82
- connection.create_table :cats, id: :uuid
83
- assert_nothing_raised { rename_table :cats, :felines }
84
- assert connection.table_exists? :felines
85
- ensure
86
- disable_extension!('uuid-ossp', connection)
87
- connection.drop_table :cats if connection.table_exists? :cats
88
- connection.drop_table :felines if connection.table_exists? :felines
89
- end
90
- end
91
- end
92
- end
93
- end
1
+ require "cases/migration/helper"
2
+
3
+ module ActiveRecord
4
+ class Migration
5
+ class RenameTableTest < ActiveRecord::TestCase
6
+ include ActiveRecord::Migration::TestHelper
7
+
8
+ self.use_transactional_tests = false
9
+
10
+ def setup
11
+ super
12
+ add_column 'test_models', :url, :string
13
+ remove_column 'test_models', :created_at
14
+ remove_column 'test_models', :updated_at
15
+ end
16
+
17
+ def teardown
18
+ ActiveSupport::Deprecation.silence { rename_table :octopi, :test_models if connection.table_exists? :octopi }
19
+ super
20
+ end
21
+
22
+ if current_adapter?(:SQLite3Adapter)
23
+ def test_rename_table_for_sqlite_should_work_with_reserved_words
24
+ renamed = false
25
+
26
+ add_column :test_models, :url, :string
27
+ connection.rename_table :references, :old_references
28
+ connection.rename_table :test_models, :references
29
+
30
+ renamed = true
31
+
32
+ # Using explicit id in insert for compatibility across all databases
33
+ connection.execute "INSERT INTO 'references' (url, created_at, updated_at) VALUES ('http://rubyonrails.com', 0, 0)"
34
+ assert_equal 'http://rubyonrails.com', connection.select_value("SELECT url FROM 'references' WHERE id=1")
35
+ ensure
36
+ return unless renamed
37
+ connection.rename_table :references, :test_models
38
+ connection.rename_table :old_references, :references
39
+ end
40
+ end
41
+
42
+ unless current_adapter?(:FbAdapter) # Firebird cannot rename tables
43
+ def test_rename_table
44
+ rename_table :test_models, :octopi
45
+
46
+ connection.execute "INSERT INTO octopi (#{connection.quote_column_name('id')}, #{connection.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')"
47
+
48
+ assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', connection.select_value("SELECT url FROM octopi WHERE id=1")
49
+ end
50
+
51
+ def test_rename_table_with_an_index
52
+ add_index :test_models, :url
53
+
54
+ rename_table :test_models, :octopi
55
+
56
+ connection.execute "INSERT INTO octopi (#{connection.quote_column_name('id')}, #{connection.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')"
57
+
58
+ assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', connection.select_value("SELECT url FROM octopi WHERE id=1")
59
+ index = connection.indexes(:octopi).first
60
+ assert index.columns.include?("url")
61
+ assert_equal 'index_octopi_on_url', index.name
62
+ end
63
+
64
+ def test_rename_table_does_not_rename_custom_named_index
65
+ add_index :test_models, :url, name: 'special_url_idx'
66
+
67
+ rename_table :test_models, :octopi
68
+
69
+ assert_equal ['special_url_idx'], connection.indexes(:octopi).map(&:name)
70
+ end
71
+ end
72
+
73
+ if current_adapter?(:PostgreSQLAdapter)
74
+ def test_rename_table_for_postgresql_should_also_rename_default_sequence
75
+ rename_table :test_models, :octopi
76
+
77
+ pk, seq = connection.pk_and_sequence_for('octopi')
78
+
79
+ assert_equal ConnectionAdapters::PostgreSQL::Name.new("public", "octopi_#{pk}_seq"), seq
80
+ end
81
+
82
+ def test_renaming_table_doesnt_attempt_to_rename_non_existent_sequences
83
+ connection.create_table :cats, id: :uuid
84
+ assert_nothing_raised { rename_table :cats, :felines }
85
+ ActiveSupport::Deprecation.silence { assert connection.table_exists? :felines }
86
+ ensure
87
+ connection.drop_table :cats, if_exists: true
88
+ connection.drop_table :felines, if_exists: true
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -1,959 +1,1157 @@
1
- require "cases/helper"
2
- require "cases/migration/helper"
3
- require 'bigdecimal/util'
4
-
5
- require 'models/person'
6
- require 'models/topic'
7
- require 'models/developer'
8
- require 'models/computer'
9
-
10
- require MIGRATIONS_ROOT + "/valid/2_we_need_reminders"
11
- require MIGRATIONS_ROOT + "/rename/1_we_need_things"
12
- require MIGRATIONS_ROOT + "/rename/2_rename_things"
13
- require MIGRATIONS_ROOT + "/decimal/1_give_me_big_numbers"
14
-
15
- class BigNumber < ActiveRecord::Base
16
- unless current_adapter?(:PostgreSQLAdapter, :SQLite3Adapter)
17
- attribute :value_of_e, Type::Integer.new
18
- end
19
- attribute :my_house_population, Type::Integer.new
20
- end
21
-
22
- class Reminder < ActiveRecord::Base; end
23
-
24
- class Thing < ActiveRecord::Base; end
25
-
26
- class MigrationTest < ActiveRecord::TestCase
27
- self.use_transactional_fixtures = false
28
-
29
- fixtures :people
30
-
31
- if (current_adapter?(:IBM_DBAdapter))
32
- #Rename is supported only for server zOS 9 , DB2 COBRA and Informix
33
- server_type = ActiveRecord::Base.connection.servertype.class.name
34
- @ibm_db_rename_supported = server_type.include?('::IBM_DB2_LUW_COBRA') ||
35
- server_type.class.name.include?('::IBM_IDS') ||
36
- (server_type.include?('IBM_DB2_ZOS') && !server_type.include?('IBM_DB2_ZOS_8'))
37
- end
38
-
39
- def setup
40
- super
41
- %w(reminders people_reminders prefix_reminders_suffix p_things_s).each do |table|
42
- Reminder.connection.drop_table(table) rescue nil
43
- end
44
- Reminder.reset_column_information
45
- @verbose_was, ActiveRecord::Migration.verbose = ActiveRecord::Migration.verbose, false
46
- ActiveRecord::Base.connection.schema_cache.clear!
47
- end
48
-
49
- teardown do
50
- ActiveRecord::Base.table_name_prefix = ""
51
- ActiveRecord::Base.table_name_suffix = ""
52
-
53
- ActiveRecord::Base.connection.initialize_schema_migrations_table
54
- ActiveRecord::Base.connection.execute "DELETE FROM #{ActiveRecord::Migrator.schema_migrations_table_name}"
55
-
56
- %w(things awesome_things prefix_things_suffix p_awesome_things_s ).each do |table|
57
- Thing.connection.drop_table(table) rescue nil
58
- end
59
- Thing.reset_column_information
60
-
61
- %w(reminders people_reminders prefix_reminders_suffix).each do |table|
62
- Reminder.connection.drop_table(table) rescue nil
63
- end
64
- Reminder.reset_table_name
65
- Reminder.reset_column_information
66
-
67
- %w(last_name key bio age height wealth birthday favorite_day
68
- moment_of_truth male administrator funny).each do |column|
69
- Person.connection.remove_column('people', column) rescue nil
70
- end
71
- Person.connection.remove_column("people", "first_name") rescue nil
72
- Person.connection.remove_column("people", "middle_name") rescue nil
73
- Person.connection.add_column("people", "first_name", :string)
74
- Person.reset_column_information
75
-
76
- ActiveRecord::Migration.verbose = @verbose_was
77
- end
78
-
79
- def test_migrator_versions
80
- migrations_path = MIGRATIONS_ROOT + "/valid"
81
- old_path = ActiveRecord::Migrator.migrations_paths
82
- ActiveRecord::Migrator.migrations_paths = migrations_path
83
-
84
- ActiveRecord::Migrator.up(migrations_path)
85
- assert_equal 3, ActiveRecord::Migrator.current_version
86
- assert_equal 3, ActiveRecord::Migrator.last_version
87
- assert_equal false, ActiveRecord::Migrator.needs_migration?
88
-
89
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid")
90
- assert_equal 0, ActiveRecord::Migrator.current_version
91
- assert_equal 3, ActiveRecord::Migrator.last_version
92
- assert_equal true, ActiveRecord::Migrator.needs_migration?
93
-
94
- ActiveRecord::SchemaMigration.create!(:version => ActiveRecord::Migrator.last_version)
95
- assert_equal true, ActiveRecord::Migrator.needs_migration?
96
- ensure
97
- ActiveRecord::Migrator.migrations_paths = old_path
98
- end
99
-
100
- def test_migration_detection_without_schema_migration_table
101
- ActiveRecord::Base.connection.drop_table('schema_migrations') if ActiveRecord::Base.connection.table_exists?('schema_migrations')
102
-
103
- migrations_path = MIGRATIONS_ROOT + "/valid"
104
- old_path = ActiveRecord::Migrator.migrations_paths
105
- ActiveRecord::Migrator.migrations_paths = migrations_path
106
-
107
- assert_equal true, ActiveRecord::Migrator.needs_migration?
108
- ensure
109
- ActiveRecord::Migrator.migrations_paths = old_path
110
- end
111
-
112
- def test_any_migrations
113
- old_path = ActiveRecord::Migrator.migrations_paths
114
- ActiveRecord::Migrator.migrations_paths = MIGRATIONS_ROOT + "/valid"
115
-
116
- assert ActiveRecord::Migrator.any_migrations?
117
-
118
- ActiveRecord::Migrator.migrations_paths = MIGRATIONS_ROOT + "/empty"
119
-
120
- assert_not ActiveRecord::Migrator.any_migrations?
121
- ensure
122
- ActiveRecord::Migrator.migrations_paths = old_path
123
- end
124
-
125
- def test_migration_version
126
- ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/version_check", 20131219224947)
127
- end
128
-
129
- def test_create_table_with_force_true_does_not_drop_nonexisting_table
130
- if Person.connection.table_exists?(:testings2)
131
- Person.connection.drop_table :testings2
132
- end
133
-
134
- # using a copy as we need the drop_table method to
135
- # continue to work for the ensure block of the test
136
- temp_conn = Person.connection.dup
137
-
138
- assert_not_equal temp_conn, Person.connection
139
-
140
- temp_conn.create_table :testings2, :force => true do |t|
141
- t.column :foo, :string
142
- end
143
- ensure
144
- Person.connection.drop_table :testings2 rescue nil
145
- end
146
-
147
- def connection
148
- ActiveRecord::Base.connection
149
- end
150
-
151
- def test_migration_instance_has_connection
152
- migration = Class.new(ActiveRecord::Migration).new
153
- assert_equal connection, migration.connection
154
- end
155
-
156
- def test_method_missing_delegates_to_connection
157
- migration = Class.new(ActiveRecord::Migration) {
158
- def connection
159
- Class.new {
160
- def create_table; "hi mom!"; end
161
- }.new
162
- end
163
- }.new
164
-
165
- assert_equal "hi mom!", migration.method_missing(:create_table)
166
- end
167
-
168
- def test_add_table_with_decimals
169
- Person.connection.drop_table :big_numbers rescue nil
170
-
171
- assert !BigNumber.table_exists?
172
- GiveMeBigNumbers.up
173
-
174
- assert BigNumber.create(
175
- :bank_balance => 1586.43,
176
- :big_bank_balance => BigDecimal("1000234000567.95"),
177
- :world_population => 6000000000,
178
- :my_house_population => 3,
179
- :value_of_e => BigDecimal("2.7182818284590452353602875")
180
- )
181
-
182
- b = BigNumber.first
183
- assert_not_nil b
184
-
185
- assert_not_nil b.bank_balance
186
- assert_not_nil b.big_bank_balance
187
- assert_not_nil b.world_population
188
- assert_not_nil b.my_house_population
189
- assert_not_nil b.value_of_e
190
-
191
- # TODO: set world_population >= 2**62 to cover 64-bit platforms and test
192
- # is_a?(Bignum)
193
- unless current_adapter?(:IBM_DBAdapter)
194
- assert_kind_of Integer, b.world_population
195
- else
196
- assert_kind_of BigDecimal, b.world_population
197
- end
198
- assert_equal 6000000000, b.world_population
199
- unless current_adapter?(:IBM_DBAdapter)
200
- assert_kind_of Fixnum, b.my_house_population
201
- else
202
- assert_kind_of BigDecimal, b.my_house_population
203
- end
204
- assert_equal 3, b.my_house_population
205
- assert_kind_of BigDecimal, b.bank_balance
206
- assert_equal BigDecimal("1586.43"), b.bank_balance
207
- assert_kind_of BigDecimal, b.big_bank_balance
208
- assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance
209
-
210
- # This one is fun. The 'value_of_e' field is defined as 'DECIMAL' with
211
- # precision/scale explicitly left out. By the SQL standard, numbers
212
- # assigned to this field should be truncated but that's seldom respected.
213
- if current_adapter?(:PostgreSQLAdapter)
214
- # - PostgreSQL changes the SQL spec on columns declared simply as
215
- # "decimal" to something more useful: instead of being given a scale
216
- # of 0, they take on the compile-time limit for precision and scale,
217
- # so the following should succeed unless you have used really wacky
218
- # compilation options
219
- # - SQLite2 has the default behavior of preserving all data sent in,
220
- # so this happens there too
221
- assert_kind_of BigDecimal, b.value_of_e
222
- assert_equal BigDecimal("2.7182818284590452353602875"), b.value_of_e
223
- elsif current_adapter?(:SQLite3Adapter)
224
- # - SQLite3 stores a float, in violation of SQL
225
- assert_kind_of BigDecimal, b.value_of_e
226
- assert_in_delta BigDecimal("2.71828182845905"), b.value_of_e, 0.00000000000001
227
- else
228
- # - SQL standard is an integer
229
- unless current_adapter?(:IBM_DBAdapter)
230
- assert_kind_of Fixnum, b.value_of_e
231
- else
232
- assert_kind_of BigDecimal, b.value_of_e
233
- end
234
- assert_equal 2, b.value_of_e
235
- end
236
-
237
- GiveMeBigNumbers.down
238
- assert_raise(ActiveRecord::StatementInvalid) { BigNumber.first }
239
- end
240
-
241
- def test_filtering_migrations
242
- assert_no_column Person, :last_name
243
- assert !Reminder.table_exists?
244
-
245
- name_filter = lambda { |migration| migration.name == "ValidPeopleHaveLastNames" }
246
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", &name_filter)
247
-
248
- assert_column Person, :last_name
249
- assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
250
-
251
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", &name_filter)
252
-
253
- assert_no_column Person, :last_name
254
- assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
255
- end
256
-
257
- class MockMigration < ActiveRecord::Migration
258
- attr_reader :went_up, :went_down
259
- def initialize
260
- @went_up = false
261
- @went_down = false
262
- end
263
-
264
- def up
265
- @went_up = true
266
- super
267
- end
268
-
269
- def down
270
- @went_down = true
271
- super
272
- end
273
- end
274
-
275
- def test_instance_based_migration_up
276
- migration = MockMigration.new
277
- assert !migration.went_up, 'have not gone up'
278
- assert !migration.went_down, 'have not gone down'
279
-
280
- migration.migrate :up
281
- assert migration.went_up, 'have gone up'
282
- assert !migration.went_down, 'have not gone down'
283
- end
284
-
285
- def test_instance_based_migration_down
286
- migration = MockMigration.new
287
- assert !migration.went_up, 'have not gone up'
288
- assert !migration.went_down, 'have not gone down'
289
-
290
- migration.migrate :down
291
- assert !migration.went_up, 'have gone up'
292
- assert migration.went_down, 'have not gone down'
293
- end
294
-
295
- if ActiveRecord::Base.connection.supports_ddl_transactions?
296
- def test_migrator_one_up_with_exception_and_rollback
297
- assert_no_column Person, :last_name
298
-
299
- migration = Class.new(ActiveRecord::Migration) {
300
- def version; 100 end
301
- def migrate(x)
302
- add_column "people", "last_name", :string
303
- raise 'Something broke'
304
- end
305
- }.new
306
-
307
- migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
308
-
309
- e = assert_raise(StandardError) { migrator.migrate }
310
-
311
- assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message
312
-
313
- assert_no_column Person, :last_name,
314
- "On error, the Migrator should revert schema changes but it did not."
315
- end
316
-
317
- def test_migrator_one_up_with_exception_and_rollback_using_run
318
- assert_no_column Person, :last_name
319
-
320
- migration = Class.new(ActiveRecord::Migration) {
321
- def version; 100 end
322
- def migrate(x)
323
- add_column "people", "last_name", :string
324
- raise 'Something broke'
325
- end
326
- }.new
327
-
328
- migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
329
-
330
- e = assert_raise(StandardError) { migrator.run }
331
-
332
- assert_equal "An error has occurred, this migration was canceled:\n\nSomething broke", e.message
333
-
334
- assert_no_column Person, :last_name,
335
- "On error, the Migrator should revert schema changes but it did not."
336
- end
337
-
338
- def test_migration_without_transaction
339
- assert_no_column Person, :last_name
340
-
341
- migration = Class.new(ActiveRecord::Migration) {
342
- self.disable_ddl_transaction!
343
-
344
- def version; 101 end
345
- def migrate(x)
346
- add_column "people", "last_name", :string
347
- raise 'Something broke'
348
- end
349
- }.new
350
-
351
- migrator = ActiveRecord::Migrator.new(:up, [migration], 101)
352
- e = assert_raise(StandardError) { migrator.migrate }
353
- assert_equal "An error has occurred, all later migrations canceled:\n\nSomething broke", e.message
354
-
355
- assert_column Person, :last_name,
356
- "without ddl transactions, the Migrator should not rollback on error but it did."
357
- ensure
358
- Person.reset_column_information
359
- if Person.column_names.include?('last_name')
360
- Person.connection.remove_column('people', 'last_name')
361
- end
362
- end
363
- end
364
-
365
- def test_schema_migrations_table_name
366
- original_schema_migrations_table_name = ActiveRecord::Migrator.schema_migrations_table_name
367
-
368
- assert_equal "schema_migrations", ActiveRecord::Migrator.schema_migrations_table_name
369
- ActiveRecord::Base.table_name_prefix = "prefix_"
370
- ActiveRecord::Base.table_name_suffix = "_suffix"
371
- Reminder.reset_table_name
372
- assert_equal "prefix_schema_migrations_suffix", ActiveRecord::Migrator.schema_migrations_table_name
373
- ActiveRecord::Base.schema_migrations_table_name = "changed"
374
- Reminder.reset_table_name
375
- assert_equal "prefix_changed_suffix", ActiveRecord::Migrator.schema_migrations_table_name
376
- ActiveRecord::Base.table_name_prefix = ""
377
- ActiveRecord::Base.table_name_suffix = ""
378
- Reminder.reset_table_name
379
- assert_equal "changed", ActiveRecord::Migrator.schema_migrations_table_name
380
- ensure
381
- ActiveRecord::Base.schema_migrations_table_name = original_schema_migrations_table_name
382
- Reminder.reset_table_name
383
- end
384
-
385
- def test_proper_table_name_on_migration
386
- reminder_class = new_isolated_reminder_class
387
- migration = ActiveRecord::Migration.new
388
- assert_equal "table", migration.proper_table_name('table')
389
- assert_equal "table", migration.proper_table_name(:table)
390
- assert_equal "reminders", migration.proper_table_name(reminder_class)
391
- reminder_class.reset_table_name
392
- assert_equal reminder_class.table_name, migration.proper_table_name(reminder_class)
393
-
394
- # Use the model's own prefix/suffix if a model is given
395
- ActiveRecord::Base.table_name_prefix = "ARprefix_"
396
- ActiveRecord::Base.table_name_suffix = "_ARsuffix"
397
- reminder_class.table_name_prefix = 'prefix_'
398
- reminder_class.table_name_suffix = '_suffix'
399
- reminder_class.reset_table_name
400
- assert_equal "prefix_reminders_suffix", migration.proper_table_name(reminder_class)
401
- reminder_class.table_name_prefix = ''
402
- reminder_class.table_name_suffix = ''
403
- reminder_class.reset_table_name
404
-
405
- # Use AR::Base's prefix/suffix if string or symbol is given
406
- ActiveRecord::Base.table_name_prefix = "prefix_"
407
- ActiveRecord::Base.table_name_suffix = "_suffix"
408
- reminder_class.reset_table_name
409
- assert_equal "prefix_table_suffix", migration.proper_table_name('table', migration.table_name_options)
410
- assert_equal "prefix_table_suffix", migration.proper_table_name(:table, migration.table_name_options)
411
- end
412
-
413
- def test_rename_table_with_prefix_and_suffix
414
- assert !Thing.table_exists?
415
- ActiveRecord::Base.table_name_prefix = 'p_'
416
- ActiveRecord::Base.table_name_suffix = '_s'
417
- Thing.reset_table_name
418
- Thing.reset_sequence_name
419
- WeNeedThings.up
420
-
421
- assert Thing.create("content" => "hello world")
422
- assert_equal "hello world", Thing.first.content
423
-
424
- RenameThings.up
425
- Thing.table_name = "p_awesome_things_s"
426
-
427
- assert_equal "hello world", Thing.first.content
428
- ensure
429
- Thing.reset_table_name
430
- Thing.reset_sequence_name
431
- end
432
-
433
- def test_add_drop_table_with_prefix_and_suffix
434
- assert !Reminder.table_exists?
435
- ActiveRecord::Base.table_name_prefix = 'prefix_'
436
- ActiveRecord::Base.table_name_suffix = '_suffix'
437
- Reminder.reset_table_name
438
- Reminder.reset_sequence_name
439
- WeNeedReminders.up
440
- assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
441
- assert_equal "hello world", Reminder.first.content
442
-
443
- WeNeedReminders.down
444
- assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
445
- ensure
446
- Reminder.reset_sequence_name
447
- end
448
-
449
- def test_create_table_with_binary_column
450
- Person.connection.drop_table :binary_testings rescue nil
451
-
452
- assert_nothing_raised {
453
- Person.connection.create_table :binary_testings do |t|
454
- t.column "data", :binary, :null => false
455
- end
456
- }
457
-
458
- columns = Person.connection.columns(:binary_testings)
459
- data_column = columns.detect { |c| c.name == "data" }
460
-
461
- assert_nil data_column.default
462
-
463
- Person.connection.drop_table :binary_testings rescue nil
464
- end
465
-
466
- unless mysql_enforcing_gtid_consistency?
467
- def test_create_table_with_query
468
- Person.connection.drop_table :table_from_query_testings rescue nil
469
- Person.connection.create_table(:person, force: true)
470
-
471
- Person.connection.create_table :table_from_query_testings, as: "SELECT id FROM person"
472
-
473
- columns = Person.connection.columns(:table_from_query_testings)
474
- assert_equal 1, columns.length
475
- assert_equal "id", columns.first.name
476
-
477
- Person.connection.drop_table :table_from_query_testings rescue nil
478
- end
479
-
480
- def test_create_table_with_query_from_relation
481
- Person.connection.drop_table :table_from_query_testings rescue nil
482
- Person.connection.create_table(:person, force: true)
483
-
484
- Person.connection.create_table :table_from_query_testings, as: Person.select(:id)
485
-
486
- columns = Person.connection.columns(:table_from_query_testings)
487
- assert_equal 1, columns.length
488
- assert_equal "id", columns.first.name
489
-
490
- Person.connection.drop_table :table_from_query_testings rescue nil
491
- end
492
- end
493
-
494
- if current_adapter? :OracleAdapter
495
- def test_create_table_with_custom_sequence_name
496
- # table name is 29 chars, the standard sequence name will
497
- # be 33 chars and should be shortened
498
- assert_nothing_raised do
499
- begin
500
- Person.connection.create_table :table_with_name_thats_just_ok do |t|
501
- t.column :foo, :string, :null => false
502
- end
503
- ensure
504
- Person.connection.drop_table :table_with_name_thats_just_ok rescue nil
505
- end
506
- end
507
-
508
- # should be all good w/ a custom sequence name
509
- assert_nothing_raised do
510
- begin
511
- Person.connection.create_table :table_with_name_thats_just_ok,
512
- :sequence_name => 'suitably_short_seq' do |t|
513
- t.column :foo, :string, :null => false
514
- end
515
-
516
- Person.connection.execute("select suitably_short_seq.nextval from dual")
517
-
518
- ensure
519
- Person.connection.drop_table :table_with_name_thats_just_ok,
520
- :sequence_name => 'suitably_short_seq' rescue nil
521
- end
522
- end
523
-
524
- # confirm the custom sequence got dropped
525
- assert_raise(ActiveRecord::StatementInvalid) do
526
- Person.connection.execute("select suitably_short_seq.nextval from dual")
527
- end
528
- end
529
- end
530
-
531
- if current_adapter?(:MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter)
532
- def test_out_of_range_limit_should_raise
533
- Person.connection.drop_table :test_limits rescue nil
534
- assert_raise(ActiveRecord::ActiveRecordError, "integer limit didn't raise") do
535
- Person.connection.create_table :test_integer_limits, :force => true do |t|
536
- t.column :bigone, :integer, :limit => 10
537
- end
538
- end
539
-
540
- unless current_adapter?(:PostgreSQLAdapter)
541
- assert_raise(ActiveRecord::ActiveRecordError, "text limit didn't raise") do
542
- Person.connection.create_table :test_text_limits, :force => true do |t|
543
- t.column :bigtext, :text, :limit => 0xfffffffff
544
- end
545
- end
546
- end
547
-
548
- Person.connection.drop_table :test_limits rescue nil
549
- end
550
- end
551
-
552
- protected
553
- # This is needed to isolate class_attribute assignments like `table_name_prefix`
554
- # for each test case.
555
- def new_isolated_reminder_class
556
- Class.new(Reminder) {
557
- def self.name; "Reminder"; end
558
- def self.base_class; self; end
559
- }
560
- end
561
- end
562
-
563
- class ReservedWordsMigrationTest < ActiveRecord::TestCase
564
- def test_drop_index_from_table_named_values
565
- connection = Person.connection
566
- connection.create_table :values, :force => true do |t|
567
- t.integer :value
568
- end
569
-
570
- assert_nothing_raised do
571
- connection.add_index :values, :value
572
- connection.remove_index :values, :column => :value
573
- end
574
-
575
- connection.drop_table :values rescue nil
576
- end
577
- end
578
-
579
- class ExplicitlyNamedIndexMigrationTest < ActiveRecord::TestCase
580
- def test_drop_index_by_name
581
- connection = Person.connection
582
- connection.create_table :values, force: true do |t|
583
- t.integer :value
584
- end
585
-
586
- assert_nothing_raised ArgumentError do
587
- connection.add_index :values, :value, name: 'a_different_name'
588
- connection.remove_index :values, column: :value, name: 'a_different_name'
589
- end
590
-
591
- connection.drop_table :values rescue nil
592
- end
593
- end
594
-
595
- if ActiveRecord::Base.connection.supports_bulk_alter?
596
- class BulkAlterTableMigrationsTest < ActiveRecord::TestCase
597
- def setup
598
- @connection = Person.connection
599
- @connection.create_table(:delete_me, :force => true) {|t| }
600
- Person.reset_column_information
601
- Person.reset_sequence_name
602
- end
603
-
604
- teardown do
605
- Person.connection.drop_table(:delete_me) rescue nil
606
- end
607
-
608
- def test_adding_multiple_columns
609
- assert_queries(1) do
610
- with_bulk_change_table do |t|
611
- t.column :name, :string
612
- t.string :qualification, :experience
613
- t.integer :age, :default => 0
614
- t.date :birthdate
615
- t.timestamps null: true
616
- end
617
- end
618
-
619
- assert_equal 8, columns.size
620
- [:name, :qualification, :experience].each {|s| assert_equal :string, column(s).type }
621
- assert_equal '0', column(:age).default
622
- end
623
-
624
- def test_removing_columns
625
- with_bulk_change_table do |t|
626
- t.string :qualification, :experience
627
- end
628
-
629
- [:qualification, :experience].each {|c| assert column(c) }
630
-
631
- assert_queries(1) do
632
- with_bulk_change_table do |t|
633
- t.remove :qualification, :experience
634
- t.string :qualification_experience
635
- end
636
- end
637
-
638
- [:qualification, :experience].each {|c| assert ! column(c) }
639
- assert column(:qualification_experience)
640
- end
641
-
642
- def test_adding_indexes
643
- with_bulk_change_table do |t|
644
- t.string :username
645
- t.string :name
646
- t.integer :age
647
- end
648
-
649
- # Adding an index fires a query every time to check if an index already exists or not
650
- assert_queries(3) do
651
- with_bulk_change_table do |t|
652
- t.index :username, :unique => true, :name => :awesome_username_index
653
- t.index [:name, :age]
654
- end
655
- end
656
-
657
- assert_equal 2, indexes.size
658
-
659
- name_age_index = index(:index_delete_me_on_name_and_age)
660
- assert_equal ['name', 'age'].sort, name_age_index.columns.sort
661
- assert ! name_age_index.unique
662
-
663
- assert index(:awesome_username_index).unique
664
- end
665
-
666
- def test_removing_index
667
- with_bulk_change_table do |t|
668
- t.string :name
669
- t.index :name
670
- end
671
-
672
- assert index(:index_delete_me_on_name)
673
-
674
- assert_queries(3) do
675
- with_bulk_change_table do |t|
676
- t.remove_index :name
677
- t.index :name, :name => :new_name_index, :unique => true
678
- end
679
- end
680
-
681
- assert ! index(:index_delete_me_on_name)
682
-
683
- new_name_index = index(:new_name_index)
684
- assert new_name_index.unique
685
- end
686
-
687
- def test_changing_columns
688
- with_bulk_change_table do |t|
689
- t.string :name
690
- t.date :birthdate
691
- end
692
-
693
- assert ! column(:name).default
694
- assert_equal :date, column(:birthdate).type
695
-
696
- # One query for columns (delete_me table)
697
- # One query for primary key (delete_me table)
698
- # One query to do the bulk change
699
- assert_queries(3, :ignore_none => true) do
700
- with_bulk_change_table do |t|
701
- t.change :name, :string, :default => 'NONAME'
702
- t.change :birthdate, :datetime
703
- end
704
- end
705
-
706
- assert_equal 'NONAME', column(:name).default
707
- assert_equal :datetime, column(:birthdate).type
708
- end
709
-
710
- protected
711
-
712
- def with_bulk_change_table
713
- # Reset columns/indexes cache as we're changing the table
714
- @columns = @indexes = nil
715
-
716
- Person.connection.change_table(:delete_me, :bulk => true) do |t|
717
- yield t
718
- end
719
- end
720
-
721
- def column(name)
722
- columns.detect {|c| c.name == name.to_s }
723
- end
724
-
725
- def columns
726
- @columns ||= Person.connection.columns('delete_me')
727
- end
728
-
729
- def index(name)
730
- indexes.detect {|i| i.name == name.to_s }
731
- end
732
-
733
- def indexes
734
- @indexes ||= Person.connection.indexes('delete_me')
735
- end
736
- end # AlterTableMigrationsTest
737
-
738
- end
739
-
740
- class CopyMigrationsTest < ActiveRecord::TestCase
741
- def setup
742
- end
743
-
744
- def clear
745
- ActiveRecord::Base.timestamped_migrations = true
746
- to_delete = Dir[@migrations_path + "/*.rb"] - @existing_migrations
747
- File.delete(*to_delete)
748
- end
749
-
750
- def test_copying_migrations_without_timestamps
751
- ActiveRecord::Base.timestamped_migrations = false
752
- @migrations_path = MIGRATIONS_ROOT + "/valid"
753
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
754
-
755
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"})
756
- assert File.exist?(@migrations_path + "/4_people_have_hobbies.bukkits.rb")
757
- assert File.exist?(@migrations_path + "/5_people_have_descriptions.bukkits.rb")
758
- assert_equal [@migrations_path + "/4_people_have_hobbies.bukkits.rb", @migrations_path + "/5_people_have_descriptions.bukkits.rb"], copied.map(&:filename)
759
-
760
- expected = "# This migration comes from bukkits (originally 1)"
761
- assert_equal expected, IO.readlines(@migrations_path + "/4_people_have_hobbies.bukkits.rb")[0].chomp
762
-
763
- files_count = Dir[@migrations_path + "/*.rb"].length
764
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"})
765
- assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
766
- assert copied.empty?
767
- ensure
768
- clear
769
- end
770
-
771
- def test_copying_migrations_without_timestamps_from_2_sources
772
- ActiveRecord::Base.timestamped_migrations = false
773
- @migrations_path = MIGRATIONS_ROOT + "/valid"
774
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
775
-
776
- sources = {}
777
- sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy"
778
- sources[:omg] = MIGRATIONS_ROOT + "/to_copy2"
779
- ActiveRecord::Migration.copy(@migrations_path, sources)
780
- assert File.exist?(@migrations_path + "/4_people_have_hobbies.bukkits.rb")
781
- assert File.exist?(@migrations_path + "/5_people_have_descriptions.bukkits.rb")
782
- assert File.exist?(@migrations_path + "/6_create_articles.omg.rb")
783
- assert File.exist?(@migrations_path + "/7_create_comments.omg.rb")
784
-
785
- files_count = Dir[@migrations_path + "/*.rb"].length
786
- ActiveRecord::Migration.copy(@migrations_path, sources)
787
- assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
788
- ensure
789
- clear
790
- end
791
-
792
- def test_copying_migrations_with_timestamps
793
- @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
794
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
795
-
796
- travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
797
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
798
- assert File.exist?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
799
- assert File.exist?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
800
- expected = [@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb",
801
- @migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb"]
802
- assert_equal expected, copied.map(&:filename)
803
-
804
- files_count = Dir[@migrations_path + "/*.rb"].length
805
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
806
- assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
807
- assert copied.empty?
808
- end
809
- ensure
810
- clear
811
- end
812
-
813
- def test_copying_migrations_with_timestamps_from_2_sources
814
- @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
815
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
816
-
817
- sources = {}
818
- sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
819
- sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_timestamps2"
820
-
821
- travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
822
- copied = ActiveRecord::Migration.copy(@migrations_path, sources)
823
- assert File.exist?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
824
- assert File.exist?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
825
- assert File.exist?(@migrations_path + "/20100726101012_create_articles.omg.rb")
826
- assert File.exist?(@migrations_path + "/20100726101013_create_comments.omg.rb")
827
- assert_equal 4, copied.length
828
-
829
- files_count = Dir[@migrations_path + "/*.rb"].length
830
- ActiveRecord::Migration.copy(@migrations_path, sources)
831
- assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
832
- end
833
- ensure
834
- clear
835
- end
836
-
837
- def test_copying_migrations_with_timestamps_to_destination_with_timestamps_in_future
838
- @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
839
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
840
-
841
- travel_to(Time.utc(2010, 2, 20, 10, 10, 10)) do
842
- ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
843
- assert File.exist?(@migrations_path + "/20100301010102_people_have_hobbies.bukkits.rb")
844
- assert File.exist?(@migrations_path + "/20100301010103_people_have_descriptions.bukkits.rb")
845
-
846
- files_count = Dir[@migrations_path + "/*.rb"].length
847
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
848
- assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
849
- assert copied.empty?
850
- end
851
- ensure
852
- clear
853
- end
854
-
855
- def test_copying_migrations_preserving_magic_comments
856
- ActiveRecord::Base.timestamped_migrations = false
857
- @migrations_path = MIGRATIONS_ROOT + "/valid"
858
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
859
-
860
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/magic"})
861
- assert File.exist?(@migrations_path + "/4_currencies_have_symbols.bukkits.rb")
862
- assert_equal [@migrations_path + "/4_currencies_have_symbols.bukkits.rb"], copied.map(&:filename)
863
-
864
- expected = "# coding: ISO-8859-15\n# This migration comes from bukkits (originally 1)"
865
- assert_equal expected, IO.readlines(@migrations_path + "/4_currencies_have_symbols.bukkits.rb")[0..1].join.chomp
866
-
867
- files_count = Dir[@migrations_path + "/*.rb"].length
868
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/magic"})
869
- assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
870
- assert copied.empty?
871
- ensure
872
- clear
873
- end
874
-
875
- def test_skipping_migrations
876
- @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
877
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
878
-
879
- sources = {}
880
- sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
881
- sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_name_collision"
882
-
883
- skipped = []
884
- on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" }
885
- copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
886
- assert_equal 2, copied.length
887
-
888
- assert_equal 1, skipped.length
889
- assert_equal ["omg PeopleHaveHobbies"], skipped
890
- ensure
891
- clear
892
- end
893
-
894
- def test_skip_is_not_called_if_migrations_are_from_the_same_plugin
895
- @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
896
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
897
-
898
- sources = {}
899
- sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
900
-
901
- skipped = []
902
- on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" }
903
- copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
904
- ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
905
-
906
- assert_equal 2, copied.length
907
- assert_equal 0, skipped.length
908
- ensure
909
- clear
910
- end
911
-
912
- def test_copying_migrations_to_non_existing_directory
913
- @migrations_path = MIGRATIONS_ROOT + "/non_existing"
914
- @existing_migrations = []
915
-
916
- travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
917
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
918
- assert File.exist?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
919
- assert File.exist?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
920
- assert_equal 2, copied.length
921
- end
922
- ensure
923
- clear
924
- Dir.delete(@migrations_path)
925
- end
926
-
927
- def test_copying_migrations_to_empty_directory
928
- @migrations_path = MIGRATIONS_ROOT + "/empty"
929
- @existing_migrations = []
930
-
931
- travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
932
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
933
- assert File.exist?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
934
- assert File.exist?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
935
- assert_equal 2, copied.length
936
- end
937
- ensure
938
- clear
939
- end
940
-
941
- def test_check_pending_with_stdlib_logger
942
- old, ActiveRecord::Base.logger = ActiveRecord::Base.logger, ::Logger.new($stdout)
943
- quietly do
944
- assert_nothing_raised { ActiveRecord::Migration::CheckPending.new(Proc.new {}).call({}) }
945
- end
946
- ensure
947
- ActiveRecord::Base.logger = old
948
- end
949
-
950
- private
951
-
952
- def quietly
953
- silence_stream(STDOUT) do
954
- silence_stream(STDERR) do
955
- yield
956
- end
957
- end
958
- end
959
- end
1
+ require 'cases/helper'
2
+ require 'cases/migration/helper'
3
+ require 'bigdecimal/util'
4
+ require 'concurrent/atomic/count_down_latch'
5
+
6
+ require 'models/person'
7
+ require 'models/topic'
8
+ require 'models/developer'
9
+ require 'models/computer'
10
+
11
+ require MIGRATIONS_ROOT + "/valid/2_we_need_reminders"
12
+ require MIGRATIONS_ROOT + "/rename/1_we_need_things"
13
+ require MIGRATIONS_ROOT + "/rename/2_rename_things"
14
+ require MIGRATIONS_ROOT + "/decimal/1_give_me_big_numbers"
15
+
16
+ class BigNumber < ActiveRecord::Base
17
+ unless current_adapter?(:PostgreSQLAdapter, :SQLite3Adapter)
18
+ attribute :value_of_e, :integer
19
+ end
20
+ attribute :my_house_population, :integer
21
+ end
22
+
23
+ class Reminder < ActiveRecord::Base; end
24
+
25
+ class Thing < ActiveRecord::Base; end
26
+
27
+ class MigrationTest < ActiveRecord::TestCase
28
+ self.use_transactional_tests = false
29
+
30
+ fixtures :people
31
+
32
+ def setup
33
+ super
34
+ %w(reminders people_reminders prefix_reminders_suffix p_things_s).each do |table|
35
+ Reminder.connection.drop_table(table) rescue nil
36
+ end
37
+ Reminder.reset_column_information
38
+ @verbose_was, ActiveRecord::Migration.verbose = ActiveRecord::Migration.verbose, false
39
+ ActiveRecord::Base.connection.schema_cache.clear!
40
+ end
41
+
42
+ teardown do
43
+ ActiveRecord::Base.table_name_prefix = ""
44
+ ActiveRecord::Base.table_name_suffix = ""
45
+
46
+ ActiveRecord::Base.connection.initialize_schema_migrations_table
47
+ ActiveRecord::Base.connection.execute "DELETE FROM #{ActiveRecord::Migrator.schema_migrations_table_name}"
48
+
49
+ %w(things awesome_things prefix_things_suffix p_awesome_things_s ).each do |table|
50
+ Thing.connection.drop_table(table) rescue nil
51
+ end
52
+ Thing.reset_column_information
53
+
54
+ %w(reminders people_reminders prefix_reminders_suffix).each do |table|
55
+ Reminder.connection.drop_table(table) rescue nil
56
+ end
57
+ Reminder.reset_table_name
58
+ Reminder.reset_column_information
59
+
60
+ %w(last_name key bio age height wealth birthday favorite_day
61
+ moment_of_truth male administrator funny).each do |column|
62
+ Person.connection.remove_column('people', column) rescue nil
63
+ end
64
+ Person.connection.remove_column("people", "first_name") rescue nil
65
+ Person.connection.remove_column("people", "middle_name") rescue nil
66
+ Person.connection.add_column("people", "first_name", :string)
67
+ Person.reset_column_information
68
+
69
+ ActiveRecord::Migration.verbose = @verbose_was
70
+ end
71
+
72
+ def test_migration_version_matches_component_version
73
+ assert_equal ActiveRecord::VERSION::STRING.to_f, ActiveRecord::Migration.current_version
74
+ end
75
+
76
+ def test_migrator_versions
77
+ migrations_path = MIGRATIONS_ROOT + "/valid"
78
+ old_path = ActiveRecord::Migrator.migrations_paths
79
+ ActiveRecord::Migrator.migrations_paths = migrations_path
80
+
81
+ ActiveRecord::Migrator.up(migrations_path)
82
+ assert_equal 3, ActiveRecord::Migrator.current_version
83
+ assert_equal false, ActiveRecord::Migrator.needs_migration?
84
+
85
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid")
86
+ assert_equal 0, ActiveRecord::Migrator.current_version
87
+ assert_equal true, ActiveRecord::Migrator.needs_migration?
88
+
89
+ ActiveRecord::SchemaMigration.create!(version: 3)
90
+ assert_equal true, ActiveRecord::Migrator.needs_migration?
91
+ ensure
92
+ ActiveRecord::Migrator.migrations_paths = old_path
93
+ end
94
+
95
+ def test_migration_detection_without_schema_migration_table
96
+ ActiveRecord::Base.connection.drop_table 'schema_migrations'
97
+ #, if_exists: true
98
+
99
+ migrations_path = MIGRATIONS_ROOT + "/valid"
100
+ old_path = ActiveRecord::Migrator.migrations_paths
101
+ ActiveRecord::Migrator.migrations_paths = migrations_path
102
+
103
+ assert_equal true, ActiveRecord::Migrator.needs_migration?
104
+ ensure
105
+ ActiveRecord::Migrator.migrations_paths = old_path
106
+ end
107
+
108
+ def test_any_migrations
109
+ old_path = ActiveRecord::Migrator.migrations_paths
110
+ ActiveRecord::Migrator.migrations_paths = MIGRATIONS_ROOT + "/valid"
111
+
112
+ assert ActiveRecord::Migrator.any_migrations?
113
+
114
+ ActiveRecord::Migrator.migrations_paths = MIGRATIONS_ROOT + "/empty"
115
+
116
+ assert_not ActiveRecord::Migrator.any_migrations?
117
+ ensure
118
+ ActiveRecord::Migrator.migrations_paths = old_path
119
+ end
120
+
121
+ def test_migration_version
122
+ assert_nothing_raised { ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/version_check", 20131219224947) }
123
+ end
124
+
125
+ def test_create_table_with_force_true_does_not_drop_nonexisting_table
126
+ # using a copy as we need the drop_table method to
127
+ # continue to work for the ensure block of the test
128
+ temp_conn = Person.connection.dup
129
+
130
+ assert_not_equal temp_conn, Person.connection
131
+
132
+ temp_conn.create_table :testings2, :force => true do |t|
133
+ t.column :foo, :string
134
+ end
135
+ ensure
136
+ Person.connection.drop_table :testings2
137
+ #, if_exists: true
138
+ end
139
+
140
+ def test_migration_instance_has_connection
141
+ migration = Class.new(ActiveRecord::Migration::Current).new
142
+ assert_equal ActiveRecord::Base.connection, migration.connection
143
+ end
144
+
145
+ def test_method_missing_delegates_to_connection
146
+ migration = Class.new(ActiveRecord::Migration::Current) {
147
+ def connection
148
+ Class.new {
149
+ def create_table; "hi mom!"; end
150
+ }.new
151
+ end
152
+ }.new
153
+
154
+ assert_equal "hi mom!", migration.method_missing(:create_table)
155
+ end
156
+
157
+ def test_add_table_with_decimals
158
+ Person.connection.drop_table :big_numbers rescue nil
159
+
160
+ assert !BigNumber.table_exists?
161
+ GiveMeBigNumbers.up
162
+ BigNumber.reset_column_information
163
+
164
+ assert BigNumber.create(
165
+ :bank_balance => 1586.43,
166
+ :big_bank_balance => BigDecimal("1000234000567.95"),
167
+ :world_population => 6000000000,
168
+ :my_house_population => 3,
169
+ :value_of_e => BigDecimal("2.7182818284590452353602875")
170
+ )
171
+
172
+ b = BigNumber.first
173
+ assert_not_nil b
174
+
175
+ assert_not_nil b.bank_balance
176
+ assert_not_nil b.big_bank_balance
177
+ assert_not_nil b.world_population
178
+ assert_not_nil b.my_house_population
179
+ assert_not_nil b.value_of_e
180
+
181
+ # TODO: set world_population >= 2**62 to cover 64-bit platforms and test
182
+ # is_a?(Bignum)
183
+ assert_kind_of Integer, b.world_population
184
+ assert_equal 6000000000, b.world_population
185
+ assert_kind_of Integer, b.my_house_population
186
+ assert_equal 3, b.my_house_population
187
+ assert_kind_of BigDecimal, b.bank_balance
188
+ assert_equal BigDecimal("1586.43"), b.bank_balance
189
+ assert_kind_of BigDecimal, b.big_bank_balance
190
+ assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance
191
+
192
+ # This one is fun. The 'value_of_e' field is defined as 'DECIMAL' with
193
+ # precision/scale explicitly left out. By the SQL standard, numbers
194
+ # assigned to this field should be truncated but that's seldom respected.
195
+ if current_adapter?(:PostgreSQLAdapter)
196
+ # - PostgreSQL changes the SQL spec on columns declared simply as
197
+ # "decimal" to something more useful: instead of being given a scale
198
+ # of 0, they take on the compile-time limit for precision and scale,
199
+ # so the following should succeed unless you have used really wacky
200
+ # compilation options
201
+ assert_kind_of BigDecimal, b.value_of_e
202
+ assert_equal BigDecimal("2.7182818284590452353602875"), b.value_of_e
203
+ elsif current_adapter?(:SQLite3Adapter)
204
+ # - SQLite3 stores a float, in violation of SQL
205
+ assert_kind_of BigDecimal, b.value_of_e
206
+ assert_in_delta BigDecimal("2.71828182845905"), b.value_of_e, 0.00000000000001
207
+ else
208
+ # - SQL standard is an integer
209
+ assert_kind_of Integer, b.value_of_e
210
+ assert_equal 2, b.value_of_e
211
+ end
212
+
213
+ GiveMeBigNumbers.down
214
+ assert_raise(ActiveRecord::StatementInvalid) { BigNumber.first }
215
+ end
216
+
217
+ def test_filtering_migrations
218
+ assert_no_column Person, :last_name
219
+ assert !Reminder.table_exists?
220
+
221
+ name_filter = lambda { |migration| migration.name == "ValidPeopleHaveLastNames" }
222
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", &name_filter)
223
+
224
+ assert_column Person, :last_name
225
+ assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
226
+
227
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", &name_filter)
228
+
229
+ assert_no_column Person, :last_name
230
+ assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
231
+ end
232
+
233
+ class MockMigration < ActiveRecord::Migration::Current
234
+ attr_reader :went_up, :went_down
235
+ def initialize
236
+ @went_up = false
237
+ @went_down = false
238
+ end
239
+
240
+ def up
241
+ @went_up = true
242
+ super
243
+ end
244
+
245
+ def down
246
+ @went_down = true
247
+ super
248
+ end
249
+ end
250
+
251
+ def test_instance_based_migration_up
252
+ migration = MockMigration.new
253
+ assert !migration.went_up, 'have not gone up'
254
+ assert !migration.went_down, 'have not gone down'
255
+
256
+ migration.migrate :up
257
+ assert migration.went_up, 'have gone up'
258
+ assert !migration.went_down, 'have not gone down'
259
+ end
260
+
261
+ def test_instance_based_migration_down
262
+ migration = MockMigration.new
263
+ assert !migration.went_up, 'have not gone up'
264
+ assert !migration.went_down, 'have not gone down'
265
+
266
+ migration.migrate :down
267
+ assert !migration.went_up, 'have gone up'
268
+ assert migration.went_down, 'have not gone down'
269
+ end
270
+
271
+ if ActiveRecord::Base.connection.supports_ddl_transactions?
272
+ def test_migrator_one_up_with_exception_and_rollback
273
+ assert_no_column Person, :last_name
274
+
275
+ migration = Class.new(ActiveRecord::Migration::Current) {
276
+ def version; 100 end
277
+ def migrate(x)
278
+ add_column "people", "last_name", :string
279
+ raise 'Something broke'
280
+ end
281
+ }.new
282
+
283
+ migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
284
+
285
+ e = assert_raise(StandardError) { migrator.migrate }
286
+
287
+ assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message
288
+
289
+ assert_no_column Person, :last_name,
290
+ "On error, the Migrator should revert schema changes but it did not."
291
+ end
292
+
293
+ def test_migrator_one_up_with_exception_and_rollback_using_run
294
+ assert_no_column Person, :last_name
295
+
296
+ migration = Class.new(ActiveRecord::Migration::Current) {
297
+ def version; 100 end
298
+ def migrate(x)
299
+ add_column "people", "last_name", :string
300
+ raise 'Something broke'
301
+ end
302
+ }.new
303
+
304
+ migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
305
+
306
+ e = assert_raise(StandardError) { migrator.run }
307
+
308
+ assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message
309
+
310
+ assert_no_column Person, :last_name,
311
+ "On error, the Migrator should revert schema changes but it did not."
312
+ end
313
+
314
+ def test_migration_without_transaction
315
+ assert_no_column Person, :last_name
316
+
317
+ migration = Class.new(ActiveRecord::Migration::Current) {
318
+ self.disable_ddl_transaction!
319
+
320
+ def version; 101 end
321
+ def migrate(x)
322
+ add_column "people", "last_name", :string
323
+ raise 'Something broke'
324
+ end
325
+ }.new
326
+
327
+ migrator = ActiveRecord::Migrator.new(:up, [migration], 101)
328
+ e = assert_raise(StandardError) { migrator.migrate }
329
+ assert_equal "An error has occurred, all later migrations canceled:\n\nSomething broke", e.message
330
+
331
+ assert_column Person, :last_name,
332
+ "without ddl transactions, the Migrator should not rollback on error but it did."
333
+ ensure
334
+ Person.reset_column_information
335
+ if Person.column_names.include?('last_name')
336
+ Person.connection.remove_column('people', 'last_name')
337
+ end
338
+ end
339
+ end
340
+
341
+ def test_schema_migrations_table_name
342
+ original_schema_migrations_table_name = ActiveRecord::Migrator.schema_migrations_table_name
343
+
344
+ assert_equal "schema_migrations", ActiveRecord::Migrator.schema_migrations_table_name
345
+ ActiveRecord::Base.table_name_prefix = "prefix_"
346
+ ActiveRecord::Base.table_name_suffix = "_suffix"
347
+ Reminder.reset_table_name
348
+ assert_equal "prefix_schema_migrations_suffix", ActiveRecord::Migrator.schema_migrations_table_name
349
+ ActiveRecord::Base.schema_migrations_table_name = "changed"
350
+ Reminder.reset_table_name
351
+ assert_equal "prefix_changed_suffix", ActiveRecord::Migrator.schema_migrations_table_name
352
+ ActiveRecord::Base.table_name_prefix = ""
353
+ ActiveRecord::Base.table_name_suffix = ""
354
+ Reminder.reset_table_name
355
+ assert_equal "changed", ActiveRecord::Migrator.schema_migrations_table_name
356
+ ensure
357
+ ActiveRecord::Base.schema_migrations_table_name = original_schema_migrations_table_name
358
+ Reminder.reset_table_name
359
+ end
360
+
361
+ def test_internal_metadata_table_name
362
+ original_internal_metadata_table_name = ActiveRecord::Base.internal_metadata_table_name
363
+
364
+ assert_equal "ar_internal_metadata", ActiveRecord::InternalMetadata.table_name
365
+ ActiveRecord::Base.table_name_prefix = "p_"
366
+ ActiveRecord::Base.table_name_suffix = "_s"
367
+ Reminder.reset_table_name
368
+ assert_equal "p_ar_internal_metadata_s", ActiveRecord::InternalMetadata.table_name
369
+ ActiveRecord::Base.internal_metadata_table_name = "changed"
370
+ Reminder.reset_table_name
371
+ assert_equal "p_changed_s", ActiveRecord::InternalMetadata.table_name
372
+ ActiveRecord::Base.table_name_prefix = ""
373
+ ActiveRecord::Base.table_name_suffix = ""
374
+ Reminder.reset_table_name
375
+ assert_equal "changed", ActiveRecord::InternalMetadata.table_name
376
+ ensure
377
+ ActiveRecord::Base.internal_metadata_table_name = original_internal_metadata_table_name
378
+ Reminder.reset_table_name
379
+ end
380
+
381
+ def test_internal_metadata_stores_environment
382
+ current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
383
+ migrations_path = MIGRATIONS_ROOT + "/valid"
384
+ old_path = ActiveRecord::Migrator.migrations_paths
385
+ ActiveRecord::Migrator.migrations_paths = migrations_path
386
+
387
+ ActiveRecord::Migrator.up(migrations_path)
388
+ assert_equal current_env, ActiveRecord::InternalMetadata[:environment]
389
+
390
+ original_rails_env = ENV["RAILS_ENV"]
391
+ original_rack_env = ENV["RACK_ENV"]
392
+ ENV["RAILS_ENV"] = ENV["RACK_ENV"] = "foofoo"
393
+ new_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
394
+
395
+ refute_equal current_env, new_env
396
+
397
+ sleep 1 # mysql by default does not store fractional seconds in the database
398
+ ActiveRecord::Migrator.up(migrations_path)
399
+ assert_equal new_env, ActiveRecord::InternalMetadata[:environment]
400
+ ensure
401
+ ActiveRecord::Migrator.migrations_paths = old_path
402
+ ENV["RAILS_ENV"] = original_rails_env
403
+ ENV["RACK_ENV"] = original_rack_env
404
+ end
405
+
406
+
407
+ def test_migration_sets_internal_metadata_even_when_fully_migrated
408
+ current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
409
+ migrations_path = MIGRATIONS_ROOT + "/valid"
410
+ old_path = ActiveRecord::Migrator.migrations_paths
411
+ ActiveRecord::Migrator.migrations_paths = migrations_path
412
+
413
+ ActiveRecord::Migrator.up(migrations_path)
414
+ assert_equal current_env, ActiveRecord::InternalMetadata[:environment]
415
+
416
+ original_rails_env = ENV["RAILS_ENV"]
417
+ original_rack_env = ENV["RACK_ENV"]
418
+ ENV["RAILS_ENV"] = ENV["RACK_ENV"] = "foofoo"
419
+ new_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
420
+
421
+ refute_equal current_env, new_env
422
+
423
+ sleep 1 # mysql by default does not store fractional seconds in the database
424
+
425
+ ActiveRecord::Migrator.up(migrations_path)
426
+ assert_equal new_env, ActiveRecord::InternalMetadata[:environment]
427
+ ensure
428
+ ActiveRecord::Migrator.migrations_paths = old_path
429
+ ENV["RAILS_ENV"] = original_rails_env
430
+ ENV["RACK_ENV"] = original_rack_env
431
+ end
432
+
433
+ def test_internal_metadata_stores_environment_when_other_data_exists
434
+ ActiveRecord::InternalMetadata.delete_all
435
+ ActiveRecord::InternalMetadata[:foo] = 'bar'
436
+
437
+ current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
438
+ migrations_path = MIGRATIONS_ROOT + "/valid"
439
+ old_path = ActiveRecord::Migrator.migrations_paths
440
+ ActiveRecord::Migrator.migrations_paths = migrations_path
441
+
442
+ current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
443
+ ActiveRecord::Migrator.up(migrations_path)
444
+ assert_equal current_env, ActiveRecord::InternalMetadata[:environment]
445
+ assert_equal 'bar', ActiveRecord::InternalMetadata[:foo]
446
+ ensure
447
+ ActiveRecord::Migrator.migrations_paths = old_path
448
+ end
449
+
450
+ def test_rename_internal_metadata_table
451
+ original_internal_metadata_table_name = ActiveRecord::Base.internal_metadata_table_name
452
+
453
+ ActiveRecord::Base.internal_metadata_table_name = "active_record_internal_metadatas"
454
+ Reminder.reset_table_name
455
+
456
+ ActiveRecord::Base.internal_metadata_table_name = original_internal_metadata_table_name
457
+ Reminder.reset_table_name
458
+
459
+ assert_equal "ar_internal_metadata", ActiveRecord::InternalMetadata.table_name
460
+ ensure
461
+ ActiveRecord::Base.internal_metadata_table_name = original_internal_metadata_table_name
462
+ Reminder.reset_table_name
463
+ end
464
+
465
+ def test_proper_table_name_on_migration
466
+ reminder_class = new_isolated_reminder_class
467
+ migration = ActiveRecord::Migration.new
468
+ assert_equal "table", migration.proper_table_name('table')
469
+ assert_equal "table", migration.proper_table_name(:table)
470
+ assert_equal "reminders", migration.proper_table_name(reminder_class)
471
+ reminder_class.reset_table_name
472
+ assert_equal reminder_class.table_name, migration.proper_table_name(reminder_class)
473
+
474
+ # Use the model's own prefix/suffix if a model is given
475
+ ActiveRecord::Base.table_name_prefix = "ARprefix_"
476
+ ActiveRecord::Base.table_name_suffix = "_ARsuffix"
477
+ reminder_class.table_name_prefix = 'prefix_'
478
+ reminder_class.table_name_suffix = '_suffix'
479
+ reminder_class.reset_table_name
480
+ assert_equal "prefix_reminders_suffix", migration.proper_table_name(reminder_class)
481
+ reminder_class.table_name_prefix = ''
482
+ reminder_class.table_name_suffix = ''
483
+ reminder_class.reset_table_name
484
+
485
+ # Use AR::Base's prefix/suffix if string or symbol is given
486
+ ActiveRecord::Base.table_name_prefix = "prefix_"
487
+ ActiveRecord::Base.table_name_suffix = "_suffix"
488
+ reminder_class.reset_table_name
489
+ assert_equal "prefix_table_suffix", migration.proper_table_name('table', migration.table_name_options)
490
+ assert_equal "prefix_table_suffix", migration.proper_table_name(:table, migration.table_name_options)
491
+ end
492
+
493
+ def test_rename_table_with_prefix_and_suffix
494
+ assert !Thing.table_exists?
495
+ ActiveRecord::Base.table_name_prefix = 'p_'
496
+ ActiveRecord::Base.table_name_suffix = '_s'
497
+ Thing.reset_table_name
498
+ Thing.reset_sequence_name
499
+ WeNeedThings.up
500
+ Thing.reset_column_information
501
+
502
+ assert Thing.create("content" => "hello world")
503
+ assert_equal "hello world", Thing.first.content
504
+
505
+ RenameThings.up
506
+ Thing.table_name = "p_awesome_things_s"
507
+
508
+ assert_equal "hello world", Thing.first.content
509
+ ensure
510
+ Thing.reset_table_name
511
+ Thing.reset_sequence_name
512
+ end
513
+
514
+ def test_add_drop_table_with_prefix_and_suffix
515
+ assert !Reminder.table_exists?
516
+ ActiveRecord::Base.table_name_prefix = 'prefix_'
517
+ ActiveRecord::Base.table_name_suffix = '_suffix'
518
+ Reminder.reset_table_name
519
+ Reminder.reset_sequence_name
520
+ Reminder.reset_column_information
521
+ WeNeedReminders.up
522
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
523
+ assert_equal "hello world", Reminder.first.content
524
+
525
+ WeNeedReminders.down
526
+ assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
527
+ ensure
528
+ Reminder.reset_sequence_name
529
+ end
530
+
531
+ def test_create_table_with_binary_column
532
+ assert_nothing_raised {
533
+ Person.connection.create_table :binary_testings do |t|
534
+ t.column "data", :binary, :null => false
535
+ end
536
+ }
537
+
538
+ columns = Person.connection.columns(:binary_testings)
539
+ data_column = columns.detect { |c| c.name == "data" }
540
+
541
+ assert_nil data_column.default
542
+ ensure
543
+ Person.connection.drop_table :binary_testings
544
+ #, if_exists: true
545
+ end
546
+
547
+ unless mysql_enforcing_gtid_consistency?
548
+ def test_create_table_with_query
549
+ Person.connection.create_table(:person, force: true)
550
+
551
+ Person.connection.create_table :table_from_query_testings, as: "SELECT id FROM person"
552
+
553
+ columns = Person.connection.columns(:table_from_query_testings)
554
+ assert_equal 1, columns.length
555
+ assert_equal "id", columns.first.name
556
+ ensure
557
+ Person.connection.drop_table :table_from_query_testings rescue nil
558
+ end
559
+
560
+ def test_create_table_with_query_from_relation
561
+ Person.connection.create_table(:person, force: true)
562
+
563
+ Person.connection.create_table :table_from_query_testings, as: Person.select(:id)
564
+
565
+ columns = Person.connection.columns(:table_from_query_testings)
566
+ assert_equal 1, columns.length
567
+ assert_equal "id", columns.first.name
568
+ ensure
569
+ Person.connection.drop_table :table_from_query_testings rescue nil
570
+ end
571
+ end
572
+
573
+ if current_adapter?(:SQLite3Adapter)
574
+ def test_allows_sqlite3_rollback_on_invalid_column_type
575
+ Person.connection.create_table :something, force: true do |t|
576
+ t.column :number, :integer
577
+ t.column :name, :string
578
+ t.column :foo, :bar
579
+ end
580
+ assert Person.connection.column_exists?(:something, :foo)
581
+ assert_nothing_raised { Person.connection.remove_column :something, :foo, :bar }
582
+ assert !Person.connection.column_exists?(:something, :foo)
583
+ assert Person.connection.column_exists?(:something, :name)
584
+ assert Person.connection.column_exists?(:something, :number)
585
+ ensure
586
+ Person.connection.drop_table :something
587
+ #, if_exists: true
588
+ end
589
+ end
590
+
591
+ if current_adapter? :OracleAdapter
592
+ def test_create_table_with_custom_sequence_name
593
+ # table name is 29 chars, the standard sequence name will
594
+ # be 33 chars and should be shortened
595
+ assert_nothing_raised do
596
+ begin
597
+ Person.connection.create_table :table_with_name_thats_just_ok do |t|
598
+ t.column :foo, :string, :null => false
599
+ end
600
+ ensure
601
+ Person.connection.drop_table :table_with_name_thats_just_ok rescue nil
602
+ end
603
+ end
604
+
605
+ # should be all good w/ a custom sequence name
606
+ assert_nothing_raised do
607
+ begin
608
+ Person.connection.create_table :table_with_name_thats_just_ok,
609
+ :sequence_name => 'suitably_short_seq' do |t|
610
+ t.column :foo, :string, :null => false
611
+ end
612
+
613
+ Person.connection.execute("select suitably_short_seq.nextval from dual")
614
+
615
+ ensure
616
+ Person.connection.drop_table :table_with_name_thats_just_ok,
617
+ :sequence_name => 'suitably_short_seq' rescue nil
618
+ end
619
+ end
620
+
621
+ # confirm the custom sequence got dropped
622
+ assert_raise(ActiveRecord::StatementInvalid) do
623
+ Person.connection.execute("select suitably_short_seq.nextval from dual")
624
+ end
625
+ end
626
+ end
627
+
628
+ if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
629
+ def test_out_of_range_integer_limit_should_raise
630
+ e = assert_raise(ActiveRecord::ActiveRecordError, "integer limit didn't raise") do
631
+ Person.connection.create_table :test_integer_limits, :force => true do |t|
632
+ t.column :bigone, :integer, :limit => 10
633
+ end
634
+ end
635
+
636
+ assert_match(/No integer type has byte size 10/, e.message)
637
+ ensure
638
+ Person.connection.drop_table :test_integer_limits
639
+ #, if_exists: true
640
+ end
641
+ end
642
+
643
+ if current_adapter?(:Mysql2Adapter)
644
+ def test_out_of_range_text_limit_should_raise
645
+ e = assert_raise(ActiveRecord::ActiveRecordError, "text limit didn't raise") do
646
+ Person.connection.create_table :test_text_limits, force: true do |t|
647
+ t.text :bigtext, limit: 0xfffffffff
648
+ end
649
+ end
650
+
651
+ assert_match(/No text type has byte length #{0xfffffffff}/, e.message)
652
+ ensure
653
+ Person.connection.drop_table :test_text_limits
654
+ #, if_exists: true
655
+ end
656
+ end
657
+
658
+ if ActiveRecord::Base.connection.supports_advisory_locks?
659
+ def test_migrator_generates_valid_lock_id
660
+ migration = Class.new(ActiveRecord::Migration::Current).new
661
+ migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
662
+
663
+ lock_id = migrator.send(:generate_migrator_advisory_lock_id)
664
+
665
+ assert ActiveRecord::Base.connection.get_advisory_lock(lock_id),
666
+ "the Migrator should have generated a valid lock id, but it didn't"
667
+ assert ActiveRecord::Base.connection.release_advisory_lock(lock_id),
668
+ "the Migrator should have generated a valid lock id, but it didn't"
669
+ end
670
+
671
+ def test_generate_migrator_advisory_lock_id
672
+ # It is important we are consistent with how we generate this so that
673
+ # exclusive locking works across migrator versions
674
+ migration = Class.new(ActiveRecord::Migration::Current).new
675
+ migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
676
+
677
+ lock_id = migrator.send(:generate_migrator_advisory_lock_id)
678
+
679
+ current_database = ActiveRecord::Base.connection.current_database
680
+ salt = ActiveRecord::Migrator::MIGRATOR_SALT
681
+ expected_id = Zlib.crc32(current_database) * salt
682
+
683
+ assert lock_id == expected_id, "expected lock id generated by the migrator to be #{expected_id}, but it was #{lock_id} instead"
684
+ assert lock_id.bit_length <= 63, "lock id must be a signed integer of max 63 bits magnitude"
685
+ end
686
+
687
+ def test_migrator_one_up_with_unavailable_lock
688
+ assert_no_column Person, :last_name
689
+
690
+ migration = Class.new(ActiveRecord::Migration::Current) {
691
+ def version; 100 end
692
+ def migrate(x)
693
+ add_column "people", "last_name", :string
694
+ end
695
+ }.new
696
+
697
+ migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
698
+ lock_id = migrator.send(:generate_migrator_advisory_lock_id)
699
+
700
+ with_another_process_holding_lock(lock_id) do
701
+ assert_raise(ActiveRecord::ConcurrentMigrationError) { migrator.migrate }
702
+ end
703
+
704
+ assert_no_column Person, :last_name,
705
+ "without an advisory lock, the Migrator should not make any changes, but it did."
706
+ end
707
+
708
+ def test_migrator_one_up_with_unavailable_lock_using_run
709
+ assert_no_column Person, :last_name
710
+
711
+ migration = Class.new(ActiveRecord::Migration::Current) {
712
+ def version; 100 end
713
+ def migrate(x)
714
+ add_column "people", "last_name", :string
715
+ end
716
+ }.new
717
+
718
+ migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
719
+ lock_id = migrator.send(:generate_migrator_advisory_lock_id)
720
+
721
+ with_another_process_holding_lock(lock_id) do
722
+ assert_raise(ActiveRecord::ConcurrentMigrationError) { migrator.run }
723
+ end
724
+
725
+ assert_no_column Person, :last_name,
726
+ "without an advisory lock, the Migrator should not make any changes, but it did."
727
+ end
728
+ end
729
+
730
+ protected
731
+ # This is needed to isolate class_attribute assignments like `table_name_prefix`
732
+ # for each test case.
733
+ def new_isolated_reminder_class
734
+ Class.new(Reminder) {
735
+ def self.name; "Reminder"; end
736
+ def self.base_class; self; end
737
+ }
738
+ end
739
+
740
+ def with_another_process_holding_lock(lock_id)
741
+ thread_lock = Concurrent::CountDownLatch.new
742
+ test_terminated = Concurrent::CountDownLatch.new
743
+
744
+ other_process = Thread.new do
745
+ begin
746
+ conn = ActiveRecord::Base.connection_pool.checkout
747
+ conn.get_advisory_lock(lock_id)
748
+ thread_lock.count_down
749
+ test_terminated.wait # hold the lock open until we tested everything
750
+ ensure
751
+ conn.release_advisory_lock(lock_id)
752
+ ActiveRecord::Base.connection_pool.checkin(conn)
753
+ end
754
+ end
755
+
756
+ thread_lock.wait # wait until the 'other process' has the lock
757
+
758
+ yield
759
+
760
+ test_terminated.count_down
761
+ other_process.join
762
+ end
763
+ end
764
+
765
+ class ReservedWordsMigrationTest < ActiveRecord::TestCase
766
+ def test_drop_index_from_table_named_values
767
+ connection = Person.connection
768
+ connection.create_table :values, :force => true do |t|
769
+ t.integer :value
770
+ end
771
+
772
+ assert_nothing_raised do
773
+ connection.add_index :values, :value
774
+ connection.remove_index :values, :column => :value
775
+ end
776
+ ensure
777
+ connection.drop_table :values rescue nil
778
+ end
779
+ end
780
+
781
+ class ExplicitlyNamedIndexMigrationTest < ActiveRecord::TestCase
782
+ def test_drop_index_by_name
783
+ connection = Person.connection
784
+ connection.create_table :values, force: true do |t|
785
+ t.integer :value
786
+ end
787
+
788
+ assert_nothing_raised do
789
+ connection.add_index :values, :value, name: 'a_different_name'
790
+ connection.remove_index :values, column: :value, name: 'a_different_name'
791
+ end
792
+ ensure
793
+ connection.drop_table :values rescue nil
794
+ end
795
+ end
796
+
797
+ if ActiveRecord::Base.connection.supports_bulk_alter?
798
+ class BulkAlterTableMigrationsTest < ActiveRecord::TestCase
799
+ def setup
800
+ @connection = Person.connection
801
+ @connection.create_table(:delete_me, :force => true) {|t| }
802
+ Person.reset_column_information
803
+ Person.reset_sequence_name
804
+ end
805
+
806
+ teardown do
807
+ Person.connection.drop_table(:delete_me) rescue nil
808
+ end
809
+
810
+ def test_adding_multiple_columns
811
+ assert_queries(1) do
812
+ with_bulk_change_table do |t|
813
+ t.column :name, :string
814
+ t.string :qualification, :experience
815
+ t.integer :age, :default => 0
816
+ t.date :birthdate
817
+ t.timestamps null: true
818
+ end
819
+ end
820
+
821
+ assert_equal 8, columns.size
822
+ [:name, :qualification, :experience].each {|s| assert_equal :string, column(s).type }
823
+ assert_equal '0', column(:age).default
824
+ end
825
+
826
+ def test_removing_columns
827
+ with_bulk_change_table do |t|
828
+ t.string :qualification, :experience
829
+ end
830
+
831
+ [:qualification, :experience].each {|c| assert column(c) }
832
+
833
+ assert_queries(1) do
834
+ with_bulk_change_table do |t|
835
+ t.remove :qualification, :experience
836
+ t.string :qualification_experience
837
+ end
838
+ end
839
+
840
+ [:qualification, :experience].each {|c| assert ! column(c) }
841
+ assert column(:qualification_experience)
842
+ end
843
+
844
+ def test_adding_indexes
845
+ with_bulk_change_table do |t|
846
+ t.string :username
847
+ t.string :name
848
+ t.integer :age
849
+ end
850
+
851
+ # Adding an index fires a query every time to check if an index already exists or not
852
+ assert_queries(3) do
853
+ with_bulk_change_table do |t|
854
+ t.index :username, :unique => true, :name => :awesome_username_index
855
+ t.index [:name, :age]
856
+ end
857
+ end
858
+
859
+ assert_equal 2, indexes.size
860
+
861
+ name_age_index = index(:index_delete_me_on_name_and_age)
862
+ assert_equal ['name', 'age'].sort, name_age_index.columns.sort
863
+ assert ! name_age_index.unique
864
+
865
+ assert index(:awesome_username_index).unique
866
+ end
867
+
868
+ def test_removing_index
869
+ with_bulk_change_table do |t|
870
+ t.string :name
871
+ t.index :name
872
+ end
873
+
874
+ assert index(:index_delete_me_on_name)
875
+
876
+ assert_queries(3) do
877
+ with_bulk_change_table do |t|
878
+ t.remove_index :name
879
+ t.index :name, :name => :new_name_index, :unique => true
880
+ end
881
+ end
882
+
883
+ assert ! index(:index_delete_me_on_name)
884
+
885
+ new_name_index = index(:new_name_index)
886
+ assert new_name_index.unique
887
+ end
888
+
889
+ def test_changing_columns
890
+ with_bulk_change_table do |t|
891
+ t.string :name
892
+ t.date :birthdate
893
+ end
894
+
895
+ assert ! column(:name).default
896
+ assert_equal :date, column(:birthdate).type
897
+
898
+ # One query for columns (delete_me table)
899
+ # One query for primary key (delete_me table)
900
+ # One query to do the bulk change
901
+ assert_queries(3, :ignore_none => true) do
902
+ with_bulk_change_table do |t|
903
+ t.change :name, :string, :default => 'NONAME'
904
+ t.change :birthdate, :datetime
905
+ end
906
+ end
907
+
908
+ assert_equal 'NONAME', column(:name).default
909
+ assert_equal :datetime, column(:birthdate).type
910
+ end
911
+
912
+ protected
913
+
914
+ def with_bulk_change_table
915
+ # Reset columns/indexes cache as we're changing the table
916
+ @columns = @indexes = nil
917
+
918
+ Person.connection.change_table(:delete_me, :bulk => true) do |t|
919
+ yield t
920
+ end
921
+ end
922
+
923
+ def column(name)
924
+ columns.detect {|c| c.name == name.to_s }
925
+ end
926
+
927
+ def columns
928
+ @columns ||= Person.connection.columns('delete_me')
929
+ end
930
+
931
+ def index(name)
932
+ indexes.detect {|i| i.name == name.to_s }
933
+ end
934
+
935
+ def indexes
936
+ @indexes ||= Person.connection.indexes('delete_me')
937
+ end
938
+ end # AlterTableMigrationsTest
939
+
940
+ end
941
+
942
+ class CopyMigrationsTest < ActiveRecord::TestCase
943
+ include ActiveSupport::Testing::Stream
944
+
945
+ def setup
946
+ end
947
+
948
+ def clear
949
+ ActiveRecord::Base.timestamped_migrations = true
950
+ to_delete = Dir[@migrations_path + "/*.rb"] - @existing_migrations
951
+ File.delete(*to_delete)
952
+ end
953
+
954
+ def test_copying_migrations_without_timestamps
955
+ ActiveRecord::Base.timestamped_migrations = false
956
+ @migrations_path = MIGRATIONS_ROOT + "/valid"
957
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
958
+
959
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"})
960
+ assert File.exist?(@migrations_path + "/4_people_have_hobbies.bukkits.rb")
961
+ assert File.exist?(@migrations_path + "/5_people_have_descriptions.bukkits.rb")
962
+ assert_equal [@migrations_path + "/4_people_have_hobbies.bukkits.rb", @migrations_path + "/5_people_have_descriptions.bukkits.rb"], copied.map(&:filename)
963
+
964
+ expected = "# This migration comes from bukkits (originally 1)"
965
+ assert_equal expected, IO.readlines(@migrations_path + "/4_people_have_hobbies.bukkits.rb")[0].chomp
966
+
967
+ files_count = Dir[@migrations_path + "/*.rb"].length
968
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"})
969
+ assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
970
+ assert copied.empty?
971
+ ensure
972
+ clear
973
+ end
974
+
975
+ def test_copying_migrations_without_timestamps_from_2_sources
976
+ ActiveRecord::Base.timestamped_migrations = false
977
+ @migrations_path = MIGRATIONS_ROOT + "/valid"
978
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
979
+
980
+ sources = {}
981
+ sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy"
982
+ sources[:omg] = MIGRATIONS_ROOT + "/to_copy2"
983
+ ActiveRecord::Migration.copy(@migrations_path, sources)
984
+ assert File.exist?(@migrations_path + "/4_people_have_hobbies.bukkits.rb")
985
+ assert File.exist?(@migrations_path + "/5_people_have_descriptions.bukkits.rb")
986
+ assert File.exist?(@migrations_path + "/6_create_articles.omg.rb")
987
+ assert File.exist?(@migrations_path + "/7_create_comments.omg.rb")
988
+
989
+ files_count = Dir[@migrations_path + "/*.rb"].length
990
+ ActiveRecord::Migration.copy(@migrations_path, sources)
991
+ assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
992
+ ensure
993
+ clear
994
+ end
995
+
996
+ def test_copying_migrations_with_timestamps
997
+ @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
998
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
999
+
1000
+ travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
1001
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1002
+ assert File.exist?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
1003
+ assert File.exist?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
1004
+ expected = [@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb",
1005
+ @migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb"]
1006
+ assert_equal expected, copied.map(&:filename)
1007
+
1008
+ files_count = Dir[@migrations_path + "/*.rb"].length
1009
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1010
+ assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
1011
+ assert copied.empty?
1012
+ end
1013
+ ensure
1014
+ clear
1015
+ end
1016
+
1017
+ def test_copying_migrations_with_timestamps_from_2_sources
1018
+ @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
1019
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
1020
+
1021
+ sources = {}
1022
+ sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
1023
+ sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_timestamps2"
1024
+
1025
+ travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
1026
+ copied = ActiveRecord::Migration.copy(@migrations_path, sources)
1027
+ assert File.exist?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
1028
+ assert File.exist?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
1029
+ assert File.exist?(@migrations_path + "/20100726101012_create_articles.omg.rb")
1030
+ assert File.exist?(@migrations_path + "/20100726101013_create_comments.omg.rb")
1031
+ assert_equal 4, copied.length
1032
+
1033
+ files_count = Dir[@migrations_path + "/*.rb"].length
1034
+ ActiveRecord::Migration.copy(@migrations_path, sources)
1035
+ assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
1036
+ end
1037
+ ensure
1038
+ clear
1039
+ end
1040
+
1041
+ def test_copying_migrations_with_timestamps_to_destination_with_timestamps_in_future
1042
+ @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
1043
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
1044
+
1045
+ travel_to(Time.utc(2010, 2, 20, 10, 10, 10)) do
1046
+ ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1047
+ assert File.exist?(@migrations_path + "/20100301010102_people_have_hobbies.bukkits.rb")
1048
+ assert File.exist?(@migrations_path + "/20100301010103_people_have_descriptions.bukkits.rb")
1049
+
1050
+ files_count = Dir[@migrations_path + "/*.rb"].length
1051
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1052
+ assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
1053
+ assert copied.empty?
1054
+ end
1055
+ ensure
1056
+ clear
1057
+ end
1058
+
1059
+ def test_copying_migrations_preserving_magic_comments
1060
+ ActiveRecord::Base.timestamped_migrations = false
1061
+ @migrations_path = MIGRATIONS_ROOT + "/valid"
1062
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
1063
+
1064
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/magic"})
1065
+ assert File.exist?(@migrations_path + "/4_currencies_have_symbols.bukkits.rb")
1066
+ assert_equal [@migrations_path + "/4_currencies_have_symbols.bukkits.rb"], copied.map(&:filename)
1067
+
1068
+ expected = "# coding: ISO-8859-15\n# This migration comes from bukkits (originally 1)"
1069
+ assert_equal expected, IO.readlines(@migrations_path + "/4_currencies_have_symbols.bukkits.rb")[0..1].join.chomp
1070
+
1071
+ files_count = Dir[@migrations_path + "/*.rb"].length
1072
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/magic"})
1073
+ assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
1074
+ assert copied.empty?
1075
+ ensure
1076
+ clear
1077
+ end
1078
+
1079
+ def test_skipping_migrations
1080
+ @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
1081
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
1082
+
1083
+ sources = {}
1084
+ sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
1085
+ sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_name_collision"
1086
+
1087
+ skipped = []
1088
+ on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" }
1089
+ copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
1090
+ assert_equal 2, copied.length
1091
+
1092
+ assert_equal 1, skipped.length
1093
+ assert_equal ["omg PeopleHaveHobbies"], skipped
1094
+ ensure
1095
+ clear
1096
+ end
1097
+
1098
+ def test_skip_is_not_called_if_migrations_are_from_the_same_plugin
1099
+ @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
1100
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
1101
+
1102
+ sources = {}
1103
+ sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
1104
+
1105
+ skipped = []
1106
+ on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" }
1107
+ copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
1108
+ ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
1109
+
1110
+ assert_equal 2, copied.length
1111
+ assert_equal 0, skipped.length
1112
+ ensure
1113
+ clear
1114
+ end
1115
+
1116
+ def test_copying_migrations_to_non_existing_directory
1117
+ @migrations_path = MIGRATIONS_ROOT + "/non_existing"
1118
+ @existing_migrations = []
1119
+
1120
+ travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
1121
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1122
+ assert File.exist?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
1123
+ assert File.exist?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
1124
+ assert_equal 2, copied.length
1125
+ end
1126
+ ensure
1127
+ clear
1128
+ Dir.delete(@migrations_path)
1129
+ end
1130
+
1131
+ def test_copying_migrations_to_empty_directory
1132
+ @migrations_path = MIGRATIONS_ROOT + "/empty"
1133
+ @existing_migrations = []
1134
+
1135
+ travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
1136
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
1137
+ assert File.exist?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
1138
+ assert File.exist?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
1139
+ assert_equal 2, copied.length
1140
+ end
1141
+ ensure
1142
+ clear
1143
+ end
1144
+
1145
+ def test_check_pending_with_stdlib_logger
1146
+ old, ActiveRecord::Base.logger = ActiveRecord::Base.logger, ::Logger.new($stdout)
1147
+ quietly do
1148
+ assert_nothing_raised { ActiveRecord::Migration::CheckPending.new(Proc.new {}).call({}) }
1149
+ end
1150
+ ensure
1151
+ ActiveRecord::Base.logger = old
1152
+ end
1153
+
1154
+ def test_unknown_migration_version_should_raise_an_argument_error
1155
+ assert_raise(ArgumentError) { ActiveRecord::Migration[1.0] }
1156
+ end
1157
+ end