database_recorder 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +40 -8
- data/lib/database_recorder/active_record/abstract_adapter_ext.rb +13 -0
- data/lib/database_recorder/{activerecord → active_record}/base_ext.rb +0 -0
- data/lib/database_recorder/{activerecord → active_record}/recorded_result.rb +0 -0
- data/lib/database_recorder/{activerecord/abstract_adapter_ext.rb → active_record/recorder.rb} +23 -8
- data/lib/database_recorder/config.rb +26 -10
- data/lib/database_recorder/core.rb +10 -8
- data/lib/database_recorder/mysql2/client_ext.rb +19 -0
- data/lib/database_recorder/mysql2/recorded_result.rb +3 -1
- data/lib/database_recorder/mysql2/recorder.rb +40 -37
- data/lib/database_recorder/mysql2/statement_ext.rb +13 -0
- data/lib/database_recorder/pg/connection_ext.rb +53 -0
- data/lib/database_recorder/pg/recorder.rb +23 -67
- data/lib/database_recorder/recording.rb +7 -2
- data/lib/database_recorder/rspec.rb +1 -2
- data/lib/database_recorder/storage/base.rb +12 -0
- data/lib/database_recorder/storage/file.rb +2 -7
- data/lib/database_recorder/storage/redis.rb +1 -6
- data/lib/database_recorder/version.rb +1 -1
- data/lib/database_recorder.rb +12 -12
- metadata +10 -6
- data/lib/database_recorder/activerecord/recorder.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bd8b63b3fa1b57dd6c2c5cdf501af590f75a5fcb52c322bc4eee702c55026db6
|
4
|
+
data.tar.gz: f2753254f7c7d79ef0fd7dd65e3439197419ae01d96e4625eb3a9f4632835bd9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 343167b893fd491b57405ad465e1b835fcf077d3cc806a4c3a4e6ca7c1253e0967acca90760c30e395de30aa8529421305910f9714879f118892259acf03dbe7
|
7
|
+
data.tar.gz: a2f8defdbd1e9f251afd6c999077870689c20f9c7868cc5d01a2947ab63c3ee1eec2c5401b14eef1378e450dbeb2fb170f93d011e54f8c8e677c150394f0b024
|
data/README.md
CHANGED
@@ -1,34 +1,66 @@
|
|
1
1
|
# Database Recorder
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/database_recorder.svg)](https://badge.fury.io/rb/database_recorder)
|
3
|
+
[![Linters](https://github.com/blocknotes/database_recorder/actions/workflows/linters.yml/badge.svg)](https://github.com/blocknotes/database_recorder/actions/workflows/linters.yml)
|
4
|
+
[![Specs ActiveRecord](https://github.com/blocknotes/database_recorder/actions/workflows/specs_active_record.yml/badge.svg)](https://github.com/blocknotes/database_recorder/actions/workflows/specs_active_record.yml)
|
5
|
+
[![Specs MySQL](https://github.com/blocknotes/database_recorder/actions/workflows/specs_mysql.yml/badge.svg)](https://github.com/blocknotes/database_recorder/actions/workflows/specs_mysql.yml)
|
6
|
+
[![Specs PostgreSQL](https://github.com/blocknotes/database_recorder/actions/workflows/specs_postgres.yml/badge.svg)](https://github.com/blocknotes/database_recorder/actions/workflows/specs_postgres.yml)
|
2
7
|
|
3
|
-
Record database queries for testing and development purposes
|
4
|
-
|
8
|
+
Record database queries for testing and development purposes.
|
9
|
+
Supports only RSpec at the moment. Store queries information on files or Redis.
|
5
10
|
|
6
11
|
Main features:
|
7
12
|
- store the history of the queries of a test when it run (for monitoring);
|
8
13
|
- eventually check if the current queries match the recorded ones (to prevent regressions);
|
9
14
|
- [EXPERIMENTAL] optionally replay the recorded queries replacing the original requests.
|
10
15
|
|
11
|
-
|
16
|
+
Sample output: [test.yml](extra/sample.yml)
|
12
17
|
|
13
18
|
## Install
|
14
19
|
|
15
|
-
- Add to your Gemfile: `gem 'database_recorder'` (:development, :test groups recommended)
|
16
|
-
-
|
17
|
-
+ Add to the `spec_helper.rb` (or rails_helper): `DatabaseRecorder::RSpec.setup`
|
18
|
-
+ In RSpec examples: add `:dbr` metadata
|
19
|
-
+ To verify the matching with the recorded query use: `dbr: { verify_queries: true }`
|
20
|
+
- Add to your Gemfile: `gem 'database_recorder', require: false` (:development, :test groups recommended)
|
21
|
+
- Using RSpec, add in **rails_helper.rb**:
|
20
22
|
|
21
23
|
```rb
|
24
|
+
require 'database_recorder'
|
25
|
+
DatabaseRecorder::RSpec.setup
|
26
|
+
```
|
27
|
+
|
28
|
+
- In the tests add `:dbr` metadata, examples:
|
29
|
+
|
30
|
+
```rb
|
31
|
+
# Activate DatabaseRecorder with the default options
|
22
32
|
it 'returns 3 posts', :dbr do
|
23
33
|
# ...
|
24
34
|
end
|
35
|
+
|
36
|
+
# Verify queries comparing with the stored ones:
|
37
|
+
it 'returns more posts', dbr: { verify_queries: true } do
|
38
|
+
# ...
|
39
|
+
end
|
25
40
|
```
|
26
41
|
|
42
|
+
Or eventually apply the metadata per path:
|
43
|
+
|
44
|
+
```rb
|
45
|
+
RSpec.configure do |config|
|
46
|
+
config.define_derived_metadata(file_path: %r{/spec/models/}) do |metadata|
|
47
|
+
metadata[:dbr] = true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
Using an environment variable to enable it:
|
53
|
+
|
54
|
+
![image1](extra/image1.png)
|
55
|
+
|
27
56
|
## Config
|
28
57
|
|
29
58
|
Add to your _spec_helper.rb_:
|
30
59
|
|
31
60
|
```rb
|
61
|
+
# Database driver to use: :active_record | :mysql2 | :pg
|
62
|
+
DatabaseRecorder::Config.db_driver = :pg
|
63
|
+
|
32
64
|
# To print the queries while executing the specs: false | true | :color
|
33
65
|
DatabaseRecorder::Config.print_queries = true
|
34
66
|
|
File without changes
|
File without changes
|
data/lib/database_recorder/{activerecord/abstract_adapter_ext.rb → active_record/recorder.rb}
RENAMED
@@ -2,12 +2,17 @@
|
|
2
2
|
|
3
3
|
module DatabaseRecorder
|
4
4
|
module ActiveRecord
|
5
|
-
module
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
module Recorder
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def ignore_query?(sql, name)
|
9
|
+
!Recording.started? ||
|
10
|
+
%w[schema transaction].include?(name&.downcase) ||
|
11
|
+
sql.downcase.match?(/\A(begin|commit|release|rollback|savepoint)/i)
|
12
|
+
end
|
13
|
+
|
14
|
+
def record(adapter, sql, name = 'SQL', binds = [], type_casted_binds = [], *args)
|
15
|
+
return yield if ignore_query?(sql, name)
|
11
16
|
|
12
17
|
Core.log_query(sql, name)
|
13
18
|
if Config.replay_recordings && Recording.from_cache
|
@@ -17,9 +22,9 @@ module DatabaseRecorder
|
|
17
22
|
|
18
23
|
RecordedResult.new(data['result']['fields'], data['result']['values'])
|
19
24
|
else
|
20
|
-
|
25
|
+
yield.tap do |result|
|
21
26
|
result_data =
|
22
|
-
if result.
|
27
|
+
if result && (result.respond_to?(:fields) || result.respond_to?(:columns))
|
23
28
|
fields = result.respond_to?(:fields) ? result.fields : result.columns
|
24
29
|
values = result.respond_to?(:values) ? result.values : result.to_a
|
25
30
|
{ 'count' => result.count, 'fields' => fields, 'values' => values }
|
@@ -28,6 +33,16 @@ module DatabaseRecorder
|
|
28
33
|
end
|
29
34
|
end
|
30
35
|
end
|
36
|
+
|
37
|
+
def setup
|
38
|
+
::ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
|
39
|
+
prepend AbstractAdapterExt
|
40
|
+
end
|
41
|
+
|
42
|
+
# ::ActiveRecord::Base.class_eval do
|
43
|
+
# prepend BaseExt
|
44
|
+
# end
|
45
|
+
end
|
31
46
|
end
|
32
47
|
end
|
33
48
|
end
|
@@ -7,28 +7,44 @@ module DatabaseRecorder
|
|
7
7
|
class Config
|
8
8
|
include Singleton
|
9
9
|
|
10
|
+
DEFAULT_DB_DRIVER = :active_record
|
11
|
+
DEFAULT_STORAGE = DatabaseRecorder::Storage::File
|
12
|
+
|
13
|
+
DB_DRIVER_VALUES = %i[active_record mysql2 pg].freeze
|
14
|
+
PRINT_QUERIES_VALUES = [false, true, :color].freeze
|
15
|
+
STORAGE_VALUES = {
|
16
|
+
file: DatabaseRecorder::Storage::File,
|
17
|
+
redis: DatabaseRecorder::Storage::Redis
|
18
|
+
}.freeze
|
19
|
+
|
10
20
|
attr_accessor :db_driver, :print_queries, :replay_recordings, :storage
|
11
21
|
|
12
22
|
class << self
|
13
23
|
extend Forwardable
|
14
24
|
|
15
|
-
def_delegators :instance, :db_driver, :
|
16
|
-
:replay_recordings=, :storage
|
25
|
+
def_delegators :instance, :db_driver, :print_queries, :replay_recordings, :replay_recordings=, :storage
|
17
26
|
|
18
27
|
def load_defaults
|
19
|
-
instance.db_driver =
|
20
|
-
instance.print_queries = false
|
28
|
+
instance.db_driver = DEFAULT_DB_DRIVER
|
29
|
+
instance.print_queries = false
|
21
30
|
instance.replay_recordings = false
|
22
|
-
|
31
|
+
instance.storage = DEFAULT_STORAGE
|
32
|
+
end
|
33
|
+
|
34
|
+
def db_driver=(value)
|
35
|
+
instance.db_driver = DB_DRIVER_VALUES.include?(value) ? value : DEFAULT_DB_DRIVER
|
36
|
+
end
|
37
|
+
|
38
|
+
def print_queries=(value)
|
39
|
+
instance.print_queries = PRINT_QUERIES_VALUES.include?(value) ? value : false
|
23
40
|
end
|
24
41
|
|
25
42
|
def storage=(value)
|
26
43
|
instance.storage =
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
else raise ArgumentError, "Unknown storage: #{value}"
|
44
|
+
if value.is_a?(Class) && value < Storage::Base
|
45
|
+
value
|
46
|
+
else
|
47
|
+
STORAGE_VALUES[value]
|
32
48
|
end
|
33
49
|
end
|
34
50
|
end
|
@@ -5,19 +5,21 @@ module DatabaseRecorder
|
|
5
5
|
module_function
|
6
6
|
|
7
7
|
def log_query(sql, source = nil)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
log =
|
9
|
+
case DatabaseRecorder::Config.print_queries
|
10
|
+
when true then "[DB] #{sql} [#{source}]"
|
11
|
+
when :color then "[DB] #{CodeRay.scan(sql, :sql).term} [#{source}]"
|
12
|
+
end
|
13
|
+
|
14
|
+
puts log if log
|
15
|
+
log
|
14
16
|
end
|
15
17
|
|
16
18
|
def setup
|
17
19
|
case DatabaseRecorder::Config.db_driver
|
18
20
|
when :active_record then ActiveRecord::Recorder.setup
|
19
|
-
when :mysql2 then Mysql2.setup
|
20
|
-
when :pg then PG.setup
|
21
|
+
when :mysql2 then Mysql2::Recorder.setup
|
22
|
+
when :pg then PG::Recorder.setup
|
21
23
|
end
|
22
24
|
end
|
23
25
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DatabaseRecorder
|
4
|
+
module Mysql2
|
5
|
+
module ClientExt
|
6
|
+
def query(sql, options = {})
|
7
|
+
Recorder.record(self, sql: sql) do
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def prepare(*args)
|
13
|
+
Recorder.record(self, sql: args[0]) do
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -3,50 +3,53 @@
|
|
3
3
|
module DatabaseRecorder
|
4
4
|
module Mysql2
|
5
5
|
module Recorder
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def ignore_query?(sql)
|
9
|
+
!Recording.started? ||
|
10
|
+
sql == 'SELECT LAST_INSERT_ID() AS _dbr_last_insert_id' ||
|
11
|
+
sql.downcase.match?(/\A(begin|commit|release|rollback|savepoint|show full fields from)/i) ||
|
12
|
+
sql.match?(/information_schema.statistics/)
|
10
13
|
end
|
11
|
-
end
|
12
14
|
|
13
|
-
|
15
|
+
def record(adapter, sql:)
|
16
|
+
return yield if ignore_query?(sql)
|
17
|
+
|
18
|
+
Core.log_query(sql)
|
19
|
+
if Config.replay_recordings && !Recording.cache.nil?
|
20
|
+
Recording.push(sql: sql)
|
21
|
+
data = Recording.cached_query_for(sql)
|
22
|
+
return yield unless data # cache miss
|
23
|
+
|
24
|
+
RecordedResult.new.prepare(data['result'].slice('count', 'fields', 'values')) if data['result']
|
25
|
+
else
|
26
|
+
yield.tap do |result|
|
27
|
+
result_data =
|
28
|
+
if result.is_a? ::Mysql2::Result
|
29
|
+
{ 'count' => result.count, 'fields' => result.fields, 'values' => result.to_a }
|
30
|
+
# else
|
31
|
+
# last_insert_id = adapter.query('SELECT LAST_INSERT_ID() AS _dbr_last_insert_id').to_a
|
32
|
+
# { 'count' => last_insert_id.count, 'fields' => ['id'], 'values' => last_insert_id }
|
33
|
+
end
|
34
|
+
|
35
|
+
Recording.push(sql: sql, result: result_data)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
14
39
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
sql.match?(/information_schema.statistics/)
|
20
|
-
end
|
40
|
+
def setup
|
41
|
+
::Mysql2::Client.class_eval do
|
42
|
+
prepend ClientExt
|
43
|
+
end
|
21
44
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
Core.log_query(sql)
|
26
|
-
if Config.replay_recordings && !Recording.cache.nil?
|
27
|
-
Recording.push(sql: sql)
|
28
|
-
data = Recording.cached_query_for(sql)
|
29
|
-
return yield unless data # cache miss
|
30
|
-
|
31
|
-
RecordedResult.new.prepare(data['result'].slice('count', 'fields', 'values')) if data['result']
|
32
|
-
else
|
33
|
-
yield.tap do |result|
|
34
|
-
result_data =
|
35
|
-
if result
|
36
|
-
{ 'count' => result.count, 'fields' => result.fields, 'values' => result.to_a }
|
37
|
-
else
|
38
|
-
last_insert_id = recorder.query('SELECT LAST_INSERT_ID() AS _dbr_last_insert_id').to_a
|
39
|
-
{ 'count' => last_insert_id.count, 'fields' => ['id'], 'values' => last_insert_id }
|
40
|
-
end
|
41
|
-
|
42
|
-
Recording.push(sql: sql, result: result_data)
|
45
|
+
::Mysql2::Statement.class_eval do
|
46
|
+
prepend StatementExt
|
43
47
|
end
|
44
48
|
end
|
45
|
-
end
|
46
49
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
+
def update_record(adapter, *args)
|
51
|
+
Recording.update_last(*args)
|
52
|
+
yield
|
50
53
|
end
|
51
54
|
end
|
52
55
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DatabaseRecorder
|
4
|
+
module PG
|
5
|
+
module ConnectionExt
|
6
|
+
def async_exec(sql)
|
7
|
+
Recorder.record(sql: sql, source: :async_exec) do
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def sync_exec(sql)
|
13
|
+
Recorder.record(sql: sql, source: :sync_exec) do
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def exec(*args)
|
19
|
+
Recorder.record(sql: args[0], source: :exec) do
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def query(*args)
|
25
|
+
Recorder.record(sql: args[0], source: :query) do
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def exec_params(*args)
|
31
|
+
Recorder.record(sql: args[0], binds: args[1], source: :exec_params) do
|
32
|
+
super
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# def async_exec_params(*args)
|
37
|
+
# puts ">>> #{args[0]}"
|
38
|
+
# super
|
39
|
+
# end
|
40
|
+
|
41
|
+
# def sync_exec_params(*args)
|
42
|
+
# puts ">>> #{args[0]}"
|
43
|
+
# super
|
44
|
+
# end
|
45
|
+
|
46
|
+
def exec_prepared(*args)
|
47
|
+
Recorder.record(sql: args[0], binds: args[1], source: :exec_prepared) do
|
48
|
+
super
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -3,81 +3,37 @@
|
|
3
3
|
module DatabaseRecorder
|
4
4
|
module PG
|
5
5
|
module Recorder
|
6
|
-
|
7
|
-
PG.record(sql: sql, source: :async_exec) do
|
8
|
-
super
|
9
|
-
end
|
10
|
-
end
|
6
|
+
module_function
|
11
7
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
15
|
-
|
8
|
+
def ignore_query?(sql)
|
9
|
+
!Recording.started? ||
|
10
|
+
sql.downcase.match?(/\A(begin|commit|release|rollback|savepoint)/i) ||
|
11
|
+
sql.match?(/ pg_attribute |SHOW max_identifier_length|SHOW search_path/)
|
16
12
|
end
|
17
13
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
14
|
+
def record(sql:, binds: nil, source: nil)
|
15
|
+
return yield if ignore_query?(sql)
|
16
|
+
|
17
|
+
Core.log_query(sql, source)
|
18
|
+
if Config.replay_recordings && !Recording.cache.nil?
|
19
|
+
Recording.push(sql: sql, binds: binds)
|
20
|
+
data = Recording.cached_query_for(sql)
|
21
|
+
return yield unless data # cache miss
|
22
|
+
|
23
|
+
RecordedResult.new(data['result'].slice('count', 'fields', 'values'))
|
24
|
+
else
|
25
|
+
yield.tap do |result|
|
26
|
+
result_data = result ? { 'count' => result.count, 'fields' => result.fields, 'values' => result.values } : nil
|
27
|
+
Recording.push(sql: sql, binds: binds, result: result_data)
|
28
|
+
end
|
31
29
|
end
|
32
30
|
end
|
33
31
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
# end
|
38
|
-
|
39
|
-
# def sync_exec_params(*args)
|
40
|
-
# puts ">>> #{args[0]}"
|
41
|
-
# super
|
42
|
-
# end
|
43
|
-
|
44
|
-
def exec_prepared(*args)
|
45
|
-
PG.record(sql: args[0], binds: args[1], source: :exec_prepared) do
|
46
|
-
super
|
32
|
+
def setup
|
33
|
+
::PG::Connection.class_eval do
|
34
|
+
prepend ConnectionExt
|
47
35
|
end
|
48
36
|
end
|
49
37
|
end
|
50
|
-
|
51
|
-
module_function
|
52
|
-
|
53
|
-
def ignore_query?(sql)
|
54
|
-
!Recording.started? ||
|
55
|
-
sql.downcase.match?(/\A(begin|commit|release|rollback|savepoint)/i) ||
|
56
|
-
sql.match?(/ pg_attribute |SHOW max_identifier_length|SHOW search_path/)
|
57
|
-
end
|
58
|
-
|
59
|
-
def record(sql:, binds: nil, source: nil)
|
60
|
-
return yield if ignore_query?(sql)
|
61
|
-
|
62
|
-
Core.log_query(sql, source)
|
63
|
-
if Config.replay_recordings && !Recording.cache.nil?
|
64
|
-
Recording.push(sql: sql, binds: binds)
|
65
|
-
data = Recording.cached_query_for(sql)
|
66
|
-
return yield unless data # cache miss
|
67
|
-
|
68
|
-
RecordedResult.new(data['result'].slice('count', 'fields', 'values'))
|
69
|
-
else
|
70
|
-
yield.tap do |result|
|
71
|
-
result_data = result ? { 'count' => result.count, 'fields' => result.fields, 'values' => result.values } : nil
|
72
|
-
Recording.push(sql: sql, binds: binds, result: result_data)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def setup
|
78
|
-
::PG::Connection.class_eval do
|
79
|
-
prepend Recorder
|
80
|
-
end
|
81
|
-
end
|
82
38
|
end
|
83
39
|
end
|
@@ -20,7 +20,7 @@ module DatabaseRecorder
|
|
20
20
|
current = @search_index
|
21
21
|
match = cache[@search_index..].find do |item|
|
22
22
|
current += 1
|
23
|
-
item['sql'] == sql
|
23
|
+
item['sql'] == sql
|
24
24
|
end
|
25
25
|
return unless match
|
26
26
|
|
@@ -55,10 +55,15 @@ module DatabaseRecorder
|
|
55
55
|
result
|
56
56
|
end
|
57
57
|
|
58
|
+
def update_last(*args)
|
59
|
+
@queries.last['binds'] = args
|
60
|
+
end
|
61
|
+
|
58
62
|
class << self
|
59
63
|
extend Forwardable
|
60
64
|
|
61
|
-
def_delegators :current_instance, :cache, :cached_query_for, :from_cache, :new_entity, :pull_entity, :push
|
65
|
+
def_delegators :current_instance, :cache, :cached_query_for, :from_cache, :new_entity, :pull_entity, :push,
|
66
|
+
:queries, :update_last
|
62
67
|
|
63
68
|
def current_instance
|
64
69
|
(@@instances ||= {})[Process.pid]
|
@@ -14,8 +14,7 @@ module DatabaseRecorder
|
|
14
14
|
ref = (example.metadata[:scoped_id] || '').split(':')[-1]
|
15
15
|
options = {}
|
16
16
|
options.merge!(example.metadata[:dbr]) if example.metadata[:dbr].is_a?(Hash)
|
17
|
-
options.merge!(example: example)
|
18
|
-
options.merge!(name: "#{example.full_description}__#{ref}") # TODO: if name is already set, append ref
|
17
|
+
options.merge!(example: example, name: "#{example.full_description}__#{ref}")
|
19
18
|
Recording.new(options: options).tap do |recording|
|
20
19
|
result = recording.start { example.run }
|
21
20
|
if options[:verify_queries] && result[:stored_queries]
|
@@ -2,16 +2,11 @@
|
|
2
2
|
|
3
3
|
module DatabaseRecorder
|
4
4
|
module Storage
|
5
|
-
class File
|
6
|
-
def initialize(recording, name:)
|
7
|
-
@recording = recording
|
8
|
-
@name = name
|
9
|
-
end
|
10
|
-
|
5
|
+
class File < Base
|
11
6
|
def load
|
12
7
|
stored_data = ::File.exist?(record_file) ? ::File.read(record_file) : false
|
13
8
|
if stored_data
|
14
|
-
data = YAML.load(stored_data)
|
9
|
+
data = YAML.load(stored_data) # rubocop:disable Security/YAMLLoad
|
15
10
|
@recording.cache = data['queries']
|
16
11
|
@recording.entities = data['entities']
|
17
12
|
true
|
data/lib/database_recorder.rb
CHANGED
@@ -3,22 +3,22 @@
|
|
3
3
|
require_relative 'database_recorder/core'
|
4
4
|
|
5
5
|
if defined? ::ActiveRecord
|
6
|
-
require_relative 'database_recorder/
|
7
|
-
require_relative 'database_recorder/
|
8
|
-
require_relative 'database_recorder/
|
9
|
-
require_relative 'database_recorder/
|
6
|
+
require_relative 'database_recorder/active_record/abstract_adapter_ext'
|
7
|
+
require_relative 'database_recorder/active_record/base_ext'
|
8
|
+
require_relative 'database_recorder/active_record/recorded_result'
|
9
|
+
require_relative 'database_recorder/active_record/recorder'
|
10
10
|
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
require_relative 'database_recorder/mysql2/client_ext'
|
13
|
+
require_relative 'database_recorder/mysql2/recorded_result'
|
14
|
+
require_relative 'database_recorder/mysql2/recorder'
|
15
|
+
require_relative 'database_recorder/mysql2/statement_ext'
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
17
|
+
require_relative 'database_recorder/pg/connection_ext'
|
18
|
+
require_relative 'database_recorder/pg/recorded_result'
|
19
|
+
require_relative 'database_recorder/pg/recorder'
|
21
20
|
|
21
|
+
require_relative 'database_recorder/storage/base'
|
22
22
|
require_relative 'database_recorder/storage/file'
|
23
23
|
require_relative 'database_recorder/storage/redis'
|
24
24
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: database_recorder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mattia Roccoberton
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-04-
|
11
|
+
date: 2022-04-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: coderay
|
@@ -35,18 +35,22 @@ files:
|
|
35
35
|
- MIT-LICENSE
|
36
36
|
- README.md
|
37
37
|
- lib/database_recorder.rb
|
38
|
-
- lib/database_recorder/
|
39
|
-
- lib/database_recorder/
|
40
|
-
- lib/database_recorder/
|
41
|
-
- lib/database_recorder/
|
38
|
+
- lib/database_recorder/active_record/abstract_adapter_ext.rb
|
39
|
+
- lib/database_recorder/active_record/base_ext.rb
|
40
|
+
- lib/database_recorder/active_record/recorded_result.rb
|
41
|
+
- lib/database_recorder/active_record/recorder.rb
|
42
42
|
- lib/database_recorder/config.rb
|
43
43
|
- lib/database_recorder/core.rb
|
44
|
+
- lib/database_recorder/mysql2/client_ext.rb
|
44
45
|
- lib/database_recorder/mysql2/recorded_result.rb
|
45
46
|
- lib/database_recorder/mysql2/recorder.rb
|
47
|
+
- lib/database_recorder/mysql2/statement_ext.rb
|
48
|
+
- lib/database_recorder/pg/connection_ext.rb
|
46
49
|
- lib/database_recorder/pg/recorded_result.rb
|
47
50
|
- lib/database_recorder/pg/recorder.rb
|
48
51
|
- lib/database_recorder/recording.rb
|
49
52
|
- lib/database_recorder/rspec.rb
|
53
|
+
- lib/database_recorder/storage/base.rb
|
50
54
|
- lib/database_recorder/storage/file.rb
|
51
55
|
- lib/database_recorder/storage/redis.rb
|
52
56
|
- lib/database_recorder/version.rb
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module DatabaseRecorder
|
4
|
-
module ActiveRecord
|
5
|
-
module Recorder
|
6
|
-
module_function
|
7
|
-
|
8
|
-
def setup
|
9
|
-
::ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
|
10
|
-
prepend AbstractAdapterExt
|
11
|
-
end
|
12
|
-
|
13
|
-
# ::ActiveRecord::Base.class_eval do
|
14
|
-
# prepend BaseExt
|
15
|
-
# end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|