Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
747bd34
add first routes to expose tables info
le-santos Jan 15, 2025
6fc2da4
draft first views and add bulma css style
le-santos Jan 15, 2025
80c6abc
adjust namespaces
le-santos Jan 15, 2025
878b9ef
add routes and views to run custom sql
le-santos Jan 15, 2025
b453588
add search bar to tables index
le-santos Jan 15, 2025
f959c3c
add new stats tab for future routes
le-santos Jan 15, 2025
f051fd2
expose more table data on index page
le-santos Jan 15, 2025
c27c46f
turn search bar to into a control pane partial
le-santos Jan 15, 2025
b2d3c91
extrat search to shared partial and include in tables views
le-santos Jan 16, 2025
5d65ae4
WIP creates a Table obj to centralize database queries for a given table
le-santos Jan 17, 2025
593100f
add Database obj to centralize db info
le-santos Jan 17, 2025
21c3b7d
replace deprecated connection method
le-santos Jan 17, 2025
23cd7f6
remove connection block logic and `it` attribute in blocks
le-santos Jan 21, 2025
6c5157a
add dummy app setup for testing
le-santos Jan 21, 2025
cf31813
WIP Table test
le-santos Jan 21, 2025
eb19c68
require all app files for tests
le-santos Jan 22, 2025
4094f3a
add test for table model
le-santos Jan 22, 2025
e08b865
add test for Database model
le-santos Jan 22, 2025
47cf2e7
adjust test description
le-santos Jan 22, 2025
1f56662
fix rubocop issues
le-santos Jan 22, 2025
479631a
fix ci test command
le-santos Jan 22, 2025
7e8787b
remove new ruby features for compatibility
le-santos Jan 22, 2025
b9a7985
fix ci file to run tests including system tests
le-santos Jan 22, 2025
392e682
adjust dummy app route for tests
le-santos Jan 22, 2025
3b5317c
add capybara and selenium for system tests
le-santos Jan 22, 2025
d8aebc4
WIP - tests for table flow
le-santos Jan 22, 2025
bd1f84d
fix rubocop
le-santos Jan 22, 2025
30c9169
add new model to dummy app to expose primary and foreign keys
le-santos Jan 23, 2025
830b778
finish system test for tables flow
le-santos Jan 23, 2025
d72dbe3
fix test
le-santos Jan 23, 2025
e31d640
fix queries links
le-santos Jan 23, 2025
0345420
adjust css load on application layout
le-santos Jan 23, 2025
9ae4e79
add missing memoize for db connection
le-santos Jan 24, 2025
6ab2e91
adding lib event store controller and railtie
garoazinha Jan 27, 2025
f444b85
testing
garoazinha Jan 27, 2025
a581db1
remove pry
garoazinha Jan 27, 2025
fd3e67b
rubocop and test
garoazinha Jan 27, 2025
083a445
use singleton module
garoazinha Jan 27, 2025
1d28891
reverse
garoazinha Jan 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
env:
RAILS_ENV: test
# REDIS_URL: redis://localhost:6379/0
run: bin/rails db:test:prepare test
run: bin/rails db:test:prepare && bin/rails app:test:all

- name: Keep screenshots from failed system tests
uses: actions/upload-artifact@v4
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@
/test/dummy/log/*.log
/test/dummy/storage/
/test/dummy/tmp/

# local IDE config
.vscode/
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ source "https://rubygems.org"
# Specify your gem's dependencies in railsdb-admin.gemspec.
gemspec

gem "capybara"
gem "selenium-webdriver"

gem "puma"

gem "sqlite3"
Expand Down
30 changes: 30 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,22 @@ GEM
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
uri (>= 0.13.1)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
ast (2.4.2)
base64 (0.2.0)
benchmark (0.4.0)
bigdecimal (3.1.9)
builder (3.3.0)
capybara (3.40.0)
addressable
matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.11)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
concurrent-ruby (1.3.4)
connection_pool (2.4.1)
crass (1.0.6)
Expand All @@ -109,6 +120,7 @@ GEM
net-pop
net-smtp
marcel (1.0.4)
matrix (0.4.2)
mini_mime (1.1.5)
minitest (5.25.4)
net-imap (0.5.4)
Expand All @@ -122,6 +134,8 @@ GEM
nio4r (2.7.4)
nokogiri (1.18.1-arm64-darwin)
racc (~> 1.4)
nokogiri (1.18.1-x86_64-linux-gnu)
racc (~> 1.4)
parallel (1.26.3)
parser (3.3.6.0)
ast (~> 2.4.1)
Expand All @@ -134,6 +148,7 @@ GEM
psych (5.2.2)
date
stringio
public_suffix (6.0.1)
puma (6.5.0)
nio4r (~> 2.0)
racc (1.8.1)
Expand Down Expand Up @@ -180,6 +195,7 @@ GEM
regexp_parser (2.10.0)
reline (0.6.0)
io-console (~> 0.5)
rexml (3.4.0)
rubocop (1.69.2)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
Expand Down Expand Up @@ -209,8 +225,16 @@ GEM
rubocop-performance
rubocop-rails
ruby-progressbar (1.13.0)
rubyzip (2.4.1)
securerandom (0.4.1)
selenium-webdriver (4.28.0)
base64 (~> 0.2)
logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
sqlite3 (2.5.0-arm64-darwin)
sqlite3 (2.5.0-x86_64-linux-gnu)
stringio (3.1.2)
thor (1.3.2)
timeout (0.4.3)
Expand All @@ -221,19 +245,25 @@ GEM
unicode-emoji (4.0.4)
uri (1.0.2)
useragent (0.16.11)
websocket (1.2.11)
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.7.1)

PLATFORMS
arm64-darwin
x86_64-linux

DEPENDENCIES
capybara
propshaft
puma
railsdb-admin!
rubocop-rails-omakase
selenium-webdriver
sqlite3

BUNDLED WITH
Expand Down
3 changes: 3 additions & 0 deletions app/assets/stylesheets/railsdb/admin/bulma.min.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion app/controllers/railsdb/admin/hello_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Railsdb
module Admin
class Railsdb::Admin::HelloController < Railsdb::Admin::ApplicationController
def index
render plain: 'Hello, Railsdb::Admin!'
render plain: "Hello, Railsdb::Admin!"
end
end
end
Expand Down
26 changes: 26 additions & 0 deletions app/controllers/railsdb/admin/queries_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module Railsdb
module Admin
class QueriesController < ApplicationController
before_action :set_connection, only: %i[ create ]

# GET /queries/new
def new; end

# POST /queries
def create
@query_items = @connection.execute(query_params[:query])
render :result
end

private

def query_params
params.permit(:query, {})
end

def set_connection
@connection ||= ActiveRecord::Base.with_connection { |con| con }
end
end
end
end
11 changes: 11 additions & 0 deletions app/controllers/railsdb/admin/stats_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Railsdb
module Admin
class StatsController < ApplicationController
def index
@stats = Railsdb::Admin::Stats.fetch_avg_durations
end

private
end
end
end
26 changes: 26 additions & 0 deletions app/controllers/railsdb/admin/tables_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module Railsdb
module Admin
class TablesController < ApplicationController
# GET /tables
def index
@tables = Database.info
end

# GET /table_data/:name
def table_data
@table = Table.explore(table_params[:name])
end

# GET /table_schema/:name
def table_schema
@table = Table.explore(table_params[:name])
end

private

def table_params
params.permit(:name)
end
end
end
end
36 changes: 36 additions & 0 deletions app/models/railsdb/admin/database.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module Railsdb
module Admin
# Plain Ruby object that provides methods to expose info,
# regarding database and its tables
#
# t = Database.info
#
class Database
def self.info
new.info
end

def info
# TODO: add pagination or LIMIT to the SELECT query
# Also, Postgres an others DB outputs might differ from SQLite
tables.map do |table|
ActiveSupport::OrderedOptions.new.tap do |attrs|
attrs.name = table
attrs.columns = connection.columns(table).count
attrs.records = connection.execute("SELECT COUNT(1) FROM #{table}").first["COUNT(1)"]
end
end
end

private

def tables
connection.tables
end

def connection
@connection ||= ActiveRecord::Base.with_connection { |con| con }
end
end
end
end
59 changes: 59 additions & 0 deletions app/models/railsdb/admin/table.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
module Railsdb
module Admin
# Plain Ruby object that provides methods to inspect info regarding a database table.
#
# t = Table.explore('table_name')
#
class Table
def initialize(name)
@name = name
end

attr_reader :name

def self.explore(name)
new(name).build_data
end

def build_data
table_attrs = ActiveSupport::OrderedOptions.new()

table_attrs.tap do |t|
t.name = name
t.columns = columns
t.data = data
t.primary_key = primary_key
t.foreign_keys = foreign_keys
t.indexes = indexes
end
end

private

def columns
connection.columns(name)
end

# TODO: add pagination or LIMIT to the SELECT query
def data
connection.execute("SELECT * FROM #{name}")
end

def primary_key
connection.primary_key(name)
end

def foreign_keys
connection.foreign_keys(name)
end

def indexes
connection.indexes(name)
end

def connection
@connection ||= ActiveRecord::Base.with_connection { |con| con }
end
end
end
end
32 changes: 32 additions & 0 deletions app/views/layouts/railsdb/admin/_control_pane.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<nav class="level">
<!-- Left side -->
<div class="level-left">
<div class="level-item">
<div class="field is-grouped">
<div class="control">

<div class="select">
<select id="sortField">
<% sort_by.each do |item| %>
<option value="<%= item %>"> <%= "Sort by #{item}" %></option>
<% end %>
</select>
</div>

<button id="sortDirection" class="button is-warning">
<span class="icon">
<span>&#8645</span>
</span>
</button>
</div>
</div>
</div>
</div>

<!-- Right side -->
<div class="level-right">
<div class="level-item">
<%= render 'railsdb/admin/shared/search', placeholder: 'search tables' %>
</div>
</div>
</nav>
13 changes: 13 additions & 0 deletions app/views/layouts/railsdb/admin/_navbar.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div class="tabs is-boxed">
<ul>
<li class="<%= 'is-active' if controller_name == 'tables' %>">
<%= link_to "Tables", tables_path %>
</li>
<li class="<%= 'is-active' if controller_name == 'queries' %>">
<%= link_to "SQL run", new_query_path %>
</li>
<li class="<%= 'is-active' if controller_name == 'statistics' %>">
<%= link_to "Statistics", '/railsdb/stats' %>
</li>
</ul>
</div>
40 changes: 30 additions & 10 deletions app/views/layouts/railsdb/admin/application.html.erb
Original file line number Diff line number Diff line change
@@ -1,17 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<title>Railsdb admin</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<head>
<title><%= content_for(:title) || "RailsDb Admin" %></title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>

<%= yield :head %>
<%= yield :head %>

<%= stylesheet_link_tag "railsdb/admin/application", media: "all" %>
</head>
<body>
<%# Enable PWA manifest for installable apps (make sure to enable in config/routes.rb too!) %>
<%#= tag.link rel: "manifest", href: pwa_manifest_path(format: :json) %>

<%= yield %>
<link rel="icon" href="/icon.png" type="image/png">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/icon.png">

</body>

<%# Includes all stylesheet files in app/assets/stylesheets %>
<%= stylesheet_link_tag "railsdb/admin/application" %>
<%= stylesheet_link_tag "railsdb/admin/bulma.min" %>
</head>

<body>
<div class="container is-fullhd">
<section class="section">
<div class="container is-fluid">
<%= render 'layouts/railsdb/admin/navbar' %>
<%= yield %>
<%= javascript_include_tag "application" %>
</div>
</section>
</div>
</body>
</html>
Loading
Loading