brick 1.0.123 → 1.0.125
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 +4 -4
- data/lib/brick/extensions.rb +53 -27
- data/lib/brick/frameworks/rails/engine.rb +15 -11
- data/lib/brick/frameworks/rails/form_tags.rb +55 -33
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +26 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc3caefac264427d0a4a7efa11160fc3b7c1cc6c82afa01bf7340941dbab18e1
|
4
|
+
data.tar.gz: 7d9aebd13fe256d43ee3ec24f94065a64ab4955e3ee379023352013db59fe3ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c02e8bdceca8f726d24a8f7eddb6057427d2e31c3db3934bd72da0393509aaf2d5e7246ba65e8bdd773fc3d995c538567137dec729eb2d062ba0f7e006ace7c6
|
7
|
+
data.tar.gz: c6061b00b761638ebd0f9750423643615c08dffb9c62bec423d1bf5c047dcfa82c9b2bccaea1491d9f7a4c23932b9299be1254e708e26ca624165a5695557c63
|
data/lib/brick/extensions.rb
CHANGED
@@ -68,6 +68,12 @@ module ActiveRecord
|
|
68
68
|
self
|
69
69
|
end
|
70
70
|
end
|
71
|
+
|
72
|
+
def json_column?(col)
|
73
|
+
col.type == :json || ::Brick.config.json_columns[table_name]&.include?(col.name) ||
|
74
|
+
((attr_types = attribute_types[col.name]).respond_to?(:coder) &&
|
75
|
+
(attr_types.coder.is_a?(Class) ? attr_types.coder : attr_types.coder&.class)&.name&.end_with?('JSON'))
|
76
|
+
end
|
71
77
|
end
|
72
78
|
|
73
79
|
def self._brick_primary_key(relation = nil)
|
@@ -638,6 +644,7 @@ module ActiveRecord
|
|
638
644
|
# Add derived table JOIN for the has_many counts
|
639
645
|
nix = []
|
640
646
|
klass._br_hm_counts.each do |k, hm|
|
647
|
+
num_bt_things = 0
|
641
648
|
count_column = if hm.options[:through]
|
642
649
|
# Build the chain of JOINs going to the final destination HMT table
|
643
650
|
# (Usually just one JOIN, but could be many.)
|
@@ -668,7 +675,9 @@ module ActiveRecord
|
|
668
675
|
from_clause << if (src_ref = a.source_reflection).macro == :belongs_to
|
669
676
|
nm = hmt_assoc.source_reflection.inverse_of&.name
|
670
677
|
link_back << nm
|
671
|
-
|
678
|
+
num_bt_things += 1
|
679
|
+
# puts "BT #{a.table_name}"
|
680
|
+
"ON br_t#{idx}.#{a.active_record.primary_key} = br_t#{idx - 1}.#{a.foreign_key}"
|
672
681
|
elsif src_ref.options[:as]
|
673
682
|
"ON br_t#{idx}.#{src_ref.type} = '#{src_ref.active_record.name}'" + # "polymorphable_type"
|
674
683
|
" AND br_t#{idx}.#{src_ref.foreign_key} = br_t#{idx - 1}.id"
|
@@ -679,18 +688,19 @@ module ActiveRecord
|
|
679
688
|
bail_out = true
|
680
689
|
break
|
681
690
|
# "ON br_t#{idx}.#{a.foreign_type} = '#{src_ref.options[:source_type]}' AND " \
|
682
|
-
# "br_t#{idx}.#{a.foreign_key} = br_t#{idx - 1}.
|
691
|
+
# "br_t#{idx}.#{a.foreign_key} = br_t#{idx - 1}.#{a.active_record.primary_key}"
|
683
692
|
else # Works for HMT through a polymorphic HO
|
684
693
|
link_back << hmt_assoc.source_reflection.inverse_of&.name # Some polymorphic "_able" thing
|
685
694
|
"ON br_t#{idx - 1}.#{a.foreign_type} = '#{src_ref.options[:source_type]}' AND " \
|
686
|
-
"br_t#{idx - 1}.#{a.foreign_key} = br_t#{idx}.
|
695
|
+
"br_t#{idx - 1}.#{a.foreign_key} = br_t#{idx}.#{a.active_record.primary_key}"
|
687
696
|
end
|
688
697
|
else # Standard has_many or has_one
|
698
|
+
# puts "HM #{a.table_name}"
|
689
699
|
# binding.pry unless (
|
690
700
|
nm = hmt_assoc.source_reflection.inverse_of&.name
|
691
701
|
# )
|
692
702
|
link_back << nm # if nm
|
693
|
-
"ON br_t#{idx}.#{a.foreign_key} = br_t#{idx - 1}.
|
703
|
+
"ON br_t#{idx}.#{a.foreign_key} = br_t#{idx - 1}.#{a.active_record.primary_key}"
|
694
704
|
end
|
695
705
|
link_back.unshift(a.source_reflection.name)
|
696
706
|
[a.table_name, a.foreign_key, a.source_reflection.macro]
|
@@ -708,7 +718,13 @@ module ActiveRecord
|
|
708
718
|
# binding.pry if link_back.length > 2
|
709
719
|
"br_t#{idx}.#{hm.foreign_key}"
|
710
720
|
else # A HMT that goes HM -> HM, something like Categories -> Products -> LineItems
|
711
|
-
#
|
721
|
+
# %%% Currently flaky, so will revisit this soon, probably while implementing the whole link_back architecture
|
722
|
+
if num_bt_things > 1
|
723
|
+
# binding.pry
|
724
|
+
nix << k
|
725
|
+
next
|
726
|
+
end
|
727
|
+
|
712
728
|
"br_t#{idx}.#{src_ref.active_record.primary_key}"
|
713
729
|
end
|
714
730
|
else
|
@@ -846,8 +862,7 @@ JOIN (SELECT #{hm_selects.map { |s| "#{'br_t0.' if from_clause}#{s}" }.join(', '
|
|
846
862
|
alias _brick_find_sti_class find_sti_class
|
847
863
|
def find_sti_class(type_name)
|
848
864
|
if ::Brick.sti_models.key?(type_name ||= name)
|
849
|
-
|
850
|
-
_brick_find_sti_class(type_name)
|
865
|
+
::Brick.sti_models[type_name].fetch(:base, nil) || _brick_find_sti_class(type_name)
|
851
866
|
else
|
852
867
|
# This auto-STI is more of a brute-force approach, building modules where needed
|
853
868
|
# The more graceful alternative is the overload of ActiveSupport::Dependencies#autoload_module! found below
|
@@ -855,9 +870,13 @@ JOIN (SELECT #{hm_selects.map { |s| "#{'br_t0.' if from_clause}#{s}" }.join(', '
|
|
855
870
|
module_prefixes = type_name.split('::')
|
856
871
|
module_prefixes.unshift('') unless module_prefixes.first.blank?
|
857
872
|
module_name = module_prefixes[0..-2].join('::')
|
858
|
-
if (
|
873
|
+
if (base_name = ::Brick.config.sti_namespace_prefixes&.fetch("#{module_name}::", nil)) ||
|
859
874
|
File.exist?(candidate_file = ::Rails.root.join('app/models' + module_prefixes.map(&:underscore).join('/') + '.rb'))
|
860
|
-
|
875
|
+
if base_name
|
876
|
+
base_name == "::#{name}" ? self : base_name.constantize
|
877
|
+
else
|
878
|
+
_brick_find_sti_class(type_name) # Find this STI class normally
|
879
|
+
end
|
861
880
|
else
|
862
881
|
# Build missing prefix modules if they don't yet exist
|
863
882
|
this_module = Object
|
@@ -978,6 +997,8 @@ Module.class_exec do
|
|
978
997
|
end
|
979
998
|
Object
|
980
999
|
else
|
1000
|
+
sti_base = (::Brick.config.sti_namespace_prefixes&.fetch("::#{name}::#{requested}", nil) ||
|
1001
|
+
::Brick.config.sti_namespace_prefixes&.fetch("::#{name}::", nil))&.constantize
|
981
1002
|
self
|
982
1003
|
end
|
983
1004
|
# puts "#{self.name} - #{args.first}"
|
@@ -985,7 +1006,7 @@ Module.class_exec do
|
|
985
1006
|
if ((is_defined = self.const_defined?(args.first)) && (possible = self.const_get(args.first)) &&
|
986
1007
|
# Reset `possible` if it's a controller request that's not a perfect match
|
987
1008
|
# Was: (possible = nil) but changed to #local_variable_set in order to suppress the "= should be ==" warning
|
988
|
-
(possible
|
1009
|
+
(possible&.name == desired_classname || (is_controller && binding.local_variable_set(:possible, nil)))) ||
|
989
1010
|
# Try to require the respective Ruby file
|
990
1011
|
((filename = ActiveSupport::Dependencies.search_for_file(desired_classname.underscore) ||
|
991
1012
|
(self != Object && ActiveSupport::Dependencies.search_for_file((desired_classname = requested).underscore))
|
@@ -995,9 +1016,11 @@ Module.class_exec do
|
|
995
1016
|
# If any class has turned up so far (and we're not in the middle of eager loading)
|
996
1017
|
# then return what we've found.
|
997
1018
|
(is_defined && !::Brick.is_eager_loading) # Used to also have: && possible != self
|
998
|
-
if (!brick_root && (filename || possible.instance_of?(Class))) ||
|
999
|
-
|
1000
|
-
|
1019
|
+
if ((!brick_root && (filename || possible.instance_of?(Class))) ||
|
1020
|
+
(possible.instance_of?(Module) && possible&.module_parent == self) ||
|
1021
|
+
(possible.instance_of?(Class) && possible == self)) && # Are we simply searching for ourselves?
|
1022
|
+
# Skip when what we found as `possible` is not related to the base class of an STI model
|
1023
|
+
(!sti_base || possible.is_a?(sti_base))
|
1001
1024
|
return possible
|
1002
1025
|
end
|
1003
1026
|
end
|
@@ -1129,7 +1152,8 @@ class Object
|
|
1129
1152
|
|
1130
1153
|
def build_model(relations, base_module, base_name, class_name, inheritable_name = nil)
|
1131
1154
|
tnp = ::Brick.config.table_name_prefixes&.find { |p| p.last == base_module.name }&.first
|
1132
|
-
if (base_model = ::Brick.config.sti_namespace_prefixes&.fetch("::#{base_module.name}
|
1155
|
+
if (base_model = (::Brick.config.sti_namespace_prefixes&.fetch("::#{base_module.name}::#{class_name}", nil) || # Are we part of an auto-STI namespace? ...
|
1156
|
+
::Brick.config.sti_namespace_prefixes&.fetch("::#{base_module.name}::", nil))&.constantize) ||
|
1133
1157
|
base_module != Object # ... or otherwise already in some namespace?
|
1134
1158
|
schema_name = [(singular_schema_name = base_name.underscore),
|
1135
1159
|
(schema_name = singular_schema_name.pluralize),
|
@@ -1141,7 +1165,6 @@ class Object
|
|
1141
1165
|
singular_table_name = ActiveSupport::Inflector.underscore(model_name).gsub('/', '.')
|
1142
1166
|
|
1143
1167
|
if base_model
|
1144
|
-
schema_name = base_name.underscore # For the auto-STI namespace models
|
1145
1168
|
table_name = base_model.table_name
|
1146
1169
|
build_model_worker(base_module, inheritable_name, model_name, singular_table_name, table_name, relations, table_name)
|
1147
1170
|
else
|
@@ -1171,7 +1194,7 @@ class Object
|
|
1171
1194
|
full_name = if relation || schema_name.blank?
|
1172
1195
|
inheritable_name || model_name
|
1173
1196
|
else # Prefix the schema to the table name + prefix the schema namespace to the class name
|
1174
|
-
schema_module = if schema_name.
|
1197
|
+
schema_module = if schema_name.is_a?(Module) # from an auto-STI namespace?
|
1175
1198
|
schema_name
|
1176
1199
|
else
|
1177
1200
|
matching = "#{schema_name}.#{matching}"
|
@@ -1870,7 +1893,7 @@ class Object
|
|
1870
1893
|
upd_hash['invitation_accepted_at'] = nil if upd_hash['invitation_accepted_at'].blank?
|
1871
1894
|
end
|
1872
1895
|
end
|
1873
|
-
if (json_cols = model.columns.select { |c|
|
1896
|
+
if (json_cols = model.columns.select { |c| model.json_column?(c) }.map(&:name)).present?
|
1874
1897
|
upd_hash ||= upd_params.to_h
|
1875
1898
|
json_cols.each do |c|
|
1876
1899
|
begin
|
@@ -2498,9 +2521,9 @@ module Brick
|
|
2498
2521
|
# rubocop:enable Style/CommentedKeyword
|
2499
2522
|
|
2500
2523
|
class << self
|
2501
|
-
def _add_bt_and_hm(fk, relations,
|
2524
|
+
def _add_bt_and_hm(fk, relations, polymorphic_class = nil, is_optional = false)
|
2502
2525
|
bt_assoc_name = ::Brick.namify(fk[2], :downcase)
|
2503
|
-
unless
|
2526
|
+
unless polymorphic_class
|
2504
2527
|
bt_assoc_name = if bt_assoc_name.underscore.end_with?('_id')
|
2505
2528
|
bt_assoc_name[-3] == '_' ? bt_assoc_name[0..-4] : bt_assoc_name[0..-3]
|
2506
2529
|
elsif bt_assoc_name.downcase.end_with?('id') && bt_assoc_name.exclude?('_')
|
@@ -2555,7 +2578,7 @@ module Brick
|
|
2555
2578
|
puts "Brick: Additional reference #{fk.inspect} refers to non-existent #{'table'.pluralize(missing.length)} #{missing.join(' and ')}. (Available tables include #{tables.join(', ')}.)"
|
2556
2579
|
return
|
2557
2580
|
end
|
2558
|
-
unless (cols = relations[fk[1]][:cols]).key?(fk[2]) || (
|
2581
|
+
unless (cols = relations[fk[1]][:cols]).key?(fk[2]) || (polymorphic_class && cols.key?("#{fk[2]}_id") && cols.key?("#{fk[2]}_type"))
|
2559
2582
|
columns = cols.map { |k, v| "#{k} (#{v.first.split(' ').first})" }
|
2560
2583
|
puts "Brick: Additional reference #{fk.inspect} refers to non-existent column #{fk[2]}. (Columns present in #{fk[1]} are #{columns.join(', ')}.)"
|
2561
2584
|
return
|
@@ -2572,9 +2595,10 @@ module Brick
|
|
2572
2595
|
return unless bts # Rails 5.0 and older can have bts end up being nil
|
2573
2596
|
|
2574
2597
|
if (assoc_bt = bts[cnstr_name])
|
2575
|
-
if
|
2598
|
+
if polymorphic_class
|
2576
2599
|
# Assuming same fk (don't yet support composite keys for polymorphics)
|
2577
2600
|
assoc_bt[:inverse_table] << fk[4]
|
2601
|
+
assoc_bt[:polymorphic] << polymorphic_class
|
2578
2602
|
else # Expect we could have a composite key going
|
2579
2603
|
if assoc_bt[:fk].is_a?(String)
|
2580
2604
|
assoc_bt[:fk] = [assoc_bt[:fk], fk[2]] unless fk[2] == assoc_bt[:fk]
|
@@ -2584,10 +2608,10 @@ module Brick
|
|
2584
2608
|
assoc_bt[:assoc_name] = "#{assoc_bt[:assoc_name]}_#{fk[2]}"
|
2585
2609
|
end
|
2586
2610
|
else
|
2587
|
-
inverse_table = [primary_table] if
|
2611
|
+
inverse_table = [primary_table] if polymorphic_class
|
2588
2612
|
assoc_bt = bts[cnstr_name] = { is_bt: true, fk: fk[2], assoc_name: bt_assoc_name, inverse_table: inverse_table || primary_table }
|
2589
2613
|
assoc_bt[:optional] = true if is_optional
|
2590
|
-
assoc_bt[:polymorphic] =
|
2614
|
+
assoc_bt[:polymorphic] = [polymorphic_class] if polymorphic_class
|
2591
2615
|
end
|
2592
2616
|
if is_class
|
2593
2617
|
# For use in finding the proper :source for a HMT association that references an STI subclass
|
@@ -2613,7 +2637,7 @@ module Brick
|
|
2613
2637
|
end
|
2614
2638
|
assoc_hm = hms[hm_cnstr_name] = { is_bt: false, fk: fk[2], assoc_name: fk_namified.pluralize, alternate_name: bt_assoc_name,
|
2615
2639
|
inverse_table: inv_tbl, inverse: assoc_bt }
|
2616
|
-
assoc_hm[:polymorphic] = true if
|
2640
|
+
assoc_hm[:polymorphic] = true if polymorphic_class
|
2617
2641
|
hm_counts = relation.fetch(:hm_counts) { relation[:hm_counts] = {} }
|
2618
2642
|
this_hm_count = hm_counts[fk[1]] = hm_counts.fetch(fk[1]) { 0 } + 1
|
2619
2643
|
end
|
@@ -2671,11 +2695,13 @@ module Brick
|
|
2671
2695
|
end
|
2672
2696
|
end
|
2673
2697
|
end
|
2674
|
-
::Brick.relations.
|
2675
|
-
tbl_parts =
|
2698
|
+
::Brick.relations.map do |k, v|
|
2699
|
+
tbl_parts = k.split('.')
|
2676
2700
|
tbl_parts.shift if ::Brick.apartment_multitenant && tbl_parts.length > 1 && tbl_parts.first == ::Brick.apartment_default_tenant
|
2677
2701
|
res = tbl_parts.join('.')
|
2678
|
-
[
|
2702
|
+
[k, (model = models[res])&.last&.table_name || v[:class_name].constantize.table_name,
|
2703
|
+
migrations&.fetch(res, nil),
|
2704
|
+
model&.first]
|
2679
2705
|
end
|
2680
2706
|
end
|
2681
2707
|
|
@@ -1245,6 +1245,7 @@ erDiagram
|
|
1245
1245
|
}
|
1246
1246
|
<% end
|
1247
1247
|
# callback < %= cb_k % > erdClick
|
1248
|
+
@_brick_monetized_attributes = model.respond_to?(:monetized_attributes) ? model.monetized_attributes.values : {}
|
1248
1249
|
%>
|
1249
1250
|
</div>
|
1250
1251
|
"
|
@@ -1612,7 +1613,7 @@ end
|
|
1612
1613
|
end %>
|
1613
1614
|
</table>
|
1614
1615
|
<%
|
1615
|
-
if (description = (relation = Brick.relations[
|
1616
|
+
if (description = (relation = Brick.relations[#{model_name}.table_name])&.fetch(:description, nil)) %><%=
|
1616
1617
|
description %><br><%
|
1617
1618
|
end
|
1618
1619
|
%><%= link_to \"(See all #\{model_name.pluralize})\", see_all_path %>
|
@@ -1686,22 +1687,25 @@ end
|
|
1686
1687
|
elsif val
|
1687
1688
|
\"<span class=\\\"orphan\\\">Orphaned ID: #\{val}</span>\".html_safe
|
1688
1689
|
end %>
|
1689
|
-
<%
|
1690
|
-
|
1691
|
-
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1690
|
+
<% elsif @_brick_monetized_attributes&.include?(k)
|
1691
|
+
%><%= f.text_field(k.to_sym, html_options.merge({ value: Money.new(val.to_i).format })) %><%
|
1692
|
+
else
|
1693
|
+
col_type = if model.json_column?(col)
|
1694
|
+
:json
|
1695
|
+
elsif col&.sql_type == 'geography'
|
1696
|
+
col.sql_type
|
1697
|
+
else
|
1698
|
+
col&.type
|
1699
|
+
end
|
1697
1700
|
case (col_type ||= col&.sql_type)
|
1698
1701
|
when :string, :text
|
1699
1702
|
if is_bcrypt?(val) # || .readonly?
|
1700
1703
|
is_revert = false %>
|
1701
1704
|
<%= hide_bcrypt(val, nil, 1000) %>
|
1702
1705
|
<% elsif col_type == :string
|
1703
|
-
if model.respond_to?(:enumerized_attributes) && (
|
1704
|
-
|
1706
|
+
if model.respond_to?(:enumerized_attributes) && (attr = model.enumerized_attributes[k])&.options.present?
|
1707
|
+
enum_html_options = attr.kind_of?(Enumerize::Multiple) ? html_options.merge({ multiple: true, size: (opts = attr.options)&.length + 1 }) : html_options %>
|
1708
|
+
<%= f.select(k.to_sym, [[\"(No #\{k} chosen)\", '^^^brick_NULL^^^']] + opts, { value: val || '^^^brick_NULL^^^' }, enum_html_options) %><%
|
1705
1709
|
else %>
|
1706
1710
|
<%= f.text_field(k.to_sym, html_options) %><%
|
1707
1711
|
end
|
@@ -20,40 +20,50 @@ module Brick::Rails::FormTags
|
|
20
20
|
s << col_name
|
21
21
|
cols[col_name] = col
|
22
22
|
end
|
23
|
+
composite_bts = bts.select { |k, _v| k.is_a?(Array) }
|
24
|
+
composite_bt_names = {}
|
25
|
+
composite_bt_cols = composite_bts.each_with_object([]) do |bt, s|
|
26
|
+
composite_bt_names[bt.first.join('__')] = bt.last
|
27
|
+
bt.first.each { |bt_col| s << bt_col unless s.include?(bt_col.first) }
|
28
|
+
end
|
23
29
|
unless sequence # If no sequence is defined, start with all inclusions
|
24
30
|
cust_cols = klass._br_cust_cols
|
25
31
|
# HOT columns, kept as symbols
|
26
32
|
hots = klass._br_bt_descrip.keys.select { |k| bts.key?(k) }
|
27
|
-
sequence = col_keys
|
33
|
+
sequence = (col_keys - composite_bt_cols) +
|
34
|
+
composite_bt_names.keys + cust_cols.keys + hots +
|
35
|
+
hms_keys.reject { |assoc_name| inclusions&.exclude?(assoc_name) }
|
28
36
|
end
|
29
37
|
sequence.reject! { |nm| exclusions.include?(nm) } if exclusions
|
30
38
|
out << sequence.each_with_object(+'') do |col_name, s|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
39
|
+
if (col = cols[col_name]).is_a?(ActiveRecord::ConnectionAdapters::Column)
|
40
|
+
s << '<th '
|
41
|
+
s << "title=\"#{col.comment}\"" if col.respond_to?(:comment) && !col.comment.blank?
|
42
|
+
s << if (bt = bts[col_name])
|
43
|
+
# Allow sorting for any BT except polymorphics
|
44
|
+
"x-order=\"#{bt.first.to_s + '"' unless bt[2]}>BT " +
|
45
|
+
bt[1].map { |bt_pair| bt_pair.first.bt_link(bt.first) }.join(' ')
|
46
|
+
else # Normal column
|
47
|
+
"x-order=\"#{col_name + '"' if true}>#{col_name}"
|
48
|
+
end
|
49
|
+
elsif col # HM column
|
50
|
+
options = {}
|
51
|
+
options[col[1].inheritance_column] = col[1].name unless col[1] == col[1].base_class
|
52
|
+
s << "<th x-order=\"#{col_name + '"' if true}>#{col[2]} "
|
53
|
+
s << (col.first ? "#{col[3]}" : "#{link_to(col[3], send("#{col[1]._brick_index}_path", options))}")
|
54
|
+
elsif cust_cols.key?(col_name) # Custom column
|
55
|
+
s << "<th x-order=\"#{col_name}\">#{col_name}"
|
56
|
+
elsif col_name.is_a?(Symbol) && (hot = bts[col_name]) # has_one :through
|
57
|
+
s << "<th x-order=\"#{hot.first.to_s}\">HOT " +
|
58
|
+
hot[1].map { |hot_pair| hot_pair.first.bt_link(col_name) }.join(' ')
|
59
|
+
elsif (bt = composite_bt_names[col_name])
|
60
|
+
s << "<th x-order=\"#{bt.first.to_s + '"' unless bt[2]}>BT comp " +
|
37
61
|
bt[1].map { |bt_pair| bt_pair.first.bt_link(bt.first) }.join(' ')
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
options = {}
|
43
|
-
options[col[1].inheritance_column] = col[1].name unless col[1] == col[1].base_class
|
44
|
-
s << "<th#{' x-order="' + col_name + '"' if true}>#{col[2]} "
|
45
|
-
s << (col.first ? "#{col[3]}" : "#{link_to(col[3], send("#{col[1]._brick_index}_path", options))}")
|
46
|
-
elsif cust_cols.key?(col_name) # Custom column
|
47
|
-
s << "<th x-order=\"#{col_name}\">#{col_name}"
|
48
|
-
elsif col_name.is_a?(Symbol) && (hot = bts[col_name]) # has_one :through
|
49
|
-
s << "<th x-order=\"#{hot.first.to_s}\">HOT " +
|
50
|
-
hot[1].map { |hot_pair| hot_pair.first.bt_link(col_name) }.join(' ')
|
51
|
-
hot[1].first
|
52
|
-
else # Bad column name!
|
53
|
-
s << "<th title=\"<< Unknown column >>\">#{col_name}"
|
62
|
+
else # Bad column name!
|
63
|
+
s << "<th title=\"<< Unknown column >>\">#{col_name}"
|
64
|
+
end
|
65
|
+
s << '</th>'
|
54
66
|
end
|
55
|
-
s << '</th>'
|
56
|
-
end
|
57
67
|
out << "</tr></thead>
|
58
68
|
<tbody>"
|
59
69
|
# %%% Have once gotten this error with MSSQL referring to http://localhost:3000/warehouse/cold_room_temperatures__archive
|
@@ -70,7 +80,7 @@ module Brick::Rails::FormTags
|
|
70
80
|
out << ' class=\"dimmed\"' unless cols.key?(col_name) || (cust_col = cust_cols[col_name]) ||
|
71
81
|
(col_name.is_a?(Symbol) && bts.key?(col_name)) # HOT
|
72
82
|
out << '>'
|
73
|
-
if (bt = bts[col_name])
|
83
|
+
if (bt = bts[col_name] || composite_bt_names[col_name])
|
74
84
|
if bt[2] # Polymorphic?
|
75
85
|
if (poly_id = obj.send("#{bt.first}_id"))
|
76
86
|
# Was: obj.send("#{bt.first}_type")
|
@@ -119,8 +129,12 @@ module Brick::Rails::FormTags
|
|
119
129
|
end
|
120
130
|
elsif (col = cols[col_name]).is_a?(ActiveRecord::ConnectionAdapters::Column)
|
121
131
|
# binding.pry if col.is_a?(Array)
|
122
|
-
|
123
|
-
|
132
|
+
out << if @_brick_monetized_attributes&.include?(col_name)
|
133
|
+
val ? Money.new(val.to_i).format : ''
|
134
|
+
else
|
135
|
+
col_type = col&.sql_type == 'geography' ? col.sql_type : col&.type
|
136
|
+
display_value(col_type || col&.sql_type, val).to_s
|
137
|
+
end
|
124
138
|
elsif cust_col
|
125
139
|
data = cust_col.first.map { |cc_part| obj.send(cc_part.last) }
|
126
140
|
cust_txt = klass.brick_descrip(cust_col[-2], data)
|
@@ -170,11 +184,8 @@ module Brick::Rails::FormTags
|
|
170
184
|
if klass
|
171
185
|
type_col = klass.inheritance_column # Usually 'type'
|
172
186
|
filter_parts << "#{type_col}=#{sti_type}" if sti_type && klass.column_names.include?(type_col)
|
173
|
-
path_params = request.path_parameters
|
174
|
-
path_params.delete(:controller)
|
175
|
-
path_params.delete(:action)
|
187
|
+
path_params = request.path_parameters
|
176
188
|
pk = (klass.primary_key || ActiveRecord::Base.primary_key).to_sym
|
177
|
-
# Used to also have this but it's a bit too permissive to identify a primary key: (path_params.length == 1 && path_params.values.first) ||
|
178
189
|
if ((id = (path_params[pk] || path_params[:id] || path_params["#{klass.name.underscore}_id".to_sym])) && (obj = klass.find_by(pk => id))) ||
|
179
190
|
(['show', 'edit', 'update', 'destroy'].include?(action_name) && (obj = klass.first))
|
180
191
|
obj
|
@@ -183,7 +194,18 @@ module Brick::Rails::FormTags
|
|
183
194
|
# %%% If there is a polymorphic association that might relate to stuff in the path_params,
|
184
195
|
# try to identify an appropriate ___able_id and ___able_type filter
|
185
196
|
((klass.column_names - [pk.to_s]) & path_params.keys.map(&:to_s)).each do |path_param|
|
186
|
-
|
197
|
+
next if [:controller, :action].include?(path_param)
|
198
|
+
|
199
|
+
foreign_id = path_params[path_param.to_sym]
|
200
|
+
# Need to convert a friendly_id slug to a real ID?
|
201
|
+
if Object.const_defined?('FriendlyId') &&
|
202
|
+
(assoc = klass.reflect_on_all_associations.find { |a| a.belongs_to? && a.foreign_key == path_param }) &&
|
203
|
+
(assoc_klass = assoc.klass).instance_variable_get(:@friendly_id_config) &&
|
204
|
+
(new_id = assoc_klass.where(assoc_klass.friendly_id_config.query_field => foreign_id)
|
205
|
+
.pluck(assoc_klass.primary_key).first)
|
206
|
+
foreign_id = new_id
|
207
|
+
end
|
208
|
+
filter_parts << "#{path_param}=#{foreign_id}"
|
187
209
|
end
|
188
210
|
klass
|
189
211
|
end
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -208,7 +208,7 @@ module Brick
|
|
208
208
|
if a.polymorphic?
|
209
209
|
rel_poly_bt = relations[model.table_name][:fks].find { |_k, fk| fk[:assoc_name] == a.name.to_s }
|
210
210
|
if (primary_tables = rel_poly_bt&.last&.fetch(:inverse_table, [])).is_a?(Array)
|
211
|
-
models =
|
211
|
+
models = rel_poly_bt[1][:polymorphic]&.map { |table| table.singularize.camelize.constantize }
|
212
212
|
s.first[a.foreign_key.to_s] = [a.name, models, true]
|
213
213
|
else
|
214
214
|
# This will come up when using Devise invitable when invited_by_class_name is not
|
@@ -218,7 +218,8 @@ module Brick
|
|
218
218
|
puts " belongs_to :#{a.name}, polymorphic: true"
|
219
219
|
end
|
220
220
|
else
|
221
|
-
|
221
|
+
bt_key = a.foreign_key.is_a?(Array) ? a.foreign_key : a.foreign_key.to_s
|
222
|
+
s.first[bt_key] = [a.name, a.klass]
|
222
223
|
end
|
223
224
|
else # This gets all forms of has_many and has_one
|
224
225
|
if through # has_many :through or has_one :through
|
@@ -523,8 +524,13 @@ module Brick
|
|
523
524
|
table_name, poly = k.split('.')
|
524
525
|
v ||= ActiveRecord::Base.execute_sql("SELECT DISTINCT #{poly}_type AS typ FROM #{table_name}").each_with_object([]) { |result, s| s << result['typ'] if result['typ'] }
|
525
526
|
v.each do |type|
|
526
|
-
|
527
|
-
|
527
|
+
# Allow polymorphic BT to relate to an STI subclass
|
528
|
+
base_type = ::Brick.config.sti_namespace_prefixes["::#{type}"] ||
|
529
|
+
::Brick.config.sti_namespace_prefixes.find { |k, _v| k.end_with?('::') && type.start_with?(k[2..-1]) }&.last&.[](2..-1)
|
530
|
+
if relations.key?(primary_table = (base_type || type).underscore.pluralize)
|
531
|
+
::Brick._add_bt_and_hm([nil, table_name, poly, nil, primary_table, "(brick) #{table_name}_#{poly}"], relations,
|
532
|
+
type, # Polymorphic class
|
533
|
+
is_optional)
|
528
534
|
else
|
529
535
|
missing_stis[primary_table] = type unless ::Brick.existing_stis.key?(type)
|
530
536
|
end
|
@@ -600,7 +606,8 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
600
606
|
::Rails.configuration.eager_load_namespaces.select { |ns| ns < ::Rails::Application }.each(&:eager_load!)
|
601
607
|
end
|
602
608
|
else
|
603
|
-
Zeitwerk::Loader.eager_load_all
|
609
|
+
# Same as: Zeitwerk::Loader.eager_load_all -- plus retry when something skips a beat
|
610
|
+
Zeitwerk::Registry.loaders.each { |loader| load_with_retry(loader) }
|
604
611
|
end
|
605
612
|
abstract_ar_bases = if do_ar_abstract_bases
|
606
613
|
ActiveRecord::Base.descendants.select { |ar| ar.abstract_class? }.map(&:name)
|
@@ -609,6 +616,20 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
609
616
|
abstract_ar_bases
|
610
617
|
end
|
611
618
|
|
619
|
+
# Some classes (like Phlex::Testing::Rails) will successfully auto-load after a retry
|
620
|
+
def load_with_retry(loader, autoloaded = nil)
|
621
|
+
autoloaded ||= loader.send(:autoloaded_dirs).dup
|
622
|
+
begin
|
623
|
+
loader.eager_load
|
624
|
+
rescue Zeitwerk::SetupRequired
|
625
|
+
# This is fine -- we eager load what can be eager loaded
|
626
|
+
rescue Zeitwerk::NameError
|
627
|
+
if autoloaded != (new_auto = loader.send(:autoloaded_dirs))
|
628
|
+
load_with_retry(loader, new_auto.dup) # Try one more time and it could come together
|
629
|
+
end
|
630
|
+
end
|
631
|
+
end
|
632
|
+
|
612
633
|
def display_classes(prefix, rels, max_length)
|
613
634
|
rels.sort.each do |rel|
|
614
635
|
::Brick.auto_models << rel.first
|
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.
|
4
|
+
version: 1.0.125
|
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-
|
11
|
+
date: 2023-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|