activerecord 2.3.18 → 3.2.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (454) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1014 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +222 -0
  5. data/examples/performance.rb +100 -126
  6. data/examples/simple.rb +14 -0
  7. data/lib/active_record/aggregations.rb +93 -99
  8. data/lib/active_record/associations/alias_tracker.rb +76 -0
  9. data/lib/active_record/associations/association.rb +247 -0
  10. data/lib/active_record/associations/association_scope.rb +134 -0
  11. data/lib/active_record/associations/belongs_to_association.rb +54 -61
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +17 -59
  13. data/lib/active_record/associations/builder/association.rb +55 -0
  14. data/lib/active_record/associations/builder/belongs_to.rb +88 -0
  15. data/lib/active_record/associations/builder/collection_association.rb +75 -0
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -0
  17. data/lib/active_record/associations/builder/has_many.rb +71 -0
  18. data/lib/active_record/associations/builder/has_one.rb +62 -0
  19. data/lib/active_record/associations/builder/singular_association.rb +32 -0
  20. data/lib/active_record/associations/collection_association.rb +580 -0
  21. data/lib/active_record/associations/collection_proxy.rb +133 -0
  22. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +39 -119
  23. data/lib/active_record/associations/has_many_association.rb +60 -79
  24. data/lib/active_record/associations/has_many_through_association.rb +127 -206
  25. data/lib/active_record/associations/has_one_association.rb +55 -114
  26. data/lib/active_record/associations/has_one_through_association.rb +25 -26
  27. data/lib/active_record/associations/join_dependency/join_association.rb +159 -0
  28. data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
  29. data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
  30. data/lib/active_record/associations/join_dependency.rb +214 -0
  31. data/lib/active_record/associations/join_helper.rb +55 -0
  32. data/lib/active_record/associations/preloader/association.rb +125 -0
  33. data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
  34. data/lib/active_record/associations/preloader/collection_association.rb +24 -0
  35. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
  36. data/lib/active_record/associations/preloader/has_many.rb +17 -0
  37. data/lib/active_record/associations/preloader/has_many_through.rb +15 -0
  38. data/lib/active_record/associations/preloader/has_one.rb +23 -0
  39. data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
  40. data/lib/active_record/associations/preloader/singular_association.rb +21 -0
  41. data/lib/active_record/associations/preloader/through_association.rb +67 -0
  42. data/lib/active_record/associations/preloader.rb +181 -0
  43. data/lib/active_record/associations/singular_association.rb +64 -0
  44. data/lib/active_record/associations/through_association.rb +87 -0
  45. data/lib/active_record/associations.rb +693 -1337
  46. data/lib/active_record/attribute_assignment.rb +221 -0
  47. data/lib/active_record/attribute_methods/before_type_cast.rb +31 -0
  48. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +32 -0
  49. data/lib/active_record/attribute_methods/dirty.rb +111 -0
  50. data/lib/active_record/attribute_methods/primary_key.rb +114 -0
  51. data/lib/active_record/attribute_methods/query.rb +39 -0
  52. data/lib/active_record/attribute_methods/read.rb +136 -0
  53. data/lib/active_record/attribute_methods/serialization.rb +120 -0
  54. data/lib/active_record/attribute_methods/time_zone_conversion.rb +65 -0
  55. data/lib/active_record/attribute_methods/write.rb +70 -0
  56. data/lib/active_record/attribute_methods.rb +211 -339
  57. data/lib/active_record/autosave_association.rb +179 -149
  58. data/lib/active_record/base.rb +401 -2907
  59. data/lib/active_record/callbacks.rb +91 -176
  60. data/lib/active_record/coders/yaml_column.rb +41 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +236 -119
  62. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +110 -58
  63. data/lib/active_record/connection_adapters/abstract/database_limits.rb +12 -11
  64. data/lib/active_record/connection_adapters/abstract/database_statements.rb +175 -74
  65. data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -35
  66. data/lib/active_record/connection_adapters/abstract/quoting.rb +71 -21
  67. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +81 -311
  68. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +194 -78
  69. data/lib/active_record/connection_adapters/abstract_adapter.rb +130 -83
  70. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +676 -0
  71. data/lib/active_record/connection_adapters/column.rb +296 -0
  72. data/lib/active_record/connection_adapters/mysql2_adapter.rb +280 -0
  73. data/lib/active_record/connection_adapters/mysql_adapter.rb +272 -493
  74. data/lib/active_record/connection_adapters/postgresql_adapter.rb +650 -405
  75. data/lib/active_record/connection_adapters/schema_cache.rb +69 -0
  76. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +30 -9
  77. data/lib/active_record/connection_adapters/sqlite_adapter.rb +276 -147
  78. data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
  79. data/lib/active_record/counter_cache.rb +123 -0
  80. data/lib/active_record/dynamic_finder_match.rb +41 -14
  81. data/lib/active_record/dynamic_matchers.rb +84 -0
  82. data/lib/active_record/dynamic_scope_match.rb +13 -15
  83. data/lib/active_record/errors.rb +195 -0
  84. data/lib/active_record/explain.rb +86 -0
  85. data/lib/active_record/explain_subscriber.rb +25 -0
  86. data/lib/active_record/fixtures/file.rb +65 -0
  87. data/lib/active_record/fixtures.rb +695 -770
  88. data/lib/active_record/identity_map.rb +162 -0
  89. data/lib/active_record/inheritance.rb +174 -0
  90. data/lib/active_record/integration.rb +60 -0
  91. data/lib/active_record/locale/en.yml +9 -27
  92. data/lib/active_record/locking/optimistic.rb +76 -73
  93. data/lib/active_record/locking/pessimistic.rb +32 -10
  94. data/lib/active_record/log_subscriber.rb +72 -0
  95. data/lib/active_record/migration/command_recorder.rb +105 -0
  96. data/lib/active_record/migration.rb +415 -205
  97. data/lib/active_record/model_schema.rb +368 -0
  98. data/lib/active_record/nested_attributes.rb +153 -63
  99. data/lib/active_record/observer.rb +27 -103
  100. data/lib/active_record/persistence.rb +376 -0
  101. data/lib/active_record/query_cache.rb +49 -8
  102. data/lib/active_record/querying.rb +58 -0
  103. data/lib/active_record/railtie.rb +131 -0
  104. data/lib/active_record/railties/console_sandbox.rb +6 -0
  105. data/lib/active_record/railties/controller_runtime.rb +49 -0
  106. data/lib/active_record/railties/databases.rake +659 -0
  107. data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
  108. data/lib/active_record/readonly_attributes.rb +26 -0
  109. data/lib/active_record/reflection.rb +269 -120
  110. data/lib/active_record/relation/batches.rb +90 -0
  111. data/lib/active_record/relation/calculations.rb +372 -0
  112. data/lib/active_record/relation/delegation.rb +49 -0
  113. data/lib/active_record/relation/finder_methods.rb +402 -0
  114. data/lib/active_record/relation/predicate_builder.rb +63 -0
  115. data/lib/active_record/relation/query_methods.rb +417 -0
  116. data/lib/active_record/relation/spawn_methods.rb +180 -0
  117. data/lib/active_record/relation.rb +537 -0
  118. data/lib/active_record/result.rb +40 -0
  119. data/lib/active_record/sanitization.rb +194 -0
  120. data/lib/active_record/schema.rb +9 -6
  121. data/lib/active_record/schema_dumper.rb +55 -32
  122. data/lib/active_record/scoping/default.rb +142 -0
  123. data/lib/active_record/scoping/named.rb +200 -0
  124. data/lib/active_record/scoping.rb +152 -0
  125. data/lib/active_record/serialization.rb +8 -91
  126. data/lib/active_record/serializers/xml_serializer.rb +43 -197
  127. data/lib/active_record/session_store.rb +129 -103
  128. data/lib/active_record/store.rb +52 -0
  129. data/lib/active_record/test_case.rb +30 -23
  130. data/lib/active_record/timestamp.rb +95 -52
  131. data/lib/active_record/transactions.rb +212 -66
  132. data/lib/active_record/translation.rb +22 -0
  133. data/lib/active_record/validations/associated.rb +43 -0
  134. data/lib/active_record/validations/uniqueness.rb +180 -0
  135. data/lib/active_record/validations.rb +43 -1106
  136. data/lib/active_record/version.rb +5 -4
  137. data/lib/active_record.rb +121 -48
  138. data/lib/rails/generators/active_record/migration/migration_generator.rb +25 -0
  139. data/lib/rails/generators/active_record/migration/templates/migration.rb +34 -0
  140. data/lib/rails/generators/active_record/migration.rb +15 -0
  141. data/lib/rails/generators/active_record/model/model_generator.rb +47 -0
  142. data/lib/rails/generators/active_record/model/templates/migration.rb +15 -0
  143. data/lib/rails/generators/active_record/model/templates/model.rb +12 -0
  144. data/lib/rails/generators/active_record/model/templates/module.rb +7 -0
  145. data/lib/rails/generators/active_record/observer/observer_generator.rb +15 -0
  146. data/lib/rails/generators/active_record/observer/templates/observer.rb +4 -0
  147. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +25 -0
  148. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +12 -0
  149. data/lib/rails/generators/active_record.rb +25 -0
  150. metadata +187 -363
  151. data/CHANGELOG +0 -5904
  152. data/README +0 -351
  153. data/RUNNING_UNIT_TESTS +0 -36
  154. data/Rakefile +0 -268
  155. data/install.rb +0 -30
  156. data/lib/active_record/association_preload.rb +0 -406
  157. data/lib/active_record/associations/association_collection.rb +0 -533
  158. data/lib/active_record/associations/association_proxy.rb +0 -288
  159. data/lib/active_record/batches.rb +0 -85
  160. data/lib/active_record/calculations.rb +0 -321
  161. data/lib/active_record/dirty.rb +0 -183
  162. data/lib/active_record/named_scope.rb +0 -197
  163. data/lib/active_record/serializers/json_serializer.rb +0 -91
  164. data/lib/activerecord.rb +0 -2
  165. data/test/assets/example.log +0 -1
  166. data/test/assets/flowers.jpg +0 -0
  167. data/test/cases/aaa_create_tables_test.rb +0 -24
  168. data/test/cases/active_schema_test_mysql.rb +0 -122
  169. data/test/cases/active_schema_test_postgresql.rb +0 -24
  170. data/test/cases/adapter_test.rb +0 -144
  171. data/test/cases/aggregations_test.rb +0 -167
  172. data/test/cases/ar_schema_test.rb +0 -32
  173. data/test/cases/associations/belongs_to_associations_test.rb +0 -438
  174. data/test/cases/associations/callbacks_test.rb +0 -161
  175. data/test/cases/associations/cascaded_eager_loading_test.rb +0 -131
  176. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +0 -36
  177. data/test/cases/associations/eager_load_nested_include_test.rb +0 -131
  178. data/test/cases/associations/eager_load_nested_polymorphic_include.rb +0 -19
  179. data/test/cases/associations/eager_singularization_test.rb +0 -145
  180. data/test/cases/associations/eager_test.rb +0 -852
  181. data/test/cases/associations/extension_test.rb +0 -62
  182. data/test/cases/associations/habtm_join_table_test.rb +0 -56
  183. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +0 -827
  184. data/test/cases/associations/has_many_associations_test.rb +0 -1273
  185. data/test/cases/associations/has_many_through_associations_test.rb +0 -360
  186. data/test/cases/associations/has_one_associations_test.rb +0 -330
  187. data/test/cases/associations/has_one_through_associations_test.rb +0 -209
  188. data/test/cases/associations/inner_join_association_test.rb +0 -93
  189. data/test/cases/associations/inverse_associations_test.rb +0 -566
  190. data/test/cases/associations/join_model_test.rb +0 -712
  191. data/test/cases/associations_test.rb +0 -282
  192. data/test/cases/attribute_methods_test.rb +0 -305
  193. data/test/cases/autosave_association_test.rb +0 -1218
  194. data/test/cases/base_test.rb +0 -2166
  195. data/test/cases/batches_test.rb +0 -81
  196. data/test/cases/binary_test.rb +0 -30
  197. data/test/cases/calculations_test.rb +0 -360
  198. data/test/cases/callbacks_observers_test.rb +0 -38
  199. data/test/cases/callbacks_test.rb +0 -438
  200. data/test/cases/class_inheritable_attributes_test.rb +0 -32
  201. data/test/cases/column_alias_test.rb +0 -17
  202. data/test/cases/column_definition_test.rb +0 -70
  203. data/test/cases/connection_pool_test.rb +0 -25
  204. data/test/cases/connection_test_firebird.rb +0 -8
  205. data/test/cases/connection_test_mysql.rb +0 -65
  206. data/test/cases/copy_table_test_sqlite.rb +0 -80
  207. data/test/cases/counter_cache_test.rb +0 -84
  208. data/test/cases/database_statements_test.rb +0 -12
  209. data/test/cases/datatype_test_postgresql.rb +0 -204
  210. data/test/cases/date_time_test.rb +0 -37
  211. data/test/cases/default_test_firebird.rb +0 -16
  212. data/test/cases/defaults_test.rb +0 -111
  213. data/test/cases/deprecated_finder_test.rb +0 -30
  214. data/test/cases/dirty_test.rb +0 -316
  215. data/test/cases/finder_respond_to_test.rb +0 -76
  216. data/test/cases/finder_test.rb +0 -1098
  217. data/test/cases/fixtures_test.rb +0 -661
  218. data/test/cases/helper.rb +0 -68
  219. data/test/cases/i18n_test.rb +0 -46
  220. data/test/cases/inheritance_test.rb +0 -262
  221. data/test/cases/invalid_date_test.rb +0 -24
  222. data/test/cases/json_serialization_test.rb +0 -219
  223. data/test/cases/lifecycle_test.rb +0 -193
  224. data/test/cases/locking_test.rb +0 -350
  225. data/test/cases/method_scoping_test.rb +0 -704
  226. data/test/cases/migration_test.rb +0 -1649
  227. data/test/cases/migration_test_firebird.rb +0 -124
  228. data/test/cases/mixin_test.rb +0 -96
  229. data/test/cases/modules_test.rb +0 -109
  230. data/test/cases/multiple_db_test.rb +0 -85
  231. data/test/cases/named_scope_test.rb +0 -372
  232. data/test/cases/nested_attributes_test.rb +0 -840
  233. data/test/cases/pk_test.rb +0 -119
  234. data/test/cases/pooled_connections_test.rb +0 -103
  235. data/test/cases/query_cache_test.rb +0 -129
  236. data/test/cases/readonly_test.rb +0 -107
  237. data/test/cases/reflection_test.rb +0 -234
  238. data/test/cases/reload_models_test.rb +0 -22
  239. data/test/cases/repair_helper.rb +0 -50
  240. data/test/cases/reserved_word_test_mysql.rb +0 -176
  241. data/test/cases/sanitize_test.rb +0 -25
  242. data/test/cases/schema_authorization_test_postgresql.rb +0 -75
  243. data/test/cases/schema_dumper_test.rb +0 -211
  244. data/test/cases/schema_test_postgresql.rb +0 -178
  245. data/test/cases/serialization_test.rb +0 -47
  246. data/test/cases/sp_test_mysql.rb +0 -16
  247. data/test/cases/synonym_test_oracle.rb +0 -17
  248. data/test/cases/timestamp_test.rb +0 -75
  249. data/test/cases/transactions_test.rb +0 -543
  250. data/test/cases/unconnected_test.rb +0 -32
  251. data/test/cases/validations_i18n_test.rb +0 -925
  252. data/test/cases/validations_test.rb +0 -1684
  253. data/test/cases/xml_serialization_test.rb +0 -240
  254. data/test/cases/yaml_serialization_test.rb +0 -11
  255. data/test/config.rb +0 -5
  256. data/test/connections/jdbc_jdbcderby/connection.rb +0 -18
  257. data/test/connections/jdbc_jdbch2/connection.rb +0 -18
  258. data/test/connections/jdbc_jdbchsqldb/connection.rb +0 -18
  259. data/test/connections/jdbc_jdbcmysql/connection.rb +0 -26
  260. data/test/connections/jdbc_jdbcpostgresql/connection.rb +0 -26
  261. data/test/connections/jdbc_jdbcsqlite3/connection.rb +0 -25
  262. data/test/connections/native_db2/connection.rb +0 -25
  263. data/test/connections/native_firebird/connection.rb +0 -26
  264. data/test/connections/native_frontbase/connection.rb +0 -27
  265. data/test/connections/native_mysql/connection.rb +0 -25
  266. data/test/connections/native_openbase/connection.rb +0 -21
  267. data/test/connections/native_oracle/connection.rb +0 -27
  268. data/test/connections/native_postgresql/connection.rb +0 -21
  269. data/test/connections/native_sqlite/connection.rb +0 -25
  270. data/test/connections/native_sqlite3/connection.rb +0 -25
  271. data/test/connections/native_sqlite3/in_memory_connection.rb +0 -18
  272. data/test/connections/native_sybase/connection.rb +0 -23
  273. data/test/fixtures/accounts.yml +0 -29
  274. data/test/fixtures/all/developers.yml +0 -0
  275. data/test/fixtures/all/people.csv +0 -0
  276. data/test/fixtures/all/tasks.yml +0 -0
  277. data/test/fixtures/author_addresses.yml +0 -5
  278. data/test/fixtures/author_favorites.yml +0 -4
  279. data/test/fixtures/authors.yml +0 -9
  280. data/test/fixtures/binaries.yml +0 -132
  281. data/test/fixtures/books.yml +0 -7
  282. data/test/fixtures/categories/special_categories.yml +0 -9
  283. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +0 -4
  284. data/test/fixtures/categories.yml +0 -14
  285. data/test/fixtures/categories_ordered.yml +0 -7
  286. data/test/fixtures/categories_posts.yml +0 -23
  287. data/test/fixtures/categorizations.yml +0 -17
  288. data/test/fixtures/clubs.yml +0 -6
  289. data/test/fixtures/comments.yml +0 -59
  290. data/test/fixtures/companies.yml +0 -56
  291. data/test/fixtures/computers.yml +0 -4
  292. data/test/fixtures/courses.yml +0 -7
  293. data/test/fixtures/customers.yml +0 -26
  294. data/test/fixtures/developers.yml +0 -21
  295. data/test/fixtures/developers_projects.yml +0 -17
  296. data/test/fixtures/edges.yml +0 -6
  297. data/test/fixtures/entrants.yml +0 -14
  298. data/test/fixtures/faces.yml +0 -11
  299. data/test/fixtures/fk_test_has_fk.yml +0 -3
  300. data/test/fixtures/fk_test_has_pk.yml +0 -2
  301. data/test/fixtures/funny_jokes.yml +0 -10
  302. data/test/fixtures/interests.yml +0 -33
  303. data/test/fixtures/items.yml +0 -4
  304. data/test/fixtures/jobs.yml +0 -7
  305. data/test/fixtures/legacy_things.yml +0 -3
  306. data/test/fixtures/mateys.yml +0 -4
  307. data/test/fixtures/member_types.yml +0 -6
  308. data/test/fixtures/members.yml +0 -6
  309. data/test/fixtures/memberships.yml +0 -20
  310. data/test/fixtures/men.yml +0 -5
  311. data/test/fixtures/minimalistics.yml +0 -2
  312. data/test/fixtures/mixed_case_monkeys.yml +0 -6
  313. data/test/fixtures/mixins.yml +0 -29
  314. data/test/fixtures/movies.yml +0 -7
  315. data/test/fixtures/naked/csv/accounts.csv +0 -1
  316. data/test/fixtures/naked/yml/accounts.yml +0 -1
  317. data/test/fixtures/naked/yml/companies.yml +0 -1
  318. data/test/fixtures/naked/yml/courses.yml +0 -1
  319. data/test/fixtures/organizations.yml +0 -5
  320. data/test/fixtures/owners.yml +0 -7
  321. data/test/fixtures/parrots.yml +0 -27
  322. data/test/fixtures/parrots_pirates.yml +0 -7
  323. data/test/fixtures/people.yml +0 -15
  324. data/test/fixtures/pets.yml +0 -14
  325. data/test/fixtures/pirates.yml +0 -9
  326. data/test/fixtures/polymorphic_designs.yml +0 -19
  327. data/test/fixtures/polymorphic_prices.yml +0 -19
  328. data/test/fixtures/posts.yml +0 -52
  329. data/test/fixtures/price_estimates.yml +0 -7
  330. data/test/fixtures/projects.yml +0 -7
  331. data/test/fixtures/readers.yml +0 -9
  332. data/test/fixtures/references.yml +0 -17
  333. data/test/fixtures/reserved_words/distinct.yml +0 -5
  334. data/test/fixtures/reserved_words/distincts_selects.yml +0 -11
  335. data/test/fixtures/reserved_words/group.yml +0 -14
  336. data/test/fixtures/reserved_words/select.yml +0 -8
  337. data/test/fixtures/reserved_words/values.yml +0 -7
  338. data/test/fixtures/ships.yml +0 -5
  339. data/test/fixtures/sponsors.yml +0 -9
  340. data/test/fixtures/subscribers.yml +0 -7
  341. data/test/fixtures/subscriptions.yml +0 -12
  342. data/test/fixtures/taggings.yml +0 -28
  343. data/test/fixtures/tags.yml +0 -7
  344. data/test/fixtures/tasks.yml +0 -7
  345. data/test/fixtures/tees.yml +0 -4
  346. data/test/fixtures/ties.yml +0 -4
  347. data/test/fixtures/topics.yml +0 -42
  348. data/test/fixtures/toys.yml +0 -4
  349. data/test/fixtures/treasures.yml +0 -10
  350. data/test/fixtures/vertices.yml +0 -4
  351. data/test/fixtures/warehouse-things.yml +0 -3
  352. data/test/fixtures/zines.yml +0 -5
  353. data/test/migrations/broken/100_migration_that_raises_exception.rb +0 -10
  354. data/test/migrations/decimal/1_give_me_big_numbers.rb +0 -15
  355. data/test/migrations/duplicate/1_people_have_last_names.rb +0 -9
  356. data/test/migrations/duplicate/2_we_need_reminders.rb +0 -12
  357. data/test/migrations/duplicate/3_foo.rb +0 -7
  358. data/test/migrations/duplicate/3_innocent_jointable.rb +0 -12
  359. data/test/migrations/duplicate_names/20080507052938_chunky.rb +0 -7
  360. data/test/migrations/duplicate_names/20080507053028_chunky.rb +0 -7
  361. data/test/migrations/interleaved/pass_1/3_innocent_jointable.rb +0 -12
  362. data/test/migrations/interleaved/pass_2/1_people_have_last_names.rb +0 -9
  363. data/test/migrations/interleaved/pass_2/3_innocent_jointable.rb +0 -12
  364. data/test/migrations/interleaved/pass_3/1_people_have_last_names.rb +0 -9
  365. data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +0 -8
  366. data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +0 -12
  367. data/test/migrations/missing/1000_people_have_middle_names.rb +0 -9
  368. data/test/migrations/missing/1_people_have_last_names.rb +0 -9
  369. data/test/migrations/missing/3_we_need_reminders.rb +0 -12
  370. data/test/migrations/missing/4_innocent_jointable.rb +0 -12
  371. data/test/migrations/valid/1_people_have_last_names.rb +0 -9
  372. data/test/migrations/valid/2_we_need_reminders.rb +0 -12
  373. data/test/migrations/valid/3_innocent_jointable.rb +0 -12
  374. data/test/models/author.rb +0 -151
  375. data/test/models/auto_id.rb +0 -4
  376. data/test/models/binary.rb +0 -2
  377. data/test/models/bird.rb +0 -9
  378. data/test/models/book.rb +0 -4
  379. data/test/models/categorization.rb +0 -5
  380. data/test/models/category.rb +0 -34
  381. data/test/models/citation.rb +0 -6
  382. data/test/models/club.rb +0 -13
  383. data/test/models/column_name.rb +0 -3
  384. data/test/models/comment.rb +0 -29
  385. data/test/models/company.rb +0 -173
  386. data/test/models/company_in_module.rb +0 -78
  387. data/test/models/computer.rb +0 -3
  388. data/test/models/contact.rb +0 -16
  389. data/test/models/contract.rb +0 -5
  390. data/test/models/course.rb +0 -3
  391. data/test/models/customer.rb +0 -73
  392. data/test/models/default.rb +0 -2
  393. data/test/models/developer.rb +0 -101
  394. data/test/models/edge.rb +0 -5
  395. data/test/models/entrant.rb +0 -3
  396. data/test/models/essay.rb +0 -3
  397. data/test/models/event.rb +0 -3
  398. data/test/models/event_author.rb +0 -8
  399. data/test/models/face.rb +0 -7
  400. data/test/models/guid.rb +0 -2
  401. data/test/models/interest.rb +0 -5
  402. data/test/models/invoice.rb +0 -4
  403. data/test/models/item.rb +0 -7
  404. data/test/models/job.rb +0 -5
  405. data/test/models/joke.rb +0 -3
  406. data/test/models/keyboard.rb +0 -3
  407. data/test/models/legacy_thing.rb +0 -3
  408. data/test/models/line_item.rb +0 -3
  409. data/test/models/man.rb +0 -9
  410. data/test/models/matey.rb +0 -4
  411. data/test/models/member.rb +0 -12
  412. data/test/models/member_detail.rb +0 -5
  413. data/test/models/member_type.rb +0 -3
  414. data/test/models/membership.rb +0 -9
  415. data/test/models/minimalistic.rb +0 -2
  416. data/test/models/mixed_case_monkey.rb +0 -3
  417. data/test/models/movie.rb +0 -5
  418. data/test/models/order.rb +0 -4
  419. data/test/models/organization.rb +0 -6
  420. data/test/models/owner.rb +0 -5
  421. data/test/models/parrot.rb +0 -22
  422. data/test/models/person.rb +0 -16
  423. data/test/models/pet.rb +0 -5
  424. data/test/models/pirate.rb +0 -80
  425. data/test/models/polymorphic_design.rb +0 -3
  426. data/test/models/polymorphic_price.rb +0 -3
  427. data/test/models/post.rb +0 -102
  428. data/test/models/price_estimate.rb +0 -3
  429. data/test/models/project.rb +0 -30
  430. data/test/models/reader.rb +0 -4
  431. data/test/models/reference.rb +0 -4
  432. data/test/models/reply.rb +0 -46
  433. data/test/models/ship.rb +0 -19
  434. data/test/models/ship_part.rb +0 -7
  435. data/test/models/sponsor.rb +0 -4
  436. data/test/models/subject.rb +0 -4
  437. data/test/models/subscriber.rb +0 -8
  438. data/test/models/subscription.rb +0 -4
  439. data/test/models/tag.rb +0 -7
  440. data/test/models/tagging.rb +0 -10
  441. data/test/models/task.rb +0 -3
  442. data/test/models/tee.rb +0 -4
  443. data/test/models/tie.rb +0 -4
  444. data/test/models/topic.rb +0 -80
  445. data/test/models/toy.rb +0 -6
  446. data/test/models/treasure.rb +0 -8
  447. data/test/models/vertex.rb +0 -9
  448. data/test/models/warehouse_thing.rb +0 -5
  449. data/test/models/zine.rb +0 -3
  450. data/test/schema/mysql_specific_schema.rb +0 -31
  451. data/test/schema/postgresql_specific_schema.rb +0 -114
  452. data/test/schema/schema.rb +0 -550
  453. data/test/schema/schema2.rb +0 -6
  454. data/test/schema/sqlite_specific_schema.rb +0 -25
@@ -1,8 +1,11 @@
1
+ require 'active_support/core_ext/array/wrap'
2
+ require 'active_support/deprecation/reporting'
3
+
1
4
  module ActiveRecord
2
5
  module ConnectionAdapters # :nodoc:
3
6
  module SchemaStatements
4
7
  # Returns a Hash of mappings from the abstract data types to the native
5
- # database types. See TableDefinition#column for details on the recognized
8
+ # database types. See TableDefinition#column for details on the recognized
6
9
  # abstract data types.
7
10
  def native_database_types
8
11
  {}
@@ -10,11 +13,13 @@ module ActiveRecord
10
13
 
11
14
  # Truncates a table alias according to the limits of the current adapter.
12
15
  def table_alias_for(table_name)
13
- table_name[0..table_alias_length-1].gsub(/\./, '_')
16
+ table_name[0...table_alias_length].gsub(/\./, '_')
14
17
  end
15
18
 
16
- # def tables(name = nil) end
17
-
19
+ # Checks to see if the table +table_name+ exists on the database.
20
+ #
21
+ # === Example
22
+ # table_exists?(:developers)
18
23
  def table_exists?(table_name)
19
24
  tables.include?(table_name.to_s)
20
25
  end
@@ -22,25 +27,76 @@ module ActiveRecord
22
27
  # Returns an array of indexes for the given table.
23
28
  # def indexes(table_name, name = nil) end
24
29
 
30
+ # Checks to see if an index exists on a table for a given index definition.
31
+ #
32
+ # === Examples
33
+ # # Check an index exists
34
+ # index_exists?(:suppliers, :company_id)
35
+ #
36
+ # # Check an index on multiple columns exists
37
+ # index_exists?(:suppliers, [:company_id, :company_type])
38
+ #
39
+ # # Check a unique index exists
40
+ # index_exists?(:suppliers, :company_id, :unique => true)
41
+ #
42
+ # # Check an index with a custom name exists
43
+ # index_exists?(:suppliers, :company_id, :name => "idx_company_id"
44
+ def index_exists?(table_name, column_name, options = {})
45
+ column_names = Array.wrap(column_name)
46
+ index_name = options.key?(:name) ? options[:name].to_s : index_name(table_name, :column => column_names)
47
+ if options[:unique]
48
+ indexes(table_name).any?{ |i| i.unique && i.name == index_name }
49
+ else
50
+ indexes(table_name).any?{ |i| i.name == index_name }
51
+ end
52
+ end
53
+
25
54
  # Returns an array of Column objects for the table specified by +table_name+.
26
55
  # See the concrete implementation for details on the expected parameter values.
27
56
  def columns(table_name, name = nil) end
28
57
 
58
+ # Checks to see if a column exists in a given table.
59
+ #
60
+ # === Examples
61
+ # # Check a column exists
62
+ # column_exists?(:suppliers, :name)
63
+ #
64
+ # # Check a column exists of a particular type
65
+ # column_exists?(:suppliers, :name, :string)
66
+ #
67
+ # # Check a column exists with a specific definition
68
+ # column_exists?(:suppliers, :name, :string, :limit => 100)
69
+ def column_exists?(table_name, column_name, type = nil, options = {})
70
+ columns(table_name).any?{ |c| c.name == column_name.to_s &&
71
+ (!type || c.type == type) &&
72
+ (!options[:limit] || c.limit == options[:limit]) &&
73
+ (!options[:precision] || c.precision == options[:precision]) &&
74
+ (!options[:scale] || c.scale == options[:scale]) }
75
+ end
76
+
29
77
  # Creates a new table with the name +table_name+. +table_name+ may either
30
78
  # be a String or a Symbol.
31
79
  #
32
- # There are two ways to work with +create_table+. You can use the block
80
+ # There are two ways to work with +create_table+. You can use the block
33
81
  # form or the regular form, like this:
34
82
  #
35
83
  # === Block form
36
84
  # # create_table() passes a TableDefinition object to the block.
37
85
  # # This form will not only create the table, but also columns for the
38
86
  # # table.
87
+ #
39
88
  # create_table(:suppliers) do |t|
40
89
  # t.column :name, :string, :limit => 60
41
90
  # # Other fields here
42
91
  # end
43
92
  #
93
+ # === Block form, with shorthand
94
+ # # You can also use the column types as method calls, rather than calling the column method.
95
+ # create_table(:suppliers) do |t|
96
+ # t.string :name, :limit => 60
97
+ # # Other fields here
98
+ # end
99
+ #
44
100
  # === Regular form
45
101
  # # Creates a table called 'suppliers' with no columns.
46
102
  # create_table(:suppliers)
@@ -50,10 +106,15 @@ module ActiveRecord
50
106
  # The +options+ hash can include the following keys:
51
107
  # [<tt>:id</tt>]
52
108
  # Whether to automatically add a primary key column. Defaults to true.
53
- # Join tables for +has_and_belongs_to_many+ should set <tt>:id => false</tt>.
109
+ # Join tables for +has_and_belongs_to_many+ should set it to false.
54
110
  # [<tt>:primary_key</tt>]
55
111
  # The name of the primary key, if one is to be added automatically.
56
- # Defaults to +id+.
112
+ # Defaults to +id+. If <tt>:id</tt> is false this option is ignored.
113
+ #
114
+ # Also note that this just sets the primary key in the table. You additionally
115
+ # need to configure the primary key in the model via +self.primary_key=+.
116
+ # Models do NOT auto-detect the primary key from their table definition.
117
+ #
57
118
  # [<tt>:options</tt>]
58
119
  # Any extra options you want appended to the table definition.
59
120
  # [<tt>:temporary</tt>]
@@ -93,10 +154,10 @@ module ActiveRecord
93
154
  #
94
155
  # See also TableDefinition#column for details on how to create columns.
95
156
  def create_table(table_name, options = {})
96
- table_definition = TableDefinition.new(self)
97
- table_definition.primary_key(options[:primary_key] || Base.get_primary_key(table_name.to_s.singularize)) unless options[:id] == false
157
+ td = table_definition
158
+ td.primary_key(options[:primary_key] || Base.get_primary_key(table_name.to_s.singularize)) unless options[:id] == false
98
159
 
99
- yield table_definition if block_given?
160
+ yield td if block_given?
100
161
 
101
162
  if options[:force] && table_exists?(table_name)
102
163
  drop_table(table_name, options)
@@ -104,7 +165,7 @@ module ActiveRecord
104
165
 
105
166
  create_sql = "CREATE#{' TEMPORARY' if options[:temporary]} TABLE "
106
167
  create_sql << "#{quote_table_name(table_name)} ("
107
- create_sql << table_definition.to_sql
168
+ create_sql << td.to_sql
108
169
  create_sql << ") #{options[:options]}"
109
170
  execute create_sql
110
171
  end
@@ -118,6 +179,13 @@ module ActiveRecord
118
179
  # # Other column alterations here
119
180
  # end
120
181
  #
182
+ # The +options+ hash can include the following keys:
183
+ # [<tt>:bulk</tt>]
184
+ # Set this to true to make this a bulk alter query, such as
185
+ # ALTER TABLE `users` ADD COLUMN age INT(11), ADD COLUMN birthdate DATETIME ...
186
+ #
187
+ # Defaults to false.
188
+ #
121
189
  # ===== Examples
122
190
  # ====== Add a column
123
191
  # change_table(:suppliers) do |t|
@@ -166,8 +234,14 @@ module ActiveRecord
166
234
  #
167
235
  # See also Table for details on
168
236
  # all of the various column transformation
169
- def change_table(table_name)
170
- yield Table.new(table_name, self)
237
+ def change_table(table_name, options = {})
238
+ if supports_bulk_alter? && options[:bulk]
239
+ recorder = ActiveRecord::Migration::CommandRecorder.new(self)
240
+ yield Table.new(table_name, recorder)
241
+ bulk_change_table(table_name, recorder.commands)
242
+ else
243
+ yield Table.new(table_name, self)
244
+ end
171
245
  end
172
246
 
173
247
  # Renames a table.
@@ -195,9 +269,14 @@ module ActiveRecord
195
269
  # remove_column(:suppliers, :qualification)
196
270
  # remove_columns(:suppliers, :qualification, :experience)
197
271
  def remove_column(table_name, *column_names)
198
- raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.empty?
199
- column_names.flatten.each do |column_name|
200
- execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{quote_column_name(column_name)}"
272
+ if column_names.flatten!
273
+ message = 'Passing array to remove_columns is deprecated, please use ' +
274
+ 'multiple arguments, like: `remove_columns(:posts, :foo, :bar)`'
275
+ ActiveSupport::Deprecation.warn message, caller
276
+ end
277
+
278
+ columns_for_remove(table_name, *column_names).each do |column_name|
279
+ execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{column_name}"
201
280
  end
202
281
  end
203
282
  alias :remove_columns :remove_column
@@ -211,12 +290,11 @@ module ActiveRecord
211
290
  raise NotImplementedError, "change_column is not implemented"
212
291
  end
213
292
 
214
- # Sets a new default value for a column. If you want to set the default
215
- # value to +NULL+, you are out of luck. You need to
216
- # DatabaseStatements#execute the appropriate SQL statement yourself.
293
+ # Sets a new default value for a column.
217
294
  # ===== Examples
218
295
  # change_column_default(:suppliers, :qualification, 'new')
219
296
  # change_column_default(:accounts, :authorized, 1)
297
+ # change_column_default(:users, :email, nil)
220
298
  def change_column_default(table_name, column_name, default)
221
299
  raise NotImplementedError, "change_column_default is not implemented"
222
300
  end
@@ -228,18 +306,11 @@ module ActiveRecord
228
306
  raise NotImplementedError, "rename_column is not implemented"
229
307
  end
230
308
 
231
- # Adds a new index to the table. +column_name+ can be a single Symbol, or
309
+ # Adds a new index to the table. +column_name+ can be a single Symbol, or
232
310
  # an Array of Symbols.
233
311
  #
234
- # The index will be named after the table and the first column name,
235
- # unless you pass <tt>:name</tt> as an option.
236
- #
237
- # When creating an index on multiple columns, the first column is used as a name
238
- # for the index. For example, when you specify an index on two columns
239
- # [<tt>:first</tt>, <tt>:last</tt>], the DBMS creates an index for both columns as well as an
240
- # index for the first column <tt>:first</tt>. Using just the first name for this index
241
- # makes sense, because you will never have to create a singular index with this
242
- # name.
312
+ # The index will be named after the table and the column name(s), unless
313
+ # you pass <tt>:name</tt> as an option.
243
314
  #
244
315
  # ===== Examples
245
316
  #
@@ -268,51 +339,35 @@ module ActiveRecord
268
339
  # CREATE INDEX by_name_surname ON accounts(name(10), surname(15))
269
340
  #
270
341
  # Note: SQLite doesn't support index length
342
+ #
343
+ # ====== Creating an index with a sort order (desc or asc, asc is the default)
344
+ # add_index(:accounts, [:branch_id, :party_id, :surname], :order => {:branch_id => :desc, :part_id => :asc})
345
+ # generates
346
+ # CREATE INDEX by_branch_desc_party ON accounts(branch_id DESC, party_id ASC, surname)
347
+ #
348
+ # Note: mysql doesn't yet support index order (it accepts the syntax but ignores it)
349
+ #
271
350
  def add_index(table_name, column_name, options = {})
272
- column_names = Array(column_name)
273
- index_name = index_name(table_name, :column => column_names)
274
-
275
- if Hash === options # legacy support, since this param was a string
276
- index_type = options[:unique] ? "UNIQUE" : ""
277
- index_name = options[:name].to_s if options[:name]
278
- else
279
- index_type = options
280
- end
281
-
282
- if index_name.length > index_name_length
283
- @logger.warn("Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{index_name_length} characters. Skipping.")
284
- return
285
- end
286
- if index_exists?(table_name, index_name, false)
287
- @logger.warn("Index name '#{index_name}' on table '#{table_name}' already exists. Skipping.")
288
- return
289
- end
290
- quoted_column_names = quoted_columns_for_index(column_names, options).join(", ")
291
-
292
- execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})"
351
+ index_name, index_type, index_columns = add_index_options(table_name, column_name, options)
352
+ execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{index_columns})"
293
353
  end
294
354
 
295
355
  # Remove the given index from the table.
296
356
  #
297
- # Remove the suppliers_name_index in the suppliers table.
298
- # remove_index :suppliers, :name
299
- # Remove the index named accounts_branch_id_index in the accounts table.
357
+ # Remove the index_accounts_on_column in the accounts table.
358
+ # remove_index :accounts, :column
359
+ # Remove the index named index_accounts_on_branch_id in the accounts table.
300
360
  # remove_index :accounts, :column => :branch_id
301
- # Remove the index named accounts_branch_id_party_id_index in the accounts table.
361
+ # Remove the index named index_accounts_on_branch_id_and_party_id in the accounts table.
302
362
  # remove_index :accounts, :column => [:branch_id, :party_id]
303
363
  # Remove the index named by_branch_party in the accounts table.
304
364
  # remove_index :accounts, :name => :by_branch_party
305
365
  def remove_index(table_name, options = {})
306
- index_name = index_name(table_name, options)
307
- unless index_exists?(table_name, index_name, true)
308
- @logger.warn("Index name '#{index_name}' on table '#{table_name}' does not exist. Skipping.")
309
- return
310
- end
311
- remove_index!(table_name, index_name)
366
+ remove_index!(table_name, index_name_for_remove(table_name, options))
312
367
  end
313
368
 
314
369
  def remove_index!(table_name, index_name) #:nodoc:
315
- execute "DROP INDEX #{quote_column_name(index_name)} ON #{table_name}"
370
+ execute "DROP INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)}"
316
371
  end
317
372
 
318
373
  # Rename an index.
@@ -330,7 +385,7 @@ module ActiveRecord
330
385
  def index_name(table_name, options) #:nodoc:
331
386
  if Hash === options # legacy support
332
387
  if options[:column]
333
- "index_#{table_name}_on_#{Array(options[:column]) * '_and_'}"
388
+ "index_#{table_name}_on_#{Array.wrap(options[:column]) * '_and_'}"
334
389
  elsif options[:name]
335
390
  options[:name]
336
391
  else
@@ -341,11 +396,11 @@ module ActiveRecord
341
396
  end
342
397
  end
343
398
 
344
- # Verify the existence of an index.
399
+ # Verify the existence of an index with a given name.
345
400
  #
346
401
  # The default argument is returned if the underlying implementation does not define the indexes method,
347
402
  # as there's no way to determine the correct answer in that case.
348
- def index_exists?(table_name, index_name, default)
403
+ def index_name_exists?(table_name, index_name, default)
349
404
  return default unless respond_to?(:indexes)
350
405
  index_name = index_name.to_s
351
406
  indexes(table_name).detect { |i| i.name == index_name }
@@ -358,7 +413,7 @@ module ActiveRecord
358
413
 
359
414
  def dump_schema_information #:nodoc:
360
415
  sm_table = ActiveRecord::Migrator.schema_migrations_table_name
361
- migrated = select_values("SELECT version FROM #{sm_table}")
416
+ migrated = select_values("SELECT version FROM #{sm_table} ORDER BY version")
362
417
  migrated.map { |v| "INSERT INTO #{sm_table} (version) VALUES ('#{v}');" }.join("\n\n")
363
418
  end
364
419
 
@@ -367,7 +422,7 @@ module ActiveRecord
367
422
  def initialize_schema_migrations_table
368
423
  sm_table = ActiveRecord::Migrator.schema_migrations_table_name
369
424
 
370
- unless tables.detect { |t| t == sm_table }
425
+ unless table_exists?(sm_table)
371
426
  create_table(sm_table, :id => false) do |schema_migrations_table|
372
427
  schema_migrations_table.column :version, :string, :null => false
373
428
  end
@@ -378,7 +433,8 @@ module ActiveRecord
378
433
  # migrated up to that point:
379
434
  si_table = Base.table_name_prefix + 'schema_info' + Base.table_name_suffix
380
435
 
381
- if tables.detect { |t| t == si_table }
436
+ if table_exists?(si_table)
437
+ ActiveSupport::Deprecation.warn "Usage of the schema table `#{si_table}` is deprecated. Please switch to using `schema_migrations` table"
382
438
 
383
439
  old_version = select_value("SELECT version FROM #{quote_table_name(si_table)}").to_i
384
440
  assume_migrated_upto_version(old_version)
@@ -387,12 +443,14 @@ module ActiveRecord
387
443
  end
388
444
  end
389
445
 
390
- def assume_migrated_upto_version(version, migrations_path = ActiveRecord::Migrator.migrations_path)
446
+ def assume_migrated_upto_version(version, migrations_paths = ActiveRecord::Migrator.migrations_paths)
447
+ migrations_paths = Array.wrap(migrations_paths)
391
448
  version = version.to_i
392
449
  sm_table = quote_table_name(ActiveRecord::Migrator.schema_migrations_table_name)
393
450
 
394
- migrated = select_values("SELECT version FROM #{sm_table}").map(&:to_i)
395
- versions = Dir["#{migrations_path}/[0-9]*_*.rb"].map do |filename|
451
+ migrated = select_values("SELECT version FROM #{sm_table}").map { |v| v.to_i }
452
+ paths = migrations_paths.map {|p| "#{p}/[0-9]*_*.rb" }
453
+ versions = Dir[*paths].map do |filename|
396
454
  filename.split('/').last.split('_').first.to_i
397
455
  end
398
456
 
@@ -412,7 +470,7 @@ module ActiveRecord
412
470
  end
413
471
 
414
472
  def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc:
415
- if native = native_database_types[type]
473
+ if native = native_database_types[type.to_sym]
416
474
  column_type_sql = (native.is_a?(Hash) ? native[:name] : native).dup
417
475
 
418
476
  if type == :decimal # ignore limit, use precision and scale
@@ -454,12 +512,6 @@ module ActiveRecord
454
512
  "DISTINCT #{columns}"
455
513
  end
456
514
 
457
- # ORDER BY clause for the passed order option.
458
- # PostgreSQL overrides this due to its stricter standards compliance.
459
- def add_order_by_for_association_limiting!(sql, options)
460
- sql << " ORDER BY #{options[:order]}"
461
- end
462
-
463
515
  # Adds timestamps (created_at and updated_at) columns to the named table.
464
516
  # ===== Examples
465
517
  # add_timestamps(:suppliers)
@@ -477,14 +529,78 @@ module ActiveRecord
477
529
  end
478
530
 
479
531
  protected
532
+ def add_index_sort_order(option_strings, column_names, options = {})
533
+ if options.is_a?(Hash) && order = options[:order]
534
+ case order
535
+ when Hash
536
+ column_names.each {|name| option_strings[name] += " #{order[name].to_s.upcase}" if order.has_key?(name)}
537
+ when String
538
+ column_names.each {|name| option_strings[name] += " #{order.upcase}"}
539
+ end
540
+ end
541
+
542
+ return option_strings
543
+ end
544
+
480
545
  # Overridden by the mysql adapter for supporting index lengths
481
546
  def quoted_columns_for_index(column_names, options = {})
482
- column_names.map {|name| quote_column_name(name) }
547
+ option_strings = Hash[column_names.map {|name| [name, '']}]
548
+
549
+ # add index sort order if supported
550
+ if supports_index_sort_order?
551
+ option_strings = add_index_sort_order(option_strings, column_names, options)
552
+ end
553
+
554
+ column_names.map {|name| quote_column_name(name) + option_strings[name]}
483
555
  end
484
556
 
485
557
  def options_include_default?(options)
486
558
  options.include?(:default) && !(options[:null] == false && options[:default].nil?)
487
559
  end
560
+
561
+ def add_index_options(table_name, column_name, options = {})
562
+ column_names = Array.wrap(column_name)
563
+ index_name = index_name(table_name, :column => column_names)
564
+
565
+ if Hash === options # legacy support, since this param was a string
566
+ index_type = options[:unique] ? "UNIQUE" : ""
567
+ index_name = options[:name].to_s if options.key?(:name)
568
+ else
569
+ index_type = options
570
+ end
571
+
572
+ if index_name.length > index_name_length
573
+ raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{index_name_length} characters"
574
+ end
575
+ if index_name_exists?(table_name, index_name, false)
576
+ raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
577
+ end
578
+ index_columns = quoted_columns_for_index(column_names, options).join(", ")
579
+
580
+ [index_name, index_type, index_columns]
581
+ end
582
+
583
+ def index_name_for_remove(table_name, options = {})
584
+ index_name = index_name(table_name, options)
585
+
586
+ unless index_name_exists?(table_name, index_name, true)
587
+ raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' does not exist"
588
+ end
589
+
590
+ index_name
591
+ end
592
+
593
+ def columns_for_remove(table_name, *column_names)
594
+ column_names = column_names.flatten
595
+
596
+ raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.blank?
597
+ column_names.map {|column_name| quote_column_name(column_name) }
598
+ end
599
+
600
+ private
601
+ def table_definition
602
+ TableDefinition.new(self)
603
+ end
488
604
  end
489
605
  end
490
606
  end