brick 1.0.34 → 1.0.37
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 +25 -0
- data/lib/brick/extensions.rb +33 -22
- data/lib/brick/frameworks/rails/engine.rb +123 -62
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +3 -23
- data/lib/generators/brick/install_generator.rb +6 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0178c8135edf190cf65ae2a4b274bde10cc5410f33adab7337798d98636f810f'
|
4
|
+
data.tar.gz: c4c51e9e22548f9f49a08a7550eb003c0075b65bac70fffea82b919b7aa07131
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6ad8492e3b19f526af3cc69f53f30e3a4de0f172f73362d36f6dbac884f7137bb7a3944f99054f61279c2fdc27989e9b840e68cb48c23aa378f6ac4bd4d2cfb
|
7
|
+
data.tar.gz: def025f413aa8c89f8f603f4e3422427f9d71b10b7c57c0db6d5fb750b0e26352dc88f3d85f01b526127d54a789e6b056dc7acee64e9046909a039e576421587
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_record/version'
|
4
|
+
|
5
|
+
# ActiveRecord before 4.0 didn't have #version
|
6
|
+
unless ActiveRecord.respond_to?(:version)
|
7
|
+
module ActiveRecord
|
8
|
+
def self.version
|
9
|
+
::Gem::Version.new(ActiveRecord::VERSION::STRING)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# In ActiveSupport older than 5.0, the duplicable? test tries to new up a BigDecimal,
|
15
|
+
# and Ruby 2.6 and later deprecates #new. This removes the warning from BigDecimal.
|
16
|
+
# This compatibility needs to be put into place in the application's "config/boot.rb"
|
17
|
+
# file by having the line "require 'brick/compatibility'" to be the last line in that
|
18
|
+
# file.
|
19
|
+
require 'bigdecimal'
|
20
|
+
if ::Gem::Version.new(RUBY_VERSION) >= ::Gem::Version.new('2.6') &&
|
21
|
+
ActiveRecord.version < ::Gem::Version.new('5.0')
|
22
|
+
def BigDecimal.new(*args, **kwargs)
|
23
|
+
BigDecimal(*args, **kwargs)
|
24
|
+
end
|
25
|
+
end
|
data/lib/brick/extensions.rb
CHANGED
@@ -203,7 +203,9 @@ module ActiveRecord
|
|
203
203
|
model_underscore = name.underscore
|
204
204
|
assoc_name = CGI.escapeHTML(assoc_name.to_s)
|
205
205
|
model_path = Rails.application.routes.url_helpers.send("#{model_underscore.tr('/', '_').pluralize}_path".to_sym)
|
206
|
-
|
206
|
+
av_class = Class.new.extend(ActionView::Helpers::UrlHelper)
|
207
|
+
av_class.extend(ActionView::Helpers::TagHelper) if ActionView.version < ::Gem::Version.new('6.1')
|
208
|
+
link = av_class.link_to(name, model_path)
|
207
209
|
model_underscore == assoc_name ? link : "#{assoc_name}-#{link}".html_safe
|
208
210
|
end
|
209
211
|
|
@@ -409,7 +411,6 @@ module ActiveRecord
|
|
409
411
|
hm_counts.each do |k, hm|
|
410
412
|
associative = nil
|
411
413
|
count_column = if hm.options[:through]
|
412
|
-
# binding.pry if associatives[hm.name].nil?
|
413
414
|
fk_col = (associative = associatives[hm.name]).foreign_key
|
414
415
|
hm.foreign_key
|
415
416
|
else
|
@@ -500,8 +501,9 @@ if ActiveSupport::Dependencies.respond_to?(:autoload_module!) # %%% Only works w
|
|
500
501
|
alias _brick_autoload_module! autoload_module!
|
501
502
|
def autoload_module!(*args)
|
502
503
|
into, const_name, qualified_name, path_suffix = args
|
503
|
-
base_class_name = ::Brick.config.sti_namespace_prefixes&.fetch("::#{into.name}::", nil)
|
504
|
-
|
504
|
+
if (base_class_name = ::Brick.config.sti_namespace_prefixes&.fetch("::#{into.name}::", nil))
|
505
|
+
base_class_name = "::#{base_class_name}" unless base_class_name.start_with?('::')
|
506
|
+
end
|
505
507
|
if (base_class = base_class_name&.constantize)
|
506
508
|
::Brick.sti_models[qualified_name] = { base: base_class }
|
507
509
|
# Build subclass and place it into the specially STI-namespaced module
|
@@ -777,9 +779,12 @@ class Object
|
|
777
779
|
options = { through: through.to_sym }
|
778
780
|
if relation[:fks].any? { |k, v| v[:assoc_name] == hmt_name }
|
779
781
|
hmt_name = "#{hmt_name.singularize}_#{fk.first[:assoc_name]}"
|
780
|
-
#
|
781
|
-
options[:class_name] = fk.first[:inverse_table].singularize.camelize
|
782
|
-
options[:foreign_key] = fk.first[:fk].to_sym
|
782
|
+
# Was:
|
783
|
+
# options[:class_name] = fk.first[:inverse_table].singularize.camelize
|
784
|
+
# options[:foreign_key] = fk.first[:fk].to_sym
|
785
|
+
far_assoc = relations[fk.first[:inverse_table]][:fks].find { |_k, v| v[:assoc_name] == fk.last }
|
786
|
+
options[:class_name] = far_assoc.last[:inverse_table].singularize.camelize
|
787
|
+
options[:foreign_key] = far_assoc.last[:fk].to_sym
|
783
788
|
end
|
784
789
|
options[:source] = fk.last.to_sym unless hmt_name.singularize == fk.last
|
785
790
|
code << " has_many :#{hmt_name}#{options.map { |opt| ", #{opt.first}: #{opt.last.inspect}" }.join}\n"
|
@@ -942,7 +947,6 @@ class Object
|
|
942
947
|
}
|
943
948
|
s
|
944
949
|
end
|
945
|
-
# binding.pry
|
946
950
|
render inline: json.to_json, content_type: request.format
|
947
951
|
return
|
948
952
|
end
|
@@ -959,7 +963,8 @@ class Object
|
|
959
963
|
return
|
960
964
|
end
|
961
965
|
|
962
|
-
|
966
|
+
quoted_table_name = model.table_name.split('.').map { |x| "\"#{x}\"" }.join('.')
|
967
|
+
order = pk.each_with_object([]) { |pk_part, s| s << "#{quoted_table_name}.\"#{pk_part}\"" }
|
963
968
|
ar_relation = order.present? ? model.order("#{order.join(', ')}") : model.all
|
964
969
|
@_brick_params = ar_relation.brick_select(params, (selects = []), (bt_descrip = {}), (hm_counts = {}), (join_array = ::Brick::JoinArray.new))
|
965
970
|
# %%% Add custom HM count columns
|
@@ -974,7 +979,8 @@ class Object
|
|
974
979
|
@_brick_join_array = join_array
|
975
980
|
end
|
976
981
|
|
977
|
-
|
982
|
+
is_pk_string = nil
|
983
|
+
if (pk_col = model&.primary_key)
|
978
984
|
code << " def show\n"
|
979
985
|
code << (find_by_id = " id = params[:id]&.split(/[\\/,_]/)
|
980
986
|
id = id.first if id.is_a?(Array) && id.length == 1
|
@@ -982,7 +988,12 @@ class Object
|
|
982
988
|
code << " end\n"
|
983
989
|
self.define_method :show do
|
984
990
|
::Brick.set_db_schema(params)
|
985
|
-
id =
|
991
|
+
id = if model.columns_hash[pk_col]&.type == :string
|
992
|
+
is_pk_string = true
|
993
|
+
params[:id]
|
994
|
+
else
|
995
|
+
params[:id]&.split(/[\/,_]/)
|
996
|
+
end
|
986
997
|
id = id.first if id.is_a?(Array) && id.length == 1
|
987
998
|
instance_variable_set("@#{singular_table_name}".to_sym, model.find(id))
|
988
999
|
end
|
@@ -1021,7 +1032,7 @@ class Object
|
|
1021
1032
|
# return
|
1022
1033
|
end
|
1023
1034
|
|
1024
|
-
id = params[:id]&.split(/[\/,_]/)
|
1035
|
+
id = is_pk_string ? params[:id] : params[:id]&.split(/[\/,_]/)
|
1025
1036
|
id = id.first if id.is_a?(Array) && id.length == 1
|
1026
1037
|
instance_variable_set("@#{singular_table_name}".to_sym, (obj = model.find(id)))
|
1027
1038
|
obj = obj.first if obj.is_a?(Array)
|
@@ -1047,19 +1058,15 @@ class Object
|
|
1047
1058
|
end
|
1048
1059
|
|
1049
1060
|
def _brick_get_hm_assoc_name(relation, hm_assoc)
|
1050
|
-
if relation[:hm_counts][hm_assoc[:assoc_name]]&.> 1
|
1051
|
-
|
1052
|
-
# x.last[:alternate_name] == hm_assoc[:alternate_name] })
|
1053
|
-
# relation[:fks].any? { |k, v| v[:assoc_name] == new_alt_name }
|
1061
|
+
if (relation[:hm_counts][hm_assoc[:assoc_name]]&.> 1) &&
|
1062
|
+
hm_assoc[:alternate_name] != hm_assoc[:inverse][:assoc_name]
|
1054
1063
|
plural = ActiveSupport::Inflector.pluralize(hm_assoc[:alternate_name])
|
1055
|
-
# binding.pry if hm_assoc[:assoc_name] == 'issue_issue_duplicates'
|
1056
1064
|
new_alt_name = (hm_assoc[:alternate_name] == name.underscore) ? "#{hm_assoc[:assoc_name].singularize}_#{plural}" : plural
|
1057
1065
|
# uniq = 1
|
1058
1066
|
# while same_name = relation[:fks].find { |x| x.last[:assoc_name] == hm_assoc[:assoc_name] && x.last != hm_assoc }
|
1059
1067
|
# hm_assoc[:assoc_name] = "#{hm_assoc_name}_#{uniq += 1}"
|
1060
1068
|
# end
|
1061
1069
|
# puts new_alt_name
|
1062
|
-
# binding.pry if new_alt_name == 'issue_duplicates'
|
1063
1070
|
# hm_assoc[:assoc_name] = new_alt_name
|
1064
1071
|
[new_alt_name, true]
|
1065
1072
|
else
|
@@ -1101,9 +1108,11 @@ module ActiveRecord::ConnectionHandling
|
|
1101
1108
|
# Only for Postgres? (Doesn't work in sqlite3)
|
1102
1109
|
# puts ActiveRecord::Base.execute_sql("SELECT current_setting('SEARCH_PATH')").to_a.inspect
|
1103
1110
|
|
1111
|
+
is_postgres = nil
|
1104
1112
|
schema_sql = 'SELECT NULL AS table_schema;'
|
1105
1113
|
case ActiveRecord::Base.connection.adapter_name
|
1106
1114
|
when 'PostgreSQL'
|
1115
|
+
is_postgres = true
|
1107
1116
|
if (is_multitenant = (multitenancy = ::Brick.config.schema_behavior[:multitenant]) &&
|
1108
1117
|
(sta = multitenancy[:schema_to_analyse]) != 'public')
|
1109
1118
|
::Brick.default_schema = schema = sta
|
@@ -1151,7 +1160,8 @@ module ActiveRecord::ConnectionHandling
|
|
1151
1160
|
# %%% Retrieve internal ActiveRecord table names like this:
|
1152
1161
|
# ActiveRecord::Base.internal_metadata_table_name, ActiveRecord::Base.schema_migrations_table_name
|
1153
1162
|
# For if it's not SQLite -- so this is the Postgres and MySQL version
|
1154
|
-
sql ||= "SELECT t.table_schema AS schema, t.table_name AS relation_name, t.table_type
|
1163
|
+
sql ||= "SELECT t.table_schema AS schema, t.table_name AS relation_name, t.table_type,#{"
|
1164
|
+
pg_catalog.obj_description((t.table_schema || '.' || t.table_name)::regclass, 'pg_class') AS table_description," if is_postgres}
|
1155
1165
|
c.column_name, c.data_type,
|
1156
1166
|
COALESCE(c.character_maximum_length, c.numeric_precision) AS max_length,
|
1157
1167
|
tc.constraint_type AS const, kcu.constraint_name AS \"key\",
|
@@ -1178,7 +1188,8 @@ module ActiveRecord::ConnectionHandling
|
|
1178
1188
|
case ActiveRecord::Base.connection.adapter_name
|
1179
1189
|
when 'PostgreSQL', 'SQLite' # These bring back a hash for each row because the query uses column aliases
|
1180
1190
|
# schema ||= 'public' if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
|
1181
|
-
ActiveRecord::
|
1191
|
+
ar_imtn = ActiveRecord.version >= ::Gem::Version.new('5.0') ? ActiveRecord::Base.internal_metadata_table_name : ''
|
1192
|
+
ActiveRecord::Base.execute_sql(sql, ActiveRecord::Base.schema_migrations_table_name, ar_imtn).each do |r|
|
1182
1193
|
# If Apartment gem lists the table as being associated with a non-tenanted model then use whatever it thinks
|
1183
1194
|
# is the default schema, usually 'public'.
|
1184
1195
|
schema_name = if ::Brick.config.schema_behavior[:multitenant]
|
@@ -1189,6 +1200,7 @@ module ActiveRecord::ConnectionHandling
|
|
1189
1200
|
relation_name = schema_name ? "#{schema_name}.#{r['relation_name']}" : r['relation_name']
|
1190
1201
|
relation = relations[relation_name]
|
1191
1202
|
relation[:isView] = true if r['table_type'] == 'VIEW'
|
1203
|
+
relation[:description] = r['table_description'] if r['table_description']
|
1192
1204
|
col_name = r['column_name']
|
1193
1205
|
key = case r['const']
|
1194
1206
|
when 'PRIMARY KEY'
|
@@ -1364,7 +1376,7 @@ module Brick
|
|
1364
1376
|
is_schema = if ::Brick.config.schema_behavior[:multitenant]
|
1365
1377
|
# If Apartment gem lists the primary table as being associated with a non-tenanted model
|
1366
1378
|
# then use 'public' schema for the primary table
|
1367
|
-
if apartment&.excluded_models.include?(fk[4].singularize.camelize)
|
1379
|
+
if apartment && apartment&.excluded_models.include?(fk[4].singularize.camelize)
|
1368
1380
|
fk[3] = Apartment.default_schema
|
1369
1381
|
true
|
1370
1382
|
end
|
@@ -1446,7 +1458,6 @@ module Brick
|
|
1446
1458
|
else
|
1447
1459
|
fk[1]
|
1448
1460
|
end
|
1449
|
-
# binding.pry if inv_tbl == 'issue_issue_duplicates' # inverse_table goofed?
|
1450
1461
|
assoc_hm = hms[hm_cnstr_name] = { is_bt: false, fk: fk[2], assoc_name: for_tbl.pluralize, alternate_name: bt_assoc_name,
|
1451
1462
|
inverse_table: inv_tbl, inverse: assoc_bt }
|
1452
1463
|
assoc_hm[:polymorphic] = true if is_polymorphic
|
@@ -141,9 +141,14 @@ module Brick
|
|
141
141
|
display: none;
|
142
142
|
}
|
143
143
|
|
144
|
+
#headerTop {
|
145
|
+
position: sticky;
|
146
|
+
top: 0px;
|
147
|
+
background-color: white;
|
148
|
+
z-index: 1;
|
149
|
+
}
|
144
150
|
table {
|
145
151
|
border-collapse: collapse;
|
146
|
-
margin: 25px 0;
|
147
152
|
font-size: 0.9em;
|
148
153
|
font-family: sans-serif;
|
149
154
|
min-width: 400px;
|
@@ -216,12 +221,17 @@ input[type=submit] {
|
|
216
221
|
<% def is_bcrypt?(val)
|
217
222
|
val.is_a?(String) && val.length == 60 && val.start_with?('$2a$')
|
218
223
|
end
|
219
|
-
def hide_bcrypt(val)
|
224
|
+
def hide_bcrypt(val, max_len = 200)
|
220
225
|
if is_bcrypt?(val)
|
221
226
|
'(hidden)'
|
222
|
-
elsif val.is_a?(String) && val.encoding.name != 'UTF-8'
|
223
|
-
val[0..1000].force_encoding('UTF-8')
|
224
227
|
else
|
228
|
+
if val.is_a?(String)
|
229
|
+
if val.length > max_len
|
230
|
+
val = val[0...max_len]
|
231
|
+
val << '...'
|
232
|
+
end
|
233
|
+
val.force_encoding('UTF-8') unless val.encoding.name == 'UTF-8'
|
234
|
+
end
|
225
235
|
val
|
226
236
|
end
|
227
237
|
end %>"
|
@@ -250,40 +260,45 @@ end %>"
|
|
250
260
|
var schemaSelect = document.getElementById(\"schema\");
|
251
261
|
var tblSelect = document.getElementById(\"tbl\");
|
252
262
|
var brickSchema;
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
263
|
+
var #{table_name}HtColumns;
|
264
|
+
|
265
|
+
// This PageTransitionEvent fires when the page first loads, as well as after any other history
|
266
|
+
// transition such as when using the browser's Back and Forward buttons.
|
267
|
+
window.addEventListener(\"pageshow\", function() {
|
268
|
+
if (schemaSelect) { // First drop-down is only present if multitenant
|
269
|
+
brickSchema = changeout(location.href, \"_brick_schema\");
|
270
|
+
if (brickSchema) {
|
271
|
+
[... document.getElementsByTagName(\"A\")].forEach(function (a) { a.href = changeout(a.href, \"_brick_schema\", brickSchema); });
|
272
|
+
}
|
273
|
+
schemaSelect.value = brickSchema || \"public\";
|
274
|
+
schemaSelect.focus();
|
275
|
+
schemaSelect.addEventListener(\"change\", function () {
|
276
|
+
// If there's an ID then remove it (trim after selected table)
|
277
|
+
location.href = changeout(location.href, \"_brick_schema\", this.value, tblSelect.value);
|
278
|
+
});
|
257
279
|
}
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
form.action = changeout(form.action, \"_brick_schema\", brickSchema);
|
268
|
-
form.addEventListener('submit', function (ev) {
|
269
|
-
[... ev.target.getElementsByTagName(\"SELECT\")].forEach(function (select) {
|
270
|
-
if (select.value === \"^^^brick_NULL^^^\")
|
271
|
-
select.value = null;
|
280
|
+
[... document.getElementsByTagName(\"FORM\")].forEach(function (form) {
|
281
|
+
if (brickSchema)
|
282
|
+
form.action = changeout(form.action, \"_brick_schema\", brickSchema);
|
283
|
+
form.addEventListener('submit', function (ev) {
|
284
|
+
[... ev.target.getElementsByTagName(\"SELECT\")].forEach(function (select) {
|
285
|
+
if (select.value === \"^^^brick_NULL^^^\")
|
286
|
+
select.value = null;
|
287
|
+
});
|
288
|
+
return true;
|
272
289
|
});
|
273
|
-
return true;
|
274
290
|
});
|
275
|
-
});
|
276
291
|
|
277
|
-
if (tblSelect) {
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
}
|
286
|
-
}
|
292
|
+
if (tblSelect) { // Always present
|
293
|
+
tblSelect.value = changeout(location.href)[schemaSelect ? 1 : 0];
|
294
|
+
tblSelect.addEventListener(\"change\", function () {
|
295
|
+
var lhr = changeout(location.href, null, this.value);
|
296
|
+
if (brickSchema)
|
297
|
+
lhr = changeout(lhr, \"_brick_schema\", schemaSelect.value);
|
298
|
+
location.href = lhr;
|
299
|
+
});
|
300
|
+
}
|
301
|
+
});
|
287
302
|
|
288
303
|
function changeout(href, param, value, trimAfter) {
|
289
304
|
var hrefParts = href.split(\"?\");
|
@@ -307,6 +322,42 @@ function changeout(href, param, value, trimAfter) {
|
|
307
322
|
params[param] = value;
|
308
323
|
return hrefParts[0] + \"?\" + Object.keys(params).reduce(function (s, v) { s.push(v + \"=\" + params[v]); return s; }, []).join(\"&\");
|
309
324
|
}
|
325
|
+
|
326
|
+
// Snag first TR for sticky header
|
327
|
+
var grid = document.getElementById(\"#{table_name}\");
|
328
|
+
#{table_name}HtColumns = grid && [grid.getElementsByTagName(\"TR\")[0]];
|
329
|
+
var headerTop = document.getElementById(\"headerTop\");
|
330
|
+
function setHeaderSizes() {
|
331
|
+
// console.log(\"start\");
|
332
|
+
// See if the headerTop is already populated
|
333
|
+
// %%% Grab the TRs from headerTop, clear it out, do this stuff, add them back
|
334
|
+
headerTop.innerHTML = \"\"; // %%% Would love to not have to clear it out like this every time! (Currently doing this to support resize events.)
|
335
|
+
var isEmpty = headerTop.childElementCount === 0;
|
336
|
+
// Set up proper sizings of sticky column header
|
337
|
+
var node;
|
338
|
+
for (var j = 0; j < #{table_name}HtColumns.length; ++j) {
|
339
|
+
var row = #{table_name}HtColumns[j];
|
340
|
+
var tr = isEmpty ? document.createElement(\"TR\") : headerTop.childNodes[j];
|
341
|
+
tr.innerHTML = row.innerHTML.trim();
|
342
|
+
// Match up widths from the original column headers
|
343
|
+
for (var i = 0; i < row.childNodes.length; ++i) {
|
344
|
+
node = row.childNodes[i];
|
345
|
+
if (node.nodeType === 1) {
|
346
|
+
var style = tr.childNodes[i].style;
|
347
|
+
style.minWidth = style.maxWidth = getComputedStyle(node).width;
|
348
|
+
}
|
349
|
+
}
|
350
|
+
if (isEmpty) headerTop.appendChild(tr);
|
351
|
+
}
|
352
|
+
grid.style.marginTop = \"-\" + getComputedStyle(headerTop).height;
|
353
|
+
// console.log(\"end\");
|
354
|
+
}
|
355
|
+
if (headerTop) {
|
356
|
+
setHeaderSizes();
|
357
|
+
window.addEventListener('resize', function(event) {
|
358
|
+
setHeaderSizes();
|
359
|
+
}, true);
|
360
|
+
}
|
310
361
|
</script>"
|
311
362
|
inline = case args.first
|
312
363
|
when 'index'
|
@@ -366,7 +417,6 @@ function changeout(href, param, value, trimAfter) {
|
|
366
417
|
|
367
418
|
async function updateSignInStatus(isSignedIn) {
|
368
419
|
if (isSignedIn) {
|
369
|
-
console.log(\"turds!\");
|
370
420
|
await gapi.client.sheets.spreadsheets.create({
|
371
421
|
properties: {
|
372
422
|
title: #{table_name.inspect},
|
@@ -411,14 +461,15 @@ function changeout(href, param, value, trimAfter) {
|
|
411
461
|
<p style=\"color: green\"><%= notice %></p>#{"
|
412
462
|
<select id=\"schema\">#{schema_options}</select>" if ::Brick.config.schema_behavior[:multitenant] && ::Brick.db_schemas.length > 1}
|
413
463
|
<select id=\"tbl\">#{table_options}</select>
|
414
|
-
<h1>#{model_plural = model_name.pluralize}</h1>#{template_link}
|
415
|
-
|
416
|
-
|
464
|
+
<h1>#{model_plural = model_name.pluralize}</h1>#{template_link}<%
|
465
|
+
if (relation = Brick.relations[#{model_name}.table_name])[:description] %><%=
|
466
|
+
relation.fetch(:description, nil) %><br><%
|
467
|
+
end
|
468
|
+
if @_brick_params&.present? %>
|
417
469
|
<% if @_brick_params.length == 1 # %%% Does not yet work with composite keys
|
418
470
|
k, id = @_brick_params.first
|
419
471
|
id = id.first if id.is_a?(Array) && id.length == 1
|
420
472
|
origin = (key_parts = k.split('.')).length == 1 ? #{model_name} : #{model_name}.reflect_on_association(key_parts.first).klass
|
421
|
-
# binding.pry
|
422
473
|
if (destination_fk = Brick.relations[origin.table_name][:fks].values.find { |fk| puts fk.inspect; fk[:fk] == key_parts.last }) &&
|
423
474
|
(obj = (destination = origin.reflect_on_association(destination_fk[:assoc_name])&.klass)&.find(id)) %>
|
424
475
|
<h3>for <%= link_to \"#{"#\{obj.brick_descrip\} (#\{destination.name\})\""}, send(\"#\{destination.name.underscore.tr('/', '_')\}_path\".to_sym, id) %></h3><%
|
@@ -426,36 +477,40 @@ function changeout(href, param, value, trimAfter) {
|
|
426
477
|
end %>
|
427
478
|
(<%= link_to 'See all #{model_plural.split('::').last}', #{path_obj_name.pluralize}_path %>)
|
428
479
|
<% end %>
|
480
|
+
<br>
|
481
|
+
<table id=\"headerTop\">
|
429
482
|
<table id=\"#{table_name}\">
|
430
|
-
<thead><tr>#{'<th></th>' if pk.present?}
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
483
|
+
<thead><tr>#{'<th></th>' if pk.present?}<%
|
484
|
+
col_order = []
|
485
|
+
@#{table_name}.columns.each do |col|
|
486
|
+
col_name = col.name
|
487
|
+
next if (#{(pk || []).inspect}.include?(col_name) && col.type == :integer && !bts.key?(col_name)) ||
|
488
|
+
::Brick.config.metadata_columns.include?(col_name) || poly_cols.include?(col_name)
|
489
|
+
|
490
|
+
col_order << col_name
|
491
|
+
%><th<%= \" title = \\\"#\{col.comment}\\\"\".html_safe unless col.comment.blank? %>><%
|
492
|
+
if (bt = bts[col_name]) %>
|
436
493
|
BT <%
|
437
494
|
bt[1].each do |bt_pair| %><%=
|
438
495
|
bt_pair.first.bt_link(bt.first) %> <%
|
439
496
|
end %><%
|
440
497
|
else %><%=
|
441
|
-
|
442
|
-
end
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
</tr></thead>
|
498
|
+
col_name %><%
|
499
|
+
end
|
500
|
+
%></th><%
|
501
|
+
end
|
502
|
+
# Consider getting the name from the association -- h.first.name -- if a more \"friendly\" alias should be used for a screwy table name
|
503
|
+
%>#{hms_headers.map { |h| "<th>#{h[1]} <%= link_to('#{h[2]}', #{h.first.klass.name.underscore.tr('/', '_').pluralize}_path) %></th>" }.join
|
504
|
+
}</tr></thead>
|
448
505
|
|
449
506
|
<tbody>
|
450
507
|
<% @#{table_name}.each do |#{obj_name}| %>
|
451
508
|
<tr>#{"
|
452
509
|
<td><%= link_to '⇛', #{path_obj_name}_path(#{obj_pk}), { class: 'big-arrow' } %></td>" if obj_pk}
|
453
|
-
<%
|
454
|
-
|
455
|
-
::Brick.config.metadata_columns.include?(k) || poly_cols.include?(k) || k.start_with?('_brfk_') || (k.start_with?('_br_') && (k.length == 63 || k.end_with?('_ct'))) %>
|
510
|
+
<% col_order.each do |col_name|
|
511
|
+
val = #{obj_name}.attributes[col_name] %>
|
456
512
|
<td>
|
457
|
-
<% if (bt = bts[
|
458
|
-
<%# binding.pry # Postgres column names are limited to 63 characters %>
|
513
|
+
<% if (bt = bts[col_name]) %>
|
459
514
|
<% if bt[2] # Polymorphic?
|
460
515
|
bt_class = #{obj_name}.send(\"#\{bt.first\}_type\")
|
461
516
|
base_class = (::Brick.existing_stis[bt_class] || bt_class).constantize.base_class.name.underscore
|
@@ -464,6 +519,7 @@ function changeout(href, param, value, trimAfter) {
|
|
464
519
|
send(\"#\{base_class\}_path\".to_sym, poly_id)) if poly_id %><%
|
465
520
|
else
|
466
521
|
bt_txt = (bt_class = bt[1].first.first).brick_descrip(
|
522
|
+
# 0..62 because Postgres column names are limited to 63 characters
|
467
523
|
#{obj_name}, (descrips = @_brick_bt_descrip[bt.first][bt_class])[0..-2].map { |z| #{obj_name}.send(z.last[0..62]) }, (bt_id_col = descrips.last)
|
468
524
|
)
|
469
525
|
bt_id = #{obj_name}.send(*bt_id_col) if bt_id_col&.present? %>
|
@@ -488,20 +544,25 @@ function changeout(href, param, value, trimAfter) {
|
|
488
544
|
<p style=\"color: green\"><%= notice %></p>#{"
|
489
545
|
<select id=\"schema\">#{schema_options}</select>" if ::Brick.config.schema_behavior[:multitenant] && ::Brick.db_schemas.length > 1}
|
490
546
|
<select id=\"tbl\">#{table_options}</select>
|
491
|
-
<h1>#{model_name}: <%= (obj = @#{obj_name})&.brick_descrip || controller_name %></h1
|
492
|
-
|
547
|
+
<h1>#{model_name}: <%= (obj = @#{obj_name})&.brick_descrip || controller_name %></h1><%
|
548
|
+
if (relation = Brick.relations[#{model_name}.table_name])[:description] %><%=
|
549
|
+
relation.fetch(:description, nil) %><br><%
|
550
|
+
end
|
551
|
+
%><%= link_to '(See all #{obj_name.pluralize})', #{path_obj_name.pluralize}_path %>
|
493
552
|
<% if obj %>
|
553
|
+
<br><br>
|
494
554
|
<%= # path_options = [obj.#{pk}]
|
495
555
|
# path_options << { '_brick_schema': } if
|
496
556
|
# url = send(:#{model_name.underscore}_path, obj.#{pk})
|
497
557
|
form_for(obj.becomes(#{model_name})) do |f| %>
|
498
558
|
<table>
|
499
559
|
<% has_fields = false
|
500
|
-
@#{obj_name}.attributes.each do |k, val|
|
560
|
+
@#{obj_name}.attributes.each do |k, val|
|
561
|
+
col = #{model_name}.columns_hash[k] %>
|
501
562
|
<tr>
|
502
563
|
<% next if (#{(pk || []).inspect}.include?(k) && !bts.key?(k)) ||
|
503
564
|
::Brick.config.metadata_columns.include?(k) %>
|
504
|
-
<th class=\"show-field\"
|
565
|
+
<th class=\"show-field\"<%= \" title = \\\"#\{col.comment}\\\"\".html_safe unless col.comment.blank? %>>
|
505
566
|
<% has_fields = true
|
506
567
|
if (bt = bts[k])
|
507
568
|
# Add a final member in this array with descriptive options to be used in <select> drop-downs
|
@@ -546,7 +607,7 @@ function changeout(href, param, value, trimAfter) {
|
|
546
607
|
<% else case #{model_name}.column_for_attribute(k).type
|
547
608
|
when :string, :text %>
|
548
609
|
<% if is_bcrypt?(val) # || .readonly? %>
|
549
|
-
<%= hide_bcrypt(val) %>
|
610
|
+
<%= hide_bcrypt(val, 1000) %>
|
550
611
|
<% else %>
|
551
612
|
<div class=\"wide-input\"><%= f.text_field k.to_sym %></div>
|
552
613
|
<% end %>
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -1,25 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
|
5
|
-
# ActiveRecord before 4.0 didn't have #version
|
6
|
-
unless ActiveRecord.respond_to?(:version)
|
7
|
-
module ActiveRecord
|
8
|
-
def self.version
|
9
|
-
::Gem::Version.new(ActiveRecord::VERSION::STRING)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
# In ActiveSupport older than 5.0, the duplicable? test tries to new up a BigDecimal,
|
15
|
-
# and Ruby 2.6 and later deprecates #new. This removes the warning from BigDecimal.
|
16
|
-
require 'bigdecimal'
|
17
|
-
if (ruby_version = ::Gem::Version.new(RUBY_VERSION)) >= ::Gem::Version.new('2.6') &&
|
18
|
-
ActiveRecord.version < ::Gem::Version.new('5.0')
|
19
|
-
def BigDecimal.new(*args, **kwargs)
|
20
|
-
BigDecimal(*args, **kwargs)
|
21
|
-
end
|
22
|
-
end
|
3
|
+
require 'brick/compatibility'
|
23
4
|
|
24
5
|
# Allow ActiveRecord 4.0 and 4.1 to work with newer Ruby (>= 2.4) by avoiding a "stack level too deep"
|
25
6
|
# error when ActiveSupport tries to smarten up Numeric by messing with Fixnum and Bignum at the end of:
|
@@ -45,8 +26,8 @@ end
|
|
45
26
|
require 'brick/util'
|
46
27
|
|
47
28
|
# Allow ActiveRecord < 3.2 to work with Ruby 2.7 and later
|
48
|
-
if
|
49
|
-
|
29
|
+
if (ruby_version = ::Gem::Version.new(RUBY_VERSION)) >= ::Gem::Version.new('2.7') &&
|
30
|
+
ActiveRecord.version < ::Gem::Version.new('3.2')
|
50
31
|
# Remove circular reference for "now"
|
51
32
|
::Brick::Util._patch_require(
|
52
33
|
'active_support/values/time_zone.rb', '/activesupport',
|
@@ -132,7 +113,6 @@ module Brick
|
|
132
113
|
associatives = hms.each_with_object({}) do |hmt, s|
|
133
114
|
if (through = hmt.last.options[:through])
|
134
115
|
skip_hms[through] = nil
|
135
|
-
# binding.pry if hmt.first == :issue_issues
|
136
116
|
s[hmt.first] = hms[through] # End up with a hash of HMT names pointing to join-table associations
|
137
117
|
elsif hmt.last.inverse_of.nil?
|
138
118
|
puts "SKIPPING #{hmt.last.name.inspect}"
|
@@ -18,7 +18,8 @@ module Brick
|
|
18
18
|
desc 'Generates an initializer file for configuring Brick'
|
19
19
|
|
20
20
|
def create_initializer_file
|
21
|
-
|
21
|
+
is_brick_file = File.exist?(filename = 'config/initializers/brick.rb')
|
22
|
+
if is_brick_file && ::Brick.config.schema_behavior[:multitenant] || !is_brick_file
|
22
23
|
# See if we can make suggestions for additional_references and polymorphic associations
|
23
24
|
resembles_fks = Hash.new { |h, k| h[k] = [] }
|
24
25
|
possible_polymorphics = {}
|
@@ -223,7 +224,10 @@ module Brick
|
|
223
224
|
# # Database schema to use when analysing existing data, such as deriving a list of polymorphic classes in the case that
|
224
225
|
# # it wasn't originally specified.
|
225
226
|
# Brick.schema_behavior = :namespaced
|
226
|
-
# Brick.schema_behavior = { multitenant: { schema_to_analyse:
|
227
|
+
#{Brick.config.schema_behavior ? "Brick.schema_behavior = { multitenant: { schema_to_analyse: #{
|
228
|
+
Brick.config.schema_behavior[:multitenant][:schema_to_analyse].inspect}" :
|
229
|
+
"# Brick.schema_behavior = { multitenant: { schema_to_analyse: 'engineering'"
|
230
|
+
} } }
|
227
231
|
|
228
232
|
# # Polymorphic associations are set up by providing a model name and polymorphic association name#{poly}
|
229
233
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brick
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.37
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lorin Thwaits
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-06-
|
11
|
+
date: 2022-06-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -214,6 +214,7 @@ extensions: []
|
|
214
214
|
extra_rdoc_files: []
|
215
215
|
files:
|
216
216
|
- lib/brick.rb
|
217
|
+
- lib/brick/compatibility.rb
|
217
218
|
- lib/brick/config.rb
|
218
219
|
- lib/brick/extensions.rb
|
219
220
|
- lib/brick/frameworks/cucumber.rb
|