brick 1.0.247 → 1.0.249
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 +4 -4
- data/lib/brick/compatibility.rb +1 -1
- data/lib/brick/extensions.rb +4 -2
- data/lib/brick/rails/engine.rb +65 -60
- data/lib/brick/rails.rb +33 -33
- data/lib/brick/reflect_tables.rb +7 -7
- data/lib/brick/util.rb +3 -3
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +8 -8
- data/lib/generators/brick/migrations_builder.rb +15 -4
- data/lib/generators/brick/seeds_builder.rb +2 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6a0179dae81efe75fe8ed60f18a8bcad431cd98db8604eadf7efba5ef200798f
|
|
4
|
+
data.tar.gz: fa409b53922fc28f8d0e0ef4753b0545efc27ae2c92fdf2f2249508d311137dc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 95ad49630d116d9fc1ca4c29065caeef4bbff0c688f4cadc64aed81b9611d057a628168ab2bd69d8958e4aa79c6caf4a2715ae2979c60741f081ddfc0fb41db5
|
|
7
|
+
data.tar.gz: a8e9d742f3207b58ff4069e3efd57a02cfa25f6c267db72ca1e725b10bc3fd29fddcaca2dd19c6501aaa4003cafc515d413789539c838f4d24cc668785776111
|
data/lib/brick/compatibility.rb
CHANGED
|
@@ -119,7 +119,7 @@ if Object.const_defined?('ActionPack') && !ActionPack.respond_to?(:version)
|
|
|
119
119
|
end
|
|
120
120
|
end
|
|
121
121
|
end
|
|
122
|
-
if Object.const_defined?('Bundler') && Bundler.locked_gems&.dependencies
|
|
122
|
+
if Object.const_defined?('Bundler') && Bundler.locked_gems&.dependencies&.key?('action_view')
|
|
123
123
|
require 'action_view' # Needed for Rails <= 4.0
|
|
124
124
|
module ::ActionView
|
|
125
125
|
if Object.const_defined?('ActionView') && !ActionView.respond_to?(:version)
|
data/lib/brick/extensions.rb
CHANGED
|
@@ -38,6 +38,8 @@
|
|
|
38
38
|
|
|
39
39
|
# Upon creation of a new object, when going to the index page, highlight this new object and scroll it into view (likely to the very bottom of everything, although might be sorted differently)
|
|
40
40
|
|
|
41
|
+
# If there is a module defined with the same name as a schema found in a Postgres, MSSQL, or Oracle database then missing models that should exist underneath that module are not auto-generated.
|
|
42
|
+
|
|
41
43
|
# ==========================================================
|
|
42
44
|
# Dynamically create model or controller classes when needed
|
|
43
45
|
# ==========================================================
|
|
@@ -213,7 +215,7 @@ module ActiveRecord
|
|
|
213
215
|
end
|
|
214
216
|
|
|
215
217
|
def is_postgres
|
|
216
|
-
@is_postgres ||= connection.adapter_name
|
|
218
|
+
@is_postgres ||= ['PostgreSQL', 'PostGIS'].include?(connection.adapter_name)
|
|
217
219
|
end
|
|
218
220
|
def is_mysql
|
|
219
221
|
@is_mysql ||= ['Mysql2', 'Trilogy'].include?(connection.adapter_name)
|
|
@@ -2206,7 +2208,7 @@ class Object
|
|
|
2206
2208
|
end
|
|
2207
2209
|
table_name = model&.table_name || ActiveSupport::Inflector.underscore(plural_class_name)
|
|
2208
2210
|
pk = model&._brick_primary_key(relations.fetch(table_name, nil))
|
|
2209
|
-
is_postgres = ActiveRecord::Base.connection.adapter_name
|
|
2211
|
+
is_postgres = ['PostgreSQL', 'PostGIS'].include?(ActiveRecord::Base.connection.adapter_name)
|
|
2210
2212
|
is_mysql = ['Mysql2', 'Trilogy'].include?(ActiveRecord::Base.connection.adapter_name)
|
|
2211
2213
|
|
|
2212
2214
|
namespace = nil if namespace == ::Object
|
data/lib/brick/rails/engine.rb
CHANGED
|
@@ -828,13 +828,13 @@ window.addEventListener(\"popstate\", linkSchemas);
|
|
|
828
828
|
end
|
|
829
829
|
css = +"
|
|
830
830
|
<%
|
|
831
|
-
if @_request.respond_to?(:content_security_policy) && (csp = @_request.content_security_policy)&.directives&.present?
|
|
831
|
+
if @_request.respond_to?(:content_security_policy) && (csp = @_request.content_security_policy)&.directives&.present? %><%
|
|
832
832
|
@_request.env['_is_brick'] = true
|
|
833
833
|
if @_request.respond_to?(:content_security_policy_nonce_directives)
|
|
834
834
|
@_request.content_security_policy_nonce_directives = %w[ script-src ]
|
|
835
835
|
@_request.env['_brick_nonce'] = \" nonce=\\\"#\{@_request.content_security_policy_nonce}\\\"\".html_safe
|
|
836
836
|
%><meta name=\"csp-nonce\" content=\"<%= @_request.content_security_policy_nonce %>\"><%
|
|
837
|
-
end
|
|
837
|
+
end %><%
|
|
838
838
|
if !@_request.respond_to?(:_brick_content_security_policy)
|
|
839
839
|
if csp.instance_variables.exclude?(:@_brick_style_shas)
|
|
840
840
|
csp.instance_variable_set(:@_brick_style_shas, [
|
|
@@ -1042,7 +1042,7 @@ if (window.brickFontFamily) {
|
|
|
1042
1042
|
}
|
|
1043
1043
|
</script>
|
|
1044
1044
|
<script src=\"https://apis.google.com/js/api.js\"></script>
|
|
1045
|
-
<script async defer src=\"https://accounts.google.com/gsi/client\" id=\"gapiScript\"
|
|
1045
|
+
<script async defer src=\"https://accounts.google.com/gsi/client\" id=\"gapiScript\"></script>
|
|
1046
1046
|
<script<%= @_request.env['_brick_nonce'] %>>
|
|
1047
1047
|
document.getElementById(\"gapiScript\").addEventListener(\"onload\",
|
|
1048
1048
|
function () { // gapiLoaded
|
|
@@ -1075,14 +1075,16 @@ if (window.brickFontFamily) {
|
|
|
1075
1075
|
</head>
|
|
1076
1076
|
<body>
|
|
1077
1077
|
<div id=\"titleBox\"><div id=\"titleSticky\">
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
end
|
|
1078
|
+
<%= if request.respond_to?(:flash)
|
|
1079
|
+
out = +''
|
|
1080
|
+
if (alert)
|
|
1081
|
+
out << \"<p class=\\\"flashAlert\\\">#\{alert}</p>\"
|
|
1082
|
+
end
|
|
1083
|
+
if (notice)
|
|
1084
|
+
out << \"<p class=\\\"flashNotice\\\">#\{notice}</p>\"
|
|
1085
|
+
end
|
|
1086
|
+
out.html_safe
|
|
1087
|
+
end %>#{"
|
|
1086
1088
|
#{schema_options}" if schema_options}
|
|
1087
1089
|
<select id=\"tbl\">#{table_options}</select>
|
|
1088
1090
|
<table id=\"resourceName\"><tr>
|
|
@@ -1103,7 +1105,7 @@ end %>#{"
|
|
|
1103
1105
|
end
|
|
1104
1106
|
%><%= if (children = model.descendants).present?
|
|
1105
1107
|
child_links = children.map do |child|
|
|
1106
|
-
path = send(\"#\{child._brick_index}_path\") + \"
|
|
1108
|
+
path = send(\"#\{child._brick_index}_path\") + \"?__#\{base_model.inheritance_column}=#\{child.name}\"
|
|
1107
1109
|
link_to(child.name, path)
|
|
1108
1110
|
end
|
|
1109
1111
|
\"<tr><td colspan=\\\"#\{td_count}\\\">Children: #\{child_links.join(' ')}</tr>\".html_safe
|
|
@@ -1114,22 +1116,22 @@ end
|
|
|
1114
1116
|
if description.present? %><span class=\"__brick\"><%=
|
|
1115
1117
|
description %></span><br><%
|
|
1116
1118
|
end
|
|
1117
|
-
# FILTER PARAMETERS
|
|
1119
|
+
# FILTER PARAMETERS %><%
|
|
1118
1120
|
if @_brick_params&.present? %>
|
|
1119
|
-
<% if @_brick_params.length == 1 # %%% Does not yet work with composite keys
|
|
1121
|
+
<% if @_brick_params.length == 1 # %%% Does not yet work with composite keys %><%
|
|
1120
1122
|
k, id = @_brick_params.first
|
|
1121
1123
|
id = id.first if id.is_a?(Array) && id.length == 1
|
|
1122
|
-
origin = (key_parts = k.split('.')).length == 1 ? model : model.reflect_on_association(key_parts.first).klass
|
|
1124
|
+
origin = (key_parts = k.split('.')).length == 1 ? model : model.reflect_on_association(key_parts.first).klass %><%
|
|
1123
1125
|
if (destination_fk = Brick.relations[origin.table_name][:fks].values.find { |fk| fk[:fk] == key_parts.last }) &&
|
|
1124
|
-
(objs = (destination = origin.reflect_on_association(destination_fk[:assoc_name])&.klass)&.find(id))
|
|
1126
|
+
(objs = (destination = origin.reflect_on_association(destination_fk[:assoc_name])&.klass)&.find(id)) %><%
|
|
1125
1127
|
objs = [objs] unless objs.is_a?(Array) %>
|
|
1126
1128
|
<h3 class=\"__brick\">for <% objs.each do |obj| %><%=
|
|
1127
1129
|
link_to \"#{"#\{obj.brick_descrip\} (#\{destination.name\})\""}, send(\"#\{destination._brick_index(:singular)\}_path\".to_sym, id)
|
|
1128
1130
|
%><% end %></h3><%
|
|
1129
|
-
end
|
|
1131
|
+
end %><%
|
|
1130
1132
|
end %>
|
|
1131
1133
|
<span class=\"__brick\">(<%= link_to \"See all #\{model.base_class.name.split('::').last.pluralize}\", #{@_brick_model._brick_index}_path %>)</span>
|
|
1132
|
-
<% end
|
|
1134
|
+
<% end %><%
|
|
1133
1135
|
# COLUMN EXCLUSIONS
|
|
1134
1136
|
if @_brick_excl&.present? %>
|
|
1135
1137
|
<div id=\"exclusions\">Excluded columns:
|
|
@@ -1144,9 +1146,10 @@ end
|
|
|
1144
1146
|
});
|
|
1145
1147
|
});
|
|
1146
1148
|
</script>
|
|
1147
|
-
<% end
|
|
1149
|
+
<% end %><%
|
|
1148
1150
|
# SEARCH BOX
|
|
1149
|
-
if @_brick_es && @_brick_es&.index('r') # Must have at least Elasticsearch Read access
|
|
1151
|
+
if @_brick_es && @_brick_es&.index('r') # Must have at least Elasticsearch Read access
|
|
1152
|
+
%>
|
|
1150
1153
|
<input type=\"text\" id=\"esSearch\" class=\"dimmed\">
|
|
1151
1154
|
<script<%= @_request.env['_brick_nonce'] %>>
|
|
1152
1155
|
var esSearch = document.getElementById(\"esSearch\");
|
|
@@ -1211,7 +1214,7 @@ end
|
|
|
1211
1214
|
</div></div>
|
|
1212
1215
|
#{::Brick::Rails.erd_markup(@_brick_model, prefix) if @_brick_model}
|
|
1213
1216
|
|
|
1214
|
-
|
|
1217
|
+
<%=# Consider getting the name from the association -- hm.first.name -- if a more \"friendly\" alias should be used for a screwy table name
|
|
1215
1218
|
# If the resource is missing, has the user simply created an inappropriately pluralised name for a table?
|
|
1216
1219
|
@#{res_name} ||= if (dym_list = instance_variables.reject do |entry|
|
|
1217
1220
|
entry.to_s.start_with?('@_') ||
|
|
@@ -1343,21 +1346,21 @@ end
|
|
|
1343
1346
|
' class=\"orphan\"' unless ::Brick.relations.key?(r[1])
|
|
1344
1347
|
else
|
|
1345
1348
|
' class=\"dimmed\"'
|
|
1346
|
-
end&.html_safe
|
|
1349
|
+
end&.html_safe %>><%=# Table
|
|
1347
1350
|
if (rowcount = rel&.fetch(:rowcount, nil))
|
|
1348
1351
|
rowcount = (rowcount > 0 ? \" (#\{rowcount})\" : nil)
|
|
1349
1352
|
end
|
|
1350
1353
|
\"#\{r[1]}#\{rowcount}\" %></td>
|
|
1351
1354
|
<td<%= lines = r[2]&.map { |line| \"#\{line.first}:#\{line.last}\" }
|
|
1352
|
-
' class=\"dimmed\"'.html_safe unless r[2]
|
|
1355
|
+
' class=\"dimmed\"'.html_safe unless r[2] %>><%=# Migration
|
|
1353
1356
|
lines&.join('<br>')&.html_safe %></td>
|
|
1354
|
-
<td<%= ' class=\"dimmed\"'.html_safe unless r[3]
|
|
1357
|
+
<td<%= ' class=\"dimmed\"'.html_safe unless r[3] %>><%=# Model
|
|
1355
1358
|
r[3] %></td>
|
|
1356
|
-
<td<%= ' class=\"dimmed\"'.html_safe unless r[4]
|
|
1359
|
+
<td<%= ' class=\"dimmed\"'.html_safe unless r[4] %>><%=# Route
|
|
1357
1360
|
%></td>
|
|
1358
|
-
<td<%= ' class=\"dimmed\"'.html_safe unless r[5]
|
|
1361
|
+
<td<%= ' class=\"dimmed\"'.html_safe unless r[5] %>><%=# Controller
|
|
1359
1362
|
%></td>
|
|
1360
|
-
<td<%= ' class=\"dimmed\"'.html_safe unless r[6]
|
|
1363
|
+
<td<%= ' class=\"dimmed\"'.html_safe unless r[6] %>><%=# Views
|
|
1361
1364
|
%></td>
|
|
1362
1365
|
</tr>
|
|
1363
1366
|
<% end %>
|
|
@@ -1372,14 +1375,14 @@ end
|
|
|
1372
1375
|
#{schema_options}" if schema_options}
|
|
1373
1376
|
<select id=\"tbl\">#{table_options}</select>
|
|
1374
1377
|
<h1>Orphans<%= \" for #\{}\" if false %></h1>
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
+
<%= @orphans.each_with_object(+'') do |o, s|
|
|
1379
|
+
if (klass = ::Brick.relations[o[0]]&.fetch(:class_name, nil)&.constantize)
|
|
1380
|
+
s << \" via = \\\" (via #\{o[4]})\\\" unless \"#\{o[2].split('.').last.underscore.singularize}_id\" == o[4]
|
|
1378
1381
|
link_to(\"#\{o[0]} #\{o[1]} refers#\{via} to non-existent #\{o[2]} #\{o[3]}#\{\" (in table \\\"#\{o[5]}\\\")\" if o[5]}\",
|
|
1379
|
-
send(\"#\{klass._brick_index(:singular)\}_path\".to_sym, o[1]))
|
|
1380
|
-
<br
|
|
1381
|
-
|
|
1382
|
-
end %>
|
|
1382
|
+
send(\"#\{klass._brick_index(:singular)\}_path\".to_sym, o[1]))
|
|
1383
|
+
s << \"\\n <br>\\n\"
|
|
1384
|
+
end
|
|
1385
|
+
end.html_safe %>
|
|
1383
1386
|
#{script}"
|
|
1384
1387
|
end
|
|
1385
1388
|
|
|
@@ -1419,25 +1422,27 @@ end
|
|
|
1419
1422
|
c23.141-70.188,89.141-120.906,167.063-120.906c97.25,0,176,78.813,176,176C511.828,227.078,404.391,119.641,271.844,119.641z\" />
|
|
1420
1423
|
</svg>
|
|
1421
1424
|
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
end
|
|
1425
|
+
<%= if request.respond_to?(:flash)
|
|
1426
|
+
out = +''
|
|
1427
|
+
if (alert)
|
|
1428
|
+
out << \"<p class=\\\"flashAlert\\\">#\{alert}</p>\"
|
|
1429
|
+
end
|
|
1430
|
+
if (notice)
|
|
1431
|
+
out << \"<p class=\\\"flashNotice\\\">#\{notice}</p>\"
|
|
1432
|
+
end
|
|
1433
|
+
out.html_safe
|
|
1434
|
+
end %>#{"
|
|
1430
1435
|
#{schema_options}" if schema_options}
|
|
1431
1436
|
<select id=\"tbl\">#{table_options}</select>
|
|
1432
1437
|
<table id=\"resourceName\"><tr><td><h1><%= page_title %></h1></td>
|
|
1433
|
-
|
|
1438
|
+
<%= rel = Brick.relations[#{model_name}.table_name]
|
|
1434
1439
|
if (in_app = rel.fetch(:existing, nil)&.fetch(:show, nil))
|
|
1435
1440
|
begin
|
|
1436
|
-
in_app = send(\"#\{in_app}_path\", #{pk.is_a?(String) ? "obj.#{pk}" : '[' + pk.map { |pk_part| "obj.#{pk_part}" }.join(', ') + ']' }) if in_app.is_a?(Symbol)
|
|
1437
|
-
<td
|
|
1438
|
-
|
|
1441
|
+
in_app = send(\"#\{in_app}_path\", #{pk.is_a?(String) ? "obj.#{pk}" : '[' + pk.map { |pk_part| "obj.#{pk_part}" }.join(', ') + ']' }) if in_app.is_a?(Symbol)
|
|
1442
|
+
\"\\n <td>#\{link_to(::Brick::Rails::IN_APP.html_safe, in_app)}</td>\\n\".html_safe
|
|
1443
|
+
rescue ActionController::UrlGenerationError
|
|
1439
1444
|
end
|
|
1440
|
-
end
|
|
1445
|
+
end %><%
|
|
1441
1446
|
|
|
1442
1447
|
if Object.const_defined?('Avo') && ::Avo.respond_to?(:railtie_namespace) %>
|
|
1443
1448
|
<td><%= link_to_brick(
|
|
@@ -1448,19 +1453,19 @@ end %>#{"
|
|
|
1448
1453
|
end,
|
|
1449
1454
|
title: \"#\{page_title} in Avo\" }
|
|
1450
1455
|
) %></td>
|
|
1451
|
-
<% end
|
|
1456
|
+
<% end %><%=
|
|
1452
1457
|
|
|
1453
1458
|
if Object.const_defined?('ActiveAdmin')
|
|
1454
|
-
ActiveAdmin.application.namespaces.names.
|
|
1455
|
-
<td
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1459
|
+
ActiveAdmin.application.namespaces.names.each_with_object(+'') do |ns, s|
|
|
1460
|
+
s << \"\\n<td>#\{link_to_brick(
|
|
1461
|
+
::Brick::Rails::AA_PNG.html_safe,
|
|
1462
|
+
{ show_proc: Proc.new do |aa_model, relation|
|
|
1463
|
+
path_helper = \"#\{ns}_#\{relation.fetch(:auto_prefixed_schema, nil)}#\{aa_model.model_name.singular_route_key}_path\".to_sym
|
|
1464
|
+
send(path_helper, obj) if respond_to?(path_helper)
|
|
1465
|
+
end,
|
|
1466
|
+
title: \"#\{page_title} in ActiveAdmin\" }
|
|
1467
|
+
)}</td>\\n\"
|
|
1468
|
+
end
|
|
1464
1469
|
end %>
|
|
1465
1470
|
</tr></table>
|
|
1466
1471
|
<%
|
|
@@ -1472,7 +1477,7 @@ end
|
|
|
1472
1477
|
<% if obj %>
|
|
1473
1478
|
<br><br>
|
|
1474
1479
|
|
|
1475
|
-
|
|
1480
|
+
<%=# Write out the mega-form
|
|
1476
1481
|
brick_form_with(model: obj, bts: bts, pk: #{pk.inspect}) %>
|
|
1477
1482
|
|
|
1478
1483
|
#{unless args.first == 'new'
|
|
@@ -1706,7 +1711,7 @@ flatpickr(\".timepicker\", {enableTime: true, noCalendar: true});
|
|
|
1706
1711
|
end
|
|
1707
1712
|
if representation == :grid
|
|
1708
1713
|
inline << "<script<%= @_request.env['_brick_nonce'] %>>
|
|
1709
|
-
|
|
1714
|
+
<%# Make column headers sort when clicked
|
|
1710
1715
|
# %%% Create a smart javascript routine which can do this client-side %>
|
|
1711
1716
|
[... document.getElementsByTagName(\"TH\")].forEach(function (th) {
|
|
1712
1717
|
th.addEventListener(\"click\", function (e) {
|
data/lib/brick/rails.rb
CHANGED
|
@@ -122,7 +122,7 @@ module ::Brick::Rails
|
|
|
122
122
|
"<div id=\"mermaidErd\">
|
|
123
123
|
<div id=\"mermaidDiagram\" class=\"mermaid\">
|
|
124
124
|
erDiagram
|
|
125
|
-
|
|
125
|
+
<%= shown_classes = {}
|
|
126
126
|
|
|
127
127
|
def erd_sidelinks(shown_classes, klass)
|
|
128
128
|
links = []
|
|
@@ -137,20 +137,20 @@ erDiagram
|
|
|
137
137
|
links.join
|
|
138
138
|
end
|
|
139
139
|
|
|
140
|
-
@_brick_bt_descrip&.
|
|
140
|
+
@_brick_bt_descrip&.each_with_object(+'') do |bt, s|
|
|
141
141
|
bt_class = bt[1].first.first
|
|
142
142
|
callbacks[bt_name = bt_class.name.split('::').last] = bt_class
|
|
143
143
|
# Used to have: &.inverse_of before &.macro
|
|
144
144
|
is_has_one = ::#{model.name}.reflect_on_association(bt.first)&.macro == :has_one ||
|
|
145
145
|
::Brick.config.has_ones&.fetch('#{model.name}', nil)&.key?(bt.first.to_s)
|
|
146
|
-
|
|
146
|
+
s << \" #{model_short_name} #\{is_has_one ? '||--o|' : '}o--||'} #\{bt_name} : \\\"#\{
|
|
147
147
|
bt_underscored = bt[1].first.first.name.underscore.singularize
|
|
148
148
|
bt.first unless bt.first.to_s == bt_underscored.split('/').last # Was: bt_underscored.tr('/', '_')
|
|
149
|
-
}\\\"\"
|
|
150
|
-
|
|
151
|
-
|
|
149
|
+
}\\\"\n\"
|
|
150
|
+
s << erd_sidelinks(shown_classes, bt_class)
|
|
151
|
+
end&.html_safe %><%=
|
|
152
152
|
last_hm = nil
|
|
153
|
-
@_brick_hm_counts&.
|
|
153
|
+
@_brick_hm_counts&.each_with_object(+'') do |hm, s|
|
|
154
154
|
# Skip showing self-referencing HM links since they would have already been drawn while evaluating the BT side
|
|
155
155
|
next if (hm_class = hm.last&.klass) == ::#{model.name}
|
|
156
156
|
|
|
@@ -159,21 +159,21 @@ erDiagram
|
|
|
159
159
|
through_name = (through_assoc = hm.last.source_reflection).active_record.name.split('::').last
|
|
160
160
|
callbacks[through_name] = through_assoc.active_record
|
|
161
161
|
if last_hm == through # Same HM, so no need to build it again, and for clarity just put in a blank line
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
162
|
+
s << \"\\n\"
|
|
163
|
+
else
|
|
164
|
+
s << \" #{model_short_name} ||--o{ #\{through_name} : \\\"\\\"\\n\"
|
|
165
|
+
s << erd_sidelinks(shown_classes, through_assoc.active_record)
|
|
166
|
+
last_hm = through
|
|
167
167
|
end
|
|
168
|
-
|
|
169
|
-
|
|
168
|
+
s << \" #\{through_name} }o--|| #\{hm_name} : \\\"\\\"\\n\"
|
|
169
|
+
s << \"#{model_short_name} }o..o{ #\{hm_name} : \\\"#\{hm.first}\\\"\\n\"
|
|
170
170
|
else # has_many
|
|
171
|
-
|
|
171
|
+
s << \" #{model_short_name} #\{hm.last.macro == :has_and_belongs_to_many ? '}o' : '||'}--o{ #\{hm_name} : \\\"#\{
|
|
172
172
|
hm.first.to_s unless (last_hm = hm.first.to_s).downcase == hm_class.name.underscore.pluralize.tr('/', '_')
|
|
173
|
-
}\\\"\"
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
|
|
173
|
+
}\\\"\\n\"
|
|
174
|
+
end
|
|
175
|
+
s << erd_sidelinks(shown_classes, hm_class)
|
|
176
|
+
end&.html_safe %><%
|
|
177
177
|
def dt_lookup(dt)
|
|
178
178
|
{ 'integer' => 'int', 'character varying' => 'varchar', 'double precision' => 'float',
|
|
179
179
|
'timestamp without time zone' => 'timestamp',
|
|
@@ -186,26 +186,26 @@ erDiagram
|
|
|
186
186
|
pkeys = cb_relation[:pkey]&.first&.last
|
|
187
187
|
fkeys = cb_relation[:fks]&.values&.each_with_object([]) { |fk, s| s << fk[:fk] if fk.fetch(:is_bt, nil) }
|
|
188
188
|
cols = cb_relation[:cols]
|
|
189
|
-
%> <%= cb_k %> {
|
|
190
|
-
pkeys&.
|
|
191
|
-
|
|
192
|
-
end
|
|
193
|
-
fkeys&.
|
|
189
|
+
%> <%= cb_k %> {<%=
|
|
190
|
+
pkeys&.each_with_object(+'') do |pk, s|
|
|
191
|
+
s << \"#\{dt_lookup(cols[pk].first)} #\{pk} \\\"PK#\{' fk' if fkeys&.include?(pk)}\\\"\"
|
|
192
|
+
end&.html_safe %><%=
|
|
193
|
+
fkeys&.each_with_object(+'') do |fk, s|
|
|
194
194
|
if fk.is_a?(Array)
|
|
195
|
-
fk.each do |fk_part|
|
|
196
|
-
|
|
195
|
+
fk.each do |fk_part|
|
|
196
|
+
s << \"#\{dt_lookup(cols[fk_part].first)} #\{fk_part} \\\" fk\\\"\" unless pkeys&.include?(fk_part)
|
|
197
197
|
end
|
|
198
198
|
else # %%% Does not yet accommodate polymorphic BTs
|
|
199
|
-
|
|
200
|
-
<%= \"#\{dt_lookup(cols[fk]&.first)} #\{fk} \\\" fk\\\"\".html_safe unless pkeys&.include?(fk) %><%
|
|
199
|
+
s << \"#\{dt_lookup(cols[fk]&.first)} #\{fk} \\\" fk\\\"\" unless pkeys&.include?(fk)
|
|
201
200
|
end
|
|
202
|
-
end
|
|
201
|
+
end&.html_safe %><%=
|
|
203
202
|
if (erd_sc = Brick.config.erd_show_columns) == true || erd_sc&.include?(cb_class.name)
|
|
204
|
-
cols&.
|
|
205
|
-
next if pkeys.include?(col.first) || fkeys.include?(col.first)
|
|
206
|
-
|
|
203
|
+
cols&.each_with_object(+'') do |col, s|
|
|
204
|
+
next if pkeys.include?(col.first) || fkeys.include?(col.first)
|
|
205
|
+
|
|
206
|
+
s << \"#\{dt_lookup(col[1]&.first&.to_s)} #\{col.first}\"
|
|
207
207
|
end
|
|
208
|
-
end %>
|
|
208
|
+
end&.html_safe %>
|
|
209
209
|
}
|
|
210
210
|
<% end
|
|
211
211
|
# callback < %= cb_k % > erdClick
|
data/lib/brick/reflect_tables.rb
CHANGED
|
@@ -100,7 +100,7 @@ module Brick
|
|
|
100
100
|
is_postgres = nil
|
|
101
101
|
is_mssql = ActiveRecord::Base.connection.adapter_name == 'SQLServer'
|
|
102
102
|
case ActiveRecord::Base.connection.adapter_name
|
|
103
|
-
when 'PostgreSQL', 'SQLServer'
|
|
103
|
+
when 'PostgreSQL', 'PostGIS', 'SQLServer'
|
|
104
104
|
is_postgres = !is_mssql
|
|
105
105
|
db_schemas = if is_postgres
|
|
106
106
|
ActiveRecord::Base.execute_sql('SELECT nspname AS table_schema, MAX(oid) AS dt FROM pg_namespace GROUP BY 1 ORDER BY 1;')
|
|
@@ -177,8 +177,8 @@ module Brick
|
|
|
177
177
|
measures = []
|
|
178
178
|
::Brick.is_oracle = true if ActiveRecord::Base.connection.adapter_name == 'OracleEnhanced'
|
|
179
179
|
case ActiveRecord::Base.connection.adapter_name
|
|
180
|
-
when 'PostgreSQL', 'SQLite' # These bring back a hash for each row because the query uses column aliases
|
|
181
|
-
# schema ||= 'public' if ActiveRecord::Base.connection.adapter_name
|
|
180
|
+
when 'PostgreSQL', 'PostGIS', 'SQLite' # These bring back a hash for each row because the query uses column aliases
|
|
181
|
+
# schema ||= 'public' if ['PostgreSQL', 'PostGIS'].include?(ActiveRecord::Base.connection.adapter_name)
|
|
182
182
|
retrieve_schema_and_tables(sql, is_postgres, is_mssql, schema).each do |r|
|
|
183
183
|
# If Apartment gem lists the table as being associated with a non-tenanted model then use whatever it thinks
|
|
184
184
|
# is the default schema, usually 'public'.
|
|
@@ -275,7 +275,7 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
|
275
275
|
end
|
|
276
276
|
|
|
277
277
|
# PostGIS adds three views which would confuse Rails if models were to be built for them.
|
|
278
|
-
if ActiveRecord::Base.connection.adapter_name
|
|
278
|
+
if ['PostgreSQL', 'PostGIS'].include?(ActiveRecord::Base.connection.adapter_name)
|
|
279
279
|
if relations.key?('geography_columns') && relations.key?('geometry_columns') && relations.key?('spatial_ref_sys')
|
|
280
280
|
(::Brick.config.exclude_tables ||= []) << 'geography_columns'
|
|
281
281
|
::Brick.config.exclude_tables << 'geometry_columns'
|
|
@@ -284,7 +284,7 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
|
284
284
|
end
|
|
285
285
|
|
|
286
286
|
# # Add unique OIDs
|
|
287
|
-
# if ActiveRecord::Base.connection.adapter_name
|
|
287
|
+
# if ['PostgreSQL', 'PostGIS'].include?(ActiveRecord::Base.connection.adapter_name)
|
|
288
288
|
# ActiveRecord::Base.execute_sql(
|
|
289
289
|
# "SELECT c.oid, n.nspname, c.relname
|
|
290
290
|
# FROM pg_catalog.pg_namespace AS n
|
|
@@ -309,7 +309,7 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
|
309
309
|
kcus = nil
|
|
310
310
|
entry_type = nil
|
|
311
311
|
case ActiveRecord::Base.connection.adapter_name
|
|
312
|
-
when 'PostgreSQL', 'Mysql2', 'Trilogy', 'SQLServer'
|
|
312
|
+
when 'PostgreSQL', 'PostGIS', 'Mysql2', 'Trilogy', 'SQLServer'
|
|
313
313
|
# Part 1 -- all KCUs
|
|
314
314
|
sql = "SELECT CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, ORDINAL_POSITION,
|
|
315
315
|
TABLE_NAME, COLUMN_NAME
|
|
@@ -369,7 +369,7 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
|
369
369
|
fk_references = ActiveRecord::Base.execute_sql(sql)
|
|
370
370
|
end
|
|
371
371
|
::Brick.is_oracle = true if ActiveRecord::Base.connection.adapter_name == 'OracleEnhanced'
|
|
372
|
-
# ::Brick.default_schema ||= schema ||= 'public' if ActiveRecord::Base.connection.adapter_name
|
|
372
|
+
# ::Brick.default_schema ||= schema ||= 'public' if ['PostgreSQL', 'PostGIS'].include?(ActiveRecord::Base.connection.adapter_name)
|
|
373
373
|
::Brick.default_schema ||= 'public' if is_postgres
|
|
374
374
|
fk_references&.each do |fk|
|
|
375
375
|
fk = fk.values unless fk.is_a?(Array)
|
data/lib/brick/util.rb
CHANGED
|
@@ -49,7 +49,7 @@ module Brick
|
|
|
49
49
|
# then required in place of the original.
|
|
50
50
|
|
|
51
51
|
Kernel.module_exec do
|
|
52
|
-
alias_method :
|
|
52
|
+
alias_method :_orig_require, :require
|
|
53
53
|
# To be most faithful to Ruby's normal behaviour, this should look like a public singleton
|
|
54
54
|
define_method(:require) do |name|
|
|
55
55
|
# %%% Can get a message such as "ActionDispatch::Routing is not missing constant RouteSet! (NameError)"
|
|
@@ -62,14 +62,14 @@ module Brick
|
|
|
62
62
|
else
|
|
63
63
|
is_replaced = false
|
|
64
64
|
if (replacement_path = ::Brick::Util._write_patched(folder_matcher, name, extension, ::Brick::Util._custom_require_dir, patched_filename, replacements))
|
|
65
|
-
is_replaced =
|
|
65
|
+
is_replaced = _orig_require(replacement_path)
|
|
66
66
|
elsif replacement_path.nil?
|
|
67
67
|
puts "Couldn't find #{name} to require it!"
|
|
68
68
|
end
|
|
69
69
|
is_replaced
|
|
70
70
|
end
|
|
71
71
|
else
|
|
72
|
-
|
|
72
|
+
_orig_require(name)
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
75
|
end
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
|
@@ -127,7 +127,7 @@ module Brick
|
|
|
127
127
|
def set_db_schema(params = nil)
|
|
128
128
|
# If Apartment::Tenant.current is not still the default (usually 'public') then an elevator has brought us into
|
|
129
129
|
# a different tenant. If so then don't allow schema navigation.
|
|
130
|
-
if ActiveRecord::Base.connection.adapter_name
|
|
130
|
+
if ['PostgreSQL', 'PostGIS'].include?(ActiveRecord::Base.connection.adapter_name) && apartment_multitenant
|
|
131
131
|
current_schema = (ActiveRecord::Base.execute_sql('SELECT current_schemas(true)')
|
|
132
132
|
.first['current_schemas'][1..-2]
|
|
133
133
|
.split(',') - ['pg_catalog', 'pg_toast', 'heroku_ext']).first
|
|
@@ -1547,8 +1547,8 @@ module ActiveRecord
|
|
|
1547
1547
|
|
|
1548
1548
|
elsif private_instance_methods.include?(:select_association_list) # AR >= 6.1
|
|
1549
1549
|
alias _brick_select_association_list select_association_list
|
|
1550
|
-
def select_association_list(associations, stashed_joins = nil)
|
|
1551
|
-
result = _brick_select_association_list(associations, stashed_joins)
|
|
1550
|
+
def select_association_list(associations, stashed_joins = nil, &block)
|
|
1551
|
+
result = _brick_select_association_list(associations, stashed_joins, &block)
|
|
1552
1552
|
result.instance_variable_set(:@relation, self)
|
|
1553
1553
|
result
|
|
1554
1554
|
end
|
|
@@ -1686,11 +1686,11 @@ module ActiveRecord
|
|
|
1686
1686
|
if (relation = child.instance_variable_get(:@assocs)&.instance_variable_get(:@relation))
|
|
1687
1687
|
link_path = child.instance_variable_get(:@link_path)
|
|
1688
1688
|
relation.brick_links(false)[link_path] = if child.table.is_a?(Arel::Nodes::TableAlias)
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1689
|
+
child.table.right
|
|
1690
|
+
else
|
|
1691
|
+
# Was: result.first&.left&.table_alias || child.table_name
|
|
1692
|
+
child.table.table_alias || child.table_name
|
|
1693
|
+
end
|
|
1694
1694
|
end
|
|
1695
1695
|
result
|
|
1696
1696
|
end
|
|
@@ -16,6 +16,17 @@ module Brick
|
|
|
16
16
|
'double precision' => 'float',
|
|
17
17
|
'smallint' => 'integer', # %%% Need to put in "limit: 2"
|
|
18
18
|
'ARRAY' => 'string', # Note that we'll also add ", array: true"
|
|
19
|
+
# MySQL data types
|
|
20
|
+
'tinytext' => 'text', # 255 bytes
|
|
21
|
+
# 'text' => 'text', # 64kb
|
|
22
|
+
'mediumtext' => 'text', # 16mb
|
|
23
|
+
'longtext' => 'text', # 4gb
|
|
24
|
+
'tinyblob' => 'binary',
|
|
25
|
+
'blob' => 'binary',
|
|
26
|
+
'mediumblob' => 'binary',
|
|
27
|
+
'longblob' => 'binary',
|
|
28
|
+
'enum' => 'string',
|
|
29
|
+
'set' => 'string', # Note that we'll also add ", array: true"
|
|
19
30
|
# Oracle data types
|
|
20
31
|
'VARCHAR2' => 'string',
|
|
21
32
|
'CHAR' => 'string',
|
|
@@ -189,7 +200,7 @@ module Brick
|
|
|
189
200
|
# disable the final FK migration by using a ".rbx" file extension.
|
|
190
201
|
fks_extension = if after_fks.length > 500
|
|
191
202
|
minutes = (after_fks.length + 1000) / 1500
|
|
192
|
-
mig << " if ActiveRecord::Base.connection.adapter_name
|
|
203
|
+
mig << " if ['PostgreSQL', 'PostGIS'].include?(ActiveRecord::Base.connection.adapter_name)\n"
|
|
193
204
|
mig << " puts 'NOTE: It could take around #{minutes} #{'minute'.pluralize(minutes)} on a FAST machine for Postgres to do all the final processing for these foreign keys. Please be patient!'\n"
|
|
194
205
|
|
|
195
206
|
mig << " # Vacuum takes only about ten seconds when all the tables are empty,
|
|
@@ -204,7 +215,7 @@ module Brick
|
|
|
204
215
|
end
|
|
205
216
|
mig << +" end\n"
|
|
206
217
|
increment_time(mig_path, current_mig_time)
|
|
207
|
-
base_name = "_#{relations[:base_name]
|
|
218
|
+
base_name = "_#{relations[:base_name].tr(' ', '').underscore}" if relations.key?(:base_name)
|
|
208
219
|
versions_to_create << migration_file_write(mig_path, "create_brick_fks#{base_name}.#{fks_extension}", current_mig_time, ar_version, mig)
|
|
209
220
|
puts "Have written out a final migration called 'create_brick_fks#{base_name}.#{fks_extension}' which creates #{after_fks.length} foreign keys."
|
|
210
221
|
if fks_extension == 'rbx'
|
|
@@ -361,7 +372,7 @@ module Brick
|
|
|
361
372
|
SQL_TYPES.find { |r| r.first.is_a?(Regexp) && col_type.first =~ r.first }&.last ||
|
|
362
373
|
col_type.first
|
|
363
374
|
suffix = col_type[3] || pkey_cols&.include?(col) ? +', null: false' : +''
|
|
364
|
-
suffix << ', array: true' if (col_type.first
|
|
375
|
+
suffix << ', array: true' if (['ARRAY', 'set'].include?(col_type.first))
|
|
365
376
|
if !is_4x_rails && klass && (comment = klass.columns_hash.fetch(col, nil)&.comment)&.present?
|
|
366
377
|
suffix << ", comment: #{comment.inspect}"
|
|
367
378
|
end
|
|
@@ -428,7 +439,7 @@ module Brick
|
|
|
428
439
|
mig << " end\n"
|
|
429
440
|
if pk_is_also_fk
|
|
430
441
|
mig << " reversible do |dir|\n"
|
|
431
|
-
mig << " dir.up { execute('ALTER TABLE #{tbl} ADD PRIMARY KEY (#{
|
|
442
|
+
mig << " dir.up { execute('ALTER TABLE #{tbl} ADD PRIMARY KEY (#{pkey_cols.map { |pk| "\"#{pk}\"" }.join(', ')})') }\n"
|
|
432
443
|
mig << " end\n"
|
|
433
444
|
end
|
|
434
445
|
add_fks.each do |add_fk|
|
|
@@ -218,11 +218,11 @@ module Brick
|
|
|
218
218
|
data = []
|
|
219
219
|
updates = []
|
|
220
220
|
relation[:cols].each do |col, _col_type|
|
|
221
|
-
# Skip primary key columns, unless they are part of a foreign key.
|
|
221
|
+
# Skip primary key columns, unless they are part of a foreign key or a composite key.
|
|
222
222
|
# (But always add all columns if it's Airtable!)
|
|
223
223
|
next if !(fk = fkeys.find { |assoc| col == assoc[:fk] }) &&
|
|
224
224
|
!is_airtable &&
|
|
225
|
-
pkey_cols.
|
|
225
|
+
pkey_cols.first == col && orig_pk_val.is_a?(Integer)
|
|
226
226
|
|
|
227
227
|
# Used to be: obj.send(col)
|
|
228
228
|
# (and with that it was possible to raise ActiveRecord::Encryption::Errors::Configuration...)
|