brick 1.0.49 → 1.0.52
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 +134 -64
- data/lib/brick/frameworks/rails/engine.rb +74 -60
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +3 -3
- 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: e3d0b398d1d3926fa3e59281c976fe2f7a54bfc16de4f99683928ce71d7ace97
|
4
|
+
data.tar.gz: 344c0de3e8691583e9a940ee451ad29015d46b0cbc55756d3b36e10d9ce27edb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0cff4e30c30d33dd13bd5a6a4a888d52e0552fc692369c42a53846da00e9ce677ab48ba840ef1396728d339984e5f7ff35d9ce33ea60f8421b9fa19edc14575
|
7
|
+
data.tar.gz: 5971fcc802dd1732f71d3bcd015e4b616f7775028a10205c7e4b9b1fa41d13c0318f581c966c223e9a0661b8b9fa52e1197ae78c007144e93ec96de61b084663
|
data/lib/brick/extensions.rb
CHANGED
@@ -221,13 +221,19 @@ module ActiveRecord
|
|
221
221
|
template
|
222
222
|
end
|
223
223
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
224
|
+
class << self
|
225
|
+
# belongs_to DSL descriptions
|
226
|
+
def _br_bt_descrip
|
227
|
+
@_br_bt_descrip ||= {}
|
228
|
+
end
|
229
|
+
# has_many count definitions
|
230
|
+
def _br_hm_counts
|
231
|
+
@_br_hm_counts ||= {}
|
232
|
+
end
|
233
|
+
# has_many :through associative tables
|
234
|
+
def _br_associatives
|
235
|
+
@_br_associatives ||= {}
|
236
|
+
end
|
231
237
|
end
|
232
238
|
|
233
239
|
# Search for BT, HM, and HMT DSL stuff
|
@@ -374,7 +380,7 @@ module ActiveRecord
|
|
374
380
|
|
375
381
|
case (ks = k.split('.')).length
|
376
382
|
when 1
|
377
|
-
next unless klass._brick_get_fks.include?(k)
|
383
|
+
next unless klass.column_names.any?(k) || klass._brick_get_fks.include?(k)
|
378
384
|
when 2
|
379
385
|
assoc_name = ks.first.to_sym
|
380
386
|
# Make sure it's a good association name and that the model has that column name
|
@@ -408,6 +414,7 @@ module ActiveRecord
|
|
408
414
|
chains = rel_dupe._brick_chains
|
409
415
|
id_for_tables = Hash.new { |h, k| h[k] = [] }
|
410
416
|
field_tbl_names = Hash.new { |h, k| h[k] = {} }
|
417
|
+
used_col_aliases = {} # Used to make sure there is not a name clash
|
411
418
|
bt_columns = klass._br_bt_descrip.each_with_object([]) do |v, s|
|
412
419
|
v.last.each do |k1, v1| # k1 is class, v1 is array of columns to snag
|
413
420
|
next if chains[k1].nil?
|
@@ -419,7 +426,12 @@ module ActiveRecord
|
|
419
426
|
|
420
427
|
# Postgres can not use DISTINCT with any columns that are XML, so for any of those just convert to text
|
421
428
|
is_xml = is_distinct && Brick.relations[sel_col.first.table_name]&.[](:cols)&.[](sel_col.last)&.first&.start_with?('xml')
|
422
|
-
|
429
|
+
# If it's not unique then also include the belongs_to association name before the column name
|
430
|
+
if used_col_aliases.key?(col_alias = "_brfk_#{v.first}__#{sel_col.last}")
|
431
|
+
col_alias = "_brfk_#{v.first}__#{v1[idx][-2..-1].map(&:to_s).join('__')}"
|
432
|
+
end
|
433
|
+
selects << "\"#{field_tbl_name}\".\"#{sel_col.last}\"#{'::text' if is_xml} AS \"#{col_alias}\""
|
434
|
+
used_col_aliases[col_alias] = nil
|
423
435
|
v1[idx] << col_alias
|
424
436
|
end
|
425
437
|
|
@@ -447,8 +459,7 @@ module ActiveRecord
|
|
447
459
|
klass._br_hm_counts.each do |k, hm|
|
448
460
|
associative = nil
|
449
461
|
count_column = if hm.options[:through]
|
450
|
-
fk_col = (associative =
|
451
|
-
hm.foreign_key if fk_col
|
462
|
+
hm.foreign_key if (fk_col = (associative = klass._br_associatives&.[](hm.name))&.foreign_key)
|
452
463
|
else
|
453
464
|
fk_col = hm.foreign_key
|
454
465
|
poly_type = hm.inverse_of.foreign_type if hm.options.key?(:as)
|
@@ -502,7 +513,7 @@ JOIN (SELECT #{selects.join(', ')}, COUNT(#{'DISTINCT ' if hm.options[:through]}
|
|
502
513
|
end
|
503
514
|
|
504
515
|
private
|
505
|
-
|
516
|
+
|
506
517
|
def shift_or_first(ary)
|
507
518
|
ary.length > 1 ? ary.shift : ary.first
|
508
519
|
end
|
@@ -536,12 +547,23 @@ JOIN (SELECT #{selects.join(', ')}, COUNT(#{'DISTINCT ' if hm.options[:through]}
|
|
536
547
|
this_module.const_set(module_name.to_sym, Module.new)
|
537
548
|
end
|
538
549
|
end
|
539
|
-
|
540
|
-
this_module.
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
550
|
+
begin
|
551
|
+
if this_module.const_defined?(class_name = module_prefixes.last.to_sym)
|
552
|
+
this_module.const_get(class_name)
|
553
|
+
else
|
554
|
+
# Build STI subclass and place it into the namespace module
|
555
|
+
this_module.const_set(class_name, klass = Class.new(self))
|
556
|
+
klass
|
557
|
+
end
|
558
|
+
rescue NameError => err
|
559
|
+
if column_names.include?(inheritance_column)
|
560
|
+
puts "Table #{table_name} has column #{inheritance_column} which ActiveRecord expects to use as its special inheritance column."
|
561
|
+
puts "Unfortunately the value \"#{type_name}\" does not seem to refer to a valid type name, greatly confusing matters. If that column is intended to be used for data and not STI, consider putting this line into your Brick initializer so that only for this table that column will not clash with ActiveRecord:"
|
562
|
+
puts " Brick.sti_type_column = { 'rails_#{inheritance_column}' => ['#{table_name}'] }"
|
563
|
+
self
|
564
|
+
else
|
565
|
+
raise
|
566
|
+
end
|
545
567
|
end
|
546
568
|
end
|
547
569
|
end
|
@@ -592,6 +614,8 @@ Module.class_exec do
|
|
592
614
|
return possible
|
593
615
|
end
|
594
616
|
class_name = args.first.to_s
|
617
|
+
# self.name is nil when a model name is requested in an .erb file
|
618
|
+
base_module = (self < ActiveRecord::Migration || !self.name) ? Object : self
|
595
619
|
# See if a file is there in the same way that ActiveSupport::Dependencies#load_missing_constant
|
596
620
|
# checks for it in ~/.rvm/gems/ruby-2.7.5/gems/activesupport-5.2.6.2/lib/active_support/dependencies.rb
|
597
621
|
# that is, checking #qualified_name_for with: from_mod, const_name
|
@@ -599,14 +623,17 @@ Module.class_exec do
|
|
599
623
|
# path_suffix = ActiveSupport::Dependencies.qualified_name_for(Object, args.first).underscore
|
600
624
|
# return self._brick_const_missing(*args) if ActiveSupport::Dependencies.search_for_file(path_suffix)
|
601
625
|
# If the file really exists, go and snag it:
|
602
|
-
if
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
return
|
607
|
-
|
608
|
-
|
609
|
-
|
626
|
+
if ActiveSupport::Dependencies.search_for_file(class_name.underscore)
|
627
|
+
return base_module._brick_const_missing(*args)
|
628
|
+
# elsif ActiveSupport::Dependencies.search_for_file(filepath) # Last-ditch effort to pick this thing up before we fill in the gaps on our own
|
629
|
+
# my_const = parent.const_missing(class_name) # ends up having: MyModule::MyClass
|
630
|
+
# return my_const
|
631
|
+
else
|
632
|
+
filepath = base_module.name&.split('::')&.[](0..-2) unless base_module == Object
|
633
|
+
filepath = ((filepath || []) + [class_name]).join('/').underscore + '.rb'
|
634
|
+
if ActiveSupport::Dependencies.search_for_file(filepath) # Last-ditch effort to pick this thing up before we fill in the gaps on our own
|
635
|
+
return base_module._brick_const_missing(*args)
|
636
|
+
end
|
610
637
|
end
|
611
638
|
|
612
639
|
relations = ::Brick.relations
|
@@ -625,7 +652,7 @@ Module.class_exec do
|
|
625
652
|
Object.send(:build_controller, self, class_name, plural_class_name, model, relations)
|
626
653
|
end
|
627
654
|
elsif (::Brick.enable_models? || ::Brick.enable_controllers?) && # Schema match?
|
628
|
-
|
655
|
+
base_module == Object && # %%% This works for Person::Person -- but also limits us to not being able to allow more than one level of namespacing
|
629
656
|
(schema_name = [(singular_table_name = class_name.underscore),
|
630
657
|
(table_name = singular_table_name.pluralize),
|
631
658
|
class_name,
|
@@ -633,7 +660,7 @@ Module.class_exec do
|
|
633
660
|
(::Brick.config.sti_namespace_prefixes&.key?("::#{class_name}::") && class_name))
|
634
661
|
# Build out a module for the schema if it's namespaced
|
635
662
|
# schema_name = schema_name.camelize
|
636
|
-
|
663
|
+
base_module.const_set(schema_name.to_sym, (built_module = Module.new))
|
637
664
|
|
638
665
|
[built_module, "module #{schema_name}; end\n"]
|
639
666
|
# # %%% Perhaps an option to use the first module just as schema, and additional modules as namespace with a table name prefix applied
|
@@ -643,8 +670,8 @@ Module.class_exec do
|
|
643
670
|
# See if a file is there in the same way that ActiveSupport::Dependencies#load_missing_constant
|
644
671
|
# checks for it in ~/.rvm/gems/ruby-2.7.5/gems/activesupport-5.2.6.2/lib/active_support/dependencies.rb
|
645
672
|
|
646
|
-
if (base_model = ::Brick.config.sti_namespace_prefixes&.fetch("::#{
|
647
|
-
|
673
|
+
if (base_model = ::Brick.config.sti_namespace_prefixes&.fetch("::#{base_module.name}::", nil)&.constantize) || # Are we part of an auto-STI namespace? ...
|
674
|
+
base_module != Object # ... or otherwise already in some namespace?
|
648
675
|
schema_name = [(singular_schema_name = name.underscore),
|
649
676
|
(schema_name = singular_schema_name.pluralize),
|
650
677
|
name,
|
@@ -657,7 +684,7 @@ Module.class_exec do
|
|
657
684
|
if base_model
|
658
685
|
schema_name = name.underscore # For the auto-STI namespace models
|
659
686
|
table_name = base_model.table_name
|
660
|
-
Object.send(:build_model,
|
687
|
+
Object.send(:build_model, base_module, inheritable_name, model_name, singular_table_name, table_name, relations, table_name)
|
661
688
|
else
|
662
689
|
# Adjust for STI if we know of a base model for the requested model name
|
663
690
|
# %%% Does not yet work with namespaced model names. Perhaps prefix with plural_class_name when doing the lookups here.
|
@@ -682,15 +709,15 @@ Module.class_exec do
|
|
682
709
|
built_class
|
683
710
|
elsif ::Brick.config.sti_namespace_prefixes&.key?("::#{class_name}") && !schema_name
|
684
711
|
# module_prefixes = type_name.split('::')
|
685
|
-
# path =
|
712
|
+
# path = base_module.name.split('::')[0..-2] + []
|
686
713
|
# module_prefixes.unshift('') unless module_prefixes.first.blank?
|
687
714
|
# candidate_file = Rails.root.join('app/models' + module_prefixes.map(&:underscore).join('/') + '.rb')
|
688
|
-
|
689
|
-
# elsif
|
715
|
+
base_module._brick_const_missing(*args)
|
716
|
+
# elsif base_module != Object
|
690
717
|
# module_parent.const_missing(*args)
|
691
718
|
else
|
692
|
-
puts "MISSING! #{
|
693
|
-
|
719
|
+
puts "MISSING! #{base_module.name} #{args.inspect} #{table_name}"
|
720
|
+
base_module._brick_const_missing(*args)
|
694
721
|
end
|
695
722
|
end
|
696
723
|
end
|
@@ -831,15 +858,15 @@ class Object
|
|
831
858
|
"#{hmt_fk}_through_#{hm.first[:assoc_name]}"
|
832
859
|
else # Use BT names to provide uniqueness
|
833
860
|
if self.name.underscore.singularize == hm.first[:alternate_name]
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
861
|
+
# Has previously been:
|
862
|
+
# # If it folds back on itself then look at the other side
|
863
|
+
# # (At this point just infer the source be the inverse of the first has_many that
|
864
|
+
# # we find that is not ourselves. If there are more than two then uh oh, can't
|
865
|
+
# # yet handle that rare circumstance!)
|
866
|
+
# other = hms.find { |hm1| hm1 != hm } # .first[:fk]
|
867
|
+
# options[:source] = other.first[:inverse][:assoc_name].to_sym
|
868
|
+
# And also has been:
|
869
|
+
# hm.first[:inverse][:assoc_name].to_sym
|
843
870
|
options[:source] = hm.last.to_sym
|
844
871
|
else
|
845
872
|
through = hm.first[:alternate_name].pluralize
|
@@ -1097,9 +1124,7 @@ class Object
|
|
1097
1124
|
is_pk_string = nil
|
1098
1125
|
if (pk_col = model&.primary_key)
|
1099
1126
|
code << " def show\n"
|
1100
|
-
code <<
|
1101
|
-
id = id.first if id.is_a?(Array) && id.length == 1
|
1102
|
-
@#{singular_table_name} = #{model.name}.find(id)\n")
|
1127
|
+
code << " #{find_by_name = "find_#{singular_table_name}"}\n"
|
1103
1128
|
code << " end\n"
|
1104
1129
|
self.define_method :show do
|
1105
1130
|
::Brick.set_db_schema(params)
|
@@ -1110,25 +1135,47 @@ class Object
|
|
1110
1135
|
params[:id]&.split(/[\/,_]/)
|
1111
1136
|
end
|
1112
1137
|
id = id.first if id.is_a?(Array) && id.length == 1
|
1113
|
-
instance_variable_set("@#{singular_table_name}".to_sym,
|
1138
|
+
instance_variable_set("@#{singular_table_name}".to_sym, find_obj)
|
1114
1139
|
end
|
1115
1140
|
end
|
1116
1141
|
|
1117
1142
|
# By default, views get marked as read-only
|
1118
|
-
unless
|
1119
|
-
code << "
|
1143
|
+
# unless model.readonly # (relation = relations[model.table_name]).key?(:isView)
|
1144
|
+
code << " def new\n"
|
1145
|
+
code << " @#{singular_table_name} = #{model.name}.new\n"
|
1146
|
+
code << " end\n"
|
1147
|
+
self.define_method :new do
|
1148
|
+
::Brick.set_db_schema(params)
|
1149
|
+
instance_variable_set("@#{singular_table_name}".to_sym, model.new)
|
1150
|
+
end
|
1151
|
+
|
1152
|
+
params_name_sym = (params_name = "#{singular_table_name}_params").to_sym
|
1120
1153
|
|
1121
|
-
|
1154
|
+
code << " def create\n"
|
1155
|
+
code << " @#{singular_table_name} = #{model.name}.create(#{params_name})\n"
|
1156
|
+
code << " end\n"
|
1157
|
+
self.define_method :create do
|
1158
|
+
::Brick.set_db_schema(params)
|
1159
|
+
instance_variable_set("@#{singular_table_name}".to_sym,
|
1160
|
+
model.send(:create, send(params_name_sym)))
|
1161
|
+
end
|
1162
|
+
|
1163
|
+
if pk_col
|
1122
1164
|
# if (schema = ::Brick.config.schema_behavior[:multitenant]&.fetch(:schema_to_analyse, nil)) && ::Brick.db_schemas&.include?(schema)
|
1123
1165
|
# ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?;", schema)
|
1124
1166
|
# end
|
1125
1167
|
|
1126
1168
|
is_need_params = true
|
1127
|
-
|
1169
|
+
code << " def edit\n"
|
1170
|
+
code << " #{find_by_name}\n"
|
1171
|
+
code << " end\n"
|
1172
|
+
self.define_method :edit do
|
1173
|
+
::Brick.set_db_schema(params)
|
1174
|
+
instance_variable_set("@#{singular_table_name}".to_sym, find_obj)
|
1175
|
+
end
|
1176
|
+
|
1128
1177
|
code << " def update\n"
|
1129
|
-
code <<
|
1130
|
-
params_name = "#{singular_table_name}_params"
|
1131
|
-
code << " @#{singular_table_name}.update(#{params_name})\n"
|
1178
|
+
code << " #{find_by_name}.update(#{params_name})\n"
|
1132
1179
|
code << " end\n"
|
1133
1180
|
self.define_method :update do
|
1134
1181
|
::Brick.set_db_schema(params)
|
@@ -1147,27 +1194,50 @@ class Object
|
|
1147
1194
|
# return
|
1148
1195
|
end
|
1149
1196
|
|
1197
|
+
instance_variable_set("@#{singular_table_name}".to_sym, (obj = find_obj))
|
1198
|
+
obj.send(:update, send(params_name_sym))
|
1199
|
+
end
|
1200
|
+
|
1201
|
+
code << " def destroy\n"
|
1202
|
+
code << " #{find_by_name}.destroy\n"
|
1203
|
+
code << " end\n"
|
1204
|
+
self.define_method :destroy do
|
1205
|
+
::Brick.set_db_schema(params)
|
1206
|
+
instance_variable_set("@#{singular_table_name}".to_sym, find_obj.send(:destroy))
|
1207
|
+
end
|
1208
|
+
end
|
1209
|
+
|
1210
|
+
code << "private\n" if pk_col || is_need_params
|
1211
|
+
|
1212
|
+
if pk_col
|
1213
|
+
code << " def find_#{singular_table_name}
|
1214
|
+
id = params[:id]&.split(/[\\/,_]/)
|
1215
|
+
@#{singular_table_name} = #{model.name}.find(id.is_a?(Array) && id.length == 1 ? id.first : id)
|
1216
|
+
end\n"
|
1217
|
+
self.define_method :find_obj do
|
1150
1218
|
id = is_pk_string ? params[:id] : params[:id]&.split(/[\/,_]/)
|
1151
|
-
|
1152
|
-
instance_variable_set("@#{singular_table_name}".to_sym, (obj = model.find(id)))
|
1153
|
-
obj = obj.first if obj.is_a?(Array)
|
1154
|
-
obj.send(:update, send(params_name = params_name.to_sym))
|
1219
|
+
model.find(id.is_a?(Array) && id.length == 1 ? id.first : id)
|
1155
1220
|
end
|
1156
1221
|
end
|
1157
1222
|
|
1158
1223
|
if is_need_params
|
1159
|
-
code << "private\n"
|
1160
1224
|
code << " def #{params_name}\n"
|
1225
|
+
permits = model.columns_hash.keys.map(&:to_sym)
|
1226
|
+
permits_txt = permits.map(&:inspect) +
|
1227
|
+
model.reflect_on_all_associations.select { |assoc| assoc.macro == :has_many && assoc.options[:through] }.map do |assoc|
|
1228
|
+
permits << { "#{assoc.name.to_s.singularize}_ids".to_sym => [] }
|
1229
|
+
"#{assoc.name.to_s.singularize}_ids: []"
|
1230
|
+
end
|
1161
1231
|
code << " params.require(:#{require_name = model.name.underscore.tr('/', '_')
|
1162
|
-
}).permit(#{
|
1232
|
+
}).permit(#{permits_txt.join(', ')})\n"
|
1163
1233
|
code << " end\n"
|
1164
1234
|
self.define_method(params_name) do
|
1165
|
-
params.require(require_name.to_sym).permit(
|
1235
|
+
params.require(require_name.to_sym).permit(permits)
|
1166
1236
|
end
|
1167
1237
|
private params_name
|
1168
1238
|
# Get column names for params from relations[model.table_name][:cols].keys
|
1169
1239
|
end
|
1170
|
-
end
|
1240
|
+
# end
|
1171
1241
|
code << "end # #{namespace_name}#{class_name}\n\n"
|
1172
1242
|
end # class definition
|
1173
1243
|
[built_controller, code]
|
@@ -58,7 +58,9 @@ module Brick
|
|
58
58
|
def template_exists?(*args, **options)
|
59
59
|
(::Brick.config.add_orphans && args.first == 'orphans') ||
|
60
60
|
_brick_template_exists?(*args, **options) ||
|
61
|
-
|
61
|
+
# Do not auto-create a template when it's searching for an application.html.erb, which comes in like: ["edit", ["games", "application"]]
|
62
|
+
((args[1].length == 1 || args[1][-1] != 'application') &&
|
63
|
+
set_brick_model(args))
|
62
64
|
end
|
63
65
|
|
64
66
|
def set_brick_model(find_args)
|
@@ -104,7 +106,7 @@ module Brick
|
|
104
106
|
path_obj_name = model_name.underscore.tr('/', '_')
|
105
107
|
table_name = obj_name.pluralize
|
106
108
|
template_link = nil
|
107
|
-
bts, hms
|
109
|
+
bts, hms = ::Brick.get_bts_and_hms(@_brick_model) # This gets BT and HM and also has_many :through (HMT)
|
108
110
|
hms_columns = [] # Used for 'index'
|
109
111
|
skip_klass_hms = ::Brick.config.skip_index_hms[model_name] || {}
|
110
112
|
hms_headers = hms.each_with_object([]) do |hm, s|
|
@@ -112,7 +114,7 @@ module Brick
|
|
112
114
|
"H#{hm_assoc.macro == :has_one ? 'O' : 'M'}#{'T' if hm_assoc.options[:through]}",
|
113
115
|
(assoc_name = hm.first)]
|
114
116
|
hm_fk_name = if hm_assoc.options[:through]
|
115
|
-
associative =
|
117
|
+
associative = @_brick_model._br_associatives[hm.first]
|
116
118
|
tbl_nm = if hm_assoc.options[:source]
|
117
119
|
associative.klass.reflect_on_association(hm_assoc.options[:source]).inverse_of&.name
|
118
120
|
else
|
@@ -131,25 +133,21 @@ module Brick
|
|
131
133
|
case args.first
|
132
134
|
when 'index'
|
133
135
|
hms_columns << if hm_assoc.macro == :has_many
|
134
|
-
set_ct = if skip_klass_hms.key?(assoc_name.to_sym)
|
135
|
-
'nil'
|
136
|
-
else
|
137
|
-
# Postgres column names are limited to 63 characters
|
138
|
-
attrib_name = "_br_#{assoc_name}_ct"[0..62]
|
139
|
-
"#{obj_name}.#{attrib_name} || 0"
|
140
|
-
end
|
141
136
|
if hm_fk_name
|
142
|
-
|
143
|
-
|
137
|
+
set_ct = if skip_klass_hms.key?(assoc_name.to_sym)
|
138
|
+
'nil'
|
139
|
+
else
|
140
|
+
# Postgres column names are limited to 63 characters
|
141
|
+
attrib_name = "_br_#{assoc_name}_ct"[0..62]
|
142
|
+
"#{obj_name}.#{attrib_name} || 0"
|
143
|
+
end
|
144
|
+
"#{hm_assoc.name}: [#{assoc_name.inspect}, #{set_ct}, #{path_keys(hm_assoc, hm_fk_name, obj_name, pk)}]"
|
144
145
|
else # %%% Would be able to remove this when multiple foreign keys to same destination becomes bulletproof
|
145
|
-
"#{assoc_name}
|
146
|
+
"#{hm_assoc.name}: [#{assoc_name.inspect}]"
|
146
147
|
end
|
147
148
|
else # has_one
|
148
149
|
# 0..62 because Postgres column names are limited to 63 characters
|
149
|
-
"
|
150
|
-
ho_txt = ho_class.brick_descrip(#{obj_name}, descrips[0..-2].map { |id| #{obj_name}.send(id.last[0..62]) }, (ho_id_col = descrips.last))
|
151
|
-
ho_id = ho_id_col.map { |id_col| #{obj_name}.send(id_col.to_sym) }
|
152
|
-
ho_id&.first ? link_to(ho_txt, send(\"#\{ho_class.base_class.name.underscore.tr('/', '_')\}_path\".to_sym, ho_id)) : ho_txt %>\n"
|
150
|
+
"#{hm_assoc.name}: [#{assoc_name.inspect}, nil, #{path_keys(hm_assoc, hm_fk_name, obj_name, pk)}]"
|
153
151
|
end
|
154
152
|
when 'show', 'update'
|
155
153
|
hm_stuff << if hm_fk_name
|
@@ -166,12 +164,12 @@ module Brick
|
|
166
164
|
# %%% If we are not auto-creating controllers (or routes) then omit by default, and if enabled anyway, such as in a development
|
167
165
|
# environment or whatever, then get either the controllers or routes list instead
|
168
166
|
apartment_default_schema = ::Brick.apartment_multitenant && Apartment.default_schema
|
169
|
-
table_options = (::Brick.relations.keys - ::Brick.config.exclude_tables).
|
167
|
+
table_options = (::Brick.relations.keys - ::Brick.config.exclude_tables).each_with_object({}) do |tbl, s|
|
170
168
|
if (tbl_parts = tbl.split('.')).first == apartment_default_schema
|
171
169
|
tbl = tbl_parts.last
|
172
170
|
end
|
173
|
-
tbl
|
174
|
-
end.sort.each_with_object(+'') do |v, s|
|
171
|
+
s[tbl] = nil
|
172
|
+
end.keys.sort.each_with_object(+'') do |v, s|
|
175
173
|
s << "<option value=\"#{v.underscore.gsub('.', '/').pluralize}\">#{v}</option>"
|
176
174
|
end.html_safe
|
177
175
|
table_options << '<option value="brick_orphans">(Orphans)</option>'.html_safe if is_orphans
|
@@ -283,8 +281,8 @@ input+svg.revert {
|
|
283
281
|
color: #FFF;
|
284
282
|
}
|
285
283
|
</style>
|
286
|
-
<% is_includes_dates = nil
|
287
284
|
|
285
|
+
<% is_includes_dates = nil
|
288
286
|
def is_bcrypt?(val)
|
289
287
|
val.is_a?(String) && val.length == 60 && val.start_with?('$2a$')
|
290
288
|
end
|
@@ -553,46 +551,46 @@ if (headerTop) {
|
|
553
551
|
<br>
|
554
552
|
<table id=\"headerTop\">
|
555
553
|
<table id=\"#{table_name}\">
|
556
|
-
<thead><tr>#{"<th x-order=\"#{pk.join(',')}\"></th>" if pk.present?}
|
554
|
+
<thead><tr>#{"<th x-order=\"#{pk.join(',')}\"></th>" if pk.present?}<%=
|
557
555
|
col_order = []
|
558
|
-
@#{table_name}.columns.each do |col|
|
559
|
-
next if (#{(pk || []).inspect}.include?(col_name = col.name) && col.type == :integer && !bts.key?(col_name)) ||
|
560
|
-
::Brick.config.metadata_columns.include?(col_name) || poly_cols.include?(col_name)
|
561
|
-
|
562
|
-
col_order << col_name
|
563
|
-
%><th<%= \" title=\\\"#\{col.comment}\\\"\".html_safe if col.respond_to?(:comment) && !col.comment.blank? %><%
|
564
|
-
if (bt = bts[col_name]) %>
|
565
|
-
<%= \" x-order=\\\"#\{bt.first}\\\"\".html_safe if true # Currently we always allow click to sort
|
566
|
-
%>>BT <%
|
567
|
-
bt[1].each do |bt_pair| %><%=
|
568
|
-
bt_pair.first.bt_link(bt.first) %> <%
|
569
|
-
end %><%
|
570
|
-
else %><%= \" x-order=\\\"#\{col_name}\\\"\".html_safe if true # Currently we always allow click to sort
|
571
|
-
%>><%= col_name %><%
|
572
|
-
end
|
573
|
-
%></th><%
|
574
|
-
end
|
575
556
|
# Consider getting the name from the association -- h.first.name -- if a more \"friendly\" alias should be used for a screwy table name
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
557
|
+
hms_hdrs = {#{hms_headers.map do |hm|
|
558
|
+
"#{hm.first.name}: [#{hm.first.name.inspect}, #{(hm.first.options[:through] && !hm.first.through_reflection).inspect}, #{hm.first.klass.name}, #{hm[1].inspect}, #{hm[2].inspect}]"
|
559
|
+
end.join(', ')}}
|
560
|
+
(@#{table_name}.columns + hms_hdrs.values).each_with_object(+'') do |col, s|
|
561
|
+
if col.is_a?(ActiveRecord::ConnectionAdapters::Column)
|
562
|
+
next if (#{(pk || []).inspect}.include?(col_name = col.name) && col.type == :integer && !bts.key?(col_name)) ||
|
563
|
+
::Brick.config.metadata_columns.include?(col_name) || poly_cols.include?(col_name)
|
564
|
+
|
565
|
+
col_order << col_name
|
566
|
+
s << if (bt = bts[col_name])
|
567
|
+
\"<th#\{' x-order=\"' + bt.first.to_s + '\"' unless bt[2]}>BT \" + # Allow sorting any BT except polymorphics
|
568
|
+
bt[1].map { |bt_pair| bt_pair.first.bt_link(bt.first) }.join(' ')
|
569
|
+
else
|
570
|
+
# Currently we always allow click to sort on non-BT columns
|
571
|
+
\"<th#\{' x-order=\"' + col_name + '\"' if true}>#\{col_name}\"
|
572
|
+
end + '</th>'
|
573
|
+
else # Currently we always allow click to sort on all HM columns (col is the hm array)
|
574
|
+
col_order << col.first # hm.name
|
575
|
+
s << \"<th#\{' x-order=\"' + col.first.to_s + '\"' if true}>\"
|
576
|
+
s << if col[1]
|
577
|
+
\"#\{col[3]} #\{col[4]}\" # %%% Would be able to remove this when multiple foreign keys to same destination becomes bulletproof
|
578
|
+
else
|
579
|
+
\"#\{col[3]} #\{link_to(col[4], send(\"#\{col[2].name.underscore.tr('/', '_').pluralize}_path\"))}\"
|
580
|
+
end + '</th>'
|
581
|
+
end
|
582
|
+
end.html_safe
|
583
|
+
%></tr></thead>
|
587
584
|
<tbody>
|
588
|
-
<% @#{table_name}.each do |#{obj_name}|
|
585
|
+
<% @#{table_name}.each do |#{obj_name}|
|
586
|
+
hms_cols = {#{hms_columns.join(', ')}} %>
|
589
587
|
<tr>#{"
|
590
588
|
<td><%= link_to '⇛', #{path_obj_name}_path(#{obj_pk}), { class: 'big-arrow' } %></td>" if obj_pk}
|
591
589
|
<% col_order.each do |col_name|
|
592
590
|
val = #{obj_name}.attributes[col_name] %>
|
593
|
-
<td
|
594
|
-
|
595
|
-
|
591
|
+
<td><%
|
592
|
+
if (bt = bts[col_name])
|
593
|
+
if bt[2] # Polymorphic?
|
596
594
|
bt_class = #{obj_name}.send(\"#\{bt.first\}_type\")
|
597
595
|
base_class = (::Brick.existing_stis[bt_class] || bt_class).constantize.base_class.name.underscore
|
598
596
|
poly_id = #{obj_name}.send(\"#\{bt.first\}_id\")
|
@@ -608,12 +606,26 @@ if (headerTop) {
|
|
608
606
|
<%= bt_id&.first ? link_to(bt_txt, send(\"#\{bt_class.base_class.name.underscore.tr('/', '_')\}_path\".to_sym, bt_id)) : bt_txt %>
|
609
607
|
<%#= Previously was: bt_obj = bt[1].first.first.find_by(bt[2] => val); link_to(bt_obj.brick_descrip, send(\"#\{bt[1].first.first.name.underscore\}_path\".to_sym, bt_obj.send(bt[1].first.first.primary_key.to_sym))) if bt_obj %>
|
610
608
|
<% end %>
|
611
|
-
<%
|
612
|
-
|
613
|
-
|
614
|
-
|
609
|
+
<% elsif (hms_col = hms_cols[col_name])
|
610
|
+
if hms_col.length == 1 %>
|
611
|
+
<%= hms_col.first %>
|
612
|
+
<% else
|
613
|
+
klass = (col = hms_hdrs[col_name])[2]
|
614
|
+
txt = if col[3] == 'HO'
|
615
|
+
descrips = @_brick_bt_descrip[col_name][klass]
|
616
|
+
ho_txt = klass.brick_descrip(#{obj_name}, descrips[0..-2].map { |id| #{obj_name}.send(id.last[0..62]) }, (ho_id_col = descrips.last))
|
617
|
+
ho_id = ho_id_col.map { |id_col| #{obj_name}.send(id_col.to_sym) }
|
618
|
+
ho_id&.first ? link_to(ho_txt, send(\"#\{klass.base_class.name.underscore.tr('/', '_')\}_path\".to_sym, ho_id)) : ho_txt
|
619
|
+
else
|
620
|
+
\"#\{hms_col[1] || 'View'\} #\{hms_col.first}\"
|
621
|
+
end %>
|
622
|
+
<%= link_to txt, send(\"#\{klass.name.underscore.tr('/', '_').pluralize}_path\".to_sym, hms_col[2]) unless hms_col[1]&.zero? %>
|
623
|
+
<% end %>
|
624
|
+
<% else
|
625
|
+
%><%= hide_bcrypt(val) %><%
|
626
|
+
end
|
627
|
+
%></td>
|
615
628
|
<% end %>
|
616
|
-
#{hms_columns.each_with_object(+'') { |hm_col, s| s << "<td>#{hm_col}</td>" }}
|
617
629
|
</tr>
|
618
630
|
<% end %>
|
619
631
|
</tbody>
|
@@ -807,7 +819,9 @@ flatpickr(\".timepicker\", {enableTime: true, noCalendar: true});
|
|
807
819
|
# %%% Create a smart javascript routine which can do this client-side %>
|
808
820
|
[... document.getElementsByTagName(\"TH\")].forEach(function (th) {
|
809
821
|
th.addEventListener(\"click\", function (e) {
|
810
|
-
|
822
|
+
var xOrder;
|
823
|
+
if (xOrder = this.getAttribute(\"x-order\"))
|
824
|
+
location.href = changeout(location.href, \"_brick_order\", xOrder);
|
811
825
|
});
|
812
826
|
});
|
813
827
|
document.querySelectorAll(\"input, select\").forEach(function (inp) {
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -172,14 +172,14 @@ module Brick
|
|
172
172
|
# Mark has_manys that go to an associative ("join") table so that they are skipped in the UI,
|
173
173
|
# as well as any possible polymorphic associations
|
174
174
|
skip_hms = {}
|
175
|
-
|
175
|
+
hms.each do |hmt|
|
176
176
|
if (through = hmt.last.options[:through])
|
177
177
|
skip_hms[through] = nil # if hms[through]
|
178
178
|
# binding.pry if !hms[through]
|
179
179
|
# End up with a hash of HMT names pointing to join-table associations
|
180
180
|
# Last part was: hmt.last.name
|
181
181
|
# Changed up because looking for: hms[:issue_issue_duplicates]
|
182
|
-
|
182
|
+
model._br_associatives[hmt.first] = hms[through] # || hms["#{(opt = hmt.last.options)[:through].to_s.singularize}_#{opt[:source].to_s.pluralize}".to_sym]
|
183
183
|
elsif hmt.last.inverse_of.nil?
|
184
184
|
puts "SKIPPING #{hmt.last.name.inspect}"
|
185
185
|
# %%% If we don't do this then below associative.name will find that associative is nil
|
@@ -187,7 +187,7 @@ module Brick
|
|
187
187
|
end
|
188
188
|
end
|
189
189
|
skip_hms.each { |k, _v| hms.delete(k) }
|
190
|
-
[bts, hms
|
190
|
+
[bts, hms]
|
191
191
|
end
|
192
192
|
|
193
193
|
# Switches Brick auto-models on or off, for all threads
|
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.52
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lorin Thwaits
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-08-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|