activerecord 3.2.22.5 → 5.2.8

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 (275) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +657 -621
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +41 -46
  5. data/examples/performance.rb +55 -42
  6. data/examples/simple.rb +6 -5
  7. data/lib/active_record/aggregations.rb +264 -236
  8. data/lib/active_record/association_relation.rb +40 -0
  9. data/lib/active_record/associations/alias_tracker.rb +47 -42
  10. data/lib/active_record/associations/association.rb +127 -75
  11. data/lib/active_record/associations/association_scope.rb +126 -92
  12. data/lib/active_record/associations/belongs_to_association.rb +78 -27
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +9 -4
  14. data/lib/active_record/associations/builder/association.rb +117 -32
  15. data/lib/active_record/associations/builder/belongs_to.rb +135 -60
  16. data/lib/active_record/associations/builder/collection_association.rb +61 -54
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +120 -42
  18. data/lib/active_record/associations/builder/has_many.rb +10 -64
  19. data/lib/active_record/associations/builder/has_one.rb +19 -51
  20. data/lib/active_record/associations/builder/singular_association.rb +28 -18
  21. data/lib/active_record/associations/collection_association.rb +226 -293
  22. data/lib/active_record/associations/collection_proxy.rb +1067 -69
  23. data/lib/active_record/associations/foreign_association.rb +13 -0
  24. data/lib/active_record/associations/has_many_association.rb +83 -47
  25. data/lib/active_record/associations/has_many_through_association.rb +98 -65
  26. data/lib/active_record/associations/has_one_association.rb +57 -20
  27. data/lib/active_record/associations/has_one_through_association.rb +18 -9
  28. data/lib/active_record/associations/join_dependency/join_association.rb +48 -126
  29. data/lib/active_record/associations/join_dependency/join_base.rb +11 -12
  30. data/lib/active_record/associations/join_dependency/join_part.rb +35 -42
  31. data/lib/active_record/associations/join_dependency.rb +212 -164
  32. data/lib/active_record/associations/preloader/association.rb +95 -89
  33. data/lib/active_record/associations/preloader/through_association.rb +84 -44
  34. data/lib/active_record/associations/preloader.rb +123 -111
  35. data/lib/active_record/associations/singular_association.rb +33 -24
  36. data/lib/active_record/associations/through_association.rb +60 -26
  37. data/lib/active_record/associations.rb +1759 -1506
  38. data/lib/active_record/attribute_assignment.rb +60 -193
  39. data/lib/active_record/attribute_decorators.rb +90 -0
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +55 -8
  41. data/lib/active_record/attribute_methods/dirty.rb +113 -74
  42. data/lib/active_record/attribute_methods/primary_key.rb +106 -77
  43. data/lib/active_record/attribute_methods/query.rb +8 -5
  44. data/lib/active_record/attribute_methods/read.rb +63 -114
  45. data/lib/active_record/attribute_methods/serialization.rb +60 -90
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +69 -43
  47. data/lib/active_record/attribute_methods/write.rb +43 -45
  48. data/lib/active_record/attribute_methods.rb +366 -149
  49. data/lib/active_record/attributes.rb +266 -0
  50. data/lib/active_record/autosave_association.rb +312 -225
  51. data/lib/active_record/base.rb +114 -505
  52. data/lib/active_record/callbacks.rb +145 -67
  53. data/lib/active_record/coders/json.rb +15 -0
  54. data/lib/active_record/coders/yaml_column.rb +32 -23
  55. data/lib/active_record/collection_cache_key.rb +53 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +883 -284
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +16 -2
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +350 -200
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +82 -27
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +150 -65
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +146 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +477 -284
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +95 -0
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1100 -310
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +283 -0
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +450 -118
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +657 -446
  69. data/lib/active_record/connection_adapters/column.rb +50 -255
  70. data/lib/active_record/connection_adapters/connection_specification.rb +287 -0
  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 +59 -210
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +163 -0
  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 +92 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +56 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  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 +41 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +111 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +168 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +206 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +774 -0
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +620 -1080
  117. data/lib/active_record/connection_adapters/schema_cache.rb +85 -36
  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 +545 -27
  126. data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
  127. data/lib/active_record/connection_handling.rb +145 -0
  128. data/lib/active_record/core.rb +559 -0
  129. data/lib/active_record/counter_cache.rb +200 -105
  130. data/lib/active_record/define_callbacks.rb +22 -0
  131. data/lib/active_record/dynamic_matchers.rb +107 -69
  132. data/lib/active_record/enum.rb +244 -0
  133. data/lib/active_record/errors.rb +245 -60
  134. data/lib/active_record/explain.rb +35 -71
  135. data/lib/active_record/explain_registry.rb +32 -0
  136. data/lib/active_record/explain_subscriber.rb +18 -9
  137. data/lib/active_record/fixture_set/file.rb +82 -0
  138. data/lib/active_record/fixtures.rb +418 -275
  139. data/lib/active_record/gem_version.rb +17 -0
  140. data/lib/active_record/inheritance.rb +209 -100
  141. data/lib/active_record/integration.rb +116 -21
  142. data/lib/active_record/internal_metadata.rb +45 -0
  143. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  144. data/lib/active_record/locale/en.yml +9 -1
  145. data/lib/active_record/locking/optimistic.rb +107 -94
  146. data/lib/active_record/locking/pessimistic.rb +20 -8
  147. data/lib/active_record/log_subscriber.rb +99 -34
  148. data/lib/active_record/migration/command_recorder.rb +199 -64
  149. data/lib/active_record/migration/compatibility.rb +217 -0
  150. data/lib/active_record/migration/join_table.rb +17 -0
  151. data/lib/active_record/migration.rb +893 -296
  152. data/lib/active_record/model_schema.rb +328 -175
  153. data/lib/active_record/nested_attributes.rb +338 -242
  154. data/lib/active_record/no_touching.rb +58 -0
  155. data/lib/active_record/null_relation.rb +68 -0
  156. data/lib/active_record/persistence.rb +557 -170
  157. data/lib/active_record/query_cache.rb +14 -43
  158. data/lib/active_record/querying.rb +36 -24
  159. data/lib/active_record/railtie.rb +147 -52
  160. data/lib/active_record/railties/console_sandbox.rb +5 -4
  161. data/lib/active_record/railties/controller_runtime.rb +13 -6
  162. data/lib/active_record/railties/databases.rake +206 -488
  163. data/lib/active_record/readonly_attributes.rb +4 -6
  164. data/lib/active_record/reflection.rb +734 -228
  165. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  166. data/lib/active_record/relation/batches.rb +249 -52
  167. data/lib/active_record/relation/calculations.rb +330 -284
  168. data/lib/active_record/relation/delegation.rb +135 -37
  169. data/lib/active_record/relation/finder_methods.rb +450 -287
  170. data/lib/active_record/relation/from_clause.rb +26 -0
  171. data/lib/active_record/relation/merger.rb +193 -0
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
  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 +19 -0
  179. data/lib/active_record/relation/predicate_builder.rb +132 -43
  180. data/lib/active_record/relation/query_attribute.rb +45 -0
  181. data/lib/active_record/relation/query_methods.rb +1037 -221
  182. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  183. data/lib/active_record/relation/spawn_methods.rb +48 -151
  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 +451 -359
  187. data/lib/active_record/result.rb +129 -20
  188. data/lib/active_record/runtime_registry.rb +24 -0
  189. data/lib/active_record/sanitization.rb +164 -136
  190. data/lib/active_record/schema.rb +31 -19
  191. data/lib/active_record/schema_dumper.rb +154 -107
  192. data/lib/active_record/schema_migration.rb +56 -0
  193. data/lib/active_record/scoping/default.rb +108 -98
  194. data/lib/active_record/scoping/named.rb +125 -112
  195. data/lib/active_record/scoping.rb +77 -123
  196. data/lib/active_record/secure_token.rb +40 -0
  197. data/lib/active_record/serialization.rb +10 -6
  198. data/lib/active_record/statement_cache.rb +121 -0
  199. data/lib/active_record/store.rb +175 -16
  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 +337 -0
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +143 -0
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +83 -0
  206. data/lib/active_record/timestamp.rb +80 -41
  207. data/lib/active_record/touch_later.rb +64 -0
  208. data/lib/active_record/transactions.rb +240 -119
  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 +9 -0
  212. data/lib/active_record/type/date_time.rb +9 -0
  213. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  214. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  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 +71 -0
  218. data/lib/active_record/type/text.rb +11 -0
  219. data/lib/active_record/type/time.rb +21 -0
  220. data/lib/active_record/type/type_map.rb +62 -0
  221. data/lib/active_record/type/unsigned_integer.rb +17 -0
  222. data/lib/active_record/type.rb +79 -0
  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 +35 -18
  228. data/lib/active_record/validations/length.rb +26 -0
  229. data/lib/active_record/validations/presence.rb +68 -0
  230. data/lib/active_record/validations/uniqueness.rb +133 -75
  231. data/lib/active_record/validations.rb +53 -43
  232. data/lib/active_record/version.rb +7 -7
  233. data/lib/active_record.rb +89 -57
  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 +61 -8
  237. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  238. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +46 -0
  239. data/lib/rails/generators/active_record/migration.rb +28 -8
  240. data/lib/rails/generators/active_record/model/model_generator.rb +23 -22
  241. data/lib/rails/generators/active_record/model/templates/model.rb.tt +13 -0
  242. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +1 -1
  243. data/lib/rails/generators/active_record.rb +10 -16
  244. metadata +141 -62
  245. data/examples/associations.png +0 -0
  246. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
  247. data/lib/active_record/associations/join_helper.rb +0 -55
  248. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  249. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  250. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  251. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  252. data/lib/active_record/associations/preloader/has_many_through.rb +0 -15
  253. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  254. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  255. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  256. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  257. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  258. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -441
  259. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  260. data/lib/active_record/dynamic_finder_match.rb +0 -68
  261. data/lib/active_record/dynamic_scope_match.rb +0 -23
  262. data/lib/active_record/fixtures/file.rb +0 -65
  263. data/lib/active_record/identity_map.rb +0 -162
  264. data/lib/active_record/observer.rb +0 -121
  265. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  266. data/lib/active_record/serializers/xml_serializer.rb +0 -203
  267. data/lib/active_record/session_store.rb +0 -360
  268. data/lib/active_record/test_case.rb +0 -73
  269. data/lib/rails/generators/active_record/migration/templates/migration.rb +0 -34
  270. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
  271. data/lib/rails/generators/active_record/model/templates/model.rb +0 -12
  272. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  273. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  274. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  275. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,51 +1,248 @@
1
- require 'active_support/core_ext/object/blank'
2
- require 'date'
3
- require 'set'
4
- require 'bigdecimal'
5
- require 'bigdecimal/util'
1
+ # frozen_string_literal: true
6
2
 
7
3
  module ActiveRecord
8
4
  module ConnectionAdapters #:nodoc:
9
- class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders) #:nodoc:
5
+ # Abstract representation of an index definition on a table. Instances of
6
+ # this type are typically created and returned by methods in database
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
10
44
  end
11
45
 
12
46
  # Abstract representation of a column definition. Instances of this type
13
47
  # are typically created by methods in TableDefinition, and added to the
14
48
  # +columns+ attribute of said TableDefinition object, in order to be used
15
49
  # 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:
50
+ ColumnDefinition = Struct.new(:name, :type, :options, :sql_type) do # :nodoc:
51
+ def primary_key?
52
+ options[:primary_key]
53
+ end
54
+
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
66
+ end
67
+
68
+ AddColumnDefinition = Struct.new(:column) # :nodoc:
17
69
 
18
- def string_to_binary(value)
19
- value
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:
75
+ def name
76
+ options[:name]
77
+ end
78
+
79
+ def column
80
+ options[:column]
81
+ end
82
+
83
+ def primary_key
84
+ options[:primary_key] || default_primary_key
85
+ end
86
+
87
+ def on_delete
88
+ options[:on_delete]
20
89
  end
21
90
 
22
- def sql_type
23
- base.type_to_sql(type.to_sym, limit, precision, scale) rescue type
91
+ def on_update
92
+ options[:on_update]
24
93
  end
25
94
 
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
95
+ def custom_primary_key?
96
+ options[:primary_key] != default_primary_key
97
+ end
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
33
111
  end
34
112
 
35
113
  private
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
138
+ end
36
139
 
37
- def add_column_options!(sql, options)
38
- base.add_column_options!(sql, options.merge(:column => self))
140
+ def add_to(table)
141
+ columns.each do |column_options|
142
+ table.column(*column_options)
39
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
199
+ end
200
+
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
207
+
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
235
+ end
236
+ alias_method :numeric, :decimal
40
237
  end
41
238
 
42
239
  # Represents the schema of an SQL table in an abstract way. This class
43
240
  # provides methods for manipulating the schema representation.
44
241
  #
45
- # Inside migration files, the +t+ object in +create_table+
242
+ # Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
46
243
  # is actually of this type:
47
244
  #
48
- # class SomeMigration < ActiveRecord::Migration
245
+ # class SomeMigration < ActiveRecord::Migration[5.0]
49
246
  # def up
50
247
  # create_table :foo do |t|
51
248
  # puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
@@ -57,33 +254,31 @@ module ActiveRecord
57
254
  # end
58
255
  # end
59
256
  #
60
- # The table definitions
61
- # The Columns are stored as a ColumnDefinition in the +columns+ attribute.
62
257
  class TableDefinition
63
- # An array of ColumnDefinition objects, representing the column changes
64
- # that have been defined.
65
- attr_accessor :columns
258
+ include ColumnMethods
66
259
 
67
- def initialize(base)
68
- @columns = []
260
+ attr_accessor :indexes
261
+ attr_reader :name, :temporary, :options, :as, :foreign_keys, :comment
262
+
263
+ def initialize(name, temporary = false, options = nil, as = nil, comment: nil)
69
264
  @columns_hash = {}
70
- @base = base
265
+ @indexes = []
266
+ @foreign_keys = []
267
+ @primary_keys = nil
268
+ @temporary = temporary
269
+ @options = options
270
+ @as = as
271
+ @name = name
272
+ @comment = comment
71
273
  end
72
274
 
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)
275
+ def primary_keys(name = nil) # :nodoc:
276
+ @primary_keys = PrimaryKeyDefinition.new(name) if name
277
+ @primary_keys
80
278
  end
81
279
 
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
280
+ # Returns an array of ColumnDefinition objects for the columns of the table.
281
+ def columns; @columns_hash.values; end
87
282
 
88
283
  # Returns a ColumnDefinition for the column with name +name+.
89
284
  def [](name)
@@ -91,117 +286,46 @@ module ActiveRecord
91
286
  end
92
287
 
93
288
  # 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>.
289
+ # See {connection.add_column}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_column]
290
+ # for available options.
291
+ #
292
+ # Additional options are:
293
+ # * <tt>:index</tt> -
294
+ # Create an index for the column. Can be either <tt>true</tt> or an options hash.
153
295
  #
154
296
  # This method returns <tt>self</tt>.
155
297
  #
156
298
  # == 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
299
  #
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
- #
178
- # # Defines a column with a database-specific type.
179
- # td.column(:foo, 'polygon')
180
- # # => foo polygon
300
+ # # Assuming +td+ is an instance of TableDefinition
301
+ # td.column(:granted, :boolean, index: true)
181
302
  #
182
303
  # == Short-hand examples
183
304
  #
184
- # 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.
185
306
  # They use the type as the method name instead of as a parameter and allow for multiple columns to be defined
186
307
  # in a single statement.
187
308
  #
188
309
  # What can be written like this with the regular calls to column:
189
310
  #
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
311
+ # create_table :products do |t|
312
+ # t.column :shop_id, :integer
313
+ # t.column :creator_id, :integer
314
+ # t.column :item_number, :string
315
+ # t.column :name, :string, default: "Untitled"
316
+ # t.column :value, :string, default: "Untitled"
317
+ # t.column :created_at, :datetime
318
+ # t.column :updated_at, :datetime
197
319
  # end
320
+ # add_index :products, :item_number
198
321
  #
199
- # Can also be written as follows using the short-hand:
322
+ # can also be written as follows using the short-hand:
200
323
  #
201
324
  # create_table :products do |t|
202
325
  # t.integer :shop_id, :creator_id
203
- # t.string :name, :value, :default => "Untitled"
204
- # t.timestamps
326
+ # t.string :item_number, index: true
327
+ # t.string :name, :value, default: "Untitled"
328
+ # t.timestamps null: false
205
329
  # end
206
330
  #
207
331
  # There's a short-hand method for each of the type values declared at the top. And then there's
@@ -209,96 +333,152 @@ module ActiveRecord
209
333
  #
210
334
  # TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
211
335
  # 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:
336
+ # options, these will be used when creating the <tt>_type</tt> column. The <tt>:index</tt> option
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:
213
339
  #
214
340
  # create_table :taggings do |t|
215
341
  # t.integer :tag_id, :tagger_id, :taggable_id
216
342
  # t.string :tagger_type
217
- # t.string :taggable_type, :default => 'Photo'
343
+ # t.string :taggable_type, default: 'Photo'
218
344
  # end
345
+ # add_index :taggings, :tag_id, name: 'index_taggings_on_tag_id'
346
+ # add_index :taggings, [:tagger_id, :tagger_type]
219
347
  #
220
348
  # Can also be written as follows using references:
221
349
  #
222
350
  # create_table :taggings do |t|
223
- # t.references :tag
224
- # t.references :tagger, :polymorphic => true
225
- # t.references :taggable, :polymorphic => { :default => 'Photo' }
351
+ # t.references :tag, index: { name: 'index_taggings_on_tag_id' }
352
+ # t.references :tagger, polymorphic: true, index: true
353
+ # t.references :taggable, polymorphic: { default: 'Photo' }
226
354
  # end
227
355
  def column(name, type, options = {})
228
356
  name = name.to_s
229
- type = type.to_sym
230
-
231
- column = self[name] || new_column_definition(@base, name, type)
357
+ type = type.to_sym if type
358
+ options = options.dup
232
359
 
233
- limit = options.fetch(:limit) do
234
- native[type][:limit] if native[type].is_a?(Hash)
360
+ if @columns_hash[name] && @columns_hash[name].primary_key?
361
+ raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
235
362
  end
236
363
 
237
- column.limit = limit
238
- column.precision = options[:precision]
239
- column.scale = options[:scale]
240
- column.default = options[:default]
241
- column.null = options[:null]
364
+ index_options = options.delete(:index)
365
+ index(name, index_options.is_a?(Hash) ? index_options : {}) if index_options
366
+ @columns_hash[name] = new_column_definition(name, type, options)
242
367
  self
243
368
  end
244
369
 
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
370
+ # remove the column +name+ from the table.
371
+ # remove_column(:account_id)
372
+ def remove_column(name)
373
+ @columns_hash.delete name.to_s
374
+ end
375
+
376
+ # Adds index options to the indexes hash, keyed by column name
377
+ # This is primarily used to track indexes that need to be created after the table
378
+ #
379
+ # index(:account_id, name: 'index_projects_on_account_id')
380
+ def index(column_name, options = {})
381
+ indexes << [column_name, options]
382
+ end
383
+
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}"
388
+ foreign_keys.push([table_name, options])
254
389
  end
255
390
 
256
391
  # Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
257
- # <tt>:updated_at</tt> to the table.
258
- def timestamps(*args)
259
- options = { :null => false }.merge(args.extract_options!)
392
+ # <tt>:updated_at</tt> to the table. See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
393
+ #
394
+ # t.timestamps null: false
395
+ def timestamps(**options)
396
+ options[:null] = false if options[:null].nil?
397
+
260
398
  column(:created_at, :datetime, options)
261
399
  column(:updated_at, :datetime, options)
262
400
  end
263
401
 
264
- def references(*args)
265
- options = args.extract_options!
266
- polymorphic = options.delete(:polymorphic)
267
- args.each do |col|
268
- column("#{col}_id", :integer, options)
269
- column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil?
402
+ # Adds a reference.
403
+ #
404
+ # t.references(:user)
405
+ # t.belongs_to(:supplier, foreign_key: true)
406
+ #
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)
270
411
  end
271
412
  end
272
413
  alias :belongs_to :references
273
414
 
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 } * ', '
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)
418
+ end
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)
279
423
  end
280
424
 
281
425
  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
426
+ def create_column_definition(name, type, options)
427
+ ColumnDefinition.new(name, type, options)
428
+ end
429
+
430
+ def aliased_types(name, fallback)
431
+ "timestamp" == name ? :datetime : fallback
432
+ end
433
+
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
441
+ end
442
+
443
+ class AlterTable # :nodoc:
444
+ attr_reader :adds
445
+ attr_reader :foreign_key_adds
446
+ attr_reader :foreign_key_drops
447
+
448
+ def initialize(td)
449
+ @td = td
450
+ @adds = []
451
+ @foreign_key_adds = []
452
+ @foreign_key_drops = []
453
+ end
454
+
455
+ def name; @td.name; end
456
+
457
+ def add_foreign_key(to_table, options)
458
+ @foreign_key_adds << ForeignKeyDefinition.new(name, to_table, options)
287
459
  end
288
460
 
289
- def native
290
- @base.native_database_types
461
+ def drop_foreign_key(name)
462
+ @foreign_key_drops << name
463
+ end
464
+
465
+ def add_column(name, type, options)
466
+ name = name.to_s
467
+ type = type.to_sym
468
+ @adds << AddColumnDefinition.new(@td.new_column_definition(name, type, options))
291
469
  end
292
470
  end
293
471
 
294
472
  # Represents an SQL table in an abstract way for updating a table.
295
- # Also see TableDefinition and SchemaStatements#create_table
473
+ # Also see TableDefinition and {connection.create_table}[rdoc-ref:SchemaStatements#create_table]
296
474
  #
297
475
  # Available transformations are:
298
476
  #
299
477
  # change_table :table do |t|
478
+ # t.primary_key
300
479
  # t.column
301
480
  # t.index
481
+ # t.rename_index
302
482
  # t.timestamps
303
483
  # t.change
304
484
  # t.change_default
@@ -308,14 +488,19 @@ module ActiveRecord
308
488
  # t.string
309
489
  # t.text
310
490
  # t.integer
491
+ # t.bigint
311
492
  # t.float
312
493
  # t.decimal
494
+ # t.numeric
313
495
  # t.datetime
314
496
  # t.timestamp
315
497
  # t.time
316
498
  # t.date
317
499
  # t.binary
318
500
  # t.boolean
501
+ # t.foreign_key
502
+ # t.json
503
+ # t.virtual
319
504
  # t.remove
320
505
  # t.remove_references
321
506
  # t.remove_belongs_to
@@ -324,169 +509,177 @@ module ActiveRecord
324
509
  # end
325
510
  #
326
511
  class Table
512
+ include ColumnMethods
513
+
514
+ attr_reader :name
515
+
327
516
  def initialize(table_name, base)
328
- @table_name = table_name
517
+ @name = table_name
329
518
  @base = base
330
519
  end
331
520
 
332
521
  # 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
522
+ #
336
523
  # t.column(:name, :string)
524
+ #
525
+ # See TableDefinition#column for details of the options you can use.
337
526
  def column(column_name, type, options = {})
338
- @base.add_column(@table_name, column_name, type, options)
527
+ @base.add_column(name, column_name, type, options)
339
528
  end
340
529
 
341
- # 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?]
342
535
  def column_exists?(column_name, type = nil, options = {})
343
- @base.column_exists?(@table_name, column_name, type, options)
536
+ @base.column_exists?(name, column_name, type, options)
344
537
  end
345
538
 
346
539
  # Adds a new index to the table. +column_name+ can be a single Symbol, or
347
- # an Array of Symbols. See SchemaStatements#add_index
540
+ # an Array of Symbols.
348
541
  #
349
- # ===== Examples
350
- # ====== Creating a simple index
351
542
  # 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')
543
+ # t.index([:branch_id, :party_id], unique: true)
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.
356
547
  def index(column_name, options = {})
357
- @base.add_index(@table_name, column_name, options)
548
+ @base.add_index(name, column_name, options)
358
549
  end
359
550
 
360
- # 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?]
361
558
  def index_exists?(column_name, options = {})
362
- @base.index_exists?(@table_name, column_name, options)
559
+ @base.index_exists?(name, column_name, options)
560
+ end
561
+
562
+ # Renames the given index on the table.
563
+ #
564
+ # t.rename_index(:user_id, :account_id)
565
+ #
566
+ # See {connection.rename_index}[rdoc-ref:SchemaStatements#rename_index]
567
+ def rename_index(index_name, new_index_name)
568
+ @base.rename_index(name, index_name, new_index_name)
363
569
  end
364
570
 
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)
571
+ # Adds timestamps (+created_at+ and +updated_at+) columns to the table.
572
+ #
573
+ # t.timestamps(null: false)
574
+ #
575
+ # See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
576
+ def timestamps(options = {})
577
+ @base.add_timestamps(name, options)
370
578
  end
371
579
 
372
580
  # 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)
581
+ #
582
+ # t.change(:name, :string, limit: 80)
376
583
  # t.change(:description, :text)
584
+ #
585
+ # See TableDefinition#column for details of the options you can use.
377
586
  def change(column_name, type, options = {})
378
- @base.change_column(@table_name, column_name, type, options)
587
+ @base.change_column(name, column_name, type, options)
379
588
  end
380
589
 
381
- # Sets a new default value for a column. See SchemaStatements#change_column_default
382
- # ===== Examples
590
+ # Sets a new default value for a column.
591
+ #
383
592
  # t.change_default(:qualification, 'new')
384
593
  # t.change_default(:authorized, 1)
385
- def change_default(column_name, default)
386
- @base.change_column_default(@table_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)
387
599
  end
388
600
 
389
601
  # Removes the column(s) from the table definition.
390
- # ===== Examples
602
+ #
391
603
  # t.remove(:qualification)
392
604
  # t.remove(:qualification, :experience)
605
+ #
606
+ # See {connection.remove_columns}[rdoc-ref:SchemaStatements#remove_columns]
393
607
  def remove(*column_names)
394
- @base.remove_column(@table_name, *column_names)
608
+ @base.remove_columns(name, *column_names)
395
609
  end
396
610
 
397
611
  # Removes the given index from the table.
398
612
  #
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
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]
408
618
  def remove_index(options = {})
409
- @base.remove_index(@table_name, options)
619
+ @base.remove_index(name, options)
410
620
  end
411
621
 
412
622
  # Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
413
- # ===== Example
623
+ #
414
624
  # t.remove_timestamps
415
- def remove_timestamps
416
- @base.remove_timestamps(@table_name)
625
+ #
626
+ # See {connection.remove_timestamps}[rdoc-ref:SchemaStatements#remove_timestamps]
627
+ def remove_timestamps(options = {})
628
+ @base.remove_timestamps(name, options)
417
629
  end
418
630
 
419
631
  # Renames a column.
420
- # ===== Example
632
+ #
421
633
  # t.rename(:description, :name)
634
+ #
635
+ # See {connection.rename_column}[rdoc-ref:SchemaStatements#rename_column]
422
636
  def rename(column_name, new_column_name)
423
- @base.rename_column(@table_name, column_name, new_column_name)
424
- end
425
-
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)
432
- def references(*args)
433
- 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?
637
+ @base.rename_column(name, column_name, new_column_name)
638
+ end
639
+
640
+ # Adds a reference.
641
+ #
642
+ # t.references(:user)
643
+ # t.belongs_to(:supplier, foreign_key: true)
644
+ #
645
+ # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
646
+ def references(*args, **options)
647
+ args.each do |ref_name|
648
+ @base.add_reference(name, ref_name, options)
438
649
  end
439
650
  end
440
651
  alias :belongs_to :references
441
652
 
442
653
  # 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)
448
- def remove_references(*args)
449
- 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?
654
+ #
655
+ # t.remove_references(:user)
656
+ # t.remove_belongs_to(:supplier, polymorphic: true)
657
+ #
658
+ # See {connection.remove_reference}[rdoc-ref:SchemaStatements#remove_reference]
659
+ def remove_references(*args, **options)
660
+ args.each do |ref_name|
661
+ @base.remove_reference(name, ref_name, options)
454
662
  end
455
663
  end
456
- alias :remove_belongs_to :remove_references
664
+ alias :remove_belongs_to :remove_references
457
665
 
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
666
+ # Adds a foreign key.
667
+ #
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)
483
673
  end
484
674
 
485
- private
486
- def native
487
- @base.native_database_types
488
- 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
489
683
  end
490
-
491
684
  end
492
685
  end