activerecord 6.0.1 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

Files changed (268) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +843 -626
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -3
  5. data/lib/active_record/aggregations.rb +1 -2
  6. data/lib/active_record/association_relation.rb +18 -17
  7. data/lib/active_record/associations/alias_tracker.rb +19 -16
  8. data/lib/active_record/associations/association.rb +49 -37
  9. data/lib/active_record/associations/association_scope.rb +17 -15
  10. data/lib/active_record/associations/belongs_to_association.rb +15 -5
  11. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
  12. data/lib/active_record/associations/builder/association.rb +9 -3
  13. data/lib/active_record/associations/builder/belongs_to.rb +10 -7
  14. data/lib/active_record/associations/builder/collection_association.rb +5 -4
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -3
  16. data/lib/active_record/associations/builder/has_many.rb +6 -2
  17. data/lib/active_record/associations/builder/has_one.rb +11 -14
  18. data/lib/active_record/associations/builder/singular_association.rb +1 -1
  19. data/lib/active_record/associations/collection_association.rb +25 -8
  20. data/lib/active_record/associations/collection_proxy.rb +14 -7
  21. data/lib/active_record/associations/foreign_association.rb +13 -0
  22. data/lib/active_record/associations/has_many_association.rb +24 -3
  23. data/lib/active_record/associations/has_many_through_association.rb +10 -4
  24. data/lib/active_record/associations/has_one_association.rb +15 -1
  25. data/lib/active_record/associations/join_dependency/join_association.rb +36 -14
  26. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  27. data/lib/active_record/associations/join_dependency.rb +73 -42
  28. data/lib/active_record/associations/preloader/association.rb +51 -25
  29. data/lib/active_record/associations/preloader/through_association.rb +2 -2
  30. data/lib/active_record/associations/preloader.rb +12 -7
  31. data/lib/active_record/associations/singular_association.rb +1 -1
  32. data/lib/active_record/associations/through_association.rb +1 -1
  33. data/lib/active_record/associations.rb +115 -12
  34. data/lib/active_record/attribute_assignment.rb +10 -9
  35. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -10
  36. data/lib/active_record/attribute_methods/dirty.rb +3 -13
  37. data/lib/active_record/attribute_methods/primary_key.rb +6 -4
  38. data/lib/active_record/attribute_methods/query.rb +3 -6
  39. data/lib/active_record/attribute_methods/read.rb +8 -12
  40. data/lib/active_record/attribute_methods/serialization.rb +11 -6
  41. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
  42. data/lib/active_record/attribute_methods/write.rb +12 -21
  43. data/lib/active_record/attribute_methods.rb +64 -54
  44. data/lib/active_record/attributes.rb +32 -8
  45. data/lib/active_record/autosave_association.rb +56 -41
  46. data/lib/active_record/base.rb +2 -14
  47. data/lib/active_record/callbacks.rb +153 -24
  48. data/lib/active_record/coders/yaml_column.rb +1 -2
  49. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +190 -136
  50. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  51. data/lib/active_record/connection_adapters/abstract/database_statements.rb +82 -37
  52. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -8
  53. data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
  54. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  55. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +152 -116
  56. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -52
  57. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  58. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +263 -107
  59. data/lib/active_record/connection_adapters/abstract/transaction.rb +82 -35
  60. data/lib/active_record/connection_adapters/abstract_adapter.rb +60 -73
  61. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +136 -111
  62. data/lib/active_record/connection_adapters/column.rb +15 -1
  63. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  64. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  65. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  66. data/lib/active_record/connection_adapters/mysql/database_statements.rb +28 -36
  67. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  68. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  69. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -7
  70. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  71. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
  72. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +17 -13
  73. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  74. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -13
  75. data/lib/active_record/connection_adapters/pool_config.rb +63 -0
  76. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  77. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  78. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -56
  79. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
  80. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  81. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  83. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  84. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
  85. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
  87. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  89. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
  90. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -6
  91. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -2
  93. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  95. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
  96. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -3
  97. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
  98. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  99. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +72 -54
  100. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  101. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  102. data/lib/active_record/connection_adapters/postgresql_adapter.rb +77 -57
  103. data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
  104. data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
  105. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +36 -12
  106. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -2
  107. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  108. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -5
  109. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +57 -57
  110. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  111. data/lib/active_record/connection_adapters.rb +50 -0
  112. data/lib/active_record/connection_handling.rb +210 -87
  113. data/lib/active_record/core.rb +229 -65
  114. data/lib/active_record/counter_cache.rb +4 -1
  115. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  116. data/lib/active_record/database_configurations/database_config.rb +52 -9
  117. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  118. data/lib/active_record/database_configurations/url_config.rb +15 -41
  119. data/lib/active_record/database_configurations.rb +124 -85
  120. data/lib/active_record/delegated_type.rb +209 -0
  121. data/lib/active_record/destroy_association_async_job.rb +36 -0
  122. data/lib/active_record/dynamic_matchers.rb +2 -3
  123. data/lib/active_record/enum.rb +40 -16
  124. data/lib/active_record/errors.rb +47 -12
  125. data/lib/active_record/explain.rb +9 -5
  126. data/lib/active_record/explain_subscriber.rb +1 -1
  127. data/lib/active_record/fixture_set/file.rb +10 -17
  128. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  129. data/lib/active_record/fixture_set/render_context.rb +1 -1
  130. data/lib/active_record/fixture_set/table_row.rb +2 -3
  131. data/lib/active_record/fixture_set/table_rows.rb +0 -1
  132. data/lib/active_record/fixtures.rb +54 -11
  133. data/lib/active_record/gem_version.rb +2 -2
  134. data/lib/active_record/inheritance.rb +40 -21
  135. data/lib/active_record/insert_all.rb +38 -9
  136. data/lib/active_record/integration.rb +3 -5
  137. data/lib/active_record/internal_metadata.rb +16 -7
  138. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  139. data/lib/active_record/locking/optimistic.rb +22 -17
  140. data/lib/active_record/locking/pessimistic.rb +6 -2
  141. data/lib/active_record/log_subscriber.rb +27 -9
  142. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  143. data/lib/active_record/middleware/database_selector/resolver.rb +6 -2
  144. data/lib/active_record/middleware/database_selector.rb +4 -2
  145. data/lib/active_record/migration/command_recorder.rb +53 -45
  146. data/lib/active_record/migration/compatibility.rb +70 -20
  147. data/lib/active_record/migration/join_table.rb +0 -1
  148. data/lib/active_record/migration.rb +114 -84
  149. data/lib/active_record/model_schema.rb +117 -15
  150. data/lib/active_record/nested_attributes.rb +2 -5
  151. data/lib/active_record/no_touching.rb +1 -1
  152. data/lib/active_record/null_relation.rb +0 -1
  153. data/lib/active_record/persistence.rb +50 -46
  154. data/lib/active_record/query_cache.rb +15 -5
  155. data/lib/active_record/querying.rb +12 -7
  156. data/lib/active_record/railtie.rb +65 -45
  157. data/lib/active_record/railties/databases.rake +267 -93
  158. data/lib/active_record/readonly_attributes.rb +4 -0
  159. data/lib/active_record/reflection.rb +77 -63
  160. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  161. data/lib/active_record/relation/batches.rb +38 -32
  162. data/lib/active_record/relation/calculations.rb +102 -45
  163. data/lib/active_record/relation/delegation.rb +9 -7
  164. data/lib/active_record/relation/finder_methods.rb +45 -16
  165. data/lib/active_record/relation/from_clause.rb +5 -1
  166. data/lib/active_record/relation/merger.rb +27 -26
  167. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  168. data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
  169. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +3 -3
  170. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  171. data/lib/active_record/relation/predicate_builder.rb +55 -35
  172. data/lib/active_record/relation/query_methods.rb +335 -187
  173. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  174. data/lib/active_record/relation/spawn_methods.rb +8 -8
  175. data/lib/active_record/relation/where_clause.rb +104 -58
  176. data/lib/active_record/relation.rb +108 -68
  177. data/lib/active_record/result.rb +41 -34
  178. data/lib/active_record/runtime_registry.rb +2 -2
  179. data/lib/active_record/sanitization.rb +6 -17
  180. data/lib/active_record/schema_dumper.rb +34 -4
  181. data/lib/active_record/schema_migration.rb +2 -8
  182. data/lib/active_record/scoping/default.rb +0 -1
  183. data/lib/active_record/scoping/named.rb +7 -18
  184. data/lib/active_record/scoping.rb +0 -1
  185. data/lib/active_record/secure_token.rb +16 -8
  186. data/lib/active_record/serialization.rb +5 -3
  187. data/lib/active_record/signed_id.rb +116 -0
  188. data/lib/active_record/statement_cache.rb +20 -4
  189. data/lib/active_record/store.rb +3 -3
  190. data/lib/active_record/suppressor.rb +2 -2
  191. data/lib/active_record/table_metadata.rb +39 -36
  192. data/lib/active_record/tasks/database_tasks.rb +139 -113
  193. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -36
  194. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -27
  195. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -10
  196. data/lib/active_record/test_databases.rb +5 -4
  197. data/lib/active_record/test_fixtures.rb +38 -16
  198. data/lib/active_record/timestamp.rb +4 -7
  199. data/lib/active_record/touch_later.rb +20 -21
  200. data/lib/active_record/transactions.rb +21 -70
  201. data/lib/active_record/type/adapter_specific_registry.rb +2 -5
  202. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  203. data/lib/active_record/type/serialized.rb +6 -3
  204. data/lib/active_record/type/time.rb +10 -0
  205. data/lib/active_record/type/type_map.rb +0 -1
  206. data/lib/active_record/type/unsigned_integer.rb +0 -1
  207. data/lib/active_record/type.rb +8 -2
  208. data/lib/active_record/type_caster/connection.rb +0 -1
  209. data/lib/active_record/type_caster/map.rb +8 -5
  210. data/lib/active_record/validations/associated.rb +1 -2
  211. data/lib/active_record/validations/numericality.rb +35 -0
  212. data/lib/active_record/validations/uniqueness.rb +24 -4
  213. data/lib/active_record/validations.rb +3 -3
  214. data/lib/active_record.rb +7 -13
  215. data/lib/arel/attributes/attribute.rb +4 -0
  216. data/lib/arel/collectors/bind.rb +5 -0
  217. data/lib/arel/collectors/composite.rb +8 -0
  218. data/lib/arel/collectors/sql_string.rb +7 -0
  219. data/lib/arel/collectors/substitute_binds.rb +7 -0
  220. data/lib/arel/nodes/binary.rb +82 -8
  221. data/lib/arel/nodes/bind_param.rb +8 -0
  222. data/lib/arel/nodes/casted.rb +21 -9
  223. data/lib/arel/nodes/equality.rb +6 -9
  224. data/lib/arel/nodes/grouping.rb +3 -0
  225. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  226. data/lib/arel/nodes/in.rb +8 -1
  227. data/lib/arel/nodes/infix_operation.rb +13 -1
  228. data/lib/arel/nodes/join_source.rb +1 -1
  229. data/lib/arel/nodes/node.rb +7 -6
  230. data/lib/arel/nodes/ordering.rb +27 -0
  231. data/lib/arel/nodes/sql_literal.rb +3 -0
  232. data/lib/arel/nodes/table_alias.rb +7 -3
  233. data/lib/arel/nodes/unary.rb +0 -1
  234. data/lib/arel/nodes.rb +3 -1
  235. data/lib/arel/predications.rb +17 -24
  236. data/lib/arel/select_manager.rb +1 -2
  237. data/lib/arel/table.rb +13 -5
  238. data/lib/arel/visitors/dot.rb +14 -3
  239. data/lib/arel/visitors/mysql.rb +11 -1
  240. data/lib/arel/visitors/postgresql.rb +15 -5
  241. data/lib/arel/visitors/sqlite.rb +0 -1
  242. data/lib/arel/visitors/to_sql.rb +89 -79
  243. data/lib/arel/visitors/visitor.rb +0 -1
  244. data/lib/arel/visitors.rb +0 -7
  245. data/lib/arel.rb +5 -9
  246. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  247. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  248. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  249. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
  250. data/lib/rails/generators/active_record/migration.rb +6 -2
  251. data/lib/rails/generators/active_record/model/model_generator.rb +38 -2
  252. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  253. metadata +26 -26
  254. data/lib/active_record/attribute_decorators.rb +0 -90
  255. data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
  256. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  257. data/lib/active_record/define_callbacks.rb +0 -22
  258. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  259. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  260. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  261. data/lib/arel/attributes.rb +0 -22
  262. data/lib/arel/visitors/depth_first.rb +0 -204
  263. data/lib/arel/visitors/ibm_db.rb +0 -34
  264. data/lib/arel/visitors/informix.rb +0 -62
  265. data/lib/arel/visitors/mssql.rb +0 -157
  266. data/lib/arel/visitors/oracle.rb +0 -159
  267. data/lib/arel/visitors/oracle12.rb +0 -66
  268. data/lib/arel/visitors/where_sql.rb +0 -23
@@ -33,6 +33,14 @@ module ActiveRecord
33
33
  @comment = comment
34
34
  end
35
35
 
36
+ def column_options
37
+ {
38
+ length: lengths,
39
+ order: orders,
40
+ opclass: opclasses,
41
+ }
42
+ end
43
+
36
44
  private
37
45
  def concise_options(options)
38
46
  if columns.size == options.size && options.values.uniq.size == 1
@@ -69,6 +77,8 @@ module ActiveRecord
69
77
 
70
78
  ChangeColumnDefinition = Struct.new(:column, :name) #:nodoc:
71
79
 
80
+ CreateIndexDefinition = Struct.new(:index, :algorithm, :if_not_exists) # :nodoc:
81
+
72
82
  PrimaryKeyDefinition = Struct.new(:name) # :nodoc:
73
83
 
74
84
  ForeignKeyDefinition = Struct.new(:from_table, :to_table, :options) do #:nodoc:
@@ -105,8 +115,9 @@ module ActiveRecord
105
115
  !ActiveRecord::SchemaDumper.fk_ignore_pattern.match?(name) if name
106
116
  end
107
117
 
108
- def defined_for?(to_table: nil, **options)
118
+ def defined_for?(to_table: nil, validate: nil, **options)
109
119
  (to_table.nil? || to_table.to_s == self.to_table) &&
120
+ (validate.nil? || validate == options.fetch(:validate, validate)) &&
110
121
  options.all? { |k, v| self.options[k].to_s == v.to_s }
111
122
  end
112
123
 
@@ -116,6 +127,21 @@ module ActiveRecord
116
127
  end
117
128
  end
118
129
 
130
+ CheckConstraintDefinition = Struct.new(:table_name, :expression, :options) do
131
+ def name
132
+ options[:name]
133
+ end
134
+
135
+ def validate?
136
+ options.fetch(:validate, true)
137
+ end
138
+ alias validated? validate?
139
+
140
+ def export_name_on_schema_dump?
141
+ !ActiveRecord::SchemaDumper.chk_ignore_pattern.match?(name) if name
142
+ end
143
+ end
144
+
119
145
  class ReferenceDefinition # :nodoc:
120
146
  def initialize(
121
147
  name,
@@ -138,16 +164,16 @@ module ActiveRecord
138
164
  end
139
165
 
140
166
  def add_to(table)
141
- columns.each do |column_options|
142
- table.column(*column_options)
167
+ columns.each do |name, type, options|
168
+ table.column(name, type, **options)
143
169
  end
144
170
 
145
171
  if index
146
- table.index(column_names, index_options)
172
+ table.index(column_names, **index_options(table.name))
147
173
  end
148
174
 
149
175
  if foreign_key
150
- table.foreign_key(foreign_table_name, foreign_key_options)
176
+ table.foreign_key(foreign_table_name, **foreign_key_options)
151
177
  end
152
178
  end
153
179
 
@@ -162,8 +188,14 @@ module ActiveRecord
162
188
  as_options(polymorphic).merge(options.slice(:null, :first, :after))
163
189
  end
164
190
 
165
- def index_options
166
- as_options(index)
191
+ def polymorphic_index_name(table_name)
192
+ "index_#{table_name}_on_#{name}"
193
+ end
194
+
195
+ def index_options(table_name)
196
+ index_options = as_options(index)
197
+ index_options[:name] ||= polymorphic_index_name(table_name) if polymorphic
198
+ index_options
167
199
  end
168
200
 
169
201
  def foreign_key_options
@@ -199,7 +231,7 @@ module ActiveRecord
199
231
  # Appends a primary key definition to the table definition.
200
232
  # Can be called multiple times, but this is probably not a good idea.
201
233
  def primary_key(name, type = :primary_key, **options)
202
- column(name, type, options.merge(primary_key: true))
234
+ column(name, type, **options.merge(primary_key: true))
203
235
  end
204
236
 
205
237
  ##
@@ -221,16 +253,17 @@ module ActiveRecord
221
253
  end
222
254
 
223
255
  class_methods do
224
- private def define_column_methods(*column_types) # :nodoc:
256
+ def define_column_methods(*column_types) # :nodoc:
225
257
  column_types.each do |column_type|
226
258
  module_eval <<-RUBY, __FILE__, __LINE__ + 1
227
259
  def #{column_type}(*names, **options)
228
260
  raise ArgumentError, "Missing column name(s) for #{column_type}" if names.empty?
229
- names.each { |name| column(name, :#{column_type}, options) }
261
+ names.each { |name| column(name, :#{column_type}, **options) }
230
262
  end
231
263
  RUBY
232
264
  end
233
265
  end
266
+ private :define_column_methods
234
267
  end
235
268
  end
236
269
 
@@ -240,7 +273,7 @@ module ActiveRecord
240
273
  # Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
241
274
  # is actually of this type:
242
275
  #
243
- # class SomeMigration < ActiveRecord::Migration[5.0]
276
+ # class SomeMigration < ActiveRecord::Migration[6.0]
244
277
  # def up
245
278
  # create_table :foo do |t|
246
279
  # puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
@@ -255,7 +288,7 @@ module ActiveRecord
255
288
  class TableDefinition
256
289
  include ColumnMethods
257
290
 
258
- attr_reader :name, :temporary, :if_not_exists, :options, :as, :comment, :indexes, :foreign_keys
291
+ attr_reader :name, :temporary, :if_not_exists, :options, :as, :comment, :indexes, :foreign_keys, :check_constraints
259
292
 
260
293
  def initialize(
261
294
  conn,
@@ -272,6 +305,7 @@ module ActiveRecord
272
305
  @indexes = []
273
306
  @foreign_keys = []
274
307
  @primary_keys = nil
308
+ @check_constraints = []
275
309
  @temporary = temporary
276
310
  @if_not_exists = if_not_exists
277
311
  @options = options
@@ -360,10 +394,9 @@ module ActiveRecord
360
394
  # t.references :tagger, polymorphic: true
361
395
  # t.references :taggable, polymorphic: { default: 'Photo' }, index: false
362
396
  # end
363
- def column(name, type, **options)
397
+ def column(name, type, index: nil, **options)
364
398
  name = name.to_s
365
399
  type = type.to_sym if type
366
- options = options.dup
367
400
 
368
401
  if @columns_hash[name]
369
402
  if @columns_hash[name].primary_key?
@@ -373,9 +406,13 @@ module ActiveRecord
373
406
  end
374
407
  end
375
408
 
376
- index_options = options.delete(:index)
377
- index(name, index_options.is_a?(Hash) ? index_options : {}) if index_options
378
- @columns_hash[name] = new_column_definition(name, type, options)
409
+ @columns_hash[name] = new_column_definition(name, type, **options)
410
+
411
+ if index
412
+ index_options = index.is_a?(Hash) ? index : {}
413
+ index(name, **index_options)
414
+ end
415
+
379
416
  self
380
417
  end
381
418
 
@@ -389,14 +426,18 @@ module ActiveRecord
389
426
  # This is primarily used to track indexes that need to be created after the table
390
427
  #
391
428
  # index(:account_id, name: 'index_projects_on_account_id')
392
- def index(column_name, options = {})
429
+ def index(column_name, **options)
393
430
  indexes << [column_name, options]
394
431
  end
395
432
 
396
- def foreign_key(table_name, options = {}) # :nodoc:
433
+ def foreign_key(table_name, **options) # :nodoc:
397
434
  foreign_keys << [table_name, options]
398
435
  end
399
436
 
437
+ def check_constraint(expression, **options)
438
+ check_constraints << [expression, options]
439
+ end
440
+
400
441
  # Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
401
442
  # <tt>:updated_at</tt> to the table. See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
402
443
  #
@@ -408,8 +449,8 @@ module ActiveRecord
408
449
  options[:precision] = 6
409
450
  end
410
451
 
411
- column(:created_at, :datetime, options)
412
- column(:updated_at, :datetime, options)
452
+ column(:created_at, :datetime, **options)
453
+ column(:updated_at, :datetime, **options)
413
454
  end
414
455
 
415
456
  # Adds a reference.
@@ -421,7 +462,7 @@ module ActiveRecord
421
462
  # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
422
463
  def references(*args, **options)
423
464
  args.each do |ref_name|
424
- ReferenceDefinition.new(ref_name, options).add_to(self)
465
+ ReferenceDefinition.new(ref_name, **options).add_to(self)
425
466
  end
426
467
  end
427
468
  alias :belongs_to :references
@@ -456,14 +497,16 @@ module ActiveRecord
456
497
 
457
498
  class AlterTable # :nodoc:
458
499
  attr_reader :adds
459
- attr_reader :foreign_key_adds
460
- attr_reader :foreign_key_drops
500
+ attr_reader :foreign_key_adds, :foreign_key_drops
501
+ attr_reader :check_constraint_adds, :check_constraint_drops
461
502
 
462
503
  def initialize(td)
463
504
  @td = td
464
505
  @adds = []
465
506
  @foreign_key_adds = []
466
507
  @foreign_key_drops = []
508
+ @check_constraint_adds = []
509
+ @check_constraint_drops = []
467
510
  end
468
511
 
469
512
  def name; @td.name; end
@@ -476,10 +519,18 @@ module ActiveRecord
476
519
  @foreign_key_drops << name
477
520
  end
478
521
 
479
- def add_column(name, type, options)
522
+ def add_check_constraint(expression, options)
523
+ @check_constraint_adds << CheckConstraintDefinition.new(name, expression, options)
524
+ end
525
+
526
+ def drop_check_constraint(constraint_name)
527
+ @check_constraint_drops << constraint_name
528
+ end
529
+
530
+ def add_column(name, type, **options)
480
531
  name = name.to_s
481
532
  type = type.to_sym
482
- @adds << AddColumnDefinition.new(@td.new_column_definition(name, type, options))
533
+ @adds << AddColumnDefinition.new(@td.new_column_definition(name, type, **options))
483
534
  end
484
535
  end
485
536
 
@@ -496,9 +547,11 @@ module ActiveRecord
496
547
  # t.timestamps
497
548
  # t.change
498
549
  # t.change_default
550
+ # t.change_null
499
551
  # t.rename
500
552
  # t.references
501
553
  # t.belongs_to
554
+ # t.check_constraint
502
555
  # t.string
503
556
  # t.text
504
557
  # t.integer
@@ -520,6 +573,7 @@ module ActiveRecord
520
573
  # t.remove_references
521
574
  # t.remove_belongs_to
522
575
  # t.remove_index
576
+ # t.remove_check_constraint
523
577
  # t.remove_timestamps
524
578
  # end
525
579
  #
@@ -538,10 +592,12 @@ module ActiveRecord
538
592
  # t.column(:name, :string)
539
593
  #
540
594
  # See TableDefinition#column for details of the options you can use.
541
- def column(column_name, type, **options)
542
- index_options = options.delete(:index)
543
- @base.add_column(name, column_name, type, options)
544
- index(column_name, index_options.is_a?(Hash) ? index_options : {}) if index_options
595
+ def column(column_name, type, index: nil, **options)
596
+ @base.add_column(name, column_name, type, **options)
597
+ if index
598
+ index_options = index.is_a?(Hash) ? index : {}
599
+ index(column_name, **index_options)
600
+ end
545
601
  end
546
602
 
547
603
  # Checks to see if a column exists.
@@ -549,8 +605,8 @@ module ActiveRecord
549
605
  # t.string(:name) unless t.column_exists?(:name, :string)
550
606
  #
551
607
  # See {connection.column_exists?}[rdoc-ref:SchemaStatements#column_exists?]
552
- def column_exists?(column_name, type = nil, options = {})
553
- @base.column_exists?(name, column_name, type, options)
608
+ def column_exists?(column_name, type = nil, **options)
609
+ @base.column_exists?(name, column_name, type, **options)
554
610
  end
555
611
 
556
612
  # Adds a new index to the table. +column_name+ can be a single Symbol, or
@@ -561,8 +617,8 @@ module ActiveRecord
561
617
  # t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
562
618
  #
563
619
  # See {connection.add_index}[rdoc-ref:SchemaStatements#add_index] for details of the options you can use.
564
- def index(column_name, options = {})
565
- @base.add_index(name, column_name, options)
620
+ def index(column_name, **options)
621
+ @base.add_index(name, column_name, **options)
566
622
  end
567
623
 
568
624
  # Checks to see if an index exists.
@@ -590,8 +646,8 @@ module ActiveRecord
590
646
  # t.timestamps(null: false)
591
647
  #
592
648
  # See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
593
- def timestamps(options = {})
594
- @base.add_timestamps(name, options)
649
+ def timestamps(**options)
650
+ @base.add_timestamps(name, **options)
595
651
  end
596
652
 
597
653
  # Changes the column's definition according to the new options.
@@ -600,8 +656,8 @@ module ActiveRecord
600
656
  # t.change(:description, :text)
601
657
  #
602
658
  # See TableDefinition#column for details of the options you can use.
603
- def change(column_name, type, options = {})
604
- @base.change_column(name, column_name, type, options)
659
+ def change(column_name, type, **options)
660
+ @base.change_column(name, column_name, type, **options)
605
661
  end
606
662
 
607
663
  # Sets a new default value for a column.
@@ -615,14 +671,24 @@ module ActiveRecord
615
671
  @base.change_column_default(name, column_name, default_or_changes)
616
672
  end
617
673
 
674
+ # Sets or removes a NOT NULL constraint on a column.
675
+ #
676
+ # t.change_null(:qualification, true)
677
+ # t.change_null(:qualification, false, 0)
678
+ #
679
+ # See {connection.change_column_null}[rdoc-ref:SchemaStatements#change_column_null]
680
+ def change_null(column_name, null, default = nil)
681
+ @base.change_column_null(name, column_name, null, default)
682
+ end
683
+
618
684
  # Removes the column(s) from the table definition.
619
685
  #
620
686
  # t.remove(:qualification)
621
687
  # t.remove(:qualification, :experience)
622
688
  #
623
689
  # See {connection.remove_columns}[rdoc-ref:SchemaStatements#remove_columns]
624
- def remove(*column_names)
625
- @base.remove_columns(name, *column_names)
690
+ def remove(*column_names, **options)
691
+ @base.remove_columns(name, *column_names, **options)
626
692
  end
627
693
 
628
694
  # Removes the given index from the table.
@@ -630,10 +696,11 @@ module ActiveRecord
630
696
  # t.remove_index(:branch_id)
631
697
  # t.remove_index(column: [:branch_id, :party_id])
632
698
  # t.remove_index(name: :by_branch_party)
699
+ # t.remove_index(:branch_id, name: :by_branch_party)
633
700
  #
634
701
  # See {connection.remove_index}[rdoc-ref:SchemaStatements#remove_index]
635
- def remove_index(options = {})
636
- @base.remove_index(name, options)
702
+ def remove_index(column_name = nil, **options)
703
+ @base.remove_index(name, column_name, **options)
637
704
  end
638
705
 
639
706
  # Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
@@ -641,8 +708,8 @@ module ActiveRecord
641
708
  # t.remove_timestamps
642
709
  #
643
710
  # See {connection.remove_timestamps}[rdoc-ref:SchemaStatements#remove_timestamps]
644
- def remove_timestamps(options = {})
645
- @base.remove_timestamps(name, options)
711
+ def remove_timestamps(**options)
712
+ @base.remove_timestamps(name, **options)
646
713
  end
647
714
 
648
715
  # Renames a column.
@@ -662,7 +729,7 @@ module ActiveRecord
662
729
  # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
663
730
  def references(*args, **options)
664
731
  args.each do |ref_name|
665
- @base.add_reference(name, ref_name, options)
732
+ @base.add_reference(name, ref_name, **options)
666
733
  end
667
734
  end
668
735
  alias :belongs_to :references
@@ -675,7 +742,7 @@ module ActiveRecord
675
742
  # See {connection.remove_reference}[rdoc-ref:SchemaStatements#remove_reference]
676
743
  def remove_references(*args, **options)
677
744
  args.each do |ref_name|
678
- @base.remove_reference(name, ref_name, options)
745
+ @base.remove_reference(name, ref_name, **options)
679
746
  end
680
747
  end
681
748
  alias :remove_belongs_to :remove_references
@@ -686,8 +753,8 @@ module ActiveRecord
686
753
  # t.foreign_key(:authors, column: :author_id, primary_key: "id")
687
754
  #
688
755
  # See {connection.add_foreign_key}[rdoc-ref:SchemaStatements#add_foreign_key]
689
- def foreign_key(*args)
690
- @base.add_foreign_key(name, *args)
756
+ def foreign_key(*args, **options)
757
+ @base.add_foreign_key(name, *args, **options)
691
758
  end
692
759
 
693
760
  # Removes the given foreign key from the table.
@@ -696,8 +763,8 @@ module ActiveRecord
696
763
  # t.remove_foreign_key(column: :author_id)
697
764
  #
698
765
  # See {connection.remove_foreign_key}[rdoc-ref:SchemaStatements#remove_foreign_key]
699
- def remove_foreign_key(*args)
700
- @base.remove_foreign_key(name, *args)
766
+ def remove_foreign_key(*args, **options)
767
+ @base.remove_foreign_key(name, *args, **options)
701
768
  end
702
769
 
703
770
  # Checks to see if a foreign key exists.
@@ -705,8 +772,26 @@ module ActiveRecord
705
772
  # t.foreign_key(:authors) unless t.foreign_key_exists?(:authors)
706
773
  #
707
774
  # See {connection.foreign_key_exists?}[rdoc-ref:SchemaStatements#foreign_key_exists?]
708
- def foreign_key_exists?(*args)
709
- @base.foreign_key_exists?(name, *args)
775
+ def foreign_key_exists?(*args, **options)
776
+ @base.foreign_key_exists?(name, *args, **options)
777
+ end
778
+
779
+ # Adds a check constraint.
780
+ #
781
+ # t.check_constraint("price > 0", name: "price_check")
782
+ #
783
+ # See {connection.add_check_constraint}[rdoc-ref:SchemaStatements#add_check_constraint]
784
+ def check_constraint(*args)
785
+ @base.add_check_constraint(name, *args)
786
+ end
787
+
788
+ # Removes the given check constraint from the table.
789
+ #
790
+ # t.remove_check_constraint(name: "price_check")
791
+ #
792
+ # See {connection.remove_check_constraint}[rdoc-ref:SchemaStatements#remove_check_constraint]
793
+ def remove_check_constraint(*args)
794
+ @base.remove_check_constraint(name, *args)
710
795
  end
711
796
  end
712
797
  end
@@ -13,9 +13,9 @@ module ActiveRecord
13
13
  end
14
14
 
15
15
  def column_spec_for_primary_key(column)
16
- return {} if default_primary_key?(column)
17
- spec = { id: schema_type(column).inspect }
18
- spec.merge!(prepare_column_options(column).except!(:null, :comment))
16
+ spec = {}
17
+ spec[:id] = schema_type(column).inspect unless default_primary_key?(column)
18
+ spec.merge!(prepare_column_options(column).except!(:null))
19
19
  spec[:default] ||= "nil" if explicit_primary_key_default?(column)
20
20
  spec
21
21
  end