activerecord 2.0.5 → 2.1.0

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 (289) hide show
  1. data/CHANGELOG +168 -6
  2. data/README +27 -22
  3. data/RUNNING_UNIT_TESTS +7 -4
  4. data/Rakefile +22 -25
  5. data/lib/active_record.rb +8 -2
  6. data/lib/active_record/aggregations.rb +21 -12
  7. data/lib/active_record/association_preload.rb +277 -0
  8. data/lib/active_record/associations.rb +481 -295
  9. data/lib/active_record/associations/association_collection.rb +162 -37
  10. data/lib/active_record/associations/association_proxy.rb +71 -7
  11. data/lib/active_record/associations/belongs_to_association.rb +5 -3
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +5 -6
  13. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +12 -64
  14. data/lib/active_record/associations/has_many_association.rb +8 -73
  15. data/lib/active_record/associations/has_many_through_association.rb +68 -117
  16. data/lib/active_record/associations/has_one_association.rb +7 -5
  17. data/lib/active_record/associations/has_one_through_association.rb +28 -0
  18. data/lib/active_record/attribute_methods.rb +69 -19
  19. data/lib/active_record/base.rb +496 -275
  20. data/lib/active_record/calculations.rb +28 -21
  21. data/lib/active_record/callbacks.rb +9 -38
  22. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +3 -2
  23. data/lib/active_record/connection_adapters/abstract/database_statements.rb +2 -2
  24. data/lib/active_record/connection_adapters/abstract/query_cache.rb +6 -0
  25. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +232 -45
  26. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +141 -27
  27. data/lib/active_record/connection_adapters/abstract_adapter.rb +9 -13
  28. data/lib/active_record/connection_adapters/mysql_adapter.rb +57 -24
  29. data/lib/active_record/connection_adapters/postgresql_adapter.rb +143 -42
  30. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -1
  31. data/lib/active_record/connection_adapters/sqlite_adapter.rb +18 -10
  32. data/lib/active_record/dirty.rb +158 -0
  33. data/lib/active_record/fixtures.rb +121 -156
  34. data/lib/active_record/locking/optimistic.rb +14 -11
  35. data/lib/active_record/locking/pessimistic.rb +2 -2
  36. data/lib/active_record/migration.rb +157 -77
  37. data/lib/active_record/named_scope.rb +163 -0
  38. data/lib/active_record/observer.rb +19 -5
  39. data/lib/active_record/reflection.rb +34 -14
  40. data/lib/active_record/schema.rb +7 -14
  41. data/lib/active_record/schema_dumper.rb +4 -4
  42. data/lib/active_record/serialization.rb +5 -5
  43. data/lib/active_record/serializers/json_serializer.rb +37 -28
  44. data/lib/active_record/serializers/xml_serializer.rb +52 -29
  45. data/lib/active_record/test_case.rb +36 -0
  46. data/lib/active_record/timestamp.rb +4 -4
  47. data/lib/active_record/transactions.rb +3 -3
  48. data/lib/active_record/validations.rb +182 -248
  49. data/lib/active_record/version.rb +2 -2
  50. data/test/{fixtures → assets}/example.log +0 -0
  51. data/test/{fixtures → assets}/flowers.jpg +0 -0
  52. data/test/cases/aaa_create_tables_test.rb +24 -0
  53. data/test/cases/active_schema_test_mysql.rb +95 -0
  54. data/test/cases/active_schema_test_postgresql.rb +24 -0
  55. data/test/{adapter_test.rb → cases/adapter_test.rb} +15 -14
  56. data/test/{adapter_test_sqlserver.rb → cases/adapter_test_sqlserver.rb} +95 -95
  57. data/test/{aggregations_test.rb → cases/aggregations_test.rb} +20 -20
  58. data/test/{ar_schema_test.rb → cases/ar_schema_test.rb} +6 -6
  59. data/test/cases/associations/belongs_to_associations_test.rb +412 -0
  60. data/test/{associations → cases/associations}/callbacks_test.rb +24 -10
  61. data/test/{associations → cases/associations}/cascaded_eager_loading_test.rb +18 -17
  62. data/test/cases/associations/eager_load_nested_include_test.rb +83 -0
  63. data/test/{associations → cases/associations}/eager_singularization_test.rb +5 -5
  64. data/test/{associations → cases/associations}/eager_test.rb +216 -51
  65. data/test/{associations → cases/associations}/extension_test.rb +8 -8
  66. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +684 -0
  67. data/test/cases/associations/has_many_associations_test.rb +932 -0
  68. data/test/cases/associations/has_many_through_associations_test.rb +190 -0
  69. data/test/cases/associations/has_one_associations_test.rb +323 -0
  70. data/test/cases/associations/has_one_through_associations_test.rb +74 -0
  71. data/test/{associations → cases/associations}/inner_join_association_test.rb +20 -20
  72. data/test/{associations → cases/associations}/join_model_test.rb +175 -35
  73. data/test/cases/associations_test.rb +262 -0
  74. data/test/{attribute_methods_test.rb → cases/attribute_methods_test.rb} +103 -11
  75. data/test/{base_test.rb → cases/base_test.rb} +338 -191
  76. data/test/{binary_test.rb → cases/binary_test.rb} +6 -4
  77. data/test/{calculations_test.rb → cases/calculations_test.rb} +35 -23
  78. data/test/{callbacks_test.rb → cases/callbacks_test.rb} +7 -7
  79. data/test/{class_inheritable_attributes_test.rb → cases/class_inheritable_attributes_test.rb} +3 -3
  80. data/test/{column_alias_test.rb → cases/column_alias_test.rb} +3 -3
  81. data/test/{connection_test_firebird.rb → cases/connection_test_firebird.rb} +2 -2
  82. data/test/{connection_test_mysql.rb → cases/connection_test_mysql.rb} +2 -2
  83. data/test/{copy_table_test_sqlite.rb → cases/copy_table_test_sqlite.rb} +13 -13
  84. data/test/{datatype_test_postgresql.rb → cases/datatype_test_postgresql.rb} +8 -8
  85. data/test/{date_time_test.rb → cases/date_time_test.rb} +5 -5
  86. data/test/{default_test_firebird.rb → cases/default_test_firebird.rb} +3 -3
  87. data/test/{defaults_test.rb → cases/defaults_test.rb} +8 -6
  88. data/test/{deprecated_finder_test.rb → cases/deprecated_finder_test.rb} +3 -3
  89. data/test/cases/dirty_test.rb +163 -0
  90. data/test/cases/finder_respond_to_test.rb +76 -0
  91. data/test/{finder_test.rb → cases/finder_test.rb} +266 -33
  92. data/test/{fixtures_test.rb → cases/fixtures_test.rb} +88 -72
  93. data/test/cases/helper.rb +47 -0
  94. data/test/{inheritance_test.rb → cases/inheritance_test.rb} +61 -17
  95. data/test/cases/invalid_date_test.rb +24 -0
  96. data/test/{json_serialization_test.rb → cases/json_serialization_test.rb} +36 -11
  97. data/test/{lifecycle_test.rb → cases/lifecycle_test.rb} +16 -13
  98. data/test/{locking_test.rb → cases/locking_test.rb} +17 -10
  99. data/test/{method_scoping_test.rb → cases/method_scoping_test.rb} +75 -39
  100. data/test/{migration_test.rb → cases/migration_test.rb} +420 -80
  101. data/test/{migration_test_firebird.rb → cases/migration_test_firebird.rb} +3 -3
  102. data/test/{mixin_test.rb → cases/mixin_test.rb} +7 -6
  103. data/test/{modules_test.rb → cases/modules_test.rb} +11 -6
  104. data/test/{multiple_db_test.rb → cases/multiple_db_test.rb} +5 -5
  105. data/test/cases/named_scope_test.rb +157 -0
  106. data/test/{pk_test.rb → cases/pk_test.rb} +10 -10
  107. data/test/{query_cache_test.rb → cases/query_cache_test.rb} +12 -10
  108. data/test/{readonly_test.rb → cases/readonly_test.rb} +11 -11
  109. data/test/{reflection_test.rb → cases/reflection_test.rb} +15 -14
  110. data/test/{reserved_word_test_mysql.rb → cases/reserved_word_test_mysql.rb} +4 -5
  111. data/test/{schema_authorization_test_postgresql.rb → cases/schema_authorization_test_postgresql.rb} +5 -5
  112. data/test/cases/schema_dumper_test.rb +138 -0
  113. data/test/cases/schema_test_postgresql.rb +102 -0
  114. data/test/{serialization_test.rb → cases/serialization_test.rb} +7 -7
  115. data/test/{synonym_test_oracle.rb → cases/synonym_test_oracle.rb} +5 -5
  116. data/test/{table_name_test_sqlserver.rb → cases/table_name_test_sqlserver.rb} +3 -3
  117. data/test/{threaded_connections_test.rb → cases/threaded_connections_test.rb} +7 -7
  118. data/test/{transactions_test.rb → cases/transactions_test.rb} +31 -5
  119. data/test/{unconnected_test.rb → cases/unconnected_test.rb} +2 -2
  120. data/test/{validations_test.rb → cases/validations_test.rb} +141 -39
  121. data/test/{xml_serialization_test.rb → cases/xml_serialization_test.rb} +12 -12
  122. data/test/config.rb +5 -0
  123. data/test/connections/native_db2/connection.rb +1 -1
  124. data/test/connections/native_firebird/connection.rb +1 -1
  125. data/test/connections/native_frontbase/connection.rb +1 -1
  126. data/test/connections/native_mysql/connection.rb +1 -1
  127. data/test/connections/native_openbase/connection.rb +1 -1
  128. data/test/connections/native_oracle/connection.rb +1 -1
  129. data/test/connections/native_postgresql/connection.rb +1 -3
  130. data/test/connections/native_sqlite/connection.rb +2 -2
  131. data/test/connections/native_sqlite3/connection.rb +2 -2
  132. data/test/connections/native_sqlite3/in_memory_connection.rb +3 -3
  133. data/test/connections/native_sybase/connection.rb +1 -1
  134. data/test/fixtures/author_addresses.yml +5 -0
  135. data/test/fixtures/authors.yml +2 -0
  136. data/test/fixtures/clubs.yml +6 -0
  137. data/test/fixtures/jobs.yml +7 -0
  138. data/test/fixtures/members.yml +4 -0
  139. data/test/fixtures/memberships.yml +20 -0
  140. data/test/fixtures/owners.yml +7 -0
  141. data/test/fixtures/people.yml +4 -1
  142. data/test/fixtures/pets.yml +14 -0
  143. data/test/fixtures/posts.yml +1 -0
  144. data/test/fixtures/price_estimates.yml +7 -0
  145. data/test/fixtures/readers.yml +5 -0
  146. data/test/fixtures/references.yml +17 -0
  147. data/test/fixtures/sponsors.yml +9 -0
  148. data/test/fixtures/subscribers.yml +7 -0
  149. data/test/fixtures/subscriptions.yml +12 -0
  150. data/test/fixtures/taggings.yml +4 -1
  151. data/test/fixtures/topics.yml +22 -2
  152. data/test/fixtures/warehouse-things.yml +3 -0
  153. data/test/{fixtures/migrations_with_decimal → migrations/decimal}/1_give_me_big_numbers.rb +0 -0
  154. data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/1_people_have_last_names.rb +1 -1
  155. data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/2_we_need_reminders.rb +1 -1
  156. data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/3_foo.rb +0 -0
  157. data/test/{fixtures/migrations → migrations/duplicate}/3_innocent_jointable.rb +0 -0
  158. data/test/migrations/duplicate_names/20080507052938_chunky.rb +7 -0
  159. data/test/migrations/duplicate_names/20080507053028_chunky.rb +7 -0
  160. data/test/{fixtures/migrations_with_duplicate → migrations/interleaved/pass_1}/3_innocent_jointable.rb +0 -0
  161. data/test/{fixtures/migrations → migrations/interleaved/pass_2}/1_people_have_last_names.rb +1 -1
  162. data/test/{fixtures/migrations_with_missing_versions/4_innocent_jointable.rb → migrations/interleaved/pass_2/3_innocent_jointable.rb} +0 -0
  163. data/test/{fixtures/migrations_with_missing_versions → migrations/interleaved/pass_3}/1_people_have_last_names.rb +1 -1
  164. data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +8 -0
  165. data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +12 -0
  166. data/test/{fixtures/migrations_with_missing_versions → migrations/missing}/1000_people_have_middle_names.rb +1 -1
  167. data/test/migrations/missing/1_people_have_last_names.rb +9 -0
  168. data/test/{fixtures/migrations_with_missing_versions → migrations/missing}/3_we_need_reminders.rb +1 -1
  169. data/test/migrations/missing/4_innocent_jointable.rb +12 -0
  170. data/test/migrations/valid/1_people_have_last_names.rb +9 -0
  171. data/test/{fixtures/migrations → migrations/valid}/2_we_need_reminders.rb +1 -1
  172. data/test/migrations/valid/3_innocent_jointable.rb +12 -0
  173. data/test/{fixtures → models}/author.rb +28 -4
  174. data/test/{fixtures → models}/auto_id.rb +0 -0
  175. data/test/{fixtures → models}/binary.rb +0 -0
  176. data/test/{fixtures → models}/book.rb +0 -0
  177. data/test/{fixtures → models}/categorization.rb +0 -0
  178. data/test/{fixtures → models}/category.rb +8 -5
  179. data/test/{fixtures → models}/citation.rb +0 -0
  180. data/test/models/club.rb +7 -0
  181. data/test/{fixtures → models}/column_name.rb +0 -0
  182. data/test/{fixtures → models}/comment.rb +5 -3
  183. data/test/{fixtures → models}/company.rb +15 -6
  184. data/test/{fixtures → models}/company_in_module.rb +5 -3
  185. data/test/{fixtures → models}/computer.rb +0 -1
  186. data/test/{fixtures → models}/contact.rb +1 -1
  187. data/test/{fixtures → models}/course.rb +0 -0
  188. data/test/{fixtures → models}/customer.rb +8 -8
  189. data/test/{fixtures → models}/default.rb +0 -0
  190. data/test/{fixtures → models}/developer.rb +14 -10
  191. data/test/{fixtures → models}/edge.rb +0 -0
  192. data/test/{fixtures → models}/entrant.rb +0 -0
  193. data/test/models/guid.rb +2 -0
  194. data/test/{fixtures → models}/item.rb +0 -0
  195. data/test/models/job.rb +5 -0
  196. data/test/{fixtures → models}/joke.rb +0 -0
  197. data/test/{fixtures → models}/keyboard.rb +0 -0
  198. data/test/{fixtures → models}/legacy_thing.rb +0 -0
  199. data/test/{fixtures → models}/matey.rb +0 -0
  200. data/test/models/member.rb +9 -0
  201. data/test/models/membership.rb +9 -0
  202. data/test/{fixtures → models}/minimalistic.rb +0 -0
  203. data/test/{fixtures → models}/mixed_case_monkey.rb +0 -0
  204. data/test/{fixtures → models}/movie.rb +0 -0
  205. data/test/{fixtures → models}/order.rb +2 -2
  206. data/test/models/owner.rb +4 -0
  207. data/test/{fixtures → models}/parrot.rb +0 -0
  208. data/test/models/person.rb +10 -0
  209. data/test/models/pet.rb +4 -0
  210. data/test/models/pirate.rb +9 -0
  211. data/test/{fixtures → models}/post.rb +23 -2
  212. data/test/models/price_estimate.rb +3 -0
  213. data/test/{fixtures → models}/project.rb +1 -0
  214. data/test/{fixtures → models}/reader.rb +0 -0
  215. data/test/models/reference.rb +4 -0
  216. data/test/{fixtures → models}/reply.rb +7 -5
  217. data/test/{fixtures → models}/ship.rb +0 -0
  218. data/test/models/sponsor.rb +4 -0
  219. data/test/{fixtures → models}/subject.rb +0 -0
  220. data/test/{fixtures → models}/subscriber.rb +2 -0
  221. data/test/models/subscription.rb +4 -0
  222. data/test/{fixtures → models}/tag.rb +0 -0
  223. data/test/{fixtures → models}/tagging.rb +0 -0
  224. data/test/{fixtures → models}/task.rb +0 -0
  225. data/test/{fixtures → models}/topic.rb +32 -4
  226. data/test/{fixtures → models}/treasure.rb +2 -0
  227. data/test/{fixtures → models}/vertex.rb +0 -0
  228. data/test/models/warehouse_thing.rb +5 -0
  229. data/test/schema/mysql_specific_schema.rb +12 -0
  230. data/test/schema/postgresql_specific_schema.rb +103 -0
  231. data/test/schema/schema.rb +421 -0
  232. data/test/schema/schema2.rb +6 -0
  233. data/test/schema/sqlite_specific_schema.rb +25 -0
  234. data/test/schema/sqlserver_specific_schema.rb +5 -0
  235. metadata +192 -176
  236. data/test/aaa_create_tables_test.rb +0 -72
  237. data/test/abstract_unit.rb +0 -84
  238. data/test/active_schema_test_mysql.rb +0 -46
  239. data/test/all.sh +0 -8
  240. data/test/association_inheritance_reload.rb +0 -14
  241. data/test/associations_test.rb +0 -2177
  242. data/test/fixtures/bad_fixtures/attr_with_numeric_first_char +0 -1
  243. data/test/fixtures/bad_fixtures/attr_with_spaces +0 -1
  244. data/test/fixtures/bad_fixtures/blank_line +0 -3
  245. data/test/fixtures/bad_fixtures/duplicate_attributes +0 -3
  246. data/test/fixtures/bad_fixtures/missing_value +0 -1
  247. data/test/fixtures/db_definitions/db2.drop.sql +0 -33
  248. data/test/fixtures/db_definitions/db2.sql +0 -235
  249. data/test/fixtures/db_definitions/db22.drop.sql +0 -2
  250. data/test/fixtures/db_definitions/db22.sql +0 -5
  251. data/test/fixtures/db_definitions/firebird.drop.sql +0 -65
  252. data/test/fixtures/db_definitions/firebird.sql +0 -310
  253. data/test/fixtures/db_definitions/firebird2.drop.sql +0 -2
  254. data/test/fixtures/db_definitions/firebird2.sql +0 -6
  255. data/test/fixtures/db_definitions/frontbase.drop.sql +0 -33
  256. data/test/fixtures/db_definitions/frontbase.sql +0 -273
  257. data/test/fixtures/db_definitions/frontbase2.drop.sql +0 -1
  258. data/test/fixtures/db_definitions/frontbase2.sql +0 -4
  259. data/test/fixtures/db_definitions/openbase.drop.sql +0 -2
  260. data/test/fixtures/db_definitions/openbase.sql +0 -318
  261. data/test/fixtures/db_definitions/openbase2.drop.sql +0 -2
  262. data/test/fixtures/db_definitions/openbase2.sql +0 -7
  263. data/test/fixtures/db_definitions/oracle.drop.sql +0 -67
  264. data/test/fixtures/db_definitions/oracle.sql +0 -330
  265. data/test/fixtures/db_definitions/oracle2.drop.sql +0 -2
  266. data/test/fixtures/db_definitions/oracle2.sql +0 -6
  267. data/test/fixtures/db_definitions/postgresql.drop.sql +0 -44
  268. data/test/fixtures/db_definitions/postgresql.sql +0 -292
  269. data/test/fixtures/db_definitions/postgresql2.drop.sql +0 -2
  270. data/test/fixtures/db_definitions/postgresql2.sql +0 -4
  271. data/test/fixtures/db_definitions/schema.rb +0 -354
  272. data/test/fixtures/db_definitions/schema2.rb +0 -11
  273. data/test/fixtures/db_definitions/sqlite.drop.sql +0 -33
  274. data/test/fixtures/db_definitions/sqlite.sql +0 -219
  275. data/test/fixtures/db_definitions/sqlite2.drop.sql +0 -2
  276. data/test/fixtures/db_definitions/sqlite2.sql +0 -5
  277. data/test/fixtures/db_definitions/sybase.drop.sql +0 -35
  278. data/test/fixtures/db_definitions/sybase.sql +0 -222
  279. data/test/fixtures/db_definitions/sybase2.drop.sql +0 -4
  280. data/test/fixtures/db_definitions/sybase2.sql +0 -5
  281. data/test/fixtures/developers_projects/david_action_controller +0 -3
  282. data/test/fixtures/developers_projects/david_active_record +0 -3
  283. data/test/fixtures/developers_projects/jamis_active_record +0 -2
  284. data/test/fixtures/person.rb +0 -4
  285. data/test/fixtures/pirate.rb +0 -5
  286. data/test/fixtures/subscribers/first +0 -2
  287. data/test/fixtures/subscribers/second +0 -2
  288. data/test/schema_dumper_test.rb +0 -131
  289. data/test/schema_test_postgresql.rb +0 -64
@@ -1,11 +1,13 @@
1
- require 'abstract_unit'
1
+ require "cases/helper"
2
2
  require 'bigdecimal/util'
3
3
 
4
- require 'fixtures/person'
5
- require 'fixtures/topic'
6
- require File.dirname(__FILE__) + '/fixtures/migrations/1_people_have_last_names'
7
- require File.dirname(__FILE__) + '/fixtures/migrations/2_we_need_reminders'
8
- require File.dirname(__FILE__) + '/fixtures/migrations_with_decimal/1_give_me_big_numbers'
4
+ require 'models/person'
5
+ require 'models/topic'
6
+
7
+ require MIGRATIONS_ROOT + "/valid/1_people_have_last_names"
8
+ require MIGRATIONS_ROOT + "/valid/2_we_need_reminders"
9
+ require MIGRATIONS_ROOT + "/decimal/1_give_me_big_numbers"
10
+ require MIGRATIONS_ROOT + "/interleaved/pass_3/2_i_raise_on_down"
9
11
 
10
12
  if ActiveRecord::Base.connection.supports_migrations?
11
13
  class BigNumber < ActiveRecord::Base; end
@@ -22,9 +24,9 @@ if ActiveRecord::Base.connection.supports_migrations?
22
24
  end
23
25
  end
24
26
 
25
- class MigrationTest < Test::Unit::TestCase
27
+ class MigrationTest < ActiveRecord::TestCase
26
28
  self.use_transactional_fixtures = false
27
-
29
+
28
30
  fixtures :people
29
31
 
30
32
  def setup
@@ -33,8 +35,8 @@ if ActiveRecord::Base.connection.supports_migrations?
33
35
  end
34
36
 
35
37
  def teardown
36
- ActiveRecord::Base.connection.initialize_schema_information
37
- ActiveRecord::Base.connection.update "UPDATE #{ActiveRecord::Migrator.schema_info_table_name} SET version = 0"
38
+ ActiveRecord::Base.connection.initialize_schema_migrations_table
39
+ ActiveRecord::Base.connection.execute "DELETE FROM #{ActiveRecord::Migrator.schema_migrations_table_name}"
38
40
 
39
41
  %w(reminders people_reminders prefix_reminders_suffix).each do |table|
40
42
  Reminder.connection.drop_table(table) rescue nil
@@ -77,10 +79,11 @@ if ActiveRecord::Base.connection.supports_migrations?
77
79
  # Note: changed index name from "key" to "key_idx" since "key" is a Firebird reserved word
78
80
  # OpenBase does not have named indexes. You must specify a single column name
79
81
  unless current_adapter?(:OpenBaseAdapter)
82
+ 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)
80
83
  assert_nothing_raised { Person.connection.add_index("people", ["key"], :name => "key_idx", :unique => true) }
81
84
  assert_nothing_raised { Person.connection.remove_index("people", :name => "key_idx", :unique => true) }
82
85
  end
83
-
86
+
84
87
  # Sybase adapter does not support indexes on :boolean columns
85
88
  # OpenBase does not have named indexes. You must specify a single column
86
89
  unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter)
@@ -180,6 +183,51 @@ if ActiveRecord::Base.connection.supports_migrations?
180
183
  Person.connection.drop_table :testings rescue nil
181
184
  end
182
185
 
186
+ def test_create_table_with_primary_key_prefix_as_table_name_with_underscore
187
+ ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore
188
+
189
+ Person.connection.create_table :testings do |t|
190
+ t.column :foo, :string
191
+ end
192
+
193
+ assert_equal %w(foo testings_id), Person.connection.columns(:testings).map { |c| c.name }.sort
194
+ ensure
195
+ Person.connection.drop_table :testings rescue nil
196
+ ActiveRecord::Base.primary_key_prefix_type = nil
197
+ end
198
+
199
+ def test_create_table_with_primary_key_prefix_as_table_name
200
+ ActiveRecord::Base.primary_key_prefix_type = :table_name
201
+
202
+ Person.connection.create_table :testings do |t|
203
+ t.column :foo, :string
204
+ end
205
+
206
+ assert_equal %w(foo testingsid), Person.connection.columns(:testings).map { |c| c.name }.sort
207
+ ensure
208
+ Person.connection.drop_table :testings rescue nil
209
+ ActiveRecord::Base.primary_key_prefix_type = nil
210
+ end
211
+
212
+ uses_mocha('test_create_table_with_force_true_does_not_drop_nonexisting_table') do
213
+ def test_create_table_with_force_true_does_not_drop_nonexisting_table
214
+ if Person.connection.table_exists?(:testings2)
215
+ Person.connection.drop_table :testings2
216
+ end
217
+
218
+ # using a copy as we need the drop_table method to
219
+ # continue to work for the ensure block of the test
220
+ temp_conn = Person.connection.dup
221
+ temp_conn.expects(:drop_table).never
222
+ temp_conn.create_table :testings2, :force => true do |t|
223
+ t.column :foo, :string
224
+ end
225
+ ensure
226
+ Person.connection.drop_table :testings2 rescue nil
227
+ end
228
+ end
229
+
230
+
183
231
  # SQL Server, Sybase, and SQLite3 will not allow you to add a NOT NULL
184
232
  # column to a table without a default value.
185
233
  unless current_adapter?(:SQLServerAdapter, :SybaseAdapter, :SQLiteAdapter)
@@ -201,8 +249,8 @@ if ActiveRecord::Base.connection.supports_migrations?
201
249
  Person.connection.create_table :testings do |t|
202
250
  t.column :foo, :string
203
251
  end
204
-
205
- con = Person.connection
252
+
253
+ con = Person.connection
206
254
  Person.connection.enable_identity_insert("testings", true) if current_adapter?(:SybaseAdapter)
207
255
  Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}) values (1, 'hello')"
208
256
  Person.connection.enable_identity_insert("testings", false) if current_adapter?(:SybaseAdapter)
@@ -233,7 +281,7 @@ if ActiveRecord::Base.connection.supports_migrations?
233
281
  # Do a manual insertion
234
282
  if current_adapter?(:OracleAdapter)
235
283
  Person.connection.execute "insert into people (id, wealth) values (people_seq.nextval, 12345678901234567890.0123456789)"
236
- elsif current_adapter?(:OpenBaseAdapter)
284
+ elsif current_adapter?(:OpenBaseAdapter) || (current_adapter?(:MysqlAdapter) && Mysql.client_version < 50003) #before mysql 5.0.3 decimals stored as strings
237
285
  Person.connection.execute "insert into people (wealth) values ('12345678901234567890.0123456789')"
238
286
  else
239
287
  Person.connection.execute "insert into people (wealth) values (12345678901234567890.0123456789)"
@@ -268,6 +316,15 @@ if ActiveRecord::Base.connection.supports_migrations?
268
316
  Person.reset_column_information
269
317
  end
270
318
 
319
+ def test_add_column_with_precision_and_scale
320
+ Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7
321
+ Person.reset_column_information
322
+
323
+ wealth_column = Person.columns_hash['wealth']
324
+ assert_equal 9, wealth_column.precision
325
+ assert_equal 7, wealth_column.scale
326
+ end
327
+
271
328
  def test_native_types
272
329
  Person.delete_all
273
330
  Person.connection.add_column "people", "last_name", :string
@@ -297,11 +354,11 @@ if ActiveRecord::Base.connection.supports_migrations?
297
354
 
298
355
  # Test for 30 significent digits (beyond the 16 of float), 10 of them
299
356
  # after the decimal place.
300
-
357
+
301
358
  unless current_adapter?(:SQLite3Adapter)
302
359
  assert_equal BigDecimal.new("0012345678901234567890.0123456789"), bob.wealth
303
360
  end
304
-
361
+
305
362
  assert_equal true, bob.male?
306
363
 
307
364
  assert_equal String, bob.first_name.class
@@ -320,10 +377,16 @@ if ActiveRecord::Base.connection.supports_migrations?
320
377
  # Test DateTime column and defaults, including timezone.
321
378
  # FIXME: moment of truth may be Time on 64-bit platforms.
322
379
  if bob.moment_of_truth.is_a?(DateTime)
323
- assert_equal DateTime.now.offset, bob.moment_of_truth.offset
324
- assert_not_equal 0, bob.moment_of_truth.offset
325
- assert_not_equal "Z", bob.moment_of_truth.zone
326
- assert_equal DateTime::ITALY, bob.moment_of_truth.start
380
+
381
+ with_env_tz 'US/Eastern' do
382
+ assert_equal DateTime.local_offset, bob.moment_of_truth.offset
383
+ assert_not_equal 0, bob.moment_of_truth.offset
384
+ assert_not_equal "Z", bob.moment_of_truth.zone
385
+ # US/Eastern is -5 hours from GMT
386
+ assert_equal Rational(-5, 24), bob.moment_of_truth.offset
387
+ assert_match /\A-05:?00\Z/, bob.moment_of_truth.zone #ruby 1.8.6 uses HH:MM, prior versions use HHMM
388
+ assert_equal DateTime::ITALY, bob.moment_of_truth.start
389
+ end
327
390
  end
328
391
 
329
392
  assert_equal TrueClass, bob.male?.class
@@ -337,7 +400,7 @@ if ActiveRecord::Base.connection.supports_migrations?
337
400
  ActiveRecord::Migration.add_column :people, :intelligence_quotient, :tinyint
338
401
  Person.reset_column_information
339
402
  Person.create :intelligence_quotient => 300
340
- jonnyg = Person.find(:first)
403
+ jonnyg = Person.find(:first)
341
404
  assert_equal 127, jonnyg.intelligence_quotient
342
405
  jonnyg.destroy
343
406
  ensure
@@ -430,13 +493,13 @@ if ActiveRecord::Base.connection.supports_migrations?
430
493
  Person.connection.add_column("people", "first_name", :string) rescue nil
431
494
  end
432
495
  end
433
-
496
+
434
497
  def test_rename_column_with_an_index
435
498
  ActiveRecord::Base.connection.create_table(:hats) do |table|
436
499
  table.column :hat_name, :string, :limit => 100
437
500
  table.column :hat_size, :integer
438
501
  end
439
- Person.connection.add_index :people, :first_name
502
+ Person.connection.add_index :hats, :hat_name
440
503
  assert_nothing_raised do
441
504
  Person.connection.rename_column "hats", "hat_name", "name"
442
505
  end
@@ -473,7 +536,7 @@ if ActiveRecord::Base.connection.supports_migrations?
473
536
  assert_nothing_raised do
474
537
  Topic.connection.change_column "topics", "written_on", :datetime, :null => false
475
538
  Topic.reset_column_information
476
-
539
+
477
540
  Topic.connection.change_column "topics", "written_on", :datetime, :null => false
478
541
  Topic.reset_column_information
479
542
  end
@@ -487,7 +550,7 @@ if ActiveRecord::Base.connection.supports_migrations?
487
550
  ActiveRecord::Base.connection.rename_table :octopuses, :octopi
488
551
 
489
552
  # Using explicit id in insert for compatibility across all databases
490
- con = ActiveRecord::Base.connection
553
+ con = ActiveRecord::Base.connection
491
554
  con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
492
555
  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')" }
493
556
  con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
@@ -499,9 +562,9 @@ if ActiveRecord::Base.connection.supports_migrations?
499
562
  ActiveRecord::Base.connection.drop_table :octopi rescue nil
500
563
  end
501
564
  end
502
-
565
+
503
566
  def test_change_column_nullability
504
- Person.delete_all
567
+ Person.delete_all
505
568
  Person.connection.add_column "people", "funny", :boolean
506
569
  Person.reset_column_information
507
570
  assert Person.columns_hash["funny"].null, "Column 'funny' must initially allow nulls"
@@ -519,11 +582,11 @@ if ActiveRecord::Base.connection.supports_migrations?
519
582
  t.column :url, :string
520
583
  end
521
584
  ActiveRecord::Base.connection.add_index :octopuses, :url
522
-
585
+
523
586
  ActiveRecord::Base.connection.rename_table :octopuses, :octopi
524
587
 
525
588
  # Using explicit id in insert for compatibility across all databases
526
- con = ActiveRecord::Base.connection
589
+ con = ActiveRecord::Base.connection
527
590
  con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
528
591
  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')" }
529
592
  con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
@@ -555,12 +618,12 @@ if ActiveRecord::Base.connection.supports_migrations?
555
618
  assert new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == false }
556
619
  assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => true }
557
620
  end
558
-
621
+
559
622
  def test_change_column_with_nil_default
560
623
  Person.connection.add_column "people", "contributor", :boolean, :default => true
561
624
  Person.reset_column_information
562
625
  assert Person.new.contributor?
563
-
626
+
564
627
  assert_nothing_raised { Person.connection.change_column "people", "contributor", :boolean, :default => nil }
565
628
  Person.reset_column_information
566
629
  assert !Person.new.contributor?
@@ -580,7 +643,7 @@ if ActiveRecord::Base.connection.supports_migrations?
580
643
  ensure
581
644
  Person.connection.remove_column("people", "administrator") rescue nil
582
645
  end
583
-
646
+
584
647
  def test_change_column_default
585
648
  Person.connection.change_column_default "people", "first_name", "Tester"
586
649
  Person.reset_column_information
@@ -609,8 +672,8 @@ if ActiveRecord::Base.connection.supports_migrations?
609
672
  assert !Reminder.table_exists?
610
673
 
611
674
  WeNeedReminders.up
612
-
613
- assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
675
+
676
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
614
677
  assert_equal "hello world", Reminder.find(:first).content
615
678
 
616
679
  WeNeedReminders.down
@@ -686,7 +749,7 @@ if ActiveRecord::Base.connection.supports_migrations?
686
749
  assert !Person.column_methods_hash.include?(:last_name)
687
750
  assert !Reminder.table_exists?
688
751
 
689
- ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/')
752
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid")
690
753
 
691
754
  assert_equal 3, ActiveRecord::Migrator.current_version
692
755
  Person.reset_column_information
@@ -694,7 +757,7 @@ if ActiveRecord::Base.connection.supports_migrations?
694
757
  assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
695
758
  assert_equal "hello world", Reminder.find(:first).content
696
759
 
697
- ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/')
760
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid")
698
761
 
699
762
  assert_equal 0, ActiveRecord::Migrator.current_version
700
763
  Person.reset_column_information
@@ -706,78 +769,145 @@ if ActiveRecord::Base.connection.supports_migrations?
706
769
  assert !Person.column_methods_hash.include?(:last_name)
707
770
  assert !Reminder.table_exists?
708
771
 
709
- ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
772
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
710
773
 
711
774
  Person.reset_column_information
712
775
  assert Person.column_methods_hash.include?(:last_name)
713
776
  assert !Reminder.table_exists?
714
777
 
715
- ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 2)
778
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 2)
716
779
 
717
780
  assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
718
781
  assert_equal "hello world", Reminder.find(:first).content
719
782
  end
720
783
 
721
784
  def test_migrator_one_down
722
- ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/')
723
-
724
- ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
725
-
785
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid")
786
+
787
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 1)
788
+
726
789
  Person.reset_column_information
727
790
  assert Person.column_methods_hash.include?(:last_name)
728
791
  assert !Reminder.table_exists?
729
792
  end
730
793
 
731
794
  def test_migrator_one_up_one_down
732
- ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
733
- ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 0)
795
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
796
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
734
797
 
735
798
  assert !Person.column_methods_hash.include?(:last_name)
736
799
  assert !Reminder.table_exists?
737
800
  end
738
801
 
802
+ def test_finds_migrations
803
+ migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/valid").migrations
804
+ [['1', 'people_have_last_names'],
805
+ ['2', 'we_need_reminders'],
806
+ ['3', 'innocent_jointable']].each_with_index do |pair, i|
807
+ migrations[i].version == pair.first
808
+ migrations[1].name == pair.last
809
+ end
810
+ end
811
+
812
+ def test_finds_pending_migrations
813
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2", 1)
814
+ migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/interleaved/pass_2").pending_migrations
815
+ assert_equal 1, migrations.size
816
+ migrations[0].version == '3'
817
+ migrations[0].name == 'innocent_jointable'
818
+ end
819
+
820
+ def test_migrator_interleaved_migrations
821
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_1")
822
+
823
+ assert_nothing_raised do
824
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2")
825
+ end
826
+
827
+ Person.reset_column_information
828
+ assert Person.column_methods_hash.include?(:last_name)
829
+
830
+ assert_nothing_raised do
831
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/interleaved/pass_3")
832
+ end
833
+ end
834
+
835
+ def test_migrator_db_has_no_schema_migrations_table
836
+ ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations;")
837
+ assert_nothing_raised do
838
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1)
839
+ end
840
+ end
841
+
739
842
  def test_migrator_verbosity
740
- ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
843
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
741
844
  assert PeopleHaveLastNames.message_count > 0
742
845
  PeopleHaveLastNames.message_count = 0
743
846
 
744
- ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 0)
847
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
745
848
  assert PeopleHaveLastNames.message_count > 0
746
849
  PeopleHaveLastNames.message_count = 0
747
850
  end
748
851
 
749
852
  def test_migrator_verbosity_off
750
853
  PeopleHaveLastNames.verbose = false
751
- ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
854
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
752
855
  assert PeopleHaveLastNames.message_count.zero?
753
- ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 0)
856
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
754
857
  assert PeopleHaveLastNames.message_count.zero?
755
858
  end
756
859
 
757
860
  def test_migrator_going_down_due_to_version_target
758
- ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
759
- ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations/', 0)
861
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
862
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0)
760
863
 
761
864
  assert !Person.column_methods_hash.include?(:last_name)
762
865
  assert !Reminder.table_exists?
763
866
 
764
- ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations/')
867
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
765
868
 
766
869
  Person.reset_column_information
767
870
  assert Person.column_methods_hash.include?(:last_name)
768
871
  assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
769
872
  assert_equal "hello world", Reminder.find(:first).content
770
873
  end
874
+
875
+ def test_migrator_rollback
876
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
877
+ assert_equal(3, ActiveRecord::Migrator.current_version)
878
+
879
+ ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
880
+ assert_equal(2, ActiveRecord::Migrator.current_version)
881
+
882
+ ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
883
+ assert_equal(1, ActiveRecord::Migrator.current_version)
884
+
885
+ ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
886
+ assert_equal(0, ActiveRecord::Migrator.current_version)
887
+
888
+ ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
889
+ assert_equal(0, ActiveRecord::Migrator.current_version)
890
+ end
891
+
892
+ def test_migrator_run
893
+ assert_equal(0, ActiveRecord::Migrator.current_version)
894
+ ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 3)
895
+ assert_equal(0, ActiveRecord::Migrator.current_version)
896
+
897
+ assert_equal(0, ActiveRecord::Migrator.current_version)
898
+ ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT + "/valid", 3)
899
+ assert_equal(0, ActiveRecord::Migrator.current_version)
900
+ end
771
901
 
772
- def test_schema_info_table_name
902
+ def test_schema_migrations_table_name
773
903
  ActiveRecord::Base.table_name_prefix = "prefix_"
774
904
  ActiveRecord::Base.table_name_suffix = "_suffix"
775
905
  Reminder.reset_table_name
776
- assert_equal "prefix_schema_info_suffix", ActiveRecord::Migrator.schema_info_table_name
906
+ assert_equal "prefix_schema_migrations_suffix", ActiveRecord::Migrator.schema_migrations_table_name
777
907
  ActiveRecord::Base.table_name_prefix = ""
778
908
  ActiveRecord::Base.table_name_suffix = ""
779
909
  Reminder.reset_table_name
780
- assert_equal "schema_info", ActiveRecord::Migrator.schema_info_table_name
910
+ assert_equal "schema_migrations", ActiveRecord::Migrator.schema_migrations_table_name
781
911
  ensure
782
912
  ActiveRecord::Base.table_name_prefix = ""
783
913
  ActiveRecord::Base.table_name_suffix = ""
@@ -843,31 +973,27 @@ if ActiveRecord::Base.connection.supports_migrations?
843
973
  columns = Person.connection.columns(:binary_testings)
844
974
  data_column = columns.detect { |c| c.name == "data" }
845
975
 
846
- if current_adapter?(:MysqlAdapter)
847
- assert_equal '', data_column.default
848
- else
849
- assert_nil data_column.default
850
- end
976
+ assert_nil data_column.default
851
977
 
852
978
  Person.connection.drop_table :binary_testings rescue nil
853
979
  end
854
980
 
855
981
  def test_migrator_with_duplicates
856
982
  assert_raises(ActiveRecord::DuplicateMigrationVersionError) do
857
- ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations_with_duplicate/', nil)
983
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate", nil)
984
+ end
985
+ end
986
+
987
+ def test_migrator_with_duplicate_names
988
+ assert_raises(ActiveRecord::DuplicateMigrationNameError, "Multiple migrations have the name Chunky") do
989
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate_names", nil)
858
990
  end
859
991
  end
860
992
 
861
993
  def test_migrator_with_missing_version_numbers
862
- ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations_with_missing_versions/', 500)
863
- assert !Person.column_methods_hash.include?(:middle_name)
864
- assert_equal 4, ActiveRecord::Migrator.current_version
865
-
866
- ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations_with_missing_versions/', 2)
867
- Person.reset_column_information
868
- assert !Reminder.table_exists?
869
- assert Person.column_methods_hash.include?(:last_name)
870
- assert_equal 2, ActiveRecord::Migrator.current_version
994
+ assert_raise(ActiveRecord::UnknownMigrationVersionError) do
995
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/missing", 500)
996
+ end
871
997
  end
872
998
 
873
999
  def test_create_table_with_custom_sequence_name
@@ -906,17 +1032,26 @@ if ActiveRecord::Base.connection.supports_migrations?
906
1032
  Person.connection.execute("select suitably_short_seq.nextval from dual")
907
1033
  end
908
1034
  end
909
- end
910
1035
 
1036
+ protected
1037
+ def with_env_tz(new_tz = 'US/Eastern')
1038
+ old_tz, ENV['TZ'] = ENV['TZ'], new_tz
1039
+ yield
1040
+ ensure
1041
+ old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
1042
+ end
1043
+
1044
+ end
1045
+
911
1046
  uses_mocha 'Sexy migration tests' do
912
- class SexyMigrationsTest < Test::Unit::TestCase
1047
+ class SexyMigrationsTest < ActiveRecord::TestCase
913
1048
  def test_references_column_type_adds_id
914
1049
  with_new_table do |t|
915
1050
  t.expects(:column).with('customer_id', :integer, {})
916
1051
  t.references :customer
917
1052
  end
918
1053
  end
919
-
1054
+
920
1055
  def test_references_column_type_with_polymorphic_adds_type
921
1056
  with_new_table do |t|
922
1057
  t.expects(:column).with('taggable_type', :string, {})
@@ -924,7 +1059,7 @@ if ActiveRecord::Base.connection.supports_migrations?
924
1059
  t.references :taggable, :polymorphic => true
925
1060
  end
926
1061
  end
927
-
1062
+
928
1063
  def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag
929
1064
  with_new_table do |t|
930
1065
  t.expects(:column).with('taggable_type', :string, {:null => false})
@@ -939,7 +1074,7 @@ if ActiveRecord::Base.connection.supports_migrations?
939
1074
  t.belongs_to :customer
940
1075
  end
941
1076
  end
942
-
1077
+
943
1078
  def test_timestamps_creates_updated_at_and_created_at
944
1079
  with_new_table do |t|
945
1080
  t.expects(:column).with(:created_at, :datetime)
@@ -947,7 +1082,7 @@ if ActiveRecord::Base.connection.supports_migrations?
947
1082
  t.timestamps
948
1083
  end
949
1084
  end
950
-
1085
+
951
1086
  def test_integer_creates_integer_column
952
1087
  with_new_table do |t|
953
1088
  t.expects(:column).with(:foo, 'integer', {})
@@ -955,7 +1090,7 @@ if ActiveRecord::Base.connection.supports_migrations?
955
1090
  t.integer :foo, :bar
956
1091
  end
957
1092
  end
958
-
1093
+
959
1094
  def test_string_creates_string_column
960
1095
  with_new_table do |t|
961
1096
  t.expects(:column).with(:foo, 'string', {})
@@ -963,17 +1098,222 @@ if ActiveRecord::Base.connection.supports_migrations?
963
1098
  t.string :foo, :bar
964
1099
  end
965
1100
  end
966
-
1101
+
967
1102
  protected
968
1103
  def with_new_table
969
- Person.connection.create_table :delete_me do |t|
1104
+ Person.connection.create_table :delete_me, :force => true do |t|
970
1105
  yield t
971
1106
  end
972
1107
  ensure
973
1108
  Person.connection.drop_table :delete_me rescue nil
974
1109
  end
975
-
1110
+
976
1111
  end # SexyMigrationsTest
977
1112
  end # uses_mocha
978
- end
979
1113
 
1114
+ uses_mocha 'ChangeTable migration tests' do
1115
+ class ChangeTableMigrationsTest < ActiveRecord::TestCase
1116
+ def setup
1117
+ @connection = Person.connection
1118
+ @connection.create_table :delete_me, :force => true do |t|
1119
+ end
1120
+ end
1121
+
1122
+ def teardown
1123
+ Person.connection.drop_table :delete_me rescue nil
1124
+ end
1125
+
1126
+ def test_references_column_type_adds_id
1127
+ with_change_table do |t|
1128
+ @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {})
1129
+ t.references :customer
1130
+ end
1131
+ end
1132
+
1133
+ def test_remove_references_column_type_removes_id
1134
+ with_change_table do |t|
1135
+ @connection.expects(:remove_column).with(:delete_me, 'customer_id')
1136
+ t.remove_references :customer
1137
+ end
1138
+ end
1139
+
1140
+ def test_add_belongs_to_works_like_add_references
1141
+ with_change_table do |t|
1142
+ @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {})
1143
+ t.belongs_to :customer
1144
+ end
1145
+ end
1146
+
1147
+ def test_remove_belongs_to_works_like_remove_references
1148
+ with_change_table do |t|
1149
+ @connection.expects(:remove_column).with(:delete_me, 'customer_id')
1150
+ t.remove_belongs_to :customer
1151
+ end
1152
+ end
1153
+
1154
+ def test_references_column_type_with_polymorphic_adds_type
1155
+ with_change_table do |t|
1156
+ @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {})
1157
+ @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {})
1158
+ t.references :taggable, :polymorphic => true
1159
+ end
1160
+ end
1161
+
1162
+ def test_remove_references_column_type_with_polymorphic_removes_type
1163
+ with_change_table do |t|
1164
+ @connection.expects(:remove_column).with(:delete_me, 'taggable_type')
1165
+ @connection.expects(:remove_column).with(:delete_me, 'taggable_id')
1166
+ t.remove_references :taggable, :polymorphic => true
1167
+ end
1168
+ end
1169
+
1170
+ def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag
1171
+ with_change_table do |t|
1172
+ @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {:null => false})
1173
+ @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {:null => false})
1174
+ t.references :taggable, :polymorphic => true, :null => false
1175
+ end
1176
+ end
1177
+
1178
+ def test_remove_references_column_type_with_polymorphic_and_options_null_is_false_removes_table_flag
1179
+ with_change_table do |t|
1180
+ @connection.expects(:remove_column).with(:delete_me, 'taggable_type')
1181
+ @connection.expects(:remove_column).with(:delete_me, 'taggable_id')
1182
+ t.remove_references :taggable, :polymorphic => true, :null => false
1183
+ end
1184
+ end
1185
+
1186
+ def test_timestamps_creates_updated_at_and_created_at
1187
+ with_change_table do |t|
1188
+ @connection.expects(:add_timestamps).with(:delete_me)
1189
+ t.timestamps
1190
+ end
1191
+ end
1192
+
1193
+ def test_remove_timestamps_creates_updated_at_and_created_at
1194
+ with_change_table do |t|
1195
+ @connection.expects(:remove_timestamps).with(:delete_me)
1196
+ t.remove_timestamps
1197
+ end
1198
+ end
1199
+
1200
+ def string_column
1201
+ if current_adapter?(:PostgreSQLAdapter)
1202
+ "character varying(255)"
1203
+ else
1204
+ 'varchar(255)'
1205
+ end
1206
+ end
1207
+
1208
+ def integer_column
1209
+ if current_adapter?(:SQLite3Adapter) || current_adapter?(:SQLiteAdapter) || current_adapter?(:PostgreSQLAdapter)
1210
+ "integer"
1211
+ else
1212
+ 'int(11)'
1213
+ end
1214
+ end
1215
+
1216
+ def test_integer_creates_integer_column
1217
+ with_change_table do |t|
1218
+ @connection.expects(:add_column).with(:delete_me, :foo, integer_column, {})
1219
+ @connection.expects(:add_column).with(:delete_me, :bar, integer_column, {})
1220
+ t.integer :foo, :bar
1221
+ end
1222
+ end
1223
+
1224
+ def test_string_creates_string_column
1225
+ with_change_table do |t|
1226
+ @connection.expects(:add_column).with(:delete_me, :foo, string_column, {})
1227
+ @connection.expects(:add_column).with(:delete_me, :bar, string_column, {})
1228
+ t.string :foo, :bar
1229
+ end
1230
+ end
1231
+
1232
+ def test_column_creates_column
1233
+ with_change_table do |t|
1234
+ @connection.expects(:add_column).with(:delete_me, :bar, :integer, {})
1235
+ t.column :bar, :integer
1236
+ end
1237
+ end
1238
+
1239
+ def test_column_creates_column_with_options
1240
+ with_change_table do |t|
1241
+ @connection.expects(:add_column).with(:delete_me, :bar, :integer, {:null => false})
1242
+ t.column :bar, :integer, :null => false
1243
+ end
1244
+ end
1245
+
1246
+ def test_index_creates_index
1247
+ with_change_table do |t|
1248
+ @connection.expects(:add_index).with(:delete_me, :bar, {})
1249
+ t.index :bar
1250
+ end
1251
+ end
1252
+
1253
+ def test_index_creates_index_with_options
1254
+ with_change_table do |t|
1255
+ @connection.expects(:add_index).with(:delete_me, :bar, {:unique => true})
1256
+ t.index :bar, :unique => true
1257
+ end
1258
+ end
1259
+
1260
+ def test_change_changes_column
1261
+ with_change_table do |t|
1262
+ @connection.expects(:change_column).with(:delete_me, :bar, :string, {})
1263
+ t.change :bar, :string
1264
+ end
1265
+ end
1266
+
1267
+ def test_change_changes_column_with_options
1268
+ with_change_table do |t|
1269
+ @connection.expects(:change_column).with(:delete_me, :bar, :string, {:null => true})
1270
+ t.change :bar, :string, :null => true
1271
+ end
1272
+ end
1273
+
1274
+ def test_change_default_changes_column
1275
+ with_change_table do |t|
1276
+ @connection.expects(:change_column_default).with(:delete_me, :bar, :string)
1277
+ t.change_default :bar, :string
1278
+ end
1279
+ end
1280
+
1281
+ def test_remove_drops_single_column
1282
+ with_change_table do |t|
1283
+ @connection.expects(:remove_column).with(:delete_me, [:bar])
1284
+ t.remove :bar
1285
+ end
1286
+ end
1287
+
1288
+ def test_remove_drops_multiple_columns
1289
+ with_change_table do |t|
1290
+ @connection.expects(:remove_column).with(:delete_me, [:bar, :baz])
1291
+ t.remove :bar, :baz
1292
+ end
1293
+ end
1294
+
1295
+ def test_remove_index_removes_index_with_options
1296
+ with_change_table do |t|
1297
+ @connection.expects(:remove_index).with(:delete_me, {:unique => true})
1298
+ t.remove_index :unique => true
1299
+ end
1300
+ end
1301
+
1302
+ def test_rename_renames_column
1303
+ with_change_table do |t|
1304
+ @connection.expects(:rename_column).with(:delete_me, :bar, :baz)
1305
+ t.rename :bar, :baz
1306
+ end
1307
+ end
1308
+
1309
+ protected
1310
+ def with_change_table
1311
+ Person.connection.change_table :delete_me do |t|
1312
+ yield t
1313
+ end
1314
+ end
1315
+
1316
+ end # ChangeTable test
1317
+ end # uses_mocha
1318
+
1319
+ end