activerecord 6.0.0 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +872 -582
- data/MIT-LICENSE +1 -1
- data/README.rdoc +3 -3
- data/lib/active_record.rb +7 -13
- data/lib/active_record/aggregations.rb +1 -2
- data/lib/active_record/association_relation.rb +22 -12
- data/lib/active_record/associations.rb +116 -13
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +49 -29
- data/lib/active_record/associations/association_scope.rb +17 -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 -3
- 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 +25 -8
- data/lib/active_record/associations/collection_proxy.rb +14 -7
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +24 -3
- 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 +77 -42
- data/lib/active_record/associations/join_dependency/join_association.rb +36 -14
- data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
- data/lib/active_record/associations/preloader.rb +13 -8
- data/lib/active_record/associations/preloader/association.rb +51 -25
- data/lib/active_record/associations/preloader/through_association.rb +2 -2
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/attribute_assignment.rb +10 -9
- data/lib/active_record/attribute_methods.rb +64 -54
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -10
- data/lib/active_record/attribute_methods/dirty.rb +3 -13
- data/lib/active_record/attribute_methods/primary_key.rb +6 -4
- data/lib/active_record/attribute_methods/query.rb +3 -6
- data/lib/active_record/attribute_methods/read.rb +8 -12
- data/lib/active_record/attribute_methods/serialization.rb +11 -6
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +12 -21
- data/lib/active_record/attributes.rb +32 -8
- data/lib/active_record/autosave_association.rb +63 -44
- data/lib/active_record/base.rb +2 -14
- data/lib/active_record/callbacks.rb +153 -24
- data/lib/active_record/coders/yaml_column.rb +1 -2
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +202 -138
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +86 -37
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +4 -9
- 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 +152 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -52
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +263 -107
- data/lib/active_record/connection_adapters/abstract/transaction.rb +82 -35
- data/lib/active_record/connection_adapters/abstract_adapter.rb +74 -76
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +149 -115
- 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/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +30 -36
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -7
- 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 +17 -13
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -13
- 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 +21 -56
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
- 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 +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -6
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -3
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +72 -54
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +81 -57
- 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 +38 -12
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -5
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -57
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_handling.rb +211 -81
- data/lib/active_record/core.rb +237 -69
- data/lib/active_record/counter_cache.rb +4 -1
- 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 -41
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +2 -3
- data/lib/active_record/enum.rb +40 -16
- data/lib/active_record/errors.rb +47 -12
- data/lib/active_record/explain.rb +9 -5
- 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 -3
- data/lib/active_record/fixture_set/table_rows.rb +0 -1
- data/lib/active_record/fixtures.rb +54 -11
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/inheritance.rb +40 -21
- data/lib/active_record/insert_all.rb +39 -10
- data/lib/active_record/integration.rb +3 -5
- data/lib/active_record/internal_metadata.rb +16 -7
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +22 -17
- data/lib/active_record/locking/pessimistic.rb +6 -2
- data/lib/active_record/log_subscriber.rb +27 -9
- data/lib/active_record/middleware/database_selector.rb +4 -2
- data/lib/active_record/middleware/database_selector/resolver.rb +14 -14
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/migration.rb +114 -84
- data/lib/active_record/migration/command_recorder.rb +53 -45
- data/lib/active_record/migration/compatibility.rb +70 -20
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/model_schema.rb +120 -15
- data/lib/active_record/nested_attributes.rb +2 -5
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +50 -46
- data/lib/active_record/query_cache.rb +15 -5
- data/lib/active_record/querying.rb +12 -7
- data/lib/active_record/railtie.rb +65 -45
- data/lib/active_record/railties/databases.rake +267 -93
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +77 -63
- data/lib/active_record/relation.rb +108 -67
- data/lib/active_record/relation/batches.rb +38 -32
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/calculations.rb +102 -45
- data/lib/active_record/relation/delegation.rb +9 -7
- data/lib/active_record/relation/finder_methods.rb +55 -17
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +27 -26
- data/lib/active_record/relation/predicate_builder.rb +55 -35
- data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
- 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 +340 -180
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -8
- data/lib/active_record/relation/where_clause.rb +104 -58
- data/lib/active_record/result.rb +41 -34
- 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 +2 -8
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/scoping/default.rb +0 -1
- data/lib/active_record/scoping/named.rb +7 -18
- 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 +3 -3
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +39 -36
- data/lib/active_record/tasks/database_tasks.rb +139 -113
- data/lib/active_record/tasks/mysql_database_tasks.rb +34 -36
- data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -27
- data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -10
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +38 -16
- data/lib/active_record/timestamp.rb +4 -7
- data/lib/active_record/touch_later.rb +20 -21
- data/lib/active_record/transactions.rb +22 -71
- data/lib/active_record/type.rb +8 -2
- data/lib/active_record/type/adapter_specific_registry.rb +2 -5
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +6 -3
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- 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 +3 -3
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +24 -4
- data/lib/arel.rb +15 -12
- 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 +17 -24
- 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 -3
- data/lib/arel/visitors/mysql.rb +11 -1
- data/lib/arel/visitors/postgresql.rb +15 -5
- data/lib/arel/visitors/sqlite.rb +0 -1
- data/lib/arel/visitors/to_sql.rb +89 -79
- data/lib/arel/visitors/visitor.rb +0 -1
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration.rb +6 -2
- 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 +4 -4
- data/lib/rails/generators/active_record/model/model_generator.rb +38 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- metadata +27 -24
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
- 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 -204
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -157
- data/lib/arel/visitors/oracle.rb +0 -159
- data/lib/arel/visitors/oracle12.rb +0 -66
- data/lib/arel/visitors/where_sql.rb +0 -23
@@ -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
|
@@ -32,13 +34,15 @@ module ActiveRecord
|
|
32
34
|
# * rename_index
|
33
35
|
# * rename_table
|
34
36
|
class CommandRecorder
|
35
|
-
ReversibleAndIrreversibleMethods = [
|
37
|
+
ReversibleAndIrreversibleMethods = [
|
38
|
+
:create_table, :create_join_table, :rename_table, :add_column, :remove_column,
|
36
39
|
:rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps,
|
37
40
|
:change_column_default, :add_reference, :remove_reference, :transaction,
|
38
41
|
:drop_join_table, :drop_table, :execute_block, :enable_extension, :disable_extension,
|
39
42
|
:change_column, :execute, :remove_columns, :change_column_null,
|
40
43
|
:add_foreign_key, :remove_foreign_key,
|
41
|
-
:change_column_comment, :change_table_comment
|
44
|
+
:change_column_comment, :change_table_comment,
|
45
|
+
:add_check_constraint, :remove_check_constraint
|
42
46
|
]
|
43
47
|
include JoinTable
|
44
48
|
|
@@ -84,6 +88,11 @@ module ActiveRecord
|
|
84
88
|
# recorder.inverse_of(:rename_table, [:old, :new])
|
85
89
|
# # => [:rename_table, [:new, :old]]
|
86
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
|
+
#
|
87
96
|
# This method will raise an +IrreversibleMigration+ exception if it cannot
|
88
97
|
# invert the +command+.
|
89
98
|
def inverse_of(command, args, &block)
|
@@ -103,11 +112,12 @@ module ActiveRecord
|
|
103
112
|
record(:"#{method}", args, &block) # record(:create_table, args, &block)
|
104
113
|
end # end
|
105
114
|
EOV
|
115
|
+
ruby2_keywords(method) if respond_to?(:ruby2_keywords, true)
|
106
116
|
end
|
107
117
|
alias :add_belongs_to :add_reference
|
108
118
|
alias :remove_belongs_to :remove_reference
|
109
119
|
|
110
|
-
def change_table(table_name, options
|
120
|
+
def change_table(table_name, **options) # :nodoc:
|
111
121
|
yield delegate.update_table_definition(table_name, self)
|
112
122
|
end
|
113
123
|
|
@@ -118,7 +128,6 @@ module ActiveRecord
|
|
118
128
|
end
|
119
129
|
|
120
130
|
private
|
121
|
-
|
122
131
|
module StraightReversions # :nodoc:
|
123
132
|
private
|
124
133
|
{
|
@@ -126,8 +135,11 @@ module ActiveRecord
|
|
126
135
|
create_table: :drop_table,
|
127
136
|
create_join_table: :drop_join_table,
|
128
137
|
add_column: :remove_column,
|
138
|
+
add_index: :remove_index,
|
129
139
|
add_timestamps: :remove_timestamps,
|
130
140
|
add_reference: :remove_reference,
|
141
|
+
add_foreign_key: :remove_foreign_key,
|
142
|
+
add_check_constraint: :remove_check_constraint,
|
131
143
|
enable_extension: :disable_extension
|
132
144
|
}.each do |cmd, inv|
|
133
145
|
[[inv, cmd], [cmd, inv]].uniq.each do |method, inverse|
|
@@ -169,44 +181,49 @@ module ActiveRecord
|
|
169
181
|
super
|
170
182
|
end
|
171
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
|
+
|
172
192
|
def invert_rename_index(args)
|
173
|
-
|
193
|
+
table_name, old_name, new_name = args
|
194
|
+
[:rename_index, [table_name, new_name, old_name]]
|
174
195
|
end
|
175
196
|
|
176
197
|
def invert_rename_column(args)
|
177
|
-
|
198
|
+
table_name, old_name, new_name = args
|
199
|
+
[:rename_column, [table_name, new_name, old_name]]
|
178
200
|
end
|
179
201
|
|
180
|
-
def
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
options_hash = options.slice(:name, :algorithm)
|
185
|
-
options_hash[:column] = columns if !options_hash[:name]
|
202
|
+
def invert_remove_index(args)
|
203
|
+
options = args.extract_options!
|
204
|
+
table, columns = args
|
186
205
|
|
187
|
-
|
188
|
-
end
|
206
|
+
columns ||= options.delete(:column)
|
189
207
|
|
190
|
-
|
191
|
-
|
192
|
-
if (options = options_or_column).is_a?(Hash)
|
193
|
-
unless options[:column]
|
194
|
-
raise ActiveRecord::IrreversibleMigration, "remove_index is only reversible if given a :column option."
|
195
|
-
end
|
196
|
-
options = options.dup
|
197
|
-
[:add_index, [table, options.delete(:column), options]]
|
198
|
-
elsif (column = options_or_column).present?
|
199
|
-
[:add_index, [table, column]]
|
208
|
+
unless columns
|
209
|
+
raise ActiveRecord::IrreversibleMigration, "remove_index is only reversible if given a :column option."
|
200
210
|
end
|
211
|
+
|
212
|
+
options.delete(:if_exists)
|
213
|
+
|
214
|
+
args = [table, columns]
|
215
|
+
args << options unless options.empty?
|
216
|
+
|
217
|
+
[:add_index, args]
|
201
218
|
end
|
202
219
|
|
203
220
|
alias :invert_add_belongs_to :invert_add_reference
|
204
221
|
alias :invert_remove_belongs_to :invert_remove_reference
|
205
222
|
|
206
223
|
def invert_change_column_default(args)
|
207
|
-
table, column, options =
|
224
|
+
table, column, options = args
|
208
225
|
|
209
|
-
unless options
|
226
|
+
unless options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
|
210
227
|
raise ActiveRecord::IrreversibleMigration, "change_column_default is only reversible if given a :from and :to option."
|
211
228
|
end
|
212
229
|
|
@@ -218,21 +235,6 @@ module ActiveRecord
|
|
218
235
|
[:change_column_null, args]
|
219
236
|
end
|
220
237
|
|
221
|
-
def invert_add_foreign_key(args)
|
222
|
-
from_table, to_table, add_options = args
|
223
|
-
add_options ||= {}
|
224
|
-
|
225
|
-
if add_options[:name]
|
226
|
-
options = { name: add_options[:name] }
|
227
|
-
elsif add_options[:column]
|
228
|
-
options = { column: add_options[:column] }
|
229
|
-
else
|
230
|
-
options = to_table
|
231
|
-
end
|
232
|
-
|
233
|
-
[:remove_foreign_key, [from_table, options]]
|
234
|
-
end
|
235
|
-
|
236
238
|
def invert_remove_foreign_key(args)
|
237
239
|
options = args.extract_options!
|
238
240
|
from_table, to_table = args
|
@@ -248,9 +250,9 @@ module ActiveRecord
|
|
248
250
|
end
|
249
251
|
|
250
252
|
def invert_change_column_comment(args)
|
251
|
-
table, column, options =
|
253
|
+
table, column, options = args
|
252
254
|
|
253
|
-
unless options
|
255
|
+
unless options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
|
254
256
|
raise ActiveRecord::IrreversibleMigration, "change_column_comment is only reversible if given a :from and :to option."
|
255
257
|
end
|
256
258
|
|
@@ -258,15 +260,20 @@ module ActiveRecord
|
|
258
260
|
end
|
259
261
|
|
260
262
|
def invert_change_table_comment(args)
|
261
|
-
table, options =
|
263
|
+
table, options = args
|
262
264
|
|
263
|
-
unless options
|
265
|
+
unless options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
|
264
266
|
raise ActiveRecord::IrreversibleMigration, "change_table_comment is only reversible if given a :from and :to option."
|
265
267
|
end
|
266
268
|
|
267
269
|
[:change_table_comment, [table, from: options[:to], to: options[:from]]]
|
268
270
|
end
|
269
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
|
+
|
270
277
|
def respond_to_missing?(method, _)
|
271
278
|
super || delegate.respond_to?(method)
|
272
279
|
end
|
@@ -279,6 +286,7 @@ module ActiveRecord
|
|
279
286
|
super
|
280
287
|
end
|
281
288
|
end
|
289
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
282
290
|
end
|
283
291
|
end
|
284
292
|
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)
|
@@ -97,7 +149,7 @@ module ActiveRecord
|
|
97
149
|
end
|
98
150
|
end
|
99
151
|
|
100
|
-
def create_table(table_name, options
|
152
|
+
def create_table(table_name, **options)
|
101
153
|
if connection.adapter_name == "Mysql2"
|
102
154
|
super(table_name, options: "ENGINE=InnoDB", **options)
|
103
155
|
else
|
@@ -119,7 +171,7 @@ module ActiveRecord
|
|
119
171
|
alias :belongs_to :references
|
120
172
|
end
|
121
173
|
|
122
|
-
def create_table(table_name, options
|
174
|
+
def create_table(table_name, **options)
|
123
175
|
if connection.adapter_name == "PostgreSQL"
|
124
176
|
if options[:id] == :uuid && !options.key?(:default)
|
125
177
|
options[:default] = "uuid_generate_v4()"
|
@@ -147,7 +199,7 @@ module ActiveRecord
|
|
147
199
|
super
|
148
200
|
end
|
149
201
|
|
150
|
-
def add_column(table_name, column_name, type, options
|
202
|
+
def add_column(table_name, column_name, type, **options)
|
151
203
|
if type == :primary_key
|
152
204
|
type = :integer
|
153
205
|
options[:primary_key] = true
|
@@ -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,8 +297,38 @@ 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.
|
300
|
+
#
|
301
|
+
# A common usage pattern for this method is to ensure all references to an attribute
|
302
|
+
# have been removed and deployed, before a migration to drop the column from the database
|
303
|
+
# has been deployed and run. Using this two step approach to dropping columns ensures there
|
304
|
+
# is no code that raises errors due to having a cached schema in memory at the time the
|
305
|
+
# schema migration is run.
|
306
|
+
#
|
307
|
+
# For example, given a model where you want to drop the "category" attribute, first mark it
|
308
|
+
# as ignored:
|
309
|
+
#
|
310
|
+
# class Project < ActiveRecord::Base
|
311
|
+
# # schema:
|
312
|
+
# # id :bigint
|
313
|
+
# # name :string, limit: 255
|
314
|
+
# # category :string, limit: 255
|
315
|
+
#
|
316
|
+
# self.ignored_columns = [:category]
|
317
|
+
# end
|
318
|
+
#
|
319
|
+
# The schema still contains `category`, but now the model omits it, so any meta-driven code or
|
320
|
+
# schema caching will not attempt to use the column:
|
321
|
+
#
|
322
|
+
# Project.columns_hash["category"] => nil
|
323
|
+
#
|
324
|
+
# You will get an error if accessing that attribute directly, so ensure all usages of the
|
325
|
+
# column are removed (automated tests can help you find any usages).
|
326
|
+
#
|
327
|
+
# user = Project.create!(name: "First Project")
|
328
|
+
# user.category # => raises NoMethodError
|
290
329
|
def ignored_columns=(columns)
|
291
|
-
|
330
|
+
reload_schema_from_cache
|
331
|
+
@ignored_columns = columns.map(&:to_s).freeze
|
292
332
|
end
|
293
333
|
|
294
334
|
def sequence_name
|
@@ -355,7 +395,7 @@ module ActiveRecord
|
|
355
395
|
|
356
396
|
def columns
|
357
397
|
load_schema
|
358
|
-
@columns ||= columns_hash.values
|
398
|
+
@columns ||= columns_hash.values.freeze
|
359
399
|
end
|
360
400
|
|
361
401
|
def attribute_types # :nodoc:
|
@@ -380,6 +420,8 @@ module ActiveRecord
|
|
380
420
|
# a string or a symbol.
|
381
421
|
def type_for_attribute(attr_name, &block)
|
382
422
|
attr_name = attr_name.to_s
|
423
|
+
attr_name = attribute_aliases[attr_name] || attr_name
|
424
|
+
|
383
425
|
if block
|
384
426
|
attribute_types.fetch(attr_name, &block)
|
385
427
|
else
|
@@ -387,11 +429,31 @@ module ActiveRecord
|
|
387
429
|
end
|
388
430
|
end
|
389
431
|
|
432
|
+
# Returns the column object for the named attribute.
|
433
|
+
# Returns an +ActiveRecord::ConnectionAdapters::NullColumn+ if the
|
434
|
+
# named attribute does not exist.
|
435
|
+
#
|
436
|
+
# class Person < ActiveRecord::Base
|
437
|
+
# end
|
438
|
+
#
|
439
|
+
# person = Person.new
|
440
|
+
# person.column_for_attribute(:name) # the result depends on the ConnectionAdapter
|
441
|
+
# # => #<ActiveRecord::ConnectionAdapters::Column:0x007ff4ab083980 @name="name", @sql_type="varchar(255)", @null=true, ...>
|
442
|
+
#
|
443
|
+
# person.column_for_attribute(:nothing)
|
444
|
+
# # => #<ActiveRecord::ConnectionAdapters::NullColumn:0xXXX @name=nil, @sql_type=nil, @cast_type=#<Type::Value>, ...>
|
445
|
+
def column_for_attribute(name)
|
446
|
+
name = name.to_s
|
447
|
+
columns_hash.fetch(name) do
|
448
|
+
ConnectionAdapters::NullColumn.new(name)
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
390
452
|
# Returns a hash where the keys are column names and the values are
|
391
453
|
# default values when instantiating the Active Record object for this table.
|
392
454
|
def column_defaults
|
393
455
|
load_schema
|
394
|
-
@column_defaults ||= _default_attributes.deep_dup.to_hash
|
456
|
+
@column_defaults ||= _default_attributes.deep_dup.to_hash.freeze
|
395
457
|
end
|
396
458
|
|
397
459
|
def _default_attributes # :nodoc:
|
@@ -401,7 +463,7 @@ module ActiveRecord
|
|
401
463
|
|
402
464
|
# Returns an array of column names as strings.
|
403
465
|
def column_names
|
404
|
-
@column_names ||= columns.map(&:name)
|
466
|
+
@column_names ||= columns.map(&:name).freeze
|
405
467
|
end
|
406
468
|
|
407
469
|
def symbol_column_to_string(name_symbol) # :nodoc:
|
@@ -415,9 +477,8 @@ module ActiveRecord
|
|
415
477
|
@content_columns ||= columns.reject do |c|
|
416
478
|
c.name == primary_key ||
|
417
479
|
c.name == inheritance_column ||
|
418
|
-
c.name.end_with?("_id")
|
419
|
-
|
420
|
-
end
|
480
|
+
c.name.end_with?("_id", "_count")
|
481
|
+
end.freeze
|
421
482
|
end
|
422
483
|
|
423
484
|
# Resets all the cached information about columns, which will cause them
|
@@ -427,7 +488,7 @@ module ActiveRecord
|
|
427
488
|
# when just after creating a table you want to populate it with some default
|
428
489
|
# values, eg:
|
429
490
|
#
|
430
|
-
# class CreateJobLevels < ActiveRecord::Migration[
|
491
|
+
# class CreateJobLevels < ActiveRecord::Migration[6.0]
|
431
492
|
# def up
|
432
493
|
# create_table :job_levels do |t|
|
433
494
|
# t.integer :id
|
@@ -456,13 +517,11 @@ module ActiveRecord
|
|
456
517
|
end
|
457
518
|
|
458
519
|
protected
|
459
|
-
|
460
520
|
def initialize_load_schema_monitor
|
461
521
|
@load_schema_monitor = Monitor.new
|
462
522
|
end
|
463
523
|
|
464
524
|
private
|
465
|
-
|
466
525
|
def inherited(child_class)
|
467
526
|
super
|
468
527
|
child_class.initialize_load_schema_monitor
|
@@ -480,15 +539,27 @@ module ActiveRecord
|
|
480
539
|
load_schema!
|
481
540
|
|
482
541
|
@schema_loaded = true
|
542
|
+
rescue
|
543
|
+
reload_schema_from_cache # If the schema loading failed half way through, we must reset the state.
|
544
|
+
raise
|
483
545
|
end
|
484
546
|
end
|
485
547
|
|
486
548
|
def load_schema!
|
487
|
-
|
549
|
+
unless table_name
|
550
|
+
raise ActiveRecord::TableNotSpecified, "#{self} has no table configured. Set one with #{self}.table_name="
|
551
|
+
end
|
552
|
+
|
553
|
+
columns_hash = connection.schema_cache.columns_hash(table_name)
|
554
|
+
columns_hash = columns_hash.except(*ignored_columns) unless ignored_columns.empty?
|
555
|
+
@columns_hash = columns_hash.freeze
|
488
556
|
@columns_hash.each do |name, column|
|
557
|
+
type = connection.lookup_cast_type_from_column(column)
|
558
|
+
type = _convert_type_from_options(type)
|
559
|
+
warn_if_deprecated_type(column)
|
489
560
|
define_attribute(
|
490
561
|
name,
|
491
|
-
|
562
|
+
type,
|
492
563
|
default: column.default,
|
493
564
|
user_provided_default: false
|
494
565
|
)
|
@@ -537,6 +608,40 @@ module ActiveRecord
|
|
537
608
|
base_class.table_name
|
538
609
|
end
|
539
610
|
end
|
611
|
+
|
612
|
+
def _convert_type_from_options(type)
|
613
|
+
if immutable_strings_by_default && type.respond_to?(:to_immutable_string)
|
614
|
+
type.to_immutable_string
|
615
|
+
else
|
616
|
+
type
|
617
|
+
end
|
618
|
+
end
|
619
|
+
|
620
|
+
def warn_if_deprecated_type(column)
|
621
|
+
return if attributes_to_define_after_schema_loads.key?(column.name)
|
622
|
+
return unless column.respond_to?(:oid)
|
623
|
+
|
624
|
+
if column.array?
|
625
|
+
array_arguments = ", array: true"
|
626
|
+
else
|
627
|
+
array_arguments = ""
|
628
|
+
end
|
629
|
+
|
630
|
+
if column.sql_type.start_with?("interval")
|
631
|
+
precision_arguments = column.precision.presence && ", precision: #{column.precision}"
|
632
|
+
ActiveSupport::Deprecation.warn(<<~WARNING)
|
633
|
+
The behavior of the `:interval` type will be changing in Rails 6.2
|
634
|
+
to return an `ActiveSupport::Duration` object. If you'd like to keep
|
635
|
+
the old behavior, you can add this line to #{self.name} model:
|
636
|
+
|
637
|
+
attribute :#{column.name}, :string#{precision_arguments}#{array_arguments}
|
638
|
+
|
639
|
+
If you'd like the new behavior today, you can add this line:
|
640
|
+
|
641
|
+
attribute :#{column.name}, :interval#{precision_arguments}#{array_arguments}
|
642
|
+
WARNING
|
643
|
+
end
|
644
|
+
end
|
540
645
|
end
|
541
646
|
end
|
542
647
|
end
|