brick 1.0.50 → 1.0.53
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 +128 -52
- data/lib/brick/frameworks/rails/engine.rb +159 -72
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +9 -0
- 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: 737256fad5c987fa2ac603cf3708da959127a33ab9b27d164ceff858b71987b9
|
4
|
+
data.tar.gz: 144352db7686d19d9c330887069287da88de456276cc17aaeeaeb3c1de7a3281
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83ec370e06c18bf9d62ec3ed445daf78dc5cbff825a85ff017cc7b814efb62f86e68022f7577734dd01ddf7e2f74b4b59de4b40b9c07656e83d0859ba6a4333d
|
7
|
+
data.tar.gz: 9106373ca7878dcc75c596f1fa44d420980c50cb09f5b63a1110d4e02dc63f02dafe3d1bc0d4de38a75d5678d964e3b8f12a720a722d2f593934e2f6be97f818
|
data/lib/brick/extensions.rb
CHANGED
@@ -547,12 +547,23 @@ JOIN (SELECT #{selects.join(', ')}, COUNT(#{'DISTINCT ' if hm.options[:through]}
|
|
547
547
|
this_module.const_set(module_name.to_sym, Module.new)
|
548
548
|
end
|
549
549
|
end
|
550
|
-
|
551
|
-
this_module.
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
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
|
556
567
|
end
|
557
568
|
end
|
558
569
|
end
|
@@ -603,6 +614,8 @@ Module.class_exec do
|
|
603
614
|
return possible
|
604
615
|
end
|
605
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
|
606
619
|
# See if a file is there in the same way that ActiveSupport::Dependencies#load_missing_constant
|
607
620
|
# checks for it in ~/.rvm/gems/ruby-2.7.5/gems/activesupport-5.2.6.2/lib/active_support/dependencies.rb
|
608
621
|
# that is, checking #qualified_name_for with: from_mod, const_name
|
@@ -610,14 +623,17 @@ Module.class_exec do
|
|
610
623
|
# path_suffix = ActiveSupport::Dependencies.qualified_name_for(Object, args.first).underscore
|
611
624
|
# return self._brick_const_missing(*args) if ActiveSupport::Dependencies.search_for_file(path_suffix)
|
612
625
|
# If the file really exists, go and snag it:
|
613
|
-
if
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
return
|
618
|
-
|
619
|
-
|
620
|
-
|
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
|
621
637
|
end
|
622
638
|
|
623
639
|
relations = ::Brick.relations
|
@@ -636,7 +652,7 @@ Module.class_exec do
|
|
636
652
|
Object.send(:build_controller, self, class_name, plural_class_name, model, relations)
|
637
653
|
end
|
638
654
|
elsif (::Brick.enable_models? || ::Brick.enable_controllers?) && # Schema match?
|
639
|
-
|
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
|
640
656
|
(schema_name = [(singular_table_name = class_name.underscore),
|
641
657
|
(table_name = singular_table_name.pluralize),
|
642
658
|
class_name,
|
@@ -644,7 +660,7 @@ Module.class_exec do
|
|
644
660
|
(::Brick.config.sti_namespace_prefixes&.key?("::#{class_name}::") && class_name))
|
645
661
|
# Build out a module for the schema if it's namespaced
|
646
662
|
# schema_name = schema_name.camelize
|
647
|
-
|
663
|
+
base_module.const_set(schema_name.to_sym, (built_module = Module.new))
|
648
664
|
|
649
665
|
[built_module, "module #{schema_name}; end\n"]
|
650
666
|
# # %%% Perhaps an option to use the first module just as schema, and additional modules as namespace with a table name prefix applied
|
@@ -654,8 +670,8 @@ Module.class_exec do
|
|
654
670
|
# See if a file is there in the same way that ActiveSupport::Dependencies#load_missing_constant
|
655
671
|
# checks for it in ~/.rvm/gems/ruby-2.7.5/gems/activesupport-5.2.6.2/lib/active_support/dependencies.rb
|
656
672
|
|
657
|
-
if (base_model = ::Brick.config.sti_namespace_prefixes&.fetch("::#{
|
658
|
-
|
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?
|
659
675
|
schema_name = [(singular_schema_name = name.underscore),
|
660
676
|
(schema_name = singular_schema_name.pluralize),
|
661
677
|
name,
|
@@ -668,7 +684,7 @@ Module.class_exec do
|
|
668
684
|
if base_model
|
669
685
|
schema_name = name.underscore # For the auto-STI namespace models
|
670
686
|
table_name = base_model.table_name
|
671
|
-
Object.send(:build_model,
|
687
|
+
Object.send(:build_model, base_module, inheritable_name, model_name, singular_table_name, table_name, relations, table_name)
|
672
688
|
else
|
673
689
|
# Adjust for STI if we know of a base model for the requested model name
|
674
690
|
# %%% Does not yet work with namespaced model names. Perhaps prefix with plural_class_name when doing the lookups here.
|
@@ -693,15 +709,15 @@ Module.class_exec do
|
|
693
709
|
built_class
|
694
710
|
elsif ::Brick.config.sti_namespace_prefixes&.key?("::#{class_name}") && !schema_name
|
695
711
|
# module_prefixes = type_name.split('::')
|
696
|
-
# path =
|
712
|
+
# path = base_module.name.split('::')[0..-2] + []
|
697
713
|
# module_prefixes.unshift('') unless module_prefixes.first.blank?
|
698
714
|
# candidate_file = Rails.root.join('app/models' + module_prefixes.map(&:underscore).join('/') + '.rb')
|
699
|
-
|
700
|
-
# elsif
|
715
|
+
base_module._brick_const_missing(*args)
|
716
|
+
# elsif base_module != Object
|
701
717
|
# module_parent.const_missing(*args)
|
702
718
|
else
|
703
|
-
puts "MISSING! #{
|
704
|
-
|
719
|
+
puts "MISSING! #{base_module.name} #{args.inspect} #{table_name}"
|
720
|
+
base_module._brick_const_missing(*args)
|
705
721
|
end
|
706
722
|
end
|
707
723
|
end
|
@@ -842,15 +858,15 @@ class Object
|
|
842
858
|
"#{hmt_fk}_through_#{hm.first[:assoc_name]}"
|
843
859
|
else # Use BT names to provide uniqueness
|
844
860
|
if self.name.underscore.singularize == hm.first[:alternate_name]
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
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
|
854
870
|
options[:source] = hm.last.to_sym
|
855
871
|
else
|
856
872
|
through = hm.first[:alternate_name].pluralize
|
@@ -1100,6 +1116,11 @@ class Object
|
|
1100
1116
|
if namespace && (idx = lookup_context.prefixes.index(table_name))
|
1101
1117
|
lookup_context.prefixes[idx] = "#{namespace.name.underscore}/#{lookup_context.prefixes[idx]}"
|
1102
1118
|
end
|
1119
|
+
@_brick_excl = session[:_brick_exclude]&.split(',')&.each_with_object([]) do |excl, s|
|
1120
|
+
if (excl_parts = excl.split('.')).first == table_name
|
1121
|
+
s << excl_parts.last
|
1122
|
+
end
|
1123
|
+
end
|
1103
1124
|
@_brick_bt_descrip = model._br_bt_descrip
|
1104
1125
|
@_brick_hm_counts = model._br_hm_counts
|
1105
1126
|
@_brick_join_array = join_array
|
@@ -1108,9 +1129,7 @@ class Object
|
|
1108
1129
|
is_pk_string = nil
|
1109
1130
|
if (pk_col = model&.primary_key)
|
1110
1131
|
code << " def show\n"
|
1111
|
-
code <<
|
1112
|
-
id = id.first if id.is_a?(Array) && id.length == 1
|
1113
|
-
@#{singular_table_name} = #{model.name}.find(id)\n")
|
1132
|
+
code << " #{find_by_name = "find_#{singular_table_name}"}\n"
|
1114
1133
|
code << " end\n"
|
1115
1134
|
self.define_method :show do
|
1116
1135
|
::Brick.set_db_schema(params)
|
@@ -1121,25 +1140,59 @@ class Object
|
|
1121
1140
|
params[:id]&.split(/[\/,_]/)
|
1122
1141
|
end
|
1123
1142
|
id = id.first if id.is_a?(Array) && id.length == 1
|
1124
|
-
instance_variable_set("@#{singular_table_name}".to_sym,
|
1143
|
+
instance_variable_set("@#{singular_table_name}".to_sym, find_obj)
|
1125
1144
|
end
|
1126
1145
|
end
|
1127
1146
|
|
1128
1147
|
# By default, views get marked as read-only
|
1129
|
-
unless
|
1130
|
-
code << "
|
1148
|
+
# unless model.readonly # (relation = relations[model.table_name]).key?(:isView)
|
1149
|
+
code << " def new\n"
|
1150
|
+
code << " @#{singular_table_name} = #{model.name}.new\n"
|
1151
|
+
code << " end\n"
|
1152
|
+
self.define_method :new do
|
1153
|
+
::Brick.set_db_schema(params)
|
1154
|
+
instance_variable_set("@#{singular_table_name}".to_sym, model.new)
|
1155
|
+
end
|
1156
|
+
|
1157
|
+
params_name_sym = (params_name = "#{singular_table_name}_params").to_sym
|
1158
|
+
|
1159
|
+
code << " def create\n"
|
1160
|
+
code << " @#{singular_table_name} = #{model.name}.create(#{params_name})\n"
|
1161
|
+
code << " end\n"
|
1162
|
+
self.define_method :create do
|
1163
|
+
::Brick.set_db_schema(params)
|
1164
|
+
if (is_json = request.content_type == 'application/json') && (col = params['_brick_exclude'])
|
1165
|
+
session[:_brick_exclude] = ((session[:_brick_exclude]&.split(',') || []) + ["#{table_name}.#{col}"]).join(',')
|
1166
|
+
render json: { result: ::Brick.exclude_column(table_name, col) }
|
1167
|
+
elsif is_json && (col = params['_brick_unexclude'])
|
1168
|
+
if (excls = ((session[:_brick_exclude]&.split(',') || []) - ["#{table_name}.#{col}"]).join(',')).empty?
|
1169
|
+
session.delete(:_brick_exclude)
|
1170
|
+
else
|
1171
|
+
session[:_brick_exclude] = excls
|
1172
|
+
end
|
1173
|
+
render json: { result: ::Brick.unexclude_column(table_name, col) }
|
1174
|
+
else
|
1175
|
+
instance_variable_set("@#{singular_table_name}".to_sym,
|
1176
|
+
model.send(:create, send(params_name_sym)))
|
1177
|
+
end
|
1178
|
+
end
|
1131
1179
|
|
1132
|
-
if
|
1180
|
+
if pk_col
|
1133
1181
|
# if (schema = ::Brick.config.schema_behavior[:multitenant]&.fetch(:schema_to_analyse, nil)) && ::Brick.db_schemas&.include?(schema)
|
1134
1182
|
# ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?;", schema)
|
1135
1183
|
# end
|
1136
1184
|
|
1137
1185
|
is_need_params = true
|
1138
|
-
|
1186
|
+
code << " def edit\n"
|
1187
|
+
code << " #{find_by_name}\n"
|
1188
|
+
code << " end\n"
|
1189
|
+
self.define_method :edit do
|
1190
|
+
::Brick.set_db_schema(params)
|
1191
|
+
instance_variable_set("@#{singular_table_name}".to_sym, find_obj)
|
1192
|
+
end
|
1193
|
+
|
1139
1194
|
code << " def update\n"
|
1140
|
-
code <<
|
1141
|
-
params_name = "#{singular_table_name}_params"
|
1142
|
-
code << " @#{singular_table_name}.update(#{params_name})\n"
|
1195
|
+
code << " #{find_by_name}.update(#{params_name})\n"
|
1143
1196
|
code << " end\n"
|
1144
1197
|
self.define_method :update do
|
1145
1198
|
::Brick.set_db_schema(params)
|
@@ -1158,27 +1211,50 @@ class Object
|
|
1158
1211
|
# return
|
1159
1212
|
end
|
1160
1213
|
|
1214
|
+
instance_variable_set("@#{singular_table_name}".to_sym, (obj = find_obj))
|
1215
|
+
obj.send(:update, send(params_name_sym))
|
1216
|
+
end
|
1217
|
+
|
1218
|
+
code << " def destroy\n"
|
1219
|
+
code << " #{find_by_name}.destroy\n"
|
1220
|
+
code << " end\n"
|
1221
|
+
self.define_method :destroy do
|
1222
|
+
::Brick.set_db_schema(params)
|
1223
|
+
instance_variable_set("@#{singular_table_name}".to_sym, find_obj.send(:destroy))
|
1224
|
+
end
|
1225
|
+
end
|
1226
|
+
|
1227
|
+
code << "private\n" if pk_col || is_need_params
|
1228
|
+
|
1229
|
+
if pk_col
|
1230
|
+
code << " def find_#{singular_table_name}
|
1231
|
+
id = params[:id]&.split(/[\\/,_]/)
|
1232
|
+
@#{singular_table_name} = #{model.name}.find(id.is_a?(Array) && id.length == 1 ? id.first : id)
|
1233
|
+
end\n"
|
1234
|
+
self.define_method :find_obj do
|
1161
1235
|
id = is_pk_string ? params[:id] : params[:id]&.split(/[\/,_]/)
|
1162
|
-
|
1163
|
-
instance_variable_set("@#{singular_table_name}".to_sym, (obj = model.find(id)))
|
1164
|
-
obj = obj.first if obj.is_a?(Array)
|
1165
|
-
obj.send(:update, send(params_name = params_name.to_sym))
|
1236
|
+
model.find(id.is_a?(Array) && id.length == 1 ? id.first : id)
|
1166
1237
|
end
|
1167
1238
|
end
|
1168
1239
|
|
1169
1240
|
if is_need_params
|
1170
|
-
code << "private\n"
|
1171
1241
|
code << " def #{params_name}\n"
|
1242
|
+
permits = model.columns_hash.keys.map(&:to_sym)
|
1243
|
+
permits_txt = permits.map(&:inspect) +
|
1244
|
+
model.reflect_on_all_associations.select { |assoc| assoc.macro == :has_many && assoc.options[:through] }.map do |assoc|
|
1245
|
+
permits << { "#{assoc.name.to_s.singularize}_ids".to_sym => [] }
|
1246
|
+
"#{assoc.name.to_s.singularize}_ids: []"
|
1247
|
+
end
|
1172
1248
|
code << " params.require(:#{require_name = model.name.underscore.tr('/', '_')
|
1173
|
-
}).permit(#{
|
1249
|
+
}).permit(#{permits_txt.join(', ')})\n"
|
1174
1250
|
code << " end\n"
|
1175
1251
|
self.define_method(params_name) do
|
1176
|
-
params.require(require_name.to_sym).permit(
|
1252
|
+
params.require(require_name.to_sym).permit(permits)
|
1177
1253
|
end
|
1178
1254
|
private params_name
|
1179
1255
|
# Get column names for params from relations[model.table_name][:cols].keys
|
1180
1256
|
end
|
1181
|
-
end
|
1257
|
+
# end
|
1182
1258
|
code << "end # #{namespace_name}#{class_name}\n\n"
|
1183
1259
|
end # class definition
|
1184
1260
|
[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)
|
@@ -130,27 +132,24 @@ module Brick
|
|
130
132
|
end
|
131
133
|
case args.first
|
132
134
|
when 'index'
|
133
|
-
|
135
|
+
hm_entry = +"'#{hm_assoc.name}' => [#{assoc_name.inspect}"
|
136
|
+
hm_entry << if hm_assoc.macro == :has_many
|
137
|
+
if hm_fk_name # %%% Can remove this check when multiple foreign keys to same destination becomes bulletproof
|
134
138
|
set_ct = if skip_klass_hms.key?(assoc_name.to_sym)
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
if hm_fk_name
|
142
|
-
"<%= ct = #{set_ct}
|
143
|
-
link_to \"#\{ct || 'View'\} #{assoc_name}\", #{hm_assoc.klass.name.underscore.tr('/', '_').pluralize}_path({ #{path_keys(hm_assoc, hm_fk_name, obj_name, pk)} }) unless ct&.zero? %>\n"
|
144
|
-
else # %%% Would be able to remove this when multiple foreign keys to same destination becomes bulletproof
|
145
|
-
"#{assoc_name}\n"
|
146
|
-
end
|
147
|
-
else # has_one
|
148
|
-
# 0..62 because Postgres column names are limited to 63 characters
|
149
|
-
"<%= descrips = @_brick_bt_descrip[#{hm.first.inspect}][ho_class = #{hm[1].klass.name}]
|
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"
|
139
|
+
'nil'
|
140
|
+
else
|
141
|
+
# Postgres column names are limited to 63 characters
|
142
|
+
"#{obj_name}.#{"_br_#{assoc_name}_ct"[0..62]} || 0"
|
143
|
+
end
|
144
|
+
", #{set_ct}, #{path_keys(hm_assoc, hm_fk_name, obj_name, pk)}"
|
153
145
|
end
|
146
|
+
else # has_one
|
147
|
+
# 0..62 because Postgres column names are limited to 63 characters
|
148
|
+
", nil, #{path_keys(hm_assoc, hm_fk_name, obj_name, pk)}"
|
149
|
+
end
|
150
|
+
hm_entry << ']'
|
151
|
+
puts hm_entry
|
152
|
+
hms_columns << hm_entry
|
154
153
|
when 'show', 'update'
|
155
154
|
hm_stuff << if hm_fk_name
|
156
155
|
"<%= link_to '#{assoc_name}', #{hm_assoc.klass.name.underscore.tr('/', '_').pluralize}_path({ #{path_keys(hm_assoc, hm_fk_name, "@#{obj_name}", pk)} }) %>\n"
|
@@ -176,6 +175,9 @@ module Brick
|
|
176
175
|
end.html_safe
|
177
176
|
table_options << '<option value="brick_orphans">(Orphans)</option>'.html_safe if is_orphans
|
178
177
|
css = +"<style>
|
178
|
+
h1, h3 {
|
179
|
+
margin-bottom: 0;
|
180
|
+
}
|
179
181
|
#dropper {
|
180
182
|
background-color: #eee;
|
181
183
|
}
|
@@ -197,19 +199,41 @@ table {
|
|
197
199
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
|
198
200
|
}
|
199
201
|
|
200
|
-
|
202
|
+
tr th {
|
201
203
|
background-color: #009879;
|
202
204
|
color: #fff;
|
203
205
|
text-align: left;
|
204
206
|
}
|
205
|
-
#headerTop
|
207
|
+
#headerTop tr th {
|
208
|
+
position: relative;
|
209
|
+
}
|
210
|
+
#headerTop tr th .exclude {
|
211
|
+
position: absolute;
|
212
|
+
display: none;
|
213
|
+
top: 0;
|
214
|
+
right: 0;
|
215
|
+
}
|
216
|
+
#headerTop tr th:hover {
|
206
217
|
background-color: #18B090;
|
207
218
|
}
|
208
|
-
|
219
|
+
#exclusions {
|
220
|
+
font-size: 0.7em;
|
221
|
+
}
|
222
|
+
#exclusions div {
|
223
|
+
border: 1px solid blue;
|
224
|
+
display: inline-block;
|
225
|
+
cursor: copy;
|
226
|
+
}
|
227
|
+
#headerTop tr th:hover .exclude {
|
228
|
+
display: inline;
|
229
|
+
cursor: pointer;
|
230
|
+
color: red;
|
231
|
+
}
|
232
|
+
tr th a {
|
209
233
|
color: #80FFB8;
|
210
234
|
}
|
211
235
|
|
212
|
-
|
236
|
+
tr th, tr td {
|
213
237
|
padding: 0.2em 0.5em;
|
214
238
|
}
|
215
239
|
|
@@ -255,6 +279,7 @@ a.big-arrow {
|
|
255
279
|
}
|
256
280
|
.dimmed {
|
257
281
|
background-color: #C0C0C0;
|
282
|
+
text-align: center;
|
258
283
|
}
|
259
284
|
.orphan {
|
260
285
|
color: red;
|
@@ -283,8 +308,8 @@ input+svg.revert {
|
|
283
308
|
color: #FFF;
|
284
309
|
}
|
285
310
|
</style>
|
286
|
-
<% is_includes_dates = nil
|
287
311
|
|
312
|
+
<% is_includes_dates = nil
|
288
313
|
def is_bcrypt?(val)
|
289
314
|
val.is_a?(String) && val.length == 60 && val.start_with?('$2a$')
|
290
315
|
end
|
@@ -416,8 +441,19 @@ function setHeaderSizes() {
|
|
416
441
|
for (var i = 0; i < row.childNodes.length; ++i) {
|
417
442
|
node = row.childNodes[i];
|
418
443
|
if (node.nodeType === 1) {
|
419
|
-
var
|
420
|
-
style.minWidth = style.maxWidth = getComputedStyle(node).width;
|
444
|
+
var th = tr.childNodes[i];
|
445
|
+
th.style.minWidth = th.style.maxWidth = getComputedStyle(node).width;
|
446
|
+
if (#{pk&.present? ? 'i > 0' : 'true'}) {
|
447
|
+
// Add <span> at the end
|
448
|
+
var span = document.createElement(\"SPAN\");
|
449
|
+
span.className = \"exclude\";
|
450
|
+
span.innerHTML = \"X\";
|
451
|
+
span.addEventListener(\"click\", function (e) {
|
452
|
+
e.stopPropagation();
|
453
|
+
doFetch(\"POST\", {_brick_exclude: this.parentElement.getAttribute(\"x-order\")});
|
454
|
+
});
|
455
|
+
th.appendChild(span);
|
456
|
+
}
|
421
457
|
}
|
422
458
|
}
|
423
459
|
if (isEmpty) headerTop.appendChild(tr);
|
@@ -425,6 +461,18 @@ function setHeaderSizes() {
|
|
425
461
|
grid.style.marginTop = \"-\" + getComputedStyle(headerTop).height;
|
426
462
|
// console.log(\"end\");
|
427
463
|
}
|
464
|
+
function doFetch(method, payload, success) {
|
465
|
+
payload.authenticity_token = <%= session[:_csrf_token].inspect.html_safe %>;
|
466
|
+
if (!success) {
|
467
|
+
success = function (p) {p.text().then(function (response) {
|
468
|
+
var result = JSON.parse(response).result;
|
469
|
+
if (result) location.href = location.href;
|
470
|
+
});};
|
471
|
+
}
|
472
|
+
var options = {method: method, headers: {\"Content-Type\": \"application/json\"}};
|
473
|
+
if (payload) options.body = JSON.stringify(payload);
|
474
|
+
return fetch(location.href, options).then(success);
|
475
|
+
}
|
428
476
|
if (headerTop) {
|
429
477
|
setHeaderSizes();
|
430
478
|
window.addEventListener('resize', function(event) {
|
@@ -459,8 +507,8 @@ if (headerTop) {
|
|
459
507
|
});
|
460
508
|
btnImport.addEventListener(\"click\", function () {
|
461
509
|
fetch(changeout(<%= #{path_obj_name}_path(-1, format: :csv).inspect.html_safe %>, \"_brick_schema\", brickSchema), {
|
462
|
-
method:
|
463
|
-
headers: {
|
510
|
+
method: \"PATCH\",
|
511
|
+
headers: { \"Content-Type\": \"text/tab-separated-values\" },
|
464
512
|
body: droppedTSV
|
465
513
|
}).then(function (tsvResponse) {
|
466
514
|
btnImport.style.display = \"none\";
|
@@ -538,6 +586,7 @@ if (headerTop) {
|
|
538
586
|
if (description = (relation = Brick.relations[#{model_name}.table_name])&.fetch(:description, nil)) %><%=
|
539
587
|
description %><br><%
|
540
588
|
end
|
589
|
+
# FILTER PARAMETERS
|
541
590
|
if @_brick_params&.present? %>
|
542
591
|
<% if @_brick_params.length == 1 # %%% Does not yet work with composite keys
|
543
592
|
k, id = @_brick_params.first
|
@@ -549,55 +598,78 @@ if (headerTop) {
|
|
549
598
|
end
|
550
599
|
end %>
|
551
600
|
(<%= link_to 'See all #{model_plural.split('::').last}', #{path_obj_name.pluralize}_path %>)
|
601
|
+
<% end
|
602
|
+
# COLUMN EXCLUSIONS
|
603
|
+
if @_brick_excl&.present? %>
|
604
|
+
<div id=\"exclusions\">Excluded columns:
|
605
|
+
<% @_brick_excl.each do |excl| %>
|
606
|
+
<div class=\"colExclusion\"><%= excl %></div>
|
607
|
+
<% end %>
|
608
|
+
</div>
|
609
|
+
<script>
|
610
|
+
[... document.getElementsByClassName(\"colExclusion\")].forEach(function (excl) {
|
611
|
+
excl.addEventListener(\"click\", function () {
|
612
|
+
doFetch(\"POST\", {_brick_unexclude: this.innerHTML});
|
613
|
+
});
|
614
|
+
});
|
615
|
+
</script>
|
552
616
|
<% end %>
|
553
|
-
<br>
|
554
617
|
<table id=\"headerTop\">
|
555
618
|
<table id=\"#{table_name}\">
|
556
|
-
<thead><tr>#{"<th x-order=\"#{pk.join(',')}\"></th>" if pk.present?}
|
557
|
-
|
558
|
-
|
559
|
-
|
619
|
+
<thead><tr>#{"<th x-order=\"#{pk.join(',')}\"></th>" if pk.present?}<%=
|
620
|
+
# Consider getting the name from the association -- hm.first.name -- if a more \"friendly\" alias should be used for a screwy table name
|
621
|
+
cols = {#{hms_keys = []
|
622
|
+
hms_headers.map do |hm|
|
623
|
+
hms_keys << (assoc_name = (assoc = hm.first).name.to_s)
|
624
|
+
"#{assoc_name.inspect} => [#{(assoc.options[:through] && !assoc.through_reflection).inspect}, #{assoc.klass.name}, #{hm[1].inspect}, #{hm[2].inspect}]"
|
625
|
+
end.join(', ')}}
|
626
|
+
col_keys = @#{table_name}.columns.each_with_object([]) do |col, s|
|
627
|
+
col_name = col.name
|
628
|
+
next if @_brick_incl&.exclude?(col_name) ||
|
629
|
+
(#{(pk || []).inspect}.include?(col_name) && col.type == :integer && !bts.key?(col_name)) ||
|
560
630
|
::Brick.config.metadata_columns.include?(col_name) || poly_cols.include?(col_name)
|
561
631
|
|
562
|
-
|
563
|
-
|
564
|
-
if (bt = bts[col_name]) %>
|
565
|
-
<%= \" x-order=\\\"#\{bt.first}\\\"\".html_safe unless bt[2] # Allow sorting any BT except polymorphics
|
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><%
|
632
|
+
s << col_name
|
633
|
+
cols[col_name] = col
|
574
634
|
end
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
635
|
+
unless @_brick_sequence # If no sequence is defined, start with all inclusions
|
636
|
+
@_brick_sequence = col_keys + #{(hms_keys).inspect}.reject { |assoc_name| @_brick_incl&.exclude?(assoc_name) }
|
637
|
+
end
|
638
|
+
@_brick_sequence.reject! { |nm| @_brick_excl.include?(nm) } if @_brick_excl # Reject exclusions
|
639
|
+
@_brick_sequence.each_with_object(+'') do |col_name, s|
|
640
|
+
if (col = cols[col_name]).is_a?(ActiveRecord::ConnectionAdapters::Column)
|
641
|
+
s << '<th'
|
642
|
+
s << \" title=\\\"#\{col.comment}\\\"\" if col.respond_to?(:comment) && !col.comment.blank?
|
643
|
+
s << if (bt = bts[col_name])
|
644
|
+
# Allow sorting for any BT except polymorphics
|
645
|
+
\"#\{' x-order=\"' + bt.first.to_s + '\"' unless bt[2]}>BT \" +
|
646
|
+
bt[1].map { |bt_pair| bt_pair.first.bt_link(bt.first) }.join(' ')
|
647
|
+
else # Normal column
|
648
|
+
\"#\{' x-order=\"' + col_name + '\"' if true}>#\{col_name}\"
|
649
|
+
end
|
650
|
+
elsif col # HM column
|
651
|
+
s << \"<th#\{' x-order=\"' + col_name + '\"' if true}>#\{col[2]} \"
|
652
|
+
s << (col.first ? \"#\{col[3]}\" : \"#\{link_to(col[3], send(\"#\{col[1].name.underscore.tr('/', '_').pluralize}_path\"))}\")
|
653
|
+
else # Bad column name!
|
654
|
+
s << \"<th title=\\\"<< Unknown column >>\\\">#\{col_name}\"
|
655
|
+
end
|
656
|
+
s << '</th>'
|
657
|
+
end.html_safe
|
658
|
+
%></tr></thead>
|
587
659
|
<tbody>
|
588
|
-
<% @#{table_name}.each do |#{obj_name}|
|
660
|
+
<% @#{table_name}.each do |#{obj_name}|
|
661
|
+
hms_cols = {#{hms_columns.join(', ')}} %>
|
589
662
|
<tr>#{"
|
590
663
|
<td><%= link_to '⇛', #{path_obj_name}_path(#{obj_pk}), { class: 'big-arrow' } %></td>" if obj_pk}
|
591
|
-
<%
|
664
|
+
<% @_brick_sequence.each do |col_name|
|
592
665
|
val = #{obj_name}.attributes[col_name] %>
|
593
|
-
<td
|
594
|
-
|
595
|
-
|
666
|
+
<td<%= ' class=\"dimmed\"'.html_safe unless cols.key?(col_name)%>><%
|
667
|
+
if (bt = bts[col_name])
|
668
|
+
if bt[2] # Polymorphic?
|
596
669
|
bt_class = #{obj_name}.send(\"#\{bt.first\}_type\")
|
597
670
|
base_class = (::Brick.existing_stis[bt_class] || bt_class).constantize.base_class.name.underscore
|
598
671
|
poly_id = #{obj_name}.send(\"#\{bt.first\}_id\")
|
599
|
-
%><%= link_to(\"#\{bt_class\} ##\{poly_id\}\",
|
600
|
-
send(\"#\{base_class\}_path\".to_sym, poly_id)) if poly_id %><%
|
672
|
+
%><%= link_to(\"#\{bt_class\} ##\{poly_id\}\", send(\"#\{base_class\}_path\".to_sym, poly_id)) if poly_id %><%
|
601
673
|
else
|
602
674
|
bt_txt = (bt_class = bt[1].first.first).brick_descrip(
|
603
675
|
# 0..62 because Postgres column names are limited to 63 characters
|
@@ -606,14 +678,29 @@ if (headerTop) {
|
|
606
678
|
bt_txt ||= \"<span class=\\\"orphan\\\"><< Orphaned ID: #\{val} >></span>\".html_safe if val
|
607
679
|
bt_id = bt_id_col.map { |id_col| #{obj_name}.send(id_col.to_sym) } %>
|
608
680
|
<%= bt_id&.first ? link_to(bt_txt, send(\"#\{bt_class.base_class.name.underscore.tr('/', '_')\}_path\".to_sym, bt_id)) : bt_txt %>
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
681
|
+
<% end
|
682
|
+
elsif (hms_col = hms_cols[col_name])
|
683
|
+
if hms_col.length == 1 %>
|
684
|
+
<%= hms_col.first %>
|
685
|
+
<% else
|
686
|
+
klass = (col = cols[col_name])[1]
|
687
|
+
txt = if col[2] == 'HO'
|
688
|
+
descrips = @_brick_bt_descrip[col_name.to_sym][klass]
|
689
|
+
ho_txt = klass.brick_descrip(#{obj_name}, descrips[0..-2].map { |id| #{obj_name}.send(id.last[0..62]) }, (ho_id_col = descrips.last))
|
690
|
+
ho_id = ho_id_col.map { |id_col| #{obj_name}.send(id_col.to_sym) }
|
691
|
+
ho_id&.first ? link_to(ho_txt, send(\"#\{klass.base_class.name.underscore.tr('/', '_')\}_path\".to_sym, ho_id)) : ho_txt
|
692
|
+
else
|
693
|
+
\"#\{hms_col[1] || 'View'\} #\{hms_col.first}\"
|
694
|
+
end %>
|
695
|
+
<%= link_to txt, send(\"#\{klass.name.underscore.tr('/', '_').pluralize}_path\".to_sym, hms_col[2]) unless hms_col[1]&.zero? %>
|
696
|
+
<% end
|
697
|
+
elsif cols.key?(col_name)
|
698
|
+
%><%= hide_bcrypt(val) %><%
|
699
|
+
else # Bad column name!
|
700
|
+
%>?<%
|
701
|
+
end
|
702
|
+
%></td>
|
615
703
|
<% end %>
|
616
|
-
#{hms_columns.each_with_object(+'') { |hm_col, s| s << "<td>#{hm_col}</td>" }}
|
617
704
|
</tr>
|
618
705
|
<% end %>
|
619
706
|
</tbody>
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -190,6 +190,15 @@ module Brick
|
|
190
190
|
[bts, hms]
|
191
191
|
end
|
192
192
|
|
193
|
+
def exclude_column(table, col)
|
194
|
+
puts "Excluding #{table}.#{col}"
|
195
|
+
true
|
196
|
+
end
|
197
|
+
def unexclude_column(table, col)
|
198
|
+
puts "Unexcluding #{table}.#{col}"
|
199
|
+
true
|
200
|
+
end
|
201
|
+
|
193
202
|
# Switches Brick auto-models on or off, for all threads
|
194
203
|
# @api public
|
195
204
|
def enable_models=(value)
|
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.53
|
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-07
|
11
|
+
date: 2022-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|