pghero 0.1.10 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of pghero might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +11 -226
- data/app/controllers/pg_hero/home_controller.rb +47 -9
- data/app/views/layouts/pg_hero/application.html.erb +43 -16
- data/app/views/pg_hero/home/_live_queries_table.html.erb +27 -0
- data/app/views/pg_hero/home/_queries_table.html.erb +25 -14
- data/app/views/pg_hero/home/index.html.erb +22 -2
- data/app/views/pg_hero/home/{indexes.html.erb → index_usage.html.erb} +1 -1
- data/app/views/pg_hero/home/live_queries.html.erb +9 -0
- data/app/views/pg_hero/home/queries.html.erb +13 -5
- data/app/views/pg_hero/home/space.html.erb +8 -5
- data/app/views/pg_hero/home/system.html.erb +14 -0
- data/config/routes.rb +25 -14
- data/guides/Docker.md +5 -0
- data/guides/Heroku.md +58 -0
- data/guides/Linux.md +203 -0
- data/guides/Query-Stats.md +60 -0
- data/guides/Rails.md +187 -0
- data/lib/pghero.rb +95 -9
- data/lib/pghero/version.rb +1 -1
- metadata +11 -6
- data/app/views/pg_hero/home/_query_stats_table.html.erb +0 -38
- data/app/views/pg_hero/home/query_stats.html.erb +0 -17
- data/app/views/pg_hero/home/system_stats.html.erb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5007ffa26cad91ceca6b39cf0049c0f935933637
|
4
|
+
data.tar.gz: 505386ddd4f407457b0d88d06840007d3aa27059
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: abb53d06f528e1e0461864b5afbc2e8a27cc2c425ad3a04e3ad4e1cee6bf45f4a1bd44d549dbb56df94052c0aa1bf53164d3a84d780530047368ee06fa190178
|
7
|
+
data.tar.gz: d2ae582ac7093732798ad45b6914b6adc4caab8af229e229a899342811f3fe2a94aeb918babb40ad8ef316e3ba2740040e313829a5a2f6bbdbbc35ac7ca96f34
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## 1.0.0
|
2
|
+
|
3
|
+
- More platforms!
|
4
|
+
- Support for multiple databases!
|
5
|
+
- Added `replica?` method
|
6
|
+
- Added `replication_lag` method
|
7
|
+
- Added `ssl_used?` method
|
8
|
+
- Added `kill_long_running_queries` method
|
9
|
+
- Added env vars for settings
|
10
|
+
|
1
11
|
## 0.1.10
|
2
12
|
|
3
13
|
- Added connections page
|
data/README.md
CHANGED
@@ -4,245 +4,30 @@ Postgres insights made easy
|
|
4
4
|
|
5
5
|
[View the demo](https://pghero.herokuapp.com/)
|
6
6
|
|
7
|
-
![Screenshot](https://pghero.herokuapp.com/assets/screenshot-
|
8
|
-
|
9
|
-
Supports PostgreSQL 9.2+
|
7
|
+
[![Screenshot](https://pghero.herokuapp.com/assets/screenshot-34a33ee68c77d64c1f89f143f6297a47.png)](https://pghero.herokuapp.com/)
|
10
8
|
|
11
9
|
:speech_balloon: Get [handcrafted updates](http://chartkick.us7.list-manage.com/subscribe?u=952c861f99eb43084e0a49f98&id=6ea6541e8e&group[0][32]=true) for new features
|
12
10
|
|
13
|
-
For pure SQL, check out [PgHero.sql](https://github.com/ankane/pghero.sql) and for a standalone app, check out [PgHero Solo](https://github.com/bmorton/pghero_solo)
|
14
|
-
|
15
|
-
A big thanks to [Craig Kerstiens](http://www.craigkerstiens.com/2013/01/10/more-on-postgres-performance/) and [Heroku](https://blog.heroku.com/archives/2013/5/10/more_insight_into_your_database_with_pgextras) for the initial queries :clap:
|
16
|
-
|
17
11
|
## Installation
|
18
12
|
|
19
|
-
|
20
|
-
|
21
|
-
```ruby
|
22
|
-
gem 'pghero'
|
23
|
-
```
|
24
|
-
|
25
|
-
And mount the dashboard in your `config/routes.rb`:
|
26
|
-
|
27
|
-
```ruby
|
28
|
-
mount PgHero::Engine, at: "pghero"
|
29
|
-
```
|
30
|
-
|
31
|
-
Be sure to [secure the dashboard](#security) in production.
|
32
|
-
|
33
|
-
## Insights
|
34
|
-
|
35
|
-
```ruby
|
36
|
-
PgHero.running_queries
|
37
|
-
PgHero.long_running_queries
|
38
|
-
PgHero.index_usage
|
39
|
-
PgHero.missing_indexes
|
40
|
-
PgHero.unused_indexes
|
41
|
-
PgHero.unused_tables
|
42
|
-
PgHero.database_size
|
43
|
-
PgHero.relation_sizes
|
44
|
-
PgHero.index_hit_rate
|
45
|
-
PgHero.table_hit_rate
|
46
|
-
PgHero.total_connections
|
47
|
-
```
|
48
|
-
|
49
|
-
Kill queries
|
50
|
-
|
51
|
-
```ruby
|
52
|
-
PgHero.kill(pid)
|
53
|
-
PgHero.kill_all
|
54
|
-
```
|
55
|
-
|
56
|
-
Query stats
|
57
|
-
|
58
|
-
```ruby
|
59
|
-
PgHero.query_stats_enabled?
|
60
|
-
PgHero.enable_query_stats
|
61
|
-
PgHero.disable_query_stats
|
62
|
-
PgHero.reset_query_stats
|
63
|
-
PgHero.query_stats
|
64
|
-
PgHero.slow_queries
|
65
|
-
```
|
66
|
-
|
67
|
-
## Users
|
68
|
-
|
69
|
-
Create a user
|
70
|
-
|
71
|
-
```ruby
|
72
|
-
PgHero.create_user("link")
|
73
|
-
# {password: "zbTrNHk2tvMgNabFgCo0ws7T"}
|
74
|
-
```
|
75
|
-
|
76
|
-
This generates and returns a secure password. The user has full access to the `public` schema.
|
77
|
-
|
78
|
-
Read-only access
|
79
|
-
|
80
|
-
```ruby
|
81
|
-
PgHero.create_user("epona", readonly: true)
|
82
|
-
```
|
83
|
-
|
84
|
-
Set the password
|
85
|
-
|
86
|
-
```ruby
|
87
|
-
PgHero.create_user("zelda", password: "hyrule")
|
88
|
-
```
|
89
|
-
|
90
|
-
Drop a user
|
91
|
-
|
92
|
-
```ruby
|
93
|
-
PgHero.drop_user("ganondorf")
|
94
|
-
```
|
95
|
-
|
96
|
-
## Security
|
97
|
-
|
98
|
-
#### Basic Authentication
|
99
|
-
|
100
|
-
Set the following variables in your environment or an initializer.
|
101
|
-
|
102
|
-
```ruby
|
103
|
-
ENV["PGHERO_USERNAME"] = "andrew"
|
104
|
-
ENV["PGHERO_PASSWORD"] = "secret"
|
105
|
-
```
|
106
|
-
|
107
|
-
#### Devise
|
108
|
-
|
109
|
-
```ruby
|
110
|
-
authenticate :user, lambda {|user| user.admin? } do
|
111
|
-
mount PgHero::Engine, at: "pghero"
|
112
|
-
end
|
113
|
-
```
|
114
|
-
|
115
|
-
## Query Stats
|
116
|
-
|
117
|
-
The [pg_stat_statements module](http://www.postgresql.org/docs/9.3/static/pgstatstatements.html) is used for query stats.
|
118
|
-
|
119
|
-
### Installation
|
120
|
-
|
121
|
-
If you have trouble enabling query stats from the dashboard, try doing it manually.
|
122
|
-
|
123
|
-
Add the following to your `postgresql.conf`:
|
124
|
-
|
125
|
-
```conf
|
126
|
-
shared_preload_libraries = 'pg_stat_statements'
|
127
|
-
pg_stat_statements.track = all
|
128
|
-
pg_stat_statements.max = 10000
|
129
|
-
track_activity_query_size = 2048
|
130
|
-
```
|
13
|
+
PgHero can be installed as a standalone app or a Rails engine.
|
131
14
|
|
132
|
-
|
15
|
+
### Standalone
|
133
16
|
|
134
|
-
|
135
|
-
CREATE extension pg_stat_statements;
|
136
|
-
```
|
17
|
+
[Linux](guides/Linux.md) - Ubuntu, Debian, and more
|
137
18
|
|
138
|
-
|
19
|
+
[Docker](guides/Docker.md)
|
139
20
|
|
140
|
-
|
21
|
+
[Heroku](guides/Heroku.md)
|
141
22
|
|
142
|
-
|
23
|
+
### Rails
|
143
24
|
|
144
|
-
|
145
|
-
CREATE extension pg_stat_statements;
|
146
|
-
```
|
25
|
+
[Rails](guides/Rails.md)
|
147
26
|
|
148
|
-
|
27
|
+
## Credits
|
149
28
|
|
150
|
-
|
151
|
-
|
152
|
-
Follow the instructions above.
|
153
|
-
|
154
|
-
#### FATAL: could not access file "pg_stat_statements": No such file or directory
|
155
|
-
|
156
|
-
Run `apt-get install postgresql-contrib-9.3` and follow the instructions above.
|
157
|
-
|
158
|
-
#### The database user does not have permission to ...
|
159
|
-
|
160
|
-
The database user is not a superuser. You can manually enable stats from the `psql` console with:
|
161
|
-
|
162
|
-
```psql
|
163
|
-
CREATE extension pg_stat_statements;
|
164
|
-
```
|
165
|
-
|
166
|
-
and reset stats with:
|
167
|
-
|
168
|
-
```psql
|
169
|
-
SELECT pg_stat_statements_reset();
|
170
|
-
```
|
171
|
-
|
172
|
-
#### Queries show up as `<insufficient privilege>`
|
173
|
-
|
174
|
-
For security reasons, only superusers can see queries executed by other users.
|
175
|
-
|
176
|
-
## System Stats
|
177
|
-
|
178
|
-
CPU usage is available for Amazon RDS. Add these lines to your application’s Gemfile:
|
179
|
-
|
180
|
-
```ruby
|
181
|
-
gem 'aws-sdk'
|
182
|
-
gem 'chartkick'
|
183
|
-
```
|
184
|
-
|
185
|
-
And add these variables to your environment:
|
186
|
-
|
187
|
-
```sh
|
188
|
-
PGHERO_ACCESS_KEY_ID=accesskey123
|
189
|
-
PGHERO_SECRET_ACCESS_KEY=secret123
|
190
|
-
PGHERO_DB_INSTANCE_IDENTIFIER=datakick-production
|
191
|
-
```
|
192
|
-
|
193
|
-
## Customize
|
194
|
-
|
195
|
-
Minimum time for long running queries
|
196
|
-
|
197
|
-
```ruby
|
198
|
-
PgHero.long_running_query_sec = 60 # default
|
199
|
-
```
|
200
|
-
|
201
|
-
Minimum average time for slow queries
|
202
|
-
|
203
|
-
```ruby
|
204
|
-
PgHero.slow_query_ms = 20 # default
|
205
|
-
```
|
206
|
-
|
207
|
-
Minimum calls for slow queries
|
208
|
-
|
209
|
-
```ruby
|
210
|
-
PgHero.slow_query_calls = 100 # default
|
211
|
-
```
|
212
|
-
|
213
|
-
Minimum connections for high connections warning
|
214
|
-
|
215
|
-
```ruby
|
216
|
-
PgHero.total_connections_threshold = 100 # default
|
217
|
-
```
|
218
|
-
|
219
|
-
## Bonus Projects
|
220
|
-
|
221
|
-
- See where queries come from with [Marginalia](https://github.com/basecamp/marginalia) - comments appear on the Live Queries tab.
|
222
|
-
- Get weekly news and articles with [Postgres Weekly](http://postgresweekly.com)
|
223
|
-
- Optimize your configuration with [PgTune](http://pgtune.leopard.in.ua) and [pgBench](http://www.postgresql.org/docs/devel/static/pgbench.html)
|
224
|
-
|
225
|
-
## TODO
|
226
|
-
|
227
|
-
- suggest indexes
|
228
|
-
- suggest paramater values
|
229
|
-
- better explanations on dashboard
|
29
|
+
A big thanks to [Craig Kerstiens](http://www.craigkerstiens.com/2013/01/10/more-on-postgres-performance/) and [Heroku](https://blog.heroku.com/archives/2013/5/10/more_insight_into_your_database_with_pgextras) for the initial queries and [Bootswatch](https://github.com/thomaspark/bootswatch) for the theme :clap:
|
230
30
|
|
231
31
|
Know a bit about PostgreSQL? [Suggestions](https://github.com/ankane/pghero/issues) are greatly appreciated.
|
232
32
|
|
233
|
-
|
234
|
-
|
235
|
-
Thanks to [Craig Kerstiens](http://www.craigkerstiens.com/2013/01/10/more-on-postgres-performance/) and [Heroku](https://blog.heroku.com/archives/2013/5/10/more_insight_into_your_database_with_pgextras) for the initial queries and [Bootswatch](https://github.com/thomaspark/bootswatch) for the theme.
|
236
|
-
|
237
|
-
## History
|
238
|
-
|
239
|
-
View the [changelog](https://github.com/ankane/pghero/blob/master/CHANGELOG.md)
|
240
|
-
|
241
|
-
## Contributing
|
242
|
-
|
243
|
-
Everyone is encouraged to help improve this project. Here are a few ways you can help:
|
244
|
-
|
245
|
-
- [Report bugs](https://github.com/ankane/pghero/issues)
|
246
|
-
- Fix bugs and [submit pull requests](https://github.com/ankane/pghero/pulls)
|
247
|
-
- Write, clarify, or fix documentation
|
248
|
-
- Suggest or add new features
|
33
|
+
:tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
|
@@ -6,10 +6,11 @@ module PgHero
|
|
6
6
|
|
7
7
|
http_basic_authenticate_with name: ENV["PGHERO_USERNAME"], password: ENV["PGHERO_PASSWORD"] if ENV["PGHERO_PASSWORD"]
|
8
8
|
|
9
|
+
around_filter :set_database
|
9
10
|
before_filter :set_query_stats_enabled
|
10
11
|
|
11
12
|
def index
|
12
|
-
@title = "
|
13
|
+
@title = "Overview"
|
13
14
|
@slow_queries = PgHero.slow_queries
|
14
15
|
@long_running_queries = PgHero.long_running_queries
|
15
16
|
@index_hit_rate = PgHero.index_hit_rate
|
@@ -20,10 +21,15 @@ module PgHero
|
|
20
21
|
@query_stats_available = PgHero.query_stats_available?
|
21
22
|
@total_connections = PgHero.total_connections
|
22
23
|
@good_total_connections = @total_connections < PgHero.total_connections_threshold
|
24
|
+
@replica = PgHero.replica?
|
25
|
+
if @replica
|
26
|
+
@replication_lag = PgHero.replication_lag
|
27
|
+
@good_replication_lag = @replication_lag < 5
|
28
|
+
end
|
23
29
|
end
|
24
30
|
|
25
|
-
def
|
26
|
-
@title = "
|
31
|
+
def index_usage
|
32
|
+
@title = "Index Usage"
|
27
33
|
@index_usage = PgHero.index_usage
|
28
34
|
end
|
29
35
|
|
@@ -33,20 +39,30 @@ module PgHero
|
|
33
39
|
@relation_sizes = PgHero.relation_sizes
|
34
40
|
end
|
35
41
|
|
36
|
-
def
|
42
|
+
def live_queries
|
37
43
|
@title = "Live Queries"
|
38
44
|
@running_queries = PgHero.running_queries
|
39
45
|
end
|
40
46
|
|
41
|
-
def
|
47
|
+
def queries
|
42
48
|
@title = "Queries"
|
43
49
|
@query_stats = PgHero.query_stats
|
44
50
|
end
|
45
51
|
|
46
|
-
def
|
47
|
-
@title = "System
|
48
|
-
|
49
|
-
|
52
|
+
def system
|
53
|
+
@title = "System"
|
54
|
+
end
|
55
|
+
|
56
|
+
def cpu_usage
|
57
|
+
render json: PgHero.cpu_usage.map { |k, v| [k, v.round] }
|
58
|
+
end
|
59
|
+
|
60
|
+
def connection_stats
|
61
|
+
render json: PgHero.connection_stats
|
62
|
+
end
|
63
|
+
|
64
|
+
def replication_lag_stats
|
65
|
+
render json: PgHero.replication_lag_stats
|
50
66
|
end
|
51
67
|
|
52
68
|
def explain
|
@@ -81,6 +97,11 @@ module PgHero
|
|
81
97
|
end
|
82
98
|
end
|
83
99
|
|
100
|
+
def kill_long_running_queries
|
101
|
+
PgHero.kill_long_running_queries
|
102
|
+
redirect_to :back, notice: "Queries killed"
|
103
|
+
end
|
104
|
+
|
84
105
|
def kill_all
|
85
106
|
PgHero.kill_all
|
86
107
|
redirect_to :back, notice: "Connections killed"
|
@@ -102,6 +123,23 @@ module PgHero
|
|
102
123
|
|
103
124
|
protected
|
104
125
|
|
126
|
+
def set_database
|
127
|
+
@databases = PgHero.config["databases"].keys
|
128
|
+
if params[:database]
|
129
|
+
PgHero.with(params[:database]) do
|
130
|
+
yield
|
131
|
+
end
|
132
|
+
elsif @databases.size > 1
|
133
|
+
redirect_to url_for(params.slice(:controller, :action).merge(database: PgHero.primary_database))
|
134
|
+
else
|
135
|
+
yield
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def default_url_options
|
140
|
+
{database: params[:database]}
|
141
|
+
end
|
142
|
+
|
105
143
|
def set_query_stats_enabled
|
106
144
|
@query_stats_enabled = PgHero.query_stats_enabled?
|
107
145
|
@system_stats_enabled = PgHero.system_stats_enabled?
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
2
|
<html>
|
3
3
|
<head>
|
4
|
-
<title><%= @
|
4
|
+
<title><%= [@databases.size > 1 ? PgHero.current_database.titleize : "PgHero", @title].compact.join(" / ") %></title>
|
5
5
|
|
6
6
|
<meta charset="utf-8" />
|
7
7
|
|
@@ -9,7 +9,7 @@
|
|
9
9
|
body {
|
10
10
|
margin: 0;
|
11
11
|
padding: 20px;
|
12
|
-
background-color: #
|
12
|
+
background-color: #eee;
|
13
13
|
}
|
14
14
|
|
15
15
|
body, textarea {
|
@@ -65,7 +65,7 @@
|
|
65
65
|
}
|
66
66
|
|
67
67
|
pre {
|
68
|
-
background-color: #
|
68
|
+
background-color: #eee;
|
69
69
|
padding: 10px;
|
70
70
|
white-space: pre-wrap;
|
71
71
|
word-break: break-word;
|
@@ -74,7 +74,7 @@
|
|
74
74
|
textarea {
|
75
75
|
width: 100%;
|
76
76
|
height: 100px;
|
77
|
-
border: solid 1px #
|
77
|
+
border: solid 1px #ddd;
|
78
78
|
padding: 10px;
|
79
79
|
}
|
80
80
|
|
@@ -94,13 +94,18 @@
|
|
94
94
|
margin-left: 6px;
|
95
95
|
}
|
96
96
|
|
97
|
+
.tiny {
|
98
|
+
font-size: 12px;
|
99
|
+
margin-left: 6px;
|
100
|
+
}
|
101
|
+
|
97
102
|
#status, .content, .alert {
|
98
103
|
margin-bottom: 20px;
|
99
104
|
}
|
100
105
|
|
101
106
|
.content {
|
102
107
|
padding: 20px 20px 1px 20px;
|
103
|
-
background-color: #
|
108
|
+
background-color: #fff;
|
104
109
|
}
|
105
110
|
|
106
111
|
.queries td {
|
@@ -114,18 +119,25 @@
|
|
114
119
|
/* nav */
|
115
120
|
|
116
121
|
.nav a {
|
117
|
-
color: #
|
122
|
+
color: #333;
|
118
123
|
text-decoration: none;
|
119
124
|
display: block;
|
120
125
|
padding: 12px 20px;
|
121
126
|
}
|
122
127
|
|
123
128
|
.nav li.active a {
|
124
|
-
background-color: #
|
129
|
+
background-color: #ddd;
|
125
130
|
}
|
126
131
|
|
127
132
|
.nav a:hover {
|
128
|
-
background-color: #
|
133
|
+
background-color: #ddd;
|
134
|
+
}
|
135
|
+
|
136
|
+
.nav-header {
|
137
|
+
font-weight: bold;
|
138
|
+
color: #333;
|
139
|
+
padding: 12px 20px 12px 0;
|
140
|
+
margin: 0;
|
129
141
|
}
|
130
142
|
|
131
143
|
/* buttons */
|
@@ -146,7 +158,7 @@
|
|
146
158
|
}
|
147
159
|
|
148
160
|
.btn-danger {
|
149
|
-
background-color: #
|
161
|
+
background-color: #d9534f;
|
150
162
|
}
|
151
163
|
|
152
164
|
.btn-info {
|
@@ -173,7 +185,7 @@
|
|
173
185
|
}
|
174
186
|
|
175
187
|
.alert-danger {
|
176
|
-
background-color: #
|
188
|
+
background-color: #d9534f;
|
177
189
|
}
|
178
190
|
|
179
191
|
.alert a {
|
@@ -349,22 +361,37 @@
|
|
349
361
|
|
350
362
|
<div class="grid">
|
351
363
|
<div class="col-3-12">
|
364
|
+
<% if @databases.size > 1 %>
|
365
|
+
<p class="nav-header"><%= PgHero.current_database.titleize %></p>
|
366
|
+
<% end %>
|
367
|
+
|
352
368
|
<ul class="nav">
|
353
369
|
<!-- poor man's active_link_to -->
|
354
|
-
<li class="<%= controller.action_name == "index" ? "active" : "" %>"><%= link_to "
|
370
|
+
<li class="<%= controller.action_name == "index" ? "active" : "" %>"><%= link_to "Overview", root_path %></li>
|
355
371
|
<% if @system_stats_enabled %>
|
356
|
-
<li class="<%= controller.action_name == "
|
372
|
+
<li class="<%= controller.action_name == "system" ? "active" : "" %>"><%= link_to "System", system_path %></li>
|
357
373
|
<% end %>
|
358
374
|
<% if @query_stats_enabled %>
|
359
|
-
<li class="<%= controller.action_name == "
|
375
|
+
<li class="<%= controller.action_name == "queries" ? "active" : "" %>"><%= link_to "Queries", queries_path %></li>
|
360
376
|
<% end %>
|
361
|
-
<li class="<%= controller.action_name == "
|
377
|
+
<li class="<%= controller.action_name == "index_usage" ? "active" : "" %>"><%= link_to "Index Usage", index_usage_path %></li>
|
362
378
|
<li class="<%= controller.action_name == "space" ? "active" : "" %>"><%= link_to "Space", space_path %></li>
|
363
|
-
<li class="<%= controller.action_name == "explain" ? "active" : "" %>"><%= link_to "Explain", explain_path %></li>
|
364
|
-
<li class="<%= controller.action_name == "queries" ? "active" : "" %>"><%= link_to "Live Queries", queries_path %></li>
|
365
379
|
<li class="<%= controller.action_name == "connections" ? "active" : "" %>"><%= link_to "Connections", connections_path %></li>
|
380
|
+
<li class="<%= controller.action_name == "live_queries" ? "active" : "" %>"><%= link_to "Live Queries", live_queries_path %></li>
|
381
|
+
<li class="<%= controller.action_name == "explain" ? "active" : "" %>"><%= link_to "Explain", explain_path %></li>
|
366
382
|
<li class="<%= controller.action_name == "tune" ? "active" : "" %>"><%= link_to "Tune", tune_path %></li>
|
367
383
|
</ul>
|
384
|
+
|
385
|
+
<% if @databases.size > 1 %>
|
386
|
+
<p class="nav-header">Other Databases</p>
|
387
|
+
<ul class="nav">
|
388
|
+
<% (@databases - [PgHero.current_database]).each do |database| %>
|
389
|
+
<li>
|
390
|
+
<%= link_to database.titleize, root_path(database: database) %>
|
391
|
+
</li>
|
392
|
+
<% end %>
|
393
|
+
</ul>
|
394
|
+
<% end %>
|
368
395
|
</div>
|
369
396
|
|
370
397
|
<div class="col-9-12">
|