activerecord 5.2.4.5 → 6.0.0.beta1
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 +299 -739
- data/MIT-LICENSE +3 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +1 -1
- data/lib/active_record.rb +2 -1
- data/lib/active_record/aggregations.rb +4 -2
- data/lib/active_record/associations.rb +16 -12
- data/lib/active_record/associations/association.rb +35 -19
- data/lib/active_record/associations/association_scope.rb +4 -6
- data/lib/active_record/associations/belongs_to_association.rb +36 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
- data/lib/active_record/associations/builder/belongs_to.rb +14 -50
- data/lib/active_record/associations/builder/collection_association.rb +3 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
- data/lib/active_record/associations/collection_association.rb +11 -25
- data/lib/active_record/associations/collection_proxy.rb +32 -6
- data/lib/active_record/associations/foreign_association.rb +7 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +25 -18
- data/lib/active_record/associations/has_one_association.rb +28 -30
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +15 -20
- data/lib/active_record/associations/join_dependency/join_association.rb +11 -26
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/preloader.rb +32 -29
- data/lib/active_record/associations/preloader/association.rb +1 -2
- data/lib/active_record/associations/singular_association.rb +2 -16
- data/lib/active_record/attribute_assignment.rb +7 -10
- data/lib/active_record/attribute_methods.rb +34 -56
- data/lib/active_record/attribute_methods/dirty.rb +64 -26
- data/lib/active_record/attribute_methods/primary_key.rb +8 -7
- data/lib/active_record/attribute_methods/read.rb +16 -48
- data/lib/active_record/attribute_methods/serialization.rb +1 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
- data/lib/active_record/attribute_methods/write.rb +15 -16
- data/lib/active_record/autosave_association.rb +7 -21
- data/lib/active_record/base.rb +2 -2
- data/lib/active_record/callbacks.rb +3 -17
- data/lib/active_record/collection_cache_key.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +13 -36
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +25 -84
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +5 -11
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -11
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +0 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +41 -27
- data/lib/active_record/connection_adapters/abstract/transaction.rb +81 -52
- data/lib/active_record/connection_adapters/abstract_adapter.rb +95 -31
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +65 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +5 -9
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -7
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +65 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -4
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +16 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +11 -36
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +9 -2
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +38 -20
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -56
- data/lib/active_record/connection_adapters/schema_cache.rb +5 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -5
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +14 -9
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +95 -62
- data/lib/active_record/connection_handling.rb +132 -26
- data/lib/active_record/core.rb +76 -43
- data/lib/active_record/counter_cache.rb +4 -29
- data/lib/active_record/database_configurations.rb +184 -0
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +74 -0
- data/lib/active_record/enum.rb +22 -7
- data/lib/active_record/errors.rb +24 -21
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +140 -472
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +12 -2
- data/lib/active_record/integration.rb +56 -16
- data/lib/active_record/internal_metadata.rb +5 -1
- data/lib/active_record/locking/optimistic.rb +2 -2
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/log_subscriber.rb +7 -26
- data/lib/active_record/migration.rb +38 -37
- data/lib/active_record/migration/command_recorder.rb +35 -5
- data/lib/active_record/migration/compatibility.rb +34 -16
- data/lib/active_record/model_schema.rb +30 -9
- data/lib/active_record/nested_attributes.rb +2 -2
- data/lib/active_record/no_touching.rb +7 -0
- data/lib/active_record/persistence.rb +18 -7
- data/lib/active_record/query_cache.rb +11 -4
- data/lib/active_record/querying.rb +19 -11
- data/lib/active_record/railtie.rb +71 -42
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +94 -43
- data/lib/active_record/reflection.rb +60 -44
- data/lib/active_record/relation.rb +150 -69
- data/lib/active_record/relation/batches.rb +13 -10
- data/lib/active_record/relation/calculations.rb +38 -28
- data/lib/active_record/relation/delegation.rb +4 -13
- data/lib/active_record/relation/finder_methods.rb +12 -25
- data/lib/active_record/relation/merger.rb +2 -6
- data/lib/active_record/relation/predicate_builder.rb +4 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/query_attribute.rb +15 -12
- data/lib/active_record/relation/query_methods.rb +29 -52
- data/lib/active_record/relation/where_clause.rb +4 -0
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/result.rb +30 -11
- data/lib/active_record/sanitization.rb +2 -39
- data/lib/active_record/schema.rb +1 -10
- data/lib/active_record/schema_dumper.rb +12 -6
- data/lib/active_record/schema_migration.rb +4 -0
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/scoping/default.rb +10 -3
- data/lib/active_record/scoping/named.rb +10 -14
- data/lib/active_record/statement_cache.rb +32 -5
- data/lib/active_record/store.rb +39 -8
- data/lib/active_record/table_metadata.rb +1 -4
- data/lib/active_record/tasks/database_tasks.rb +89 -23
- data/lib/active_record/tasks/mysql_database_tasks.rb +2 -4
- data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
- data/lib/active_record/test_databases.rb +38 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +4 -6
- data/lib/active_record/transactions.rb +3 -22
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type.rb +3 -4
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type_caster/connection.rb +1 -6
- data/lib/active_record/type_caster/map.rb +1 -4
- data/lib/active_record/validations/uniqueness.rb +13 -25
- data/lib/arel.rb +44 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes.rb +67 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +63 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values.rb +16 -0
- data/lib/arel/nodes/values_list.rb +24 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/visitors/depth_first.rb +199 -0
- data/lib/arel/visitors/dot.rb +292 -0
- data/lib/arel/visitors/ibm_db.rb +21 -0
- data/lib/arel/visitors/informix.rb +56 -0
- data/lib/arel/visitors/mssql.rb +143 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +67 -0
- data/lib/arel/visitors/postgresql.rb +116 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +913 -0
- data/lib/arel/visitors/visitor.rb +42 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record/migration.rb +14 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
- metadata +104 -26
@@ -68,9 +68,7 @@ module ActiveRecord
|
|
68
68
|
|
69
69
|
private
|
70
70
|
|
71
|
-
|
72
|
-
@configuration
|
73
|
-
end
|
71
|
+
attr_reader :configuration
|
74
72
|
|
75
73
|
def configuration_without_database
|
76
74
|
configuration.merge("database" => nil)
|
@@ -106,7 +104,7 @@ module ActiveRecord
|
|
106
104
|
end
|
107
105
|
|
108
106
|
def run_cmd_error(cmd, args, action)
|
109
|
-
msg = "failed to execute: `#{cmd}`\n"
|
107
|
+
msg = +"failed to execute: `#{cmd}`\n"
|
110
108
|
msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
|
111
109
|
msg
|
112
110
|
end
|
@@ -6,8 +6,8 @@ module ActiveRecord
|
|
6
6
|
module Tasks # :nodoc:
|
7
7
|
class PostgreSQLDatabaseTasks # :nodoc:
|
8
8
|
DEFAULT_ENCODING = ENV["CHARSET"] || "utf8"
|
9
|
-
ON_ERROR_STOP_1 = "ON_ERROR_STOP=1"
|
10
|
-
SQL_COMMENT_BEGIN = "--"
|
9
|
+
ON_ERROR_STOP_1 = "ON_ERROR_STOP=1"
|
10
|
+
SQL_COMMENT_BEGIN = "--"
|
11
11
|
|
12
12
|
delegate :connection, :establish_connection, :clear_active_connections!,
|
13
13
|
to: ActiveRecord::Base
|
@@ -82,7 +82,7 @@ module ActiveRecord
|
|
82
82
|
|
83
83
|
def structure_load(filename, extra_flags)
|
84
84
|
set_psql_env
|
85
|
-
args = ["-v", ON_ERROR_STOP_1, "-q", "-f", filename]
|
85
|
+
args = ["-v", ON_ERROR_STOP_1, "-q", "-X", "-f", filename]
|
86
86
|
args.concat(Array(extra_flags)) if extra_flags
|
87
87
|
args << configuration["database"]
|
88
88
|
run_cmd("psql", args, "loading")
|
@@ -90,9 +90,7 @@ module ActiveRecord
|
|
90
90
|
|
91
91
|
private
|
92
92
|
|
93
|
-
|
94
|
-
@configuration
|
95
|
-
end
|
93
|
+
attr_reader :configuration
|
96
94
|
|
97
95
|
def encoding
|
98
96
|
configuration["encoding"] || DEFAULT_ENCODING
|
@@ -117,7 +115,7 @@ module ActiveRecord
|
|
117
115
|
end
|
118
116
|
|
119
117
|
def run_cmd_error(cmd, args, action)
|
120
|
-
msg = "failed to execute:\n"
|
118
|
+
msg = +"failed to execute:\n"
|
121
119
|
msg << "#{cmd} #{args.join(' ')}\n\n"
|
122
120
|
msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
|
123
121
|
msg
|
@@ -60,20 +60,14 @@ module ActiveRecord
|
|
60
60
|
|
61
61
|
private
|
62
62
|
|
63
|
-
|
64
|
-
@configuration
|
65
|
-
end
|
66
|
-
|
67
|
-
def root
|
68
|
-
@root
|
69
|
-
end
|
63
|
+
attr_reader :configuration, :root
|
70
64
|
|
71
65
|
def run_cmd(cmd, args, out)
|
72
66
|
fail run_cmd_error(cmd, args) unless Kernel.system(cmd, *args, out: out)
|
73
67
|
end
|
74
68
|
|
75
69
|
def run_cmd_error(cmd, args)
|
76
|
-
msg = "failed to execute:\n"
|
70
|
+
msg = +"failed to execute:\n"
|
77
71
|
msg << "#{cmd} #{args.join(' ')}\n\n"
|
78
72
|
msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
|
79
73
|
msg
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/testing/parallelization"
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
module TestDatabases # :nodoc:
|
7
|
+
ActiveSupport::Testing::Parallelization.after_fork_hook do |i|
|
8
|
+
create_and_load_schema(i, env_name: Rails.env)
|
9
|
+
end
|
10
|
+
|
11
|
+
ActiveSupport::Testing::Parallelization.run_cleanup_hook do
|
12
|
+
drop(env_name: Rails.env)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.create_and_load_schema(i, env_name:)
|
16
|
+
old, ENV["VERBOSE"] = ENV["VERBOSE"], "false"
|
17
|
+
|
18
|
+
ActiveRecord::Base.configurations.configs_for(env_name: env_name).each do |db_config|
|
19
|
+
db_config.config["database"] += "-#{i}"
|
20
|
+
ActiveRecord::Tasks::DatabaseTasks.create(db_config.config)
|
21
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config.config, ActiveRecord::Base.schema_format, nil, env_name, db_config.spec_name)
|
22
|
+
end
|
23
|
+
ensure
|
24
|
+
ActiveRecord::Base.establish_connection(Rails.env.to_sym)
|
25
|
+
ENV["VERBOSE"] = old
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.drop(env_name:)
|
29
|
+
old, ENV["VERBOSE"] = ENV["VERBOSE"], "false"
|
30
|
+
|
31
|
+
ActiveRecord::Base.configurations.configs_for(env_name: env_name).each do |db_config|
|
32
|
+
ActiveRecord::Tasks::DatabaseTasks.drop(db_config.config)
|
33
|
+
end
|
34
|
+
ensure
|
35
|
+
ENV["VERBOSE"] = old
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module TestFixtures
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def before_setup # :nodoc:
|
8
|
+
setup_fixtures
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def after_teardown # :nodoc:
|
13
|
+
super
|
14
|
+
teardown_fixtures
|
15
|
+
end
|
16
|
+
|
17
|
+
included do
|
18
|
+
class_attribute :fixture_path, instance_writer: false
|
19
|
+
class_attribute :fixture_table_names, default: []
|
20
|
+
class_attribute :fixture_class_names, default: {}
|
21
|
+
class_attribute :use_transactional_tests, default: true
|
22
|
+
class_attribute :use_instantiated_fixtures, default: false # true, false, or :no_instances
|
23
|
+
class_attribute :pre_loaded_fixtures, default: false
|
24
|
+
class_attribute :config, default: ActiveRecord::Base
|
25
|
+
class_attribute :lock_threads, default: true
|
26
|
+
end
|
27
|
+
|
28
|
+
module ClassMethods
|
29
|
+
# Sets the model class for a fixture when the class name cannot be inferred from the fixture name.
|
30
|
+
#
|
31
|
+
# Examples:
|
32
|
+
#
|
33
|
+
# set_fixture_class some_fixture: SomeModel,
|
34
|
+
# 'namespaced/fixture' => Another::Model
|
35
|
+
#
|
36
|
+
# The keys must be the fixture names, that coincide with the short paths to the fixture files.
|
37
|
+
def set_fixture_class(class_names = {})
|
38
|
+
self.fixture_class_names = fixture_class_names.merge(class_names.stringify_keys)
|
39
|
+
end
|
40
|
+
|
41
|
+
def fixtures(*fixture_set_names)
|
42
|
+
if fixture_set_names.first == :all
|
43
|
+
raise StandardError, "No fixture path found. Please set `#{self}.fixture_path`." if fixture_path.blank?
|
44
|
+
fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"].uniq
|
45
|
+
fixture_set_names.map! { |f| f[(fixture_path.to_s.size + 1)..-5] }
|
46
|
+
else
|
47
|
+
fixture_set_names = fixture_set_names.flatten.map(&:to_s)
|
48
|
+
end
|
49
|
+
|
50
|
+
self.fixture_table_names |= fixture_set_names
|
51
|
+
setup_fixture_accessors(fixture_set_names)
|
52
|
+
end
|
53
|
+
|
54
|
+
def setup_fixture_accessors(fixture_set_names = nil)
|
55
|
+
fixture_set_names = Array(fixture_set_names || fixture_table_names)
|
56
|
+
methods = Module.new do
|
57
|
+
fixture_set_names.each do |fs_name|
|
58
|
+
fs_name = fs_name.to_s
|
59
|
+
accessor_name = fs_name.tr("/", "_").to_sym
|
60
|
+
|
61
|
+
define_method(accessor_name) do |*fixture_names|
|
62
|
+
force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
|
63
|
+
return_single_record = fixture_names.size == 1
|
64
|
+
fixture_names = @loaded_fixtures[fs_name].fixtures.keys if fixture_names.empty?
|
65
|
+
|
66
|
+
@fixture_cache[fs_name] ||= {}
|
67
|
+
|
68
|
+
instances = fixture_names.map do |f_name|
|
69
|
+
f_name = f_name.to_s if f_name.is_a?(Symbol)
|
70
|
+
@fixture_cache[fs_name].delete(f_name) if force_reload
|
71
|
+
|
72
|
+
if @loaded_fixtures[fs_name][f_name]
|
73
|
+
@fixture_cache[fs_name][f_name] ||= @loaded_fixtures[fs_name][f_name].find
|
74
|
+
else
|
75
|
+
raise StandardError, "No fixture named '#{f_name}' found for fixture set '#{fs_name}'"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
return_single_record ? instances.first : instances
|
80
|
+
end
|
81
|
+
private accessor_name
|
82
|
+
end
|
83
|
+
end
|
84
|
+
include methods
|
85
|
+
end
|
86
|
+
|
87
|
+
def uses_transaction(*methods)
|
88
|
+
@uses_transaction = [] unless defined?(@uses_transaction)
|
89
|
+
@uses_transaction.concat methods.map(&:to_s)
|
90
|
+
end
|
91
|
+
|
92
|
+
def uses_transaction?(method)
|
93
|
+
@uses_transaction = [] unless defined?(@uses_transaction)
|
94
|
+
@uses_transaction.include?(method.to_s)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def run_in_transaction?
|
99
|
+
use_transactional_tests &&
|
100
|
+
!self.class.uses_transaction?(method_name)
|
101
|
+
end
|
102
|
+
|
103
|
+
def setup_fixtures(config = ActiveRecord::Base)
|
104
|
+
if pre_loaded_fixtures && !use_transactional_tests
|
105
|
+
raise RuntimeError, "pre_loaded_fixtures requires use_transactional_tests"
|
106
|
+
end
|
107
|
+
|
108
|
+
@fixture_cache = {}
|
109
|
+
@fixture_connections = []
|
110
|
+
@@already_loaded_fixtures ||= {}
|
111
|
+
@connection_subscriber = nil
|
112
|
+
|
113
|
+
# Load fixtures once and begin transaction.
|
114
|
+
if run_in_transaction?
|
115
|
+
if @@already_loaded_fixtures[self.class]
|
116
|
+
@loaded_fixtures = @@already_loaded_fixtures[self.class]
|
117
|
+
else
|
118
|
+
@loaded_fixtures = load_fixtures(config)
|
119
|
+
@@already_loaded_fixtures[self.class] = @loaded_fixtures
|
120
|
+
end
|
121
|
+
|
122
|
+
# Begin transactions for connections already established
|
123
|
+
@fixture_connections = enlist_fixture_connections
|
124
|
+
@fixture_connections.each do |connection|
|
125
|
+
connection.begin_transaction joinable: false
|
126
|
+
connection.pool.lock_thread = true if lock_threads
|
127
|
+
end
|
128
|
+
|
129
|
+
# When connections are established in the future, begin a transaction too
|
130
|
+
@connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
|
131
|
+
spec_name = payload[:spec_name] if payload.key?(:spec_name)
|
132
|
+
|
133
|
+
if spec_name
|
134
|
+
begin
|
135
|
+
connection = ActiveRecord::Base.connection_handler.retrieve_connection(spec_name)
|
136
|
+
rescue ConnectionNotEstablished
|
137
|
+
connection = nil
|
138
|
+
end
|
139
|
+
|
140
|
+
if connection && !@fixture_connections.include?(connection)
|
141
|
+
connection.begin_transaction joinable: false
|
142
|
+
connection.pool.lock_thread = true if lock_threads
|
143
|
+
@fixture_connections << connection
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Load fixtures for every test.
|
149
|
+
else
|
150
|
+
ActiveRecord::FixtureSet.reset_cache
|
151
|
+
@@already_loaded_fixtures[self.class] = nil
|
152
|
+
@loaded_fixtures = load_fixtures(config)
|
153
|
+
end
|
154
|
+
|
155
|
+
# Instantiate fixtures for every test if requested.
|
156
|
+
instantiate_fixtures if use_instantiated_fixtures
|
157
|
+
end
|
158
|
+
|
159
|
+
def teardown_fixtures
|
160
|
+
# Rollback changes if a transaction is active.
|
161
|
+
if run_in_transaction?
|
162
|
+
ActiveSupport::Notifications.unsubscribe(@connection_subscriber) if @connection_subscriber
|
163
|
+
@fixture_connections.each do |connection|
|
164
|
+
connection.rollback_transaction if connection.transaction_open?
|
165
|
+
connection.pool.lock_thread = false
|
166
|
+
end
|
167
|
+
@fixture_connections.clear
|
168
|
+
else
|
169
|
+
ActiveRecord::FixtureSet.reset_cache
|
170
|
+
end
|
171
|
+
|
172
|
+
ActiveRecord::Base.clear_active_connections!
|
173
|
+
end
|
174
|
+
|
175
|
+
def enlist_fixture_connections
|
176
|
+
setup_shared_connection_pool
|
177
|
+
|
178
|
+
ActiveRecord::Base.connection_handler.connection_pool_list.map(&:connection)
|
179
|
+
end
|
180
|
+
|
181
|
+
private
|
182
|
+
|
183
|
+
# Shares the writing connection pool with connections on
|
184
|
+
# other handlers.
|
185
|
+
#
|
186
|
+
# In an application with a primary and replica the test fixtures
|
187
|
+
# need to share a connection pool so that the reading connection
|
188
|
+
# can see data in the open transaction on the writing connection.
|
189
|
+
def setup_shared_connection_pool
|
190
|
+
writing_handler = ActiveRecord::Base.connection_handler
|
191
|
+
|
192
|
+
ActiveRecord::Base.connection_handlers.values.each do |handler|
|
193
|
+
if handler != writing_handler
|
194
|
+
handler.connection_pool_list.each do |pool|
|
195
|
+
name = pool.spec.name
|
196
|
+
writing_connection = writing_handler.retrieve_connection_pool(name)
|
197
|
+
handler.send(:owner_to_pool)[name] = writing_connection
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def load_fixtures(config)
|
204
|
+
fixtures = ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names, config)
|
205
|
+
Hash[fixtures.map { |f| [f.name, f] }]
|
206
|
+
end
|
207
|
+
|
208
|
+
def instantiate_fixtures
|
209
|
+
if pre_loaded_fixtures
|
210
|
+
raise RuntimeError, "Load fixtures before instantiating them." if ActiveRecord::FixtureSet.all_loaded_fixtures.empty?
|
211
|
+
ActiveRecord::FixtureSet.instantiate_all_loaded_fixtures(self, load_instances?)
|
212
|
+
else
|
213
|
+
raise RuntimeError, "Load fixtures before instantiating them." if @loaded_fixtures.nil?
|
214
|
+
@loaded_fixtures.each_value do |fixture_set|
|
215
|
+
ActiveRecord::FixtureSet.instantiate_fixtures(self, fixture_set, load_instances?)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def load_instances?
|
221
|
+
use_instantiated_fixtures != :no_instances
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
@@ -56,8 +56,7 @@ module ActiveRecord
|
|
56
56
|
def touch_attributes_with_time(*names, time: nil)
|
57
57
|
attribute_names = timestamp_attributes_for_update_in_model
|
58
58
|
attribute_names |= names.map(&:to_s)
|
59
|
-
time
|
60
|
-
attribute_names.each_with_object({}) { |attr_name, result| result[attr_name] = time }
|
59
|
+
attribute_names.index_with(time || current_time_from_proper_timezone)
|
61
60
|
end
|
62
61
|
|
63
62
|
private
|
@@ -134,11 +133,10 @@ module ActiveRecord
|
|
134
133
|
self.class.send(:current_time_from_proper_timezone)
|
135
134
|
end
|
136
135
|
|
137
|
-
def max_updated_column_timestamp
|
138
|
-
|
139
|
-
.map { |attr| self[attr] }
|
136
|
+
def max_updated_column_timestamp
|
137
|
+
timestamp_attributes_for_update_in_model
|
138
|
+
.map { |attr| self[attr]&.to_time }
|
140
139
|
.compact
|
141
|
-
.map(&:to_time)
|
142
140
|
.max
|
143
141
|
end
|
144
142
|
|
@@ -306,9 +306,7 @@ module ActiveRecord
|
|
306
306
|
end
|
307
307
|
|
308
308
|
def save(*) #:nodoc:
|
309
|
-
|
310
|
-
with_transaction_returning_status { super }
|
311
|
-
end
|
309
|
+
with_transaction_returning_status { super }
|
312
310
|
end
|
313
311
|
|
314
312
|
def save!(*) #:nodoc:
|
@@ -319,17 +317,6 @@ module ActiveRecord
|
|
319
317
|
with_transaction_returning_status { super }
|
320
318
|
end
|
321
319
|
|
322
|
-
# Reset id and @new_record if the transaction rolls back.
|
323
|
-
def rollback_active_record_state!
|
324
|
-
remember_transaction_record_state
|
325
|
-
yield
|
326
|
-
rescue Exception
|
327
|
-
restore_transaction_record_state
|
328
|
-
raise
|
329
|
-
ensure
|
330
|
-
clear_transaction_record_state
|
331
|
-
end
|
332
|
-
|
333
320
|
def before_committed! # :nodoc:
|
334
321
|
_run_before_commit_without_transaction_enrollment_callbacks
|
335
322
|
_run_before_commit_callbacks
|
@@ -340,7 +327,6 @@ module ActiveRecord
|
|
340
327
|
# Ensure that it is not called if the object was never persisted (failed create),
|
341
328
|
# but call it after the commit of a destroyed object.
|
342
329
|
def committed!(should_run_callbacks: true) #:nodoc:
|
343
|
-
force_clear_transaction_record_state
|
344
330
|
if should_run_callbacks && (destroyed? || persisted?)
|
345
331
|
@_committed_already_called = true
|
346
332
|
_run_commit_without_transaction_enrollment_callbacks
|
@@ -348,6 +334,7 @@ module ActiveRecord
|
|
348
334
|
end
|
349
335
|
ensure
|
350
336
|
@_committed_already_called = false
|
337
|
+
force_clear_transaction_record_state
|
351
338
|
end
|
352
339
|
|
353
340
|
# Call the #after_rollback callbacks. The +force_restore_state+ argument indicates if the record
|
@@ -388,16 +375,10 @@ module ActiveRecord
|
|
388
375
|
raise ActiveRecord::Rollback unless status
|
389
376
|
end
|
390
377
|
status
|
391
|
-
ensure
|
392
|
-
if @transaction_state && @transaction_state.committed?
|
393
|
-
clear_transaction_record_state
|
394
|
-
end
|
395
378
|
end
|
396
379
|
|
397
|
-
protected
|
398
|
-
attr_reader :_committed_already_called, :_trigger_update_callback, :_trigger_destroy_callback
|
399
|
-
|
400
380
|
private
|
381
|
+
attr_reader :_committed_already_called, :_trigger_update_callback, :_trigger_destroy_callback
|
401
382
|
|
402
383
|
# Save the new record state and id of a record so it can be restored later if a transaction fails.
|
403
384
|
def remember_transaction_record_state
|
data/lib/active_record/type.rb
CHANGED
@@ -48,12 +48,11 @@ module ActiveRecord
|
|
48
48
|
|
49
49
|
private
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
def current_adapter_name
|
52
|
+
ActiveRecord::Base.connection.adapter_name.downcase.to_sym
|
53
|
+
end
|
54
54
|
end
|
55
55
|
|
56
|
-
Helpers = ActiveModel::Type::Helpers
|
57
56
|
BigInteger = ActiveModel::Type::BigInteger
|
58
57
|
Binary = ActiveModel::Type::Binary
|
59
58
|
Boolean = ActiveModel::Type::Boolean
|