brick 1.0.131 → 1.0.133

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: 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