brick 1.0.25 → 1.0.26
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/config.rb +8 -0
- data/lib/brick/extensions.rb +26 -30
- data/lib/brick/frameworks/rails/engine.rb +22 -20
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +33 -4
- data/lib/generators/brick/install_generator.rb +78 -18
- 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: 922a55ec392e2ea9cef11c7297e4c2e4883e918130a23e49102b5a7e2442140e
|
4
|
+
data.tar.gz: 7cda213ec2e7cdccae096ef4ad8091a53a91359a1e6fabeb753cc2b579ac5c16
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b817257f9c2aedd47bc2471b12e13edc8b370b71920258755f0f9a7594060e065d022e8d4b2b360cdc41f2a60def02cfc406889d526d80088670bd64acd58be
|
7
|
+
data.tar.gz: 1ea923301103dcc53853940770861ab5c2635f1280026e0740287274c0e9bb7d566ddcf96db0d3858467b788bc9ee4b73e7bcfc61145be1bbb43775cfb859b80
|
data/lib/brick/config.rb
CHANGED
@@ -122,6 +122,14 @@ module Brick
|
|
122
122
|
@mutex.synchronize { @sti_namespace_prefixes = prefixes }
|
123
123
|
end
|
124
124
|
|
125
|
+
def schema_to_analyse
|
126
|
+
@mutex.synchronize { @schema_to_analyse }
|
127
|
+
end
|
128
|
+
|
129
|
+
def schema_to_analyse=(schema)
|
130
|
+
@mutex.synchronize { @schema_to_analyse = schema }
|
131
|
+
end
|
132
|
+
|
125
133
|
def skip_database_views
|
126
134
|
@mutex.synchronize { @skip_database_views }
|
127
135
|
end
|
data/lib/brick/extensions.rb
CHANGED
@@ -52,14 +52,6 @@ module Arel
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
# module ActiveModel
|
56
|
-
# class NotNullValidator < EachValidator
|
57
|
-
# def validate_each(record, attribute, value)
|
58
|
-
# record.errors[attribute] << "must not be null" if value.nil?
|
59
|
-
# end
|
60
|
-
# end
|
61
|
-
# end
|
62
|
-
|
63
55
|
module ActiveRecord
|
64
56
|
class Base
|
65
57
|
def self._assoc_names
|
@@ -82,7 +74,6 @@ module ActiveRecord
|
|
82
74
|
dsl
|
83
75
|
end
|
84
76
|
|
85
|
-
# Pass in true for build_array, or just pass in a JoinArray
|
86
77
|
def self.brick_parse_dsl(build_array = nil, prefix = [], translations = {}, is_polymorphic = false)
|
87
78
|
build_array = ::Brick::JoinArray.new.tap { |ary| ary.replace([build_array]) } if build_array.is_a?(::Brick::JoinHash)
|
88
79
|
build_array = ::Brick::JoinArray.new unless build_array.nil? || build_array.is_a?(Array)
|
@@ -308,6 +299,8 @@ module ActiveRecord
|
|
308
299
|
if is_add_bts || is_add_hms
|
309
300
|
bts, hms, associatives = ::Brick.get_bts_and_hms(klass)
|
310
301
|
bts.each do |_k, bt|
|
302
|
+
next if bt[2] # Polymorphic?
|
303
|
+
|
311
304
|
# join_array will receive this relation name when calling #brick_parse_dsl
|
312
305
|
bt_descrip[bt.first] = if bt[1].is_a?(Array)
|
313
306
|
bt[1].each_with_object({}) { |bt_class, s| s[bt_class] = bt_class.brick_parse_dsl(join_array, bt.first, translations, true) }
|
@@ -363,15 +356,16 @@ module ActiveRecord
|
|
363
356
|
end
|
364
357
|
# end
|
365
358
|
|
366
|
-
|
359
|
+
unless id_for_tables.key?(v.first)
|
367
360
|
# Accommodate composite primary key by allowing id_col to come in as an array
|
368
|
-
(id_col.is_a?(Array) ? id_col : [id_col]).each do |id_part|
|
369
|
-
|
370
|
-
|
361
|
+
((id_col = k1.primary_key).is_a?(Array) ? id_col : [id_col]).each do |id_part|
|
362
|
+
id_for_tables[v.first] << if id_part
|
363
|
+
selects << "#{"#{tbl_name}.#{id_part}"} AS \"#{(id_alias = "_brfk_#{v.first}__#{id_part}")}\""
|
364
|
+
id_alias
|
365
|
+
end
|
371
366
|
end
|
372
|
-
v1 << id_for_tables[v.first]
|
367
|
+
v1 << id_for_tables[v.first].compact
|
373
368
|
end
|
374
|
-
|
375
369
|
end
|
376
370
|
end
|
377
371
|
join_array.each do |assoc_name|
|
@@ -454,8 +448,7 @@ JOIN (SELECT #{selects.join(', ')}, COUNT(#{count_column}) AS _ct_ FROM #{associ
|
|
454
448
|
this_module.const_get(class_name)
|
455
449
|
else
|
456
450
|
# Build STI subclass and place it into the namespace module
|
457
|
-
|
458
|
-
puts [this_module.const_set(class_name, klass = Class.new(self)).name, class_name].inspect
|
451
|
+
this_module.const_set(class_name, klass = Class.new(self))
|
459
452
|
klass
|
460
453
|
end
|
461
454
|
end
|
@@ -530,7 +523,7 @@ class Object
|
|
530
523
|
singular_table_name = ActiveSupport::Inflector.underscore(model_name)
|
531
524
|
|
532
525
|
# Adjust for STI if we know of a base model for the requested model name
|
533
|
-
table_name = if (base_model = ::Brick.sti_models[model_name]&.fetch(:base,
|
526
|
+
table_name = if (base_model = ::Brick.sti_models[model_name]&.fetch(:base, ::Brick.existing_stis[model_name]&.constantize))
|
534
527
|
base_model.table_name
|
535
528
|
else
|
536
529
|
ActiveSupport::Inflector.pluralize(singular_table_name)
|
@@ -571,7 +564,7 @@ class Object
|
|
571
564
|
return
|
572
565
|
end
|
573
566
|
|
574
|
-
if (base_model = ::Brick.sti_models[model_name]&.fetch(:base,
|
567
|
+
if (base_model = ::Brick.sti_models[model_name]&.fetch(:base, ::Brick.existing_stis[model_name]&.constantize))
|
575
568
|
is_sti = true
|
576
569
|
else
|
577
570
|
base_model = ::Brick.config.models_inherit_from || ActiveRecord::Base
|
@@ -698,9 +691,8 @@ class Object
|
|
698
691
|
# need_class_name = ActiveSupport::Inflector.singularize(assoc_name) == ActiveSupport::Inflector.singularize(table_name.underscore)
|
699
692
|
# Are there multiple foreign keys out to the same table?
|
700
693
|
assoc_name, need_class_name = _brick_get_hm_assoc_name(relation, assoc)
|
701
|
-
# binding.pry if assoc.key?(:polymorphic)
|
702
694
|
if assoc.key?(:polymorphic)
|
703
|
-
options[:as] = assoc[:fk].to_sym
|
695
|
+
options[:as] = assoc[:fk].to_sym
|
704
696
|
else
|
705
697
|
need_fk = "#{ActiveSupport::Inflector.singularize(assoc[:inverse][:inverse_table])}_id" != assoc[:fk]
|
706
698
|
end
|
@@ -1064,12 +1056,8 @@ module Brick
|
|
1064
1056
|
bts = (relation = relations.fetch(fk[0], nil))&.fetch(:fks) { relation[:fks] = {} }
|
1065
1057
|
# %%% Do we miss out on has_many :through or even HM based on constantizing this model early?
|
1066
1058
|
# Maybe it's already gotten this info because we got as far as to say there was a unique class
|
1067
|
-
|
1068
|
-
|
1069
|
-
# else
|
1070
|
-
primary_table = (is_class = fk[2].is_a?(Hash) && fk[2].key?(:class)) ? (primary_class = fk[2][:class].constantize).table_name : fk[2]
|
1071
|
-
hms = (relation = relations.fetch(primary_table, nil))&.fetch(:fks) { relation[:fks] = {} } unless is_class
|
1072
|
-
# end
|
1059
|
+
primary_table = (is_class = fk[2].is_a?(Hash) && fk[2].key?(:class)) ? (primary_class = fk[2][:class].constantize).table_name : fk[2]
|
1060
|
+
hms = (relation = relations.fetch(primary_table, nil))&.fetch(:fks) { relation[:fks] = {} } unless is_class
|
1073
1061
|
|
1074
1062
|
unless (cnstr_name = fk[3])
|
1075
1063
|
# For any appended references (those that come from config), arrive upon a definitely unique constraint name
|
@@ -1102,8 +1090,12 @@ module Brick
|
|
1102
1090
|
if is_polymorphic
|
1103
1091
|
# Assuming same fk (don't yet support composite keys for polymorphics)
|
1104
1092
|
assoc_bt[:inverse_table] << fk[2]
|
1105
|
-
else # Expect we
|
1106
|
-
|
1093
|
+
else # Expect we could have a composite key going
|
1094
|
+
if assoc_bt[:fk].is_a?(String)
|
1095
|
+
assoc_bt[:fk] = [assoc_bt[:fk], fk[1]] unless fk[1] == assoc_bt[:fk]
|
1096
|
+
elsif assoc_bt[:fk].exclude?(fk[1])
|
1097
|
+
assoc_bt[:fk] << fk[1]
|
1098
|
+
end
|
1107
1099
|
assoc_bt[:assoc_name] = "#{assoc_bt[:assoc_name]}_#{fk[1]}"
|
1108
1100
|
end
|
1109
1101
|
else
|
@@ -1121,7 +1113,11 @@ module Brick
|
|
1121
1113
|
return if is_class || ::Brick.config.exclude_hms&.any? { |exclusion| fk[0] == exclusion[0] && fk[1] == exclusion[1] && primary_table == exclusion[2] }
|
1122
1114
|
|
1123
1115
|
if (assoc_hm = hms.fetch((hm_cnstr_name = "hm_#{cnstr_name}"), nil))
|
1124
|
-
|
1116
|
+
if assoc_bt[:fk].is_a?(String)
|
1117
|
+
assoc_bt[:fk] = [assoc_bt[:fk], fk[1]] unless fk[1] == assoc_bt[:fk]
|
1118
|
+
elsif assoc_bt[:fk].exclude?(fk[1])
|
1119
|
+
assoc_bt[:fk] << fk[1]
|
1120
|
+
end
|
1125
1121
|
assoc_hm[:alternate_name] = "#{assoc_hm[:alternate_name]}_#{bt_assoc_name}" unless assoc_hm[:alternate_name] == bt_assoc_name
|
1126
1122
|
assoc_hm[:inverse] = assoc_bt
|
1127
1123
|
else
|
@@ -210,16 +210,19 @@ def hide_bcrypt(val)
|
|
210
210
|
end %>"
|
211
211
|
|
212
212
|
if ['index', 'show', 'update'].include?(args.first)
|
213
|
+
poly_cols = []
|
213
214
|
css << "<% bts = { #{
|
214
215
|
bts.each_with_object([]) do |v, s|
|
215
|
-
foreign_models = if v.last[
|
216
|
+
foreign_models = if v.last[2] # Polymorphic?
|
217
|
+
poly_cols << @_brick_model.reflect_on_association(v[1].first).foreign_type
|
216
218
|
v.last[1].each_with_object([]) { |x, s| s << "[#{x.name}, #{x.primary_key.inspect}]" }.join(', ')
|
217
219
|
else
|
218
220
|
"[#{v.last[1].name}, #{v.last[1].primary_key.inspect}]"
|
219
221
|
end
|
220
|
-
s << "#{v.first.inspect} => [#{v.last.first.inspect}, [#{foreign_models}]]"
|
222
|
+
s << "#{v.first.inspect} => [#{v.last.first.inspect}, [#{foreign_models}], #{v.last[2].inspect}]"
|
221
223
|
end.join(', ')
|
222
|
-
} }
|
224
|
+
} }
|
225
|
+
poly_cols = #{poly_cols.inspect} %>"
|
223
226
|
end
|
224
227
|
|
225
228
|
# %%% When doing schema select, if there's an ID then remove it, or if we're on a new page go to index
|
@@ -384,7 +387,7 @@ function changeout(href, param, value) {
|
|
384
387
|
<table id=\"#{table_name}\">
|
385
388
|
<thead><tr>#{'<th></th>' if pk}
|
386
389
|
<% @#{table_name}.columns.map(&:name).each do |col| %>
|
387
|
-
<% next if col == '#{pk}' || ::Brick.config.metadata_columns.include?(col) %>
|
390
|
+
<% next if col == '#{pk}' || ::Brick.config.metadata_columns.include?(col) || poly_cols.include?(col) %>
|
388
391
|
<th>
|
389
392
|
<% if (bt = bts[col]) %>
|
390
393
|
BT <%
|
@@ -405,22 +408,22 @@ function changeout(href, param, value) {
|
|
405
408
|
<tr>#{"
|
406
409
|
<td><%= link_to '⇛', #{obj_name}_path(#{obj_pk}), { class: 'big-arrow' } %></td>" if obj_pk}
|
407
410
|
<% #{obj_name}.attributes.each do |k, val| %>
|
408
|
-
<% next if k == '#{pk}' || ::Brick.config.metadata_columns.include?(k) || k.start_with?('_brfk_') || (k.start_with?('_br_') && (k.length == 63 || k.end_with?('_ct'))) %>
|
411
|
+
<% next if k == '#{pk}' || ::Brick.config.metadata_columns.include?(k) || poly_cols.include?(k) || k.start_with?('_brfk_') || (k.start_with?('_br_') && (k.length == 63 || k.end_with?('_ct'))) %>
|
409
412
|
<td>
|
410
413
|
<% if (bt = bts[k]) %>
|
411
414
|
<%# binding.pry # Postgres column names are limited to 63 characters %>
|
412
|
-
<% if
|
415
|
+
<% if bt[2] # Polymorphic?
|
413
416
|
bt_class = #{obj_name}.send(\"#\{bt.first\}_type\")
|
414
|
-
|
417
|
+
base_class = (::Brick.existing_stis[bt_class] || bt_class).constantize.base_class.name.underscore
|
415
418
|
poly_id = #{obj_name}.send(\"#\{bt.first\}_id\")
|
416
419
|
%><%= link_to(\"#\{bt_class\} ##\{poly_id\}\",
|
417
|
-
send(\"#\{
|
418
|
-
else
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
<%= bt_id ? link_to(bt_txt, send(\"#\{bt_class.name.underscore\}_path\".to_sym, bt_id)) : bt_txt %>
|
420
|
+
send(\"#\{base_class\}_path\".to_sym, poly_id)) if poly_id %><%
|
421
|
+
else
|
422
|
+
bt_txt = (bt_class = bt[1].first.first).brick_descrip(
|
423
|
+
#{obj_name}, (descrips = @_brick_bt_descrip[bt.first][bt_class])[0..-2].map { |z| #{obj_name}.send(z.last[0..62]) }, (bt_id_col = descrips.last)
|
424
|
+
)
|
425
|
+
bt_id = #{obj_name}.send(*bt_id_col) if bt_id_col&.present? %>
|
426
|
+
<%= bt_id ? link_to(bt_txt, send(\"#\{bt_class.base_class.name.underscore\}_path\".to_sym, bt_id)) : bt_txt %>
|
424
427
|
<%#= 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 %>
|
425
428
|
<% end %>
|
426
429
|
<% else %>
|
@@ -460,9 +463,9 @@ function changeout(href, param, value) {
|
|
460
463
|
# Add a final member in this array with descriptive options to be used in <select> drop-downs
|
461
464
|
bt_name = bt[1].map { |x| x.first.name }.join('/')
|
462
465
|
# %%% Only do this if the user has permissions to edit this bt field
|
463
|
-
if
|
466
|
+
if bt[2] # Polymorphic?
|
464
467
|
poly_class_name = @#{obj_name}.first.send(\"#\{bt.first\}_type\")
|
465
|
-
bt_pair =
|
468
|
+
bt_pair = bt[1].find { |pair| pair.first.name == poly_class_name }
|
466
469
|
# descrips = @_brick_bt_descrip[bt.first][bt_class]
|
467
470
|
poly_id = @#{obj_name}.first.send(\"#\{bt.first\}_id\")
|
468
471
|
# bt_class.order(obj_pk = bt_class.primary_key).each { |obj| option_detail << [obj.brick_descrip(nil, obj_pk), obj.send(obj_pk)] }
|
@@ -470,7 +473,7 @@ function changeout(href, param, value) {
|
|
470
473
|
bt_pair = bt[1].first
|
471
474
|
end
|
472
475
|
bt_class = bt_pair.first
|
473
|
-
if bt.length <
|
476
|
+
if bt.length < 4
|
474
477
|
bt << (option_detail = [[\"(No #\{bt_name\} chosen)\", '^^^brick_NULL^^^']])
|
475
478
|
# %%% Accommodate composite keys for obj.pk at the end here
|
476
479
|
bt_class.order(obj_pk = bt_class.primary_key).each { |obj| option_detail << [obj.brick_descrip(nil, obj_pk), obj.send(obj_pk)] }
|
@@ -484,8 +487,8 @@ function changeout(href, param, value) {
|
|
484
487
|
<% if bt
|
485
488
|
html_options = { prompt: \"Select #\{bt_name\}\" }
|
486
489
|
html_options[:class] = 'dimmed' unless val %>
|
487
|
-
<%= f.select k.to_sym, bt[
|
488
|
-
<%= bt_obj = bt_class.find_by(bt_pair[1] => val); link_to('⇛', send(\"#\{bt_class.name.underscore\}_path\".to_sym, bt_obj.send(bt_class.primary_key.to_sym)), { class: 'show-arrow' }) if bt_obj %>
|
490
|
+
<%= f.select k.to_sym, bt[3], { value: val || '^^^brick_NULL^^^' }, html_options %>
|
491
|
+
<%= bt_obj = bt_class.find_by(bt_pair[1] => val); link_to('⇛', send(\"#\{bt_class.base_class.name.underscore\}_path\".to_sym, bt_obj.send(bt_class.primary_key.to_sym)), { class: 'show-arrow' }) if bt_obj %>
|
489
492
|
<% else case #{model_name}.column_for_attribute(k).type
|
490
493
|
when :string, :text %>
|
491
494
|
<% if is_bcrypt?(val) # || .readonly? %>
|
@@ -538,7 +541,6 @@ function changeout(href, param, value) {
|
|
538
541
|
#{script}"
|
539
542
|
|
540
543
|
end
|
541
|
-
puts inline
|
542
544
|
# As if it were an inline template (see #determine_template in actionview-5.2.6.2/lib/action_view/renderer/template_renderer.rb)
|
543
545
|
keys = options.has_key?(:locals) ? options[:locals].keys : []
|
544
546
|
handler = ActionView::Template.handler_for_extension(options[:type] || 'erb')
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -85,12 +85,16 @@ module Brick
|
|
85
85
|
@sti_models ||= {}
|
86
86
|
end
|
87
87
|
|
88
|
+
def self.existing_stis
|
89
|
+
@existing_stis ||= Brick.config.sti_namespace_prefixes.each_with_object({}) { |snp, s| s[snp.first[2..-1]] = snp.last unless snp.first.end_with?('::') }
|
90
|
+
end
|
91
|
+
|
88
92
|
class << self
|
89
93
|
attr_accessor :db_schemas
|
90
94
|
|
91
95
|
def set_db_schema(params)
|
92
96
|
schema = params['_brick_schema'] || 'public'
|
93
|
-
ActiveRecord::Base.
|
97
|
+
ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?;", schema) if schema && ::Brick.db_schemas&.include?(schema)
|
94
98
|
end
|
95
99
|
|
96
100
|
# All tables and views (what Postgres calls "relations" including column and foreign key info)
|
@@ -103,14 +107,14 @@ module Brick
|
|
103
107
|
|
104
108
|
def get_bts_and_hms(model)
|
105
109
|
bts, hms = model.reflect_on_all_associations.each_with_object([{}, {}]) do |a, s|
|
106
|
-
next if
|
110
|
+
next if !const_defined?(a.name.to_s.singularize.camelize) && ::Brick.config.exclude_tables.include?(a.plural_name)
|
107
111
|
|
108
112
|
case a.macro
|
109
113
|
when :belongs_to
|
110
114
|
s.first[a.foreign_key] = if a.polymorphic?
|
111
115
|
primary_tables = relations[model.table_name][:fks].find { |_k, fk| fk[:assoc_name] == a.name.to_s }&.last&.fetch(:inverse_table, [])
|
112
116
|
models = primary_tables&.map { |table| table.singularize.camelize.constantize }
|
113
|
-
[a.name, models]
|
117
|
+
[a.name, models, true]
|
114
118
|
else
|
115
119
|
[a.name, a.klass]
|
116
120
|
end
|
@@ -264,6 +268,7 @@ module Brick
|
|
264
268
|
|
265
269
|
# Polymorphic associations
|
266
270
|
def polymorphics=(polys)
|
271
|
+
polys = polys.each_with_object({}) { |poly, s| s[poly] = nil } if polys.is_a?(Array)
|
267
272
|
Brick.config.polymorphics = polys || {}
|
268
273
|
end
|
269
274
|
|
@@ -279,6 +284,13 @@ module Brick
|
|
279
284
|
Brick.config.sti_namespace_prefixes = snp
|
280
285
|
end
|
281
286
|
|
287
|
+
# Database schema to use when analysing existing data, such as deriving a list of polymorphic classes
|
288
|
+
# for polymorphics in which it wasn't originally specified.
|
289
|
+
# @api public
|
290
|
+
def schema_to_analyse=(schema)
|
291
|
+
Brick.config.schema_to_analyse = schema
|
292
|
+
end
|
293
|
+
|
282
294
|
# Load additional references (virtual foreign keys)
|
283
295
|
# This is attempted early if a brick initialiser file is found, and then again as a failsafe at the end of our engine's initialisation
|
284
296
|
# %%% Maybe look for differences the second time 'round and just add new stuff instead of entirely deferring
|
@@ -289,13 +301,30 @@ module Brick
|
|
289
301
|
if (ars = ::Brick.config.additional_references) || ::Brick.config.polymorphics
|
290
302
|
ars.each { |fk| ::Brick._add_bt_and_hm(fk[0..2], relations) } if ars
|
291
303
|
if (polys = ::Brick.config.polymorphics)
|
304
|
+
if (schema = ::Brick.config.schema_to_analyse) && ::Brick.db_schemas&.include?(schema)
|
305
|
+
ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?;", schema)
|
306
|
+
end
|
307
|
+
missing_stis = {}
|
292
308
|
polys.each do |k, v|
|
293
309
|
table_name, poly = k.split('.')
|
294
310
|
v ||= ActiveRecord::Base.execute_sql("SELECT DISTINCT #{poly}_type AS typ FROM #{table_name}").map { |result| result['typ'] }
|
295
311
|
v.each do |type|
|
296
|
-
|
312
|
+
if relations.key?(primary_table = type.underscore.pluralize)
|
313
|
+
::Brick._add_bt_and_hm([table_name, poly, primary_table, "(brick) #{table_name}_#{poly}"], relations, true)
|
314
|
+
else
|
315
|
+
missing_stis[primary_table] = type unless ::Brick.existing_stis.key?(type)
|
316
|
+
end
|
297
317
|
end
|
298
318
|
end
|
319
|
+
unless missing_stis.empty?
|
320
|
+
print "
|
321
|
+
You might be missing an STI namespace prefix entry for these tables: #{missing_stis.keys.join(', ')}.
|
322
|
+
In config/initializers/brick.rb appropriate entries would look something like:
|
323
|
+
Brick.sti_namespace_prefixes = {"
|
324
|
+
puts missing_stis.map { |_k, missing_sti| "\n '::#{missing_sti}' => 'YourParentModel'" }.join(',')
|
325
|
+
puts " }
|
326
|
+
(Just trade out YourParentModel with some more appropriate one.)"
|
327
|
+
end
|
299
328
|
end
|
300
329
|
@_additional_references_loaded = true
|
301
330
|
end
|
@@ -19,11 +19,31 @@ module Brick
|
|
19
19
|
|
20
20
|
def create_initializer_file
|
21
21
|
unless File.exist?(filename = 'config/initializers/brick.rb')
|
22
|
-
# See if we can make suggestions for additional_references
|
23
|
-
resembles_fks = []
|
24
|
-
|
25
|
-
|
22
|
+
# See if we can make suggestions for additional_references and polymorphic associations
|
23
|
+
resembles_fks = Hash.new { |h, k| h[k] = [] }
|
24
|
+
possible_polymorphics = {}
|
25
|
+
possible_additional_references = (relations = ::Brick.relations).each_with_object(Hash.new { |h, k| h[k] = [] }) do |v, s|
|
26
|
+
model_filename = "app/models/#{ActiveSupport::Inflector.singularize(v.first)}.rb"
|
27
|
+
v.last[:cols].each do |col, type|
|
26
28
|
col_down = col.downcase
|
29
|
+
|
30
|
+
if (is_possible_poly = ['character varying', 'text'].include?(type.first))
|
31
|
+
if col_down.end_with?('_type') &&
|
32
|
+
poly_type_cut_length = -6
|
33
|
+
col_down = col_down[0..-6]
|
34
|
+
elsif col_down.end_with?('type')
|
35
|
+
poly_type_cut_length = -5
|
36
|
+
col_down = col_down[0..-5]
|
37
|
+
else
|
38
|
+
is_possible_poly = false
|
39
|
+
end
|
40
|
+
is_possible_poly = false if col_down.length < 6 # Was it simply called "type" or something else really short?
|
41
|
+
if is_possible_poly && !File.exist?(model_filename) # Make sure a model file isn't present
|
42
|
+
possible_polymorphics["#{v.first}.#{col_down}"] = "'#{v.first}.#{col[0..poly_type_cut_length]}'"
|
43
|
+
next
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
27
47
|
is_possible = true
|
28
48
|
if col_down.end_with?('_id')
|
29
49
|
col_down = col_down[0..-4]
|
@@ -40,30 +60,48 @@ module Brick
|
|
40
60
|
if col_down.start_with?('fk_')
|
41
61
|
is_possible = true
|
42
62
|
col_down = col_down[3..-1]
|
63
|
+
elsif col_down.start_with?('fk')
|
64
|
+
is_possible = true
|
65
|
+
col_down = col_down[2..-1]
|
43
66
|
end
|
44
67
|
# This possible key not really a primary key and not yet used as a foreign key?
|
45
68
|
if is_possible && !(relation = relations.fetch(v.first, {}))[:pkey].first&.last&.include?(col) &&
|
46
69
|
!relations.fetch(v.first, {})[:fks]&.any? { |_k, v| v[:is_bt] && v[:fk] == col }
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
70
|
+
# Starting to look promising ... make sure a model file isn't present
|
71
|
+
if !File.exist?(model_filename)
|
72
|
+
if (relations.fetch(f_table = col_down, nil) ||
|
73
|
+
relations.fetch(f_table = ActiveSupport::Inflector.pluralize(col_down), nil)) &&
|
74
|
+
s["#{v.first}.#{col_down}"] << "['#{v.first}', '#{col}', '#{f_table}']"
|
75
|
+
else
|
76
|
+
resembles_fks["#{v.first}.#{col_down}"] << "#{v.first}.#{col}"
|
77
|
+
end
|
54
78
|
end
|
55
79
|
end
|
56
80
|
end
|
57
|
-
s
|
58
81
|
end
|
59
82
|
|
60
|
-
|
83
|
+
possible_polymorphics.each_key do |k|
|
84
|
+
# Also matching one of the FK suggestions means it could be polymorphic,
|
85
|
+
# so delete any suggestions for a FK of the same name and only recommend
|
86
|
+
# the polymorphic association.
|
87
|
+
if resembles_fks.key?(k)
|
88
|
+
resembles_fks.delete(k)
|
89
|
+
elsif possible_additional_references.key?(k)
|
90
|
+
possible_additional_references.delete(k)
|
91
|
+
else
|
92
|
+
# While this one has a type, it's missing a corresponding ID column so it isn't polymorphic
|
93
|
+
possible_polymorphics.delete(k)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
resembles_fks = resembles_fks.values.flatten
|
97
|
+
|
98
|
+
bar = case (possible_additional_references = possible_additional_references.values.flatten).length
|
61
99
|
when 0
|
62
100
|
+"# Brick.additional_references = [['orders', 'customer_id', 'customer'],
|
63
101
|
# ['customer', 'region_id', 'regions']]"
|
64
102
|
when 1
|
65
103
|
+"# # Here is a possible additional reference that has been auto-identified for the #{ActiveRecord::Base.connection.current_database} database:
|
66
|
-
# Brick.additional_references = [
|
104
|
+
# Brick.additional_references = [#{possible_additional_references.first}]"
|
67
105
|
else
|
68
106
|
+"# # Here are possible additional references that have been auto-identified for the #{ActiveRecord::Base.connection.current_database} database:
|
69
107
|
# Brick.additional_references = [
|
@@ -75,6 +113,26 @@ module Brick
|
|
75
113
|
# # #{resembles_fks.join(', ')}"
|
76
114
|
end
|
77
115
|
|
116
|
+
poly = case (possible_polymorphics = possible_polymorphics.values.flatten).length
|
117
|
+
when 0
|
118
|
+
" like this:
|
119
|
+
# Brick.polymorphics = [
|
120
|
+
# 'comments.commentable',
|
121
|
+
# 'images.imageable'
|
122
|
+
# ]"
|
123
|
+
when 1
|
124
|
+
".
|
125
|
+
# # Here is a possible polymorphic association that has been auto-identified for the #{ActiveRecord::Base.connection.current_database} database:
|
126
|
+
# Brick.polymorphics = [#{possible_additional_references.first}]"
|
127
|
+
|
128
|
+
else
|
129
|
+
".
|
130
|
+
# # Here are possible polymorphic associations that have been auto-identified for the #{ActiveRecord::Base.connection.current_database} database:
|
131
|
+
# Brick.polymorphics = [
|
132
|
+
# #{possible_polymorphics.join(",\n# ")}
|
133
|
+
# ]"
|
134
|
+
end
|
135
|
+
|
78
136
|
create_file(filename, "# frozen_string_literal: true
|
79
137
|
|
80
138
|
# # Settings for the Brick gem
|
@@ -119,7 +177,7 @@ module Brick
|
|
119
177
|
# # Skip showing counts for these specific has_many associations when building auto-generated #index views.
|
120
178
|
# # When there are related tables with a significant number of records, this can lessen the load on the database
|
121
179
|
# # considerably, sometimes fixing what might appear to be an index page that just \"hangs\" for no apparent reason.
|
122
|
-
Brick.skip_index_hms = ['User.litany_of_woes']
|
180
|
+
# Brick.skip_index_hms = ['User.litany_of_woes']
|
123
181
|
|
124
182
|
# # By default primary tables involved in a foreign key relationship will indicate a \"has_many\" relationship pointing
|
125
183
|
# # back to the foreign table. In order to represent a \"has_one\" association instead, an override can be provided
|
@@ -157,9 +215,11 @@ Brick.skip_index_hms = ['User.litany_of_woes']
|
|
157
215
|
# Brick.sti_namespace_prefixes = { '::Animals::' => 'Animal',
|
158
216
|
# '::Snake' => 'Reptile' }
|
159
217
|
|
160
|
-
# #
|
161
|
-
# #
|
162
|
-
# Brick.
|
218
|
+
# # Database schema to use when analysing existing data, such as deriving a list of polymorphic classes in the case that
|
219
|
+
# # it wasn't originally specified.
|
220
|
+
# Brick.schema_to_analyse = 'engineering'
|
221
|
+
|
222
|
+
# # Polymorphic associations are set up by providing a model name and polymorphic association name#{poly}
|
163
223
|
|
164
224
|
# # If a default route is not supplied, Brick attempts to find the most \"central\" table and wires up the default
|
165
225
|
# # route to go to the :index action for what would be a controller for that table. You can specify any controller
|
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.26
|
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-05-
|
11
|
+
date: 2022-05-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|