activerecord 6.0.4.1 → 6.1.0.rc1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +767 -851
- data/MIT-LICENSE +1 -1
- data/README.rdoc +3 -3
- data/lib/active_record.rb +7 -14
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/association_relation.rb +22 -14
- data/lib/active_record/associations.rb +114 -11
- data/lib/active_record/associations/alias_tracker.rb +19 -15
- data/lib/active_record/associations/association.rb +39 -27
- data/lib/active_record/associations/association_scope.rb +11 -15
- data/lib/active_record/associations/belongs_to_association.rb +15 -5
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
- data/lib/active_record/associations/builder/association.rb +9 -3
- data/lib/active_record/associations/builder/belongs_to.rb +10 -7
- data/lib/active_record/associations/builder/collection_association.rb +5 -4
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -1
- data/lib/active_record/associations/builder/has_many.rb +6 -2
- data/lib/active_record/associations/builder/has_one.rb +11 -14
- data/lib/active_record/associations/builder/singular_association.rb +1 -1
- data/lib/active_record/associations/collection_association.rb +19 -13
- data/lib/active_record/associations/collection_proxy.rb +12 -5
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +24 -2
- data/lib/active_record/associations/has_many_through_association.rb +10 -4
- data/lib/active_record/associations/has_one_association.rb +15 -1
- data/lib/active_record/associations/join_dependency.rb +63 -49
- data/lib/active_record/associations/join_dependency/join_association.rb +29 -14
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/preloader.rb +5 -3
- data/lib/active_record/associations/preloader/association.rb +13 -5
- data/lib/active_record/associations/preloader/through_association.rb +1 -1
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/attribute_assignment.rb +10 -8
- data/lib/active_record/attribute_methods.rb +52 -48
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -9
- data/lib/active_record/attribute_methods/dirty.rb +1 -11
- data/lib/active_record/attribute_methods/primary_key.rb +6 -2
- data/lib/active_record/attribute_methods/query.rb +3 -6
- data/lib/active_record/attribute_methods/read.rb +8 -11
- data/lib/active_record/attribute_methods/serialization.rb +4 -4
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -13
- data/lib/active_record/attribute_methods/write.rb +12 -20
- data/lib/active_record/attributes.rb +27 -7
- data/lib/active_record/autosave_association.rb +47 -30
- data/lib/active_record/base.rb +2 -14
- data/lib/active_record/callbacks.rb +32 -22
- data/lib/active_record/coders/yaml_column.rb +1 -1
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +180 -134
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -22
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -7
- data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +110 -30
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +224 -85
- data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -24
- data/lib/active_record/connection_adapters/abstract_adapter.rb +31 -70
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +123 -87
- data/lib/active_record/connection_adapters/column.rb +15 -1
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +22 -24
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +33 -6
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +3 -3
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -12
- data/lib/active_record/connection_adapters/pool_config.rb +63 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +12 -53
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -10
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +61 -29
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +72 -55
- data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +30 -5
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +36 -3
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +48 -50
- data/lib/active_record/connection_handling.rb +210 -71
- data/lib/active_record/core.rb +215 -49
- data/lib/active_record/database_configurations.rb +124 -85
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +52 -9
- data/lib/active_record/database_configurations/hash_config.rb +54 -8
- data/lib/active_record/database_configurations/url_config.rb +15 -40
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/enum.rb +33 -23
- data/lib/active_record/errors.rb +47 -12
- data/lib/active_record/explain.rb +9 -4
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +10 -17
- data/lib/active_record/fixture_set/model_metadata.rb +1 -2
- data/lib/active_record/fixture_set/render_context.rb +1 -1
- data/lib/active_record/fixture_set/table_row.rb +2 -2
- data/lib/active_record/fixtures.rb +54 -8
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +40 -18
- data/lib/active_record/insert_all.rb +32 -5
- data/lib/active_record/integration.rb +3 -5
- data/lib/active_record/internal_metadata.rb +15 -4
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +13 -16
- data/lib/active_record/locking/pessimistic.rb +6 -2
- data/lib/active_record/log_subscriber.rb +26 -8
- data/lib/active_record/middleware/database_selector.rb +4 -1
- data/lib/active_record/middleware/database_selector/resolver.rb +5 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/migration.rb +113 -83
- data/lib/active_record/migration/command_recorder.rb +47 -27
- data/lib/active_record/migration/compatibility.rb +67 -17
- data/lib/active_record/model_schema.rb +88 -42
- data/lib/active_record/nested_attributes.rb +2 -3
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/persistence.rb +50 -45
- data/lib/active_record/query_cache.rb +15 -5
- data/lib/active_record/querying.rb +11 -6
- data/lib/active_record/railtie.rb +64 -44
- data/lib/active_record/railties/databases.rake +253 -98
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +59 -44
- data/lib/active_record/relation.rb +90 -64
- data/lib/active_record/relation/batches.rb +38 -31
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/calculations.rb +100 -43
- data/lib/active_record/relation/finder_methods.rb +44 -14
- data/lib/active_record/relation/from_clause.rb +1 -1
- data/lib/active_record/relation/merger.rb +20 -23
- data/lib/active_record/relation/predicate_builder.rb +57 -33
- data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +2 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +3 -3
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +319 -196
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +6 -5
- data/lib/active_record/relation/where_clause.rb +104 -57
- data/lib/active_record/result.rb +41 -33
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +6 -17
- data/lib/active_record/schema_dumper.rb +34 -4
- data/lib/active_record/schema_migration.rb +0 -4
- data/lib/active_record/scoping/named.rb +1 -17
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +5 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +20 -4
- data/lib/active_record/store.rb +2 -2
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +36 -52
- data/lib/active_record/tasks/database_tasks.rb +139 -113
- data/lib/active_record/tasks/mysql_database_tasks.rb +34 -35
- data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -26
- data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -9
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +36 -33
- data/lib/active_record/timestamp.rb +4 -6
- data/lib/active_record/touch_later.rb +21 -21
- data/lib/active_record/transactions.rb +15 -64
- data/lib/active_record/type.rb +8 -1
- data/lib/active_record/type/serialized.rb +6 -2
- data/lib/active_record/type_caster/connection.rb +0 -1
- data/lib/active_record/type_caster/map.rb +8 -5
- data/lib/active_record/validations.rb +1 -0
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +24 -4
- data/lib/arel.rb +5 -13
- data/lib/arel/attributes/attribute.rb +4 -0
- data/lib/arel/collectors/bind.rb +5 -0
- data/lib/arel/collectors/composite.rb +8 -0
- data/lib/arel/collectors/sql_string.rb +7 -0
- data/lib/arel/collectors/substitute_binds.rb +7 -0
- data/lib/arel/nodes.rb +3 -1
- data/lib/arel/nodes/binary.rb +82 -8
- data/lib/arel/nodes/bind_param.rb +8 -0
- data/lib/arel/nodes/casted.rb +21 -9
- data/lib/arel/nodes/equality.rb +6 -9
- data/lib/arel/nodes/grouping.rb +3 -0
- data/lib/arel/nodes/homogeneous_in.rb +72 -0
- data/lib/arel/nodes/in.rb +8 -1
- data/lib/arel/nodes/infix_operation.rb +13 -1
- data/lib/arel/nodes/join_source.rb +1 -1
- data/lib/arel/nodes/node.rb +7 -6
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/sql_literal.rb +3 -0
- data/lib/arel/nodes/table_alias.rb +7 -3
- data/lib/arel/nodes/unary.rb +0 -1
- data/lib/arel/predications.rb +12 -18
- data/lib/arel/select_manager.rb +1 -2
- data/lib/arel/table.rb +13 -5
- data/lib/arel/visitors.rb +0 -7
- data/lib/arel/visitors/dot.rb +14 -2
- data/lib/arel/visitors/mysql.rb +11 -1
- data/lib/arel/visitors/postgresql.rb +15 -4
- data/lib/arel/visitors/to_sql.rb +89 -78
- data/lib/rails/generators/active_record/migration.rb +6 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +3 -3
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- metadata +30 -31
- data/lib/active_record/advisory_lock_base.rb +0 -18
- data/lib/active_record/attribute_decorators.rb +0 -88
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -296
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
- data/lib/active_record/relation/where_clause_factory.rb +0 -33
- data/lib/arel/attributes.rb +0 -22
- data/lib/arel/visitors/depth_first.rb +0 -203
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -156
- data/lib/arel/visitors/oracle.rb +0 -158
- data/lib/arel/visitors/oracle12.rb +0 -65
- data/lib/arel/visitors/where_sql.rb +0 -22
@@ -8,6 +8,7 @@ module ActiveRecord
|
|
8
8
|
#
|
9
9
|
# * add_column
|
10
10
|
# * add_foreign_key
|
11
|
+
# * add_check_constraint
|
11
12
|
# * add_index
|
12
13
|
# * add_reference
|
13
14
|
# * add_timestamps
|
@@ -25,6 +26,7 @@ module ActiveRecord
|
|
25
26
|
# * remove_column (must supply a type)
|
26
27
|
# * remove_columns (must specify at least one column name or more)
|
27
28
|
# * remove_foreign_key (must supply a second table)
|
29
|
+
# * remove_check_constraint
|
28
30
|
# * remove_index
|
29
31
|
# * remove_reference
|
30
32
|
# * remove_timestamps
|
@@ -39,7 +41,8 @@ module ActiveRecord
|
|
39
41
|
:drop_join_table, :drop_table, :execute_block, :enable_extension, :disable_extension,
|
40
42
|
:change_column, :execute, :remove_columns, :change_column_null,
|
41
43
|
:add_foreign_key, :remove_foreign_key,
|
42
|
-
:change_column_comment, :change_table_comment
|
44
|
+
:change_column_comment, :change_table_comment,
|
45
|
+
:add_check_constraint, :remove_check_constraint
|
43
46
|
]
|
44
47
|
include JoinTable
|
45
48
|
|
@@ -85,6 +88,11 @@ module ActiveRecord
|
|
85
88
|
# recorder.inverse_of(:rename_table, [:old, :new])
|
86
89
|
# # => [:rename_table, [:new, :old]]
|
87
90
|
#
|
91
|
+
# If the inverse of a command requires several commands, returns array of commands.
|
92
|
+
#
|
93
|
+
# recorder.inverse_of(:remove_columns, [:some_table, :foo, :bar, type: :string])
|
94
|
+
# # => [[:add_column, :some_table, :foo, :string], [:add_column, :some_table, :bar, :string]]
|
95
|
+
#
|
88
96
|
# This method will raise an +IrreversibleMigration+ exception if it cannot
|
89
97
|
# invert the +command+.
|
90
98
|
def inverse_of(command, args, &block)
|
@@ -127,9 +135,11 @@ module ActiveRecord
|
|
127
135
|
create_table: :drop_table,
|
128
136
|
create_join_table: :drop_join_table,
|
129
137
|
add_column: :remove_column,
|
138
|
+
add_index: :remove_index,
|
130
139
|
add_timestamps: :remove_timestamps,
|
131
140
|
add_reference: :remove_reference,
|
132
141
|
add_foreign_key: :remove_foreign_key,
|
142
|
+
add_check_constraint: :remove_check_constraint,
|
133
143
|
enable_extension: :disable_extension
|
134
144
|
}.each do |cmd, inv|
|
135
145
|
[[inv, cmd], [cmd, inv]].uniq.each do |method, inverse|
|
@@ -171,44 +181,49 @@ module ActiveRecord
|
|
171
181
|
super
|
172
182
|
end
|
173
183
|
|
184
|
+
def invert_remove_columns(args)
|
185
|
+
unless args[-1].is_a?(Hash) && args[-1].has_key?(:type)
|
186
|
+
raise ActiveRecord::IrreversibleMigration, "remove_columns is only reversible if given a type."
|
187
|
+
end
|
188
|
+
|
189
|
+
[:add_columns, args]
|
190
|
+
end
|
191
|
+
|
174
192
|
def invert_rename_index(args)
|
175
|
-
|
193
|
+
table_name, old_name, new_name = args
|
194
|
+
[:rename_index, [table_name, new_name, old_name]]
|
176
195
|
end
|
177
196
|
|
178
197
|
def invert_rename_column(args)
|
179
|
-
|
198
|
+
table_name, old_name, new_name = args
|
199
|
+
[:rename_column, [table_name, new_name, old_name]]
|
180
200
|
end
|
181
201
|
|
182
|
-
def
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
options_hash = options.slice(:name, :algorithm)
|
187
|
-
options_hash[:column] = columns if !options_hash[:name]
|
202
|
+
def invert_remove_index(args)
|
203
|
+
options = args.extract_options!
|
204
|
+
table, columns = args
|
188
205
|
|
189
|
-
|
190
|
-
end
|
206
|
+
columns ||= options.delete(:column)
|
191
207
|
|
192
|
-
|
193
|
-
|
194
|
-
if (options = options_or_column).is_a?(Hash)
|
195
|
-
unless options[:column]
|
196
|
-
raise ActiveRecord::IrreversibleMigration, "remove_index is only reversible if given a :column option."
|
197
|
-
end
|
198
|
-
options = options.dup
|
199
|
-
[:add_index, [table, options.delete(:column), options]]
|
200
|
-
elsif (column = options_or_column).present?
|
201
|
-
[:add_index, [table, column]]
|
208
|
+
unless columns
|
209
|
+
raise ActiveRecord::IrreversibleMigration, "remove_index is only reversible if given a :column option."
|
202
210
|
end
|
211
|
+
|
212
|
+
options.delete(:if_exists)
|
213
|
+
|
214
|
+
args = [table, columns]
|
215
|
+
args << options unless options.empty?
|
216
|
+
|
217
|
+
[:add_index, args]
|
203
218
|
end
|
204
219
|
|
205
220
|
alias :invert_add_belongs_to :invert_add_reference
|
206
221
|
alias :invert_remove_belongs_to :invert_remove_reference
|
207
222
|
|
208
223
|
def invert_change_column_default(args)
|
209
|
-
table, column, options =
|
224
|
+
table, column, options = args
|
210
225
|
|
211
|
-
unless options
|
226
|
+
unless options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
|
212
227
|
raise ActiveRecord::IrreversibleMigration, "change_column_default is only reversible if given a :from and :to option."
|
213
228
|
end
|
214
229
|
|
@@ -235,9 +250,9 @@ module ActiveRecord
|
|
235
250
|
end
|
236
251
|
|
237
252
|
def invert_change_column_comment(args)
|
238
|
-
table, column, options =
|
253
|
+
table, column, options = args
|
239
254
|
|
240
|
-
unless options
|
255
|
+
unless options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
|
241
256
|
raise ActiveRecord::IrreversibleMigration, "change_column_comment is only reversible if given a :from and :to option."
|
242
257
|
end
|
243
258
|
|
@@ -245,15 +260,20 @@ module ActiveRecord
|
|
245
260
|
end
|
246
261
|
|
247
262
|
def invert_change_table_comment(args)
|
248
|
-
table, options =
|
263
|
+
table, options = args
|
249
264
|
|
250
|
-
unless options
|
265
|
+
unless options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
|
251
266
|
raise ActiveRecord::IrreversibleMigration, "change_table_comment is only reversible if given a :from and :to option."
|
252
267
|
end
|
253
268
|
|
254
269
|
[:change_table_comment, [table, from: options[:to], to: options[:from]]]
|
255
270
|
end
|
256
271
|
|
272
|
+
def invert_remove_check_constraint(args)
|
273
|
+
raise ActiveRecord::IrreversibleMigration, "remove_check_constraint is only reversible if given an expression." if args.size < 2
|
274
|
+
super
|
275
|
+
end
|
276
|
+
|
257
277
|
def respond_to_missing?(method, _)
|
258
278
|
super || delegate.respond_to?(method)
|
259
279
|
end
|
@@ -13,7 +13,61 @@ module ActiveRecord
|
|
13
13
|
const_get(name)
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
V6_1 = Current
|
17
|
+
|
18
|
+
class V6_0 < V6_1
|
19
|
+
class ReferenceDefinition < ConnectionAdapters::ReferenceDefinition
|
20
|
+
def index_options(table_name)
|
21
|
+
as_options(index)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module TableDefinition
|
26
|
+
def references(*args, **options)
|
27
|
+
args.each do |ref_name|
|
28
|
+
ReferenceDefinition.new(ref_name, **options).add_to(self)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
alias :belongs_to :references
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_table(table_name, **options)
|
35
|
+
if block_given?
|
36
|
+
super { |t| yield compatible_table_definition(t) }
|
37
|
+
else
|
38
|
+
super
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def change_table(table_name, **options)
|
43
|
+
if block_given?
|
44
|
+
super { |t| yield compatible_table_definition(t) }
|
45
|
+
else
|
46
|
+
super
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_join_table(table_1, table_2, **options)
|
51
|
+
if block_given?
|
52
|
+
super { |t| yield compatible_table_definition(t) }
|
53
|
+
else
|
54
|
+
super
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_reference(table_name, ref_name, **options)
|
59
|
+
ReferenceDefinition.new(ref_name, **options).add_to(update_table_definition(table_name, self))
|
60
|
+
end
|
61
|
+
alias :add_belongs_to :add_reference
|
62
|
+
|
63
|
+
private
|
64
|
+
def compatible_table_definition(t)
|
65
|
+
class << t
|
66
|
+
prepend TableDefinition
|
67
|
+
end
|
68
|
+
t
|
69
|
+
end
|
70
|
+
end
|
17
71
|
|
18
72
|
class V5_2 < V6_0
|
19
73
|
module TableDefinition
|
@@ -29,13 +83,11 @@ module ActiveRecord
|
|
29
83
|
end
|
30
84
|
|
31
85
|
def invert_change_column_comment(args)
|
32
|
-
|
33
|
-
[:change_column_comment, [table_name, column_name, from: comment, to: comment]]
|
86
|
+
[:change_column_comment, args]
|
34
87
|
end
|
35
88
|
|
36
89
|
def invert_change_table_comment(args)
|
37
|
-
|
38
|
-
[:change_table_comment, [table_name, from: comment, to: comment]]
|
90
|
+
[:change_table_comment, args]
|
39
91
|
end
|
40
92
|
end
|
41
93
|
|
@@ -86,9 +138,9 @@ module ActiveRecord
|
|
86
138
|
end
|
87
139
|
|
88
140
|
class V5_1 < V5_2
|
89
|
-
def change_column(table_name, column_name, type, options
|
141
|
+
def change_column(table_name, column_name, type, **options)
|
90
142
|
if connection.adapter_name == "PostgreSQL"
|
91
|
-
super(table_name, column_name, type, options.except(:default, :null, :comment))
|
143
|
+
super(table_name, column_name, type, **options.except(:default, :null, :comment))
|
92
144
|
connection.change_column_default(table_name, column_name, options[:default]) if options.key?(:default)
|
93
145
|
connection.change_column_null(table_name, column_name, options[:null], options[:default]) if options.key?(:null)
|
94
146
|
connection.change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
|
@@ -194,7 +246,7 @@ module ActiveRecord
|
|
194
246
|
super
|
195
247
|
end
|
196
248
|
|
197
|
-
def index_exists?(table_name, column_name, options
|
249
|
+
def index_exists?(table_name, column_name, **options)
|
198
250
|
column_names = Array(column_name).map(&:to_s)
|
199
251
|
options[:name] =
|
200
252
|
if options[:name].present?
|
@@ -205,10 +257,9 @@ module ActiveRecord
|
|
205
257
|
super
|
206
258
|
end
|
207
259
|
|
208
|
-
def remove_index(table_name,
|
209
|
-
options =
|
210
|
-
|
211
|
-
super(table_name, options)
|
260
|
+
def remove_index(table_name, column_name = nil, **options)
|
261
|
+
options[:name] = index_name_for_remove(table_name, column_name, options)
|
262
|
+
super
|
212
263
|
end
|
213
264
|
|
214
265
|
private
|
@@ -219,13 +270,12 @@ module ActiveRecord
|
|
219
270
|
super
|
220
271
|
end
|
221
272
|
|
222
|
-
def index_name_for_remove(table_name, options
|
223
|
-
index_name = connection.index_name(table_name, options)
|
273
|
+
def index_name_for_remove(table_name, column_name, options)
|
274
|
+
index_name = connection.index_name(table_name, column_name || options)
|
224
275
|
|
225
276
|
unless connection.index_name_exists?(table_name, index_name)
|
226
|
-
if options.
|
227
|
-
options_without_column = options.
|
228
|
-
options_without_column.delete :column
|
277
|
+
if options.key?(:name)
|
278
|
+
options_without_column = options.except(:column)
|
229
279
|
index_name_without_column = connection.index_name(table_name, options_without_column)
|
230
280
|
|
231
281
|
if connection.index_name_exists?(table_name, index_name_without_column)
|
@@ -115,8 +115,17 @@ module ActiveRecord
|
|
115
115
|
#
|
116
116
|
# Sets the column to sort records by when no explicit order clause is used
|
117
117
|
# during an ordered finder call. Useful when the primary key is not an
|
118
|
-
# auto-incrementing integer, for example when it's a UUID.
|
119
|
-
#
|
118
|
+
# auto-incrementing integer, for example when it's a UUID. Records are subsorted
|
119
|
+
# by the primary key if it exists to ensure deterministic results.
|
120
|
+
|
121
|
+
##
|
122
|
+
# :singleton-method: immutable_strings_by_default=
|
123
|
+
# :call-seq: immutable_strings_by_default=(bool)
|
124
|
+
#
|
125
|
+
# Determines whether columns should infer their type as `:string` or
|
126
|
+
# `:immutable_string`. This setting does not affect the behavior of
|
127
|
+
# `attribute :foo, :string`. Defaults to false.
|
128
|
+
|
120
129
|
included do
|
121
130
|
mattr_accessor :primary_key_prefix_type, instance_writer: false
|
122
131
|
|
@@ -126,12 +135,13 @@ module ActiveRecord
|
|
126
135
|
class_attribute :internal_metadata_table_name, instance_accessor: false, default: "ar_internal_metadata"
|
127
136
|
class_attribute :pluralize_table_names, instance_writer: false, default: true
|
128
137
|
class_attribute :implicit_order_column, instance_accessor: false
|
138
|
+
class_attribute :immutable_strings_by_default, instance_accessor: false
|
129
139
|
|
130
140
|
self.protected_environments = ["production"]
|
131
141
|
self.inheritance_column = "type"
|
132
142
|
self.ignored_columns = [].freeze
|
133
143
|
|
134
|
-
delegate :type_for_attribute, to: :class
|
144
|
+
delegate :type_for_attribute, :column_for_attribute, to: :class
|
135
145
|
|
136
146
|
initialize_load_schema_monitor
|
137
147
|
end
|
@@ -287,37 +297,9 @@ module ActiveRecord
|
|
287
297
|
|
288
298
|
# Sets the columns names the model should ignore. Ignored columns won't have attribute
|
289
299
|
# accessors defined, and won't be referenced in SQL queries.
|
290
|
-
#
|
291
|
-
# A common usage pattern for this method is to ensure all references to an attribute
|
292
|
-
# have been removed and deployed, before a migration to drop the column from the database
|
293
|
-
# has been deployed and run. Using this two step approach to dropping columns ensures there
|
294
|
-
# is no code that raises errors due to having a cached schema in memory at the time the
|
295
|
-
# schema migration is run.
|
296
|
-
#
|
297
|
-
# For example, given a model where you want to drop the "category" attribute, first mark it
|
298
|
-
# as ignored:
|
299
|
-
#
|
300
|
-
# class Project < ActiveRecord::Base
|
301
|
-
# # schema:
|
302
|
-
# # id :bigint
|
303
|
-
# # name :string, limit: 255
|
304
|
-
# # category :string, limit: 255
|
305
|
-
#
|
306
|
-
# self.ignored_columns = [:category]
|
307
|
-
# end
|
308
|
-
#
|
309
|
-
# The schema still contains `category`, but now the model omits it, so any meta-driven code or
|
310
|
-
# schema caching will not attempt to use the column:
|
311
|
-
#
|
312
|
-
# Project.columns_hash["category"] => nil
|
313
|
-
#
|
314
|
-
# You will get an error if accessing that attribute directly, so ensure all usages of the
|
315
|
-
# column are removed (automated tests can help you find any usages).
|
316
|
-
#
|
317
|
-
# user = Project.create!(name: "First Project")
|
318
|
-
# user.category # => raises NoMethodError
|
319
300
|
def ignored_columns=(columns)
|
320
|
-
|
301
|
+
reload_schema_from_cache
|
302
|
+
@ignored_columns = columns.map(&:to_s).freeze
|
321
303
|
end
|
322
304
|
|
323
305
|
def sequence_name
|
@@ -384,7 +366,7 @@ module ActiveRecord
|
|
384
366
|
|
385
367
|
def columns
|
386
368
|
load_schema
|
387
|
-
@columns ||= columns_hash.values
|
369
|
+
@columns ||= columns_hash.values.freeze
|
388
370
|
end
|
389
371
|
|
390
372
|
def attribute_types # :nodoc:
|
@@ -409,6 +391,8 @@ module ActiveRecord
|
|
409
391
|
# a string or a symbol.
|
410
392
|
def type_for_attribute(attr_name, &block)
|
411
393
|
attr_name = attr_name.to_s
|
394
|
+
attr_name = attribute_aliases[attr_name] || attr_name
|
395
|
+
|
412
396
|
if block
|
413
397
|
attribute_types.fetch(attr_name, &block)
|
414
398
|
else
|
@@ -416,11 +400,31 @@ module ActiveRecord
|
|
416
400
|
end
|
417
401
|
end
|
418
402
|
|
403
|
+
# Returns the column object for the named attribute.
|
404
|
+
# Returns an +ActiveRecord::ConnectionAdapters::NullColumn+ if the
|
405
|
+
# named attribute does not exist.
|
406
|
+
#
|
407
|
+
# class Person < ActiveRecord::Base
|
408
|
+
# end
|
409
|
+
#
|
410
|
+
# person = Person.new
|
411
|
+
# person.column_for_attribute(:name) # the result depends on the ConnectionAdapter
|
412
|
+
# # => #<ActiveRecord::ConnectionAdapters::Column:0x007ff4ab083980 @name="name", @sql_type="varchar(255)", @null=true, ...>
|
413
|
+
#
|
414
|
+
# person.column_for_attribute(:nothing)
|
415
|
+
# # => #<ActiveRecord::ConnectionAdapters::NullColumn:0xXXX @name=nil, @sql_type=nil, @cast_type=#<Type::Value>, ...>
|
416
|
+
def column_for_attribute(name)
|
417
|
+
name = name.to_s
|
418
|
+
columns_hash.fetch(name) do
|
419
|
+
ConnectionAdapters::NullColumn.new(name)
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
419
423
|
# Returns a hash where the keys are column names and the values are
|
420
424
|
# default values when instantiating the Active Record object for this table.
|
421
425
|
def column_defaults
|
422
426
|
load_schema
|
423
|
-
@column_defaults ||= _default_attributes.deep_dup.to_hash
|
427
|
+
@column_defaults ||= _default_attributes.deep_dup.to_hash.freeze
|
424
428
|
end
|
425
429
|
|
426
430
|
def _default_attributes # :nodoc:
|
@@ -430,7 +434,7 @@ module ActiveRecord
|
|
430
434
|
|
431
435
|
# Returns an array of column names as strings.
|
432
436
|
def column_names
|
433
|
-
@column_names ||= columns.map(&:name)
|
437
|
+
@column_names ||= columns.map(&:name).freeze
|
434
438
|
end
|
435
439
|
|
436
440
|
def symbol_column_to_string(name_symbol) # :nodoc:
|
@@ -444,9 +448,8 @@ module ActiveRecord
|
|
444
448
|
@content_columns ||= columns.reject do |c|
|
445
449
|
c.name == primary_key ||
|
446
450
|
c.name == inheritance_column ||
|
447
|
-
c.name.end_with?("_id")
|
448
|
-
|
449
|
-
end
|
451
|
+
c.name.end_with?("_id", "_count")
|
452
|
+
end.freeze
|
450
453
|
end
|
451
454
|
|
452
455
|
# Resets all the cached information about columns, which will cause them
|
@@ -456,7 +459,7 @@ module ActiveRecord
|
|
456
459
|
# when just after creating a table you want to populate it with some default
|
457
460
|
# values, eg:
|
458
461
|
#
|
459
|
-
# class CreateJobLevels < ActiveRecord::Migration[
|
462
|
+
# class CreateJobLevels < ActiveRecord::Migration[6.0]
|
460
463
|
# def up
|
461
464
|
# create_table :job_levels do |t|
|
462
465
|
# t.integer :id
|
@@ -514,11 +517,20 @@ module ActiveRecord
|
|
514
517
|
end
|
515
518
|
|
516
519
|
def load_schema!
|
517
|
-
|
520
|
+
unless table_name
|
521
|
+
raise ActiveRecord::TableNotSpecified, "#{self} has no table configured. Set one with #{self}.table_name="
|
522
|
+
end
|
523
|
+
|
524
|
+
columns_hash = connection.schema_cache.columns_hash(table_name)
|
525
|
+
columns_hash = columns_hash.except(*ignored_columns) unless ignored_columns.empty?
|
526
|
+
@columns_hash = columns_hash.freeze
|
518
527
|
@columns_hash.each do |name, column|
|
528
|
+
type = connection.lookup_cast_type_from_column(column)
|
529
|
+
type = _convert_type_from_options(type)
|
530
|
+
warn_if_deprecated_type(column)
|
519
531
|
define_attribute(
|
520
532
|
name,
|
521
|
-
|
533
|
+
type,
|
522
534
|
default: column.default,
|
523
535
|
user_provided_default: false
|
524
536
|
)
|
@@ -567,6 +579,40 @@ module ActiveRecord
|
|
567
579
|
base_class.table_name
|
568
580
|
end
|
569
581
|
end
|
582
|
+
|
583
|
+
def _convert_type_from_options(type)
|
584
|
+
if immutable_strings_by_default && type.respond_to?(:to_immutable_string)
|
585
|
+
type.to_immutable_string
|
586
|
+
else
|
587
|
+
type
|
588
|
+
end
|
589
|
+
end
|
590
|
+
|
591
|
+
def warn_if_deprecated_type(column)
|
592
|
+
return if attributes_to_define_after_schema_loads.key?(column.name)
|
593
|
+
return unless column.respond_to?(:oid)
|
594
|
+
|
595
|
+
if column.array?
|
596
|
+
array_arguments = ", array: true"
|
597
|
+
else
|
598
|
+
array_arguments = ""
|
599
|
+
end
|
600
|
+
|
601
|
+
if column.sql_type.start_with?("interval")
|
602
|
+
precision_arguments = column.precision.presence && ", precision: #{column.precision}"
|
603
|
+
ActiveSupport::Deprecation.warn(<<~WARNING)
|
604
|
+
The behavior of the `:interval` type will be changing in Rails 6.2
|
605
|
+
to return an `ActiveSupport::Duration` object. If you'd like to keep
|
606
|
+
the old behavior, you can add this line to #{self.name} model:
|
607
|
+
|
608
|
+
attribute :#{column.name}, :string#{precision_arguments}#{array_arguments}
|
609
|
+
|
610
|
+
If you'd like the new behavior today, you can add this line:
|
611
|
+
|
612
|
+
attribute :#{column.name}, :interval#{precision_arguments}#{array_arguments}
|
613
|
+
WARNING
|
614
|
+
end
|
615
|
+
end
|
570
616
|
end
|
571
617
|
end
|
572
618
|
end
|