activerecord 2.3.18 → 3.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (378) hide show
  1. data/CHANGELOG +105 -34
  2. data/examples/performance.rb +3 -39
  3. data/examples/simple.rb +14 -0
  4. data/lib/active_record.rb +81 -47
  5. data/lib/active_record/aggregations.rb +1 -3
  6. data/lib/active_record/association_preload.rb +39 -54
  7. data/lib/active_record/associations.rb +262 -419
  8. data/lib/active_record/associations/association_collection.rb +85 -100
  9. data/lib/active_record/associations/association_proxy.rb +20 -18
  10. data/lib/active_record/associations/belongs_to_association.rb +8 -8
  11. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +13 -35
  12. data/lib/active_record/associations/has_many_association.rb +11 -19
  13. data/lib/active_record/associations/has_many_through_association.rb +30 -183
  14. data/lib/active_record/associations/has_one_association.rb +10 -10
  15. data/lib/active_record/associations/has_one_through_association.rb +13 -11
  16. data/lib/active_record/associations/through_association_scope.rb +153 -0
  17. data/lib/active_record/attribute_methods.rb +17 -370
  18. data/lib/active_record/attribute_methods/before_type_cast.rb +33 -0
  19. data/lib/active_record/attribute_methods/dirty.rb +87 -0
  20. data/lib/active_record/attribute_methods/primary_key.rb +44 -0
  21. data/lib/active_record/attribute_methods/query.rb +37 -0
  22. data/lib/active_record/attribute_methods/read.rb +116 -0
  23. data/lib/active_record/attribute_methods/time_zone_conversion.rb +60 -0
  24. data/lib/active_record/attribute_methods/write.rb +37 -0
  25. data/lib/active_record/autosave_association.rb +20 -41
  26. data/lib/active_record/base.rb +357 -1180
  27. data/lib/active_record/batches.rb +10 -16
  28. data/lib/active_record/callbacks.rb +66 -126
  29. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +17 -13
  30. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +5 -25
  31. data/lib/active_record/connection_adapters/abstract/database_statements.rb +4 -43
  32. data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -2
  33. data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -4
  34. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
  35. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +18 -72
  36. data/lib/active_record/connection_adapters/abstract_adapter.rb +16 -49
  37. data/lib/active_record/connection_adapters/mysql_adapter.rb +15 -27
  38. data/lib/active_record/connection_adapters/postgresql_adapter.rb +84 -46
  39. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +9 -3
  40. data/lib/active_record/connection_adapters/sqlite_adapter.rb +34 -65
  41. data/lib/active_record/fixtures.rb +21 -25
  42. data/lib/active_record/locale/en.yml +9 -27
  43. data/lib/active_record/locking/optimistic.rb +16 -48
  44. data/lib/active_record/migration.rb +59 -46
  45. data/lib/active_record/named_scope.rb +85 -92
  46. data/lib/active_record/nested_attributes.rb +18 -24
  47. data/lib/active_record/observer.rb +18 -94
  48. data/lib/active_record/railtie.rb +83 -0
  49. data/lib/active_record/railties/controller_runtime.rb +38 -0
  50. data/lib/active_record/railties/databases.rake +477 -0
  51. data/lib/active_record/railties/subscriber.rb +27 -0
  52. data/lib/active_record/reflection.rb +2 -15
  53. data/lib/active_record/relation.rb +339 -0
  54. data/lib/active_record/relation/calculations.rb +259 -0
  55. data/lib/active_record/relation/finder_methods.rb +315 -0
  56. data/lib/active_record/relation/predicate_builder.rb +46 -0
  57. data/lib/active_record/relation/query_methods.rb +218 -0
  58. data/lib/active_record/relation/spawn_methods.rb +102 -0
  59. data/lib/active_record/schema_dumper.rb +10 -6
  60. data/lib/active_record/serialization.rb +31 -74
  61. data/lib/active_record/serializers/xml_serializer.rb +33 -121
  62. data/lib/active_record/session_store.rb +1 -9
  63. data/lib/active_record/test_case.rb +1 -3
  64. data/lib/active_record/timestamp.rb +7 -5
  65. data/lib/active_record/transactions.rb +9 -9
  66. data/lib/active_record/validations.rb +51 -1100
  67. data/lib/active_record/validations/associated.rb +47 -0
  68. data/lib/active_record/validations/uniqueness.rb +181 -0
  69. data/lib/active_record/version.rb +3 -3
  70. data/lib/generators/active_record.rb +30 -0
  71. data/lib/generators/active_record/migration/migration_generator.rb +25 -0
  72. data/lib/generators/active_record/migration/templates/migration.rb +11 -0
  73. data/lib/generators/active_record/model/model_generator.rb +33 -0
  74. data/lib/generators/active_record/model/templates/migration.rb +16 -0
  75. data/lib/generators/active_record/model/templates/model.rb +5 -0
  76. data/lib/generators/active_record/observer/observer_generator.rb +15 -0
  77. data/lib/generators/active_record/observer/templates/observer.rb +2 -0
  78. data/lib/generators/active_record/session_migration/session_migration_generator.rb +24 -0
  79. data/lib/generators/active_record/session_migration/templates/migration.rb +16 -0
  80. metadata +67 -325
  81. data/RUNNING_UNIT_TESTS +0 -36
  82. data/Rakefile +0 -268
  83. data/install.rb +0 -30
  84. data/lib/active_record/calculations.rb +0 -321
  85. data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -57
  86. data/lib/active_record/dirty.rb +0 -183
  87. data/lib/active_record/serializers/json_serializer.rb +0 -91
  88. data/lib/activerecord.rb +0 -2
  89. data/test/assets/example.log +0 -1
  90. data/test/assets/flowers.jpg +0 -0
  91. data/test/cases/aaa_create_tables_test.rb +0 -24
  92. data/test/cases/active_schema_test_mysql.rb +0 -122
  93. data/test/cases/active_schema_test_postgresql.rb +0 -24
  94. data/test/cases/adapter_test.rb +0 -144
  95. data/test/cases/aggregations_test.rb +0 -167
  96. data/test/cases/ar_schema_test.rb +0 -32
  97. data/test/cases/associations/belongs_to_associations_test.rb +0 -438
  98. data/test/cases/associations/callbacks_test.rb +0 -161
  99. data/test/cases/associations/cascaded_eager_loading_test.rb +0 -131
  100. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +0 -36
  101. data/test/cases/associations/eager_load_nested_include_test.rb +0 -131
  102. data/test/cases/associations/eager_load_nested_polymorphic_include.rb +0 -19
  103. data/test/cases/associations/eager_singularization_test.rb +0 -145
  104. data/test/cases/associations/eager_test.rb +0 -852
  105. data/test/cases/associations/extension_test.rb +0 -62
  106. data/test/cases/associations/habtm_join_table_test.rb +0 -56
  107. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +0 -827
  108. data/test/cases/associations/has_many_associations_test.rb +0 -1273
  109. data/test/cases/associations/has_many_through_associations_test.rb +0 -360
  110. data/test/cases/associations/has_one_associations_test.rb +0 -330
  111. data/test/cases/associations/has_one_through_associations_test.rb +0 -209
  112. data/test/cases/associations/inner_join_association_test.rb +0 -93
  113. data/test/cases/associations/inverse_associations_test.rb +0 -566
  114. data/test/cases/associations/join_model_test.rb +0 -712
  115. data/test/cases/associations_test.rb +0 -282
  116. data/test/cases/attribute_methods_test.rb +0 -305
  117. data/test/cases/autosave_association_test.rb +0 -1218
  118. data/test/cases/base_test.rb +0 -2166
  119. data/test/cases/batches_test.rb +0 -81
  120. data/test/cases/binary_test.rb +0 -30
  121. data/test/cases/calculations_test.rb +0 -360
  122. data/test/cases/callbacks_observers_test.rb +0 -38
  123. data/test/cases/callbacks_test.rb +0 -438
  124. data/test/cases/class_inheritable_attributes_test.rb +0 -32
  125. data/test/cases/column_alias_test.rb +0 -17
  126. data/test/cases/column_definition_test.rb +0 -70
  127. data/test/cases/connection_pool_test.rb +0 -25
  128. data/test/cases/connection_test_firebird.rb +0 -8
  129. data/test/cases/connection_test_mysql.rb +0 -65
  130. data/test/cases/copy_table_test_sqlite.rb +0 -80
  131. data/test/cases/counter_cache_test.rb +0 -84
  132. data/test/cases/database_statements_test.rb +0 -12
  133. data/test/cases/datatype_test_postgresql.rb +0 -204
  134. data/test/cases/date_time_test.rb +0 -37
  135. data/test/cases/default_test_firebird.rb +0 -16
  136. data/test/cases/defaults_test.rb +0 -111
  137. data/test/cases/deprecated_finder_test.rb +0 -30
  138. data/test/cases/dirty_test.rb +0 -316
  139. data/test/cases/finder_respond_to_test.rb +0 -76
  140. data/test/cases/finder_test.rb +0 -1098
  141. data/test/cases/fixtures_test.rb +0 -661
  142. data/test/cases/helper.rb +0 -68
  143. data/test/cases/i18n_test.rb +0 -46
  144. data/test/cases/inheritance_test.rb +0 -262
  145. data/test/cases/invalid_date_test.rb +0 -24
  146. data/test/cases/json_serialization_test.rb +0 -219
  147. data/test/cases/lifecycle_test.rb +0 -193
  148. data/test/cases/locking_test.rb +0 -350
  149. data/test/cases/method_scoping_test.rb +0 -704
  150. data/test/cases/migration_test.rb +0 -1649
  151. data/test/cases/migration_test_firebird.rb +0 -124
  152. data/test/cases/mixin_test.rb +0 -96
  153. data/test/cases/modules_test.rb +0 -109
  154. data/test/cases/multiple_db_test.rb +0 -85
  155. data/test/cases/named_scope_test.rb +0 -372
  156. data/test/cases/nested_attributes_test.rb +0 -840
  157. data/test/cases/pk_test.rb +0 -119
  158. data/test/cases/pooled_connections_test.rb +0 -103
  159. data/test/cases/query_cache_test.rb +0 -129
  160. data/test/cases/readonly_test.rb +0 -107
  161. data/test/cases/reflection_test.rb +0 -234
  162. data/test/cases/reload_models_test.rb +0 -22
  163. data/test/cases/repair_helper.rb +0 -50
  164. data/test/cases/reserved_word_test_mysql.rb +0 -176
  165. data/test/cases/sanitize_test.rb +0 -25
  166. data/test/cases/schema_authorization_test_postgresql.rb +0 -75
  167. data/test/cases/schema_dumper_test.rb +0 -211
  168. data/test/cases/schema_test_postgresql.rb +0 -178
  169. data/test/cases/serialization_test.rb +0 -47
  170. data/test/cases/sp_test_mysql.rb +0 -16
  171. data/test/cases/synonym_test_oracle.rb +0 -17
  172. data/test/cases/timestamp_test.rb +0 -75
  173. data/test/cases/transactions_test.rb +0 -543
  174. data/test/cases/unconnected_test.rb +0 -32
  175. data/test/cases/validations_i18n_test.rb +0 -925
  176. data/test/cases/validations_test.rb +0 -1684
  177. data/test/cases/xml_serialization_test.rb +0 -240
  178. data/test/cases/yaml_serialization_test.rb +0 -11
  179. data/test/config.rb +0 -5
  180. data/test/connections/jdbc_jdbcderby/connection.rb +0 -18
  181. data/test/connections/jdbc_jdbch2/connection.rb +0 -18
  182. data/test/connections/jdbc_jdbchsqldb/connection.rb +0 -18
  183. data/test/connections/jdbc_jdbcmysql/connection.rb +0 -26
  184. data/test/connections/jdbc_jdbcpostgresql/connection.rb +0 -26
  185. data/test/connections/jdbc_jdbcsqlite3/connection.rb +0 -25
  186. data/test/connections/native_db2/connection.rb +0 -25
  187. data/test/connections/native_firebird/connection.rb +0 -26
  188. data/test/connections/native_frontbase/connection.rb +0 -27
  189. data/test/connections/native_mysql/connection.rb +0 -25
  190. data/test/connections/native_openbase/connection.rb +0 -21
  191. data/test/connections/native_oracle/connection.rb +0 -27
  192. data/test/connections/native_postgresql/connection.rb +0 -21
  193. data/test/connections/native_sqlite/connection.rb +0 -25
  194. data/test/connections/native_sqlite3/connection.rb +0 -25
  195. data/test/connections/native_sqlite3/in_memory_connection.rb +0 -18
  196. data/test/connections/native_sybase/connection.rb +0 -23
  197. data/test/fixtures/accounts.yml +0 -29
  198. data/test/fixtures/all/developers.yml +0 -0
  199. data/test/fixtures/all/people.csv +0 -0
  200. data/test/fixtures/all/tasks.yml +0 -0
  201. data/test/fixtures/author_addresses.yml +0 -5
  202. data/test/fixtures/author_favorites.yml +0 -4
  203. data/test/fixtures/authors.yml +0 -9
  204. data/test/fixtures/binaries.yml +0 -132
  205. data/test/fixtures/books.yml +0 -7
  206. data/test/fixtures/categories.yml +0 -14
  207. data/test/fixtures/categories/special_categories.yml +0 -9
  208. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +0 -4
  209. data/test/fixtures/categories_ordered.yml +0 -7
  210. data/test/fixtures/categories_posts.yml +0 -23
  211. data/test/fixtures/categorizations.yml +0 -17
  212. data/test/fixtures/clubs.yml +0 -6
  213. data/test/fixtures/comments.yml +0 -59
  214. data/test/fixtures/companies.yml +0 -56
  215. data/test/fixtures/computers.yml +0 -4
  216. data/test/fixtures/courses.yml +0 -7
  217. data/test/fixtures/customers.yml +0 -26
  218. data/test/fixtures/developers.yml +0 -21
  219. data/test/fixtures/developers_projects.yml +0 -17
  220. data/test/fixtures/edges.yml +0 -6
  221. data/test/fixtures/entrants.yml +0 -14
  222. data/test/fixtures/faces.yml +0 -11
  223. data/test/fixtures/fk_test_has_fk.yml +0 -3
  224. data/test/fixtures/fk_test_has_pk.yml +0 -2
  225. data/test/fixtures/funny_jokes.yml +0 -10
  226. data/test/fixtures/interests.yml +0 -33
  227. data/test/fixtures/items.yml +0 -4
  228. data/test/fixtures/jobs.yml +0 -7
  229. data/test/fixtures/legacy_things.yml +0 -3
  230. data/test/fixtures/mateys.yml +0 -4
  231. data/test/fixtures/member_types.yml +0 -6
  232. data/test/fixtures/members.yml +0 -6
  233. data/test/fixtures/memberships.yml +0 -20
  234. data/test/fixtures/men.yml +0 -5
  235. data/test/fixtures/minimalistics.yml +0 -2
  236. data/test/fixtures/mixed_case_monkeys.yml +0 -6
  237. data/test/fixtures/mixins.yml +0 -29
  238. data/test/fixtures/movies.yml +0 -7
  239. data/test/fixtures/naked/csv/accounts.csv +0 -1
  240. data/test/fixtures/naked/yml/accounts.yml +0 -1
  241. data/test/fixtures/naked/yml/companies.yml +0 -1
  242. data/test/fixtures/naked/yml/courses.yml +0 -1
  243. data/test/fixtures/organizations.yml +0 -5
  244. data/test/fixtures/owners.yml +0 -7
  245. data/test/fixtures/parrots.yml +0 -27
  246. data/test/fixtures/parrots_pirates.yml +0 -7
  247. data/test/fixtures/people.yml +0 -15
  248. data/test/fixtures/pets.yml +0 -14
  249. data/test/fixtures/pirates.yml +0 -9
  250. data/test/fixtures/polymorphic_designs.yml +0 -19
  251. data/test/fixtures/polymorphic_prices.yml +0 -19
  252. data/test/fixtures/posts.yml +0 -52
  253. data/test/fixtures/price_estimates.yml +0 -7
  254. data/test/fixtures/projects.yml +0 -7
  255. data/test/fixtures/readers.yml +0 -9
  256. data/test/fixtures/references.yml +0 -17
  257. data/test/fixtures/reserved_words/distinct.yml +0 -5
  258. data/test/fixtures/reserved_words/distincts_selects.yml +0 -11
  259. data/test/fixtures/reserved_words/group.yml +0 -14
  260. data/test/fixtures/reserved_words/select.yml +0 -8
  261. data/test/fixtures/reserved_words/values.yml +0 -7
  262. data/test/fixtures/ships.yml +0 -5
  263. data/test/fixtures/sponsors.yml +0 -9
  264. data/test/fixtures/subscribers.yml +0 -7
  265. data/test/fixtures/subscriptions.yml +0 -12
  266. data/test/fixtures/taggings.yml +0 -28
  267. data/test/fixtures/tags.yml +0 -7
  268. data/test/fixtures/tasks.yml +0 -7
  269. data/test/fixtures/tees.yml +0 -4
  270. data/test/fixtures/ties.yml +0 -4
  271. data/test/fixtures/topics.yml +0 -42
  272. data/test/fixtures/toys.yml +0 -4
  273. data/test/fixtures/treasures.yml +0 -10
  274. data/test/fixtures/vertices.yml +0 -4
  275. data/test/fixtures/warehouse-things.yml +0 -3
  276. data/test/fixtures/zines.yml +0 -5
  277. data/test/migrations/broken/100_migration_that_raises_exception.rb +0 -10
  278. data/test/migrations/decimal/1_give_me_big_numbers.rb +0 -15
  279. data/test/migrations/duplicate/1_people_have_last_names.rb +0 -9
  280. data/test/migrations/duplicate/2_we_need_reminders.rb +0 -12
  281. data/test/migrations/duplicate/3_foo.rb +0 -7
  282. data/test/migrations/duplicate/3_innocent_jointable.rb +0 -12
  283. data/test/migrations/duplicate_names/20080507052938_chunky.rb +0 -7
  284. data/test/migrations/duplicate_names/20080507053028_chunky.rb +0 -7
  285. data/test/migrations/interleaved/pass_1/3_innocent_jointable.rb +0 -12
  286. data/test/migrations/interleaved/pass_2/1_people_have_last_names.rb +0 -9
  287. data/test/migrations/interleaved/pass_2/3_innocent_jointable.rb +0 -12
  288. data/test/migrations/interleaved/pass_3/1_people_have_last_names.rb +0 -9
  289. data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +0 -8
  290. data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +0 -12
  291. data/test/migrations/missing/1000_people_have_middle_names.rb +0 -9
  292. data/test/migrations/missing/1_people_have_last_names.rb +0 -9
  293. data/test/migrations/missing/3_we_need_reminders.rb +0 -12
  294. data/test/migrations/missing/4_innocent_jointable.rb +0 -12
  295. data/test/migrations/valid/1_people_have_last_names.rb +0 -9
  296. data/test/migrations/valid/2_we_need_reminders.rb +0 -12
  297. data/test/migrations/valid/3_innocent_jointable.rb +0 -12
  298. data/test/models/author.rb +0 -151
  299. data/test/models/auto_id.rb +0 -4
  300. data/test/models/binary.rb +0 -2
  301. data/test/models/bird.rb +0 -9
  302. data/test/models/book.rb +0 -4
  303. data/test/models/categorization.rb +0 -5
  304. data/test/models/category.rb +0 -34
  305. data/test/models/citation.rb +0 -6
  306. data/test/models/club.rb +0 -13
  307. data/test/models/column_name.rb +0 -3
  308. data/test/models/comment.rb +0 -29
  309. data/test/models/company.rb +0 -173
  310. data/test/models/company_in_module.rb +0 -78
  311. data/test/models/computer.rb +0 -3
  312. data/test/models/contact.rb +0 -16
  313. data/test/models/contract.rb +0 -5
  314. data/test/models/course.rb +0 -3
  315. data/test/models/customer.rb +0 -73
  316. data/test/models/default.rb +0 -2
  317. data/test/models/developer.rb +0 -101
  318. data/test/models/edge.rb +0 -5
  319. data/test/models/entrant.rb +0 -3
  320. data/test/models/essay.rb +0 -3
  321. data/test/models/event.rb +0 -3
  322. data/test/models/event_author.rb +0 -8
  323. data/test/models/face.rb +0 -7
  324. data/test/models/guid.rb +0 -2
  325. data/test/models/interest.rb +0 -5
  326. data/test/models/invoice.rb +0 -4
  327. data/test/models/item.rb +0 -7
  328. data/test/models/job.rb +0 -5
  329. data/test/models/joke.rb +0 -3
  330. data/test/models/keyboard.rb +0 -3
  331. data/test/models/legacy_thing.rb +0 -3
  332. data/test/models/line_item.rb +0 -3
  333. data/test/models/man.rb +0 -9
  334. data/test/models/matey.rb +0 -4
  335. data/test/models/member.rb +0 -12
  336. data/test/models/member_detail.rb +0 -5
  337. data/test/models/member_type.rb +0 -3
  338. data/test/models/membership.rb +0 -9
  339. data/test/models/minimalistic.rb +0 -2
  340. data/test/models/mixed_case_monkey.rb +0 -3
  341. data/test/models/movie.rb +0 -5
  342. data/test/models/order.rb +0 -4
  343. data/test/models/organization.rb +0 -6
  344. data/test/models/owner.rb +0 -5
  345. data/test/models/parrot.rb +0 -22
  346. data/test/models/person.rb +0 -16
  347. data/test/models/pet.rb +0 -5
  348. data/test/models/pirate.rb +0 -80
  349. data/test/models/polymorphic_design.rb +0 -3
  350. data/test/models/polymorphic_price.rb +0 -3
  351. data/test/models/post.rb +0 -102
  352. data/test/models/price_estimate.rb +0 -3
  353. data/test/models/project.rb +0 -30
  354. data/test/models/reader.rb +0 -4
  355. data/test/models/reference.rb +0 -4
  356. data/test/models/reply.rb +0 -46
  357. data/test/models/ship.rb +0 -19
  358. data/test/models/ship_part.rb +0 -7
  359. data/test/models/sponsor.rb +0 -4
  360. data/test/models/subject.rb +0 -4
  361. data/test/models/subscriber.rb +0 -8
  362. data/test/models/subscription.rb +0 -4
  363. data/test/models/tag.rb +0 -7
  364. data/test/models/tagging.rb +0 -10
  365. data/test/models/task.rb +0 -3
  366. data/test/models/tee.rb +0 -4
  367. data/test/models/tie.rb +0 -4
  368. data/test/models/topic.rb +0 -80
  369. data/test/models/toy.rb +0 -6
  370. data/test/models/treasure.rb +0 -8
  371. data/test/models/vertex.rb +0 -9
  372. data/test/models/warehouse_thing.rb +0 -5
  373. data/test/models/zine.rb +0 -3
  374. data/test/schema/mysql_specific_schema.rb +0 -31
  375. data/test/schema/postgresql_specific_schema.rb +0 -114
  376. data/test/schema/schema.rb +0 -550
  377. data/test/schema/schema2.rb +0 -6
  378. data/test/schema/sqlite_specific_schema.rb +0 -25
@@ -1,1649 +0,0 @@
1
- require "cases/helper"
2
- require 'bigdecimal/util'
3
-
4
- require 'models/person'
5
- require 'models/topic'
6
- require 'models/developer'
7
-
8
- require MIGRATIONS_ROOT + "/valid/1_people_have_last_names"
9
- require MIGRATIONS_ROOT + "/valid/2_we_need_reminders"
10
- require MIGRATIONS_ROOT + "/decimal/1_give_me_big_numbers"
11
- require MIGRATIONS_ROOT + "/interleaved/pass_3/2_i_raise_on_down"
12
-
13
- if ActiveRecord::Base.connection.supports_migrations?
14
- class BigNumber < ActiveRecord::Base; end
15
-
16
- class Reminder < ActiveRecord::Base; end
17
-
18
- class ActiveRecord::Migration
19
- class <<self
20
- attr_accessor :message_count
21
- def puts(text="")
22
- self.message_count ||= 0
23
- self.message_count += 1
24
- end
25
- end
26
- end
27
-
28
- class MigrationTableAndIndexTest < ActiveRecord::TestCase
29
- def test_add_schema_info_respects_prefix_and_suffix
30
- conn = ActiveRecord::Base.connection
31
-
32
- conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
33
- ActiveRecord::Base.table_name_prefix = 'foo_'
34
- ActiveRecord::Base.table_name_suffix = '_bar'
35
- conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
36
-
37
- conn.initialize_schema_migrations_table
38
-
39
- assert_equal "foo_unique_schema_migrations_bar", conn.indexes(ActiveRecord::Migrator.schema_migrations_table_name)[0][:name]
40
- ensure
41
- ActiveRecord::Base.table_name_prefix = ""
42
- ActiveRecord::Base.table_name_suffix = ""
43
- end
44
- end
45
-
46
- class MigrationTest < ActiveRecord::TestCase
47
- self.use_transactional_fixtures = false
48
-
49
- fixtures :people
50
-
51
- def setup
52
- ActiveRecord::Migration.verbose = true
53
- PeopleHaveLastNames.message_count = 0
54
- end
55
-
56
- def teardown
57
- ActiveRecord::Base.connection.initialize_schema_migrations_table
58
- ActiveRecord::Base.connection.execute "DELETE FROM #{ActiveRecord::Migrator.schema_migrations_table_name}"
59
-
60
- %w(reminders people_reminders prefix_reminders_suffix).each do |table|
61
- Reminder.connection.drop_table(table) rescue nil
62
- end
63
- Reminder.reset_column_information
64
-
65
- %w(last_name key bio age height wealth birthday favorite_day
66
- moment_of_truth male administrator funny).each do |column|
67
- Person.connection.remove_column('people', column) rescue nil
68
- end
69
- Person.connection.remove_column("people", "first_name") rescue nil
70
- Person.connection.remove_column("people", "middle_name") rescue nil
71
- Person.connection.add_column("people", "first_name", :string, :limit => 40)
72
- Person.reset_column_information
73
- end
74
-
75
- def test_add_index
76
- # Limit size of last_name and key columns to support Firebird index limitations
77
- Person.connection.add_column "people", "last_name", :string, :limit => 100
78
- Person.connection.add_column "people", "key", :string, :limit => 100
79
- Person.connection.add_column "people", "administrator", :boolean
80
-
81
- assert_nothing_raised { Person.connection.add_index("people", "last_name") }
82
- assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
83
-
84
- # Orcl nds shrt indx nms. Sybs 2.
85
- # OpenBase does not have named indexes. You must specify a single column name
86
- unless current_adapter?(:OracleAdapter, :SybaseAdapter, :OpenBaseAdapter)
87
- assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
88
- assert_nothing_raised { Person.connection.remove_index("people", :column => ["last_name", "first_name"]) }
89
- assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
90
- assert_nothing_raised { Person.connection.remove_index("people", :name => "index_people_on_last_name_and_first_name") }
91
- assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
92
- assert_nothing_raised { Person.connection.remove_index("people", "last_name_and_first_name") }
93
- assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
94
- assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
95
- assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :length => 10) }
96
- assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
97
- assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :length => {:last_name => 10}) }
98
- assert_nothing_raised { Person.connection.remove_index("people", ["last_name"]) }
99
- assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :length => 10) }
100
- assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
101
- assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :length => {:last_name => 10, :first_name => 20}) }
102
- assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
103
- end
104
-
105
- # quoting
106
- # Note: changed index name from "key" to "key_idx" since "key" is a Firebird reserved word
107
- # OpenBase does not have named indexes. You must specify a single column name
108
- unless current_adapter?(:OpenBaseAdapter)
109
- Person.update_all "#{Person.connection.quote_column_name 'key'}=#{Person.connection.quote_column_name 'id'}" #some databases (including sqlite2 won't add a unique index if existing data non unique)
110
- assert_nothing_raised { Person.connection.add_index("people", ["key"], :name => "key_idx", :unique => true) }
111
- assert_nothing_raised { Person.connection.remove_index("people", :name => "key_idx", :unique => true) }
112
- end
113
-
114
- # Sybase adapter does not support indexes on :boolean columns
115
- # OpenBase does not have named indexes. You must specify a single column
116
- unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter)
117
- assert_nothing_raised { Person.connection.add_index("people", %w(last_name first_name administrator), :name => "named_admin") }
118
- assert_nothing_raised { Person.connection.remove_index("people", :name => "named_admin") }
119
- end
120
- end
121
-
122
- def test_index_symbol_names
123
- assert_nothing_raised { Person.connection.add_index :people, :primary_contact_id, :name => :symbol_index_name }
124
- assert Person.connection.index_exists?(:people, :symbol_index_name, true)
125
- assert_nothing_raised { Person.connection.remove_index :people, :name => :symbol_index_name }
126
- assert_equal true, !Person.connection.index_exists?(:people, :symbol_index_name, false)
127
- end
128
-
129
- def test_add_index_length_limit
130
- good_index_name = 'x' * Person.connection.index_name_length
131
- too_long_index_name = good_index_name + 'x'
132
- assert_nothing_raised { Person.connection.add_index("people", "first_name", :name => too_long_index_name) }
133
- assert !Person.connection.index_exists?("people", too_long_index_name, false)
134
- assert_nothing_raised { Person.connection.add_index("people", "first_name", :name => good_index_name) }
135
- assert Person.connection.index_exists?("people", good_index_name, false)
136
- end
137
-
138
- def test_remove_nonexistent_index
139
- # we do this by name, so OpenBase is a wash as noted above
140
- unless current_adapter?(:OpenBaseAdapter)
141
- assert_nothing_raised { Person.connection.remove_index("people", "no_such_index") }
142
- end
143
- end
144
-
145
- def test_rename_index
146
- unless current_adapter?(:OpenBaseAdapter)
147
- # keep the names short to make Oracle and similar behave
148
- Person.connection.add_index('people', [:first_name], :name => 'old_idx')
149
- assert_nothing_raised { Person.connection.rename_index('people', 'old_idx', 'new_idx') }
150
- # if the adapter doesn't support the indexes call, pick defaults that let the test pass
151
- assert !Person.connection.index_exists?('people', 'old_idx', false)
152
- assert Person.connection.index_exists?('people', 'new_idx', true)
153
- end
154
- end
155
-
156
- def test_double_add_index
157
- unless current_adapter?(:OpenBaseAdapter)
158
- Person.connection.add_index('people', [:first_name], :name => 'some_idx')
159
- assert_nothing_raised { Person.connection.add_index('people', [:first_name], :name => 'some_idx') }
160
- end
161
- end
162
-
163
- def testing_table_with_only_foo_attribute
164
- Person.connection.create_table :testings, :id => false do |t|
165
- t.column :foo, :string
166
- end
167
-
168
- yield Person.connection
169
- ensure
170
- Person.connection.drop_table :testings rescue nil
171
- end
172
- protected :testing_table_with_only_foo_attribute
173
-
174
- def test_create_table_without_id
175
- testing_table_with_only_foo_attribute do |connection|
176
- assert_equal connection.columns(:testings).size, 1
177
- end
178
- end
179
-
180
- def test_add_column_with_primary_key_attribute
181
- testing_table_with_only_foo_attribute do |connection|
182
- assert_nothing_raised { connection.add_column :testings, :id, :primary_key }
183
- assert_equal connection.columns(:testings).size, 2
184
- end
185
- end
186
-
187
- def test_create_table_adds_id
188
- Person.connection.create_table :testings do |t|
189
- t.column :foo, :string
190
- end
191
-
192
- assert_equal %w(foo id),
193
- Person.connection.columns(:testings).map { |c| c.name }.sort
194
- ensure
195
- Person.connection.drop_table :testings rescue nil
196
- end
197
-
198
- def test_create_table_with_not_null_column
199
- assert_nothing_raised do
200
- Person.connection.create_table :testings do |t|
201
- t.column :foo, :string, :null => false
202
- end
203
- end
204
-
205
- assert_raise(ActiveRecord::StatementInvalid) do
206
- Person.connection.execute "insert into testings (foo) values (NULL)"
207
- end
208
- ensure
209
- Person.connection.drop_table :testings rescue nil
210
- end
211
-
212
- def test_create_table_with_defaults
213
- # MySQL doesn't allow defaults on TEXT or BLOB columns.
214
- mysql = current_adapter?(:MysqlAdapter)
215
-
216
- Person.connection.create_table :testings do |t|
217
- t.column :one, :string, :default => "hello"
218
- t.column :two, :boolean, :default => true
219
- t.column :three, :boolean, :default => false
220
- t.column :four, :integer, :default => 1
221
- t.column :five, :text, :default => "hello" unless mysql
222
- end
223
-
224
- columns = Person.connection.columns(:testings)
225
- one = columns.detect { |c| c.name == "one" }
226
- two = columns.detect { |c| c.name == "two" }
227
- three = columns.detect { |c| c.name == "three" }
228
- four = columns.detect { |c| c.name == "four" }
229
- five = columns.detect { |c| c.name == "five" } unless mysql
230
-
231
- assert_equal "hello", one.default
232
- assert_equal true, two.default
233
- assert_equal false, three.default
234
- assert_equal 1, four.default
235
- assert_equal "hello", five.default unless mysql
236
-
237
- ensure
238
- Person.connection.drop_table :testings rescue nil
239
- end
240
-
241
- def test_create_table_with_limits
242
- assert_nothing_raised do
243
- Person.connection.create_table :testings do |t|
244
- t.column :foo, :string, :limit => 255
245
-
246
- t.column :default_int, :integer
247
-
248
- t.column :one_int, :integer, :limit => 1
249
- t.column :four_int, :integer, :limit => 4
250
- t.column :eight_int, :integer, :limit => 8
251
- t.column :eleven_int, :integer, :limit => 11
252
- end
253
- end
254
-
255
- columns = Person.connection.columns(:testings)
256
- foo = columns.detect { |c| c.name == "foo" }
257
- assert_equal 255, foo.limit
258
-
259
- default = columns.detect { |c| c.name == "default_int" }
260
- one = columns.detect { |c| c.name == "one_int" }
261
- four = columns.detect { |c| c.name == "four_int" }
262
- eight = columns.detect { |c| c.name == "eight_int" }
263
- eleven = columns.detect { |c| c.name == "eleven_int" }
264
-
265
- if current_adapter?(:PostgreSQLAdapter)
266
- assert_equal 'integer', default.sql_type
267
- assert_equal 'smallint', one.sql_type
268
- assert_equal 'integer', four.sql_type
269
- assert_equal 'bigint', eight.sql_type
270
- assert_equal 'integer', eleven.sql_type
271
- elsif current_adapter?(:MysqlAdapter)
272
- assert_match 'int(11)', default.sql_type
273
- assert_match 'tinyint', one.sql_type
274
- assert_match 'int', four.sql_type
275
- assert_match 'bigint', eight.sql_type
276
- assert_match 'int(11)', eleven.sql_type
277
- elsif current_adapter?(:OracleAdapter)
278
- assert_equal 'NUMBER(38)', default.sql_type
279
- assert_equal 'NUMBER(1)', one.sql_type
280
- assert_equal 'NUMBER(4)', four.sql_type
281
- assert_equal 'NUMBER(8)', eight.sql_type
282
- end
283
- ensure
284
- Person.connection.drop_table :testings rescue nil
285
- end
286
-
287
- def test_create_table_with_primary_key_prefix_as_table_name_with_underscore
288
- ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore
289
-
290
- Person.connection.create_table :testings do |t|
291
- t.column :foo, :string
292
- end
293
-
294
- assert_equal %w(foo testing_id), Person.connection.columns(:testings).map { |c| c.name }.sort
295
- ensure
296
- Person.connection.drop_table :testings rescue nil
297
- ActiveRecord::Base.primary_key_prefix_type = nil
298
- end
299
-
300
- def test_create_table_with_primary_key_prefix_as_table_name
301
- ActiveRecord::Base.primary_key_prefix_type = :table_name
302
-
303
- Person.connection.create_table :testings do |t|
304
- t.column :foo, :string
305
- end
306
-
307
- assert_equal %w(foo testingid), Person.connection.columns(:testings).map { |c| c.name }.sort
308
- ensure
309
- Person.connection.drop_table :testings rescue nil
310
- ActiveRecord::Base.primary_key_prefix_type = nil
311
- end
312
-
313
- def test_create_table_with_force_true_does_not_drop_nonexisting_table
314
- if Person.connection.table_exists?(:testings2)
315
- Person.connection.drop_table :testings2
316
- end
317
-
318
- # using a copy as we need the drop_table method to
319
- # continue to work for the ensure block of the test
320
- temp_conn = Person.connection.dup
321
- temp_conn.expects(:drop_table).never
322
- temp_conn.create_table :testings2, :force => true do |t|
323
- t.column :foo, :string
324
- end
325
- ensure
326
- Person.connection.drop_table :testings2 rescue nil
327
- end
328
-
329
- def test_create_table_with_timestamps_should_create_datetime_columns
330
- table_name = :testings
331
-
332
- Person.connection.create_table table_name do |t|
333
- t.timestamps
334
- end
335
- created_columns = Person.connection.columns(table_name)
336
-
337
- created_at_column = created_columns.detect {|c| c.name == 'created_at' }
338
- updated_at_column = created_columns.detect {|c| c.name == 'updated_at' }
339
-
340
- assert created_at_column.null
341
- assert updated_at_column.null
342
- ensure
343
- Person.connection.drop_table table_name rescue nil
344
- end
345
-
346
- def test_create_table_with_timestamps_should_create_datetime_columns_with_options
347
- table_name = :testings
348
-
349
- Person.connection.create_table table_name do |t|
350
- t.timestamps :null => false
351
- end
352
- created_columns = Person.connection.columns(table_name)
353
-
354
- created_at_column = created_columns.detect {|c| c.name == 'created_at' }
355
- updated_at_column = created_columns.detect {|c| c.name == 'updated_at' }
356
-
357
- assert !created_at_column.null
358
- assert !updated_at_column.null
359
- ensure
360
- Person.connection.drop_table table_name rescue nil
361
- end
362
-
363
- def test_create_table_without_a_block
364
- table_name = :testings
365
- Person.connection.create_table table_name
366
- ensure
367
- Person.connection.drop_table table_name rescue nil
368
- end
369
-
370
- # Sybase, and SQLite3 will not allow you to add a NOT NULL
371
- # column to a table without a default value.
372
- unless current_adapter?(:SybaseAdapter, :SQLiteAdapter)
373
- def test_add_column_not_null_without_default
374
- Person.connection.create_table :testings do |t|
375
- t.column :foo, :string
376
- end
377
- Person.connection.add_column :testings, :bar, :string, :null => false
378
-
379
- assert_raise(ActiveRecord::StatementInvalid) do
380
- Person.connection.execute "insert into testings (foo, bar) values ('hello', NULL)"
381
- end
382
- ensure
383
- Person.connection.drop_table :testings rescue nil
384
- end
385
- end
386
-
387
- def test_add_column_not_null_with_default
388
- Person.connection.create_table :testings do |t|
389
- t.column :foo, :string
390
- end
391
-
392
- con = Person.connection
393
- Person.connection.enable_identity_insert("testings", true) if current_adapter?(:SybaseAdapter)
394
- Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}) values (1, 'hello')"
395
- Person.connection.enable_identity_insert("testings", false) if current_adapter?(:SybaseAdapter)
396
- assert_nothing_raised {Person.connection.add_column :testings, :bar, :string, :null => false, :default => "default" }
397
-
398
- assert_raise(ActiveRecord::StatementInvalid) do
399
- unless current_adapter?(:OpenBaseAdapter)
400
- Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) values (2, 'hello', NULL)"
401
- else
402
- Person.connection.insert("INSERT INTO testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) VALUES (2, 'hello', NULL)",
403
- "Testing Insert","id",2)
404
- end
405
- end
406
- ensure
407
- Person.connection.drop_table :testings rescue nil
408
- end
409
-
410
- # We specifically do a manual INSERT here, and then test only the SELECT
411
- # functionality. This allows us to more easily catch INSERT being broken,
412
- # but SELECT actually working fine.
413
- def test_native_decimal_insert_manual_vs_automatic
414
- correct_value = '0012345678901234567890.0123456789'.to_d
415
-
416
- Person.delete_all
417
- Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
418
- Person.reset_column_information
419
-
420
- # Do a manual insertion
421
- if current_adapter?(:OracleAdapter)
422
- Person.connection.execute "insert into people (id, wealth) values (people_seq.nextval, 12345678901234567890.0123456789)"
423
- elsif current_adapter?(:OpenBaseAdapter) || (current_adapter?(:MysqlAdapter) && Mysql.client_version < 50003) #before mysql 5.0.3 decimals stored as strings
424
- Person.connection.execute "insert into people (wealth) values ('12345678901234567890.0123456789')"
425
- else
426
- Person.connection.execute "insert into people (wealth) values (12345678901234567890.0123456789)"
427
- end
428
-
429
- # SELECT
430
- row = Person.find(:first)
431
- assert_kind_of BigDecimal, row.wealth
432
-
433
- # If this assert fails, that means the SELECT is broken!
434
- unless current_adapter?(:SQLite3Adapter)
435
- assert_equal correct_value, row.wealth
436
- end
437
-
438
- # Reset to old state
439
- Person.delete_all
440
-
441
- # Now use the Rails insertion
442
- assert_nothing_raised { Person.create :wealth => BigDecimal.new("12345678901234567890.0123456789") }
443
-
444
- # SELECT
445
- row = Person.find(:first)
446
- assert_kind_of BigDecimal, row.wealth
447
-
448
- # If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken!
449
- unless current_adapter?(:SQLite3Adapter)
450
- assert_equal correct_value, row.wealth
451
- end
452
-
453
- # Reset to old state
454
- Person.connection.del_column "people", "wealth" rescue nil
455
- Person.reset_column_information
456
- end
457
-
458
- def test_add_column_with_precision_and_scale
459
- Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7
460
- Person.reset_column_information
461
-
462
- wealth_column = Person.columns_hash['wealth']
463
- assert_equal 9, wealth_column.precision
464
- assert_equal 7, wealth_column.scale
465
- end
466
-
467
- def test_native_types
468
- Person.delete_all
469
- Person.connection.add_column "people", "last_name", :string
470
- Person.connection.add_column "people", "bio", :text
471
- Person.connection.add_column "people", "age", :integer
472
- Person.connection.add_column "people", "height", :float
473
- Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
474
- Person.connection.add_column "people", "birthday", :datetime
475
- Person.connection.add_column "people", "favorite_day", :date
476
- Person.connection.add_column "people", "moment_of_truth", :datetime
477
- Person.connection.add_column "people", "male", :boolean
478
- Person.reset_column_information
479
-
480
- assert_nothing_raised do
481
- Person.create :first_name => 'bob', :last_name => 'bobsen',
482
- :bio => "I was born ....", :age => 18, :height => 1.78,
483
- :wealth => BigDecimal.new("12345678901234567890.0123456789"),
484
- :birthday => 18.years.ago, :favorite_day => 10.days.ago,
485
- :moment_of_truth => "1782-10-10 21:40:18", :male => true
486
- end
487
-
488
- bob = Person.find(:first)
489
- assert_equal 'bob', bob.first_name
490
- assert_equal 'bobsen', bob.last_name
491
- assert_equal "I was born ....", bob.bio
492
- assert_equal 18, bob.age
493
-
494
- # Test for 30 significent digits (beyond the 16 of float), 10 of them
495
- # after the decimal place.
496
-
497
- unless current_adapter?(:SQLite3Adapter)
498
- assert_equal BigDecimal.new("0012345678901234567890.0123456789"), bob.wealth
499
- end
500
-
501
- assert_equal true, bob.male?
502
-
503
- assert_equal String, bob.first_name.class
504
- assert_equal String, bob.last_name.class
505
- assert_equal String, bob.bio.class
506
- assert_equal Fixnum, bob.age.class
507
- assert_equal Time, bob.birthday.class
508
-
509
- if current_adapter?(:OracleAdapter, :SybaseAdapter)
510
- # Sybase, and Oracle don't differentiate between date/time
511
- assert_equal Time, bob.favorite_day.class
512
- else
513
- assert_equal Date, bob.favorite_day.class
514
- end
515
-
516
- # Test DateTime column and defaults, including timezone.
517
- # FIXME: moment of truth may be Time on 64-bit platforms.
518
- if bob.moment_of_truth.is_a?(DateTime)
519
-
520
- with_env_tz 'US/Eastern' do
521
- assert_equal DateTime.local_offset, bob.moment_of_truth.offset
522
- assert_not_equal 0, bob.moment_of_truth.offset
523
- assert_not_equal "Z", bob.moment_of_truth.zone
524
- # US/Eastern is -5 hours from GMT
525
- assert_equal Rational(-5, 24), bob.moment_of_truth.offset
526
- assert_match /\A-05:?00\Z/, bob.moment_of_truth.zone #ruby 1.8.6 uses HH:MM, prior versions use HHMM
527
- assert_equal DateTime::ITALY, bob.moment_of_truth.start
528
- end
529
- end
530
-
531
- assert_equal TrueClass, bob.male?.class
532
- assert_kind_of BigDecimal, bob.wealth
533
- end
534
-
535
- if current_adapter?(:MysqlAdapter)
536
- def test_unabstracted_database_dependent_types
537
- Person.delete_all
538
-
539
- ActiveRecord::Migration.add_column :people, :intelligence_quotient, :tinyint
540
- Person.reset_column_information
541
- assert_match /tinyint/, Person.columns_hash['intelligence_quotient'].sql_type
542
- ensure
543
- ActiveRecord::Migration.remove_column :people, :intelligence_quotient rescue nil
544
- end
545
- end
546
-
547
- def test_add_remove_single_field_using_string_arguments
548
- assert !Person.column_methods_hash.include?(:last_name)
549
-
550
- ActiveRecord::Migration.add_column 'people', 'last_name', :string
551
-
552
- Person.reset_column_information
553
- assert Person.column_methods_hash.include?(:last_name)
554
-
555
- ActiveRecord::Migration.remove_column 'people', 'last_name'
556
-
557
- Person.reset_column_information
558
- assert !Person.column_methods_hash.include?(:last_name)
559
- end
560
-
561
- def test_add_remove_single_field_using_symbol_arguments
562
- assert !Person.column_methods_hash.include?(:last_name)
563
-
564
- ActiveRecord::Migration.add_column :people, :last_name, :string
565
-
566
- Person.reset_column_information
567
- assert Person.column_methods_hash.include?(:last_name)
568
-
569
- ActiveRecord::Migration.remove_column :people, :last_name
570
-
571
- Person.reset_column_information
572
- assert !Person.column_methods_hash.include?(:last_name)
573
- end
574
-
575
- if current_adapter?(:MysqlAdapter)
576
- def testing_table_for_positioning
577
- Person.connection.create_table :testings, :id => false do |t|
578
- t.column :first, :integer
579
- t.column :second, :integer
580
- t.column :third, :integer
581
- end
582
-
583
- yield Person.connection
584
- ensure
585
- Person.connection.drop_table :testings rescue nil
586
- end
587
- protected :testing_table_for_positioning
588
-
589
- def test_column_positioning
590
- testing_table_for_positioning do |conn|
591
- assert_equal %w(first second third), conn.columns(:testings).map {|c| c.name }
592
- end
593
- end
594
-
595
- def test_add_column_with_positioning
596
- testing_table_for_positioning do |conn|
597
- conn.add_column :testings, :new_col, :integer
598
- assert_equal %w(first second third new_col), conn.columns(:testings).map {|c| c.name }
599
- end
600
- testing_table_for_positioning do |conn|
601
- conn.add_column :testings, :new_col, :integer, :first => true
602
- assert_equal %w(new_col first second third), conn.columns(:testings).map {|c| c.name }
603
- end
604
- testing_table_for_positioning do |conn|
605
- conn.add_column :testings, :new_col, :integer, :after => :first
606
- assert_equal %w(first new_col second third), conn.columns(:testings).map {|c| c.name }
607
- end
608
- end
609
-
610
- def test_change_column_with_positioning
611
- testing_table_for_positioning do |conn|
612
- conn.change_column :testings, :second, :integer, :first => true
613
- assert_equal %w(second first third), conn.columns(:testings).map {|c| c.name }
614
- end
615
- testing_table_for_positioning do |conn|
616
- conn.change_column :testings, :second, :integer, :after => :third
617
- assert_equal %w(first third second), conn.columns(:testings).map {|c| c.name }
618
- end
619
- end
620
- end
621
-
622
- def test_add_rename
623
- Person.delete_all
624
-
625
- begin
626
- Person.connection.add_column "people", "girlfriend", :string
627
- Person.reset_column_information
628
- Person.create :girlfriend => 'bobette'
629
-
630
- Person.connection.rename_column "people", "girlfriend", "exgirlfriend"
631
-
632
- Person.reset_column_information
633
- bob = Person.find(:first)
634
-
635
- assert_equal "bobette", bob.exgirlfriend
636
- ensure
637
- Person.connection.remove_column("people", "girlfriend") rescue nil
638
- Person.connection.remove_column("people", "exgirlfriend") rescue nil
639
- end
640
-
641
- end
642
-
643
- def test_rename_column_using_symbol_arguments
644
- begin
645
- names_before = Person.find(:all).map(&:first_name)
646
- Person.connection.rename_column :people, :first_name, :nick_name
647
- Person.reset_column_information
648
- assert Person.column_names.include?("nick_name")
649
- assert_equal names_before, Person.find(:all).map(&:nick_name)
650
- ensure
651
- Person.connection.remove_column("people","nick_name")
652
- Person.connection.add_column("people","first_name", :string)
653
- end
654
- end
655
-
656
- def test_rename_column
657
- begin
658
- names_before = Person.find(:all).map(&:first_name)
659
- Person.connection.rename_column "people", "first_name", "nick_name"
660
- Person.reset_column_information
661
- assert Person.column_names.include?("nick_name")
662
- assert_equal names_before, Person.find(:all).map(&:nick_name)
663
- ensure
664
- Person.connection.remove_column("people","nick_name")
665
- Person.connection.add_column("people","first_name", :string)
666
- end
667
- end
668
-
669
- def test_rename_column_preserves_default_value_not_null
670
- begin
671
- default_before = Developer.connection.columns("developers").find { |c| c.name == "salary" }.default
672
- assert_equal 70000, default_before
673
- Developer.connection.rename_column "developers", "salary", "anual_salary"
674
- Developer.reset_column_information
675
- assert Developer.column_names.include?("anual_salary")
676
- default_after = Developer.connection.columns("developers").find { |c| c.name == "anual_salary" }.default
677
- assert_equal 70000, default_after
678
- ensure
679
- Developer.connection.rename_column "developers", "anual_salary", "salary"
680
- Developer.reset_column_information
681
- end
682
- end
683
-
684
- def test_rename_nonexistent_column
685
- ActiveRecord::Base.connection.create_table(:hats) do |table|
686
- table.column :hat_name, :string, :default => nil
687
- end
688
- exception = if current_adapter?(:PostgreSQLAdapter)
689
- ActiveRecord::StatementInvalid
690
- else
691
- ActiveRecord::ActiveRecordError
692
- end
693
- assert_raise(exception) do
694
- Person.connection.rename_column "hats", "nonexistent", "should_fail"
695
- end
696
- ensure
697
- ActiveRecord::Base.connection.drop_table(:hats)
698
- end
699
-
700
- def test_rename_column_with_sql_reserved_word
701
- begin
702
- assert_nothing_raised { Person.connection.rename_column "people", "first_name", "group" }
703
- Person.reset_column_information
704
- assert Person.column_names.include?("group")
705
- ensure
706
- Person.connection.remove_column("people", "group") rescue nil
707
- Person.connection.add_column("people", "first_name", :string) rescue nil
708
- end
709
- end
710
-
711
- def test_rename_column_with_an_index
712
- ActiveRecord::Base.connection.create_table(:hats) do |table|
713
- table.column :hat_name, :string, :limit => 100
714
- table.column :hat_size, :integer
715
- end
716
- Person.connection.add_index :hats, :hat_name
717
- assert_nothing_raised do
718
- Person.connection.rename_column "hats", "hat_name", "name"
719
- end
720
- ensure
721
- ActiveRecord::Base.connection.drop_table(:hats)
722
- end
723
-
724
- def test_remove_column_with_index
725
- ActiveRecord::Base.connection.create_table(:hats) do |table|
726
- table.column :hat_name, :string, :limit => 100
727
- table.column :hat_size, :integer
728
- end
729
- ActiveRecord::Base.connection.add_index "hats", "hat_size"
730
-
731
- assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") }
732
- ensure
733
- ActiveRecord::Base.connection.drop_table(:hats)
734
- end
735
-
736
- def test_remove_column_with_multi_column_index
737
- ActiveRecord::Base.connection.create_table(:hats) do |table|
738
- table.column :hat_name, :string, :limit => 100
739
- table.column :hat_size, :integer
740
- table.column :hat_style, :string, :limit => 100
741
- end
742
- ActiveRecord::Base.connection.add_index "hats", ["hat_style", "hat_size"], :unique => true
743
-
744
- assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") }
745
- ensure
746
- ActiveRecord::Base.connection.drop_table(:hats)
747
- end
748
-
749
- def test_remove_column_no_second_parameter_raises_exception
750
- assert_raise(ArgumentError) { Person.connection.remove_column("funny") }
751
- end
752
-
753
- def test_change_type_of_not_null_column
754
- assert_nothing_raised do
755
- Topic.connection.change_column "topics", "written_on", :datetime, :null => false
756
- Topic.reset_column_information
757
-
758
- Topic.connection.change_column "topics", "written_on", :datetime, :null => false
759
- Topic.reset_column_information
760
- end
761
- end
762
-
763
- def test_rename_table
764
- begin
765
- ActiveRecord::Base.connection.create_table :octopuses do |t|
766
- t.column :url, :string
767
- end
768
- ActiveRecord::Base.connection.rename_table :octopuses, :octopi
769
-
770
- # Using explicit id in insert for compatibility across all databases
771
- con = ActiveRecord::Base.connection
772
- con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
773
- assert_nothing_raised { con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" }
774
- con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
775
-
776
- assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1")
777
-
778
- ensure
779
- ActiveRecord::Base.connection.drop_table :octopuses rescue nil
780
- ActiveRecord::Base.connection.drop_table :octopi rescue nil
781
- end
782
- end
783
-
784
- def test_change_column_nullability
785
- Person.delete_all
786
- Person.connection.add_column "people", "funny", :boolean
787
- Person.reset_column_information
788
- assert Person.columns_hash["funny"].null, "Column 'funny' must initially allow nulls"
789
- Person.connection.change_column "people", "funny", :boolean, :null => false, :default => true
790
- Person.reset_column_information
791
- assert !Person.columns_hash["funny"].null, "Column 'funny' must *not* allow nulls at this point"
792
- Person.connection.change_column "people", "funny", :boolean, :null => true
793
- Person.reset_column_information
794
- assert Person.columns_hash["funny"].null, "Column 'funny' must allow nulls again at this point"
795
- end
796
-
797
- def test_rename_table_with_an_index
798
- begin
799
- ActiveRecord::Base.connection.create_table :octopuses do |t|
800
- t.column :url, :string
801
- end
802
- ActiveRecord::Base.connection.add_index :octopuses, :url
803
-
804
- ActiveRecord::Base.connection.rename_table :octopuses, :octopi
805
-
806
- # Using explicit id in insert for compatibility across all databases
807
- con = ActiveRecord::Base.connection
808
- con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
809
- assert_nothing_raised { con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" }
810
- con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
811
-
812
- assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1")
813
- assert ActiveRecord::Base.connection.indexes(:octopi).first.columns.include?("url")
814
- ensure
815
- ActiveRecord::Base.connection.drop_table :octopuses rescue nil
816
- ActiveRecord::Base.connection.drop_table :octopi rescue nil
817
- end
818
- end
819
-
820
- def test_change_column
821
- Person.connection.add_column 'people', 'age', :integer
822
- old_columns = Person.connection.columns(Person.table_name, "#{name} Columns")
823
- assert old_columns.find { |c| c.name == 'age' and c.type == :integer }
824
-
825
- assert_nothing_raised { Person.connection.change_column "people", "age", :string }
826
-
827
- new_columns = Person.connection.columns(Person.table_name, "#{name} Columns")
828
- assert_nil new_columns.find { |c| c.name == 'age' and c.type == :integer }
829
- assert new_columns.find { |c| c.name == 'age' and c.type == :string }
830
-
831
- old_columns = Topic.connection.columns(Topic.table_name, "#{name} Columns")
832
- assert old_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
833
- assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => false }
834
- new_columns = Topic.connection.columns(Topic.table_name, "#{name} Columns")
835
- assert_nil new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
836
- assert new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == false }
837
- assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => true }
838
- end
839
-
840
- def test_change_column_with_nil_default
841
- Person.connection.add_column "people", "contributor", :boolean, :default => true
842
- Person.reset_column_information
843
- assert Person.new.contributor?
844
-
845
- assert_nothing_raised { Person.connection.change_column "people", "contributor", :boolean, :default => nil }
846
- Person.reset_column_information
847
- assert !Person.new.contributor?
848
- assert_nil Person.new.contributor
849
- ensure
850
- Person.connection.remove_column("people", "contributor") rescue nil
851
- end
852
-
853
- def test_change_column_with_new_default
854
- Person.connection.add_column "people", "administrator", :boolean, :default => true
855
- Person.reset_column_information
856
- assert Person.new.administrator?
857
-
858
- assert_nothing_raised { Person.connection.change_column "people", "administrator", :boolean, :default => false }
859
- Person.reset_column_information
860
- assert !Person.new.administrator?
861
- ensure
862
- Person.connection.remove_column("people", "administrator") rescue nil
863
- end
864
-
865
- def test_change_column_default
866
- Person.connection.change_column_default "people", "first_name", "Tester"
867
- Person.reset_column_information
868
- assert_equal "Tester", Person.new.first_name
869
- end
870
-
871
- def test_change_column_quotes_column_names
872
- Person.connection.create_table :testings do |t|
873
- t.column :select, :string
874
- end
875
-
876
- assert_nothing_raised { Person.connection.change_column :testings, :select, :string, :limit => 10 }
877
-
878
- assert_nothing_raised { Person.connection.execute "insert into testings (#{Person.connection.quote_column_name('select')}) values ('7 chars')" }
879
- ensure
880
- Person.connection.drop_table :testings rescue nil
881
- end
882
-
883
- def test_keeping_default_and_notnull_constaint_on_change
884
- Person.connection.create_table :testings do |t|
885
- t.column :title, :string
886
- end
887
- person_klass = Class.new(Person)
888
- person_klass.set_table_name 'testings'
889
-
890
- person_klass.connection.add_column "testings", "wealth", :integer, :null => false, :default => 99
891
- person_klass.reset_column_information
892
- assert_equal 99, person_klass.columns_hash["wealth"].default
893
- assert_equal false, person_klass.columns_hash["wealth"].null
894
- assert_nothing_raised {person_klass.connection.execute("insert into testings (title) values ('tester')")}
895
-
896
- # change column default to see that column doesn't lose its not null definition
897
- person_klass.connection.change_column_default "testings", "wealth", 100
898
- person_klass.reset_column_information
899
- assert_equal 100, person_klass.columns_hash["wealth"].default
900
- assert_equal false, person_klass.columns_hash["wealth"].null
901
-
902
- # rename column to see that column doesn't lose its not null and/or default definition
903
- person_klass.connection.rename_column "testings", "wealth", "money"
904
- person_klass.reset_column_information
905
- assert_nil person_klass.columns_hash["wealth"]
906
- assert_equal 100, person_klass.columns_hash["money"].default
907
- assert_equal false, person_klass.columns_hash["money"].null
908
-
909
- # change column
910
- person_klass.connection.change_column "testings", "money", :integer, :null => false, :default => 1000
911
- person_klass.reset_column_information
912
- assert_equal 1000, person_klass.columns_hash["money"].default
913
- assert_equal false, person_klass.columns_hash["money"].null
914
-
915
- # change column, make it nullable and clear default
916
- person_klass.connection.change_column "testings", "money", :integer, :null => true, :default => nil
917
- person_klass.reset_column_information
918
- assert_nil person_klass.columns_hash["money"].default
919
- assert_equal true, person_klass.columns_hash["money"].null
920
-
921
- # change_column_null, make it not nullable and set null values to a default value
922
- person_klass.connection.execute('UPDATE testings SET money = NULL')
923
- person_klass.connection.change_column_null "testings", "money", false, 2000
924
- person_klass.reset_column_information
925
- assert_nil person_klass.columns_hash["money"].default
926
- assert_equal false, person_klass.columns_hash["money"].null
927
- assert_equal [2000], Person.connection.select_values("SELECT money FROM testings").map { |s| s.to_i }.sort
928
- ensure
929
- Person.connection.drop_table :testings rescue nil
930
- end
931
-
932
- def test_change_column_default_to_null
933
- Person.connection.change_column_default "people", "first_name", nil
934
- Person.reset_column_information
935
- assert_nil Person.new.first_name
936
- end
937
-
938
- def test_add_table
939
- assert !Reminder.table_exists?
940
-
941
- WeNeedReminders.up
942
-
943
- assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
944
- assert_equal "hello world", Reminder.find(:first).content
945
-
946
- WeNeedReminders.down
947
- assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
948
- end
949
-
950
- def test_add_table_with_decimals
951
- Person.connection.drop_table :big_numbers rescue nil
952
-
953
- assert !BigNumber.table_exists?
954
- GiveMeBigNumbers.up
955
-
956
- assert BigNumber.create(
957
- :bank_balance => 1586.43,
958
- :big_bank_balance => BigDecimal("1000234000567.95"),
959
- :world_population => 6000000000,
960
- :my_house_population => 3,
961
- :value_of_e => BigDecimal("2.7182818284590452353602875")
962
- )
963
-
964
- b = BigNumber.find(:first)
965
- assert_not_nil b
966
-
967
- assert_not_nil b.bank_balance
968
- assert_not_nil b.big_bank_balance
969
- assert_not_nil b.world_population
970
- assert_not_nil b.my_house_population
971
- assert_not_nil b.value_of_e
972
-
973
- # TODO: set world_population >= 2**62 to cover 64-bit platforms and test
974
- # is_a?(Bignum)
975
- assert_kind_of Integer, b.world_population
976
- assert_equal 6000000000, b.world_population
977
- assert_kind_of Fixnum, b.my_house_population
978
- assert_equal 3, b.my_house_population
979
- assert_kind_of BigDecimal, b.bank_balance
980
- assert_equal BigDecimal("1586.43"), b.bank_balance
981
- assert_kind_of BigDecimal, b.big_bank_balance
982
- assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance
983
-
984
- # This one is fun. The 'value_of_e' field is defined as 'DECIMAL' with
985
- # precision/scale explicitly left out. By the SQL standard, numbers
986
- # assigned to this field should be truncated but that's seldom respected.
987
- if current_adapter?(:PostgreSQLAdapter, :SQLite2Adapter)
988
- # - PostgreSQL changes the SQL spec on columns declared simply as
989
- # "decimal" to something more useful: instead of being given a scale
990
- # of 0, they take on the compile-time limit for precision and scale,
991
- # so the following should succeed unless you have used really wacky
992
- # compilation options
993
- # - SQLite2 has the default behavior of preserving all data sent in,
994
- # so this happens there too
995
- assert_kind_of BigDecimal, b.value_of_e
996
- assert_equal BigDecimal("2.7182818284590452353602875"), b.value_of_e
997
- elsif current_adapter?(:SQLiteAdapter)
998
- # - SQLite3 stores a float, in violation of SQL
999
- assert_kind_of BigDecimal, b.value_of_e
1000
- assert_equal BigDecimal("2.71828182845905"), b.value_of_e
1001
- else
1002
- # - SQL standard is an integer
1003
- assert_kind_of Fixnum, b.value_of_e
1004
- assert_equal 2, b.value_of_e
1005
- end
1006
-
1007
- GiveMeBigNumbers.down
1008
- assert_raise(ActiveRecord::StatementInvalid) { BigNumber.find(:first) }
1009
- end
1010
-
1011
- def test_migrator
1012
- assert !Person.column_methods_hash.include?(:last_name)
1013
- assert !Reminder.table_exists?
1014
-
1015
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid")
1016
-
1017
- assert_equal 3, ActiveRecord::Migrator.current_version
1018
- Person.reset_column_information
1019
- assert Person.column_methods_hash.include?(:last_name)
1020
- assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1021
- assert_equal "hello world", Reminder.find(:first).content
1022
-
1023
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid")
1024
-
1025
- assert_equal 0, ActiveRecord::Migrator.current_version
1026
- Person.reset_column_information
1027
- assert !Person.column_methods_hash.include?(:last_name)
1028
- assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
1029
- end
1030
-
1031
- def test_migrator_one_up
1032
- assert !Person.column_methods_hash.include?(:last_name)
1033
- assert !Reminder.table_exists?
1034
-
1035
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1036
-
1037
- Person.reset_column_information
1038
- assert Person.column_methods_hash.include?(:last_name)
1039
- assert !Reminder.table_exists?
1040
-
1041
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 2)
1042
-
1043
- assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1044
- assert_equal "hello world", Reminder.find(:first).content
1045
- end
1046
-
1047
- def test_migrator_one_down
1048
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid")
1049
-
1050
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 1)
1051
-
1052
- Person.reset_column_information
1053
- assert Person.column_methods_hash.include?(:last_name)
1054
- assert !Reminder.table_exists?
1055
- end
1056
-
1057
- def test_migrator_one_up_one_down
1058
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1059
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
1060
-
1061
- assert !Person.column_methods_hash.include?(:last_name)
1062
- assert !Reminder.table_exists?
1063
- end
1064
-
1065
- def test_migrator_double_up
1066
- assert_equal(0, ActiveRecord::Migrator.current_version)
1067
- ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1)
1068
- assert_nothing_raised { ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1) }
1069
- assert_equal(1, ActiveRecord::Migrator.current_version)
1070
- end
1071
-
1072
- def test_migrator_double_down
1073
- assert_equal(0, ActiveRecord::Migrator.current_version)
1074
- ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1)
1075
- ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT + "/valid", 1)
1076
- assert_nothing_raised { ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT + "/valid", 1) }
1077
- assert_equal(0, ActiveRecord::Migrator.current_version)
1078
- end
1079
-
1080
- if ActiveRecord::Base.connection.supports_ddl_transactions?
1081
- def test_migrator_one_up_with_exception_and_rollback
1082
- assert !Person.column_methods_hash.include?(:last_name)
1083
-
1084
- e = assert_raise(StandardError) do
1085
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/broken", 100)
1086
- end
1087
-
1088
- assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message
1089
-
1090
- Person.reset_column_information
1091
- assert !Person.column_methods_hash.include?(:last_name)
1092
- end
1093
- end
1094
-
1095
- def test_finds_migrations
1096
- migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/valid").migrations
1097
-
1098
- [[1, 'PeopleHaveLastNames'], [2, 'WeNeedReminders'], [3, 'InnocentJointable']].each_with_index do |pair, i|
1099
- assert_equal migrations[i].version, pair.first
1100
- assert_equal migrations[i].name, pair.last
1101
- end
1102
- end
1103
-
1104
- def test_finds_pending_migrations
1105
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2", 1)
1106
- migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/interleaved/pass_2").pending_migrations
1107
-
1108
- assert_equal 1, migrations.size
1109
- assert_equal migrations[0].version, 3
1110
- assert_equal migrations[0].name, 'InnocentJointable'
1111
- end
1112
-
1113
- def test_only_loads_pending_migrations
1114
- # migrate up to 1
1115
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1116
-
1117
- # now unload the migrations that have been defined
1118
- PeopleHaveLastNames.unloadable
1119
- ActiveSupport::Dependencies.remove_unloadable_constants!
1120
-
1121
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", nil)
1122
-
1123
- assert !defined? PeopleHaveLastNames
1124
-
1125
- %w(WeNeedReminders, InnocentJointable).each do |migration|
1126
- assert defined? migration
1127
- end
1128
-
1129
- ensure
1130
- load(MIGRATIONS_ROOT + "/valid/1_people_have_last_names.rb")
1131
- end
1132
-
1133
- def test_target_version_zero_should_run_only_once
1134
- # migrate up to 1
1135
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1)
1136
-
1137
- # migrate down to 0
1138
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0)
1139
-
1140
- # now unload the migrations that have been defined
1141
- PeopleHaveLastNames.unloadable
1142
- ActiveSupport::Dependencies.remove_unloadable_constants!
1143
-
1144
- # migrate down to 0 again
1145
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0)
1146
-
1147
- assert !defined? PeopleHaveLastNames
1148
- ensure
1149
- load(MIGRATIONS_ROOT + "/valid/1_people_have_last_names.rb")
1150
- end
1151
-
1152
- def test_migrator_interleaved_migrations
1153
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_1")
1154
-
1155
- assert_nothing_raised do
1156
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2")
1157
- end
1158
-
1159
- Person.reset_column_information
1160
- assert Person.column_methods_hash.include?(:last_name)
1161
-
1162
- assert_nothing_raised do
1163
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/interleaved/pass_3")
1164
- end
1165
- end
1166
-
1167
- def test_migrator_db_has_no_schema_migrations_table
1168
- ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations;")
1169
- assert_nothing_raised do
1170
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1)
1171
- end
1172
- end
1173
-
1174
- def test_migrator_verbosity
1175
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1176
- assert PeopleHaveLastNames.message_count > 0
1177
- PeopleHaveLastNames.message_count = 0
1178
-
1179
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
1180
- assert PeopleHaveLastNames.message_count > 0
1181
- PeopleHaveLastNames.message_count = 0
1182
- end
1183
-
1184
- def test_migrator_verbosity_off
1185
- PeopleHaveLastNames.verbose = false
1186
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1187
- assert PeopleHaveLastNames.message_count.zero?
1188
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
1189
- assert PeopleHaveLastNames.message_count.zero?
1190
- end
1191
-
1192
- def test_migrator_going_down_due_to_version_target
1193
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1194
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0)
1195
-
1196
- assert !Person.column_methods_hash.include?(:last_name)
1197
- assert !Reminder.table_exists?
1198
-
1199
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
1200
-
1201
- Person.reset_column_information
1202
- assert Person.column_methods_hash.include?(:last_name)
1203
- assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1204
- assert_equal "hello world", Reminder.find(:first).content
1205
- end
1206
-
1207
- def test_migrator_rollback
1208
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
1209
- assert_equal(3, ActiveRecord::Migrator.current_version)
1210
-
1211
- ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1212
- assert_equal(2, ActiveRecord::Migrator.current_version)
1213
-
1214
- ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1215
- assert_equal(1, ActiveRecord::Migrator.current_version)
1216
-
1217
- ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1218
- assert_equal(0, ActiveRecord::Migrator.current_version)
1219
-
1220
- ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1221
- assert_equal(0, ActiveRecord::Migrator.current_version)
1222
- end
1223
-
1224
- def test_schema_migrations_table_name
1225
- ActiveRecord::Base.table_name_prefix = "prefix_"
1226
- ActiveRecord::Base.table_name_suffix = "_suffix"
1227
- Reminder.reset_table_name
1228
- assert_equal "prefix_schema_migrations_suffix", ActiveRecord::Migrator.schema_migrations_table_name
1229
- ActiveRecord::Base.table_name_prefix = ""
1230
- ActiveRecord::Base.table_name_suffix = ""
1231
- Reminder.reset_table_name
1232
- assert_equal "schema_migrations", ActiveRecord::Migrator.schema_migrations_table_name
1233
- ensure
1234
- ActiveRecord::Base.table_name_prefix = ""
1235
- ActiveRecord::Base.table_name_suffix = ""
1236
- end
1237
-
1238
- def test_proper_table_name
1239
- assert_equal "table", ActiveRecord::Migrator.proper_table_name('table')
1240
- assert_equal "table", ActiveRecord::Migrator.proper_table_name(:table)
1241
- assert_equal "reminders", ActiveRecord::Migrator.proper_table_name(Reminder)
1242
- Reminder.reset_table_name
1243
- assert_equal Reminder.table_name, ActiveRecord::Migrator.proper_table_name(Reminder)
1244
-
1245
- # Use the model's own prefix/suffix if a model is given
1246
- ActiveRecord::Base.table_name_prefix = "ARprefix_"
1247
- ActiveRecord::Base.table_name_suffix = "_ARsuffix"
1248
- Reminder.table_name_prefix = 'prefix_'
1249
- Reminder.table_name_suffix = '_suffix'
1250
- Reminder.reset_table_name
1251
- assert_equal "prefix_reminders_suffix", ActiveRecord::Migrator.proper_table_name(Reminder)
1252
- Reminder.table_name_prefix = ''
1253
- Reminder.table_name_suffix = ''
1254
- Reminder.reset_table_name
1255
-
1256
- # Use AR::Base's prefix/suffix if string or symbol is given
1257
- ActiveRecord::Base.table_name_prefix = "prefix_"
1258
- ActiveRecord::Base.table_name_suffix = "_suffix"
1259
- Reminder.reset_table_name
1260
- assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name('table')
1261
- assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name(:table)
1262
- ActiveRecord::Base.table_name_prefix = ""
1263
- ActiveRecord::Base.table_name_suffix = ""
1264
- Reminder.reset_table_name
1265
- end
1266
-
1267
- def test_add_drop_table_with_prefix_and_suffix
1268
- assert !Reminder.table_exists?
1269
- ActiveRecord::Base.table_name_prefix = 'prefix_'
1270
- ActiveRecord::Base.table_name_suffix = '_suffix'
1271
- Reminder.reset_table_name
1272
- Reminder.reset_sequence_name
1273
- WeNeedReminders.up
1274
- assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1275
- assert_equal "hello world", Reminder.find(:first).content
1276
-
1277
- WeNeedReminders.down
1278
- assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
1279
- ensure
1280
- ActiveRecord::Base.table_name_prefix = ''
1281
- ActiveRecord::Base.table_name_suffix = ''
1282
- Reminder.reset_table_name
1283
- Reminder.reset_sequence_name
1284
- end
1285
-
1286
- def test_create_table_with_binary_column
1287
- Person.connection.drop_table :binary_testings rescue nil
1288
-
1289
- assert_nothing_raised {
1290
- Person.connection.create_table :binary_testings do |t|
1291
- t.column "data", :binary, :null => false
1292
- end
1293
- }
1294
-
1295
- columns = Person.connection.columns(:binary_testings)
1296
- data_column = columns.detect { |c| c.name == "data" }
1297
-
1298
- if current_adapter?(:MysqlAdapter)
1299
- assert_equal '', data_column.default
1300
- else
1301
- assert_nil data_column.default
1302
- end
1303
-
1304
- Person.connection.drop_table :binary_testings rescue nil
1305
- end
1306
-
1307
- def test_migrator_with_duplicates
1308
- assert_raise(ActiveRecord::DuplicateMigrationVersionError) do
1309
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate", nil)
1310
- end
1311
- end
1312
-
1313
- def test_migrator_with_duplicate_names
1314
- assert_raise(ActiveRecord::DuplicateMigrationNameError, "Multiple migrations have the name Chunky") do
1315
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate_names", nil)
1316
- end
1317
- end
1318
-
1319
- def test_migrator_with_missing_version_numbers
1320
- assert_raise(ActiveRecord::UnknownMigrationVersionError) do
1321
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/missing", 500)
1322
- end
1323
- end
1324
-
1325
- def test_create_table_with_custom_sequence_name
1326
- return unless current_adapter? :OracleAdapter
1327
-
1328
- # table name is 29 chars, the standard sequence name will
1329
- # be 33 chars and fail
1330
- assert_raise(ActiveRecord::StatementInvalid) do
1331
- begin
1332
- Person.connection.create_table :table_with_name_thats_just_ok do |t|
1333
- t.column :foo, :string, :null => false
1334
- end
1335
- ensure
1336
- Person.connection.drop_table :table_with_name_thats_just_ok rescue nil
1337
- end
1338
- end
1339
-
1340
- # should be all good w/ a custom sequence name
1341
- assert_nothing_raised do
1342
- begin
1343
- Person.connection.create_table :table_with_name_thats_just_ok,
1344
- :sequence_name => 'suitably_short_seq' do |t|
1345
- t.column :foo, :string, :null => false
1346
- end
1347
-
1348
- Person.connection.execute("select suitably_short_seq.nextval from dual")
1349
-
1350
- ensure
1351
- Person.connection.drop_table :table_with_name_thats_just_ok,
1352
- :sequence_name => 'suitably_short_seq' rescue nil
1353
- end
1354
- end
1355
-
1356
- # confirm the custom sequence got dropped
1357
- assert_raise(ActiveRecord::StatementInvalid) do
1358
- Person.connection.execute("select suitably_short_seq.nextval from dual")
1359
- end
1360
- end
1361
-
1362
- protected
1363
- def with_env_tz(new_tz = 'US/Eastern')
1364
- old_tz, ENV['TZ'] = ENV['TZ'], new_tz
1365
- yield
1366
- ensure
1367
- old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
1368
- end
1369
-
1370
- end
1371
-
1372
- class SexyMigrationsTest < ActiveRecord::TestCase
1373
- def test_references_column_type_adds_id
1374
- with_new_table do |t|
1375
- t.expects(:column).with('customer_id', :integer, {})
1376
- t.references :customer
1377
- end
1378
- end
1379
-
1380
- def test_references_column_type_with_polymorphic_adds_type
1381
- with_new_table do |t|
1382
- t.expects(:column).with('taggable_type', :string, {})
1383
- t.expects(:column).with('taggable_id', :integer, {})
1384
- t.references :taggable, :polymorphic => true
1385
- end
1386
- end
1387
-
1388
- def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag
1389
- with_new_table do |t|
1390
- t.expects(:column).with('taggable_type', :string, {:null => false})
1391
- t.expects(:column).with('taggable_id', :integer, {:null => false})
1392
- t.references :taggable, :polymorphic => true, :null => false
1393
- end
1394
- end
1395
-
1396
- def test_belongs_to_works_like_references
1397
- with_new_table do |t|
1398
- t.expects(:column).with('customer_id', :integer, {})
1399
- t.belongs_to :customer
1400
- end
1401
- end
1402
-
1403
- def test_timestamps_creates_updated_at_and_created_at
1404
- with_new_table do |t|
1405
- t.expects(:column).with(:created_at, :datetime, kind_of(Hash))
1406
- t.expects(:column).with(:updated_at, :datetime, kind_of(Hash))
1407
- t.timestamps
1408
- end
1409
- end
1410
-
1411
- def test_integer_creates_integer_column
1412
- with_new_table do |t|
1413
- t.expects(:column).with(:foo, 'integer', {})
1414
- t.expects(:column).with(:bar, 'integer', {})
1415
- t.integer :foo, :bar
1416
- end
1417
- end
1418
-
1419
- def test_string_creates_string_column
1420
- with_new_table do |t|
1421
- t.expects(:column).with(:foo, 'string', {})
1422
- t.expects(:column).with(:bar, 'string', {})
1423
- t.string :foo, :bar
1424
- end
1425
- end
1426
-
1427
- if current_adapter?(:PostgreSQLAdapter)
1428
- def test_xml_creates_xml_column
1429
- with_new_table do |t|
1430
- t.expects(:column).with(:data, 'xml', {})
1431
- t.xml :data
1432
- end
1433
- end
1434
- end
1435
-
1436
- protected
1437
- def with_new_table
1438
- Person.connection.create_table :delete_me, :force => true do |t|
1439
- yield t
1440
- end
1441
- ensure
1442
- Person.connection.drop_table :delete_me rescue nil
1443
- end
1444
-
1445
- end # SexyMigrationsTest
1446
-
1447
- class ChangeTableMigrationsTest < ActiveRecord::TestCase
1448
- def setup
1449
- @connection = Person.connection
1450
- @connection.create_table :delete_me, :force => true do |t|
1451
- end
1452
- end
1453
-
1454
- def teardown
1455
- Person.connection.drop_table :delete_me rescue nil
1456
- end
1457
-
1458
- def test_references_column_type_adds_id
1459
- with_change_table do |t|
1460
- @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {})
1461
- t.references :customer
1462
- end
1463
- end
1464
-
1465
- def test_remove_references_column_type_removes_id
1466
- with_change_table do |t|
1467
- @connection.expects(:remove_column).with(:delete_me, 'customer_id')
1468
- t.remove_references :customer
1469
- end
1470
- end
1471
-
1472
- def test_add_belongs_to_works_like_add_references
1473
- with_change_table do |t|
1474
- @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {})
1475
- t.belongs_to :customer
1476
- end
1477
- end
1478
-
1479
- def test_remove_belongs_to_works_like_remove_references
1480
- with_change_table do |t|
1481
- @connection.expects(:remove_column).with(:delete_me, 'customer_id')
1482
- t.remove_belongs_to :customer
1483
- end
1484
- end
1485
-
1486
- def test_references_column_type_with_polymorphic_adds_type
1487
- with_change_table do |t|
1488
- @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {})
1489
- @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {})
1490
- t.references :taggable, :polymorphic => true
1491
- end
1492
- end
1493
-
1494
- def test_remove_references_column_type_with_polymorphic_removes_type
1495
- with_change_table do |t|
1496
- @connection.expects(:remove_column).with(:delete_me, 'taggable_type')
1497
- @connection.expects(:remove_column).with(:delete_me, 'taggable_id')
1498
- t.remove_references :taggable, :polymorphic => true
1499
- end
1500
- end
1501
-
1502
- def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag
1503
- with_change_table do |t|
1504
- @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {:null => false})
1505
- @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {:null => false})
1506
- t.references :taggable, :polymorphic => true, :null => false
1507
- end
1508
- end
1509
-
1510
- def test_remove_references_column_type_with_polymorphic_and_options_null_is_false_removes_table_flag
1511
- with_change_table do |t|
1512
- @connection.expects(:remove_column).with(:delete_me, 'taggable_type')
1513
- @connection.expects(:remove_column).with(:delete_me, 'taggable_id')
1514
- t.remove_references :taggable, :polymorphic => true, :null => false
1515
- end
1516
- end
1517
-
1518
- def test_timestamps_creates_updated_at_and_created_at
1519
- with_change_table do |t|
1520
- @connection.expects(:add_timestamps).with(:delete_me)
1521
- t.timestamps
1522
- end
1523
- end
1524
-
1525
- def test_remove_timestamps_creates_updated_at_and_created_at
1526
- with_change_table do |t|
1527
- @connection.expects(:remove_timestamps).with(:delete_me)
1528
- t.remove_timestamps
1529
- end
1530
- end
1531
-
1532
- def string_column
1533
- if current_adapter?(:PostgreSQLAdapter)
1534
- "character varying(255)"
1535
- else
1536
- 'varchar(255)'
1537
- end
1538
- end
1539
-
1540
- def integer_column
1541
- if current_adapter?(:MysqlAdapter)
1542
- 'int(11)'
1543
- else
1544
- 'integer'
1545
- end
1546
- end
1547
-
1548
- def test_integer_creates_integer_column
1549
- with_change_table do |t|
1550
- @connection.expects(:add_column).with(:delete_me, :foo, integer_column, {})
1551
- @connection.expects(:add_column).with(:delete_me, :bar, integer_column, {})
1552
- t.integer :foo, :bar
1553
- end
1554
- end
1555
-
1556
- def test_string_creates_string_column
1557
- with_change_table do |t|
1558
- @connection.expects(:add_column).with(:delete_me, :foo, string_column, {})
1559
- @connection.expects(:add_column).with(:delete_me, :bar, string_column, {})
1560
- t.string :foo, :bar
1561
- end
1562
- end
1563
-
1564
- def test_column_creates_column
1565
- with_change_table do |t|
1566
- @connection.expects(:add_column).with(:delete_me, :bar, :integer, {})
1567
- t.column :bar, :integer
1568
- end
1569
- end
1570
-
1571
- def test_column_creates_column_with_options
1572
- with_change_table do |t|
1573
- @connection.expects(:add_column).with(:delete_me, :bar, :integer, {:null => false})
1574
- t.column :bar, :integer, :null => false
1575
- end
1576
- end
1577
-
1578
- def test_index_creates_index
1579
- with_change_table do |t|
1580
- @connection.expects(:add_index).with(:delete_me, :bar, {})
1581
- t.index :bar
1582
- end
1583
- end
1584
-
1585
- def test_index_creates_index_with_options
1586
- with_change_table do |t|
1587
- @connection.expects(:add_index).with(:delete_me, :bar, {:unique => true})
1588
- t.index :bar, :unique => true
1589
- end
1590
- end
1591
-
1592
- def test_change_changes_column
1593
- with_change_table do |t|
1594
- @connection.expects(:change_column).with(:delete_me, :bar, :string, {})
1595
- t.change :bar, :string
1596
- end
1597
- end
1598
-
1599
- def test_change_changes_column_with_options
1600
- with_change_table do |t|
1601
- @connection.expects(:change_column).with(:delete_me, :bar, :string, {:null => true})
1602
- t.change :bar, :string, :null => true
1603
- end
1604
- end
1605
-
1606
- def test_change_default_changes_column
1607
- with_change_table do |t|
1608
- @connection.expects(:change_column_default).with(:delete_me, :bar, :string)
1609
- t.change_default :bar, :string
1610
- end
1611
- end
1612
-
1613
- def test_remove_drops_single_column
1614
- with_change_table do |t|
1615
- @connection.expects(:remove_column).with(:delete_me, [:bar])
1616
- t.remove :bar
1617
- end
1618
- end
1619
-
1620
- def test_remove_drops_multiple_columns
1621
- with_change_table do |t|
1622
- @connection.expects(:remove_column).with(:delete_me, [:bar, :baz])
1623
- t.remove :bar, :baz
1624
- end
1625
- end
1626
-
1627
- def test_remove_index_removes_index_with_options
1628
- with_change_table do |t|
1629
- @connection.expects(:remove_index).with(:delete_me, {:unique => true})
1630
- t.remove_index :unique => true
1631
- end
1632
- end
1633
-
1634
- def test_rename_renames_column
1635
- with_change_table do |t|
1636
- @connection.expects(:rename_column).with(:delete_me, :bar, :baz)
1637
- t.rename :bar, :baz
1638
- end
1639
- end
1640
-
1641
- protected
1642
- def with_change_table
1643
- Person.connection.change_table :delete_me do |t|
1644
- yield t
1645
- end
1646
- end
1647
- end
1648
- end
1649
-