rails-pg-extras-web 1.4.1 → 2.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: abc008aaf05163eebc554ac1bb9eb7746f51fe83ff7557c4f924e5fc19b151ae
4
- data.tar.gz: 41a7833a4550b17c93a884a9abdd17b7304822db9dc85d560469469e8728791e
3
+ metadata.gz: 5699fd3b704d3c1b44dba980a4c7f744bceb7a8ac56e59c7cc013b8b68544871
4
+ data.tar.gz: 9d881723852e10a275e0e146a0a2586275b7830e0ef21a9f10e263d9523c5d25
5
5
  SHA512:
6
- metadata.gz: f0527a2d23300b0602a807e68fb2c058941051cac537f0828420a3cd8ac3a450df256c43dd52dba9e9556705015cd86833cea9e0c470866e3c9b5e5d60b51b05
7
- data.tar.gz: 6dcd0d8dc82528e9eaa3afd75caec3e9642c54bb7115410982914ea313b22e37fcadec35fa44884c1c987efbb98ba1470e989c55fbe8d9e06a1168644a8f7d7d
6
+ metadata.gz: 62c46bf2750fe4582b78454b610cf187735bccc48b39a33150d8445bb90c52e785e83d52f8d6ecb1fb01309eeb83c58eb2b1e2f1f2185e9364ed4dc132c05033
7
+ data.tar.gz: 49e2b3c3c17b16f4cad995d0ff79162699e51294aa0c93e6e2e71c31acb34a731a750b8fe05c4e3780f1d0cf39b18bd95a442c505bb9b2a16c2740d7e6ea35cc
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # RailsPgExtrasWeb
2
- Web UI for rails-pg-extras-web
2
+ Web UI for [rails-pg-extras](https://github.com/pawurb/rails-pg-extras)
3
3
 
4
4
  ## Installation
5
5
  Add this line to your application's Gemfile:
@@ -7,30 +7,5 @@ module RailsPgExtrasWeb
7
7
  if Rails.env.production? && ENV['PG_EXTRAS_USER'].present? && ENV['PG_EXTRAS_PASSWORD'].present?
8
8
  http_basic_authenticate_with name: ENV['PG_EXTRAS_USER'], password: ENV['PG_EXTRAS_PASSWORD']
9
9
  end
10
-
11
- protect_from_forgery with: :exception
12
-
13
- helper_method :pg_stats_statements_enabled?
14
-
15
- private
16
-
17
- def load_queries
18
- @all_queries = {}
19
-
20
- ::RailsPGExtras::QUERIES.each do |query_name|
21
- @all_queries[query_name] = {
22
- disabled: query_disabled?(query_name),
23
- command: query_name == :kill_all
24
- }
25
- end
26
- end
27
-
28
- def query_disabled?(query_name)
29
- query_name.in?([:calls, :outliers]) && !pg_stats_statements_enabled?
30
- end
31
-
32
- def pg_stats_statements_enabled?
33
- ActiveRecord::Base.connection.extensions.include?("pg_stat_statements")
34
- end
35
10
  end
36
11
  end
@@ -1,19 +1,49 @@
1
1
  module RailsPgExtrasWeb
2
2
  class QueriesController < ApplicationController
3
+ REQUIRED_EXTENSIONS = {
4
+ pg_stat_statements: %i[calls outliers],
5
+ pg_buffercache: %i[buffercache_stats buffercache_usage]
6
+ }
7
+
3
8
  before_action :load_queries
9
+ helper_method :unavailable_extensions
4
10
 
5
- def index; end
11
+ def index
12
+ if params[:query_name].present?
13
+ @query_name = params[:query_name].to_sym.presence_in(@all_queries.keys)
14
+ return unless @query_name
6
15
 
7
- def run
8
- if @query_name = params[:query_name].presence
9
16
  begin
10
17
  @result = RailsPGExtras.run_query(query_name: @query_name.to_sym, in_format: :raw)
11
18
  rescue ActiveRecord::StatementInvalid => e
12
19
  @error = e.message
13
20
  end
14
- else
15
- redirect_to root_path
21
+
22
+ render :show
16
23
  end
17
24
  end
25
+
26
+ private
27
+
28
+ def load_queries
29
+ @all_queries = RailsPGExtras::QUERIES.inject({}) do |memo, query_name|
30
+ unless query_name.in? %i[kill_all mandelbrot]
31
+ memo[query_name] = { disabled: query_disabled?(query_name) }
32
+ end
33
+
34
+ memo
35
+ end
36
+ end
37
+
38
+ def query_disabled?(query_name)
39
+ unavailable_extensions.values.flatten.include?(query_name)
40
+ end
41
+
42
+ def unavailable_extensions
43
+ return @unavailable_extensions if defined?(@unavailable_extensions)
44
+
45
+ enabled_extensions = ActiveRecord::Base.connection.extensions
46
+ @unavailable_extensions = REQUIRED_EXTENSIONS.delete_if { |ext| ext.to_s.in?(enabled_extensions) }
47
+ end
18
48
  end
19
49
  end
@@ -1,21 +1,10 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
- <title>PG::Extras</title>
5
- <%= csrf_meta_tags %>
6
- <%= csp_meta_tag %>
4
+ <title><%= content_for :title %></title>
5
+ <link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
7
6
  </head>
8
- <body onload="document.forms.queries.query_name.focus()">
9
- <%= form_with url: run_query_url, id: "queries" do |f| %>
10
- <%= f.select :query_name, options_for_select(@all_queries.except(:kill_all, :mandelbrot), params[:query_name]),
11
- prompt: "--- select query ---"
12
- %>
13
-
14
- <button type="submit">Run</button>
15
- <% end %>
16
-
17
- <div style='margin-top: 20px'>
18
- <%= yield %>
19
- </div>
7
+ <body class="p-5 text-xs">
8
+ <%= yield %>
20
9
  </body>
21
10
  </html>
@@ -0,0 +1,22 @@
1
+ <h1 class="font-bold text-xl my-5"><%= title %></h1>
2
+
3
+ <table class="w-full font-mono border-collapse border border-green-800 my-5">
4
+ <thead>
5
+ <tr class="bg-gray-300">
6
+ <% headers.each do |header| %>
7
+ <th class="p-2 border text-left"><%= header %></th>
8
+ <% end %>
9
+ </tr>
10
+ </thead>
11
+ <tbody>
12
+ <% rows.each.with_index do |row, i| %>
13
+ <tr class="hover:bg-gray-400 hover:text-white <%= i.even? ? "bg-gray-100" : "bg-gray-200" %>">
14
+ <% row.each do |column| %>
15
+ <td class="p-1 border"><%= column %></td>
16
+ <% end %>
17
+ </tr>
18
+ <% end %>
19
+ </tbody>
20
+ </table>
21
+
22
+ <span class="italic">run_at: <%= Time.now.utc %></span>
@@ -0,0 +1,48 @@
1
+ <div class="text-red-500 p-3 font-mono my-5">
2
+ <% unavailable_extensions.each do |extension, queries| %>
3
+ WARNING: Queries <%= queries.map { |q| "<b><u>#{q}</u></b>" }.join(", ").html_safe %> require extension: <b><%= extension %></b>
4
+ <br>
5
+ <% end %>
6
+ </div>
7
+
8
+
9
+ <span id="rails" class="font-mono font-bold p-3 bg-gray-100 cursor-pointer select-none">RAILS</span> <span id="sql" class="font-mono font-normal p-3 bg-gray-50 cursor-pointer select-none">SQL</span>
10
+ <pre id="rails_code" class="font-mono p-5 bg-gray-100 block">
11
+ <% unavailable_extensions.each do |extension, queries| %>
12
+ ActiveRecord::Base.connection.enable_extension "<%= extension %>"
13
+ <% end %>
14
+ </pre>
15
+
16
+ <pre id="sql_code" class="font-mono p-5 bg-gray-100 hidden">
17
+ <% unavailable_extensions.each do |extension, queries| %>
18
+ CREATE EXTENSION <%= extension %>;
19
+ <% end %>
20
+ </pre>
21
+
22
+ <script>
23
+ const rails = document.getElementById('rails')
24
+ const sql = document.getElementById('sql')
25
+ const railsCode = document.getElementById('rails_code')
26
+ const sqlCode = document.getElementById('sql_code')
27
+
28
+ rails.addEventListener('click', (e) => {
29
+ railsCode.classList.remove('hidden')
30
+ sqlCode.classList.add('hidden')
31
+
32
+ rails.classList.replace('bg-gray-50','bg-gray-100')
33
+ sql.classList.replace('bg-gray-100','bg-gray-50')
34
+ rails.classList.replace('font-normal','font-bold')
35
+ sql.classList.replace('font-bold','font-normal')
36
+ })
37
+
38
+ sql.addEventListener('click', (e) => {
39
+ railsCode.classList.add('hidden')
40
+ sqlCode.classList.remove('hidden')
41
+
42
+ rails.classList.replace('bg-gray-100','bg-gray-50')
43
+ sql.classList.replace('bg-gray-50','bg-gray-100')
44
+ rails.classList.replace('font-bold','font-normal')
45
+ sql.classList.replace('font-normal','font-bold')
46
+ })
47
+ </script>
48
+
@@ -1,10 +1,4 @@
1
- <% unless pg_stats_statements_enabled? %>
2
- <span style='color: red'>
3
- WARNING: <b><u>outliers</u></b>, <b><u>calls</u></b> require extension: <b>pg_stat_statements</b>
4
- </span>
1
+ <%= content_for :title, "pg_extras" %>
2
+ <%= render "rails_pg_extras_web/shared/queries_selector" %>
5
3
 
6
- <h4>Rails</h4>
7
- <pre style='background-color: #e2e2e2; padding: 10px'>ActiveRecord::Base.connection.enable_extension "pg_stat_statements"</pre>
8
- <h4>SQL</h4>
9
- <pre style='background-color: #e2e2e2; padding: 10px'>CREATE EXTENSION pg_stat_statements</pre>
10
- <% end %>
4
+ <%= render "unavailable_extensions_warning" if unavailable_extensions.any? %>
@@ -0,0 +1,24 @@
1
+ <%= content_for :title, params[:query_name].presence || "pg_extras" %>
2
+ <%= render "rails_pg_extras_web/shared/queries_selector" %>
3
+
4
+ <% if @error %>
5
+ <span class="text-red"><%= @error %></span>
6
+ <% else %>
7
+ <% if @result&.any? %>
8
+ <%= render "result",
9
+ title: RubyPGExtras.description_for(query_name: @query_name),
10
+ headers: @result[0].keys,
11
+ rows: @result.values
12
+ %>
13
+ <% else %>
14
+ <div class="font-mono p-3 bg-gray-100 mt-3">No results</div>
15
+ <% end %>
16
+ <% end %>
17
+
18
+ <style>
19
+ @media print {
20
+ form {
21
+ display: none
22
+ }
23
+ }
24
+ </style>
@@ -0,0 +1,11 @@
1
+ <%= form_with url: queries_path, id: "queries", method: :get do |f| %>
2
+ <%= f.select :query_name, options_for_select(@all_queries, params[:query_name]),
3
+ {prompt: "--- select query ---"},
4
+ {class: "border p-2 font-bold", autofocus: true}
5
+ %>
6
+ <% end %>
7
+ <script>
8
+ document.getElementById('queries').addEventListener('change', (e) => {
9
+ e.target.form.submit()
10
+ })
11
+ </script>
data/config/routes.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  RailsPgExtrasWeb::Engine.routes.draw do
2
- root to: "queries#index"
2
+ resources :queries, only: [:index]
3
3
 
4
- post "/queries/run", as: :run_query
4
+ root to: "queries#index"
5
5
  end
@@ -1,3 +1,3 @@
1
1
  module RailsPgExtrasWeb
2
- VERSION = '1.4.1'
2
+ VERSION = '2.0.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-pg-extras-web
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomasz Mazur
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-04 00:00:00.000000000 Z
11
+ date: 2021-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pg
@@ -30,15 +30,15 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.4.0
33
+ version: '2.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.4.0
41
- description:
40
+ version: '2.0'
41
+ description:
42
42
  email:
43
43
  - tomasz.mazur@hey.com
44
44
  executables: []
@@ -51,8 +51,11 @@ files:
51
51
  - app/controllers/rails_pg_extras_web/application_controller.rb
52
52
  - app/controllers/rails_pg_extras_web/queries_controller.rb
53
53
  - app/views/layouts/rails_pg_extras_web/application.html.erb
54
+ - app/views/rails_pg_extras_web/queries/_result.html.erb
55
+ - app/views/rails_pg_extras_web/queries/_unavailable_extensions_warning.html.erb
54
56
  - app/views/rails_pg_extras_web/queries/index.html.erb
55
- - app/views/rails_pg_extras_web/queries/run.html.erb
57
+ - app/views/rails_pg_extras_web/queries/show.html.erb
58
+ - app/views/rails_pg_extras_web/shared/_queries_selector.html.erb
56
59
  - config/routes.rb
57
60
  - lib/rails-pg-extras-web.rb
58
61
  - lib/rails_pg_extras_web/engine.rb
@@ -61,7 +64,7 @@ homepage: https://github.com/defkode/rails-pg-extras-web
61
64
  licenses:
62
65
  - MIT
63
66
  metadata: {}
64
- post_install_message:
67
+ post_install_message:
65
68
  rdoc_options: []
66
69
  require_paths:
67
70
  - lib
@@ -76,8 +79,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
76
79
  - !ruby/object:Gem::Version
77
80
  version: '0'
78
81
  requirements: []
79
- rubygems_version: 3.1.4
80
- signing_key:
82
+ rubygems_version: 3.1.6
83
+ signing_key:
81
84
  specification_version: 4
82
85
  summary: Web UI for rails-pg-extras
83
86
  test_files: []
@@ -1,59 +0,0 @@
1
- <% if @error %>
2
- <span style='color: red'><%= @error %></span>
3
- <% else %>
4
- <% if @result && @result.any? %>
5
- <table>
6
- <caption><%= RubyPGExtras.description_for(query_name: @query_name) %></caption>
7
- <thead>
8
- <tr>
9
- <% @result[0].keys.each do |header| %>
10
- <th><%= header %></th>
11
- <% end %>
12
- </tr>
13
- </thead>
14
- <tbody>
15
- <% @result.values.each do |row| %>
16
- <tr>
17
- <% row.each do |column| %>
18
- <td><%= column %></td>
19
- <% end %>
20
- </tr>
21
- <% end %>
22
- </tbody>
23
- </table>
24
-
25
- <pre>run_at: <%= Time.now.utc %></pre>
26
- <% else %>
27
- <pre>No results</pre>
28
- <% end %>
29
- <% end %>
30
-
31
- <style media="screen">
32
- table {
33
- font-family: monospace;
34
- border-collapse: collapse;
35
- width: 100%;
36
- }
37
-
38
- table th {
39
- background-color: #c9c9;
40
- }
41
-
42
- table th, table td {
43
- text-align: left;
44
- border: 1px solid #c9c9;
45
- padding: 3px;
46
- }
47
-
48
- table td {
49
- overflow: hidden;
50
- text-overflow: ellipsis;
51
- white-space: nowrap;
52
- }
53
-
54
- table caption {
55
- padding: 5px;
56
- font-size: 15px;
57
- font-weight: bold;
58
- }
59
- </style>