activerecord 7.0.0 → 7.2.1
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 +515 -1268
- data/MIT-LICENSE +1 -1
- data/README.rdoc +31 -31
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +35 -12
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +23 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +22 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +28 -17
- data/lib/active_record/associations/collection_proxy.rb +36 -13
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +28 -18
- 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/join_association.rb +27 -25
- data/lib/active_record/associations/join_dependency.rb +18 -14
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +33 -8
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +2 -4
- data/lib/active_record/associations/preloader.rb +13 -10
- data/lib/active_record/associations/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +378 -491
- data/lib/active_record/attribute_assignment.rb +1 -13
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +53 -35
- data/lib/active_record/attribute_methods/primary_key.rb +45 -25
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +8 -7
- data/lib/active_record/attribute_methods/serialization.rb +153 -70
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -6
- data/lib/active_record/attribute_methods/write.rb +6 -6
- data/lib/active_record/attribute_methods.rb +153 -40
- data/lib/active_record/attributes.rb +63 -48
- data/lib/active_record/autosave_association.rb +70 -38
- data/lib/active_record/base.rb +12 -8
- 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 +124 -132
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +4 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +297 -88
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +160 -45
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +215 -63
- data/lib/active_record/connection_adapters/abstract/quoting.rb +83 -65
- 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 +319 -135
- data/lib/active_record/connection_adapters/abstract/transaction.rb +367 -75
- data/lib/active_record/connection_adapters/abstract_adapter.rb +512 -126
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +282 -119
- 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 +27 -140
- data/lib/active_record/connection_adapters/mysql/quoting.rb +64 -52
- 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 +45 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +101 -68
- data/lib/active_record/connection_adapters/pool_config.rb +20 -10
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +16 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +101 -48
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -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 +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +94 -61
- 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 +151 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +379 -66
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +370 -203
- data/lib/active_record/connection_adapters/schema_cache.rb +302 -79
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +60 -43
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +61 -46
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +64 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +321 -110
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
- data/lib/active_record/connection_adapters.rb +124 -1
- data/lib/active_record/connection_handling.rb +98 -106
- data/lib/active_record/core.rb +220 -177
- data/lib/active_record/counter_cache.rb +68 -34
- data/lib/active_record/database_configurations/connection_url_resolver.rb +8 -2
- data/lib/active_record/database_configurations/database_config.rb +26 -5
- data/lib/active_record/database_configurations/hash_config.rb +52 -34
- data/lib/active_record/database_configurations/url_config.rb +37 -12
- data/lib/active_record/database_configurations.rb +88 -35
- data/lib/active_record/delegated_type.rb +40 -11
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +3 -1
- data/lib/active_record/disable_joins_association_relation.rb +1 -1
- data/lib/active_record/dynamic_matchers.rb +2 -2
- 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 +47 -25
- data/lib/active_record/encryption/encrypted_attribute_type.rb +49 -14
- data/lib/active_record/encryption/encryptor.rb +25 -10
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +3 -3
- data/lib/active_record/encryption/extended_deterministic_queries.rb +83 -86
- 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_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +6 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/properties.rb +4 -4
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/encryption/scheme.rb +23 -22
- data/lib/active_record/encryption.rb +1 -0
- data/lib/active_record/enum.rb +131 -27
- data/lib/active_record/errors.rb +151 -31
- data/lib/active_record/explain.rb +21 -12
- 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 +169 -99
- data/lib/active_record/future_result.rb +47 -8
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +34 -18
- data/lib/active_record/insert_all.rb +72 -22
- data/lib/active_record/integration.rb +13 -10
- data/lib/active_record/internal_metadata.rb +124 -20
- data/lib/active_record/locking/optimistic.rb +39 -24
- data/lib/active_record/locking/pessimistic.rb +8 -5
- data/lib/active_record/log_subscriber.rb +28 -27
- 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 +110 -13
- data/lib/active_record/migration/compatibility.rb +174 -64
- data/lib/active_record/migration/default_strategy.rb +22 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +292 -125
- data/lib/active_record/model_schema.rb +113 -112
- data/lib/active_record/nested_attributes.rb +35 -9
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +177 -345
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +19 -25
- data/lib/active_record/query_logs.rb +102 -51
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +34 -9
- data/lib/active_record/railtie.rb +153 -100
- data/lib/active_record/railties/controller_runtime.rb +24 -10
- data/lib/active_record/railties/databases.rake +148 -152
- 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 +278 -69
- data/lib/active_record/relation/batches/batch_enumerator.rb +20 -5
- data/lib/active_record/relation/batches.rb +198 -63
- data/lib/active_record/relation/calculations.rb +293 -108
- data/lib/active_record/relation/delegation.rb +31 -20
- data/lib/active_record/relation/finder_methods.rb +93 -18
- data/lib/active_record/relation/merger.rb +6 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +38 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +28 -16
- data/lib/active_record/relation/query_attribute.rb +25 -1
- data/lib/active_record/relation/query_methods.rb +625 -107
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +5 -4
- data/lib/active_record/relation/where_clause.rb +7 -19
- data/lib/active_record/relation.rb +602 -96
- data/lib/active_record/result.rb +55 -52
- data/lib/active_record/runtime_registry.rb +63 -1
- data/lib/active_record/sanitization.rb +76 -30
- data/lib/active_record/schema.rb +39 -23
- data/lib/active_record/schema_dumper.rb +82 -30
- data/lib/active_record/schema_migration.rb +75 -24
- data/lib/active_record/scoping/default.rb +20 -12
- data/lib/active_record/scoping/named.rb +3 -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 +29 -8
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/store.rb +16 -11
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +7 -3
- data/lib/active_record/tasks/database_tasks.rb +191 -121
- 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 +16 -7
- data/lib/active_record/test_fixtures.rb +174 -152
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +31 -17
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +12 -7
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +109 -27
- data/lib/active_record/translation.rb +1 -3
- 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 +9 -7
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +12 -6
- 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 +63 -14
- data/lib/active_record/validations.rb +12 -5
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +266 -30
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/collectors/bind.rb +2 -0
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- 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/binary.rb +6 -7
- data/lib/arel/nodes/bound_sql_literal.rb +65 -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 +1 -9
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
- data/lib/arel/nodes/node.rb +115 -5
- data/lib/arel/nodes/sql_literal.rb +13 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +6 -2
- data/lib/arel/predications.rb +3 -1
- data/lib/arel/select_manager.rb +1 -1
- data/lib/arel/table.rb +9 -5
- data/lib/arel/tree_manager.rb +8 -3
- data/lib/arel/update_manager.rb +2 -1
- data/lib/arel/visitors/dot.rb +1 -0
- data/lib/arel/visitors/mysql.rb +17 -5
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/to_sql.rb +112 -34
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +21 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
- 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 +59 -17
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
|
@@ -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,15 @@ module ActiveRecord
|
|
|
65
65
|
private
|
|
66
66
|
attr_reader :db_config, :root
|
|
67
67
|
|
|
68
|
+
def connection
|
|
69
|
+
ActiveRecord::Base.lease_connection
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def establish_connection(config = db_config)
|
|
73
|
+
ActiveRecord::Base.establish_connection(config)
|
|
74
|
+
connection.connect!
|
|
75
|
+
end
|
|
76
|
+
|
|
68
77
|
def run_cmd(cmd, args, out)
|
|
69
78
|
fail run_cmd_error(cmd, args) unless Kernel.system(cmd, *args, out: out)
|
|
70
79
|
end
|
|
@@ -13,17 +13,31 @@ module ActiveRecord
|
|
|
13
13
|
|
|
14
14
|
def after_teardown # :nodoc:
|
|
15
15
|
super
|
|
16
|
+
ensure
|
|
16
17
|
teardown_fixtures
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
included do
|
|
20
|
-
|
|
21
|
+
##
|
|
22
|
+
# :singleton-method: fixture_paths
|
|
23
|
+
#
|
|
24
|
+
# Returns the ActiveRecord::FixtureSet collection
|
|
25
|
+
|
|
26
|
+
##
|
|
27
|
+
# :singleton-method: fixture_paths=
|
|
28
|
+
#
|
|
29
|
+
# :call-seq:
|
|
30
|
+
# fixture_paths=(fixture_paths)
|
|
31
|
+
class_attribute :fixture_paths, instance_writer: false, default: []
|
|
21
32
|
class_attribute :fixture_table_names, default: []
|
|
22
33
|
class_attribute :fixture_class_names, default: {}
|
|
23
34
|
class_attribute :use_transactional_tests, default: true
|
|
24
35
|
class_attribute :use_instantiated_fixtures, default: false # true, false, or :no_instances
|
|
25
36
|
class_attribute :pre_loaded_fixtures, default: false
|
|
26
37
|
class_attribute :lock_threads, default: true
|
|
38
|
+
class_attribute :fixture_sets, default: {}
|
|
39
|
+
|
|
40
|
+
ActiveSupport.run_load_hooks(:active_record_fixtures, self)
|
|
27
41
|
end
|
|
28
42
|
|
|
29
43
|
module ClassMethods
|
|
@@ -41,51 +55,36 @@ module ActiveRecord
|
|
|
41
55
|
|
|
42
56
|
def fixtures(*fixture_set_names)
|
|
43
57
|
if fixture_set_names.first == :all
|
|
44
|
-
raise StandardError, "No fixture path found. Please set `#{self}.
|
|
45
|
-
fixture_set_names =
|
|
46
|
-
|
|
47
|
-
|
|
58
|
+
raise StandardError, "No fixture path found. Please set `#{self}.fixture_paths`." if fixture_paths.blank?
|
|
59
|
+
fixture_set_names = fixture_paths.flat_map do |path|
|
|
60
|
+
names = Dir[::File.join(path, "{**,*}/*.{yml}")].uniq
|
|
61
|
+
names.reject! { |f| f.start_with?(file_fixture_path.to_s) } if defined?(file_fixture_path) && file_fixture_path
|
|
62
|
+
names.map! { |f| f[path.to_s.size..-5].delete_prefix("/") }
|
|
63
|
+
end.uniq
|
|
48
64
|
else
|
|
49
65
|
fixture_set_names = fixture_set_names.flatten.map(&:to_s)
|
|
50
66
|
end
|
|
51
67
|
|
|
52
|
-
self.fixture_table_names
|
|
68
|
+
self.fixture_table_names = (fixture_table_names | fixture_set_names).sort
|
|
53
69
|
setup_fixture_accessors(fixture_set_names)
|
|
54
70
|
end
|
|
55
71
|
|
|
56
72
|
def setup_fixture_accessors(fixture_set_names = nil)
|
|
57
73
|
fixture_set_names = Array(fixture_set_names || fixture_table_names)
|
|
58
|
-
|
|
74
|
+
unless fixture_set_names.empty?
|
|
75
|
+
self.fixture_sets = fixture_sets.dup
|
|
59
76
|
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
|
|
77
|
+
key = fs_name.to_s.include?("/") ? -fs_name.to_s.tr("/", "_") : fs_name
|
|
78
|
+
key = -key.to_s if key.is_a?(Symbol)
|
|
79
|
+
fs_name = -fs_name.to_s if fs_name.is_a?(Symbol)
|
|
80
|
+
fixture_sets[key] = fs_name
|
|
84
81
|
end
|
|
85
82
|
end
|
|
86
|
-
include methods
|
|
87
83
|
end
|
|
88
84
|
|
|
85
|
+
# Prevents automatically wrapping each specified test in a transaction,
|
|
86
|
+
# to allow application logic transactions to be tested in a top-level
|
|
87
|
+
# (non-nested) context.
|
|
89
88
|
def uses_transaction(*methods)
|
|
90
89
|
@uses_transaction = [] unless defined?(@uses_transaction)
|
|
91
90
|
@uses_transaction.concat methods.map(&:to_s)
|
|
@@ -97,95 +96,109 @@ module ActiveRecord
|
|
|
97
96
|
end
|
|
98
97
|
end
|
|
99
98
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
99
|
+
# Generic fixture accessor for fixture names that may conflict with other methods.
|
|
100
|
+
#
|
|
101
|
+
# assert_equal "Ruby on Rails", web_sites(:rubyonrails).name
|
|
102
|
+
# assert_equal "Ruby on Rails", fixture(:web_sites, :rubyonrails).name
|
|
103
|
+
def fixture(fixture_set_name, *fixture_names)
|
|
104
|
+
active_record_fixture(fixture_set_name, *fixture_names)
|
|
103
105
|
end
|
|
104
106
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
107
|
+
private
|
|
108
|
+
def run_in_transaction?
|
|
109
|
+
use_transactional_tests &&
|
|
110
|
+
!self.class.uses_transaction?(name)
|
|
108
111
|
end
|
|
109
112
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
113
|
+
def setup_fixtures(config = ActiveRecord::Base)
|
|
114
|
+
if pre_loaded_fixtures && !use_transactional_tests
|
|
115
|
+
raise RuntimeError, "pre_loaded_fixtures requires use_transactional_tests"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
@fixture_cache = {}
|
|
119
|
+
@fixture_cache_key = [self.class.fixture_table_names.dup, self.class.fixture_paths.dup, self.class.fixture_class_names.dup]
|
|
120
|
+
@fixture_connection_pools = []
|
|
121
|
+
@@already_loaded_fixtures ||= {}
|
|
122
|
+
@connection_subscriber = nil
|
|
123
|
+
@saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
|
|
124
|
+
|
|
125
|
+
if run_in_transaction?
|
|
126
|
+
# Load fixtures once and begin transaction.
|
|
127
|
+
@loaded_fixtures = @@already_loaded_fixtures[@fixture_cache_key]
|
|
128
|
+
unless @loaded_fixtures
|
|
129
|
+
@@already_loaded_fixtures.clear
|
|
130
|
+
@loaded_fixtures = @@already_loaded_fixtures[@fixture_cache_key] = load_fixtures(config)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
setup_transactional_fixtures
|
|
121
134
|
else
|
|
135
|
+
# Load fixtures for every test.
|
|
136
|
+
ActiveRecord::FixtureSet.reset_cache
|
|
137
|
+
invalidate_already_loaded_fixtures
|
|
122
138
|
@loaded_fixtures = load_fixtures(config)
|
|
123
|
-
@@already_loaded_fixtures[self.class] = @loaded_fixtures
|
|
124
139
|
end
|
|
125
140
|
|
|
141
|
+
# Instantiate fixtures for every test if requested.
|
|
142
|
+
instantiate_fixtures if use_instantiated_fixtures
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def teardown_fixtures
|
|
146
|
+
# Rollback changes if a transaction is active.
|
|
147
|
+
if run_in_transaction?
|
|
148
|
+
teardown_transactional_fixtures
|
|
149
|
+
else
|
|
150
|
+
ActiveRecord::FixtureSet.reset_cache
|
|
151
|
+
invalidate_already_loaded_fixtures
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
ActiveRecord::Base.connection_handler.clear_active_connections!(:all)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def invalidate_already_loaded_fixtures
|
|
158
|
+
@@already_loaded_fixtures.clear
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def setup_transactional_fixtures
|
|
162
|
+
setup_shared_connection_pool
|
|
163
|
+
|
|
126
164
|
# Begin transactions for connections already established
|
|
127
|
-
@
|
|
128
|
-
@
|
|
129
|
-
|
|
130
|
-
|
|
165
|
+
@fixture_connection_pools = ActiveRecord::Base.connection_handler.connection_pool_list(:writing)
|
|
166
|
+
@fixture_connection_pools.each do |pool|
|
|
167
|
+
pool.pin_connection!(lock_threads)
|
|
168
|
+
pool.lease_connection
|
|
131
169
|
end
|
|
132
170
|
|
|
133
171
|
# When connections are established in the future, begin a transaction too
|
|
134
172
|
@connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
|
|
135
|
-
|
|
173
|
+
connection_name = payload[:connection_name] if payload.key?(:connection_name)
|
|
136
174
|
shard = payload[:shard] if payload.key?(:shard)
|
|
137
|
-
setup_shared_connection_pool
|
|
138
175
|
|
|
139
|
-
if
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
connection = nil
|
|
144
|
-
end
|
|
176
|
+
if connection_name
|
|
177
|
+
pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(connection_name, shard: shard)
|
|
178
|
+
if pool
|
|
179
|
+
setup_shared_connection_pool
|
|
145
180
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
181
|
+
unless @fixture_connection_pools.include?(pool)
|
|
182
|
+
pool.pin_connection!(lock_threads)
|
|
183
|
+
pool.lease_connection
|
|
184
|
+
@fixture_connection_pools << pool
|
|
185
|
+
end
|
|
150
186
|
end
|
|
151
187
|
end
|
|
152
188
|
end
|
|
153
|
-
|
|
154
|
-
# Load fixtures for every test.
|
|
155
|
-
else
|
|
156
|
-
ActiveRecord::FixtureSet.reset_cache
|
|
157
|
-
@@already_loaded_fixtures[self.class] = nil
|
|
158
|
-
@loaded_fixtures = load_fixtures(config)
|
|
159
189
|
end
|
|
160
190
|
|
|
161
|
-
|
|
162
|
-
instantiate_fixtures if use_instantiated_fixtures
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
def teardown_fixtures
|
|
166
|
-
# Rollback changes if a transaction is active.
|
|
167
|
-
if run_in_transaction?
|
|
191
|
+
def teardown_transactional_fixtures
|
|
168
192
|
ActiveSupport::Notifications.unsubscribe(@connection_subscriber) if @connection_subscriber
|
|
169
|
-
@
|
|
170
|
-
|
|
171
|
-
|
|
193
|
+
unless @fixture_connection_pools.map(&:unpin_connection!).all?
|
|
194
|
+
# Something caused the transaction to be committed or rolled back
|
|
195
|
+
# We can no longer trust the database is in a clean state.
|
|
196
|
+
@@already_loaded_fixtures.clear
|
|
172
197
|
end
|
|
173
|
-
@
|
|
198
|
+
@fixture_connection_pools.clear
|
|
174
199
|
teardown_shared_connection_pool
|
|
175
|
-
else
|
|
176
|
-
ActiveRecord::FixtureSet.reset_cache
|
|
177
200
|
end
|
|
178
201
|
|
|
179
|
-
ActiveRecord::Base.clear_active_connections!
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
def enlist_fixture_connections
|
|
183
|
-
setup_shared_connection_pool
|
|
184
|
-
|
|
185
|
-
ActiveRecord::Base.connection_handler.connection_pool_list.map(&:connection)
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
private
|
|
189
202
|
# Shares the writing connection pool with connections on
|
|
190
203
|
# other handlers.
|
|
191
204
|
#
|
|
@@ -193,79 +206,43 @@ module ActiveRecord
|
|
|
193
206
|
# need to share a connection pool so that the reading connection
|
|
194
207
|
# can see data in the open transaction on the writing connection.
|
|
195
208
|
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
|
|
209
|
+
handler = ActiveRecord::Base.connection_handler
|
|
210
|
+
|
|
211
|
+
handler.connection_pool_names.each do |name|
|
|
212
|
+
pool_manager = handler.send(:connection_name_to_pool_manager)[name]
|
|
213
|
+
pool_manager.shard_names.each do |shard_name|
|
|
214
|
+
writing_pool_config = pool_manager.get_pool_config(ActiveRecord.writing_role, shard_name)
|
|
215
|
+
@saved_pool_configs[name][shard_name] ||= {}
|
|
216
|
+
pool_manager.role_names.each do |role|
|
|
217
|
+
next unless pool_config = pool_manager.get_pool_config(role, shard_name)
|
|
218
|
+
next if pool_config == writing_pool_config
|
|
219
|
+
|
|
220
|
+
@saved_pool_configs[name][shard_name][role] = pool_config
|
|
221
|
+
pool_manager.set_pool_config(role, shard_name, writing_pool_config)
|
|
233
222
|
end
|
|
234
223
|
end
|
|
235
224
|
end
|
|
236
225
|
end
|
|
237
226
|
|
|
238
227
|
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
|
|
228
|
+
handler = ActiveRecord::Base.connection_handler
|
|
250
229
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
230
|
+
@saved_pool_configs.each_pair do |name, shards|
|
|
231
|
+
pool_manager = handler.send(:connection_name_to_pool_manager)[name]
|
|
232
|
+
shards.each_pair do |shard_name, roles|
|
|
233
|
+
roles.each_pair do |role, pool_config|
|
|
234
|
+
next unless pool_manager.get_pool_config(role, shard_name)
|
|
256
235
|
|
|
257
|
-
|
|
258
|
-
end
|
|
236
|
+
pool_manager.set_pool_config(role, shard_name, pool_config)
|
|
259
237
|
end
|
|
260
238
|
end
|
|
261
239
|
end
|
|
262
240
|
|
|
263
|
-
@legacy_saved_pool_configs.clear
|
|
264
241
|
@saved_pool_configs.clear
|
|
265
242
|
end
|
|
266
243
|
|
|
267
244
|
def load_fixtures(config)
|
|
268
|
-
ActiveRecord::FixtureSet.create_fixtures(
|
|
245
|
+
ActiveRecord::FixtureSet.create_fixtures(fixture_paths, fixture_table_names, fixture_class_names, config).index_by(&:name)
|
|
269
246
|
end
|
|
270
247
|
|
|
271
248
|
def instantiate_fixtures
|
|
@@ -283,5 +260,50 @@ module ActiveRecord
|
|
|
283
260
|
def load_instances?
|
|
284
261
|
use_instantiated_fixtures != :no_instances
|
|
285
262
|
end
|
|
263
|
+
|
|
264
|
+
def method_missing(method, ...)
|
|
265
|
+
if fixture_sets.key?(method.name)
|
|
266
|
+
active_record_fixture(method, ...)
|
|
267
|
+
else
|
|
268
|
+
super
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def respond_to_missing?(method, include_private = false)
|
|
273
|
+
if include_private && fixture_sets.key?(method.name)
|
|
274
|
+
true
|
|
275
|
+
else
|
|
276
|
+
super
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def active_record_fixture(fixture_set_name, *fixture_names)
|
|
281
|
+
if fs_name = fixture_sets[fixture_set_name.name]
|
|
282
|
+
access_fixture(fs_name, *fixture_names)
|
|
283
|
+
else
|
|
284
|
+
raise StandardError, "No fixture set named '#{fixture_set_name.inspect}'"
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def access_fixture(fs_name, *fixture_names)
|
|
289
|
+
force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
|
|
290
|
+
return_single_record = fixture_names.size == 1
|
|
291
|
+
|
|
292
|
+
fixture_names = @loaded_fixtures[fs_name].fixtures.keys if fixture_names.empty?
|
|
293
|
+
@fixture_cache[fs_name] ||= {}
|
|
294
|
+
|
|
295
|
+
instances = fixture_names.map do |f_name|
|
|
296
|
+
f_name = f_name.to_s if f_name.is_a?(Symbol)
|
|
297
|
+
@fixture_cache[fs_name].delete(f_name) if force_reload
|
|
298
|
+
|
|
299
|
+
if @loaded_fixtures[fs_name][f_name]
|
|
300
|
+
@fixture_cache[fs_name][f_name] ||= @loaded_fixtures[fs_name][f_name].find
|
|
301
|
+
else
|
|
302
|
+
raise StandardError, "No fixture named '#{f_name}' found for fixture set '#{fs_name}'"
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
return_single_record ? instances.first : instances
|
|
307
|
+
end
|
|
286
308
|
end
|
|
287
309
|
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Assertions
|
|
5
|
+
module QueryAssertions
|
|
6
|
+
# Asserts that the number of SQL queries executed in the given block matches the expected count.
|
|
7
|
+
#
|
|
8
|
+
# # Check for exact number of queries
|
|
9
|
+
# assert_queries_count(1) { Post.first }
|
|
10
|
+
#
|
|
11
|
+
# # Check for any number of queries
|
|
12
|
+
# assert_queries_count { Post.first }
|
|
13
|
+
#
|
|
14
|
+
# If the +:include_schema+ option is provided, any queries (including schema related) are counted.
|
|
15
|
+
#
|
|
16
|
+
# assert_queries_count(1, include_schema: true) { Post.columns }
|
|
17
|
+
#
|
|
18
|
+
def assert_queries_count(count = nil, include_schema: false, &block)
|
|
19
|
+
ActiveRecord::Base.lease_connection.materialize_transactions
|
|
20
|
+
|
|
21
|
+
counter = SQLCounter.new
|
|
22
|
+
ActiveSupport::Notifications.subscribed(counter, "sql.active_record") do
|
|
23
|
+
result = _assert_nothing_raised_or_warn("assert_queries_count", &block)
|
|
24
|
+
queries = include_schema ? counter.log_all : counter.log
|
|
25
|
+
if count
|
|
26
|
+
assert_equal count, queries.size, "#{queries.size} instead of #{count} queries were executed. Queries: #{queries.join("\n\n")}"
|
|
27
|
+
else
|
|
28
|
+
assert_operator queries.size, :>=, 1, "1 or more queries expected, but none were executed.#{queries.empty? ? '' : "\nQueries:\n#{queries.join("\n")}"}"
|
|
29
|
+
end
|
|
30
|
+
result
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Asserts that no SQL queries are executed in the given block.
|
|
35
|
+
#
|
|
36
|
+
# assert_no_queries { post.comments }
|
|
37
|
+
#
|
|
38
|
+
# If the +:include_schema+ option is provided, any queries (including schema related) are counted.
|
|
39
|
+
#
|
|
40
|
+
# assert_no_queries(include_schema: true) { Post.columns }
|
|
41
|
+
#
|
|
42
|
+
def assert_no_queries(include_schema: false, &block)
|
|
43
|
+
assert_queries_count(0, include_schema: include_schema, &block)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Asserts that the SQL queries executed in the given block match expected pattern.
|
|
47
|
+
#
|
|
48
|
+
# # Check for exact number of queries
|
|
49
|
+
# assert_queries_match(/LIMIT \?/, count: 1) { Post.first }
|
|
50
|
+
#
|
|
51
|
+
# # Check for any number of queries
|
|
52
|
+
# assert_queries_match(/LIMIT \?/) { Post.first }
|
|
53
|
+
#
|
|
54
|
+
# If the +:include_schema+ option is provided, any queries (including schema related)
|
|
55
|
+
# that match the matcher are considered.
|
|
56
|
+
#
|
|
57
|
+
# assert_queries_match(/FROM pg_attribute/i, include_schema: true) { Post.columns }
|
|
58
|
+
#
|
|
59
|
+
def assert_queries_match(match, count: nil, include_schema: false, &block)
|
|
60
|
+
ActiveRecord::Base.lease_connection.materialize_transactions
|
|
61
|
+
|
|
62
|
+
counter = SQLCounter.new
|
|
63
|
+
ActiveSupport::Notifications.subscribed(counter, "sql.active_record") do
|
|
64
|
+
result = _assert_nothing_raised_or_warn("assert_queries_match", &block)
|
|
65
|
+
queries = include_schema ? counter.log_all : counter.log
|
|
66
|
+
matched_queries = queries.select { |query| match === query }
|
|
67
|
+
|
|
68
|
+
if count
|
|
69
|
+
assert_equal count, matched_queries.size, "#{matched_queries.size} instead of #{count} queries were executed.#{queries.empty? ? '' : "\nQueries:\n#{queries.join("\n")}"}"
|
|
70
|
+
else
|
|
71
|
+
assert_operator matched_queries.size, :>=, 1, "1 or more queries expected, but none were executed.#{queries.empty? ? '' : "\nQueries:\n#{queries.join("\n")}"}"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
result
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Asserts that no SQL queries matching the pattern are executed in the given block.
|
|
79
|
+
#
|
|
80
|
+
# assert_no_queries_match(/SELECT/i) { post.comments }
|
|
81
|
+
#
|
|
82
|
+
# If the +:include_schema+ option is provided, any queries (including schema related)
|
|
83
|
+
# that match the matcher are counted.
|
|
84
|
+
#
|
|
85
|
+
# assert_no_queries_match(/FROM pg_attribute/i, include_schema: true) { Post.columns }
|
|
86
|
+
#
|
|
87
|
+
def assert_no_queries_match(match, include_schema: false, &block)
|
|
88
|
+
assert_queries_match(match, count: 0, include_schema: include_schema, &block)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
class SQLCounter # :nodoc:
|
|
92
|
+
attr_reader :log_full, :log_all
|
|
93
|
+
|
|
94
|
+
def initialize
|
|
95
|
+
@log_full = []
|
|
96
|
+
@log_all = []
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def log
|
|
100
|
+
@log_full.map(&:first)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def call(*, payload)
|
|
104
|
+
return if payload[:cached]
|
|
105
|
+
|
|
106
|
+
sql = payload[:sql]
|
|
107
|
+
@log_all << sql
|
|
108
|
+
|
|
109
|
+
unless payload[:name] == "SCHEMA"
|
|
110
|
+
bound_values = (payload[:binds] || []).map do |value|
|
|
111
|
+
value = value.value_for_database if value.respond_to?(:value_for_database)
|
|
112
|
+
value
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
@log_full << [sql, bound_values]
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|