activerecord 6.0.6 → 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 +783 -910
- data/MIT-LICENSE +1 -1
- data/README.rdoc +3 -3
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/association_relation.rb +22 -14
- data/lib/active_record/associations/alias_tracker.rb +19 -15
- data/lib/active_record/associations/association.rb +43 -26
- 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/join_association.rb +29 -14
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +63 -49
- 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/preloader.rb +5 -3
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations.rb +114 -11
- data/lib/active_record/attribute_assignment.rb +10 -8
- 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 +11 -5
- 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/attribute_methods.rb +64 -54
- data/lib/active_record/attributes.rb +32 -7
- data/lib/active_record/autosave_association.rb +47 -30
- data/lib/active_record/base.rb +2 -14
- data/lib/active_record/callbacks.rb +152 -22
- data/lib/active_record/coders/yaml_column.rb +2 -24
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +185 -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 +80 -32
- data/lib/active_record/connection_adapters/abstract_adapter.rb +49 -72
- 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 +32 -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/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 -2
- 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/oid.rb +2 -0
- 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_adapters.rb +50 -0
- data/lib/active_record/connection_handling.rb +210 -71
- data/lib/active_record/core.rb +223 -66
- 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/database_configurations.rb +124 -85
- 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 +27 -10
- 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 +2 -2
- data/lib/active_record/inheritance.rb +40 -18
- data/lib/active_record/insert_all.rb +34 -5
- 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 +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/resolver/session.rb +3 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +5 -0
- data/lib/active_record/middleware/database_selector.rb +4 -1
- data/lib/active_record/migration/command_recorder.rb +47 -27
- data/lib/active_record/migration/compatibility.rb +67 -17
- data/lib/active_record/migration.rb +113 -83
- data/lib/active_record/model_schema.rb +88 -13
- 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 +266 -95
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +60 -44
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +38 -31
- 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/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/predicate_builder.rb +57 -33
- data/lib/active_record/relation/query_methods.rb +318 -195
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -7
- data/lib/active_record/relation/where_clause.rb +104 -57
- data/lib/active_record/relation.rb +90 -64
- 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 +2 -8
- 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 +39 -51
- 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/serialized.rb +6 -2
- data/lib/active_record/type.rb +8 -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/associated.rb +1 -1
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +24 -4
- data/lib/active_record/validations.rb +1 -0
- data/lib/active_record.rb +7 -14
- 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/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/nodes.rb +3 -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/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/arel/visitors.rb +0 -7
- data/lib/arel.rb +5 -13
- 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/migration.rb +6 -1
- 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 +28 -30
- 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
@@ -12,26 +12,24 @@ module ActiveRecord
|
|
12
12
|
delegate :connection, :establish_connection, :clear_active_connections!,
|
13
13
|
to: ActiveRecord::Base
|
14
14
|
|
15
|
-
def
|
16
|
-
|
15
|
+
def self.using_database_configurations?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(db_config)
|
20
|
+
@db_config = db_config
|
21
|
+
@configuration_hash = db_config.configuration_hash
|
17
22
|
end
|
18
23
|
|
19
24
|
def create(master_established = false)
|
20
25
|
establish_master_connection unless master_established
|
21
|
-
connection.create_database
|
22
|
-
|
23
|
-
establish_connection configuration
|
24
|
-
rescue ActiveRecord::StatementInvalid => error
|
25
|
-
if error.cause.is_a?(PG::DuplicateDatabase)
|
26
|
-
raise DatabaseAlreadyExists
|
27
|
-
else
|
28
|
-
raise
|
29
|
-
end
|
26
|
+
connection.create_database(db_config.database, configuration_hash.merge(encoding: encoding))
|
27
|
+
establish_connection(db_config)
|
30
28
|
end
|
31
29
|
|
32
30
|
def drop
|
33
31
|
establish_master_connection
|
34
|
-
connection.drop_database
|
32
|
+
connection.drop_database(db_config.database)
|
35
33
|
end
|
36
34
|
|
37
35
|
def charset
|
@@ -54,14 +52,14 @@ module ActiveRecord
|
|
54
52
|
search_path = \
|
55
53
|
case ActiveRecord::Base.dump_schemas
|
56
54
|
when :schema_search_path
|
57
|
-
|
55
|
+
configuration_hash[:schema_search_path]
|
58
56
|
when :all
|
59
57
|
nil
|
60
58
|
when String
|
61
59
|
ActiveRecord::Base.dump_schemas
|
62
60
|
end
|
63
61
|
|
64
|
-
args = ["-
|
62
|
+
args = ["--schema-only", "--no-privileges", "--no-owner", "--file", filename]
|
65
63
|
args.concat(Array(extra_flags)) if extra_flags
|
66
64
|
unless search_path.blank?
|
67
65
|
args += search_path.split(",").map do |part|
|
@@ -74,7 +72,7 @@ module ActiveRecord
|
|
74
72
|
args += ignore_tables.flat_map { |table| ["-T", table] }
|
75
73
|
end
|
76
74
|
|
77
|
-
args <<
|
75
|
+
args << db_config.database
|
78
76
|
run_cmd("pg_dump", args, "dumping")
|
79
77
|
remove_sql_header_comments(filename)
|
80
78
|
File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" }
|
@@ -82,31 +80,31 @@ module ActiveRecord
|
|
82
80
|
|
83
81
|
def structure_load(filename, extra_flags)
|
84
82
|
set_psql_env
|
85
|
-
args = ["
|
83
|
+
args = ["--set", ON_ERROR_STOP_1, "--quiet", "--no-psqlrc", "--file", filename]
|
86
84
|
args.concat(Array(extra_flags)) if extra_flags
|
87
|
-
args <<
|
85
|
+
args << db_config.database
|
88
86
|
run_cmd("psql", args, "loading")
|
89
87
|
end
|
90
88
|
|
91
89
|
private
|
92
|
-
attr_reader :
|
90
|
+
attr_reader :db_config, :configuration_hash
|
93
91
|
|
94
92
|
def encoding
|
95
|
-
|
93
|
+
configuration_hash[:encoding] || DEFAULT_ENCODING
|
96
94
|
end
|
97
95
|
|
98
96
|
def establish_master_connection
|
99
|
-
establish_connection
|
100
|
-
|
101
|
-
|
97
|
+
establish_connection configuration_hash.merge(
|
98
|
+
database: "postgres",
|
99
|
+
schema_search_path: "public"
|
102
100
|
)
|
103
101
|
end
|
104
102
|
|
105
103
|
def set_psql_env
|
106
|
-
ENV["PGHOST"] =
|
107
|
-
ENV["PGPORT"] =
|
108
|
-
ENV["PGPASSWORD"] =
|
109
|
-
ENV["PGUSER"] =
|
104
|
+
ENV["PGHOST"] = db_config.host if db_config.host
|
105
|
+
ENV["PGPORT"] = configuration_hash[:port].to_s if configuration_hash[:port]
|
106
|
+
ENV["PGPASSWORD"] = configuration_hash[:password].to_s if configuration_hash[:password]
|
107
|
+
ENV["PGUSER"] = configuration_hash[:username].to_s if configuration_hash[:username]
|
110
108
|
end
|
111
109
|
|
112
110
|
def run_cmd(cmd, args, action)
|
@@ -5,20 +5,25 @@ module ActiveRecord
|
|
5
5
|
class SQLiteDatabaseTasks # :nodoc:
|
6
6
|
delegate :connection, :establish_connection, to: ActiveRecord::Base
|
7
7
|
|
8
|
-
def
|
9
|
-
|
8
|
+
def self.using_database_configurations?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(db_config, root = ActiveRecord::Tasks::DatabaseTasks.root)
|
13
|
+
@db_config = db_config
|
14
|
+
@root = root
|
10
15
|
end
|
11
16
|
|
12
17
|
def create
|
13
|
-
raise DatabaseAlreadyExists if File.exist?(
|
18
|
+
raise DatabaseAlreadyExists if File.exist?(db_config.database)
|
14
19
|
|
15
|
-
establish_connection
|
20
|
+
establish_connection(db_config)
|
16
21
|
connection
|
17
22
|
end
|
18
23
|
|
19
24
|
def drop
|
20
25
|
require "pathname"
|
21
|
-
path = Pathname.new
|
26
|
+
path = Pathname.new(db_config.database)
|
22
27
|
file = path.absolute? ? path.to_s : File.join(root, path)
|
23
28
|
|
24
29
|
FileUtils.rm(file)
|
@@ -40,7 +45,7 @@ module ActiveRecord
|
|
40
45
|
def structure_dump(filename, extra_flags)
|
41
46
|
args = []
|
42
47
|
args.concat(Array(extra_flags)) if extra_flags
|
43
|
-
args <<
|
48
|
+
args << db_config.database
|
44
49
|
|
45
50
|
ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
|
46
51
|
if ignore_tables.any?
|
@@ -53,13 +58,12 @@ module ActiveRecord
|
|
53
58
|
end
|
54
59
|
|
55
60
|
def structure_load(filename, extra_flags)
|
56
|
-
dbfile = configuration["database"]
|
57
61
|
flags = extra_flags.join(" ") if extra_flags
|
58
|
-
`sqlite3 #{flags} #{
|
62
|
+
`sqlite3 #{flags} #{db_config.database} < "#{filename}"`
|
59
63
|
end
|
60
64
|
|
61
65
|
private
|
62
|
-
attr_reader :
|
66
|
+
attr_reader :db_config, :root
|
63
67
|
|
64
68
|
def run_cmd(cmd, args, out)
|
65
69
|
fail run_cmd_error(cmd, args) unless Kernel.system(cmd, *args, out: out)
|
@@ -5,18 +5,19 @@ require "active_support/testing/parallelization"
|
|
5
5
|
module ActiveRecord
|
6
6
|
module TestDatabases # :nodoc:
|
7
7
|
ActiveSupport::Testing::Parallelization.after_fork_hook do |i|
|
8
|
-
create_and_load_schema(i, env_name:
|
8
|
+
create_and_load_schema(i, env_name: ActiveRecord::ConnectionHandling::DEFAULT_ENV.call)
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.create_and_load_schema(i, env_name:)
|
12
12
|
old, ENV["VERBOSE"] = ENV["VERBOSE"], "false"
|
13
13
|
|
14
14
|
ActiveRecord::Base.configurations.configs_for(env_name: env_name).each do |db_config|
|
15
|
-
db_config.
|
16
|
-
|
15
|
+
db_config._database = "#{db_config.database}-#{i}"
|
16
|
+
|
17
|
+
ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config, ActiveRecord::Base.schema_format, nil)
|
17
18
|
end
|
18
19
|
ensure
|
19
|
-
ActiveRecord::Base.establish_connection
|
20
|
+
ActiveRecord::Base.establish_connection
|
20
21
|
ENV["VERBOSE"] = old
|
21
22
|
end
|
22
23
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/enumerable"
|
4
|
+
|
3
5
|
module ActiveRecord
|
4
6
|
module TestFixtures
|
5
7
|
extend ActiveSupport::Concern
|
@@ -21,7 +23,6 @@ module ActiveRecord
|
|
21
23
|
class_attribute :use_transactional_tests, default: true
|
22
24
|
class_attribute :use_instantiated_fixtures, default: false # true, false, or :no_instances
|
23
25
|
class_attribute :pre_loaded_fixtures, default: false
|
24
|
-
class_attribute :config, default: ActiveRecord::Base
|
25
26
|
class_attribute :lock_threads, default: true
|
26
27
|
end
|
27
28
|
|
@@ -41,8 +42,9 @@ module ActiveRecord
|
|
41
42
|
def fixtures(*fixture_set_names)
|
42
43
|
if fixture_set_names.first == :all
|
43
44
|
raise StandardError, "No fixture path found. Please set `#{self}.fixture_path`." if fixture_path.blank?
|
44
|
-
fixture_set_names = Dir["
|
45
|
-
fixture_set_names.
|
45
|
+
fixture_set_names = Dir[::File.join(fixture_path, "{**,*}/*.{yml}")].uniq
|
46
|
+
fixture_set_names.reject! { |f| f.start_with?(file_fixture_path.to_s) } if defined?(file_fixture_path) && file_fixture_path
|
47
|
+
fixture_set_names.map! { |f| f[fixture_path.to_s.size..-5].delete_prefix("/") }
|
46
48
|
else
|
47
49
|
fixture_set_names = fixture_set_names.flatten.map(&:to_s)
|
48
50
|
end
|
@@ -97,7 +99,7 @@ module ActiveRecord
|
|
97
99
|
|
98
100
|
def run_in_transaction?
|
99
101
|
use_transactional_tests &&
|
100
|
-
!self.class.uses_transaction?(
|
102
|
+
!self.class.uses_transaction?(name)
|
101
103
|
end
|
102
104
|
|
103
105
|
def setup_fixtures(config = ActiveRecord::Base)
|
@@ -112,8 +114,6 @@ module ActiveRecord
|
|
112
114
|
|
113
115
|
# Load fixtures once and begin transaction.
|
114
116
|
if run_in_transaction?
|
115
|
-
@saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
|
116
|
-
|
117
117
|
if @@already_loaded_fixtures[self.class]
|
118
118
|
@loaded_fixtures = @@already_loaded_fixtures[self.class]
|
119
119
|
else
|
@@ -131,11 +131,12 @@ module ActiveRecord
|
|
131
131
|
# When connections are established in the future, begin a transaction too
|
132
132
|
@connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
|
133
133
|
spec_name = payload[:spec_name] if payload.key?(:spec_name)
|
134
|
+
shard = payload[:shard] if payload.key?(:shard)
|
134
135
|
setup_shared_connection_pool
|
135
136
|
|
136
137
|
if spec_name
|
137
138
|
begin
|
138
|
-
connection = ActiveRecord::Base.connection_handler.retrieve_connection(spec_name)
|
139
|
+
connection = ActiveRecord::Base.connection_handler.retrieve_connection(spec_name, shard: shard)
|
139
140
|
rescue ConnectionNotEstablished
|
140
141
|
connection = nil
|
141
142
|
end
|
@@ -168,7 +169,6 @@ module ActiveRecord
|
|
168
169
|
connection.pool.lock_thread = false
|
169
170
|
end
|
170
171
|
@fixture_connections.clear
|
171
|
-
teardown_shared_connection_pool
|
172
172
|
else
|
173
173
|
ActiveRecord::FixtureSet.reset_cache
|
174
174
|
end
|
@@ -190,38 +190,41 @@ module ActiveRecord
|
|
190
190
|
# need to share a connection pool so that the reading connection
|
191
191
|
# can see data in the open transaction on the writing connection.
|
192
192
|
def setup_shared_connection_pool
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
handler
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
193
|
+
if ActiveRecord::Base.legacy_connection_handling
|
194
|
+
writing_handler = ActiveRecord::Base.connection_handlers[ActiveRecord::Base.writing_role]
|
195
|
+
|
196
|
+
ActiveRecord::Base.connection_handlers.values.each do |handler|
|
197
|
+
if handler != writing_handler
|
198
|
+
handler.connection_pool_names.each do |name|
|
199
|
+
writing_pool_manager = writing_handler.send(:owner_to_pool_manager)[name]
|
200
|
+
return unless writing_pool_manager
|
201
|
+
|
202
|
+
pool_manager = handler.send(:owner_to_pool_manager)[name]
|
203
|
+
pool_manager.shard_names.each do |shard_name|
|
204
|
+
writing_pool_config = writing_pool_manager.get_pool_config(nil, shard_name)
|
205
|
+
pool_manager.set_pool_config(nil, shard_name, writing_pool_config)
|
206
|
+
end
|
207
|
+
end
|
207
208
|
end
|
208
209
|
end
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
210
|
+
else
|
211
|
+
handler = ActiveRecord::Base.connection_handler
|
212
|
+
|
213
|
+
handler.connection_pool_names.each do |name|
|
214
|
+
pool_manager = handler.send(:owner_to_pool_manager)[name]
|
215
|
+
pool_manager.shard_names.each do |shard_name|
|
216
|
+
writing_pool_config = pool_manager.get_pool_config(ActiveRecord::Base.writing_role, shard_name)
|
217
|
+
pool_manager.role_names.each do |role|
|
218
|
+
next unless pool_manager.get_pool_config(role, shard_name)
|
219
|
+
pool_manager.set_pool_config(role, shard_name, writing_pool_config)
|
220
|
+
end
|
221
|
+
end
|
216
222
|
end
|
217
223
|
end
|
218
|
-
|
219
|
-
@saved_pool_configs.clear
|
220
224
|
end
|
221
225
|
|
222
226
|
def load_fixtures(config)
|
223
|
-
|
224
|
-
Hash[fixtures.map { |f| [f.name, f] }]
|
227
|
+
ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names, config).index_by(&:name)
|
225
228
|
end
|
226
229
|
|
227
230
|
def instantiate_fixtures
|
@@ -80,11 +80,11 @@ module ActiveRecord
|
|
80
80
|
|
81
81
|
private
|
82
82
|
def timestamp_attributes_for_create
|
83
|
-
["created_at", "created_on"]
|
83
|
+
["created_at", "created_on"].map! { |name| attribute_aliases[name] || name }
|
84
84
|
end
|
85
85
|
|
86
86
|
def timestamp_attributes_for_update
|
87
|
-
["updated_at", "updated_on"]
|
87
|
+
["updated_at", "updated_on"].map! { |name| attribute_aliases[name] || name }
|
88
88
|
end
|
89
89
|
|
90
90
|
def reload_schema_from_cache
|
@@ -101,9 +101,7 @@ module ActiveRecord
|
|
101
101
|
current_time = current_time_from_proper_timezone
|
102
102
|
|
103
103
|
all_timestamp_attributes_in_model.each do |column|
|
104
|
-
|
105
|
-
_write_attribute(column, current_time)
|
106
|
-
end
|
104
|
+
_write_attribute(column, current_time) unless _read_attribute(column)
|
107
105
|
end
|
108
106
|
end
|
109
107
|
|
@@ -159,7 +157,7 @@ module ActiveRecord
|
|
159
157
|
def clear_timestamp_attributes
|
160
158
|
all_timestamp_attributes_in_model.each do |attribute_name|
|
161
159
|
self[attribute_name] = nil
|
162
|
-
|
160
|
+
clear_attribute_change(attribute_name)
|
163
161
|
end
|
164
162
|
end
|
165
163
|
end
|
@@ -3,22 +3,20 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
# = Active Record Touch Later
|
5
5
|
module TouchLater # :nodoc:
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
before_commit_without_transaction_enrollment :touch_deferred_attributes
|
6
|
+
def before_committed!
|
7
|
+
touch_deferred_attributes if has_defer_touch_attrs? && persisted?
|
8
|
+
super
|
10
9
|
end
|
11
10
|
|
12
|
-
def touch_later(*names
|
13
|
-
unless persisted?
|
14
|
-
raise ActiveRecordError, <<-MSG.squish
|
15
|
-
cannot touch on a new or destroyed record object. Consider using
|
16
|
-
persisted?, new_record?, or destroyed? before touching
|
17
|
-
MSG
|
18
|
-
end
|
11
|
+
def touch_later(*names) # :nodoc:
|
12
|
+
_raise_record_not_touched_error unless persisted?
|
19
13
|
|
20
14
|
@_defer_touch_attrs ||= timestamp_attributes_for_update_in_model
|
21
|
-
@_defer_touch_attrs |= names
|
15
|
+
@_defer_touch_attrs |= names.map! do |name|
|
16
|
+
name = name.to_s
|
17
|
+
self.class.attribute_aliases[name] || name
|
18
|
+
end unless names.empty?
|
19
|
+
|
22
20
|
@_touch_time = current_time_from_proper_timezone
|
23
21
|
|
24
22
|
surreptitiously_touch @_defer_touch_attrs
|
@@ -36,22 +34,24 @@ module ActiveRecord
|
|
36
34
|
def touch(*names, time: nil) # :nodoc:
|
37
35
|
if has_defer_touch_attrs?
|
38
36
|
names |= @_defer_touch_attrs
|
37
|
+
super(*names, time: time)
|
38
|
+
@_defer_touch_attrs, @_touch_time = nil, nil
|
39
|
+
else
|
40
|
+
super
|
39
41
|
end
|
40
|
-
super(*names, time: time)
|
41
42
|
end
|
42
43
|
|
43
44
|
private
|
44
|
-
def surreptitiously_touch(
|
45
|
-
|
46
|
-
|
45
|
+
def surreptitiously_touch(attr_names)
|
46
|
+
attr_names.each do |attr_name|
|
47
|
+
_write_attribute(attr_name, @_touch_time)
|
48
|
+
clear_attribute_change(attr_name)
|
49
|
+
end
|
47
50
|
end
|
48
51
|
|
49
52
|
def touch_deferred_attributes
|
50
|
-
|
51
|
-
|
52
|
-
touch(*@_defer_touch_attrs, time: @_touch_time)
|
53
|
-
@_defer_touch_attrs, @_touch_time = nil, nil
|
54
|
-
end
|
53
|
+
@_skip_dirty_tracking = true
|
54
|
+
touch(time: @_touch_time)
|
55
55
|
end
|
56
56
|
|
57
57
|
def has_defer_touch_attrs?
|
@@ -10,9 +10,6 @@ module ActiveRecord
|
|
10
10
|
included do
|
11
11
|
define_callbacks :commit, :rollback,
|
12
12
|
:before_commit,
|
13
|
-
:before_commit_without_transaction_enrollment,
|
14
|
-
:commit_without_transaction_enrollment,
|
15
|
-
:rollback_without_transaction_enrollment,
|
16
13
|
scope: [:kind, :name]
|
17
14
|
end
|
18
15
|
|
@@ -164,13 +161,13 @@ module ActiveRecord
|
|
164
161
|
# end
|
165
162
|
# end
|
166
163
|
#
|
167
|
-
# only "Kotori" is created.
|
164
|
+
# only "Kotori" is created.
|
168
165
|
#
|
169
166
|
# Most databases don't support true nested transactions. At the time of
|
170
167
|
# writing, the only database that we're aware of that supports true nested
|
171
168
|
# transactions, is MS-SQL. Because of this, Active Record emulates nested
|
172
|
-
# transactions by using savepoints
|
173
|
-
# https://dev.mysql.com/doc/refman/
|
169
|
+
# transactions by using savepoints. See
|
170
|
+
# https://dev.mysql.com/doc/refman/en/savepoint.html
|
174
171
|
# for more information about savepoints.
|
175
172
|
#
|
176
173
|
# === \Callbacks
|
@@ -266,21 +263,6 @@ module ActiveRecord
|
|
266
263
|
set_callback(:rollback, :after, *args, &block)
|
267
264
|
end
|
268
265
|
|
269
|
-
def before_commit_without_transaction_enrollment(*args, &block) # :nodoc:
|
270
|
-
set_options_for_callbacks!(args)
|
271
|
-
set_callback(:before_commit_without_transaction_enrollment, :before, *args, &block)
|
272
|
-
end
|
273
|
-
|
274
|
-
def after_commit_without_transaction_enrollment(*args, &block) # :nodoc:
|
275
|
-
set_options_for_callbacks!(args)
|
276
|
-
set_callback(:commit_without_transaction_enrollment, :after, *args, &block)
|
277
|
-
end
|
278
|
-
|
279
|
-
def after_rollback_without_transaction_enrollment(*args, &block) # :nodoc:
|
280
|
-
set_options_for_callbacks!(args)
|
281
|
-
set_callback(:rollback_without_transaction_enrollment, :after, *args, &block)
|
282
|
-
end
|
283
|
-
|
284
266
|
private
|
285
267
|
def set_options_for_callbacks!(args, enforced_options = {})
|
286
268
|
options = args.extract_options!.merge!(enforced_options)
|
@@ -302,7 +284,7 @@ module ActiveRecord
|
|
302
284
|
end
|
303
285
|
|
304
286
|
# See ActiveRecord::Transactions::ClassMethods for detailed documentation.
|
305
|
-
def transaction(options
|
287
|
+
def transaction(**options, &block)
|
306
288
|
self.class.transaction(**options, &block)
|
307
289
|
end
|
308
290
|
|
@@ -310,11 +292,11 @@ module ActiveRecord
|
|
310
292
|
with_transaction_returning_status { super }
|
311
293
|
end
|
312
294
|
|
313
|
-
def save(
|
295
|
+
def save(**) #:nodoc:
|
314
296
|
with_transaction_returning_status { super }
|
315
297
|
end
|
316
298
|
|
317
|
-
def save!(
|
299
|
+
def save!(**) #:nodoc:
|
318
300
|
with_transaction_returning_status { super }
|
319
301
|
end
|
320
302
|
|
@@ -323,7 +305,6 @@ module ActiveRecord
|
|
323
305
|
end
|
324
306
|
|
325
307
|
def before_committed! # :nodoc:
|
326
|
-
_run_before_commit_without_transaction_enrollment_callbacks
|
327
308
|
_run_before_commit_callbacks
|
328
309
|
end
|
329
310
|
|
@@ -335,7 +316,6 @@ module ActiveRecord
|
|
335
316
|
force_clear_transaction_record_state
|
336
317
|
if should_run_callbacks
|
337
318
|
@_committed_already_called = true
|
338
|
-
_run_commit_without_transaction_enrollment_callbacks
|
339
319
|
_run_commit_callbacks
|
340
320
|
end
|
341
321
|
ensure
|
@@ -347,7 +327,6 @@ module ActiveRecord
|
|
347
327
|
def rolledback!(force_restore_state: false, should_run_callbacks: true) #:nodoc:
|
348
328
|
if should_run_callbacks
|
349
329
|
_run_rollback_callbacks
|
350
|
-
_run_rollback_without_transaction_enrollment_callbacks
|
351
330
|
end
|
352
331
|
ensure
|
353
332
|
restore_transaction_record_state(force_restore_state)
|
@@ -363,13 +342,11 @@ module ActiveRecord
|
|
363
342
|
# instance.
|
364
343
|
def with_transaction_returning_status
|
365
344
|
status = nil
|
366
|
-
self.class.
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
@transaction_state = self.class.connection.transaction_state
|
372
|
-
end
|
345
|
+
connection = self.class.connection
|
346
|
+
ensure_finalize = !connection.transaction_open?
|
347
|
+
|
348
|
+
connection.transaction do
|
349
|
+
add_to_transaction(ensure_finalize || has_transactional_callbacks?)
|
373
350
|
remember_transaction_record_state
|
374
351
|
|
375
352
|
status = yield
|
@@ -391,6 +368,7 @@ module ActiveRecord
|
|
391
368
|
@_start_transaction_state ||= {
|
392
369
|
id: id,
|
393
370
|
new_record: @new_record,
|
371
|
+
previously_new_record: @previously_new_record,
|
394
372
|
destroyed: @destroyed,
|
395
373
|
attributes: @attributes,
|
396
374
|
frozen?: frozen?,
|
@@ -415,7 +393,6 @@ module ActiveRecord
|
|
415
393
|
# Force to clear the transaction record state.
|
416
394
|
def force_clear_transaction_record_state
|
417
395
|
@_start_transaction_state = nil
|
418
|
-
@transaction_state = nil
|
419
396
|
end
|
420
397
|
|
421
398
|
# Restore the new record state and id of a record that was previously saved by a call to save_record_state.
|
@@ -423,6 +400,7 @@ module ActiveRecord
|
|
423
400
|
if restore_state = @_start_transaction_state
|
424
401
|
if force_restore_state || restore_state[:level] <= 1
|
425
402
|
@new_record = restore_state[:new_record]
|
403
|
+
@previously_new_record = restore_state[:previously_new_record]
|
426
404
|
@destroyed = restore_state[:destroyed]
|
427
405
|
@attributes = restore_state[:attributes].map do |attr|
|
428
406
|
value = @attributes.fetch_value(attr.name)
|
@@ -455,39 +433,12 @@ module ActiveRecord
|
|
455
433
|
|
456
434
|
# Add the record to the current transaction so that the #after_rollback and #after_commit
|
457
435
|
# callbacks can be called.
|
458
|
-
def add_to_transaction
|
459
|
-
self.class.connection.add_transaction_record(self)
|
436
|
+
def add_to_transaction(ensure_finalize = true)
|
437
|
+
self.class.connection.add_transaction_record(self, ensure_finalize)
|
460
438
|
end
|
461
439
|
|
462
440
|
def has_transactional_callbacks?
|
463
441
|
!_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty?
|
464
442
|
end
|
465
|
-
|
466
|
-
# Updates the attributes on this particular Active Record object so that
|
467
|
-
# if it's associated with a transaction, then the state of the Active Record
|
468
|
-
# object will be updated to reflect the current state of the transaction.
|
469
|
-
#
|
470
|
-
# The <tt>@transaction_state</tt> variable stores the states of the associated
|
471
|
-
# transaction. This relies on the fact that a transaction can only be in
|
472
|
-
# one rollback or commit (otherwise a list of states would be required).
|
473
|
-
# Each Active Record object inside of a transaction carries that transaction's
|
474
|
-
# TransactionState.
|
475
|
-
#
|
476
|
-
# This method checks to see if the ActiveRecord object's state reflects
|
477
|
-
# the TransactionState, and rolls back or commits the Active Record object
|
478
|
-
# as appropriate.
|
479
|
-
def sync_with_transaction_state
|
480
|
-
if transaction_state = @transaction_state
|
481
|
-
if transaction_state.fully_committed?
|
482
|
-
force_clear_transaction_record_state
|
483
|
-
elsif transaction_state.committed?
|
484
|
-
clear_transaction_record_state
|
485
|
-
elsif transaction_state.rolledback?
|
486
|
-
force_restore_state = transaction_state.fully_rolledback?
|
487
|
-
restore_transaction_record_state(force_restore_state)
|
488
|
-
clear_transaction_record_state
|
489
|
-
end
|
490
|
-
end
|
491
|
-
end
|
492
443
|
end
|
493
444
|
end
|
@@ -61,9 +61,13 @@ module ActiveRecord
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def encoded(value)
|
64
|
-
|
65
|
-
|
64
|
+
return if default_value?(value)
|
65
|
+
payload = coder.dump(value)
|
66
|
+
if payload && binary? && payload.encoding != Encoding::BINARY
|
67
|
+
payload = payload.dup if payload.frozen?
|
68
|
+
payload.force_encoding(Encoding::BINARY)
|
66
69
|
end
|
70
|
+
payload
|
67
71
|
end
|
68
72
|
end
|
69
73
|
end
|
data/lib/active_record/type.rb
CHANGED
@@ -46,9 +46,14 @@ module ActiveRecord
|
|
46
46
|
@default_value ||= Value.new
|
47
47
|
end
|
48
48
|
|
49
|
+
def adapter_name_from(model) # :nodoc:
|
50
|
+
# TODO: this shouldn't depend on a connection to the database
|
51
|
+
model.connection.adapter_name.downcase.to_sym
|
52
|
+
end
|
53
|
+
|
49
54
|
private
|
50
55
|
def current_adapter_name
|
51
|
-
ActiveRecord::Base
|
56
|
+
adapter_name_from(ActiveRecord::Base)
|
52
57
|
end
|
53
58
|
end
|
54
59
|
|
@@ -58,6 +63,7 @@ module ActiveRecord
|
|
58
63
|
Decimal = ActiveModel::Type::Decimal
|
59
64
|
Float = ActiveModel::Type::Float
|
60
65
|
Integer = ActiveModel::Type::Integer
|
66
|
+
ImmutableString = ActiveModel::Type::ImmutableString
|
61
67
|
String = ActiveModel::Type::String
|
62
68
|
Value = ActiveModel::Type::Value
|
63
69
|
|
@@ -69,6 +75,7 @@ module ActiveRecord
|
|
69
75
|
register(:decimal, Type::Decimal, override: false)
|
70
76
|
register(:float, Type::Float, override: false)
|
71
77
|
register(:integer, Type::Integer, override: false)
|
78
|
+
register(:immutable_string, Type::ImmutableString, override: false)
|
72
79
|
register(:json, Type::Json, override: false)
|
73
80
|
register(:string, Type::String, override: false)
|
74
81
|
register(:text, Type::Text, override: false)
|