rack-mini-profiler 4.0.0 → 5.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fb35c9ff911dd9dcc3fc5cccf15d62f21f0c04ed79ff5dec3e88746fcb90a43f
4
- data.tar.gz: a8cd39cdb11b4bb2ed154e9c3269de66b6f9c351c8cdcdb775e73e0c25e5d5a2
3
+ metadata.gz: 1749ebee33645ba891e149b102076cdde85f4284f4153ebbf8d26f5950aeea43
4
+ data.tar.gz: 76dfaba4c53defec6ea3d9ed7e366cf5bed55e50ae1b5f675e7a0d86d36f689a
5
5
  SHA512:
6
- metadata.gz: 1c1123a2fc22b5f20ea63fa089b4914f214a6da3d88dbba2fe1b3f597c92c653a166dc1c97d8a68e51a71893b9787ca11b99db1a68aa19da04cad494d8f33af9
7
- data.tar.gz: b21baa7055d5252cf3f57031be17e67810d898e4b40428d12409027454bfa15b414e2346f07e49d09b139945eb177f8951a34f41c765773ac543c49c2f0efd81
6
+ metadata.gz: 39b09627883a19db3a7c56c7355b7184ae68511150aef5ac35f4038c7e82206166221124cc8e07f1e007ace6e71bef4bcd3dbbdb0b653bfb34bceae0611df531
7
+ data.tar.gz: a0636582e639483770aabe8e72b3f10e08d500c8e927df6cab12eb8f737e66d09be8678002938563c36b235807069ed7338721a3b2751ab80b468b61a0a07b0d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 5.0.0 - 2026-08-21
4
+
5
+ - [BREAKING CHANGE] Require Ruby 3.2.0 or later. [#658](https://github.com/MiniProfiler/rack-mini-profiler/pull/658)
6
+ - [FEATURE] Record bind parameters for parameterized and prepared PostgreSQL queries. [#405](https://github.com/MiniProfiler/rack-mini-profiler/issues/405)
7
+ - [FIX] Add CSP nonce support to flamegraph rendering. [#648](https://github.com/MiniProfiler/rack-mini-profiler/pull/648)
8
+ - [FIX] Support simple Active Record bind parameters. [#657](https://github.com/MiniProfiler/rack-mini-profiler/pull/657)
9
+ - [FIX] Prevent asset requests from clearing profiler authorization. [#641](https://github.com/MiniProfiler/rack-mini-profiler/pull/641)
10
+ - [FIX] Preserve the full `Cache-Control` header when `disable_caching` is false. [#620](https://github.com/MiniProfiler/rack-mini-profiler/pull/620)
11
+ - [FIX] Show the profiler badge after Turbo Drive page loads. [#631](https://github.com/MiniProfiler/rack-mini-profiler/pull/631)
12
+ - [FIX] Disable advanced debugging tools by default in Rails development environments. [#645](https://github.com/MiniProfiler/rack-mini-profiler/pull/645)
13
+ - [FIX] Prevent unhandled promise rejections when profiled fetch requests fail. [#490](https://github.com/MiniProfiler/rack-mini-profiler/issues/490)
14
+
15
+ ## 4.0.1 - 2025-07-31
16
+
17
+ - [FIX] Ensure Rack 2 / 3 cross compatibility [#653](https://github.com/MiniProfiler/rack-mini-profiler/pull/653)
3
18
  ## 4.0 - 2025-06-11
4
19
 
5
20
  - [BREAKING CHANGE] Ruby version 3.1.0 or later is required. [#632](https://github.com/MiniProfiler/rack-mini-profiler/pull/632)
@@ -13,6 +28,7 @@
13
28
  - [FIX] `flamegraph_mode` query param having no effect. [#635](https://github.com/MiniProfiler/rack-mini-profiler/pull/635)
14
29
  - [FIX] max_traces_to_show had chance to break the profiler frontend [#297](https://github.com/MiniProfiler/rack-mini-profiler/issues/297)
15
30
 
31
+
16
32
  ## 3.3.1 - 2024-02-15
17
33
  - [FEATURE] Support dynamic `config.content_security_policy_nonce` [#609](https://github.com/MiniProfiler/rack-mini-profiler/pull/609)
18
34
  - [FEATURE] Add flamgraph path to response header: [#601](https://github.com/MiniProfiler/rack-mini-profiler/pull/601)
data/README.md CHANGED
@@ -29,7 +29,7 @@ If you feel like taking on any of this start an issue and update us on your prog
29
29
 
30
30
  ## Installation
31
31
 
32
- Install/add to Gemfile in Ruby 2.6+
32
+ Install/add to Gemfile in Ruby 3.2+
33
33
 
34
34
  ```ruby
35
35
  gem 'rack-mini-profiler'
data/lib/html/includes.js CHANGED
@@ -11,6 +11,8 @@ var _MiniProfiler = (function() {
11
11
  // so we never pull down a profiler twice
12
12
  ajaxStartTime,
13
13
  totalsControl,
14
+ lastTurboRequestUrl,
15
+ lastTurboProfilingResult,
14
16
  reqs = 0,
15
17
  expandedResults = false,
16
18
  totalTime = 0,
@@ -153,6 +155,8 @@ var _MiniProfiler = (function() {
153
155
  fetchedIds.push(id);
154
156
 
155
157
  if (json != "hidden" && MiniProfiler.templates) {
158
+ if (options.hotwireTurboDriveSupport) lastTurboProfilingResult = json;
159
+
156
160
  buttonShow(json);
157
161
  }
158
162
  }
@@ -172,6 +176,50 @@ var _MiniProfiler = (function() {
172
176
  }
173
177
  };
174
178
 
179
+ var fetchResultsFromAsyncResponse = function fetchResultsFromAsyncResponse(response) {
180
+ try {
181
+ // look for x-mini-profile-ids
182
+ var entries = response.headers.entries();
183
+ var _iteratorNormalCompletion = true;
184
+ var _didIteratorError = false;
185
+ var _iteratorError = undefined;
186
+
187
+ try {
188
+ for (
189
+ var _iterator = entries[Symbol.iterator](), _step;
190
+ !(_iteratorNormalCompletion = (_step = _iterator.next())
191
+ .done);
192
+ _iteratorNormalCompletion = true
193
+ ) {
194
+ var pair = _step.value;
195
+
196
+ if (
197
+ pair[0] &&
198
+ pair[0].toLowerCase() == "x-miniprofiler-ids"
199
+ ) {
200
+ var ids = pair[1].split(",");
201
+ fetchResults(ids);
202
+ }
203
+ }
204
+ } catch (err) {
205
+ _didIteratorError = true;
206
+ _iteratorError = err;
207
+ } finally {
208
+ try {
209
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
210
+ _iterator.return();
211
+ }
212
+ } finally {
213
+ if (_didIteratorError) {
214
+ throw _iteratorError;
215
+ }
216
+ }
217
+ }
218
+ } catch (e) {
219
+ console.error(e);
220
+ }
221
+ }
222
+
175
223
  var toQueryString = function toQueryString(data, parentKey) {
176
224
  var result = [];
177
225
  for (var key in data) {
@@ -496,10 +544,30 @@ var _MiniProfiler = (function() {
496
544
  }, 3000);
497
545
  };
498
546
 
547
+ var onTurboBeforeFetchResponse = function onTurboBeforeFetchResponse(e) {
548
+ lastTurboRequestUrl = e.detail.fetchResponse.response.url;
549
+
550
+ var response = e.detail.fetchResponse.response;
551
+ fetchResultsFromAsyncResponse(response);
552
+ }
553
+
499
554
  var onTurboBeforeVisit = function onTurboBeforeVisit(e) {
500
555
  if(!e.defaultPrevented) {
501
556
  window.MiniProfilerContainer = document.querySelector('body > .profiler-results')
502
557
  window.MiniProfiler.pageTransition()
558
+
559
+ var visitingUrl = e.detail.url
560
+
561
+ // To preserve the last prefetched profiling result so badge doesn't disappear when Turbo replaces page HTML
562
+ if (
563
+ visitingUrl === lastTurboRequestUrl &&
564
+ visitingUrl !== Turbo.session.view.lastRenderedLocation.href &&
565
+ lastTurboProfilingResult
566
+ ) {
567
+ buttonShow(lastTurboProfilingResult);
568
+ lastTurboProfilingResult = null;
569
+ lastTurboRequestUrl = null;
570
+ }
503
571
  }
504
572
  }
505
573
 
@@ -670,6 +738,7 @@ var _MiniProfiler = (function() {
670
738
  if (options.hotwireTurboDriveSupport) {
671
739
  document.addEventListener("turbo:before-visit", onTurboBeforeVisit)
672
740
  document.addEventListener("turbo:load", onTurboLoad)
741
+ document.addEventListener("turbo:before-fetch-response", onTurboBeforeFetchResponse);
673
742
  }
674
743
  };
675
744
 
@@ -685,6 +754,7 @@ var _MiniProfiler = (function() {
685
754
  );
686
755
  document.removeEventListener("turbo:before-visit", onTurboBeforeVisit);
687
756
  document.removeEventListener("turbo:load", onTurboLoad);
757
+ document.removeEventListener("turbo:before-fetch-response", onTurboBeforeFetchResponse);
688
758
  };
689
759
 
690
760
  var initFullView = function initFullView() {
@@ -963,48 +1033,9 @@ var _MiniProfiler = (function() {
963
1033
  var originalFetchRun = __originalFetch(input, init);
964
1034
 
965
1035
  originalFetchRun.then(function(response) {
966
- try {
967
- // look for x-mini-profile-ids
968
- var entries = response.headers.entries();
969
- var _iteratorNormalCompletion = true;
970
- var _didIteratorError = false;
971
- var _iteratorError = undefined;
972
-
973
- try {
974
- for (
975
- var _iterator = entries[Symbol.iterator](), _step;
976
- !(_iteratorNormalCompletion = (_step = _iterator.next())
977
- .done);
978
- _iteratorNormalCompletion = true
979
- ) {
980
- var pair = _step.value;
981
-
982
- if (
983
- pair[0] &&
984
- pair[0].toLowerCase() == "x-miniprofiler-ids"
985
- ) {
986
- var ids = pair[1].split(",");
987
- fetchResults(ids);
988
- }
989
- }
990
- } catch (err) {
991
- _didIteratorError = true;
992
- _iteratorError = err;
993
- } finally {
994
- try {
995
- if (!_iteratorNormalCompletion && _iterator.return != null) {
996
- _iterator.return();
997
- }
998
- } finally {
999
- if (_didIteratorError) {
1000
- throw _iteratorError;
1001
- }
1002
- }
1003
- }
1004
- } catch (e) {
1005
- console.error(e);
1006
- }
1007
- });
1036
+ fetchResultsFromAsyncResponse(response)
1037
+ }).catch(function() {});
1038
+
1008
1039
  return originalFetchRun;
1009
1040
  };
1010
1041
  }
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Rack
3
3
  class MiniProfiler
4
- ASSET_VERSION = 'e0bcc9ce0ae3bb5d6b736b6f282f601f'
4
+ ASSET_VERSION = '0ab236f63a9cce6719807f4cd6470f29'
5
5
  end
6
6
  end
@@ -39,13 +39,13 @@ module Rack
39
39
 
40
40
  end
41
41
 
42
- def handle_cookie(result)
42
+ def handle_cookie(result, preserve_cookie: false)
43
43
  status, headers, _body = result
44
44
 
45
45
  if (MiniProfiler.config.authorization_mode == :allow_authorized && !MiniProfiler.request_authorized?)
46
46
  # this is non-obvious, don't kill the profiling cookie on errors or short requests
47
47
  # this ensures that stuff that never reaches the rails stack does not kill profiling
48
- if status.to_i >= 200 && status.to_i < 300 && ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - @start) > 0.1)
48
+ if !preserve_cookie && status.to_i >= 200 && status.to_i < 300 && ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - @start) > 0.1)
49
49
  discard_cookie!(headers)
50
50
  end
51
51
  else
@@ -151,7 +151,7 @@ String stats:
151
151
  body << "#{count} : #{string}\n"
152
152
  end
153
153
 
154
- [200, { 'Content-Type' => 'text/plain' }, body]
154
+ [200, { Rack::CONTENT_TYPE => 'text/plain' }, body]
155
155
  ensure
156
156
  prev_gc_state ? GC.disable : GC.enable
157
157
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Rack
4
4
  class MiniProfiler
5
- VERSION = "4.0.0"
5
+ VERSION = "5.0.0"
6
6
  SOURCE_CODE_URI = "https://github.com/MiniProfiler/rack-mini-profiler"
7
7
  end
8
8
  end
@@ -10,6 +10,18 @@ module Rack
10
10
  @share_template ||= ERB.new(::File.read(::File.expand_path("../html/share.html", ::File.dirname(__FILE__))))
11
11
  end
12
12
 
13
+ def get_csp_nonce(env, response_headers = {})
14
+ configured_nonce = @config.content_security_policy_nonce
15
+ if configured_nonce && !configured_nonce.is_a?(String)
16
+ configured_nonce = configured_nonce.call(env, response_headers)
17
+ end
18
+
19
+ configured_nonce ||
20
+ env["action_dispatch.content_security_policy_nonce"] ||
21
+ env["secure_headers_content_security_policy_nonce"] ||
22
+ ""
23
+ end
24
+
13
25
  def generate_html(page_struct, env, result_json = page_struct.to_json)
14
26
  # double-assigning to suppress "assigned but unused variable" warnings
15
27
  path = path = "#{env['RACK_MINI_PROFILER_ORIGINAL_SCRIPT_NAME']}#{@config.base_url_path}"
@@ -39,15 +51,6 @@ module Rack
39
51
  url = "#{path}includes.js?v=#{version}" if !url
40
52
  css_url = "#{path}includes.css?v=#{version}" if !css_url
41
53
 
42
- configured_nonce = @config.content_security_policy_nonce
43
- if configured_nonce && !configured_nonce.is_a?(String)
44
- configured_nonce = configured_nonce.call(env, response_headers)
45
- end
46
-
47
- content_security_policy_nonce = configured_nonce ||
48
- env["action_dispatch.content_security_policy_nonce"] ||
49
- env["secure_headers_content_security_policy_nonce"]
50
-
51
54
  settings = {
52
55
  path: path,
53
56
  url: url,
@@ -66,7 +69,7 @@ module Rack
66
69
  collapseResults: @config.collapse_results,
67
70
  htmlContainer: @config.html_container,
68
71
  hiddenCustomFields: @config.snapshot_hidden_custom_fields.join(','),
69
- cspNonce: content_security_policy_nonce,
72
+ cspNonce: get_csp_nonce(env, response_headers),
70
73
  hotwireTurboDriveSupport: @config.enable_hotwire_turbo_drive_support,
71
74
  }
72
75
 
@@ -112,6 +115,8 @@ module Rack
112
115
  def flamegraph(graph, path, env)
113
116
  headers = { 'content-type' => 'text/html' }
114
117
  iframe_src = "#{public_base_path(env)}speedscope/index.html"
118
+ csp_nonce = get_csp_nonce(env, headers)
119
+
115
120
  html = <<~HTML
116
121
  <!DOCTYPE html>
117
122
  <html>
@@ -123,7 +128,7 @@ module Rack
123
128
  </style>
124
129
  </head>
125
130
  <body>
126
- <script type="text/javascript">
131
+ <script type="text/javascript" nonce="#{csp_nonce}">
127
132
  var graph = #{JSON.generate(graph)};
128
133
  var json = JSON.stringify(graph);
129
134
  var blob = new Blob([json], { type: 'text/plain' });
data/lib/mini_profiler.rb CHANGED
@@ -96,8 +96,15 @@ module Rack
96
96
 
97
97
  def binds_to_params(binds)
98
98
  return if binds.nil? || config.max_sql_param_length == 0
99
- # map ActiveRecord::Relation::QueryAttribute to [name, value]
100
- params = binds.map { |c| c.kind_of?(Array) ? [c.first, c.last] : [c.name, c.value] }
99
+ params = binds.map do |c|
100
+ if c.kind_of?(Array)
101
+ [c.first, c.last]
102
+ elsif c.respond_to?(:name) && c.respond_to?(:value) # ActiveRecord::Relation::QueryAttribute
103
+ [c.name, c.value]
104
+ else # Time, String, Integer
105
+ ["param", c]
106
+ end
107
+ end
101
108
  if (skip = config.skip_sql_param_names)
102
109
  params.map { |(n, v)| n =~ skip ? [n, nil] : [n, v] }
103
110
  else
@@ -176,7 +183,8 @@ module Rack
176
183
  end
177
184
  )
178
185
  if skip_it
179
- return client_settings.handle_cookie(@app.call(env))
186
+ # preserve_cookie to ensure we don't deauthorize the request (delete the auth cookie) when loading assets
187
+ return client_settings.handle_cookie(@app.call(env), preserve_cookie: true)
180
188
  end
181
189
 
182
190
  skip_it = (@config.pre_authorize_cb && !@config.pre_authorize_cb.call(env))
@@ -329,7 +337,7 @@ module Rack
329
337
  )
330
338
  end
331
339
  elsif path == '/rack-mini-profiler/requests'
332
- status, headers, body = [200, { 'Content-Type' => 'text/html' }, [blank_page_html.dup]] # important to dup here!
340
+ status, headers, body = [200, { Rack::CONTENT_TYPE => 'text/html' }, [blank_page_html.dup]] # important to dup here!
333
341
  else
334
342
  status, headers, body = @app.call(env)
335
343
  end
@@ -423,20 +431,20 @@ module Rack
423
431
  def inject_profiler(env, status, headers, body)
424
432
  # mini profiler is meddling with stuff, we can not cache cause we will get incorrect data
425
433
  # Rack::ETag has already inserted some nonesense in the chain
426
- content_type = headers['Content-Type']
434
+ content_type = headers[Rack::CONTENT_TYPE]
435
+
436
+ headers['x-miniprofiler-original-cache-control'] = headers[Rack::CACHE_CONTROL] unless headers[Rack::CACHE_CONTROL].nil?
427
437
 
428
438
  if config.disable_caching
429
- headers.delete('ETag')
430
- headers.delete('Date')
439
+ headers.delete(Rack::ETAG)
440
+ headers.delete('date') || headers.delete('Date')
441
+ headers[Rack::CACHE_CONTROL] = "no-store, must-revalidate, private, max-age=0"
431
442
  end
432
443
 
433
- headers['X-MiniProfiler-Original-Cache-Control'] = headers['Cache-Control'] unless headers['Cache-Control'].nil?
434
- headers['Cache-Control'] = "#{"no-store, " if config.disable_caching}must-revalidate, private, max-age=0"
435
-
436
444
  # inject header
437
445
  if headers.is_a? Hash
438
- headers['X-MiniProfiler-Ids'] = ids_comma_separated(env)
439
- headers['X-MiniProfiler-Flamegraph-Path'] = flamegraph_path(env) if current.page_struct[:has_flamegraph]
446
+ headers['x-miniprofiler-ids'] = ids_comma_separated(env)
447
+ headers['x-miniprofiler-flamegraph-path'] = flamegraph_path(env) if current.page_struct[:has_flamegraph]
440
448
  end
441
449
 
442
450
  if current.inject_js && content_type =~ /text\/html/
@@ -589,7 +597,7 @@ module Rack
589
597
  end
590
598
 
591
599
  def text_result(body, status: 200, headers: nil)
592
- headers = (headers || {}).merge('Content-Type' => 'text/plain; charset=utf-8')
600
+ headers = (headers || {}).merge(Rack::CONTENT_TYPE => 'text/plain; charset=utf-8')
593
601
  [status, headers, [body]]
594
602
  end
595
603
 
@@ -34,7 +34,7 @@ module Rack::MiniProfilerRails
34
34
  c.skip_paths << wp_assets_path if wp_assets_path
35
35
  end
36
36
 
37
- unless Rails.env.development? || Rails.env.test?
37
+ unless Rails.env.local?
38
38
  c.authorization_mode = :allow_authorized
39
39
  end
40
40
 
@@ -55,11 +55,10 @@ module Rack::MiniProfilerRails
55
55
  # Quiet the SQL stack traces
56
56
  c.backtrace_remove = Rails.root.to_s + "/"
57
57
  c.backtrace_includes = [/^\/?(app|config|lib|test)/]
58
- c.skip_schema_queries = (Rails.env.development? || Rails.env.test?)
58
+ c.skip_schema_queries = Rails.env.local?
59
59
 
60
60
  # Install the Middleware
61
61
  app.middleware.insert(0, Rack::MiniProfiler)
62
- c.enable_advanced_debugging_tools = Rails.env.development?
63
62
 
64
63
  if ::Rack::MiniProfiler.patch_rails?
65
64
  # Attach to various Rails methods
@@ -166,7 +165,9 @@ module Rack::MiniProfilerRails
166
165
  return false
167
166
  end
168
167
 
169
- if ::Rails.version >= "5.0.0"
168
+ if ::Rails.version >= "5.1.0"
169
+ ::Rails.configuration.public_file_server.enabled || ::Rails.configuration.assets.unknown_asset_fallback
170
+ elsif ::Rails.version >= "5.0.0"
170
171
  ::Rails.configuration.public_file_server.enabled
171
172
  elsif ::Rails.version >= "4.2.0"
172
173
  ::Rails.configuration.serve_static_files
@@ -15,12 +15,12 @@ module Rack
15
15
  end
16
16
  end
17
17
 
18
- def log_with_miniprofiler(*args, &block)
19
- return log_without_miniprofiler(*args, &block) unless SqlPatches.should_measure?
18
+ def log_with_miniprofiler(*args, **kwargs, &block)
19
+ return log_without_miniprofiler(*args, **kwargs, &block) unless SqlPatches.should_measure?
20
20
 
21
21
  sql, name, binds = args
22
22
  start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
23
- rval = log_without_miniprofiler(*args, &block)
23
+ rval = log_without_miniprofiler(*args, **kwargs, &block)
24
24
 
25
25
  # Don't log schema queries if the option is set
26
26
  return rval if Rack::MiniProfiler.config.skip_schema_queries && name =~ (/SCHEMA/)
@@ -57,7 +57,9 @@ class PG::Connection
57
57
  start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
58
58
  result = exec_without_profiling(*args, &blk)
59
59
  elapsed_time = SqlPatches.elapsed_time(start)
60
- record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time)
60
+ record = ::Rack::MiniProfiler.record_sql(
61
+ args[0], elapsed_time, ::Rack::MiniProfiler.binds_to_params(args[1])
62
+ )
61
63
  result.instance_variable_set("@miniprofiler_sql_id", record) if result
62
64
 
63
65
  result
@@ -70,7 +72,9 @@ class PG::Connection
70
72
  start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
71
73
  result = exec_params_without_profiling(*args, &blk)
72
74
  elapsed_time = SqlPatches.elapsed_time(start)
73
- record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time)
75
+ record = ::Rack::MiniProfiler.record_sql(
76
+ args[0], elapsed_time, ::Rack::MiniProfiler.binds_to_params(args[1])
77
+ )
74
78
  result.instance_variable_set("@miniprofiler_sql_id", record) if result
75
79
 
76
80
  result
@@ -85,7 +89,9 @@ class PG::Connection
85
89
  elapsed_time = SqlPatches.elapsed_time(start)
86
90
  mapped = args[0]
87
91
  mapped = @prepare_map[mapped] || args[0] if @prepare_map
88
- record = ::Rack::MiniProfiler.record_sql(mapped, elapsed_time)
92
+ record = ::Rack::MiniProfiler.record_sql(
93
+ mapped, elapsed_time, ::Rack::MiniProfiler.binds_to_params(args[1])
94
+ )
89
95
  result.instance_variable_set("@miniprofiler_sql_id", record) if result
90
96
 
91
97
  result
@@ -99,7 +105,9 @@ class PG::Connection
99
105
  elapsed_time = SqlPatches.elapsed_time(start)
100
106
  mapped = args[0]
101
107
  mapped = @prepare_map[mapped] || args[0] if @prepare_map
102
- record = ::Rack::MiniProfiler.record_sql(mapped, elapsed_time)
108
+ record = ::Rack::MiniProfiler.record_sql(
109
+ mapped, elapsed_time, ::Rack::MiniProfiler.binds_to_params(args[1])
110
+ )
103
111
  result.instance_variable_set("@miniprofiler_sql_id", record) if result
104
112
 
105
113
  result
@@ -111,7 +119,9 @@ class PG::Connection
111
119
  start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
112
120
  result = exec_without_profiling(*args, &blk)
113
121
  elapsed_time = SqlPatches.elapsed_time(start)
114
- record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time)
122
+ record = ::Rack::MiniProfiler.record_sql(
123
+ args[0], elapsed_time, ::Rack::MiniProfiler.binds_to_params(args[1])
124
+ )
115
125
  result.instance_variable_set("@miniprofiler_sql_id", record) if result
116
126
 
117
127
  result
@@ -49,7 +49,9 @@ class PG::Connection
49
49
  start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
50
50
  result = super
51
51
  elapsed_time = SqlPatches.elapsed_time(start)
52
- record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time)
52
+ record = ::Rack::MiniProfiler.record_sql(
53
+ args[0], elapsed_time, ::Rack::MiniProfiler.binds_to_params(args[1])
54
+ )
53
55
  result.instance_variable_set("@miniprofiler_sql_id", record) if result
54
56
 
55
57
  result
@@ -62,7 +64,9 @@ class PG::Connection
62
64
  start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
63
65
  result = super
64
66
  elapsed_time = SqlPatches.elapsed_time(start)
65
- record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time)
67
+ record = ::Rack::MiniProfiler.record_sql(
68
+ args[0], elapsed_time, ::Rack::MiniProfiler.binds_to_params(args[1])
69
+ )
66
70
  result.instance_variable_set("@miniprofiler_sql_id", record) if result
67
71
 
68
72
  result
@@ -77,7 +81,9 @@ class PG::Connection
77
81
  elapsed_time = SqlPatches.elapsed_time(start)
78
82
  mapped = args[0]
79
83
  mapped = @prepare_map[mapped] || args[0] if @prepare_map
80
- record = ::Rack::MiniProfiler.record_sql(mapped, elapsed_time)
84
+ record = ::Rack::MiniProfiler.record_sql(
85
+ mapped, elapsed_time, ::Rack::MiniProfiler.binds_to_params(args[1])
86
+ )
81
87
  result.instance_variable_set("@miniprofiler_sql_id", record) if result
82
88
 
83
89
  result
@@ -91,7 +97,9 @@ class PG::Connection
91
97
  elapsed_time = SqlPatches.elapsed_time(start)
92
98
  mapped = args[0]
93
99
  mapped = @prepare_map[mapped] || args[0] if @prepare_map
94
- record = ::Rack::MiniProfiler.record_sql(mapped, elapsed_time)
100
+ record = ::Rack::MiniProfiler.record_sql(
101
+ mapped, elapsed_time, ::Rack::MiniProfiler.binds_to_params(args[1])
102
+ )
95
103
  result.instance_variable_set("@miniprofiler_sql_id", record) if result
96
104
 
97
105
  result
@@ -103,7 +111,9 @@ class PG::Connection
103
111
  start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
104
112
  result = super
105
113
  elapsed_time = SqlPatches.elapsed_time(start)
106
- record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time)
114
+ record = ::Rack::MiniProfiler.record_sql(
115
+ args[0], elapsed_time, ::Rack::MiniProfiler.binds_to_params(args[1])
116
+ )
107
117
  result.instance_variable_set("@miniprofiler_sql_id", record) if result
108
118
 
109
119
  result
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
21
21
  "CHANGELOG.md"
22
22
  ]
23
23
  s.add_runtime_dependency 'rack', '>= 1.2.0'
24
- s.required_ruby_version = '>= 3.1.0'
24
+ s.required_ruby_version = '>= 3.2.0'
25
25
 
26
26
  s.metadata = {
27
27
  'source_code_uri' => Rack::MiniProfiler::SOURCE_CODE_URI,
@@ -42,6 +42,7 @@ Gem::Specification.new do |s|
42
42
  s.add_development_dependency 'listen'
43
43
  s.add_development_dependency 'webpacker'
44
44
  s.add_development_dependency 'rails', '>= 7.1'
45
+ s.add_development_dependency 'sqlite3'
45
46
  s.add_development_dependency 'webmock', '3.9.1'
46
47
  s.add_development_dependency 'rubyzip'
47
48
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-mini-profiler
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
@@ -9,7 +9,7 @@ authors:
9
9
  - Aleks Totic
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-06-10 00:00:00.000000000 Z
12
+ date: 1980-01-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -221,6 +221,20 @@ dependencies:
221
221
  - - ">="
222
222
  - !ruby/object:Gem::Version
223
223
  version: '7.1'
224
+ - !ruby/object:Gem::Dependency
225
+ name: sqlite3
226
+ requirement: !ruby/object:Gem::Requirement
227
+ requirements:
228
+ - - ">="
229
+ - !ruby/object:Gem::Version
230
+ version: '0'
231
+ type: :development
232
+ prerelease: false
233
+ version_requirements: !ruby/object:Gem::Requirement
234
+ requirements:
235
+ - - ">="
236
+ - !ruby/object:Gem::Version
237
+ version: '0'
224
238
  - !ruby/object:Gem::Dependency
225
239
  name: webmock
226
240
  requirement: !ruby/object:Gem::Requirement
@@ -255,8 +269,8 @@ email: sam.saffron@gmail.com
255
269
  executables: []
256
270
  extensions: []
257
271
  extra_rdoc_files:
258
- - README.md
259
272
  - CHANGELOG.md
273
+ - README.md
260
274
  files:
261
275
  - CHANGELOG.md
262
276
  - README.md
@@ -354,14 +368,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
354
368
  requirements:
355
369
  - - ">="
356
370
  - !ruby/object:Gem::Version
357
- version: 3.1.0
371
+ version: 3.2.0
358
372
  required_rubygems_version: !ruby/object:Gem::Requirement
359
373
  requirements:
360
374
  - - ">="
361
375
  - !ruby/object:Gem::Version
362
376
  version: '0'
363
377
  requirements: []
364
- rubygems_version: 3.6.3
378
+ rubygems_version: 3.6.9
365
379
  specification_version: 4
366
380
  summary: Profiles loading speed for rack applications.
367
381
  test_files: []