brick 1.0.123 → 1.0.125
Sign up to get free protection for your applications and to get access to all the features.
- 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
|