brick 1.0.98 → 1.0.99
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/brick/extensions.rb +44 -14
- data/lib/brick/frameworks/rails/engine.rb +18 -2
- data/lib/brick/frameworks/rails/form_tags.rb +47 -2
- data/lib/brick/version_number.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 431e2aee4c3c199095d8475eeedcc46bd95e86a47c51623e3cea7fbbde59edcd
|
4
|
+
data.tar.gz: 32144a9a9ab6ec60ef297f27ae73e35cc891e5f9462b9beae4e7a0534ab77135
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f471bc993d97e92deae3c03e6cac9db0e350e72bd070afe5bcde1d0ca18d650b546db0d018a101009e429e9870a7e2c5e566f980c9e5b1319bc18873271c5550
|
7
|
+
data.tar.gz: 95f128f0f2a29cf0d1af1b5001eae27885b7e11ce23194e4a4da0141a0bfc059edd1917036f4addf1ee2aa4b69f763962e821ca31f9473048a6934dbecd8518e
|
data/lib/brick/extensions.rb
CHANGED
@@ -398,15 +398,27 @@ module ActiveRecord
|
|
398
398
|
# Links from ActiveRecord association pathing names over to real table correlation names
|
399
399
|
# that get chosen when the AREL AST tree is walked.
|
400
400
|
def brick_links
|
401
|
-
@brick_links ||= {}
|
401
|
+
@brick_links ||= { '' => table_name }
|
402
402
|
end
|
403
403
|
|
404
404
|
def brick_select(params, selects = [], order_by = nil, translations = {}, join_array = ::Brick::JoinArray.new)
|
405
405
|
is_add_bts = is_add_hms = true
|
406
406
|
|
407
|
-
|
408
|
-
|
409
|
-
|
407
|
+
if selects.empty?
|
408
|
+
# Build out cust_cols, bt_descrip and hm_counts now so that they are available on the
|
409
|
+
# model early in case the user wants to do an ORDER BY based on any of that.
|
410
|
+
model._brick_calculate_bts_hms(translations, join_array) if is_add_bts || is_add_hms
|
411
|
+
else
|
412
|
+
is_api = true
|
413
|
+
# If there are any provided selects, treat them as API columns and build them as cust_cols since they
|
414
|
+
# can be built using DSL.
|
415
|
+
# false = not polymorphic, and true = yes -- please emit_dsl
|
416
|
+
selects.each do |api_col|
|
417
|
+
pieces, my_dsl = brick_parse_dsl(join_array, [], translations, false, "[#{api_col}]", true)
|
418
|
+
_br_cust_cols[api_col.tr('.', '_')] = [pieces, my_dsl]
|
419
|
+
end
|
420
|
+
selects.clear # Now these have become custom columns
|
421
|
+
end
|
410
422
|
|
411
423
|
is_postgres = ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
|
412
424
|
is_mysql = ActiveRecord::Base.connection.adapter_name == 'Mysql2'
|
@@ -414,7 +426,7 @@ module ActiveRecord
|
|
414
426
|
is_distinct = nil
|
415
427
|
wheres = {}
|
416
428
|
params.each do |k, v|
|
417
|
-
next if ['_brick_schema', '_brick_order', 'controller', 'action'].include?(k)
|
429
|
+
next if ['_brick_schema', '_brick_order', '_brick_api', 'controller', 'action'].include?(k)
|
418
430
|
|
419
431
|
if (where_col = (ks = k.split('.')).last)[-1] == '!'
|
420
432
|
where_col = where_col[0..-2]
|
@@ -436,11 +448,14 @@ module ActiveRecord
|
|
436
448
|
|
437
449
|
# %%% Skip the metadata columns
|
438
450
|
if selects.empty? # Default to all columns
|
451
|
+
id_parts = (id_col = klass.primary_key).is_a?(Array) ? id_col : [id_col]
|
439
452
|
tbl_no_schema = table.name.split('.').last
|
440
453
|
# %%% Have once gotten this error with MSSQL referring to http://localhost:3000/warehouse/cold_room_temperatures__archive
|
441
454
|
# ActiveRecord::StatementInvalid (TinyTds::Error: DBPROCESS is dead or not enabled)
|
442
455
|
# Relevant info here: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues/402
|
443
456
|
columns.each do |col|
|
457
|
+
next if is_api && id_parts.exclude?(col.name) # Only keep the ID columns if this is an API request
|
458
|
+
|
444
459
|
col_alias = " AS #{col.name}_" if (col_name = col.name) == 'class'
|
445
460
|
selects << if is_mysql
|
446
461
|
"`#{tbl_no_schema}`.`#{col_name}`#{col_alias}"
|
@@ -490,22 +505,28 @@ module ActiveRecord
|
|
490
505
|
# binding.pry
|
491
506
|
next
|
492
507
|
end
|
493
|
-
|
494
508
|
key_klass = nil
|
495
509
|
key_tbl_name = nil
|
496
510
|
dest_pk = nil
|
497
511
|
key_alias = nil
|
498
512
|
cc.first.each do |cc_part|
|
499
|
-
dest_klass = cc_part[0..-2].inject(klass)
|
513
|
+
dest_klass = cc_part[0..-2].inject(klass) do |kl, cc_part_term|
|
514
|
+
# %%% Clear column info properly so we can do multiple subsequent requests
|
515
|
+
# binding.pry unless kl.reflect_on_association(cc_part_term)
|
516
|
+
kl.reflect_on_association(cc_part_term)&.klass || klass
|
517
|
+
end
|
500
518
|
tbl_name = rel_dupe.brick_links[cc_part[0..-2].map(&:to_s).join('.')]
|
501
519
|
# Deal with the conflict if there are two parts in the custom column named the same,
|
502
520
|
# "category.name" and "product.name" for instance will end up with aliases of "name"
|
503
521
|
# and "product__name".
|
504
|
-
cc_part_idx = cc_part.length - 1
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
522
|
+
if (cc_part_idx = cc_part.length - 1).zero?
|
523
|
+
col_alias = "br_cc_#{k}__#{table_name.tr('.', '_')}"
|
524
|
+
else
|
525
|
+
while cc_part_idx > 0 &&
|
526
|
+
(col_alias = "br_cc_#{k}__#{cc_part[cc_part_idx..-1].map(&:to_s).join('__').tr('.', '_')}") &&
|
527
|
+
used_col_aliases.key?(col_alias)
|
528
|
+
cc_part_idx -= 1
|
529
|
+
end
|
509
530
|
end
|
510
531
|
used_col_aliases[col_alias] = nil
|
511
532
|
# Set up custom column links by preparing key_klass and key_alias
|
@@ -1372,7 +1393,7 @@ class Object
|
|
1372
1393
|
when Symbol
|
1373
1394
|
order_tbl[order_default] || order_default
|
1374
1395
|
else
|
1375
|
-
pk.map(
|
1396
|
+
pk.map { |part| "#{table_name}.#{part}"}.join(', ') # If it's not a custom ORDER BY, just use the key
|
1376
1397
|
end
|
1377
1398
|
end
|
1378
1399
|
|
@@ -1568,7 +1589,15 @@ class Object
|
|
1568
1589
|
order_by, _ = model._brick_calculate_ordering(ordering, true) # Don't do the txt part
|
1569
1590
|
|
1570
1591
|
ar_relation = ActiveRecord.version < Gem::Version.new('4') ? model.preload : model.all
|
1571
|
-
|
1592
|
+
|
1593
|
+
if (cc = params['_brick_api']&.split(','))
|
1594
|
+
is_api = true
|
1595
|
+
selects = cc
|
1596
|
+
counts = [] # No need for any extra HM count columns
|
1597
|
+
model._br_cust_cols.clear
|
1598
|
+
end
|
1599
|
+
|
1600
|
+
@_brick_params = ar_relation.brick_select(params, (selects ||= []), order_by,
|
1572
1601
|
translations = {},
|
1573
1602
|
join_array = ::Brick::JoinArray.new)
|
1574
1603
|
# %%% Add custom HM count columns
|
@@ -1582,6 +1611,7 @@ class Object
|
|
1582
1611
|
"b_r_#{v.first}.c_t_ AS \"b_r_#{v.first}_ct\""
|
1583
1612
|
end
|
1584
1613
|
end
|
1614
|
+
|
1585
1615
|
ar_select = ar_relation.respond_to?(:_select!) ? ar_relation.dup._select!(*selects, *counts) : ar_relation.select(selects + counts)
|
1586
1616
|
instance_variable_set("@#{table_name.pluralize}".to_sym, ar_select)
|
1587
1617
|
if namespace && (idx = lookup_context.prefixes.index(table_name))
|
@@ -424,6 +424,14 @@ h1, h3 {
|
|
424
424
|
cursor: pointer;
|
425
425
|
}
|
426
426
|
|
427
|
+
#apiToggle {
|
428
|
+
border: 2px solid purple;
|
429
|
+
}
|
430
|
+
|
431
|
+
#apiToggle, .apiColName {
|
432
|
+
cursor: pointer;
|
433
|
+
}
|
434
|
+
|
427
435
|
#dropper {
|
428
436
|
background-color: #eee;
|
429
437
|
}
|
@@ -1004,6 +1012,9 @@ erDiagram
|
|
1004
1012
|
<p style=\"color: green\"><%= notice %></p>#{"
|
1005
1013
|
#{schema_options}" if schema_options}
|
1006
1014
|
<select id=\"tbl\">#{table_options}</select>
|
1015
|
+
|
1016
|
+
<%= pick_api(#{model_name}).html_safe %>
|
1017
|
+
|
1007
1018
|
<table id=\"resourceName\"><tr>
|
1008
1019
|
<td><h1>#{model_name}</h1></td>
|
1009
1020
|
<td id=\"imgErd\" title=\"Show ERD\"></td>
|
@@ -1077,8 +1088,13 @@ erDiagram
|
|
1077
1088
|
end
|
1078
1089
|
|
1079
1090
|
# Write out the mega-grid
|
1080
|
-
|
1081
|
-
|
1091
|
+
if params['_brick_api'] # API response?
|
1092
|
+
brick_grid(@#{table_name}, @_brick_bt_descrip, @_brick_sequence, [], @_brick_excl,
|
1093
|
+
cols, poly_cols, {}, [], {})
|
1094
|
+
else
|
1095
|
+
brick_grid(@#{table_name}, @_brick_bt_descrip, @_brick_sequence, @_brick_incl, @_brick_excl,
|
1096
|
+
cols, poly_cols, bts, #{hms_keys.inspect}, {#{hms_columns.join(', ')}})
|
1097
|
+
end %>
|
1082
1098
|
|
1083
1099
|
#{"<hr><%= link_to \"New #{obj_name}\", new_#{path_obj_name}_path %>" unless @_brick_model.is_view?}
|
1084
1100
|
#{script}
|
@@ -11,7 +11,7 @@ module Brick::Rails::FormTags
|
|
11
11
|
out << "<th x-order=\"#{pk.join(',')}\"></th>"
|
12
12
|
end
|
13
13
|
|
14
|
-
col_keys
|
14
|
+
col_keys ||= relation.columns.each_with_object([]) do |col, s|
|
15
15
|
col_name = col.name
|
16
16
|
next if inclusions&.exclude?(col_name) ||
|
17
17
|
(pk.include?(col_name) && [:integer, :uuid].include?(col.type) && !bts.key?(col_name)) ||
|
@@ -122,7 +122,7 @@ module Brick::Rails::FormTags
|
|
122
122
|
if (link_id = obj.send(cust_col.last[1]) if cust_col.last)
|
123
123
|
out << link_to(cust_txt, send("#{cust_col.last.first._brick_index(:singular)}_path", link_id))
|
124
124
|
else
|
125
|
-
out << cust_txt
|
125
|
+
out << (cust_txt || '')
|
126
126
|
end
|
127
127
|
else # Bad column name!
|
128
128
|
out << '?'
|
@@ -137,6 +137,51 @@ module Brick::Rails::FormTags
|
|
137
137
|
out.html_safe
|
138
138
|
end # brick_grid
|
139
139
|
|
140
|
+
# Recursively render UL and LI to choose columns to include
|
141
|
+
def pick_api(model, is_last = nil, visited = [])
|
142
|
+
out = +''
|
143
|
+
if visited.empty?
|
144
|
+
out << '<span id="apiToggle">API buffet</span><div id="apiBuffet" style="display: none;">'
|
145
|
+
out << '<textarea id="apiCode" cols="100"></textarea>'
|
146
|
+
out << '<input type="button" id="apiRender" value="Render">'
|
147
|
+
end
|
148
|
+
out << "\n#{indent = ' ' * visited.length}<ul>"
|
149
|
+
model.column_names.each { |col_name| out << "\n#{indent} <li class=\"apiColName\" x-nm=\"#{visited.map { |v| "#{v.last}." }.join}#{col_name}\">#{col_name}</li>" }
|
150
|
+
unless is_last || visited.length == 2
|
151
|
+
model.reflect_on_all_associations.each_with_object({}) do |v, s|
|
152
|
+
next if v.macro == :has_many || v.polymorphic?
|
153
|
+
|
154
|
+
out << "\n#{indent} <li><b>#{v.name}</b>#{pick_api(v.klass, visited.map(&:first).include?(v.klass),
|
155
|
+
visited.dup << [v.klass, v.name]
|
156
|
+
)}"
|
157
|
+
out << "\n#{indent} </li>"
|
158
|
+
s[v.name] = nil
|
159
|
+
end
|
160
|
+
end
|
161
|
+
out << "\n#{indent}</ul>"
|
162
|
+
if visited.empty?
|
163
|
+
out << '</div><script>[... document.getElementsByClassName("apiColName")].forEach(function (li) {li.addEventListener("click", apiColClick);});'
|
164
|
+
out << "
|
165
|
+
var colList = [];
|
166
|
+
var apiBuffet = document.getElementById(\"apiBuffet\");
|
167
|
+
var apiCode = document.getElementById(\"apiCode\");
|
168
|
+
function apiColClick(evt) {
|
169
|
+
apiCode.innerHTML += this.getAttribute(\"x-nm\") + \",\\n\";
|
170
|
+
}
|
171
|
+
document.getElementById(\"apiToggle\").addEventListener(\"click\", function () {
|
172
|
+
apiBuffet.style.display = (apiBuffet.style.display === \"block\" ? \"none\" : \"block\");
|
173
|
+
});
|
174
|
+
// Cheap and cheerful way to render a list of columns just for the demo
|
175
|
+
document.getElementById(\"apiRender\").addEventListener(\"click\", function () {
|
176
|
+
var changecolList = apiCode.innerHTML.substring(0, apiCode.innerHTML.length - 2);
|
177
|
+
location.href = changeout(location.href, \"_brick_api\", changecolList);
|
178
|
+
});
|
179
|
+
</script>
|
180
|
+
"
|
181
|
+
end
|
182
|
+
out
|
183
|
+
end
|
184
|
+
|
140
185
|
def link_to_brick(*args, **kwargs)
|
141
186
|
return unless ::Brick.config.mode == :on
|
142
187
|
|
data/lib/brick/version_number.rb
CHANGED
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.99
|
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-12-
|
11
|
+
date: 2022-12-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|