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