rails-pg-extras-web 1.6.0 → 3.1.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: c7f43ce0a38a6e61ba4c9424cd92614afd7f6609436d9da8aa0365365ad08a87
4
- data.tar.gz: e0ffa21d94bc8c12069c081d746410b954d9dd56b2e88809b36fd456e94bca30
3
+ metadata.gz: 8ca457b8f7491e7b1eab0a053ec0fd563db431209718b40203a121dc31ecf453
4
+ data.tar.gz: aa628d82e9b6858f565ea0b6fbb57c4c945706e684ba9c9e85530bbaf728fa69
5
5
  SHA512:
6
- metadata.gz: 55039e4b67cc04e64545ab07092bf135f9844ae84414d1a7688957fdcad0124918f538b4f3f020e133b7fedabfe86e4b3b5682654887794429c6d9c75ee99834
7
- data.tar.gz: 368e5bcda5b27669152df55c5fec5940a7575bd1557628af8d206cd2f4221700eedf91818dfdad08dd7262bd37866eab47be7d018559eec368cb91df9158dbc4
6
+ metadata.gz: 70c68e56d0f99bb4511b23ac98d246e381e67634b751f02b6c6e57906ca8efd9a6c07861c75cb15a043fb8654d89c1a991ec9288b1cd07a087e9eefcbc45eecd
7
+ data.tar.gz: d9d877137d79912412c3d7885e8b49bdf1d4a3ad0024d37908f99dc4567de864ab963359ee9158288a2ece7b82e6444d78cd9eb7c1a9468a4467578522b3e12b
data/README.md CHANGED
@@ -1,5 +1,7 @@
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
+
4
+ ![WebUI](https://raw.githubusercontent.com/pawurb/rails-pg-extras/master/rails-pg-extras-web.png)
3
5
 
4
6
  ## Installation
5
7
  Add this line to your application's Gemfile:
@@ -0,0 +1,26 @@
1
+ module RailsPgExtrasWeb
2
+ class ActionsController < ApplicationController
3
+ def kill_all
4
+ run(:kill_all)
5
+ end
6
+
7
+ def pg_stat_statements_reset
8
+ run(:pg_stat_statements_reset)
9
+ end
10
+
11
+ def add_extensions
12
+ run(:add_extensions)
13
+ end
14
+
15
+ private
16
+
17
+ def run(action)
18
+ begin
19
+ RailsPGExtras.run_query(query_name: action, in_format: :raw)
20
+ redirect_to root_path, notice: "Successfully ran #{action}"
21
+ rescue ActiveRecord::StatementInvalid => e
22
+ redirect_to root_path, alert: "Error: #{e.message}"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,9 +1,18 @@
1
1
  require "rails-pg-extras"
2
+ require "rails-pg-extras/version"
2
3
 
3
4
  module RailsPgExtrasWeb
4
5
  class ApplicationController < ActionController::Base
5
6
  layout "rails_pg_extras_web/application"
6
7
 
8
+ REQUIRED_EXTENSIONS = {
9
+ pg_stat_statements: %i[calls outliers pg_stat_statements_reset],
10
+ pg_buffercache: %i[buffercache_stats buffercache_usage],
11
+ sslinfo: %i[ssl_used]
12
+ }
13
+
14
+ ACTIONS = %i[kill_all pg_stat_statements_reset add_extensions]
15
+
7
16
  if Rails.env.production? && ENV['PG_EXTRAS_USER'].present? && ENV['PG_EXTRAS_PASSWORD'].present?
8
17
  http_basic_authenticate_with name: ENV['PG_EXTRAS_USER'], password: ENV['PG_EXTRAS_PASSWORD']
9
18
  end
@@ -1,51 +1,44 @@
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
-
8
3
  before_action :load_queries
9
4
  helper_method :unavailable_extensions
10
5
 
11
6
  def index
12
- @query_name = params[:query_name]&.to_sym.presence_in(@all_queries.keys)
13
- return unless @query_name
7
+ if params[:query_name].present?
8
+ @query_name = params[:query_name].to_sym.presence_in(@all_queries.keys)
9
+ return unless @query_name
10
+
11
+ begin
12
+ @result = RailsPGExtras.run_query(query_name: @query_name.to_sym, in_format: :raw)
13
+ rescue ActiveRecord::StatementInvalid => e
14
+ @error = e.message
15
+ end
14
16
 
15
- @result = RailsPGExtras.run_query(query_name: @query_name.to_sym, in_format: :raw)
16
- rescue ActiveRecord::StatementInvalid => e
17
- @error = e.message
17
+ render :show
18
+ end
18
19
  end
19
20
 
20
21
  private
21
22
 
22
23
  def load_queries
23
- @all_queries = {}
24
+ @all_queries = (RailsPGExtras::QUERIES - ACTIONS).inject({}) do |memo, query_name|
25
+ unless query_name.in? %i[mandelbrot]
26
+ memo[query_name] = { disabled: query_disabled?(query_name) }
27
+ end
24
28
 
25
- ::RailsPGExtras::QUERIES.each do |query_name|
26
- @all_queries[query_name] = {
27
- disabled: query_disabled?(query_name),
28
- command: query_name == :kill_all
29
- }
29
+ memo
30
30
  end
31
31
  end
32
32
 
33
33
  def query_disabled?(query_name)
34
- case query_name
35
- when :calls, :outliers
36
- unavailable_extensions.key?(:pg_stat_statements)
37
- when :buffercache_stats, :buffercache_usage
38
- unavailable_extensions.key?(:pg_buffercache)
39
- else
40
- false
41
- end
34
+ unavailable_extensions.values.flatten.include?(query_name)
42
35
  end
43
36
 
44
37
  def unavailable_extensions
45
38
  return @unavailable_extensions if defined?(@unavailable_extensions)
46
39
 
47
- extensions = ActiveRecord::Base.connection.extensions
48
- @unavailable_extensions = REQUIRED_EXTENSIONS.select { |extension, _| !extensions.include?(extension.to_s) }
40
+ enabled_extensions = ActiveRecord::Base.connection.extensions
41
+ @unavailable_extensions = REQUIRED_EXTENSIONS.delete_if { |ext| ext.to_s.in?(enabled_extensions) }
49
42
  end
50
43
  end
51
44
  end
@@ -1,19 +1,26 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
- <head>
4
- <title>PG::Extras</title>
5
- </head>
6
- <body onload="document.forms.queries.query_name.focus()">
7
- <%= form_with url: queries_path, id: "queries", method: :get do |f| %>
8
- <%= f.select :query_name, options_for_select(@all_queries.except(:kill_all, :mandelbrot), params[:query_name]),
9
- prompt: "--- select query ---"
10
- %>
3
+ <head>
4
+ <title><%= content_for :title %> | v<%= RailsPGExtras::VERSION %></title>
5
+ <%= javascript_include_tag "https://unpkg.com/@rails/ujs" %>
6
+ <link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body class="p-5 text-xs">
10
+ <% if flash[:notice] %>
11
+ <div class="bg-green-100 border-l-4 border-green-500 text-green-700 p-4 mb-4" role="alert">
12
+ <p class="font-bold">Notice</p>
13
+ <p><%= flash[:notice] %></p>
14
+ </div>
15
+ <% end %>
11
16
 
12
- <button type="submit">Run</button>
13
- <% end %>
17
+ <% if flash[:alert] %>
18
+ <div class="bg-red-100 border-l-4 border-red-500 text-red-700 p-4 mb-4" role="alert">
19
+ <p class="font-bold">Alert</p>
20
+ <p><%= flash[:alert] %></p>
21
+ </div>
22
+ <% end %>
14
23
 
15
- <div style='margin-top: 20px'>
16
24
  <%= yield %>
17
- </div>
18
- </body>
25
+ </body>
19
26
  </html>
@@ -0,0 +1,9 @@
1
+ <h1 class="font-bold text-xl my-5">Diagnose</h1>
2
+ <table class="w-full font-mono border-collapse border my-5">
3
+ <% RailsPGExtras.diagnose(in_format: :hash).each do |diagnosis| %>
4
+ <tr class="<%= diagnosis[:ok] ? 'bg-green-300' : 'bg-red-300' %>">
5
+ <td class='p-1 border font-bold'><%= diagnosis[:check_name] %></td>
6
+ <td class='p-1 border'><%= diagnosis[:message] %></td>
7
+ </tr>
8
+ <% end %>
9
+ </table>
@@ -0,0 +1,21 @@
1
+ <h1 class="font-bold text-xl my-5"><%= title %></h1>
2
+
3
+ <table class="w-full font-mono border-collapse border 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
+ <span class="italic">run_at: <%= Time.now.utc %></span>
@@ -0,0 +1,13 @@
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
+ <%= link_to "Enable extensions", add_extensions_action_path,
9
+ method: "post",
10
+ data: {
11
+ confirm: "This command will enable following extensions: #{unavailable_extensions.keys.join(', ')}. Do you want to proceeed?"
12
+ }, class: 'border p-3 bg-green-500 text-white hover:bg-green-600 font-bold rounded' %>
13
+
@@ -1,72 +1,21 @@
1
- <% if unavailable_extensions.any? && !@result %>
2
- <% unavailable_extensions.each do |extension, queries| %>
3
- <span style='color: orange'>
4
- WARNING: Queries <%= queries.map { |q| "<b><u>#{q}</u></b>" }.join(", ").html_safe %> require extension: <b><%= extension %></b>
5
- </span>
6
-
7
- <h4>Rails</h4>
8
- <pre style='background-color: #e2e2e2; padding: 10px'>ActiveRecord::Base.connection.enable_extension "<%= extension %>"</pre>
9
- <h4>SQL</h4>
10
- <pre style='background-color: #e2e2e2; padding: 10px'>CREATE EXTENSION <%= extension %></pre>
11
- <% end %>
12
- <% end %>
13
-
14
- <% if @error %>
15
- <span style='color: red'><%= @error %></span>
16
- <% else %>
17
- <% if @result && @result.any? %>
18
- <table>
19
- <caption><%= RubyPGExtras.description_for(query_name: @query_name) %></caption>
20
- <thead>
21
- <tr>
22
- <% @result[0].keys.each do |header| %>
23
- <th><%= header %></th>
24
- <% end %>
25
- </tr>
26
- </thead>
27
- <tbody>
28
- <% @result.values.each do |row| %>
29
- <tr>
30
- <% row.each do |column| %>
31
- <td><%= column %></td>
32
- <% end %>
33
- </tr>
34
- <% end %>
35
- </tbody>
36
- </table>
37
-
38
- <pre>run_at: <%= Time.now.utc %></pre>
39
- <% else %>
40
- <pre>No results</pre>
41
- <% end %>
42
- <% end %>
43
-
44
- <style media="screen">
45
- table {
46
- font-family: monospace;
47
- border-collapse: collapse;
48
- width: 100%;
49
- }
50
-
51
- table th {
52
- background-color: #c9c9;
53
- }
54
-
55
- table th, table td {
56
- text-align: left;
57
- border: 1px solid #c9c9;
58
- padding: 3px;
59
- }
60
-
61
- table td {
62
- overflow: hidden;
63
- text-overflow: ellipsis;
64
- white-space: nowrap;
65
- }
66
-
67
- table caption {
68
- padding: 5px;
69
- font-size: 15px;
70
- font-weight: bold;
71
- }
72
- </style>
1
+ <%= content_for :title, "pg_extras" %>
2
+ <%= render "rails_pg_extras_web/shared/queries_selector" %>
3
+ <%= render "unavailable_extensions_warning" if unavailable_extensions.any? %>
4
+ <%= render "diagnose" if unavailable_extensions.none? %>
5
+
6
+ <h1 class="font-bold text-xl my-5">Actions</h1>
7
+
8
+ <%= link_to "kill_all", kill_all_action_path,
9
+ method: "post",
10
+ data: {
11
+ confirm: "This commands kills all the currently active connections to the database. Do you want to proceed?"
12
+ },
13
+ class: 'border p-3 bg-red-500 text-white hover:bg-red-600 font-bold rounded'
14
+ %>
15
+
16
+ <%= link_to "pg_stat_statements_reset", pg_stat_statements_reset_action_path,
17
+ method: "post",
18
+ data: {
19
+ confirm: "This command discards all statistics gathered so far by pg_stat_statements. Do you want to proceed?"
20
+ }, class: 'border p-3 bg-blue-500 text-white hover:bg-blue-600 font-bold rounded'
21
+ %>
@@ -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
+ <div class="text-red-500 p-3 font-mono my-5"><%= @error %></div>
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,9 @@
1
1
  RailsPgExtrasWeb::Engine.routes.draw do
2
- resources :queries, only: :index
2
+ resources :queries, only: [:index]
3
+
4
+ post "/actions/kill_all" => "actions#kill_all", as: :kill_all_action
5
+ post "/actions/pg_stat_statements_reset" => "actions#pg_stat_statements_reset", as: :pg_stat_statements_reset_action
6
+ post "/actions/add_extensions" => "actions#add_extensions", as: :add_extensions_action
3
7
 
4
8
  root to: "queries#index"
5
9
  end
@@ -1,3 +1,3 @@
1
1
  module RailsPgExtrasWeb
2
- VERSION = '1.6.0'
2
+ VERSION = '3.1.0'
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.6.0
4
+ version: 3.1.0
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-04-19 00:00:00.000000000 Z
11
+ date: 2021-10-30 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.6.0
33
+ version: '3.1'
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.6.0
41
- description:
40
+ version: '3.1'
41
+ description:
42
42
  email:
43
43
  - tomasz.mazur@hey.com
44
44
  executables: []
@@ -48,10 +48,16 @@ files:
48
48
  - MIT-LICENSE
49
49
  - README.md
50
50
  - Rakefile
51
+ - app/controllers/rails_pg_extras_web/actions_controller.rb
51
52
  - app/controllers/rails_pg_extras_web/application_controller.rb
52
53
  - app/controllers/rails_pg_extras_web/queries_controller.rb
53
54
  - app/views/layouts/rails_pg_extras_web/application.html.erb
55
+ - app/views/rails_pg_extras_web/queries/_diagnose.html.erb
56
+ - app/views/rails_pg_extras_web/queries/_result.html.erb
57
+ - app/views/rails_pg_extras_web/queries/_unavailable_extensions_warning.html.erb
54
58
  - app/views/rails_pg_extras_web/queries/index.html.erb
59
+ - app/views/rails_pg_extras_web/queries/show.html.erb
60
+ - app/views/rails_pg_extras_web/shared/_queries_selector.html.erb
55
61
  - config/routes.rb
56
62
  - lib/rails-pg-extras-web.rb
57
63
  - lib/rails_pg_extras_web/engine.rb
@@ -60,7 +66,7 @@ homepage: https://github.com/defkode/rails-pg-extras-web
60
66
  licenses:
61
67
  - MIT
62
68
  metadata: {}
63
- post_install_message:
69
+ post_install_message:
64
70
  rdoc_options: []
65
71
  require_paths:
66
72
  - lib
@@ -76,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
76
82
  version: '0'
77
83
  requirements: []
78
84
  rubygems_version: 3.1.6
79
- signing_key:
85
+ signing_key:
80
86
  specification_version: 4
81
87
  summary: Web UI for rails-pg-extras
82
88
  test_files: []