brick 1.0.64 → 1.0.67

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c48ee6a2f143563e2e443f6edf0dc0e04e800e8fae6951e05b0362956129e950
4
- data.tar.gz: f632f6e795dcf9b3aeb97e36a37c8074302c5967206b5f415a9a4b862bb4fda7
3
+ metadata.gz: 60ed6bcfecfc09b579a605a6141e06b958d0e274c010432be8b97980833be6fc
4
+ data.tar.gz: 4ce18cf47d569f61e58cf25d3bd26577fea4932e7171cbcf5cb7756f9d4a8cc5
5
5
  SHA512:
6
- metadata.gz: 0cd5e05899a2f780a0bbf378f8f49e49f604b90cf122f2cd7efe34839c434af814c9a228f36bd18b112cd8e40b6736e88742ea0f2a1a0b55ac3f8f573e614918
7
- data.tar.gz: a34a9f47746159f6b4b39f8a3cd994055e022be9eefe8737b73c63e5d475b283ae3b99a6a11e3faf140ca6efbf67d7f400e03147a757c237c8875f11ea2c0ea4
6
+ metadata.gz: 7691f14a41dad2cea3fcc73f60fc88a57e24ecd8ab1d69575be6b716e43f9ae15eddc6e0e1bd089ba8b3daf7cef2e78ecdaf12a0a86e249ec8f609d00b0a473d
7
+ data.tar.gz: 237aa7e873db35c6dad6c89c3641c7b9d81016520ddbbc0d1ddfc94576e067adc162c3e8a5f15c983df624e4e3d185d1e1e695a505f7b3a66bda6dd036d91e8c
@@ -257,7 +257,7 @@ module ActiveRecord
257
257
  # For our purposes a :has_one is similar enough to a :belongs_to that we can just join forces
258
258
  _br_bt_descrip[k] = { hm.klass => hm.klass.brick_parse_dsl(join_array, k, translations) }
259
259
  else # Standard :has_many
260
- _br_hm_counts[k] = hm
260
+ _br_hm_counts[k] = hm unless hm.options[:through] && !_br_associatives.fetch(hm.name, nil)
261
261
  end
262
262
  end
263
263
  end
@@ -398,7 +398,7 @@ module ActiveRecord
398
398
  if selects&.empty? # Default to all columns
399
399
  tbl_no_schema = table.name.split('.').last
400
400
  columns.each do |col|
401
- col_alias = ' AS _class' if (col_name = col.name) == 'class'
401
+ col_alias = " AS _#{col.name}" if (col_name = col.name) == 'class'
402
402
  selects << if is_mysql
403
403
  "`#{tbl_no_schema}`.`#{col_name}`#{col_alias}"
404
404
  else
@@ -479,24 +479,25 @@ module ActiveRecord
479
479
  end
480
480
  next unless count_column # %%% Would be able to remove this when multiple foreign keys to same destination becomes bulletproof
481
481
 
482
- tbl_alias = "_br_#{hm.name}"
482
+ tbl_alias = is_mysql ? "`_br_#{hm.name}`" : "\"_br_#{hm.name}\""
483
483
  pri_tbl = hm.active_record
484
+ pri_tbl_name = is_mysql ? "`#{pri_tbl.table_name}`" : "\"#{pri_tbl.table_name.gsub('.', '"."')}\""
484
485
  on_clause = []
485
486
  if fk_col.is_a?(Array) # Composite key?
486
- fk_col.each_with_index { |fk_col_part, idx| on_clause << "#{tbl_alias}.#{fk_col_part} = #{pri_tbl.table_name}.#{pri_tbl.primary_key[idx]}" }
487
+ fk_col.each_with_index { |fk_col_part, idx| on_clause << "#{tbl_alias}.#{fk_col_part} = #{pri_tbl_name}.#{pri_tbl.primary_key[idx]}" }
487
488
  selects = fk_col.dup
488
489
  else
489
490
  selects = [fk_col]
490
- on_clause << "#{tbl_alias}.#{fk_col} = #{pri_tbl.table_name}.#{pri_tbl.primary_key}"
491
+ on_clause << "#{tbl_alias}.#{fk_col} = #{pri_tbl_name}.#{pri_tbl.primary_key}"
491
492
  end
492
493
  if poly_type
493
494
  selects << poly_type
494
495
  on_clause << "#{tbl_alias}.#{poly_type} = '#{name}'"
495
496
  end
497
+ hm_table_name = is_mysql ? "`#{associative&.table_name || hm.klass.table_name}`" : "\"#{(associative&.table_name || hm.klass.table_name).gsub('.', '"."')}\""
496
498
  join_clause = "LEFT OUTER
497
499
  JOIN (SELECT #{selects.join(', ')}, COUNT(#{'DISTINCT ' if hm.options[:through]}#{count_column
498
- }) AS _ct_ FROM #{associative&.table_name || hm.klass.table_name
499
- } GROUP BY #{(1..selects.length).to_a.join(', ')}) AS #{tbl_alias}"
500
+ }) AS _ct_ FROM #{hm_table_name} GROUP BY #{(1..selects.length).to_a.join(', ')}) AS #{tbl_alias}"
500
501
  joins!("#{join_clause} ON #{on_clause.join(' AND ')}")
501
502
  end
502
503
  where!(wheres) unless wheres.empty?
@@ -656,9 +657,12 @@ Module.class_exec do
656
657
  full_class_name = +''
657
658
  full_class_name << "::#{self.name}" unless self == Object
658
659
  full_class_name << "::#{plural_class_name.underscore.singularize.camelize}"
659
- if (plural_class_name == 'BrickSwagger' ||
660
- ((::Brick.config.add_status || ::Brick.config.add_orphans) && plural_class_name == 'BrickGem') ||
661
- model = self.const_get(full_class_name))
660
+ if plural_class_name == 'BrickSwagger' ||
661
+ (
662
+ (::Brick.config.add_status || ::Brick.config.add_orphans) &&
663
+ plural_class_name == 'BrickGem'
664
+ ) ||
665
+ model = self.const_get(full_class_name)
662
666
  # if it's a controller and no match or a model doesn't really use the same table name, eager load all models and try to find a model class of the right name.
663
667
  Object.send(:build_controller, self, class_name, plural_class_name, model, relations)
664
668
  end
@@ -1016,6 +1020,7 @@ class Object
1016
1020
  table_name = ActiveSupport::Inflector.underscore(plural_class_name)
1017
1021
  singular_table_name = ActiveSupport::Inflector.singularize(table_name)
1018
1022
  pk = model&._brick_primary_key(relations.fetch(table_name, nil))
1023
+ is_mysql = ActiveRecord::Base.connection.adapter_name == 'Mysql2'
1019
1024
 
1020
1025
  namespace_name = "#{namespace.name}::" if namespace
1021
1026
  code = +"class #{namespace_name}#{class_name} < ApplicationController\n"
@@ -1031,7 +1036,7 @@ class Object
1031
1036
  self.define_method :orphans do
1032
1037
  instance_variable_set(:@orphans, ::Brick.find_orphans(::Brick.set_db_schema(params)))
1033
1038
  end
1034
- return [new_controller_class, code + ' # BrickGem controller']
1039
+ return [new_controller_class, code + "end # BrickGem controller\n"]
1035
1040
  when 'BrickSwagger'
1036
1041
  is_swagger = true # if request.format == :json)
1037
1042
  end
@@ -1119,7 +1124,9 @@ class Object
1119
1124
  @_brick_params = (ar_relation = model.all).brick_select(params, (selects = []), order_by, translations, join_array)
1120
1125
  # %%% Add custom HM count columns
1121
1126
  # %%% What happens when the PK is composite?
1122
- counts = model._br_hm_counts.each_with_object([]) { |v, s| s << "_br_#{v.first}._ct_ AS _br_#{v.first}_ct" }
1127
+ counts = model._br_hm_counts.each_with_object([]) do |v, s|
1128
+ s << (is_mysql ? "`_br_#{v.first}`._ct_ AS \"_br_#{v.first}_ct\"" : "\"_br_#{v.first}\"._ct_ AS \"_br_#{v.first}_ct\"")
1129
+ end
1123
1130
  instance_variable_set("@#{table_name}".to_sym, ar_relation.dup._select!(*selects, *counts))
1124
1131
  if namespace && (idx = lookup_context.prefixes.index(table_name))
1125
1132
  lookup_context.prefixes[idx] = "#{namespace.name.underscore}/#{lookup_context.prefixes[idx]}"
@@ -1189,6 +1196,8 @@ class Object
1189
1196
  else
1190
1197
  instance_variable_set("@#{singular_table_name}".to_sym,
1191
1198
  model.send(:create, send(params_name_sym)))
1199
+ index
1200
+ render :index
1192
1201
  end
1193
1202
  end
1194
1203
 
@@ -1525,7 +1534,9 @@ module ActiveRecord::ConnectionHandling
1525
1534
 
1526
1535
  def retrieve_schema_and_tables(sql = nil, is_postgres = nil, schema = nil)
1527
1536
  sql ||= "SELECT t.table_schema AS \"schema\", t.table_name AS relation_name, t.table_type,#{"
1528
- pg_catalog.obj_description((t.table_schema || '.' || t.table_name)::regclass, 'pg_class') AS table_description," if is_postgres}
1537
+ pg_catalog.obj_description(
1538
+ ('\"' || t.table_schema || '\".\"' || t.table_name || '\"')::regclass, 'pg_class'
1539
+ ) AS table_description," if is_postgres}
1529
1540
  c.column_name, c.data_type,
1530
1541
  COALESCE(c.character_maximum_length, c.numeric_precision) AS max_length,
1531
1542
  tc.constraint_type AS const, kcu.constraint_name AS \"key\",
@@ -1595,6 +1606,8 @@ module Brick
1595
1606
  "#{bt_assoc_name}_bt"
1596
1607
  end
1597
1608
  end
1609
+ bt_assoc_name = "_#{bt_assoc_name}" if bt_assoc_name == 'attribute'
1610
+
1598
1611
  # %%% Temporary schema patch
1599
1612
  for_tbl = fk[1]
1600
1613
  apartment = Object.const_defined?('Apartment') && Apartment
@@ -96,12 +96,13 @@ module Brick
96
96
 
97
97
  alias :_brick_find_template :find_template
98
98
  def find_template(*args, **options)
99
- unless (model_name = (
99
+ unless (is_status = ::Brick.config.add_status && args[0..1] == ['status', ['brick_gem']]) ||
100
+ (is_orphans = ::Brick.config.add_orphans && args[0..1] == ['orphans', ['brick_gem']]) ||
101
+ (model_name = (
100
102
  @_brick_model ||
101
- (ActionView.version < ::Gem::Version.new('5.0') && args[1].is_a?(Array) ? set_brick_model(args) : nil)
102
- )&.name) ||
103
- (is_status = ::Brick.config.add_status && args[0..1] == ['status', ['brick_gem']]) ||
104
- (is_orphans = ::Brick.config.add_orphans && args[0..1] == ['orphans', ['brick_gem']])
103
+ # Used to also have: ActionView.version < ::Gem::Version.new('5.0') &&
104
+ (args[1].is_a?(Array) ? set_brick_model(args) : nil)
105
+ )&.name)
105
106
  return _brick_find_template(*args, **options)
106
107
  end
107
108
 
@@ -118,7 +119,9 @@ module Brick
118
119
  hm_stuff = [(hm_assoc = hm.last),
119
120
  "H#{hm_assoc.macro == :has_one ? 'O' : 'M'}#{'T' if hm_assoc.options[:through]}",
120
121
  (assoc_name = hm.first)]
121
- hm_fk_name = if hm_assoc.options[:through]
122
+ hm_fk_name = if (through = hm_assoc.options[:through])
123
+ next unless @_brick_model.instance_methods.include?(through)
124
+
122
125
  associative = @_brick_model._br_associatives[hm.first]
123
126
  tbl_nm = if hm_assoc.options[:source]
124
127
  associative.klass.reflect_on_association(hm_assoc.options[:source]).inverse_of&.name
@@ -154,7 +157,7 @@ module Brick
154
157
  end
155
158
  hm_entry << ']'
156
159
  hms_columns << hm_entry
157
- when 'show', 'update'
160
+ when 'show', 'new', 'update'
158
161
  hm_stuff << if hm_fk_name
159
162
  "<%= link_to '#{assoc_name}', #{hm_assoc.klass.name.underscore.tr('/', '_').pluralize}_path({ #{path_keys(hm_assoc, hm_fk_name, "@#{obj_name}", pk)} }) %>\n"
160
163
  else # %%% Would be able to remove this when multiple foreign keys to same destination becomes bulletproof
@@ -177,13 +180,14 @@ module Brick
177
180
  end.keys.sort.each_with_object(+'') do |v, s|
178
181
  s << "<option value=\"#{v.underscore.gsub('.', '/').pluralize}\">#{v}</option>"
179
182
  end.html_safe
183
+ table_options << '<option value="brick_status">(Status)</option>'.html_safe
180
184
  table_options << '<option value="brick_orphans">(Orphans)</option>'.html_safe if is_orphans
181
185
  css = +"<style>
182
186
  h1, h3 {
183
187
  margin-bottom: 0;
184
188
  }
185
189
  #imgErd {
186
- background-image:url(assets/brick_erd.png);
190
+ background-image:url(/assets/brick_erd.png);
187
191
  background-size: 100% 100%;
188
192
  width: 2.2em;
189
193
  height: 2.2em;
@@ -363,8 +367,8 @@ def display_value(col_type, val)
363
367
  @is_mysql = ActiveRecord::Base.connection.adapter_name == 'Mysql2' if @is_mysql.nil?
364
368
  if @is_mysql
365
369
  # MySQL's \"Internal Geometry Format\" is like WKB, but with an initial 4 bytes that indicates the SRID.
366
- srid = val[..3].unpack('I')
367
- val = val[4..]
370
+ srid = val[0..3].unpack('I')
371
+ val = val[4..-1]
368
372
  end
369
373
  RGeo::WKRep::WKBParser.new.parse(val)
370
374
  else
@@ -377,9 +381,10 @@ def display_value(col_type, val)
377
381
  '?'
378
382
  end
379
383
  end
380
- end %>"
384
+ end
385
+ callbacks = {} %>"
381
386
 
382
- if ['index', 'show', 'update'].include?(args.first)
387
+ if ['index', 'show', 'new', 'update'].include?(args.first)
383
388
  poly_cols = []
384
389
  css << "<% bts = { #{
385
390
  bt_items = bts.each_with_object([]) do |v, s|
@@ -534,6 +539,66 @@ if (headerTop) {
534
539
  }, true);
535
540
  }
536
541
  </script>"
542
+
543
+ erd_markup = if @_brick_model
544
+ "<div id=\"mermaidErd\" class=\"mermaid\">
545
+ erDiagram
546
+ <% model_short_name = #{@_brick_model.name.split('::').last.inspect}
547
+ @_brick_bt_descrip&.each do |bt|
548
+ bt_class = bt[1].first.first
549
+ callbacks[bt_name = bt_class.name.split('::').last] = bt_class
550
+ is_has_one = #{@_brick_model.name}.reflect_on_association(bt.first).inverse_of&.macro == :has_one ||
551
+ ::Brick.config.has_ones&.fetch('#{@_brick_model.name}', nil)&.key?(bt.first.to_s)
552
+ %> <%= \"#\{model_short_name} #\{is_has_one ? '||' : '}o'}--|| #\{bt_name} : \\\"#\{
553
+ bt.first unless bt.first.to_s == bt[1].first.first.name.underscore.singularize.tr('/', '_')
554
+ }\\\"\".html_safe %>
555
+ <% end
556
+ last_through = nil
557
+ @_brick_hm_counts&.each do |hm|
558
+ # Skip showing self-referencing HM links since they would have already been drawn while evaluating the BT side
559
+ next if (hm_class = hm.last&.klass) == #{@_brick_model.name}
560
+
561
+ callbacks[hm_name = hm_class.name.split('::').last] = hm_class
562
+ if (through = hm.last.options[:through]&.to_s) # has_many :through (HMT)
563
+ callbacks[through.singularize.camelize] = (through_assoc = hm.last.source_reflection).active_record
564
+ if last_through == through # Same HM, so no need to build it again, and for clarity just put in a blank line
565
+ %><%= \"\n\"
566
+ %><% else
567
+ %> <%= \"#\{model_short_name} ||--o{ #\{through_assoc.active_record.name}\".html_safe %> : \"\"
568
+ <% last_through = through
569
+ end
570
+ %> <%= \"#\{through_assoc.active_record.name} }o--|| #\{hm_name}\".html_safe %> : \"\"
571
+ <%= \"#\{model_short_name} }o..o{ #\{hm_name} : \\\"#\{hm.first}\\\"\".html_safe %><%
572
+ else # has_many
573
+ %> <%= \"#\{model_short_name} ||--o{ #\{hm_name} : \\\"#\{
574
+ hm_name unless hm.first.to_s == hm_class.name.underscore.pluralize.tr('/', '_')
575
+ }\\\"\".html_safe %><%
576
+ end %>
577
+ <% end
578
+ callbacks.merge({model_short_name => #{@_brick_model.name}}).each do |cb_k, cb_class|
579
+ cb_relation = ::Brick.relations[cb_class.table_name]
580
+ pkeys = cb_relation[:pkey]&.first&.last
581
+ fkeys = cb_relation[:fks]&.values&.each_with_object([]) { |fk, s| s << fk[:fk] if fk.fetch(:is_bt, nil) }
582
+ %> <%= cb_k %> {<%
583
+ pkeys&.each do |pk| %>
584
+ <%= \"int #\{pk} \\\"PK#\{' fk' if fkeys&.include?(pk)}\\\"\".html_safe %><%
585
+ end %><%
586
+ fkeys&.each do |fk|
587
+ if fk.is_a?(Array)
588
+ fk.each do |fk_part| %>
589
+ <%= \"int #\{fk_part} \\\"&nbsp;&nbsp;&nbsp;&nbsp;fk\\\"\".html_safe unless pkeys&.include?(fk_part) %><%
590
+ end
591
+ else %>
592
+ <%= \"int #\{fk} \\\"&nbsp;&nbsp;&nbsp;&nbsp;fk\\\"\".html_safe unless pkeys&.include?(fk) %><%
593
+ end
594
+ end %>
595
+ }
596
+ <% end
597
+ # callback < %= cb_k % > erdClick
598
+ %>
599
+ </div>
600
+ "
601
+ end
537
602
  inline = case args.first
538
603
  when 'index'
539
604
  obj_pk = if pk&.is_a?(Array) # Composite primary key?
@@ -670,68 +735,9 @@ if (headerTop) {
670
735
  });
671
736
  });
672
737
  </script>
673
- <% end
674
- if true # @_brick_erd
675
- %><div id=\"mermaidErd\" class=\"mermaid\">
676
- erDiagram
677
- <% model_short_name = #{@_brick_model.name.split('::').last.inspect}
678
- callbacks = {}
679
- @_brick_bt_descrip.each do |bt|
680
- bt_class = bt[1].first.first
681
- callbacks[bt_name = bt_class.name.split('::').last] = bt_class
682
- is_has_one = #{@_brick_model.name}.reflect_on_association(bt.first).inverse_of&.macro == :has_one ||
683
- ::Brick.config.has_ones&.fetch('#{@_brick_model.name}', nil)&.key?(bt.first.to_s)
684
- %> <%= \"#\{model_short_name} #\{is_has_one ? '||' : '}o'}--|| #\{bt_name} : \\\"#\{
685
- bt.first unless bt.first.to_s == bt[1].first.first.name.underscore.singularize.tr('/', '_')
686
- }\\\"\".html_safe %>
687
- <% end
688
- last_through = nil
689
- @_brick_hm_counts.each do |hm|
690
- # Skip showing self-referencing HM links since they would have already been drawn while evaluating the BT side
691
- next if (hm_class = hm.last.klass) == #{@_brick_model.name}
692
-
693
- callbacks[hm_name = hm_class.name.split('::').last] = hm_class
694
- if (through = hm.last.options[:through]&.to_s) # has_many :through (HMT)
695
- callbacks[through.singularize.camelize] = (through_assoc = hm.last.source_reflection).active_record
696
- if last_through == through # Same HM, so no need to build it again, and for clarity just put in a blank line
697
- %><%= \"\n\"
698
- %><% else
699
- %> <%= \"#\{model_short_name} ||--o{ #\{through_assoc.active_record.name}\".html_safe %> : \"\"
700
- <% last_through = through
701
- end
702
- %> <%= \"#\{through_assoc.active_record.name} }o--|| #\{hm_name}\".html_safe %> : \"\"
703
- <%= \"#\{model_short_name} }o..o{ #\{hm_name} : \\\"#\{hm.first}\\\"\".html_safe %><%
704
- else # has_many
705
- %> <%= \"#\{model_short_name} ||--o{ #\{hm_name} : \\\"#\{
706
- hm_name unless hm.first.to_s == hm_class.name.underscore.pluralize.tr('/', '_')
707
- }\\\"\".html_safe %><%
708
- end %>
709
- <% end
710
- callbacks.merge({model_short_name => #{@_brick_model.name}}).each do |cb_k, cb_class|
711
- cb_relation = ::Brick.relations[cb_class.table_name]
712
- pkeys = cb_relation[:pkey]&.first&.last
713
- fkeys = cb_relation[:fks]&.values&.each_with_object([]) { |fk, s| s << fk[:fk] if fk.fetch(:is_bt, nil) }
714
- %> <%= cb_k %> {<%
715
- pkeys&.each do |pk| %>
716
- <%= \"int #\{pk} \\\"PK#\{' fk' if fkeys&.include?(pk)}\\\"\".html_safe %><%
717
- end %><%
718
- fkeys&.each do |fk|
719
- if fk.is_a?(Array)
720
- fk.each do |fk_part| %>
721
- <%= \"int #\{fk_part} \\\"&nbsp;&nbsp;&nbsp;&nbsp;fk\\\"\".html_safe unless pkeys&.include?(fk_part) %><%
722
- end
723
- else %>
724
- <%= \"int #\{fk} \\\"&nbsp;&nbsp;&nbsp;&nbsp;fk\\\"\".html_safe unless pkeys&.include?(fk) %><%
725
- end
726
- end %>
727
- }
728
- <% end
729
- # callback < %= cb_k % > erdClick
730
- %>
731
- </div>
732
- <% end
733
-
734
- %><table id=\"headerTop\"></table>
738
+ <% end %>
739
+ #{erd_markup}
740
+ <table id=\"headerTop\"></table>
735
741
  <table id=\"#{table_name}\" class=\"shadow\">
736
742
  <thead><tr>#{"<th x-order=\"#{pk.join(',')}\"></th>" if pk.present?}<%=
737
743
  # Consider getting the name from the association -- hm.first.name -- if a more \"friendly\" alias should be used for a screwy table name
@@ -888,7 +894,7 @@ erDiagram
888
894
  #{script}"
889
895
  end
890
896
 
891
- when 'show', 'update'
897
+ when 'show', 'new', 'update'
892
898
  +"#{css}
893
899
 
894
900
  <svg id=\"revertTemplate\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"
@@ -905,6 +911,7 @@ if (description = (relation = Brick.relations[#{model_name}.table_name])&.fetch(
905
911
  description %><br><%
906
912
  end
907
913
  %><%= link_to '(See all #{obj_name.pluralize})', #{path_obj_name.pluralize}_path %>
914
+ #{erd_markup}
908
915
  <% if obj %>
909
916
  <br><br>
910
917
  <%= # path_options = [obj.#{pk}]
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 64
8
+ TINY = 67
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.64
4
+ version: 1.0.67
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-08-28 00:00:00.000000000 Z
11
+ date: 2022-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord