brick 1.0.131 → 1.0.133

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: 6e9356edd43a6af6120f30bfbcd520383f3ae700e6ff04be11ebdd3493852ef4
4
- data.tar.gz: a099075c53acc9bf29c718043cc619b5ab4f895366f9c7ddd14d53c8f7f432b8
3
+ metadata.gz: 6804b443d939d24da85968d5b75c4c0603c8880dcc5ab4d07b20be0a52e5a349
4
+ data.tar.gz: 17ed154ec5f8ec1f351a83120673e9354f892217da76957fdc49a31e663e9eba
5
5
  SHA512:
6
- metadata.gz: 9f9df598bad9ce128a88f4fe364d568be8c38eee57e595024866d39a255b42f513a26adc68d64d14cdecd4b5d13fb7424935f17df7dbb41c3bda2ae31057a4c7
7
- data.tar.gz: 845e5747a916a338ee494426e4ef0ac6fd5c65c3579df0210c8a80468887fac12103407acfbaee3659b3b45763f98ef0bd109935d70920b932b4fd41cc15fdc5
6
+ metadata.gz: 1b4e53fe24d3de942a7388453d6ee732b0263097b08cbed104d7499842ffaa4eb7239b1bdb81b7300d08df9a628b2a99aad74f47de1fd3579b1eefbf0382b18a
7
+ data.tar.gz: 3eb38e2a8f1e5c12493ff6e3a524d42157dcae2781d6d39f339d098b04b12d936989f3974977df589419ca04663a4c27f6b7425e09b9695817d9103fb7fd543f
data/lib/brick/config.rb CHANGED
@@ -258,7 +258,9 @@ module Brick
258
258
  else
259
259
  # Custom STI type columns for models built from specific tables
260
260
  (v.last.is_a?(Array) ? v.last : [v.last]).each do |table|
261
- ::Brick.relations[table][:sti_col] = v.first
261
+ if (relation = ::Brick.relations.fetch(table, nil))
262
+ relation[:sti_col] = v.first
263
+ end
262
264
  end
263
265
  end
264
266
  end
@@ -44,9 +44,20 @@
44
44
 
45
45
  module ActiveRecord
46
46
  class Base
47
+ @_brick_inheriteds = {}
47
48
  class << self
48
49
  attr_reader :_brick_relation
49
50
 
51
+ def _brick_inheriteds
52
+ @_brick_inheriteds ||= ::ActiveRecord::Base.instance_variable_get(:@_brick_inheriteds)
53
+ end
54
+
55
+ # Track the file(s) in which each model is defined
56
+ def inherited(model)
57
+ (_brick_inheriteds[model] ||= []) << caller.first.split(':')[0..1] unless caller.first.include?('/lib/brick/extensions.rb:')
58
+ super
59
+ end
60
+
50
61
  def is_brick?
51
62
  instance_variables.include?(:@_brick_built) && instance_variable_get(:@_brick_built)
52
63
  end
@@ -2743,31 +2754,15 @@ module Brick
2743
2754
  end
2744
2755
  end
2745
2756
  abstract_activerecord_bases = ::Brick.eager_load_classes(true)
2746
- models = if Dir.exist?(model_path = "#{rails_root}/app/models")
2747
- Dir["#{model_path}/**/*.rb"].each_with_object({}) do |path, s|
2748
- modules = []
2749
- File.read(path).split("\n").each do |line|
2750
- # Capture a list of modules leading up to this class
2751
- if line.lstrip.start_with?('module ') && (idx = line.index('module'))
2752
- modules << line[idx + 6..-1].match(/[\s:]+([\w:]+)/)&.captures&.first
2753
- end
2754
- # For all non-commented lines, look for any that start with "class " and also "< ApplicationRecord"
2755
- if line.lstrip.start_with?('class ') && (idx = line.index('class')) &&
2756
- (model_name = line[idx + 5..-1].match(/[\s:]+([\w:]+)/)&.captures&.first)
2757
- # Prefix model class name with module names, if any
2758
- model_name = modules.map{|m| "#{m}::"}.join + model_name
2759
- unless abstract_activerecord_bases.include?(model_name)
2760
- klass = begin
2761
- model_name.constantize
2762
- rescue
2763
- end
2764
- s[model_name.underscore.tr('/', '.').pluralize] = [
2765
- path.start_with?(rails_root) ? path[rails_root.length + 1..-1] : path,
2766
- klass
2767
- ]
2768
- end
2769
- end
2757
+ rails_root = ::Rails.root.to_s
2758
+ models = ::Brick.relations.each_with_object({}) do |rel, s|
2759
+ begin
2760
+ if (model = rel.last[:class_name]&.constantize) &&
2761
+ (inh = ActiveRecord::Base._brick_inheriteds[model]&.join(':'))
2762
+ inh = inh[rails_root.length + 1..-1] if inh.start_with?(rails_root)
2763
+ s[rel.first] = [inh, model]
2770
2764
  end
2765
+ rescue
2771
2766
  end
2772
2767
  end
2773
2768
  ::Brick.relations.map do |k, v|
@@ -2781,7 +2776,8 @@ module Brick
2781
2776
  v[:class_name].constantize.table_name
2782
2777
  rescue
2783
2778
  end
2784
- [k, table_name || k, migrations&.fetch(res, nil), model&.first]
2779
+ model = model.first if model.is_a?(Array)
2780
+ [k, table_name || k, migrations&.fetch(res, nil), model]
2785
2781
  end
2786
2782
  end
2787
2783
 
@@ -3,7 +3,7 @@
3
3
  module Brick
4
4
  module Rails
5
5
  class << self
6
- def display_value(col_type, val)
6
+ def display_value(col_type, val, lat_lng = nil)
7
7
  is_mssql_geography = nil
8
8
  # Some binary thing that really looks like a Microsoft-encoded WGS84 point? (With the first two bytes, E6 10, indicating an EPSG code of 4326)
9
9
  if col_type == :binary && val && val.length < 31 && (val.length - 6) % 8 == 0 && val[0..5].bytes == [230, 16, 0, 0, 1, 12]
@@ -61,14 +61,21 @@ module Brick
61
61
  ::Brick::Rails.display_binary(val)
62
62
  else
63
63
  if col_type
64
- ::Brick::Rails::FormBuilder.hide_bcrypt(val, col_type == :xml)
64
+ if lat_lng && !(lat_lng.first.zero? && lat_lng.last.zero?)
65
+ # Create a link to this style of Google maps URL: https://www.google.com/maps/place/38.7071296+-121.2810649/@38.7071296,-121.2810649,12z
66
+ "<a href=\"https://www.google.com/maps/place/#{lat_lng.first}+#{lat_lng.last}/@#{lat_lng.first},#{lat_lng.last},12z\" target=\"blank\">#{val}</a>"
67
+ elsif val.is_a?(Numeric)
68
+ ::ActiveSupport::NumberHelper.number_to_delimited(val, delimiter: ',')
69
+ else
70
+ ::Brick::Rails::FormBuilder.hide_bcrypt(val, col_type == :xml)
71
+ end
65
72
  else
66
73
  '?'
67
74
  end
68
75
  end
69
76
  end
70
77
 
71
- def display_binary(val)
78
+ def display_binary(val, max_size = 100_000)
72
79
  return unless val
73
80
 
74
81
  @image_signatures ||= { (+"\xFF\xD8\xFF\xEE").force_encoding('ASCII-8BIT') => 'jpeg',
@@ -94,15 +101,12 @@ module Brick
94
101
  val = val[object_start...object_start + real_object_size]
95
102
  end
96
103
 
97
- if (signature = @image_signatures.find { |k, _v| val[0...k.length] == k }) ||
98
- (val[0..3] == 'RIFF' && val[8..11] == 'WEBP' && (signature = 'webp'))
99
- if val.length < 500_000
100
- "<img src=\"data:image/#{signature.last};base64,#{Base64.encode64(val)}\">"
101
- else
102
- "&lt;&nbsp;#{signature.last} image, #{val.length} bytes&nbsp;>"
103
- end
104
+ if ((signature = @image_signatures.find { |k, _v| val[0...k.length] == k }&.last) ||
105
+ (val[0..3] == 'RIFF' && val[8..11] == 'WEBP' && binding.local_variable_set(:signature, 'webp'))) &&
106
+ val.length < max_size
107
+ "<img src=\"data:image/#{signature.last};base64,#{Base64.encode64(val)}\">"
104
108
  else
105
- "&lt;&nbsp;Binary, #{val.length} bytes&nbsp;>"
109
+ "&lt;&nbsp;#{signature ? "#{signature} image" : 'Binary'}, #{val.length} bytes&nbsp;>"
106
110
  end
107
111
  end
108
112
  end
@@ -920,6 +924,9 @@ a.big-arrow {
920
924
  background-color: #C0C0C0;
921
925
  text-align: center;
922
926
  }
927
+ .right {
928
+ text-align: right;
929
+ }
923
930
  .orphan {
924
931
  color: red;
925
932
  white-space: nowrap;
@@ -1108,6 +1115,14 @@ if (headerTop) {
1108
1115
  setHeaderSizes();
1109
1116
  }, true);
1110
1117
  }
1118
+ // Cause descriptive text to use the same font as the resource
1119
+ var brickFontFamily = document.getElementById(\"resourceName\").computedStyleMap().get(\"font-family\");
1120
+ if (window.brickFontFamily) {
1121
+ [...document.getElementsByClassName(\"__brick\")].forEach(function (x){
1122
+ if (!x.style.fontFamily)
1123
+ x.style.fontFamily = brickFontFamily.toString();
1124
+ });
1125
+ }
1111
1126
  </script>"
1112
1127
 
1113
1128
  erd_markup = if @_brick_model
@@ -1352,8 +1367,8 @@ end
1352
1367
  %><%= if (page_num = @#{table_name}._brick_page_num)
1353
1368
  \"<tr><td colspan=\\\"#\{td_count}\\\">Page #\{page_num}</td></tr>\".html_safe
1354
1369
  end %></table>#{template_link}<%
1355
- if description.present? %><%=
1356
- description %><br><%
1370
+ if description.present? %><span class=\"__brick\"><%=
1371
+ description %></span><br><%
1357
1372
  end
1358
1373
  # FILTER PARAMETERS
1359
1374
  if @_brick_params&.present? %>
@@ -1364,12 +1379,12 @@ end
1364
1379
  if (destination_fk = Brick.relations[origin.table_name][:fks].values.find { |fk| fk[:fk] == key_parts.last }) &&
1365
1380
  (objs = (destination = origin.reflect_on_association(destination_fk[:assoc_name])&.klass)&.find(id))
1366
1381
  objs = [objs] unless objs.is_a?(Array) %>
1367
- <h3>for <% objs.each do |obj| %><%=
1382
+ <h3 class=\"__brick\">for <% objs.each do |obj| %><%=
1368
1383
  link_to \"#{"#\{obj.brick_descrip\} (#\{destination.name\})\""}, send(\"#\{destination._brick_index(:singular)\}_path\".to_sym, id)
1369
1384
  %><% end %></h3><%
1370
1385
  end
1371
1386
  end %>
1372
- (<%= link_to \"See all #\{model.base_class.name.split('::').last.pluralize}\", #{@_brick_model._brick_index}_path %>)
1387
+ <span class=\"__brick\">(<%= link_to \"See all #\{model.base_class.name.split('::').last.pluralize}\", #{@_brick_model._brick_index}_path %>)</span>
1373
1388
  <% end
1374
1389
  # COLUMN EXCLUSIONS
1375
1390
  if @_brick_excl&.present? %>
@@ -1420,7 +1435,7 @@ end
1420
1435
  cols, poly_cols, bts, #{hms_keys.inspect}, {#{hms_columns.join(', ')}}) %>
1421
1436
 
1422
1437
  #{"<hr><%= link_to(\"New #{new_path_name = "new_#{path_obj_name}_path"
1423
- obj_name}\", #{new_path_name}) if respond_to?(:#{new_path_name}) %>" unless @_brick_model.is_view?}
1438
+ obj_name}\", #{new_path_name}, { class: '__brick' }) if respond_to?(:#{new_path_name}) %>" unless @_brick_model.is_view?}
1424
1439
  #{script}
1425
1440
  </body>
1426
1441
  </html>
@@ -1532,7 +1547,7 @@ end
1532
1547
  <p style=\"color: green\"><%= notice if request.respond_to?(:flash) %></p>#{"
1533
1548
  #{schema_options}" if schema_options}
1534
1549
  <select id=\"tbl\">#{table_options}</select>
1535
- <table><td><h1><%= page_title %></h1></td>
1550
+ <table id=\"resourceName\"><td><h1><%= page_title %></h1></td>
1536
1551
  <% if Object.const_defined?('Avo') && ::Avo.respond_to?(:railtie_namespace) %>
1537
1552
  <td><%= link_to_brick(
1538
1553
  avo_svg,
@@ -1558,10 +1573,10 @@ end
1558
1573
  end %>
1559
1574
  </table>
1560
1575
  <%
1561
- if (description = (relation = Brick.relations[#{model_name}.table_name])&.fetch(:description, nil)) %><%=
1562
- description %><br><%
1576
+ if (description = (relation = Brick.relations[#{model_name}.table_name])&.fetch(:description, nil)) %>
1577
+ <span class=\"__brick\"><%= description %></span><br><%
1563
1578
  end
1564
- %><%= link_to \"(See all #\{model_name.pluralize})\", see_all_path %>
1579
+ %><%= link_to \"(See all #\{model_name.pluralize})\", see_all_path, { class: '__brick' } %>
1565
1580
  #{erd_markup}
1566
1581
  <% if obj
1567
1582
  # path_options = [obj.#{pk}]
@@ -1636,16 +1651,17 @@ end
1636
1651
  <tr><td colspan=\"2\">(No displayable fields)</td></tr>
1637
1652
  <% end %>
1638
1653
  </table>#{
1639
- "<%= binary = begin
1640
- ::Brick::Rails.display_binary(obj&.blob&.download)&.html_safe
1641
- rescue
1642
- end %>" if model_name == 'ActiveStorage::Attachment'}
1654
+ "<%= begin
1655
+ ::Brick::Rails.display_binary(obj&.blob&.download, 500_000)&.html_safe
1656
+ rescue
1657
+ end %>" if model_name == 'ActiveStorage::Attachment'}
1643
1658
  <% end %>
1644
1659
 
1645
1660
  #{unless args.first == 'new'
1646
1661
  # Was: confirm_are_you_sure = ActionView.version < ::Gem::Version.new('7.0') ? "data: { confirm: 'Delete #\{model_name} -- Are you sure?' }" : "form: { data: { turbo_confirm: 'Delete #\{model_name} -- Are you sure?' } }"
1647
1662
  confirm_are_you_sure = "data: { confirm: 'Delete #\{model_name} -- Are you sure?' }"
1648
- hms_headers.each_with_object(+'') do |hm, s|
1663
+ ret = +"<%= button_to(\"Delete #\{@#{obj_name}.brick_descrip}\", send(\"#\{#{model_name}._brick_index(:singular)}_path\".to_sym, @#{obj_name}), { method: 'delete', class: 'danger', #{confirm_are_you_sure} }) %>"
1664
+ hms_headers.each_with_object(ret) do |hm, s|
1649
1665
  # %%% Would be able to remove this when multiple foreign keys to same destination becomes bulletproof
1650
1666
  next if hm.first.options[:through] && !hm.first.through_reflection
1651
1667
 
@@ -1674,7 +1690,7 @@ end
1674
1690
  collection = collection.instance_exec(&assoc.scopes.first) if assoc.scopes.present?
1675
1691
  if assoc.klass.name == 'ActiveStorage::Attachment'
1676
1692
  br_descrip = begin
1677
- ::Brick::Rails.display_binary(obj.send(assoc.name)&.blob&.download)&.html_safe
1693
+ ::Brick::Rails.display_binary(obj.send(assoc.name)&.blob&.download, 500_000)&.html_safe
1678
1694
  rescue
1679
1695
  end
1680
1696
  end
@@ -1705,8 +1721,7 @@ end
1705
1721
  else
1706
1722
  s
1707
1723
  end
1708
- end +
1709
- "<%= button_to(\"Delete #\{@#{obj_name}.brick_descrip}\", send(\"#\{#{model_name}._brick_index(:singular)}_path\".to_sym, @#{obj_name}), { method: 'delete', class: 'danger', #{confirm_are_you_sure} }) %>"
1724
+ end
1710
1725
  end}
1711
1726
  <% end %>
1712
1727
  #{script}
@@ -1791,7 +1806,8 @@ flatpickr(\".timepicker\", {enableTime: true, noCalendar: true});
1791
1806
 
1792
1807
  mermaidCode = document.createElement(\"SCRIPT\");
1793
1808
  mermaidCode.setAttribute(\"src\", \"https://cdn.jsdelivr.net/npm/mermaid@9.1.7/dist/mermaid.min.js\");
1794
- mermaidCode.addEventListener(\"load\", function () {
1809
+ mermaidCode.addEventListener(\"load\", mermaidLoaded);
1810
+ function mermaidLoaded() {
1795
1811
  mermaid.initialize({
1796
1812
  startOnLoad: true,
1797
1813
  securityLevel: \"loose\",
@@ -1824,6 +1840,14 @@ flatpickr(\".timepicker\", {enableTime: true, noCalendar: true});
1824
1840
  window.history.pushState({}, '', changeout(location.href, '_brick_erd', null));
1825
1841
  });
1826
1842
  mermaidErd.appendChild(span);
1843
+ }
1844
+ // If there's an error with the CDN during load, revert to our local copy
1845
+ mermaidCode.addEventListener(\"error\", function (e) {
1846
+ console.warn(\"As we're unable to load Mermaid from\\n \" + e.srcElement.src + \" ,\\nnow reverting to copy from /assets.\");
1847
+ var mermaidCode2 = document.createElement(\"SCRIPT\");
1848
+ mermaidCode2.setAttribute(\"src\", \"/assets/mermaid.min.js\");
1849
+ mermaidCode2.addEventListener(\"load\", mermaidLoaded);
1850
+ e.srcElement.replaceWith(mermaidCode2);
1827
1851
  });
1828
1852
  document.body.appendChild(mermaidCode);
1829
1853
  }
@@ -76,11 +76,14 @@ module Brick::Rails::FormTags
76
76
  pk.map { |pk_part| obj.send(pk_part.to_sym) }), { class: 'big-arrow' })}</td>\n" if pk.present?
77
77
  sequence.each do |col_name|
78
78
  val = obj.attributes[col_name]
79
+ bt = bts[col_name]
79
80
  out << '<td'
80
- out << ' class=\"dimmed\"' unless cols.key?(col_name) || (cust_col = cust_cols[col_name]) ||
81
- (col_name.is_a?(Symbol) && bts.key?(col_name)) # HOT
81
+ (classes ||= []) << 'dimmed' unless cols.key?(col_name) || (cust_col = cust_cols[col_name]) ||
82
+ (col_name.is_a?(Symbol) && bts.key?(col_name)) # HOT
83
+ (classes ||= []) << 'right' if val.is_a?(Numeric) && !bt
84
+ out << " class=\"#{classes.join(' ')}\"" if classes&.present?
82
85
  out << '>'
83
- if (bt = bts[col_name] || composite_bt_names[col_name])
86
+ if (bt || composite_bt_names[col_name])
84
87
  if bt[2] # Polymorphic?
85
88
  if (poly_id = obj.send("#{bt.first}_id"))
86
89
  # Was: obj.send("#{bt.first}_type")
@@ -139,8 +142,19 @@ module Brick::Rails::FormTags
139
142
  out << if @_brick_monetized_attributes&.include?(col_name)
140
143
  val ? Money.new(val.to_i).format : ''
141
144
  else
145
+ lat_lng = if [:float, :decimal].include?(col.type) &&
146
+ (
147
+ ((col_name == 'latitude' && obj.respond_to?('longitude') && (lng = obj.send('longitude')) && lng.is_a?(Numeric) && (lat = val)) ||
148
+ (col_name == 'longitude' && obj.respond_to?('latitude') && (lat = obj.send('latitude')) && lat.is_a?(Numeric) && (lng = val))
149
+ ) ||
150
+ ((col_name == 'lat' && obj.respond_to?('lng') && (lng = obj.send('lng')) && lng.is_a?(Numeric) && (lat = val)) ||
151
+ (col_name == 'lng' && obj.respond_to?('lat') && (lat = obj.send('lat')) && lat.is_a?(Numeric) && (lng = val))
152
+ )
153
+ )
154
+ [lat, lng]
155
+ end
142
156
  col_type = col&.sql_type == 'geography' ? col.sql_type : col&.type
143
- ::Brick::Rails.display_value(col_type || col&.sql_type, val).to_s
157
+ ::Brick::Rails.display_value(col_type || col&.sql_type, val, lat_lng).to_s
144
158
  end
145
159
  elsif cust_col
146
160
  data = cust_col.first.map { |cc_part| obj.send(cc_part.last) }
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 131
8
+ TINY = 133
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
@@ -62,7 +62,7 @@ module Brick
62
62
  dir = +"#{::Rails.root}/app"
63
63
  path[0..-2].each do |path_part|
64
64
  dir << "/#{path_part}"
65
- Dir.mkdir(dir) unless Dir.exists?(dir)
65
+ Dir.mkdir(dir) unless Dir.exist?(dir)
66
66
  end
67
67
  File.open("#{dir}/#{path.last}.rb", 'w') { |f| f.write code } unless code.blank?
68
68
  end
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.131
4
+ version: 1.0.133
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lorin Thwaits
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-16 00:00:00.000000000 Z
11
+ date: 2023-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord