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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d4285ef6fb81d75bd90ceffc7d66c7fa096f04fb998da590f291f28fc9dfb45d
4
- data.tar.gz: 2d031b156fd9c82d19af9b7818387eaecdd8cfadf939cbcf3b3b479474a77b54
3
+ metadata.gz: 431e2aee4c3c199095d8475eeedcc46bd95e86a47c51623e3cea7fbbde59edcd
4
+ data.tar.gz: 32144a9a9ab6ec60ef297f27ae73e35cc891e5f9462b9beae4e7a0534ab77135
5
5
  SHA512:
6
- metadata.gz: 5967ede119f86cd92f88abb0f43bd2049eda4272c14ae7fa1c3f9ecc54c813c4c227be2d99aaa501363e42ef34a3eb5d0a0924ac4e540ab668e40a9a9d28311e
7
- data.tar.gz: ab01005e485b9335c67ba48bb01a13db78fed3ce31293122fae8fbf1317b3bc0c3197adb087ec4b125e2ff7153e52fb55d8b7fc675b1e7759233cf8d42769ac7
6
+ metadata.gz: f471bc993d97e92deae3c03e6cac9db0e350e72bd070afe5bcde1d0ca18d650b546db0d018a101009e429e9870a7e2c5e566f980c9e5b1319bc18873271c5550
7
+ data.tar.gz: 95f128f0f2a29cf0d1af1b5001eae27885b7e11ce23194e4a4da0141a0bfc059edd1917036f4addf1ee2aa4b69f763962e821ca31f9473048a6934dbecd8518e
@@ -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
- # Build out cust_cols, bt_descrip and hm_counts now so that they are available on the
408
- # model early in case the user wants to do an ORDER BY based on any of that.
409
- model._brick_calculate_bts_hms(translations, join_array) if is_add_bts || is_add_hms
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) { |kl, cc_part_term| kl.reflect_on_association(cc_part_term).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
- while cc_part_idx > 0 &&
506
- (col_alias = "br_cc_#{k}__#{cc_part[cc_part_idx..-1].map(&:to_s).join('__')}") &&
507
- used_col_aliases.key?(col_alias)
508
- cc_part_idx -= 1
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(&:to_sym) # If it's not a custom ORDER BY, just use the key
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
- @_brick_params = ar_relation.brick_select(params, (selects = []), order_by,
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
- brick_grid(@#{table_name}, @_brick_bt_descrip, @_brick_sequence, @_brick_incl, @_brick_excl,
1081
- cols, poly_cols, bts, #{hms_keys.inspect}, {#{hms_columns.join(', ')}}) %>
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 = relation.columns.each_with_object([]) do |col, s|
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
 
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 98
8
+ TINY = 99
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
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.98
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-04 00:00:00.000000000 Z
11
+ date: 2022-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord