activerecord 8.1.0.beta1 → 8.1.0.rc1
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 +105 -4
- data/lib/active_record/associations/belongs_to_association.rb +2 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +10 -2
- data/lib/active_record/attribute_methods.rb +1 -1
- data/lib/active_record/autosave_association.rb +2 -2
- data/lib/active_record/base.rb +2 -3
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +31 -29
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +32 -13
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -8
- data/lib/active_record/connection_adapters/abstract/transaction.rb +9 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +25 -11
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +0 -2
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +0 -2
- data/lib/active_record/connection_adapters/postgresql/column.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +8 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +7 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +16 -5
- data/lib/active_record/connection_handling.rb +2 -1
- data/lib/active_record/database_configurations/hash_config.rb +5 -2
- data/lib/active_record/encryption/encryptor.rb +12 -0
- data/lib/active_record/errors.rb +3 -3
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_registry.rb +51 -1
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/log_subscriber.rb +1 -1
- data/lib/active_record/migration/compatibility.rb +1 -1
- data/lib/active_record/model_schema.rb +26 -3
- data/lib/active_record/railties/controller_runtime.rb +11 -6
- data/lib/active_record/railties/databases.rake +1 -1
- data/lib/active_record/railties/job_runtime.rb +2 -2
- data/lib/active_record/relation/batches.rb +3 -3
- data/lib/active_record/relation/merger.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +9 -9
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +7 -7
- data/lib/active_record/relation/predicate_builder.rb +7 -5
- data/lib/active_record/relation/query_methods.rb +1 -1
- data/lib/active_record/relation/where_clause.rb +2 -0
- data/lib/active_record/relation.rb +1 -1
- data/lib/active_record/runtime_registry.rb +41 -58
- data/lib/active_record/structured_event_subscriber.rb +85 -0
- data/lib/active_record/table_metadata.rb +5 -20
- data/lib/active_record/tasks/database_tasks.rb +24 -14
- data/lib/active_record/test_databases.rb +4 -2
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- metadata +9 -9
- data/lib/active_record/explain_subscriber.rb +0 -34
@@ -176,6 +176,8 @@ module ActiveRecord
|
|
176
176
|
end
|
177
177
|
|
178
178
|
def except_predicates(columns)
|
179
|
+
return predicates if columns.empty?
|
180
|
+
|
179
181
|
attrs = columns.extract! { |node| node.is_a?(Arel::Attribute) }
|
180
182
|
non_attrs = columns.extract! { |node| node.is_a?(Arel::Predications) }
|
181
183
|
|
@@ -307,7 +307,7 @@ module ActiveRecord
|
|
307
307
|
end
|
308
308
|
end
|
309
309
|
|
310
|
-
# Like #find_or_create_by, but calls {new}[rdoc-ref:Core
|
310
|
+
# Like #find_or_create_by, but calls {new}[rdoc-ref:Core.new]
|
311
311
|
# instead of {create}[rdoc-ref:Persistence::ClassMethods#create].
|
312
312
|
def find_or_initialize_by(attributes, &block)
|
313
313
|
find_by(attributes) || new(attributes, &block)
|
@@ -3,80 +3,63 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
# This is a thread locals registry for Active Record. For example:
|
5
5
|
#
|
6
|
-
# ActiveRecord::RuntimeRegistry.sql_runtime
|
6
|
+
# ActiveRecord::RuntimeRegistry.stats.sql_runtime
|
7
7
|
#
|
8
8
|
# returns the connection handler local to the current unit of execution (either thread of fiber).
|
9
9
|
module RuntimeRegistry # :nodoc:
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
class Stats
|
11
|
+
attr_accessor :sql_runtime, :async_sql_runtime, :queries_count, :cached_queries_count
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@sql_runtime = 0.0
|
15
|
+
@async_sql_runtime = 0.0
|
16
|
+
@queries_count = 0
|
17
|
+
@cached_queries_count = 0
|
18
|
+
end
|
19
|
+
|
20
|
+
def reset_runtimes
|
21
|
+
sql_runtime_was = @sql_runtime
|
22
|
+
@sql_runtime = 0.0
|
23
|
+
@async_sql_runtime = 0.0
|
24
|
+
sql_runtime_was
|
25
|
+
end
|
26
|
+
|
27
|
+
public alias_method :reset, :initialize
|
14
28
|
end
|
15
29
|
|
16
|
-
|
17
|
-
ActiveSupport::IsolatedExecutionState[:active_record_sql_runtime] = runtime
|
18
|
-
end
|
19
|
-
|
20
|
-
def async_sql_runtime
|
21
|
-
ActiveSupport::IsolatedExecutionState[:active_record_async_sql_runtime] ||= 0.0
|
22
|
-
end
|
30
|
+
extend self
|
23
31
|
|
24
|
-
def
|
25
|
-
|
32
|
+
def call(name, start, finish, id, payload)
|
33
|
+
record(
|
34
|
+
payload[:name],
|
35
|
+
(finish - start) * 1_000.0,
|
36
|
+
async: payload[:async],
|
37
|
+
lock_wait: payload[:lock_wait],
|
38
|
+
)
|
26
39
|
end
|
27
40
|
|
28
|
-
def
|
29
|
-
|
30
|
-
end
|
41
|
+
def record(query_name, runtime, cached: false, async: false, lock_wait: nil)
|
42
|
+
stats = self.stats
|
31
43
|
|
32
|
-
|
33
|
-
|
34
|
-
|
44
|
+
unless query_name == "TRANSACTION" || query_name == "SCHEMA"
|
45
|
+
stats.queries_count += 1
|
46
|
+
stats.cached_queries_count += 1 if cached
|
47
|
+
end
|
35
48
|
|
36
|
-
|
37
|
-
|
49
|
+
if async
|
50
|
+
stats.async_sql_runtime += (runtime - lock_wait)
|
51
|
+
end
|
52
|
+
stats.sql_runtime += runtime
|
38
53
|
end
|
39
54
|
|
40
|
-
def
|
41
|
-
ActiveSupport::IsolatedExecutionState[:
|
55
|
+
def stats
|
56
|
+
ActiveSupport::IsolatedExecutionState[:active_record_runtime] ||= Stats.new
|
42
57
|
end
|
43
58
|
|
44
59
|
def reset
|
45
|
-
|
46
|
-
reset_queries_count
|
47
|
-
reset_cached_queries_count
|
48
|
-
end
|
49
|
-
|
50
|
-
def reset_runtimes
|
51
|
-
rt, self.sql_runtime = sql_runtime, 0.0
|
52
|
-
self.async_sql_runtime = 0.0
|
53
|
-
rt
|
54
|
-
end
|
55
|
-
|
56
|
-
def reset_queries_count
|
57
|
-
qc = queries_count
|
58
|
-
self.queries_count = 0
|
59
|
-
qc
|
60
|
-
end
|
61
|
-
|
62
|
-
def reset_cached_queries_count
|
63
|
-
qc = cached_queries_count
|
64
|
-
self.cached_queries_count = 0
|
65
|
-
qc
|
60
|
+
stats.reset
|
66
61
|
end
|
67
62
|
end
|
68
63
|
end
|
69
64
|
|
70
|
-
ActiveSupport::Notifications.monotonic_subscribe("sql.active_record"
|
71
|
-
unless ["SCHEMA", "TRANSACTION"].include?(payload[:name])
|
72
|
-
ActiveRecord::RuntimeRegistry.queries_count += 1
|
73
|
-
ActiveRecord::RuntimeRegistry.cached_queries_count += 1 if payload[:cached]
|
74
|
-
end
|
75
|
-
|
76
|
-
runtime = (finish - start) * 1_000.0
|
77
|
-
|
78
|
-
if payload[:async]
|
79
|
-
ActiveRecord::RuntimeRegistry.async_sql_runtime += (runtime - payload[:lock_wait])
|
80
|
-
end
|
81
|
-
ActiveRecord::RuntimeRegistry.sql_runtime += runtime
|
82
|
-
end
|
65
|
+
ActiveSupport::Notifications.monotonic_subscribe("sql.active_record", ActiveRecord::RuntimeRegistry)
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/structured_event_subscriber"
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
class StructuredEventSubscriber < ActiveSupport::StructuredEventSubscriber # :nodoc:
|
7
|
+
IGNORE_PAYLOAD_NAMES = ["SCHEMA", "EXPLAIN"]
|
8
|
+
|
9
|
+
def strict_loading_violation(event)
|
10
|
+
owner = event.payload[:owner]
|
11
|
+
reflection = event.payload[:reflection]
|
12
|
+
|
13
|
+
emit_debug_event("active_record.strict_loading_violation",
|
14
|
+
owner: owner.name,
|
15
|
+
class: reflection.klass.name,
|
16
|
+
name: reflection.name,
|
17
|
+
)
|
18
|
+
end
|
19
|
+
debug_only :strict_loading_violation
|
20
|
+
|
21
|
+
def sql(event)
|
22
|
+
payload = event.payload
|
23
|
+
|
24
|
+
return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
|
25
|
+
|
26
|
+
binds = nil
|
27
|
+
|
28
|
+
if payload[:binds]&.any?
|
29
|
+
casted_params = type_casted_binds(payload[:type_casted_binds])
|
30
|
+
|
31
|
+
binds = []
|
32
|
+
payload[:binds].each_with_index do |attr, i|
|
33
|
+
attribute_name = if attr.respond_to?(:name)
|
34
|
+
attr.name
|
35
|
+
elsif attr.respond_to?(:[]) && attr[i].respond_to?(:name)
|
36
|
+
attr[i].name
|
37
|
+
else
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
|
41
|
+
filtered_params = filter(attribute_name, casted_params[i])
|
42
|
+
|
43
|
+
binds << render_bind(attr, filtered_params)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
emit_debug_event("active_record.sql",
|
48
|
+
async: payload[:async],
|
49
|
+
name: payload[:name],
|
50
|
+
sql: payload[:sql],
|
51
|
+
cached: payload[:cached],
|
52
|
+
lock_wait: payload[:lock_wait],
|
53
|
+
binds: binds,
|
54
|
+
duration_ms: event.duration.round(2),
|
55
|
+
)
|
56
|
+
end
|
57
|
+
debug_only :sql
|
58
|
+
|
59
|
+
private
|
60
|
+
def type_casted_binds(casted_binds)
|
61
|
+
casted_binds.respond_to?(:call) ? casted_binds.call : casted_binds
|
62
|
+
end
|
63
|
+
|
64
|
+
def render_bind(attr, value)
|
65
|
+
case attr
|
66
|
+
when ActiveModel::Attribute
|
67
|
+
if attr.type.binary? && attr.value
|
68
|
+
value = "<#{attr.value_for_database.to_s.bytesize} bytes of binary data>"
|
69
|
+
end
|
70
|
+
when Array
|
71
|
+
attr = attr.first
|
72
|
+
else
|
73
|
+
attr = nil
|
74
|
+
end
|
75
|
+
|
76
|
+
[attr&.name, value]
|
77
|
+
end
|
78
|
+
|
79
|
+
def filter(name, value)
|
80
|
+
ActiveRecord::Base.inspection_filter.filter_param(name, value)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
ActiveRecord::StructuredEventSubscriber.attach_to :active_record
|
@@ -2,12 +2,9 @@
|
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
class TableMetadata # :nodoc:
|
5
|
-
|
6
|
-
|
7
|
-
def initialize(klass, arel_table, reflection = nil)
|
5
|
+
def initialize(klass, arel_table)
|
8
6
|
@klass = klass
|
9
7
|
@arel_table = arel_table
|
10
|
-
@reflection = reflection
|
11
8
|
end
|
12
9
|
|
13
10
|
def primary_key
|
@@ -22,7 +19,7 @@ module ActiveRecord
|
|
22
19
|
klass&.columns_hash&.key?(column_name)
|
23
20
|
end
|
24
21
|
|
25
|
-
def associated_with
|
22
|
+
def associated_with(table_name)
|
26
23
|
klass&._reflect_on_association(table_name)
|
27
24
|
end
|
28
25
|
|
@@ -42,26 +39,14 @@ module ActiveRecord
|
|
42
39
|
if association_klass
|
43
40
|
arel_table = association_klass.arel_table
|
44
41
|
arel_table = arel_table.alias(table_name) if arel_table.name != table_name
|
45
|
-
TableMetadata.new(association_klass, arel_table
|
42
|
+
TableMetadata.new(association_klass, arel_table)
|
46
43
|
else
|
47
44
|
type_caster = TypeCaster::Connection.new(klass, table_name)
|
48
45
|
arel_table = Arel::Table.new(table_name, type_caster: type_caster)
|
49
|
-
TableMetadata.new(nil, arel_table
|
46
|
+
TableMetadata.new(nil, arel_table)
|
50
47
|
end
|
51
48
|
end
|
52
49
|
|
53
|
-
def polymorphic_association?
|
54
|
-
reflection&.polymorphic?
|
55
|
-
end
|
56
|
-
|
57
|
-
def polymorphic_name_association
|
58
|
-
reflection&.polymorphic_name
|
59
|
-
end
|
60
|
-
|
61
|
-
def through_association?
|
62
|
-
reflection&.through_reflection?
|
63
|
-
end
|
64
|
-
|
65
50
|
def reflect_on_aggregation(aggregation_name)
|
66
51
|
klass&.reflect_on_aggregation(aggregation_name)
|
67
52
|
end
|
@@ -78,6 +63,6 @@ module ActiveRecord
|
|
78
63
|
attr_reader :arel_table
|
79
64
|
|
80
65
|
private
|
81
|
-
attr_reader :klass
|
66
|
+
attr_reader :klass
|
82
67
|
end
|
83
68
|
end
|
@@ -428,9 +428,15 @@ module ActiveRecord
|
|
428
428
|
end
|
429
429
|
|
430
430
|
def dump_all
|
431
|
-
|
432
|
-
|
431
|
+
seen_schemas = []
|
432
|
+
|
433
|
+
ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
|
434
|
+
schema_path = schema_dump_path(db_config, ENV["SCHEMA_FORMAT"] || db_config.schema_format)
|
435
|
+
|
436
|
+
next if seen_schemas.include?(schema_path)
|
437
|
+
|
433
438
|
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, ENV["SCHEMA_FORMAT"] || db_config.schema_format)
|
439
|
+
seen_schemas << schema_path
|
434
440
|
end
|
435
441
|
end
|
436
442
|
|
@@ -441,18 +447,22 @@ module ActiveRecord
|
|
441
447
|
filename = schema_dump_path(db_config, format)
|
442
448
|
return unless filename
|
443
449
|
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
450
|
+
with_temporary_pool(db_config) do |pool|
|
451
|
+
FileUtils.mkdir_p(db_dir)
|
452
|
+
case format.to_sym
|
453
|
+
when :ruby
|
454
|
+
File.open(filename, "w:utf-8") do |file|
|
455
|
+
ActiveRecord::SchemaDumper.dump(pool, file)
|
456
|
+
end
|
457
|
+
when :sql
|
458
|
+
structure_dump(db_config, filename)
|
459
|
+
if pool.schema_migration.table_exists?
|
460
|
+
File.open(filename, "a") do |f|
|
461
|
+
pool.with_connection do |connection|
|
462
|
+
f.puts connection.dump_schema_versions
|
463
|
+
end
|
464
|
+
f.print "\n"
|
465
|
+
end
|
456
466
|
end
|
457
467
|
end
|
458
468
|
end
|
@@ -19,10 +19,12 @@ module ActiveRecord
|
|
19
19
|
def self.create_and_load_schema(i, env_name:)
|
20
20
|
old, ENV["VERBOSE"] = ENV["VERBOSE"], "false"
|
21
21
|
|
22
|
-
ActiveRecord::Base.configurations.configs_for(env_name: env_name).each do |db_config|
|
22
|
+
ActiveRecord::Base.configurations.configs_for(env_name: env_name, include_hidden: true).each do |db_config|
|
23
23
|
db_config._database = "#{db_config.database}_#{i}"
|
24
24
|
|
25
|
-
|
25
|
+
if db_config.database_tasks?
|
26
|
+
ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config, nil)
|
27
|
+
end
|
26
28
|
end
|
27
29
|
ensure
|
28
30
|
ActiveRecord::Base.establish_connection
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 8.1.0.
|
4
|
+
version: 8.1.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
@@ -15,28 +15,28 @@ dependencies:
|
|
15
15
|
requirements:
|
16
16
|
- - '='
|
17
17
|
- !ruby/object:Gem::Version
|
18
|
-
version: 8.1.0.
|
18
|
+
version: 8.1.0.rc1
|
19
19
|
type: :runtime
|
20
20
|
prerelease: false
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
22
22
|
requirements:
|
23
23
|
- - '='
|
24
24
|
- !ruby/object:Gem::Version
|
25
|
-
version: 8.1.0.
|
25
|
+
version: 8.1.0.rc1
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: activemodel
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
29
29
|
requirements:
|
30
30
|
- - '='
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 8.1.0.
|
32
|
+
version: 8.1.0.rc1
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
37
|
- - '='
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 8.1.0.
|
39
|
+
version: 8.1.0.rc1
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: timeout
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
@@ -253,7 +253,6 @@ files:
|
|
253
253
|
- lib/active_record/errors.rb
|
254
254
|
- lib/active_record/explain.rb
|
255
255
|
- lib/active_record/explain_registry.rb
|
256
|
-
- lib/active_record/explain_subscriber.rb
|
257
256
|
- lib/active_record/filter_attribute_handler.rb
|
258
257
|
- lib/active_record/fixture_set/file.rb
|
259
258
|
- lib/active_record/fixture_set/model_metadata.rb
|
@@ -337,6 +336,7 @@ files:
|
|
337
336
|
- lib/active_record/signed_id.rb
|
338
337
|
- lib/active_record/statement_cache.rb
|
339
338
|
- lib/active_record/store.rb
|
339
|
+
- lib/active_record/structured_event_subscriber.rb
|
340
340
|
- lib/active_record/suppressor.rb
|
341
341
|
- lib/active_record/table_metadata.rb
|
342
342
|
- lib/active_record/tasks/abstract_tasks.rb
|
@@ -478,10 +478,10 @@ licenses:
|
|
478
478
|
- MIT
|
479
479
|
metadata:
|
480
480
|
bug_tracker_uri: https://github.com/rails/rails/issues
|
481
|
-
changelog_uri: https://github.com/rails/rails/blob/v8.1.0.
|
482
|
-
documentation_uri: https://api.rubyonrails.org/v8.1.0.
|
481
|
+
changelog_uri: https://github.com/rails/rails/blob/v8.1.0.rc1/activerecord/CHANGELOG.md
|
482
|
+
documentation_uri: https://api.rubyonrails.org/v8.1.0.rc1/
|
483
483
|
mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
|
484
|
-
source_code_uri: https://github.com/rails/rails/tree/v8.1.0.
|
484
|
+
source_code_uri: https://github.com/rails/rails/tree/v8.1.0.rc1/activerecord
|
485
485
|
rubygems_mfa_required: 'true'
|
486
486
|
rdoc_options:
|
487
487
|
- "--main"
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "active_support/notifications"
|
4
|
-
require "active_record/explain_registry"
|
5
|
-
|
6
|
-
module ActiveRecord
|
7
|
-
class ExplainSubscriber # :nodoc:
|
8
|
-
def start(name, id, payload)
|
9
|
-
# unused
|
10
|
-
end
|
11
|
-
|
12
|
-
def finish(name, id, payload)
|
13
|
-
if ExplainRegistry.collect? && !ignore_payload?(payload)
|
14
|
-
ExplainRegistry.queries << payload.values_at(:sql, :binds)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
# SCHEMA queries cannot be EXPLAINed, also we do not want to run EXPLAIN on
|
19
|
-
# our own EXPLAINs no matter how loopingly beautiful that would be.
|
20
|
-
#
|
21
|
-
# On the other hand, we want to monitor the performance of our real database
|
22
|
-
# queries, not the performance of the access to the query cache.
|
23
|
-
IGNORED_PAYLOADS = %w(SCHEMA EXPLAIN)
|
24
|
-
EXPLAINED_SQLS = /\A\s*(\/\*.*\*\/)?\s*(with|select|update|delete|insert)\b/i
|
25
|
-
def ignore_payload?(payload)
|
26
|
-
payload[:exception] ||
|
27
|
-
payload[:cached] ||
|
28
|
-
IGNORED_PAYLOADS.include?(payload[:name]) ||
|
29
|
-
!payload[:sql].match?(EXPLAINED_SQLS)
|
30
|
-
end
|
31
|
-
|
32
|
-
ActiveSupport::Notifications.subscribe("sql.active_record", new)
|
33
|
-
end
|
34
|
-
end
|