activerecord 4.2.11.3 → 5.0.0.1

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