activerecord 3.2.19 → 5.0.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 (264) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1715 -604
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +40 -45
  5. data/examples/performance.rb +33 -22
  6. data/examples/simple.rb +3 -4
  7. data/lib/active_record/aggregations.rb +76 -51
  8. data/lib/active_record/association_relation.rb +35 -0
  9. data/lib/active_record/associations/alias_tracker.rb +54 -40
  10. data/lib/active_record/associations/association.rb +76 -56
  11. data/lib/active_record/associations/association_scope.rb +125 -93
  12. data/lib/active_record/associations/belongs_to_association.rb +57 -28
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -2
  14. data/lib/active_record/associations/builder/association.rb +120 -32
  15. data/lib/active_record/associations/builder/belongs_to.rb +115 -62
  16. data/lib/active_record/associations/builder/collection_association.rb +61 -53
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +117 -43
  18. data/lib/active_record/associations/builder/has_many.rb +9 -65
  19. data/lib/active_record/associations/builder/has_one.rb +18 -52
  20. data/lib/active_record/associations/builder/singular_association.rb +18 -19
  21. data/lib/active_record/associations/collection_association.rb +268 -186
  22. data/lib/active_record/associations/collection_proxy.rb +1003 -63
  23. data/lib/active_record/associations/foreign_association.rb +11 -0
  24. data/lib/active_record/associations/has_many_association.rb +81 -41
  25. data/lib/active_record/associations/has_many_through_association.rb +76 -55
  26. data/lib/active_record/associations/has_one_association.rb +51 -21
  27. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  28. data/lib/active_record/associations/join_dependency/join_association.rb +83 -108
  29. data/lib/active_record/associations/join_dependency/join_base.rb +7 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +30 -37
  31. data/lib/active_record/associations/join_dependency.rb +239 -155
  32. data/lib/active_record/associations/preloader/association.rb +97 -62
  33. data/lib/active_record/associations/preloader/collection_association.rb +2 -8
  34. data/lib/active_record/associations/preloader/has_many_through.rb +7 -3
  35. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  36. data/lib/active_record/associations/preloader/singular_association.rb +3 -3
  37. data/lib/active_record/associations/preloader/through_association.rb +75 -33
  38. data/lib/active_record/associations/preloader.rb +111 -79
  39. data/lib/active_record/associations/singular_association.rb +35 -13
  40. data/lib/active_record/associations/through_association.rb +41 -19
  41. data/lib/active_record/associations.rb +727 -501
  42. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  43. data/lib/active_record/attribute.rb +213 -0
  44. data/lib/active_record/attribute_assignment.rb +32 -162
  45. data/lib/active_record/attribute_decorators.rb +67 -0
  46. data/lib/active_record/attribute_methods/before_type_cast.rb +52 -7
  47. data/lib/active_record/attribute_methods/dirty.rb +101 -61
  48. data/lib/active_record/attribute_methods/primary_key.rb +50 -36
  49. data/lib/active_record/attribute_methods/query.rb +7 -6
  50. data/lib/active_record/attribute_methods/read.rb +56 -117
  51. data/lib/active_record/attribute_methods/serialization.rb +43 -96
  52. data/lib/active_record/attribute_methods/time_zone_conversion.rb +93 -42
  53. data/lib/active_record/attribute_methods/write.rb +34 -45
  54. data/lib/active_record/attribute_methods.rb +333 -144
  55. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  56. data/lib/active_record/attribute_set/builder.rb +108 -0
  57. data/lib/active_record/attribute_set.rb +108 -0
  58. data/lib/active_record/attributes.rb +265 -0
  59. data/lib/active_record/autosave_association.rb +285 -223
  60. data/lib/active_record/base.rb +95 -490
  61. data/lib/active_record/callbacks.rb +95 -61
  62. data/lib/active_record/coders/json.rb +13 -0
  63. data/lib/active_record/coders/yaml_column.rb +28 -19
  64. data/lib/active_record/collection_cache_key.rb +40 -0
  65. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +724 -277
  66. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  67. data/lib/active_record/connection_adapters/abstract/database_statements.rb +199 -192
  68. data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -26
  69. data/lib/active_record/connection_adapters/abstract/quoting.rb +140 -57
  70. data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
  71. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +147 -0
  72. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +419 -276
  73. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +105 -0
  74. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +963 -276
  75. data/lib/active_record/connection_adapters/abstract/transaction.rb +232 -0
  76. data/lib/active_record/connection_adapters/abstract_adapter.rb +397 -106
  77. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +643 -342
  78. data/lib/active_record/connection_adapters/column.rb +30 -259
  79. data/lib/active_record/connection_adapters/connection_specification.rb +263 -0
  80. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  81. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  82. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  83. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  84. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  85. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  86. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  87. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  88. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  89. data/lib/active_record/connection_adapters/mysql2_adapter.rb +47 -196
  90. data/lib/active_record/connection_adapters/postgresql/column.rb +15 -0
  91. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +170 -0
  92. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +70 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +48 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +21 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +10 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +39 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +93 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +15 -0
  110. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
  111. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
  112. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  113. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  114. data/lib/active_record/connection_adapters/postgresql/oid.rb +31 -0
  115. data/lib/active_record/connection_adapters/postgresql/quoting.rb +116 -0
  116. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +49 -0
  117. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +180 -0
  118. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  119. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +682 -0
  120. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  121. data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
  122. data/lib/active_record/connection_adapters/postgresql_adapter.rb +558 -1039
  123. data/lib/active_record/connection_adapters/schema_cache.rb +74 -36
  124. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  125. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +538 -24
  129. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  130. data/lib/active_record/connection_handling.rb +155 -0
  131. data/lib/active_record/core.rb +561 -0
  132. data/lib/active_record/counter_cache.rb +146 -105
  133. data/lib/active_record/dynamic_matchers.rb +101 -64
  134. data/lib/active_record/enum.rb +234 -0
  135. data/lib/active_record/errors.rb +153 -56
  136. data/lib/active_record/explain.rb +15 -63
  137. data/lib/active_record/explain_registry.rb +30 -0
  138. data/lib/active_record/explain_subscriber.rb +10 -6
  139. data/lib/active_record/fixture_set/file.rb +77 -0
  140. data/lib/active_record/fixtures.rb +355 -232
  141. data/lib/active_record/gem_version.rb +15 -0
  142. data/lib/active_record/inheritance.rb +144 -79
  143. data/lib/active_record/integration.rb +66 -13
  144. data/lib/active_record/internal_metadata.rb +56 -0
  145. data/lib/active_record/legacy_yaml_adapter.rb +46 -0
  146. data/lib/active_record/locale/en.yml +9 -1
  147. data/lib/active_record/locking/optimistic.rb +77 -56
  148. data/lib/active_record/locking/pessimistic.rb +6 -6
  149. data/lib/active_record/log_subscriber.rb +53 -28
  150. data/lib/active_record/migration/command_recorder.rb +166 -33
  151. data/lib/active_record/migration/compatibility.rb +126 -0
  152. data/lib/active_record/migration/join_table.rb +15 -0
  153. data/lib/active_record/migration.rb +792 -264
  154. data/lib/active_record/model_schema.rb +192 -130
  155. data/lib/active_record/nested_attributes.rb +238 -145
  156. data/lib/active_record/no_touching.rb +52 -0
  157. data/lib/active_record/null_relation.rb +89 -0
  158. data/lib/active_record/persistence.rb +357 -157
  159. data/lib/active_record/query_cache.rb +22 -43
  160. data/lib/active_record/querying.rb +34 -23
  161. data/lib/active_record/railtie.rb +88 -48
  162. data/lib/active_record/railties/console_sandbox.rb +3 -4
  163. data/lib/active_record/railties/controller_runtime.rb +5 -4
  164. data/lib/active_record/railties/databases.rake +170 -422
  165. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  166. data/lib/active_record/readonly_attributes.rb +2 -5
  167. data/lib/active_record/reflection.rb +715 -189
  168. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  169. data/lib/active_record/relation/batches.rb +203 -50
  170. data/lib/active_record/relation/calculations.rb +203 -194
  171. data/lib/active_record/relation/delegation.rb +103 -25
  172. data/lib/active_record/relation/finder_methods.rb +457 -261
  173. data/lib/active_record/relation/from_clause.rb +32 -0
  174. data/lib/active_record/relation/merger.rb +167 -0
  175. data/lib/active_record/relation/predicate_builder/array_handler.rb +43 -0
  176. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  177. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  178. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  179. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  180. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  181. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  182. data/lib/active_record/relation/predicate_builder/relation_handler.rb +13 -0
  183. data/lib/active_record/relation/predicate_builder.rb +153 -48
  184. data/lib/active_record/relation/query_attribute.rb +19 -0
  185. data/lib/active_record/relation/query_methods.rb +1019 -194
  186. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  187. data/lib/active_record/relation/spawn_methods.rb +46 -150
  188. data/lib/active_record/relation/where_clause.rb +174 -0
  189. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  190. data/lib/active_record/relation.rb +450 -245
  191. data/lib/active_record/result.rb +104 -12
  192. data/lib/active_record/runtime_registry.rb +22 -0
  193. data/lib/active_record/sanitization.rb +120 -94
  194. data/lib/active_record/schema.rb +28 -18
  195. data/lib/active_record/schema_dumper.rb +141 -74
  196. data/lib/active_record/schema_migration.rb +50 -0
  197. data/lib/active_record/scoping/default.rb +64 -57
  198. data/lib/active_record/scoping/named.rb +93 -108
  199. data/lib/active_record/scoping.rb +73 -121
  200. data/lib/active_record/secure_token.rb +38 -0
  201. data/lib/active_record/serialization.rb +7 -5
  202. data/lib/active_record/statement_cache.rb +113 -0
  203. data/lib/active_record/store.rb +173 -15
  204. data/lib/active_record/suppressor.rb +58 -0
  205. data/lib/active_record/table_metadata.rb +68 -0
  206. data/lib/active_record/tasks/database_tasks.rb +313 -0
  207. data/lib/active_record/tasks/mysql_database_tasks.rb +151 -0
  208. data/lib/active_record/tasks/postgresql_database_tasks.rb +110 -0
  209. data/lib/active_record/tasks/sqlite_database_tasks.rb +59 -0
  210. data/lib/active_record/timestamp.rb +42 -24
  211. data/lib/active_record/touch_later.rb +58 -0
  212. data/lib/active_record/transactions.rb +233 -105
  213. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  214. data/lib/active_record/type/date.rb +7 -0
  215. data/lib/active_record/type/date_time.rb +7 -0
  216. data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
  217. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  218. data/lib/active_record/type/internal/timezone.rb +15 -0
  219. data/lib/active_record/type/serialized.rb +63 -0
  220. data/lib/active_record/type/time.rb +20 -0
  221. data/lib/active_record/type/type_map.rb +64 -0
  222. data/lib/active_record/type.rb +72 -0
  223. data/lib/active_record/type_caster/connection.rb +29 -0
  224. data/lib/active_record/type_caster/map.rb +19 -0
  225. data/lib/active_record/type_caster.rb +7 -0
  226. data/lib/active_record/validations/absence.rb +23 -0
  227. data/lib/active_record/validations/associated.rb +33 -18
  228. data/lib/active_record/validations/length.rb +24 -0
  229. data/lib/active_record/validations/presence.rb +66 -0
  230. data/lib/active_record/validations/uniqueness.rb +128 -68
  231. data/lib/active_record/validations.rb +48 -40
  232. data/lib/active_record/version.rb +5 -7
  233. data/lib/active_record.rb +71 -47
  234. data/lib/rails/generators/active_record/migration/migration_generator.rb +56 -8
  235. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +24 -0
  236. data/lib/rails/generators/active_record/migration/templates/migration.rb +28 -16
  237. data/lib/rails/generators/active_record/migration.rb +18 -8
  238. data/lib/rails/generators/active_record/model/model_generator.rb +38 -16
  239. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  240. data/lib/rails/generators/active_record/model/templates/model.rb +7 -6
  241. data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
  242. data/lib/rails/generators/active_record.rb +3 -11
  243. metadata +188 -134
  244. data/examples/associations.png +0 -0
  245. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
  246. data/lib/active_record/associations/join_helper.rb +0 -55
  247. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  248. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  249. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  250. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -441
  251. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  252. data/lib/active_record/dynamic_finder_match.rb +0 -68
  253. data/lib/active_record/dynamic_scope_match.rb +0 -23
  254. data/lib/active_record/fixtures/file.rb +0 -65
  255. data/lib/active_record/identity_map.rb +0 -162
  256. data/lib/active_record/observer.rb +0 -121
  257. data/lib/active_record/serializers/xml_serializer.rb +0 -203
  258. data/lib/active_record/session_store.rb +0 -360
  259. data/lib/active_record/test_case.rb +0 -73
  260. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
  261. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  262. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  263. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  264. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,51 +1,197 @@
1
- require 'active_support/core_ext/object/blank'
2
- require 'date'
3
- require 'set'
4
- require 'bigdecimal'
5
- require 'bigdecimal/util'
6
-
7
1
  module ActiveRecord
8
2
  module ConnectionAdapters #:nodoc:
9
- class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders) #:nodoc:
3
+ # Abstract representation of an index definition on a table. Instances of
4
+ # this type are typically created and returned by methods in database
5
+ # adapters. e.g. ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter#indexes
6
+ class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders, :where, :type, :using, :comment) #:nodoc:
10
7
  end
11
8
 
12
9
  # Abstract representation of a column definition. Instances of this type
13
10
  # are typically created by methods in TableDefinition, and added to the
14
11
  # +columns+ attribute of said TableDefinition object, in order to be used
15
12
  # for generating a number of table creation or table changing SQL statements.
16
- class ColumnDefinition < Struct.new(:base, :name, :type, :limit, :precision, :scale, :default, :null) #:nodoc:
13
+ class ColumnDefinition < Struct.new(:name, :type, :limit, :precision, :scale, :default, :null, :first, :after, :auto_increment, :primary_key, :collation, :sql_type, :comment) #:nodoc:
14
+
15
+ def primary_key?
16
+ primary_key || type.to_sym == :primary_key
17
+ end
18
+ end
19
+
20
+ class AddColumnDefinition < Struct.new(:column) # :nodoc:
21
+ end
22
+
23
+ class ChangeColumnDefinition < Struct.new(:column, :name) #:nodoc:
24
+ end
25
+
26
+ class PrimaryKeyDefinition < Struct.new(:name) # :nodoc:
27
+ end
17
28
 
18
- def string_to_binary(value)
19
- value
29
+ class ForeignKeyDefinition < Struct.new(:from_table, :to_table, :options) #:nodoc:
30
+ def name
31
+ options[:name]
20
32
  end
21
33
 
22
- def sql_type
23
- base.type_to_sql(type.to_sym, limit, precision, scale) rescue type
34
+ def column
35
+ options[:column]
24
36
  end
25
37
 
26
- def to_sql
27
- column_sql = "#{base.quote_column_name(name)} #{sql_type}"
28
- column_options = {}
29
- column_options[:null] = null unless null.nil?
30
- column_options[:default] = default unless default.nil?
31
- add_column_options!(column_sql, column_options) unless type.to_sym == :primary_key
32
- column_sql
38
+ def primary_key
39
+ options[:primary_key] || default_primary_key
40
+ end
41
+
42
+ def on_delete
43
+ options[:on_delete]
44
+ end
45
+
46
+ def on_update
47
+ options[:on_update]
48
+ end
49
+
50
+ def custom_primary_key?
51
+ options[:primary_key] != default_primary_key
52
+ end
53
+
54
+ def defined_for?(options_or_to_table = {})
55
+ if options_or_to_table.is_a?(Hash)
56
+ options_or_to_table.all? {|key, value| options[key].to_s == value.to_s }
57
+ else
58
+ to_table == options_or_to_table.to_s
59
+ end
33
60
  end
34
61
 
35
62
  private
63
+ def default_primary_key
64
+ "id"
65
+ end
66
+ end
67
+
68
+ class ReferenceDefinition # :nodoc:
69
+ def initialize(
70
+ name,
71
+ polymorphic: false,
72
+ index: true,
73
+ foreign_key: false,
74
+ type: :integer,
75
+ **options
76
+ )
77
+ @name = name
78
+ @polymorphic = polymorphic
79
+ @index = index
80
+ @foreign_key = foreign_key
81
+ @type = type
82
+ @options = options
83
+
84
+ if polymorphic && foreign_key
85
+ raise ArgumentError, "Cannot add a foreign key to a polymorphic relation"
86
+ end
87
+ end
88
+
89
+ def add_to(table)
90
+ columns.each do |column_options|
91
+ table.column(*column_options)
92
+ end
93
+
94
+ if index
95
+ table.index(column_names, index_options)
96
+ end
36
97
 
37
- def add_column_options!(sql, options)
38
- base.add_column_options!(sql, options.merge(:column => self))
98
+ if foreign_key
99
+ table.foreign_key(foreign_table_name, foreign_key_options)
39
100
  end
101
+ end
102
+
103
+ protected
104
+
105
+ attr_reader :name, :polymorphic, :index, :foreign_key, :type, :options
106
+
107
+ private
108
+
109
+ def as_options(value, default = {})
110
+ if value.is_a?(Hash)
111
+ value
112
+ else
113
+ default
114
+ end
115
+ end
116
+
117
+ def polymorphic_options
118
+ as_options(polymorphic, options)
119
+ end
120
+
121
+ def index_options
122
+ as_options(index)
123
+ end
124
+
125
+ def foreign_key_options
126
+ as_options(foreign_key).merge(column: column_name)
127
+ end
128
+
129
+ def columns
130
+ result = [[column_name, type, options]]
131
+ if polymorphic
132
+ result.unshift(["#{name}_type", :string, polymorphic_options])
133
+ end
134
+ result
135
+ end
136
+
137
+ def column_name
138
+ "#{name}_id"
139
+ end
140
+
141
+ def column_names
142
+ columns.map(&:first)
143
+ end
144
+
145
+ def foreign_table_name
146
+ foreign_key_options.fetch(:to_table) do
147
+ Base.pluralize_table_names ? name.to_s.pluralize : name
148
+ end
149
+ end
150
+ end
151
+
152
+ module ColumnMethods
153
+ # Appends a primary key definition to the table definition.
154
+ # Can be called multiple times, but this is probably not a good idea.
155
+ def primary_key(name, type = :primary_key, **options)
156
+ column(name, type, options.merge(primary_key: true))
157
+ end
158
+
159
+ # Appends a column or columns of a specified type.
160
+ #
161
+ # t.string(:goat)
162
+ # t.string(:goat, :sheep)
163
+ #
164
+ # See TableDefinition#column
165
+ [
166
+ :bigint,
167
+ :binary,
168
+ :boolean,
169
+ :date,
170
+ :datetime,
171
+ :decimal,
172
+ :float,
173
+ :integer,
174
+ :string,
175
+ :text,
176
+ :time,
177
+ :timestamp,
178
+ ].each do |column_type|
179
+ module_eval <<-CODE, __FILE__, __LINE__ + 1
180
+ def #{column_type}(*args, **options)
181
+ args.each { |name| column(name, :#{column_type}, options) }
182
+ end
183
+ CODE
184
+ end
185
+ alias_method :numeric, :decimal
40
186
  end
41
187
 
42
188
  # Represents the schema of an SQL table in an abstract way. This class
43
189
  # provides methods for manipulating the schema representation.
44
190
  #
45
- # Inside migration files, the +t+ object in +create_table+
191
+ # Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
46
192
  # is actually of this type:
47
193
  #
48
- # class SomeMigration < ActiveRecord::Migration
194
+ # class SomeMigration < ActiveRecord::Migration[5.0]
49
195
  # def up
50
196
  # create_table :foo do |t|
51
197
  # puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
@@ -57,33 +203,31 @@ module ActiveRecord
57
203
  # end
58
204
  # end
59
205
  #
60
- # The table definitions
61
- # The Columns are stored as a ColumnDefinition in the +columns+ attribute.
62
206
  class TableDefinition
63
- # An array of ColumnDefinition objects, representing the column changes
64
- # that have been defined.
65
- attr_accessor :columns
207
+ include ColumnMethods
66
208
 
67
- def initialize(base)
68
- @columns = []
209
+ attr_accessor :indexes
210
+ attr_reader :name, :temporary, :options, :as, :foreign_keys, :comment
211
+
212
+ def initialize(name, temporary = false, options = nil, as = nil, comment: nil)
69
213
  @columns_hash = {}
70
- @base = base
214
+ @indexes = {}
215
+ @foreign_keys = []
216
+ @primary_keys = nil
217
+ @temporary = temporary
218
+ @options = options
219
+ @as = as
220
+ @name = name
221
+ @comment = comment
71
222
  end
72
223
 
73
- def xml(*args)
74
- raise NotImplementedError unless %w{
75
- sqlite mysql mysql2
76
- }.include? @base.adapter_name.downcase
77
-
78
- options = args.extract_options!
79
- column(args[0], :text, options)
224
+ def primary_keys(name = nil) # :nodoc:
225
+ @primary_keys = PrimaryKeyDefinition.new(name) if name
226
+ @primary_keys
80
227
  end
81
228
 
82
- # Appends a primary key definition to the table definition.
83
- # Can be called multiple times, but this is probably not a good idea.
84
- def primary_key(name)
85
- column(name, :primary_key)
86
- end
229
+ # Returns an array of ColumnDefinition objects for the columns of the table.
230
+ def columns; @columns_hash.values; end
87
231
 
88
232
  # Returns a ColumnDefinition for the column with name +name+.
89
233
  def [](name)
@@ -91,117 +235,46 @@ module ActiveRecord
91
235
  end
92
236
 
93
237
  # Instantiates a new column for the table.
94
- # The +type+ parameter is normally one of the migrations native types,
95
- # which is one of the following:
96
- # <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>,
97
- # <tt>:integer</tt>, <tt>:float</tt>, <tt>:decimal</tt>,
98
- # <tt>:datetime</tt>, <tt>:timestamp</tt>, <tt>:time</tt>,
99
- # <tt>:date</tt>, <tt>:binary</tt>, <tt>:boolean</tt>.
100
- #
101
- # You may use a type not in this list as long as it is supported by your
102
- # database (for example, "polygon" in MySQL), but this will not be database
103
- # agnostic and should usually be avoided.
104
- #
105
- # Available options are (none of these exists by default):
106
- # * <tt>:limit</tt> -
107
- # Requests a maximum column length. This is number of characters for <tt>:string</tt> and
108
- # <tt>:text</tt> columns and number of bytes for <tt>:binary</tt> and <tt>:integer</tt> columns.
109
- # * <tt>:default</tt> -
110
- # The column's default value. Use nil for NULL.
111
- # * <tt>:null</tt> -
112
- # Allows or disallows +NULL+ values in the column. This option could
113
- # have been named <tt>:null_allowed</tt>.
114
- # * <tt>:precision</tt> -
115
- # Specifies the precision for a <tt>:decimal</tt> column.
116
- # * <tt>:scale</tt> -
117
- # Specifies the scale for a <tt>:decimal</tt> column.
118
- #
119
- # For clarity's sake: the precision is the number of significant digits,
120
- # while the scale is the number of digits that can be stored following
121
- # the decimal point. For example, the number 123.45 has a precision of 5
122
- # and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
123
- # range from -999.99 to 999.99.
124
- #
125
- # Please be aware of different RDBMS implementations behavior with
126
- # <tt>:decimal</tt> columns:
127
- # * The SQL standard says the default scale should be 0, <tt>:scale</tt> <=
128
- # <tt>:precision</tt>, and makes no comments about the requirements of
129
- # <tt>:precision</tt>.
130
- # * MySQL: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..30].
131
- # Default is (10,0).
132
- # * PostgreSQL: <tt>:precision</tt> [1..infinity],
133
- # <tt>:scale</tt> [0..infinity]. No default.
134
- # * SQLite2: Any <tt>:precision</tt> and <tt>:scale</tt> may be used.
135
- # Internal storage as strings. No default.
136
- # * SQLite3: No restrictions on <tt>:precision</tt> and <tt>:scale</tt>,
137
- # but the maximum supported <tt>:precision</tt> is 16. No default.
138
- # * Oracle: <tt>:precision</tt> [1..38], <tt>:scale</tt> [-84..127].
139
- # Default is (38,0).
140
- # * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
141
- # Default unknown.
142
- # * Firebird: <tt>:precision</tt> [1..18], <tt>:scale</tt> [0..18].
143
- # Default (9,0). Internal types NUMERIC and DECIMAL have different
144
- # storage rules, decimal being better.
145
- # * FrontBase?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
146
- # Default (38,0). WARNING Max <tt>:precision</tt>/<tt>:scale</tt> for
147
- # NUMERIC is 19, and DECIMAL is 38.
148
- # * SqlServer?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
149
- # Default (38,0).
150
- # * Sybase: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
151
- # Default (38,0).
152
- # * OpenBase?: Documentation unclear. Claims storage in <tt>double</tt>.
238
+ # See {connection.add_column}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_column]
239
+ # for available options.
240
+ #
241
+ # Additional options are:
242
+ # * <tt>:index</tt> -
243
+ # Create an index for the column. Can be either <tt>true</tt> or an options hash.
153
244
  #
154
245
  # This method returns <tt>self</tt>.
155
246
  #
156
247
  # == Examples
157
- # # Assuming +td+ is an instance of TableDefinition
158
- # td.column(:granted, :boolean)
159
- # # granted BOOLEAN
160
- #
161
- # td.column(:picture, :binary, :limit => 2.megabytes)
162
- # # => picture BLOB(2097152)
163
- #
164
- # td.column(:sales_stage, :string, :limit => 20, :default => 'new', :null => false)
165
- # # => sales_stage VARCHAR(20) DEFAULT 'new' NOT NULL
166
- #
167
- # td.column(:bill_gates_money, :decimal, :precision => 15, :scale => 2)
168
- # # => bill_gates_money DECIMAL(15,2)
169
- #
170
- # td.column(:sensor_reading, :decimal, :precision => 30, :scale => 20)
171
- # # => sensor_reading DECIMAL(30,20)
172
- #
173
- # # While <tt>:scale</tt> defaults to zero on most databases, it
174
- # # probably wouldn't hurt to include it.
175
- # td.column(:huge_integer, :decimal, :precision => 30)
176
- # # => huge_integer DECIMAL(30)
177
248
  #
178
- # # Defines a column with a database-specific type.
179
- # td.column(:foo, 'polygon')
180
- # # => foo polygon
249
+ # # Assuming +td+ is an instance of TableDefinition
250
+ # td.column(:granted, :boolean, index: true)
181
251
  #
182
252
  # == Short-hand examples
183
253
  #
184
- # Instead of calling +column+ directly, you can also work with the short-hand definitions for the default types.
254
+ # Instead of calling #column directly, you can also work with the short-hand definitions for the default types.
185
255
  # They use the type as the method name instead of as a parameter and allow for multiple columns to be defined
186
256
  # in a single statement.
187
257
  #
188
258
  # What can be written like this with the regular calls to column:
189
259
  #
190
- # create_table "products", :force => true do |t|
191
- # t.column "shop_id", :integer
192
- # t.column "creator_id", :integer
193
- # t.column "name", :string, :default => "Untitled"
194
- # t.column "value", :string, :default => "Untitled"
195
- # t.column "created_at", :datetime
196
- # t.column "updated_at", :datetime
260
+ # create_table :products do |t|
261
+ # t.column :shop_id, :integer
262
+ # t.column :creator_id, :integer
263
+ # t.column :item_number, :string
264
+ # t.column :name, :string, default: "Untitled"
265
+ # t.column :value, :string, default: "Untitled"
266
+ # t.column :created_at, :datetime
267
+ # t.column :updated_at, :datetime
197
268
  # end
269
+ # add_index :products, :item_number
198
270
  #
199
- # Can also be written as follows using the short-hand:
271
+ # can also be written as follows using the short-hand:
200
272
  #
201
273
  # create_table :products do |t|
202
274
  # t.integer :shop_id, :creator_id
203
- # t.string :name, :value, :default => "Untitled"
204
- # t.timestamps
275
+ # t.string :item_number, index: true
276
+ # t.string :name, :value, default: "Untitled"
277
+ # t.timestamps null: false
205
278
  # end
206
279
  #
207
280
  # There's a short-hand method for each of the type values declared at the top. And then there's
@@ -209,96 +282,154 @@ module ActiveRecord
209
282
  #
210
283
  # TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
211
284
  # column if the <tt>:polymorphic</tt> option is supplied. If <tt>:polymorphic</tt> is a hash of
212
- # options, these will be used when creating the <tt>_type</tt> column. So what can be written like this:
285
+ # options, these will be used when creating the <tt>_type</tt> column. The <tt>:index</tt> option
286
+ # will also create an index, similar to calling {add_index}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_index].
287
+ # So what can be written like this:
213
288
  #
214
289
  # create_table :taggings do |t|
215
290
  # t.integer :tag_id, :tagger_id, :taggable_id
216
291
  # t.string :tagger_type
217
- # t.string :taggable_type, :default => 'Photo'
292
+ # t.string :taggable_type, default: 'Photo'
218
293
  # end
294
+ # add_index :taggings, :tag_id, name: 'index_taggings_on_tag_id'
295
+ # add_index :taggings, [:tagger_id, :tagger_type]
219
296
  #
220
297
  # Can also be written as follows using references:
221
298
  #
222
299
  # create_table :taggings do |t|
223
- # t.references :tag
224
- # t.references :tagger, :polymorphic => true
225
- # t.references :taggable, :polymorphic => { :default => 'Photo' }
300
+ # t.references :tag, index: { name: 'index_taggings_on_tag_id' }
301
+ # t.references :tagger, polymorphic: true, index: true
302
+ # t.references :taggable, polymorphic: { default: 'Photo' }
226
303
  # end
227
304
  def column(name, type, options = {})
228
305
  name = name.to_s
229
306
  type = type.to_sym
307
+ options = options.dup
230
308
 
231
- column = self[name] || new_column_definition(@base, name, type)
232
-
233
- limit = options.fetch(:limit) do
234
- native[type][:limit] if native[type].is_a?(Hash)
309
+ if @columns_hash[name] && @columns_hash[name].primary_key?
310
+ raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
235
311
  end
236
312
 
237
- column.limit = limit
238
- column.precision = options[:precision]
239
- column.scale = options[:scale]
240
- column.default = options[:default]
241
- column.null = options[:null]
313
+ index_options = options.delete(:index)
314
+ index(name, index_options.is_a?(Hash) ? index_options : {}) if index_options
315
+ @columns_hash[name] = new_column_definition(name, type, options)
242
316
  self
243
317
  end
244
318
 
245
- %w( string text integer float decimal datetime timestamp time date binary boolean ).each do |column_type|
246
- class_eval <<-EOV, __FILE__, __LINE__ + 1
247
- def #{column_type}(*args) # def string(*args)
248
- options = args.extract_options! # options = args.extract_options!
249
- column_names = args # column_names = args
250
- type = :'#{column_type}' # type = :string
251
- column_names.each { |name| column(name, type, options) } # column_names.each { |name| column(name, type, options) }
252
- end # end
253
- EOV
319
+ # remove the column +name+ from the table.
320
+ # remove_column(:account_id)
321
+ def remove_column(name)
322
+ @columns_hash.delete name.to_s
323
+ end
324
+
325
+ # Adds index options to the indexes hash, keyed by column name
326
+ # This is primarily used to track indexes that need to be created after the table
327
+ #
328
+ # index(:account_id, name: 'index_projects_on_account_id')
329
+ def index(column_name, options = {})
330
+ indexes[column_name] = options
331
+ end
332
+
333
+ def foreign_key(table_name, options = {}) # :nodoc:
334
+ table_name_prefix = ActiveRecord::Base.table_name_prefix
335
+ table_name_suffix = ActiveRecord::Base.table_name_suffix
336
+ table_name = "#{table_name_prefix}#{table_name}#{table_name_suffix}"
337
+ foreign_keys.push([table_name, options])
254
338
  end
255
339
 
256
340
  # Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
257
- # <tt>:updated_at</tt> to the table.
341
+ # <tt>:updated_at</tt> to the table. See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
342
+ #
343
+ # t.timestamps null: false
258
344
  def timestamps(*args)
259
- options = { :null => false }.merge(args.extract_options!)
345
+ options = args.extract_options!
346
+
347
+ options[:null] = false if options[:null].nil?
348
+
260
349
  column(:created_at, :datetime, options)
261
350
  column(:updated_at, :datetime, options)
262
351
  end
263
352
 
264
- def references(*args)
265
- options = args.extract_options!
266
- polymorphic = options.delete(:polymorphic)
353
+ # Adds a reference.
354
+ #
355
+ # t.references(:user)
356
+ # t.belongs_to(:supplier, foreign_key: true)
357
+ #
358
+ # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
359
+ def references(*args, **options)
267
360
  args.each do |col|
268
- column("#{col}_id", :integer, options)
269
- column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil?
361
+ ReferenceDefinition.new(col, **options).add_to(self)
270
362
  end
271
363
  end
272
364
  alias :belongs_to :references
273
365
 
274
- # Returns a String whose contents are the column definitions
275
- # concatenated together. This string can then be prepended and appended to
276
- # to generate the final SQL to create the table.
277
- def to_sql
278
- @columns.map { |c| c.to_sql } * ', '
366
+ def new_column_definition(name, type, options) # :nodoc:
367
+ type = aliased_types(type.to_s, type)
368
+ column = create_column_definition name, type
369
+
370
+ column.limit = options[:limit]
371
+ column.precision = options[:precision]
372
+ column.scale = options[:scale]
373
+ column.default = options[:default]
374
+ column.null = options[:null]
375
+ column.first = options[:first]
376
+ column.after = options[:after]
377
+ column.auto_increment = options[:auto_increment]
378
+ column.primary_key = type == :primary_key || options[:primary_key]
379
+ column.collation = options[:collation]
380
+ column.comment = options[:comment]
381
+ column
279
382
  end
280
383
 
281
384
  private
282
- def new_column_definition(base, name, type)
283
- definition = ColumnDefinition.new base, name, type
284
- @columns << definition
285
- @columns_hash[name] = definition
286
- definition
385
+ def create_column_definition(name, type)
386
+ ColumnDefinition.new name, type
387
+ end
388
+
389
+ def aliased_types(name, fallback)
390
+ 'timestamp' == name ? :datetime : fallback
287
391
  end
392
+ end
393
+
394
+ class AlterTable # :nodoc:
395
+ attr_reader :adds
396
+ attr_reader :foreign_key_adds
397
+ attr_reader :foreign_key_drops
398
+
399
+ def initialize(td)
400
+ @td = td
401
+ @adds = []
402
+ @foreign_key_adds = []
403
+ @foreign_key_drops = []
404
+ end
405
+
406
+ def name; @td.name; end
288
407
 
289
- def native
290
- @base.native_database_types
408
+ def add_foreign_key(to_table, options)
409
+ @foreign_key_adds << ForeignKeyDefinition.new(name, to_table, options)
410
+ end
411
+
412
+ def drop_foreign_key(name)
413
+ @foreign_key_drops << name
414
+ end
415
+
416
+ def add_column(name, type, options)
417
+ name = name.to_s
418
+ type = type.to_sym
419
+ @adds << AddColumnDefinition.new(@td.new_column_definition(name, type, options))
291
420
  end
292
421
  end
293
422
 
294
423
  # Represents an SQL table in an abstract way for updating a table.
295
- # Also see TableDefinition and SchemaStatements#create_table
424
+ # Also see TableDefinition and {connection.create_table}[rdoc-ref:SchemaStatements#create_table]
296
425
  #
297
426
  # Available transformations are:
298
427
  #
299
428
  # change_table :table do |t|
429
+ # t.primary_key
300
430
  # t.column
301
431
  # t.index
432
+ # t.rename_index
302
433
  # t.timestamps
303
434
  # t.change
304
435
  # t.change_default
@@ -308,8 +439,10 @@ module ActiveRecord
308
439
  # t.string
309
440
  # t.text
310
441
  # t.integer
442
+ # t.bigint
311
443
  # t.float
312
444
  # t.decimal
445
+ # t.numeric
313
446
  # t.datetime
314
447
  # t.timestamp
315
448
  # t.time
@@ -324,169 +457,179 @@ module ActiveRecord
324
457
  # end
325
458
  #
326
459
  class Table
460
+ include ColumnMethods
461
+
462
+ attr_reader :name
463
+
327
464
  def initialize(table_name, base)
328
- @table_name = table_name
465
+ @name = table_name
329
466
  @base = base
330
467
  end
331
468
 
332
469
  # Adds a new column to the named table.
333
- # See TableDefinition#column for details of the options you can use.
334
- # ===== Example
335
- # ====== Creating a simple column
470
+ #
336
471
  # t.column(:name, :string)
472
+ #
473
+ # See TableDefinition#column for details of the options you can use.
337
474
  def column(column_name, type, options = {})
338
- @base.add_column(@table_name, column_name, type, options)
475
+ @base.add_column(name, column_name, type, options)
339
476
  end
340
477
 
341
- # Checks to see if a column exists. See SchemaStatements#column_exists?
478
+ # Checks to see if a column exists.
479
+ #
480
+ # t.string(:name) unless t.column_exists?(:name, :string)
481
+ #
482
+ # See {connection.column_exists?}[rdoc-ref:SchemaStatements#column_exists?]
342
483
  def column_exists?(column_name, type = nil, options = {})
343
- @base.column_exists?(@table_name, column_name, type, options)
484
+ @base.column_exists?(name, column_name, type, options)
344
485
  end
345
486
 
346
487
  # Adds a new index to the table. +column_name+ can be a single Symbol, or
347
- # an Array of Symbols. See SchemaStatements#add_index
488
+ # an Array of Symbols.
348
489
  #
349
- # ===== Examples
350
- # ====== Creating a simple index
351
490
  # t.index(:name)
352
- # ====== Creating a unique index
353
- # t.index([:branch_id, :party_id], :unique => true)
354
- # ====== Creating a named index
355
- # t.index([:branch_id, :party_id], :unique => true, :name => 'by_branch_party')
491
+ # t.index([:branch_id, :party_id], unique: true)
492
+ # t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
493
+ #
494
+ # See {connection.add_index}[rdoc-ref:SchemaStatements#add_index] for details of the options you can use.
356
495
  def index(column_name, options = {})
357
- @base.add_index(@table_name, column_name, options)
496
+ @base.add_index(name, column_name, options)
358
497
  end
359
498
 
360
- # Checks to see if an index exists. See SchemaStatements#index_exists?
499
+ # Checks to see if an index exists.
500
+ #
501
+ # unless t.index_exists?(:branch_id)
502
+ # t.index(:branch_id)
503
+ # end
504
+ #
505
+ # See {connection.index_exists?}[rdoc-ref:SchemaStatements#index_exists?]
361
506
  def index_exists?(column_name, options = {})
362
- @base.index_exists?(@table_name, column_name, options)
507
+ @base.index_exists?(name, column_name, options)
508
+ end
509
+
510
+ # Renames the given index on the table.
511
+ #
512
+ # t.rename_index(:user_id, :account_id)
513
+ #
514
+ # See {connection.rename_index}[rdoc-ref:SchemaStatements#rename_index]
515
+ def rename_index(index_name, new_index_name)
516
+ @base.rename_index(name, index_name, new_index_name)
363
517
  end
364
518
 
365
- # Adds timestamps (+created_at+ and +updated_at+) columns to the table. See SchemaStatements#add_timestamps
366
- # ===== Example
367
- # t.timestamps
368
- def timestamps
369
- @base.add_timestamps(@table_name)
519
+ # Adds timestamps (+created_at+ and +updated_at+) columns to the table.
520
+ #
521
+ # t.timestamps(null: false)
522
+ #
523
+ # See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
524
+ def timestamps(options = {})
525
+ @base.add_timestamps(name, options)
370
526
  end
371
527
 
372
528
  # Changes the column's definition according to the new options.
373
- # See TableDefinition#column for details of the options you can use.
374
- # ===== Examples
375
- # t.change(:name, :string, :limit => 80)
529
+ #
530
+ # t.change(:name, :string, limit: 80)
376
531
  # t.change(:description, :text)
532
+ #
533
+ # See TableDefinition#column for details of the options you can use.
377
534
  def change(column_name, type, options = {})
378
- @base.change_column(@table_name, column_name, type, options)
535
+ @base.change_column(name, column_name, type, options)
379
536
  end
380
537
 
381
- # Sets a new default value for a column. See SchemaStatements#change_column_default
382
- # ===== Examples
538
+ # Sets a new default value for a column.
539
+ #
383
540
  # t.change_default(:qualification, 'new')
384
541
  # t.change_default(:authorized, 1)
385
- def change_default(column_name, default)
386
- @base.change_column_default(@table_name, column_name, default)
542
+ # t.change_default(:status, from: nil, to: "draft")
543
+ #
544
+ # See {connection.change_column_default}[rdoc-ref:SchemaStatements#change_column_default]
545
+ def change_default(column_name, default_or_changes)
546
+ @base.change_column_default(name, column_name, default_or_changes)
387
547
  end
388
548
 
389
549
  # Removes the column(s) from the table definition.
390
- # ===== Examples
550
+ #
391
551
  # t.remove(:qualification)
392
552
  # t.remove(:qualification, :experience)
553
+ #
554
+ # See {connection.remove_columns}[rdoc-ref:SchemaStatements#remove_columns]
393
555
  def remove(*column_names)
394
- @base.remove_column(@table_name, *column_names)
556
+ @base.remove_columns(name, *column_names)
395
557
  end
396
558
 
397
559
  # Removes the given index from the table.
398
560
  #
399
- # ===== Examples
400
- # ====== Remove the index_table_name_on_column in the table_name table
401
- # t.remove_index :column
402
- # ====== Remove the index named index_table_name_on_branch_id in the table_name table
403
- # t.remove_index :column => :branch_id
404
- # ====== Remove the index named index_table_name_on_branch_id_and_party_id in the table_name table
405
- # t.remove_index :column => [:branch_id, :party_id]
406
- # ====== Remove the index named by_branch_party in the table_name table
407
- # t.remove_index :name => :by_branch_party
561
+ # t.remove_index(:branch_id)
562
+ # t.remove_index(column: [:branch_id, :party_id])
563
+ # t.remove_index(name: :by_branch_party)
564
+ #
565
+ # See {connection.remove_index}[rdoc-ref:SchemaStatements#remove_index]
408
566
  def remove_index(options = {})
409
- @base.remove_index(@table_name, options)
567
+ @base.remove_index(name, options)
410
568
  end
411
569
 
412
570
  # Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
413
- # ===== Example
571
+ #
414
572
  # t.remove_timestamps
415
- def remove_timestamps
416
- @base.remove_timestamps(@table_name)
573
+ #
574
+ # See {connection.remove_timestamps}[rdoc-ref:SchemaStatements#remove_timestamps]
575
+ def remove_timestamps(options = {})
576
+ @base.remove_timestamps(name, options)
417
577
  end
418
578
 
419
579
  # Renames a column.
420
- # ===== Example
580
+ #
421
581
  # t.rename(:description, :name)
582
+ #
583
+ # See {connection.rename_column}[rdoc-ref:SchemaStatements#rename_column]
422
584
  def rename(column_name, new_column_name)
423
- @base.rename_column(@table_name, column_name, new_column_name)
585
+ @base.rename_column(name, column_name, new_column_name)
424
586
  end
425
587
 
426
- # Adds a reference. Optionally adds a +type+ column, if <tt>:polymorphic</tt> option is provided.
427
- # <tt>references</tt> and <tt>belongs_to</tt> are acceptable.
428
- # ===== Examples
429
- # t.references(:goat)
430
- # t.references(:goat, :polymorphic => true)
431
- # t.belongs_to(:goat)
588
+ # Adds a reference.
589
+ #
590
+ # t.references(:user)
591
+ # t.belongs_to(:supplier, foreign_key: true)
592
+ #
593
+ # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
432
594
  def references(*args)
433
595
  options = args.extract_options!
434
- polymorphic = options.delete(:polymorphic)
435
- args.each do |col|
436
- @base.add_column(@table_name, "#{col}_id", :integer, options)
437
- @base.add_column(@table_name, "#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil?
596
+ args.each do |ref_name|
597
+ @base.add_reference(name, ref_name, options)
438
598
  end
439
599
  end
440
600
  alias :belongs_to :references
441
601
 
442
602
  # Removes a reference. Optionally removes a +type+ column.
443
- # <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable.
444
- # ===== Examples
445
- # t.remove_references(:goat)
446
- # t.remove_references(:goat, :polymorphic => true)
447
- # t.remove_belongs_to(:goat)
603
+ #
604
+ # t.remove_references(:user)
605
+ # t.remove_belongs_to(:supplier, polymorphic: true)
606
+ #
607
+ # See {connection.remove_reference}[rdoc-ref:SchemaStatements#remove_reference]
448
608
  def remove_references(*args)
449
609
  options = args.extract_options!
450
- polymorphic = options.delete(:polymorphic)
451
- args.each do |col|
452
- @base.remove_column(@table_name, "#{col}_id")
453
- @base.remove_column(@table_name, "#{col}_type") unless polymorphic.nil?
610
+ args.each do |ref_name|
611
+ @base.remove_reference(name, ref_name, options)
454
612
  end
455
613
  end
456
- alias :remove_belongs_to :remove_references
614
+ alias :remove_belongs_to :remove_references
457
615
 
458
- # Adds a column or columns of a specified type
459
- # ===== Examples
460
- # t.string(:goat)
461
- # t.string(:goat, :sheep)
462
- %w( string text integer float decimal datetime timestamp time date binary boolean ).each do |column_type|
463
- class_eval <<-EOV, __FILE__, __LINE__ + 1
464
- def #{column_type}(*args) # def string(*args)
465
- options = args.extract_options! # options = args.extract_options!
466
- column_names = args # column_names = args
467
- type = :'#{column_type}' # type = :string
468
- column_names.each do |name| # column_names.each do |name|
469
- column = ColumnDefinition.new(@base, name.to_s, type) # column = ColumnDefinition.new(@base, name, type)
470
- if options[:limit] # if options[:limit]
471
- column.limit = options[:limit] # column.limit = options[:limit]
472
- elsif native[type].is_a?(Hash) # elsif native[type].is_a?(Hash)
473
- column.limit = native[type][:limit] # column.limit = native[type][:limit]
474
- end # end
475
- column.precision = options[:precision] # column.precision = options[:precision]
476
- column.scale = options[:scale] # column.scale = options[:scale]
477
- column.default = options[:default] # column.default = options[:default]
478
- column.null = options[:null] # column.null = options[:null]
479
- @base.add_column(@table_name, name, column.sql_type, options) # @base.add_column(@table_name, name, column.sql_type, options)
480
- end # end
481
- end # end
482
- EOV
616
+ # Adds a foreign key.
617
+ #
618
+ # t.foreign_key(:authors)
619
+ #
620
+ # See {connection.add_foreign_key}[rdoc-ref:SchemaStatements#add_foreign_key]
621
+ def foreign_key(*args) # :nodoc:
622
+ @base.add_foreign_key(name, *args)
483
623
  end
484
624
 
485
- private
486
- def native
487
- @base.native_database_types
488
- end
625
+ # Checks to see if a foreign key exists.
626
+ #
627
+ # t.foreign_key(:authors) unless t.foreign_key_exists?(:authors)
628
+ #
629
+ # See {connection.foreign_key_exists?}[rdoc-ref:SchemaStatements#foreign_key_exists?]
630
+ def foreign_key_exists?(*args) # :nodoc:
631
+ @base.foreign_key_exists?(name, *args)
632
+ end
489
633
  end
490
-
491
634
  end
492
635
  end