activerecord 7.0.0 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1607 -1040
- data/MIT-LICENSE +1 -1
- data/README.rdoc +17 -18
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/association.rb +18 -3
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +14 -6
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +21 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +17 -12
- data/lib/active_record/associations/collection_proxy.rb +22 -12
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +27 -17
- data/lib/active_record/associations/has_many_through_association.rb +10 -6
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency.rb +20 -14
- data/lib/active_record/associations/preloader/association.rb +27 -6
- data/lib/active_record/associations/preloader/through_association.rb +1 -1
- data/lib/active_record/associations/preloader.rb +13 -10
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +345 -219
- data/lib/active_record/attribute_assignment.rb +0 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/dirty.rb +40 -26
- data/lib/active_record/attribute_methods/primary_key.rb +76 -24
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +18 -5
- data/lib/active_record/attribute_methods/serialization.rb +172 -69
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +110 -28
- data/lib/active_record/attributes.rb +3 -3
- data/lib/active_record/autosave_association.rb +56 -10
- data/lib/active_record/base.rb +10 -5
- data/lib/active_record/callbacks.rb +16 -32
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -34
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +164 -89
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +3 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +63 -43
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +128 -32
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +60 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +52 -8
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +163 -29
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +302 -129
- data/lib/active_record/connection_adapters/abstract/transaction.rb +287 -58
- data/lib/active_record/connection_adapters/abstract_adapter.rb +504 -106
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +217 -104
- data/lib/active_record/connection_adapters/column.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +23 -144
- data/lib/active_record/connection_adapters/mysql/quoting.rb +29 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +38 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +98 -53
- data/lib/active_record/connection_adapters/pool_config.rb +14 -5
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +72 -45
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +41 -8
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +6 -10
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +131 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +358 -57
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +343 -181
- data/lib/active_record/connection_adapters/schema_cache.rb +287 -59
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +45 -39
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +22 -5
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +41 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +242 -81
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +98 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
- data/lib/active_record/connection_adapters.rb +3 -1
- data/lib/active_record/connection_handling.rb +73 -96
- data/lib/active_record/core.rb +136 -148
- data/lib/active_record/counter_cache.rb +46 -25
- data/lib/active_record/database_configurations/connection_url_resolver.rb +1 -0
- data/lib/active_record/database_configurations/database_config.rb +9 -3
- data/lib/active_record/database_configurations/hash_config.rb +22 -12
- data/lib/active_record/database_configurations/url_config.rb +17 -11
- data/lib/active_record/database_configurations.rb +87 -34
- data/lib/active_record/delegated_type.rb +9 -4
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +2 -0
- data/lib/active_record/disable_joins_association_relation.rb +1 -1
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
- data/lib/active_record/encryption/config.rb +25 -1
- data/lib/active_record/encryption/configurable.rb +13 -14
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +8 -4
- data/lib/active_record/encryption/derived_secret_key_provider.rb +9 -3
- data/lib/active_record/encryption/deterministic_key_provider.rb +1 -1
- data/lib/active_record/encryption/encryptable_record.rb +38 -22
- data/lib/active_record/encryption/encrypted_attribute_type.rb +19 -8
- data/lib/active_record/encryption/encryptor.rb +7 -7
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +3 -3
- data/lib/active_record/encryption/extended_deterministic_queries.rb +83 -71
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/message.rb +1 -1
- data/lib/active_record/encryption/message_serializer.rb +2 -0
- data/lib/active_record/encryption/properties.rb +4 -4
- data/lib/active_record/encryption/scheme.rb +20 -23
- data/lib/active_record/encryption.rb +1 -0
- data/lib/active_record/enum.rb +114 -27
- data/lib/active_record/errors.rb +108 -15
- data/lib/active_record/explain.rb +23 -3
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +29 -8
- data/lib/active_record/fixtures.rb +121 -73
- data/lib/active_record/future_result.rb +30 -5
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +30 -16
- data/lib/active_record/insert_all.rb +55 -8
- data/lib/active_record/integration.rb +10 -10
- data/lib/active_record/internal_metadata.rb +118 -30
- data/lib/active_record/locking/optimistic.rb +32 -18
- data/lib/active_record/locking/pessimistic.rb +8 -5
- data/lib/active_record/log_subscriber.rb +39 -17
- data/lib/active_record/marshalling.rb +56 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
- data/lib/active_record/middleware/database_selector.rb +18 -13
- data/lib/active_record/middleware/shard_selector.rb +7 -5
- data/lib/active_record/migration/command_recorder.rb +104 -9
- data/lib/active_record/migration/compatibility.rb +158 -64
- data/lib/active_record/migration/default_strategy.rb +23 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration.rb +271 -117
- data/lib/active_record/model_schema.rb +82 -50
- data/lib/active_record/nested_attributes.rb +23 -3
- data/lib/active_record/normalization.rb +159 -0
- data/lib/active_record/persistence.rb +200 -47
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +3 -21
- data/lib/active_record/query_logs.rb +87 -51
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +16 -3
- data/lib/active_record/railtie.rb +127 -61
- data/lib/active_record/railties/controller_runtime.rb +12 -8
- data/lib/active_record/railties/databases.rake +142 -143
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +32 -5
- data/lib/active_record/reflection.rb +177 -45
- data/lib/active_record/relation/batches/batch_enumerator.rb +5 -3
- data/lib/active_record/relation/batches.rb +190 -61
- data/lib/active_record/relation/calculations.rb +200 -83
- data/lib/active_record/relation/delegation.rb +23 -9
- data/lib/active_record/relation/finder_methods.rb +77 -16
- data/lib/active_record/relation/merger.rb +2 -0
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +26 -14
- data/lib/active_record/relation/query_attribute.rb +25 -1
- data/lib/active_record/relation/query_methods.rb +429 -76
- data/lib/active_record/relation/spawn_methods.rb +18 -1
- data/lib/active_record/relation.rb +98 -41
- data/lib/active_record/result.rb +25 -9
- data/lib/active_record/runtime_registry.rb +10 -1
- data/lib/active_record/sanitization.rb +57 -16
- data/lib/active_record/schema.rb +36 -22
- data/lib/active_record/schema_dumper.rb +65 -23
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +20 -12
- data/lib/active_record/scoping/named.rb +2 -2
- data/lib/active_record/scoping.rb +2 -1
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/serialization.rb +5 -0
- data/lib/active_record/signed_id.rb +9 -7
- data/lib/active_record/store.rb +16 -11
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +16 -3
- data/lib/active_record/tasks/database_tasks.rb +138 -107
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +17 -15
- data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
- data/lib/active_record/test_fixtures.rb +123 -99
- data/lib/active_record/timestamp.rb +26 -14
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +39 -13
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +8 -4
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +3 -3
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +50 -5
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +143 -16
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +1 -1
- data/lib/arel/nodes/and.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -1
- data/lib/arel/nodes/bound_sql_literal.rb +61 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/filter.rb +1 -1
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +0 -8
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +4 -0
- data/lib/arel/predications.rb +2 -0
- data/lib/arel/table.rb +9 -5
- data/lib/arel/visitors/mysql.rb +8 -1
- data/lib/arel/visitors/to_sql.rb +81 -17
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +16 -2
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- metadata +50 -15
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
@@ -5,8 +5,6 @@ module ActiveRecord
|
|
5
5
|
class MySQLDatabaseTasks # :nodoc:
|
6
6
|
ER_DB_CREATE_EXISTS = 1007
|
7
7
|
|
8
|
-
delegate :connection, :establish_connection, to: ActiveRecord::Base
|
9
|
-
|
10
8
|
def self.using_database_configurations?
|
11
9
|
true
|
12
10
|
end
|
@@ -19,17 +17,18 @@ module ActiveRecord
|
|
19
17
|
def create
|
20
18
|
establish_connection(configuration_hash_without_database)
|
21
19
|
connection.create_database(db_config.database, creation_options)
|
22
|
-
establish_connection
|
20
|
+
establish_connection
|
23
21
|
end
|
24
22
|
|
25
23
|
def drop
|
26
|
-
establish_connection
|
24
|
+
establish_connection
|
27
25
|
connection.drop_database(db_config.database)
|
28
26
|
end
|
29
27
|
|
30
28
|
def purge
|
31
|
-
establish_connection(
|
29
|
+
establish_connection(configuration_hash_without_database)
|
32
30
|
connection.recreate_database(db_config.database, creation_options)
|
31
|
+
establish_connection
|
33
32
|
end
|
34
33
|
|
35
34
|
def charset
|
@@ -49,6 +48,7 @@ module ActiveRecord
|
|
49
48
|
|
50
49
|
ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
|
51
50
|
if ignore_tables.any?
|
51
|
+
ignore_tables = connection.data_sources.select { |table| ignore_tables.any? { |pattern| pattern === table } }
|
52
52
|
args += ignore_tables.map { |table| "--ignore-table=#{db_config.database}.#{table}" }
|
53
53
|
end
|
54
54
|
|
@@ -70,6 +70,14 @@ module ActiveRecord
|
|
70
70
|
private
|
71
71
|
attr_reader :db_config, :configuration_hash
|
72
72
|
|
73
|
+
def connection
|
74
|
+
ActiveRecord::Base.connection
|
75
|
+
end
|
76
|
+
|
77
|
+
def establish_connection(config = db_config)
|
78
|
+
ActiveRecord::Base.establish_connection(config)
|
79
|
+
end
|
80
|
+
|
73
81
|
def configuration_hash_without_database
|
74
82
|
configuration_hash.merge(database: nil)
|
75
83
|
end
|
@@ -93,7 +101,8 @@ module ActiveRecord
|
|
93
101
|
sslcert: "--ssl-cert",
|
94
102
|
sslcapath: "--ssl-capath",
|
95
103
|
sslcipher: "--ssl-cipher",
|
96
|
-
sslkey: "--ssl-key"
|
104
|
+
sslkey: "--ssl-key",
|
105
|
+
ssl_mode: "--ssl-mode"
|
97
106
|
}.filter_map { |opt, arg| "#{arg}=#{configuration_hash[opt]}" if configuration_hash[opt] }
|
98
107
|
|
99
108
|
args
|
@@ -9,9 +9,6 @@ module ActiveRecord
|
|
9
9
|
ON_ERROR_STOP_1 = "ON_ERROR_STOP=1"
|
10
10
|
SQL_COMMENT_BEGIN = "--"
|
11
11
|
|
12
|
-
delegate :connection, :establish_connection, :clear_active_connections!,
|
13
|
-
to: ActiveRecord::Base
|
14
|
-
|
15
12
|
def self.using_database_configurations?
|
16
13
|
true
|
17
14
|
end
|
@@ -21,14 +18,14 @@ module ActiveRecord
|
|
21
18
|
@configuration_hash = db_config.configuration_hash
|
22
19
|
end
|
23
20
|
|
24
|
-
def create(
|
25
|
-
|
21
|
+
def create(connection_already_established = false)
|
22
|
+
establish_connection(public_schema_config) unless connection_already_established
|
26
23
|
connection.create_database(db_config.database, configuration_hash.merge(encoding: encoding))
|
27
|
-
establish_connection
|
24
|
+
establish_connection
|
28
25
|
end
|
29
26
|
|
30
27
|
def drop
|
31
|
-
|
28
|
+
establish_connection(public_schema_config)
|
32
29
|
connection.drop_database(db_config.database)
|
33
30
|
end
|
34
31
|
|
@@ -41,7 +38,7 @@ module ActiveRecord
|
|
41
38
|
end
|
42
39
|
|
43
40
|
def purge
|
44
|
-
clear_active_connections!
|
41
|
+
ActiveRecord::Base.connection_handler.clear_active_connections!(:all)
|
45
42
|
drop
|
46
43
|
create true
|
47
44
|
end
|
@@ -58,7 +55,6 @@ module ActiveRecord
|
|
58
55
|
end
|
59
56
|
|
60
57
|
args = ["--schema-only", "--no-privileges", "--no-owner"]
|
61
|
-
args << "--no-comment" if connection.database_version >= 110_000
|
62
58
|
args.concat(["--file", filename])
|
63
59
|
|
64
60
|
args.concat(Array(extra_flags)) if extra_flags
|
@@ -71,6 +67,7 @@ module ActiveRecord
|
|
71
67
|
|
72
68
|
ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
|
73
69
|
if ignore_tables.any?
|
70
|
+
ignore_tables = connection.data_sources.select { |table| ignore_tables.any? { |pattern| pattern === table } }
|
74
71
|
args += ignore_tables.flat_map { |table| ["-T", table] }
|
75
72
|
end
|
76
73
|
|
@@ -81,7 +78,7 @@ module ActiveRecord
|
|
81
78
|
end
|
82
79
|
|
83
80
|
def structure_load(filename, extra_flags)
|
84
|
-
args = ["--set", ON_ERROR_STOP_1, "--quiet", "--no-psqlrc", "--file", filename]
|
81
|
+
args = ["--set", ON_ERROR_STOP_1, "--quiet", "--no-psqlrc", "--output", File::NULL, "--file", filename]
|
85
82
|
args.concat(Array(extra_flags)) if extra_flags
|
86
83
|
args << db_config.database
|
87
84
|
run_cmd("psql", args, "loading")
|
@@ -90,15 +87,20 @@ module ActiveRecord
|
|
90
87
|
private
|
91
88
|
attr_reader :db_config, :configuration_hash
|
92
89
|
|
90
|
+
def connection
|
91
|
+
ActiveRecord::Base.connection
|
92
|
+
end
|
93
|
+
|
94
|
+
def establish_connection(config = db_config)
|
95
|
+
ActiveRecord::Base.establish_connection(config)
|
96
|
+
end
|
97
|
+
|
93
98
|
def encoding
|
94
99
|
configuration_hash[:encoding] || DEFAULT_ENCODING
|
95
100
|
end
|
96
101
|
|
97
|
-
def
|
98
|
-
|
99
|
-
database: "postgres",
|
100
|
-
schema_search_path: "public"
|
101
|
-
)
|
102
|
+
def public_schema_config
|
103
|
+
configuration_hash.merge(database: "postgres", schema_search_path: "public")
|
102
104
|
end
|
103
105
|
|
104
106
|
def psql_env
|
@@ -3,8 +3,6 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Tasks # :nodoc:
|
5
5
|
class SQLiteDatabaseTasks # :nodoc:
|
6
|
-
delegate :connection, :establish_connection, to: ActiveRecord::Base
|
7
|
-
|
8
6
|
def self.using_database_configurations?
|
9
7
|
true
|
10
8
|
end
|
@@ -17,25 +15,26 @@ module ActiveRecord
|
|
17
15
|
def create
|
18
16
|
raise DatabaseAlreadyExists if File.exist?(db_config.database)
|
19
17
|
|
20
|
-
establish_connection
|
18
|
+
establish_connection
|
21
19
|
connection
|
22
20
|
end
|
23
21
|
|
24
22
|
def drop
|
25
|
-
|
26
|
-
|
27
|
-
file = path.absolute? ? path.to_s : File.join(root, path)
|
28
|
-
|
23
|
+
db_path = db_config.database
|
24
|
+
file = File.absolute_path?(db_path) ? db_path : File.join(root, db_path)
|
29
25
|
FileUtils.rm(file)
|
26
|
+
FileUtils.rm_f(["#{file}-shm", "#{file}-wal"])
|
30
27
|
rescue Errno::ENOENT => error
|
31
28
|
raise NoDatabaseError.new(error.message)
|
32
29
|
end
|
33
30
|
|
34
31
|
def purge
|
32
|
+
connection.disconnect!
|
35
33
|
drop
|
36
34
|
rescue NoDatabaseError
|
37
35
|
ensure
|
38
36
|
create
|
37
|
+
connection.reconnect!
|
39
38
|
end
|
40
39
|
|
41
40
|
def charset
|
@@ -49,6 +48,7 @@ module ActiveRecord
|
|
49
48
|
|
50
49
|
ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
|
51
50
|
if ignore_tables.any?
|
51
|
+
ignore_tables = connection.data_sources.select { |table| ignore_tables.any? { |pattern| pattern === table } }
|
52
52
|
condition = ignore_tables.map { |table| connection.quote(table) }.join(", ")
|
53
53
|
args << "SELECT sql FROM sqlite_master WHERE tbl_name NOT IN (#{condition}) ORDER BY tbl_name, type DESC, name"
|
54
54
|
else
|
@@ -65,6 +65,14 @@ module ActiveRecord
|
|
65
65
|
private
|
66
66
|
attr_reader :db_config, :root
|
67
67
|
|
68
|
+
def connection
|
69
|
+
ActiveRecord::Base.connection
|
70
|
+
end
|
71
|
+
|
72
|
+
def establish_connection(config = db_config)
|
73
|
+
ActiveRecord::Base.establish_connection(config)
|
74
|
+
end
|
75
|
+
|
68
76
|
def run_cmd(cmd, args, out)
|
69
77
|
fail run_cmd_error(cmd, args) unless Kernel.system(cmd, *args, out: out)
|
70
78
|
end
|
@@ -17,13 +17,26 @@ module ActiveRecord
|
|
17
17
|
end
|
18
18
|
|
19
19
|
included do
|
20
|
-
|
20
|
+
##
|
21
|
+
# :singleton-method: fixture_paths
|
22
|
+
#
|
23
|
+
# Returns the ActiveRecord::FixtureSet collection
|
24
|
+
|
25
|
+
##
|
26
|
+
# :singleton-method: fixture_paths=
|
27
|
+
#
|
28
|
+
# :call-seq:
|
29
|
+
# fixture_paths=(fixture_paths)
|
30
|
+
class_attribute :fixture_paths, instance_writer: false, default: []
|
21
31
|
class_attribute :fixture_table_names, default: []
|
22
32
|
class_attribute :fixture_class_names, default: {}
|
23
33
|
class_attribute :use_transactional_tests, default: true
|
24
34
|
class_attribute :use_instantiated_fixtures, default: false # true, false, or :no_instances
|
25
35
|
class_attribute :pre_loaded_fixtures, default: false
|
26
36
|
class_attribute :lock_threads, default: true
|
37
|
+
class_attribute :fixture_sets, default: {}
|
38
|
+
|
39
|
+
ActiveSupport.run_load_hooks(:active_record_fixtures, self)
|
27
40
|
end
|
28
41
|
|
29
42
|
module ClassMethods
|
@@ -39,12 +52,28 @@ module ActiveRecord
|
|
39
52
|
self.fixture_class_names = fixture_class_names.merge(class_names.stringify_keys)
|
40
53
|
end
|
41
54
|
|
55
|
+
def fixture_path # :nodoc:
|
56
|
+
ActiveRecord.deprecator.warn(<<~WARNING)
|
57
|
+
TestFixtures.fixture_path is deprecated and will be removed in Rails 7.2. Use .fixture_paths instead.
|
58
|
+
If multiple fixture paths have been configured with .fixture_paths, then .fixture_path will just return
|
59
|
+
the first path.
|
60
|
+
WARNING
|
61
|
+
fixture_paths.first
|
62
|
+
end
|
63
|
+
|
64
|
+
def fixture_path=(path) # :nodoc:
|
65
|
+
ActiveRecord.deprecator.warn("TestFixtures.fixture_path= is deprecated and will be removed in Rails 7.2. Use .fixture_paths= instead.")
|
66
|
+
self.fixture_paths = Array(path)
|
67
|
+
end
|
68
|
+
|
42
69
|
def fixtures(*fixture_set_names)
|
43
70
|
if fixture_set_names.first == :all
|
44
|
-
raise StandardError, "No fixture path found. Please set `#{self}.
|
45
|
-
fixture_set_names =
|
46
|
-
|
47
|
-
|
71
|
+
raise StandardError, "No fixture path found. Please set `#{self}.fixture_paths`." if fixture_paths.blank?
|
72
|
+
fixture_set_names = fixture_paths.flat_map do |path|
|
73
|
+
names = Dir[::File.join(path, "{**,*}/*.{yml}")].uniq
|
74
|
+
names.reject! { |f| f.start_with?(file_fixture_path.to_s) } if defined?(file_fixture_path) && file_fixture_path
|
75
|
+
names.map! { |f| f[path.to_s.size..-5].delete_prefix("/") }
|
76
|
+
end.uniq
|
48
77
|
else
|
49
78
|
fixture_set_names = fixture_set_names.flatten.map(&:to_s)
|
50
79
|
end
|
@@ -55,37 +84,20 @@ module ActiveRecord
|
|
55
84
|
|
56
85
|
def setup_fixture_accessors(fixture_set_names = nil)
|
57
86
|
fixture_set_names = Array(fixture_set_names || fixture_table_names)
|
58
|
-
|
87
|
+
unless fixture_set_names.empty?
|
88
|
+
self.fixture_sets = fixture_sets.dup
|
59
89
|
fixture_set_names.each do |fs_name|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
|
65
|
-
return_single_record = fixture_names.size == 1
|
66
|
-
fixture_names = @loaded_fixtures[fs_name].fixtures.keys if fixture_names.empty?
|
67
|
-
|
68
|
-
@fixture_cache[fs_name] ||= {}
|
69
|
-
|
70
|
-
instances = fixture_names.map do |f_name|
|
71
|
-
f_name = f_name.to_s if f_name.is_a?(Symbol)
|
72
|
-
@fixture_cache[fs_name].delete(f_name) if force_reload
|
73
|
-
|
74
|
-
if @loaded_fixtures[fs_name][f_name]
|
75
|
-
@fixture_cache[fs_name][f_name] ||= @loaded_fixtures[fs_name][f_name].find
|
76
|
-
else
|
77
|
-
raise StandardError, "No fixture named '#{f_name}' found for fixture set '#{fs_name}'"
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
return_single_record ? instances.first : instances
|
82
|
-
end
|
83
|
-
private accessor_name
|
90
|
+
key = fs_name.to_s.include?("/") ? -fs_name.to_s.tr("/", "_") : fs_name
|
91
|
+
key = -key.to_s if key.is_a?(Symbol)
|
92
|
+
fs_name = -fs_name.to_s if fs_name.is_a?(Symbol)
|
93
|
+
fixture_sets[key] = fs_name
|
84
94
|
end
|
85
95
|
end
|
86
|
-
include methods
|
87
96
|
end
|
88
97
|
|
98
|
+
# Prevents automatically wrapping each specified test in a transaction,
|
99
|
+
# to allow application logic transactions to be tested in a top-level
|
100
|
+
# (non-nested) context.
|
89
101
|
def uses_transaction(*methods)
|
90
102
|
@uses_transaction = [] unless defined?(@uses_transaction)
|
91
103
|
@uses_transaction.concat methods.map(&:to_s)
|
@@ -97,6 +109,15 @@ module ActiveRecord
|
|
97
109
|
end
|
98
110
|
end
|
99
111
|
|
112
|
+
def fixture_path # :nodoc:
|
113
|
+
ActiveRecord.deprecator.warn(<<~WARNING)
|
114
|
+
TestFixtures#fixture_path is deprecated and will be removed in Rails 7.2. Use #fixture_paths instead.
|
115
|
+
If multiple fixture paths have been configured with #fixture_paths, then #fixture_path will just return
|
116
|
+
the first path.
|
117
|
+
WARNING
|
118
|
+
fixture_paths.first
|
119
|
+
end
|
120
|
+
|
100
121
|
def run_in_transaction?
|
101
122
|
use_transactional_tests &&
|
102
123
|
!self.class.uses_transaction?(name)
|
@@ -111,7 +132,6 @@ module ActiveRecord
|
|
111
132
|
@fixture_connections = []
|
112
133
|
@@already_loaded_fixtures ||= {}
|
113
134
|
@connection_subscriber = nil
|
114
|
-
@legacy_saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
|
115
135
|
@saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
|
116
136
|
|
117
137
|
# Load fixtures once and begin transaction.
|
@@ -132,21 +152,24 @@ module ActiveRecord
|
|
132
152
|
|
133
153
|
# When connections are established in the future, begin a transaction too
|
134
154
|
@connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
|
135
|
-
|
155
|
+
connection_name = payload[:connection_name] if payload.key?(:connection_name)
|
136
156
|
shard = payload[:shard] if payload.key?(:shard)
|
137
|
-
setup_shared_connection_pool
|
138
157
|
|
139
|
-
if
|
158
|
+
if connection_name
|
140
159
|
begin
|
141
|
-
connection = ActiveRecord::Base.connection_handler.retrieve_connection(
|
160
|
+
connection = ActiveRecord::Base.connection_handler.retrieve_connection(connection_name, shard: shard)
|
142
161
|
rescue ConnectionNotEstablished
|
143
162
|
connection = nil
|
144
163
|
end
|
145
164
|
|
146
|
-
if connection
|
147
|
-
|
148
|
-
|
149
|
-
|
165
|
+
if connection
|
166
|
+
setup_shared_connection_pool
|
167
|
+
|
168
|
+
if !@fixture_connections.include?(connection)
|
169
|
+
connection.begin_transaction joinable: false, _lazy: false
|
170
|
+
connection.pool.lock_thread = true if lock_threads
|
171
|
+
@fixture_connections << connection
|
172
|
+
end
|
150
173
|
end
|
151
174
|
end
|
152
175
|
end
|
@@ -176,13 +199,13 @@ module ActiveRecord
|
|
176
199
|
ActiveRecord::FixtureSet.reset_cache
|
177
200
|
end
|
178
201
|
|
179
|
-
ActiveRecord::Base.clear_active_connections!
|
202
|
+
ActiveRecord::Base.connection_handler.clear_active_connections!(:all)
|
180
203
|
end
|
181
204
|
|
182
205
|
def enlist_fixture_connections
|
183
206
|
setup_shared_connection_pool
|
184
207
|
|
185
|
-
ActiveRecord::Base.connection_handler.connection_pool_list.map(&:connection)
|
208
|
+
ActiveRecord::Base.connection_handler.connection_pool_list(:writing).map(&:connection)
|
186
209
|
end
|
187
210
|
|
188
211
|
private
|
@@ -193,79 +216,43 @@ module ActiveRecord
|
|
193
216
|
# need to share a connection pool so that the reading connection
|
194
217
|
# can see data in the open transaction on the writing connection.
|
195
218
|
def setup_shared_connection_pool
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
pool_config = pool_manager.get_pool_config(nil, shard_name)
|
210
|
-
next if pool_config == writing_pool_config
|
211
|
-
|
212
|
-
@legacy_saved_pool_configs[handler][name][shard_name] = pool_config
|
213
|
-
pool_manager.set_pool_config(nil, shard_name, writing_pool_config)
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|
217
|
-
end
|
218
|
-
else
|
219
|
-
handler = ActiveRecord::Base.connection_handler
|
220
|
-
|
221
|
-
handler.connection_pool_names.each do |name|
|
222
|
-
pool_manager = handler.send(:owner_to_pool_manager)[name]
|
223
|
-
pool_manager.shard_names.each do |shard_name|
|
224
|
-
writing_pool_config = pool_manager.get_pool_config(ActiveRecord.writing_role, shard_name)
|
225
|
-
@saved_pool_configs[name][shard_name] ||= {}
|
226
|
-
pool_manager.role_names.each do |role|
|
227
|
-
next unless pool_config = pool_manager.get_pool_config(role, shard_name)
|
228
|
-
next if pool_config == writing_pool_config
|
229
|
-
|
230
|
-
@saved_pool_configs[name][shard_name][role] = pool_config
|
231
|
-
pool_manager.set_pool_config(role, shard_name, writing_pool_config)
|
232
|
-
end
|
219
|
+
handler = ActiveRecord::Base.connection_handler
|
220
|
+
|
221
|
+
handler.connection_pool_names.each do |name|
|
222
|
+
pool_manager = handler.send(:connection_name_to_pool_manager)[name]
|
223
|
+
pool_manager.shard_names.each do |shard_name|
|
224
|
+
writing_pool_config = pool_manager.get_pool_config(ActiveRecord.writing_role, shard_name)
|
225
|
+
@saved_pool_configs[name][shard_name] ||= {}
|
226
|
+
pool_manager.role_names.each do |role|
|
227
|
+
next unless pool_config = pool_manager.get_pool_config(role, shard_name)
|
228
|
+
next if pool_config == writing_pool_config
|
229
|
+
|
230
|
+
@saved_pool_configs[name][shard_name][role] = pool_config
|
231
|
+
pool_manager.set_pool_config(role, shard_name, writing_pool_config)
|
233
232
|
end
|
234
233
|
end
|
235
234
|
end
|
236
235
|
end
|
237
236
|
|
238
237
|
def teardown_shared_connection_pool
|
239
|
-
|
240
|
-
@legacy_saved_pool_configs.each_pair do |handler, names|
|
241
|
-
names.each_pair do |name, shards|
|
242
|
-
shards.each_pair do |shard_name, pool_config|
|
243
|
-
pool_manager = handler.send(:owner_to_pool_manager)[name]
|
244
|
-
pool_manager.set_pool_config(nil, shard_name, pool_config)
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
else
|
249
|
-
handler = ActiveRecord::Base.connection_handler
|
238
|
+
handler = ActiveRecord::Base.connection_handler
|
250
239
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
240
|
+
@saved_pool_configs.each_pair do |name, shards|
|
241
|
+
pool_manager = handler.send(:connection_name_to_pool_manager)[name]
|
242
|
+
shards.each_pair do |shard_name, roles|
|
243
|
+
roles.each_pair do |role, pool_config|
|
244
|
+
next unless pool_manager.get_pool_config(role, shard_name)
|
256
245
|
|
257
|
-
|
258
|
-
end
|
246
|
+
pool_manager.set_pool_config(role, shard_name, pool_config)
|
259
247
|
end
|
260
248
|
end
|
261
249
|
end
|
262
250
|
|
263
|
-
@legacy_saved_pool_configs.clear
|
264
251
|
@saved_pool_configs.clear
|
265
252
|
end
|
266
253
|
|
267
254
|
def load_fixtures(config)
|
268
|
-
ActiveRecord::FixtureSet.create_fixtures(
|
255
|
+
ActiveRecord::FixtureSet.create_fixtures(fixture_paths, fixture_table_names, fixture_class_names, config).index_by(&:name)
|
269
256
|
end
|
270
257
|
|
271
258
|
def instantiate_fixtures
|
@@ -283,5 +270,42 @@ module ActiveRecord
|
|
283
270
|
def load_instances?
|
284
271
|
use_instantiated_fixtures != :no_instances
|
285
272
|
end
|
273
|
+
|
274
|
+
def method_missing(name, *args, **kwargs, &block)
|
275
|
+
if fs_name = fixture_sets[name.to_s]
|
276
|
+
access_fixture(fs_name, *args, **kwargs, &block)
|
277
|
+
else
|
278
|
+
super
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
def respond_to_missing?(name, include_private = false)
|
283
|
+
if include_private && fixture_sets.key?(name.to_s)
|
284
|
+
true
|
285
|
+
else
|
286
|
+
super
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
def access_fixture(fs_name, *fixture_names)
|
291
|
+
force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
|
292
|
+
return_single_record = fixture_names.size == 1
|
293
|
+
|
294
|
+
fixture_names = @loaded_fixtures[fs_name].fixtures.keys if fixture_names.empty?
|
295
|
+
@fixture_cache[fs_name] ||= {}
|
296
|
+
|
297
|
+
instances = fixture_names.map do |f_name|
|
298
|
+
f_name = f_name.to_s if f_name.is_a?(Symbol)
|
299
|
+
@fixture_cache[fs_name].delete(f_name) if force_reload
|
300
|
+
|
301
|
+
if @loaded_fixtures[fs_name][f_name]
|
302
|
+
@fixture_cache[fs_name][f_name] ||= @loaded_fixtures[fs_name][f_name].find
|
303
|
+
else
|
304
|
+
raise StandardError, "No fixture named '#{f_name}' found for fixture set '#{fs_name}'"
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
return_single_record ? instances.first : instances
|
309
|
+
end
|
286
310
|
end
|
287
311
|
end
|
@@ -75,9 +75,17 @@ module ActiveRecord
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def current_time_from_proper_timezone
|
78
|
-
|
78
|
+
connection.default_timezone == :utc ? Time.now.utc : Time.now
|
79
79
|
end
|
80
80
|
|
81
|
+
protected
|
82
|
+
def reload_schema_from_cache(recursive = true)
|
83
|
+
@timestamp_attributes_for_create_in_model = nil
|
84
|
+
@timestamp_attributes_for_update_in_model = nil
|
85
|
+
@all_timestamp_attributes_in_model = nil
|
86
|
+
super
|
87
|
+
end
|
88
|
+
|
81
89
|
private
|
82
90
|
def timestamp_attributes_for_create
|
83
91
|
["created_at", "created_on"].map! { |name| attribute_aliases[name] || name }
|
@@ -86,16 +94,14 @@ module ActiveRecord
|
|
86
94
|
def timestamp_attributes_for_update
|
87
95
|
["updated_at", "updated_on"].map! { |name| attribute_aliases[name] || name }
|
88
96
|
end
|
89
|
-
|
90
|
-
def reload_schema_from_cache
|
91
|
-
@timestamp_attributes_for_create_in_model = nil
|
92
|
-
@timestamp_attributes_for_update_in_model = nil
|
93
|
-
@all_timestamp_attributes_in_model = nil
|
94
|
-
super
|
95
|
-
end
|
96
97
|
end
|
97
98
|
|
98
99
|
private
|
100
|
+
def init_internals
|
101
|
+
super
|
102
|
+
@_touch_record = nil
|
103
|
+
end
|
104
|
+
|
99
105
|
def _create_record
|
100
106
|
if record_timestamps
|
101
107
|
current_time = current_time_from_proper_timezone
|
@@ -109,6 +115,17 @@ module ActiveRecord
|
|
109
115
|
end
|
110
116
|
|
111
117
|
def _update_record
|
118
|
+
record_update_timestamps
|
119
|
+
|
120
|
+
super
|
121
|
+
end
|
122
|
+
|
123
|
+
def create_or_update(touch: true, **)
|
124
|
+
@_touch_record = touch
|
125
|
+
super
|
126
|
+
end
|
127
|
+
|
128
|
+
def record_update_timestamps
|
112
129
|
if @_touch_record && should_record_timestamps?
|
113
130
|
current_time = current_time_from_proper_timezone
|
114
131
|
|
@@ -118,12 +135,7 @@ module ActiveRecord
|
|
118
135
|
end
|
119
136
|
end
|
120
137
|
|
121
|
-
|
122
|
-
end
|
123
|
-
|
124
|
-
def create_or_update(touch: true, **)
|
125
|
-
@_touch_record = touch
|
126
|
-
super
|
138
|
+
yield if block_given?
|
127
139
|
end
|
128
140
|
|
129
141
|
def should_record_timestamps?
|