activerecord 6.0.0 → 6.1.4
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 +1178 -600
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- data/lib/active_record/aggregations.rb +5 -6
- data/lib/active_record/association_relation.rb +30 -10
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +55 -29
- data/lib/active_record/associations/association_scope.rb +19 -15
- data/lib/active_record/associations/belongs_to_association.rb +23 -10
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -3
- data/lib/active_record/associations/builder/association.rb +32 -5
- 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/join_association.rb +39 -16
- data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
- data/lib/active_record/associations/join_dependency.rb +77 -42
- 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/preloader.rb +13 -8
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +120 -13
- data/lib/active_record/attribute_assignment.rb +10 -9
- 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/attribute_methods.rb +64 -54
- data/lib/active_record/attributes.rb +33 -9
- 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 +12 -3
- 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 +87 -38
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +5 -10
- 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 +141 -52
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +267 -105
- data/lib/active_record/connection_adapters/abstract/transaction.rb +94 -36
- data/lib/active_record/connection_adapters/abstract_adapter.rb +76 -79
- 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 +35 -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 +18 -3
- 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 +5 -2
- 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 +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -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/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/money.rb +2 -2
- 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/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 +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 +83 -65
- data/lib/active_record/connection_adapters/schema_cache.rb +106 -15
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -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_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +219 -81
- data/lib/active_record/core.rb +268 -71
- data/lib/active_record/counter_cache.rb +4 -1
- 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/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/dynamic_matchers.rb +2 -3
- data/lib/active_record/enum.rb +80 -38
- 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 +58 -12
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +40 -21
- data/lib/active_record/insert_all.rb +43 -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 +33 -18
- data/lib/active_record/locking/pessimistic.rb +6 -2
- data/lib/active_record/log_subscriber.rb +28 -9
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +14 -14
- data/lib/active_record/middleware/database_selector.rb +4 -2
- data/lib/active_record/migration/command_recorder.rb +53 -45
- data/lib/active_record/migration/compatibility.rb +71 -20
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +115 -85
- 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/console_sandbox.rb +2 -4
- data/lib/active_record/railties/databases.rake +280 -99
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +77 -63
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +38 -32
- data/lib/active_record/relation/calculations.rb +106 -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/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 +10 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +59 -40
- data/lib/active_record/relation/query_methods.rb +344 -181
- 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 +111 -62
- data/lib/active_record/relation.rb +116 -82
- 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/default.rb +1 -4
- data/lib/active_record/scoping/named.rb +7 -18
- data/lib/active_record/scoping.rb +0 -1
- 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 +42 -36
- data/lib/active_record/tasks/database_tasks.rb +140 -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 +79 -16
- data/lib/active_record/timestamp.rb +4 -7
- data/lib/active_record/touch_later.rb +20 -21
- data/lib/active_record/transactions.rb +26 -73
- 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.rb +8 -2
- data/lib/active_record/type_caster/connection.rb +0 -1
- data/lib/active_record/type_caster/map.rb +8 -5
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +24 -4
- data/lib/active_record/validations.rb +3 -3
- data/lib/active_record.rb +7 -13
- data/lib/arel/attributes/attribute.rb +4 -0
- data/lib/arel/collectors/bind.rb +5 -0
- data/lib/arel/collectors/composite.rb +8 -0
- data/lib/arel/collectors/sql_string.rb +7 -0
- data/lib/arel/collectors/substitute_binds.rb +7 -0
- data/lib/arel/nodes/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 +76 -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 +17 -24
- data/lib/arel/select_manager.rb +1 -2
- data/lib/arel/table.rb +13 -5
- 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/arel/visitors.rb +0 -7
- data/lib/arel.rb +15 -12
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
- data/lib/rails/generators/active_record/migration.rb +6 -2
- 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
@@ -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,32 +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
|
-
|
93
|
-
attr_reader :configuration
|
90
|
+
attr_reader :db_config, :configuration_hash
|
94
91
|
|
95
92
|
def encoding
|
96
|
-
|
93
|
+
configuration_hash[:encoding] || DEFAULT_ENCODING
|
97
94
|
end
|
98
95
|
|
99
96
|
def establish_master_connection
|
100
|
-
establish_connection
|
101
|
-
|
102
|
-
|
97
|
+
establish_connection configuration_hash.merge(
|
98
|
+
database: "postgres",
|
99
|
+
schema_search_path: "public"
|
103
100
|
)
|
104
101
|
end
|
105
102
|
|
106
103
|
def set_psql_env
|
107
|
-
ENV["PGHOST"] =
|
108
|
-
ENV["PGPORT"] =
|
109
|
-
ENV["PGPASSWORD"] =
|
110
|
-
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]
|
111
108
|
end
|
112
109
|
|
113
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,14 +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
|
-
|
63
|
-
attr_reader :configuration, :root
|
66
|
+
attr_reader :db_config, :root
|
64
67
|
|
65
68
|
def run_cmd(cmd, args, out)
|
66
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)
|
@@ -109,6 +111,8 @@ module ActiveRecord
|
|
109
111
|
@fixture_connections = []
|
110
112
|
@@already_loaded_fixtures ||= {}
|
111
113
|
@connection_subscriber = nil
|
114
|
+
@legacy_saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
|
115
|
+
@saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
|
112
116
|
|
113
117
|
# Load fixtures once and begin transaction.
|
114
118
|
if run_in_transaction?
|
@@ -129,10 +133,12 @@ module ActiveRecord
|
|
129
133
|
# When connections are established in the future, begin a transaction too
|
130
134
|
@connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
|
131
135
|
spec_name = payload[:spec_name] if payload.key?(:spec_name)
|
136
|
+
shard = payload[:shard] if payload.key?(:shard)
|
137
|
+
setup_shared_connection_pool
|
132
138
|
|
133
139
|
if spec_name
|
134
140
|
begin
|
135
|
-
connection = ActiveRecord::Base.connection_handler.retrieve_connection(spec_name)
|
141
|
+
connection = ActiveRecord::Base.connection_handler.retrieve_connection(spec_name, shard: shard)
|
136
142
|
rescue ConnectionNotEstablished
|
137
143
|
connection = nil
|
138
144
|
end
|
@@ -165,6 +171,7 @@ module ActiveRecord
|
|
165
171
|
connection.pool.lock_thread = false
|
166
172
|
end
|
167
173
|
@fixture_connections.clear
|
174
|
+
teardown_shared_connection_pool
|
168
175
|
else
|
169
176
|
ActiveRecord::FixtureSet.reset_cache
|
170
177
|
end
|
@@ -179,7 +186,6 @@ module ActiveRecord
|
|
179
186
|
end
|
180
187
|
|
181
188
|
private
|
182
|
-
|
183
189
|
# Shares the writing connection pool with connections on
|
184
190
|
# other handlers.
|
185
191
|
#
|
@@ -187,22 +193,79 @@ module ActiveRecord
|
|
187
193
|
# need to share a connection pool so that the reading connection
|
188
194
|
# can see data in the open transaction on the writing connection.
|
189
195
|
def setup_shared_connection_pool
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
handler
|
195
|
-
|
196
|
-
|
197
|
-
|
196
|
+
if ActiveRecord::Base.legacy_connection_handling
|
197
|
+
writing_handler = ActiveRecord::Base.connection_handlers[ActiveRecord::Base.writing_role]
|
198
|
+
|
199
|
+
ActiveRecord::Base.connection_handlers.values.each do |handler|
|
200
|
+
if handler != writing_handler
|
201
|
+
handler.connection_pool_names.each do |name|
|
202
|
+
writing_pool_manager = writing_handler.send(:owner_to_pool_manager)[name]
|
203
|
+
return unless writing_pool_manager
|
204
|
+
|
205
|
+
pool_manager = handler.send(:owner_to_pool_manager)[name]
|
206
|
+
@legacy_saved_pool_configs[handler][name] ||= {}
|
207
|
+
pool_manager.shard_names.each do |shard_name|
|
208
|
+
writing_pool_config = writing_pool_manager.get_pool_config(nil, shard_name)
|
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::Base.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
|
198
233
|
end
|
199
234
|
end
|
200
235
|
end
|
201
236
|
end
|
202
237
|
|
238
|
+
def teardown_shared_connection_pool
|
239
|
+
if ActiveRecord::Base.legacy_connection_handling
|
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
|
250
|
+
|
251
|
+
@saved_pool_configs.each_pair do |name, shards|
|
252
|
+
pool_manager = handler.send(:owner_to_pool_manager)[name]
|
253
|
+
shards.each_pair do |shard_name, roles|
|
254
|
+
roles.each_pair do |role, pool_config|
|
255
|
+
next unless pool_manager.get_pool_config(role, shard_name)
|
256
|
+
|
257
|
+
pool_manager.set_pool_config(role, shard_name, pool_config)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
@legacy_saved_pool_configs.clear
|
264
|
+
@saved_pool_configs.clear
|
265
|
+
end
|
266
|
+
|
203
267
|
def load_fixtures(config)
|
204
|
-
|
205
|
-
Hash[fixtures.map { |f| [f.name, f] }]
|
268
|
+
ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names, config).index_by(&:name)
|
206
269
|
end
|
207
270
|
|
208
271
|
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
|
@@ -96,15 +96,12 @@ module ActiveRecord
|
|
96
96
|
end
|
97
97
|
|
98
98
|
private
|
99
|
-
|
100
99
|
def _create_record
|
101
100
|
if record_timestamps
|
102
101
|
current_time = current_time_from_proper_timezone
|
103
102
|
|
104
103
|
all_timestamp_attributes_in_model.each do |column|
|
105
|
-
|
106
|
-
_write_attribute(column, current_time)
|
107
|
-
end
|
104
|
+
_write_attribute(column, current_time) unless _read_attribute(column)
|
108
105
|
end
|
109
106
|
end
|
110
107
|
|
@@ -160,7 +157,7 @@ module ActiveRecord
|
|
160
157
|
def clear_timestamp_attributes
|
161
158
|
all_timestamp_attributes_in_model.each do |attribute_name|
|
162
159
|
self[attribute_name] = nil
|
163
|
-
|
160
|
+
clear_attribute_change(attribute_name)
|
164
161
|
end
|
165
162
|
end
|
166
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
11
|
def touch_later(*names) # :nodoc:
|
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
|
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,23 +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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
48
50
|
end
|
49
51
|
|
50
52
|
def touch_deferred_attributes
|
51
|
-
|
52
|
-
|
53
|
-
touch(*@_defer_touch_attrs, time: @_touch_time)
|
54
|
-
@_defer_touch_attrs, @_touch_time = nil, nil
|
55
|
-
end
|
53
|
+
@_skip_dirty_tracking = true
|
54
|
+
touch(time: @_touch_time)
|
56
55
|
end
|
57
56
|
|
58
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
|
@@ -208,8 +205,8 @@ module ActiveRecord
|
|
208
205
|
# Note that "TRUNCATE" is also a MySQL DDL statement!
|
209
206
|
module ClassMethods
|
210
207
|
# See the ConnectionAdapters::DatabaseStatements#transaction API docs.
|
211
|
-
def transaction(options
|
212
|
-
connection.transaction(options, &block)
|
208
|
+
def transaction(**options, &block)
|
209
|
+
connection.transaction(**options, &block)
|
213
210
|
end
|
214
211
|
|
215
212
|
def before_commit(*args, &block) # :nodoc:
|
@@ -266,23 +263,7 @@ 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
|
-
|
286
267
|
def set_options_for_callbacks!(args, enforced_options = {})
|
287
268
|
options = args.extract_options!.merge!(enforced_options)
|
288
269
|
args << options
|
@@ -290,8 +271,10 @@ module ActiveRecord
|
|
290
271
|
if options[:on]
|
291
272
|
fire_on = Array(options[:on])
|
292
273
|
assert_valid_transaction_action(fire_on)
|
293
|
-
options[:if] =
|
294
|
-
|
274
|
+
options[:if] = [
|
275
|
+
-> { transaction_include_any_action?(fire_on) },
|
276
|
+
*options[:if]
|
277
|
+
]
|
295
278
|
end
|
296
279
|
end
|
297
280
|
|
@@ -303,28 +286,27 @@ module ActiveRecord
|
|
303
286
|
end
|
304
287
|
|
305
288
|
# See ActiveRecord::Transactions::ClassMethods for detailed documentation.
|
306
|
-
def transaction(options
|
307
|
-
self.class.transaction(options, &block)
|
289
|
+
def transaction(**options, &block)
|
290
|
+
self.class.transaction(**options, &block)
|
308
291
|
end
|
309
292
|
|
310
293
|
def destroy #:nodoc:
|
311
294
|
with_transaction_returning_status { super }
|
312
295
|
end
|
313
296
|
|
314
|
-
def save(
|
297
|
+
def save(**) #:nodoc:
|
315
298
|
with_transaction_returning_status { super }
|
316
299
|
end
|
317
300
|
|
318
|
-
def save!(
|
301
|
+
def save!(**) #:nodoc:
|
319
302
|
with_transaction_returning_status { super }
|
320
303
|
end
|
321
304
|
|
322
|
-
def touch(
|
305
|
+
def touch(*, **) #:nodoc:
|
323
306
|
with_transaction_returning_status { super }
|
324
307
|
end
|
325
308
|
|
326
309
|
def before_committed! # :nodoc:
|
327
|
-
_run_before_commit_without_transaction_enrollment_callbacks
|
328
310
|
_run_before_commit_callbacks
|
329
311
|
end
|
330
312
|
|
@@ -333,14 +315,13 @@ module ActiveRecord
|
|
333
315
|
# Ensure that it is not called if the object was never persisted (failed create),
|
334
316
|
# but call it after the commit of a destroyed object.
|
335
317
|
def committed!(should_run_callbacks: true) #:nodoc:
|
318
|
+
force_clear_transaction_record_state
|
336
319
|
if should_run_callbacks
|
337
320
|
@_committed_already_called = true
|
338
|
-
_run_commit_without_transaction_enrollment_callbacks
|
339
321
|
_run_commit_callbacks
|
340
322
|
end
|
341
323
|
ensure
|
342
|
-
@_committed_already_called = false
|
343
|
-
force_clear_transaction_record_state
|
324
|
+
@_committed_already_called = @_trigger_update_callback = @_trigger_destroy_callback = false
|
344
325
|
end
|
345
326
|
|
346
327
|
# Call the #after_rollback callbacks. The +force_restore_state+ argument indicates if the record
|
@@ -348,11 +329,11 @@ module ActiveRecord
|
|
348
329
|
def rolledback!(force_restore_state: false, should_run_callbacks: true) #:nodoc:
|
349
330
|
if should_run_callbacks
|
350
331
|
_run_rollback_callbacks
|
351
|
-
_run_rollback_without_transaction_enrollment_callbacks
|
352
332
|
end
|
353
333
|
ensure
|
354
334
|
restore_transaction_record_state(force_restore_state)
|
355
335
|
clear_transaction_record_state
|
336
|
+
@_trigger_update_callback = @_trigger_destroy_callback = false if force_restore_state
|
356
337
|
end
|
357
338
|
|
358
339
|
# Executes +method+ within a transaction and captures its return value as a
|
@@ -363,13 +344,11 @@ module ActiveRecord
|
|
363
344
|
# instance.
|
364
345
|
def with_transaction_returning_status
|
365
346
|
status = nil
|
366
|
-
self.class.
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
@transaction_state = self.class.connection.transaction_state
|
372
|
-
end
|
347
|
+
connection = self.class.connection
|
348
|
+
ensure_finalize = !connection.transaction_open?
|
349
|
+
|
350
|
+
connection.transaction do
|
351
|
+
add_to_transaction(ensure_finalize || has_transactional_callbacks?)
|
373
352
|
remember_transaction_record_state
|
374
353
|
|
375
354
|
status = yield
|
@@ -391,6 +370,7 @@ module ActiveRecord
|
|
391
370
|
@_start_transaction_state ||= {
|
392
371
|
id: id,
|
393
372
|
new_record: @new_record,
|
373
|
+
previously_new_record: @previously_new_record,
|
394
374
|
destroyed: @destroyed,
|
395
375
|
attributes: @attributes,
|
396
376
|
frozen?: frozen?,
|
@@ -415,7 +395,6 @@ module ActiveRecord
|
|
415
395
|
# Force to clear the transaction record state.
|
416
396
|
def force_clear_transaction_record_state
|
417
397
|
@_start_transaction_state = nil
|
418
|
-
@transaction_state = nil
|
419
398
|
end
|
420
399
|
|
421
400
|
# Restore the new record state and id of a record that was previously saved by a call to save_record_state.
|
@@ -423,6 +402,7 @@ module ActiveRecord
|
|
423
402
|
if restore_state = @_start_transaction_state
|
424
403
|
if force_restore_state || restore_state[:level] <= 1
|
425
404
|
@new_record = restore_state[:new_record]
|
405
|
+
@previously_new_record = restore_state[:previously_new_record]
|
426
406
|
@destroyed = restore_state[:destroyed]
|
427
407
|
@attributes = restore_state[:attributes].map do |attr|
|
428
408
|
value = @attributes.fetch_value(attr.name)
|
@@ -455,39 +435,12 @@ module ActiveRecord
|
|
455
435
|
|
456
436
|
# Add the record to the current transaction so that the #after_rollback and #after_commit
|
457
437
|
# callbacks can be called.
|
458
|
-
def add_to_transaction
|
459
|
-
self.class.connection.add_transaction_record(self)
|
438
|
+
def add_to_transaction(ensure_finalize = true)
|
439
|
+
self.class.connection.add_transaction_record(self, ensure_finalize)
|
460
440
|
end
|
461
441
|
|
462
442
|
def has_transactional_callbacks?
|
463
443
|
!_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty?
|
464
444
|
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
445
|
end
|
493
446
|
end
|