activerecord 4.2.11.1 → 5.2.4.5

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