brick 1.0.121 → 1.0.123

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: 142adfa751be46ca1115b6e6f6945ab25ad10148e55c7584eba6f91be62c6cf0
4
- data.tar.gz: a20a11f7fc6c864fbf9c5d9b4c6f80f29c0d26380e0aa110b63183f6e0c2e3e0
3
+ metadata.gz: baad039242ee5623097ad6170fec07e5feb0eb2fed6d41a9079f0775cccaceea
4
+ data.tar.gz: 603377f6b2c4437c448630bce6581d3650b8dfc13187e82afbaab1d425d171e2
5
5
  SHA512:
6
- metadata.gz: 84c6880fcb0c2aa00ee7484053c40afc61e2f9e66af38bb677408f762002c8a990a2f68bd3f17443916e02ed1a08b1db605bc28a7e913b2841bbb1318a3dcca0
7
- data.tar.gz: 377decd3c088a4ddc6034de54aed3885e99b10e54a5336885a4b8ed1c611e52947af99728b48ffa6bb0b5ec29babf971dea580bcfca053deb4f5fb3f60fd1877
6
+ metadata.gz: 1f4e48c1a437684929a81ace3e75ab15bb627c006680dba5a7454825fba358142560712f016bf944575aefeb27655716c3212d72a2b9b5a083a09cd2dfa8537c
7
+ data.tar.gz: ea9c376866230e4c2bab7b6c34dfc435a8cf81b568bc22af3a0e69497accca1620152ae311eab6c96649b79ecedf978b880afa88888dc6d1c4d3700bc3ef3060
@@ -58,6 +58,16 @@ module ActiveRecord
58
58
  def is_view?
59
59
  false
60
60
  end
61
+
62
+ def real_model(params)
63
+ if params && (sub_model = params.fetch(type_col = inheritance_column, nil))
64
+ sub_model = sub_model.first if sub_model.is_a?(Array) # Support the params style that gets returned from #brick_select
65
+ # Make sure the chosen model is really the same or a subclass of this model
66
+ (possible_model = sub_model.constantize) <= self ? possible_model : self
67
+ else
68
+ self
69
+ end
70
+ end
61
71
  end
62
72
 
63
73
  def self._brick_primary_key(relation = nil)
@@ -1651,16 +1661,18 @@ class Object
1651
1661
  return
1652
1662
  end
1653
1663
 
1664
+ real_model = model.real_model(params)
1665
+
1654
1666
  if request.format == :csv # Asking for a template?
1655
1667
  require 'csv'
1656
1668
  exported_csv = CSV.generate(force_quotes: false) do |csv_out|
1657
- model.df_export(model.brick_import_template).each { |row| csv_out << row }
1669
+ real_model.df_export(real_model.brick_import_template).each { |row| csv_out << row }
1658
1670
  end
1659
1671
  render inline: exported_csv, content_type: request.format
1660
1672
  return
1661
1673
  # elsif request.format == :js || current_api_root # Asking for JSON?
1662
1674
  # # %%% Add: where, order, page, page_size, offset, limit
1663
- # data = (model.is_view? || !Object.const_defined?('DutyFree')) ? model.limit(1000) : model.df_export(model.brick_import_template)
1675
+ # data = (real_model.is_view? || !Object.const_defined?('DutyFree')) ? real_model.limit(1000) : real_model.df_export(real_model.brick_import_template)
1664
1676
  # render inline: { data: data }.to_json, content_type: request.format == '*/*' ? 'application/json' : request.format
1665
1677
  # return
1666
1678
  end
@@ -1670,9 +1682,9 @@ class Object
1670
1682
  # %%% Allow params to define which columns to use for order_by
1671
1683
  # Overriding the default by providing a querystring param?
1672
1684
  ordering = params['_brick_order']&.split(',')&.map(&:to_sym) || Object.send(:default_ordering, table_name, pk)
1673
- order_by, _ = model._brick_calculate_ordering(ordering, true) # Don't do the txt part
1685
+ order_by, _ = real_model._brick_calculate_ordering(ordering, true) # Don't do the txt part
1674
1686
 
1675
- ar_relation = ActiveRecord.version < Gem::Version.new('4') ? model.preload : model.all
1687
+ ar_relation = ActiveRecord.version < Gem::Version.new('4') ? real_model.preload : real_model.all
1676
1688
  params['_brick_is_api'] = true if (is_api = request.format == :js || current_api_root)
1677
1689
  @_brick_params = ar_relation.brick_select(params, (selects ||= []), order_by,
1678
1690
  translations = {},
@@ -1682,7 +1694,7 @@ class Object
1682
1694
  # Apply column renaming
1683
1695
  data = ar_relation.respond_to?(:_select!) ? ar_relation.dup._select!(*selects) : ar_relation.select(selects)
1684
1696
  if data.present? &&
1685
- (column_renaming = ::Brick.find_col_renaming(current_api_root, model&._brick_relation)&.select { |cr| cr.last })
1697
+ (column_renaming = ::Brick.find_col_renaming(current_api_root, real_model&._brick_relation)&.select { |cr| cr.last })
1686
1698
  data.map!({}) do |row, s|
1687
1699
  column_renaming.each_with_object({}) do |rename, s|
1688
1700
  s[rename.last] = row[rename.first] if rename.last
@@ -1693,7 +1705,7 @@ class Object
1693
1705
  # # %%% This currently only gives a window to check security and raise an exception if someone isn't
1694
1706
  # # authenticated / authorised. Still need to figure out column filtering and transformations.
1695
1707
  # proc_result = if (column_filter = ::Brick.config.api_column_filter).is_a?(Proc)
1696
- # object_columns = (relation = model&._brick_relation)[:cols]
1708
+ # object_columns = (relation = real_model&._brick_relation)[:cols]
1697
1709
  # begin
1698
1710
  # num_args = column_filter.arity.negative? ? 5 : column_filter.arity
1699
1711
  # # object_name, api_version, columns, data
@@ -1718,7 +1730,7 @@ class Object
1718
1730
 
1719
1731
  # %%% Add custom HM count columns
1720
1732
  # %%% What happens when the PK is composite?
1721
- counts = model._br_hm_counts.each_with_object([]) do |v, s|
1733
+ counts = real_model._br_hm_counts.each_with_object([]) do |v, s|
1722
1734
  s << if is_mysql
1723
1735
  "`b_r_#{v.first}`.c_t_ AS \"b_r_#{v.first}_ct\""
1724
1736
  elsif is_postgres
@@ -1738,8 +1750,8 @@ class Object
1738
1750
  s << excl_parts.last
1739
1751
  end
1740
1752
  end
1741
- @_brick_bt_descrip = model._br_bt_descrip
1742
- @_brick_hm_counts = model._br_hm_counts
1753
+ @_brick_bt_descrip = real_model._br_bt_descrip
1754
+ @_brick_hm_counts = real_model._br_hm_counts
1743
1755
  @_brick_join_array = join_array
1744
1756
  @_brick_erd = params['_brick_erd']&.to_i
1745
1757
  end
@@ -1847,18 +1859,27 @@ class Object
1847
1859
  instance_variable_set("@#{singular_table_name}".to_sym, (obj = find_obj))
1848
1860
  upd_params = send(params_name_sym)
1849
1861
  json_overrides = ::Brick.config.json_columns&.fetch(table_name, nil)
1850
- if (json_cols = model.columns.select { |c| c.type == :json || json_overrides&.include?(c.name) }.map(&:name)).present?
1862
+ if model.respond_to?(:devise_modules)
1851
1863
  upd_hash = upd_params.to_h
1864
+ upd_hash['reset_password_token'] = nil if upd_hash['reset_password_token'].blank?
1865
+ upd_hash['reset_password_sent_at'] = nil if upd_hash['reset_password_sent_at'].blank?
1866
+ if model.devise_modules.include?(:invitable)
1867
+ upd_hash['invitation_token'] = nil if upd_hash['invitation_token'].blank?
1868
+ upd_hash['invitation_created_at'] = nil if upd_hash['invitation_created_at'].blank?
1869
+ upd_hash['invitation_sent_at'] = nil if upd_hash['invitation_sent_at'].blank?
1870
+ upd_hash['invitation_accepted_at'] = nil if upd_hash['invitation_accepted_at'].blank?
1871
+ end
1872
+ end
1873
+ if (json_cols = model.columns.select { |c| c.type == :json || json_overrides&.include?(c.name) }.map(&:name)).present?
1874
+ upd_hash ||= upd_params.to_h
1852
1875
  json_cols.each do |c|
1853
1876
  begin
1854
1877
  upd_hash[c] = JSON.parse(upd_hash[c].tr('`', '"').gsub('^^br_btick__', '`'))
1855
1878
  rescue
1856
1879
  end
1857
1880
  end
1858
- obj.send(:update, upd_hash)
1859
- else
1860
- obj.send(:update, upd_params)
1861
1881
  end
1882
+ obj.send(:update, upd_hash || upd_params)
1862
1883
  end
1863
1884
 
1864
1885
  code << " def destroy\n"
@@ -1894,10 +1915,11 @@ class Object
1894
1915
  end
1895
1916
  end
1896
1917
  # Support friendly_id gem
1918
+ id_simplified = id.is_a?(Array) && id.length == 1 ? id.first : id
1897
1919
  if Object.const_defined?('FriendlyId') && model.instance_variable_get(:@friendly_id_config)
1898
- model.friendly.find(id.is_a?(Array) && id.length == 1 ? id.first : id)
1920
+ model.friendly.find(id_simplified)
1899
1921
  else
1900
- model.find(id.is_a?(Array) && id.length == 1 ? id.first : id)
1922
+ model.find(id_simplified)
1901
1923
  end
1902
1924
  end
1903
1925
  end
@@ -2032,8 +2054,18 @@ end.class_exec do
2032
2054
  load inflections
2033
2055
  end
2034
2056
  # Now the Brick initializer since there may be important schema things configured
2035
- if File.exist?(brick_initializer = ::Rails.root.join('config/initializers/brick.rb'))
2057
+ if !::Brick.initializer_loaded && File.exist?(brick_initializer = ::Rails.root.join('config/initializers/brick.rb'))
2036
2058
  ::Brick.initializer_loaded = load brick_initializer
2059
+
2060
+ # After loading the initializer, add compatibility for ActiveStorage and ActionText if those haven't already been
2061
+ # defined. (Further JSON configuration for ActiveStorage metadata happens later in the after_initialize hook.)
2062
+ ['ActiveStorage', 'ActionText'].each do |ar_extension|
2063
+ if Object.const_defined?(ar_extension) &&
2064
+ (extension = Object.const_get(ar_extension)).respond_to?(:table_name_prefix) &&
2065
+ !::Brick.config.table_name_prefixes.key?(as_tnp = extension.table_name_prefix)
2066
+ ::Brick.config.table_name_prefixes[as_tnp] = ar_extension
2067
+ end
2068
+ end
2037
2069
  end
2038
2070
  # Load the initializer for the Apartment gem a little early so that if .excluded_models and
2039
2071
  # .default_schema are specified then we can work with non-tenanted models more appropriately
@@ -188,6 +188,17 @@ function linkSchemas() {
188
188
  (app.config.assets.paths ||= []) << assets_path
189
189
  end
190
190
 
191
+ # Treat ActiveStorage::Blob metadata as JSON
192
+ if ::Brick.config.table_name_prefixes.fetch('active_storage_', nil) == 'ActiveStorage' &&
193
+ ActiveStorage.const_defined?('Blob')
194
+ unless (md = (::Brick.config.model_descrips ||= {})).key?('ActiveStorage::Blob')
195
+ md['ActiveStorage::Blob'] = '[filename]'
196
+ end
197
+ unless (asbm = (::Brick.config.json_columns['active_storage_blobs'] ||= [])).include?('metadata')
198
+ asbm << 'metadata'
199
+ end
200
+ end
201
+
191
202
  # Smarten up Avo so it recognises Brick's querystring option for Apartment multi-tenancy
192
203
  if Object.const_defined?('Avo') && ::Avo.respond_to?(:railtie_namespace)
193
204
  module ::Avo
@@ -510,6 +521,16 @@ window.addEventListener(\"popstate\", linkSchemas);
510
521
  # Dynamically create generic templates
511
522
  # ====================================
512
523
  if ::Brick.enable_views?
524
+ # Add the params to the lookup_context so that we have context about STI classes when setting @_brick_model
525
+ ActionView::ViewPaths.class_exec do
526
+ alias :_brick_lookup_context :lookup_context
527
+ def lookup_context(*args)
528
+ ret = _brick_lookup_context(*args)
529
+ @_lookup_context.instance_variable_set(:@_brick_req_params, params)
530
+ ret
531
+ end
532
+ end
533
+
513
534
  ActionView::LookupContext.class_exec do
514
535
  # Used by Rails 5.0 and above
515
536
  alias :_brick_template_exists? :template_exists?
@@ -520,10 +541,10 @@ window.addEventListener(\"popstate\", linkSchemas);
520
541
  _brick_template_exists?(*args, **options) ||
521
542
  # Do not auto-create a template when it's searching for an application.html.erb, which comes in like: ["edit", ["games", "application"]]
522
543
  ((args[1].length == 1 || args[1][-1] != 'application') &&
523
- set_brick_model(args))
544
+ set_brick_model(args, @_brick_req_params))
524
545
  end
525
546
 
526
- def set_brick_model(find_args)
547
+ def set_brick_model(find_args, params)
527
548
  # Return an appropriate model for a given view template request.
528
549
  # find_args will generally be something like: ["index", ["categories"]]
529
550
  # and must cycle through all of find_args[1] because in some cases such as with Devise we get something like:
@@ -537,7 +558,7 @@ window.addEventListener(\"popstate\", linkSchemas);
537
558
  # Only CUD stuff has create / update / destroy
538
559
  (!model.is_view? && ['new', 'create', 'edit', 'update', 'destroy'].include?(find_args.first))
539
560
  )
540
- @_brick_model = model
561
+ @_brick_model = model.real_model(params)
541
562
  end
542
563
  rescue
543
564
  end
@@ -576,10 +597,14 @@ window.addEventListener(\"popstate\", linkSchemas);
576
597
  return possible_template
577
598
  end
578
599
  rescue StandardError => e
579
- find_template_err = e # Can come up with stuff like Devise which has its own view templates
600
+ # Search through the routes to confirm that something might match (Devise stuff for instance, which has its own view templates),
601
+ # and bubble the same exception (probably an ActionView::MissingTemplate) if a legitimate option is found.
602
+ raise if ::Rails.application.routes.set.find { |x| args[1].include?(x.defaults[:controller]) && args[0] == x.defaults[:action] }
603
+
604
+ find_template_err = e
580
605
  end
581
606
  # Used to also have: ActionView.version < ::Gem::Version.new('5.0') &&
582
- model_name = set_brick_model(args)&.name
607
+ model_name = set_brick_model(args, @_brick_req_params)&.name
583
608
  end
584
609
 
585
610
  if @_brick_model
@@ -636,7 +661,7 @@ window.addEventListener(\"popstate\", linkSchemas);
636
661
  (hm_fk_name.is_a?(String) && hm_fk_name.include?('.')) # HMT? (Could do a better check for this)
637
662
  predicates = path_keys(hm_assoc, hm_fk_name, pk).map do |k, v|
638
663
  if v == '[sti_type]'
639
- "'#{k}': @#{obj_name}.#{hm_assoc.active_record.inheritance_column}"
664
+ "'#{k}': (@#{obj_name}.#{hm_assoc.active_record.inheritance_column}).constantize.base_class.name"
640
665
  else
641
666
  v.is_a?(String) ? "'#{k}': '#{v}'" : "'#{k}': @#{obj_name}.#{v}"
642
667
  end
@@ -848,6 +873,10 @@ input+svg.revert {
848
873
  color: #FFF;
849
874
  }
850
875
  </style>
876
+ <script>
877
+ if (window.history.state && window.history.state.turbo)
878
+ window.addEventListener(\"popstate\", function () { location.reload(true); });
879
+ </script>
851
880
 
852
881
  <% is_includes_dates = nil
853
882
  is_includes_json = nil
@@ -1158,7 +1187,7 @@ erDiagram
1158
1187
  @_brick_bt_descrip&.each do |bt|
1159
1188
  bt_class = bt[1].first.first
1160
1189
  callbacks[bt_name = bt_class.name.split('::').last] = bt_class
1161
- is_has_one = #{@_brick_model.name}.reflect_on_association(bt.first).inverse_of&.macro == :has_one ||
1190
+ is_has_one = #{@_brick_model.name}.reflect_on_association(bt.first)&.inverse_of&.macro == :has_one ||
1162
1191
  ::Brick.config.has_ones&.fetch('#{@_brick_model.name}', nil)&.key?(bt.first.to_s)
1163
1192
  %> <%= \"#\{model_short_name} #\{is_has_one ? '||' : '}o'}--|| #\{bt_name} : \\\"#\{
1164
1193
  bt_underscored = bt[1].first.first.name.underscore.singularize
@@ -1316,13 +1345,9 @@ erDiagram
1316
1345
  +"<html>
1317
1346
  <head>
1318
1347
  #{css}
1319
- <title><% model = #{model_name}
1320
- if sub_model = @_brick_params&.fetch(type_col = model.inheritance_column, nil)&.first
1321
- model = Object.const_get(sub_model.to_sym)
1322
- end
1323
- %><%= model.name %><%
1324
- if (description = (relation = Brick.relations[model.table_name])&.fetch(:description, nil)).present?
1325
- %> - <%= description
1348
+ <title><%= (model = #{model_name}).name %><%
1349
+ if (description = (relation = Brick.relations[model.table_name])&.fetch(:description, nil)).present?
1350
+ %> - <%= description
1326
1351
  %><% end
1327
1352
  %></title>
1328
1353
  </head>
@@ -1359,7 +1384,27 @@ erDiagram
1359
1384
  ) %></td>
1360
1385
  <% end
1361
1386
  end %>
1362
- </tr><%= if (page_num = @#{table_name}._brick_page_num)
1387
+ </tr>
1388
+
1389
+ <%= if model < (base_model = model.base_class)
1390
+ this_model = model
1391
+ parent_links = []
1392
+ until this_model == base_model do
1393
+ this_model = this_model.superclass
1394
+ path = send(\"#\{this_model._brick_index}_path\")
1395
+ path << \"?#\{base_model.inheritance_column}=#\{this_model.name}\" unless this_model == base_model
1396
+ parent_links << link_to(this_model.name, path)
1397
+ end
1398
+ \"<tr><td colspan=\\\"#\{td_count}\\\">Parent: #\{parent_links.join(' ')}</tr>\".html_safe
1399
+ end
1400
+ %><%= if (children = model.descendants).present?
1401
+ child_links = children.map do |child|
1402
+ path = send(\"#\{child._brick_index}_path\") + \"?#\{base_model.inheritance_column}=#\{child.name}\"
1403
+ link_to(child.name, path)
1404
+ end
1405
+ \"<tr><td colspan=\\\"#\{td_count}\\\">Children: #\{child_links.join(' ')}</tr>\".html_safe
1406
+ end
1407
+ %><%= if (page_num = @#{table_name}._brick_page_num)
1363
1408
  \"<tr><td colspan=\\\"#\{td_count}\\\">Page #\{page_num}</td></tr>\".html_safe
1364
1409
  end %></table>#{template_link}<%
1365
1410
  if description.present? %><%=
@@ -1521,8 +1566,12 @@ erDiagram
1521
1566
  <head>
1522
1567
  #{css}
1523
1568
  <title><%=
1524
- model = (obj = @#{obj_name})&.class
1525
- model_name = @#{obj_name}.#{inh_col = @_brick_model.inheritance_column} if obj.respond_to?(:#{inh_col})
1569
+ base_model = (model = (obj = @#{obj_name})&.class).base_class
1570
+ see_all_path = send(\"#\{base_model._brick_index}_path\")
1571
+ if obj.respond_to?(:#{inh_col = @_brick_model.inheritance_column}) &&
1572
+ (model_name = @#{obj_name}.#{inh_col}) != base_model.name
1573
+ see_all_path << \"?#{inh_col}=#\{model_name}\"
1574
+ end
1526
1575
  page_title = (\"#\{model_name ||= model.name}: #\{obj&.brick_descrip || controller_name}\")
1527
1576
  %></title>
1528
1577
  </head>
@@ -1566,7 +1615,7 @@ erDiagram
1566
1615
  if (description = (relation = Brick.relations[tbl_name = #{model_name}.table_name])&.fetch(:description, nil)) %><%=
1567
1616
  description %><br><%
1568
1617
  end
1569
- %><%= link_to '(See all #{obj_name.pluralize})', #{@_brick_model._brick_index}_path %>
1618
+ %><%= link_to \"(See all #\{model_name.pluralize})\", see_all_path %>
1570
1619
  #{erd_markup}
1571
1620
  <% if obj
1572
1621
  # path_options = [obj.#{pk}]
@@ -1582,11 +1631,11 @@ end
1582
1631
  <%= form_for(obj.becomes(#{model_name}), options) do |f| %>
1583
1632
  <table class=\"shadow\">
1584
1633
  <% has_fields = false
1585
- @#{obj_name}.attributes.each do |k, val|
1586
- col = #{model_name}.columns_hash[k] %>
1587
- <tr>
1588
- <% next if (#{(pk || []).inspect}.include?(k) && !bts.key?(k)) ||
1634
+ @#{obj_name}.attributes.each do |k, val|
1635
+ next if !(col = #{model_name}.columns_hash[k]) ||
1636
+ (#{(pk || []).inspect}.include?(k) && !bts.key?(k)) ||
1589
1637
  ::Brick.config.metadata_columns.include?(k) %>
1638
+ <tr>
1590
1639
  <th class=\"show-field\"<%= \" title=\\\"#\{col.comment}\\\"\".html_safe if col.respond_to?(:comment) && !col.comment.blank? %>>
1591
1640
  <% has_fields = true
1592
1641
  if (bt = bts[k])
@@ -1650,9 +1699,13 @@ end
1650
1699
  if is_bcrypt?(val) # || .readonly?
1651
1700
  is_revert = false %>
1652
1701
  <%= hide_bcrypt(val, nil, 1000) %>
1653
- <% elsif col_type == :string %>
1654
- <%= f.text_field(k.to_sym, html_options) %>
1655
- <% else
1702
+ <% elsif col_type == :string
1703
+ if model.respond_to?(:enumerized_attributes) && (opts = model.enumerized_attributes[k]&.options).present? %>
1704
+ <%= f.select(k.to_sym, [[\"(No #\{k} chosen)\", '^^^brick_NULL^^^']] + opts, { value: val || '^^^brick_NULL^^^' }, html_options) %><%
1705
+ else %>
1706
+ <%= f.text_field(k.to_sym, html_options) %><%
1707
+ end
1708
+ else
1656
1709
  is_includes_text = true %>
1657
1710
  <%= f.hidden_field(k.to_sym, html_options) %>
1658
1711
  <trix-editor input=\"<%= f.field_id(k) %>\"></trix-editor>
@@ -86,19 +86,13 @@ module Brick::Rails::FormTags
86
86
  elsif descrips.length == 1
87
87
  [obj.class.reflect_on_association(bt.first)&.foreign_key]
88
88
  else
89
- # Was: descrips.last -- but the ID stuff is not coming through anymore
90
- [bt.first]
89
+ descrips.last
91
90
  end
92
- txt_parts = descrips.map do |id|
93
- obj2 = obj
94
- id[0..-2].each { |ref| obj2 = obj2&.send(ref) }
91
+ bt_txt = bt_class.brick_descrip(
95
92
  # 0..62 because Postgres column names are limited to 63 characters
96
- obj2&.send(id.last[0..62])
97
- end
98
- unless txt_parts.compact.empty?
99
- bt_txt = bt_class.brick_descrip(obj, txt_parts, bt_id_col)
100
- bt_txt = ::Brick::Rails.display_binary(bt_txt).html_safe if bt_txt&.encoding&.name == 'ASCII-8BIT'
101
- end
93
+ obj, descrips[0..-2].map { |id| obj.send(id.last[0..62]) }, bt_id_col
94
+ )
95
+ bt_txt = ::Brick::Rails.display_binary(bt_txt).html_safe if bt_txt&.encoding&.name == 'ASCII-8BIT'
102
96
  bt_txt ||= "<span class=\"orphan\">&lt;&lt; Orphaned ID: #{val} >></span>" if val
103
97
  bt_id = bt_id_col&.map { |id_col| obj.respond_to?(id_sym = id_col.to_sym) ? obj.send(id_sym) : id_col }
104
98
  out << (bt_id&.first ? link_to(bt_txt, send("#{bt_class.base_class._brick_index(:singular)}_path".to_sym, bt_id)) : bt_txt || '')
@@ -110,16 +104,16 @@ module Brick::Rails::FormTags
110
104
  hm_klass = (col = cols[col_name])[1]
111
105
  if col[2] == 'HO'
112
106
  descrips = bt_descrip[col_name.to_sym][hm_klass]
113
- if (ho_id = (ho_id_col = descrips.last).map { |id_col| obj.respond_to?(id_sym = id_col.to_sym) && obj.send(id_sym) })&.first
107
+ if (ho_id = (ho_id_col = descrips.last).map { |id_col| obj.send(id_col.to_sym) })&.first
114
108
  ho_txt = hm_klass.brick_descrip(obj, descrips[0..-2].map { |id| obj.send(id.last[0..62]) }, ho_id_col)
115
109
  out << link_to(ho_txt, send("#{hm_klass.base_class._brick_index(:singular)}_path".to_sym, ho_id))
116
110
  end
117
111
  else
118
112
  if (ct = obj.send(hms_col[1].to_sym)&.to_i)&.positive?
113
+ predicates = hms_col[2].each_with_object({}) { |v, s| s[v.first] = v.last.is_a?(String) ? v.last : obj.send(v.last) }
114
+ predicates.each { |k, v| predicates[k] = obj.class.name if v == '[sti_type]' }
119
115
  out << "#{link_to("#{ct || 'View'} #{hms_col.first}",
120
- send("#{hm_klass._brick_index}_path".to_sym,
121
- hms_col[2].each_with_object({}) { |v, s| s[v.first] = v.last.is_a?(String) ? v.last : obj.send(v.last) })
122
- )}\n"
116
+ send("#{hm_klass._brick_index}_path".to_sym, predicates))}\n"
123
117
  end
124
118
  end
125
119
  end
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 121
8
+ TINY = 123
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
data/lib/brick.rb CHANGED
@@ -1618,8 +1618,8 @@ module ActiveRecord
1618
1618
  end
1619
1619
  end
1620
1620
 
1621
- if JoinDependency.private_instance_methods.include?(:table_aliases_for)
1622
- # No matter if it's older or newer Rails, now extend so that we can associate AR links to table_alias names
1621
+ # No matter if it's older or newer Rails, now extend so that we can associate AR links to table_alias names
1622
+ if ActiveRecord.version < ::Gem::Version.new('6.1')
1623
1623
  alias _brick_table_aliases_for table_aliases_for
1624
1624
  def table_aliases_for(parent, node)
1625
1625
  result = _brick_table_aliases_for(parent, node)
@@ -1630,7 +1630,7 @@ module ActiveRecord
1630
1630
  end
1631
1631
  result
1632
1632
  end
1633
- else # Same idea but for Rails 7
1633
+ else # Same idea but for Rails >= 6.1
1634
1634
  alias _brick_make_constraints make_constraints
1635
1635
  def make_constraints(parent, child, join_type)
1636
1636
  result = _brick_make_constraints(parent, child, join_type)
@@ -1657,7 +1657,7 @@ if Gem::Specification.all_names.any? { |g| g.start_with?('ransack-') }
1657
1657
  module Polyamorous::JoinDependencyExtensions
1658
1658
  def build(associations, base_klass, root = nil, path = '')
1659
1659
  root ||= associations
1660
- puts associations.map(&:first)
1660
+ # puts associations.map(&:first)
1661
1661
 
1662
1662
  associations.map do |name, right|
1663
1663
  link_path = path.blank? ? name.to_s : path + ".#{name}"
@@ -1694,6 +1694,29 @@ if Gem::Specification.all_names.any? { |g| g.start_with?('ransack-') }
1694
1694
  end
1695
1695
  end
1696
1696
 
1697
+ # Patch Enumerize so that #becomes works when an STI subclass is becoming a base class
1698
+ # which does not include Enumerize.
1699
+ # (See https://github.com/brainspec/enumerize/issues/426)
1700
+ if Object.const_defined?('Enumerize') && Enumerize.const_defined?('ActiveRecordSupport')
1701
+ Enumerize::ActiveRecordSupport::InstanceMethods.class_exec do
1702
+ def becomes(klass)
1703
+ became = super
1704
+ klass = self.class unless klass.respond_to?(:enumerized_attributes)
1705
+ klass.enumerized_attributes.each do |attr|
1706
+ begin
1707
+ if became.respond_to?(setter = "#{attr.name}=")
1708
+ became.send(setter, send(attr.name))
1709
+ end
1710
+ rescue ActiveModel::MissingAttributeError
1711
+ rescue ActiveRecord::SerializationTypeMismatch
1712
+ became.send(setter, send(attr.name).to_ary)
1713
+ end
1714
+ end
1715
+ became
1716
+ end
1717
+ end
1718
+ end
1719
+
1697
1720
  # Keyword arguments updates for Rails <= 5.2.x and Ruby >= 3.0
1698
1721
  if ActiveRecord.version < ::Gem::Version.new('6.0') && ruby_version >= ::Gem::Version.new('3.0')
1699
1722
  admsm = ActionDispatch::MiddlewareStack::Middleware
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.121
4
+ version: 1.0.123
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-03-19 00:00:00.000000000 Z
11
+ date: 2023-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord