brick 1.0.48 → 1.0.49
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 +24 -0
- data/lib/brick/extensions.rb +123 -48
- data/lib/brick/frameworks/rails/engine.rb +30 -9
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +5 -0
- data/lib/generators/brick/install_generator.rb +46 -2
- 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: 8b42f1ad45e6dc942ed2e875d39318f8705f9a467c0cb31f267a71a01053bfd4
|
4
|
+
data.tar.gz: 1e8f0cd1c374c5d75be4e4f1a8b659dd32b46f991c85cce4d234a6949d017e4b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 437d415278f01a2ffced31687f77324c21416e6e7ef395d6a5d3db5a1853ccfb301c01716747ba4427417164a1200100205e7b7c75443bef83f1050f01683dda
|
7
|
+
data.tar.gz: d42367f291f2900876c5263aab30280f7b5b3d9f205c4199349b9e24d35326b5457e1db8fd0d39a512f59af9691bbe44e29dd05d3384d5a0013c05ffe6447d8c
|
data/lib/brick/config.rb
CHANGED
@@ -190,6 +190,30 @@ module Brick
|
|
190
190
|
@mutex.synchronize { @table_name_prefixes = value }
|
191
191
|
end
|
192
192
|
|
193
|
+
def order
|
194
|
+
@mutex.synchronize { @order || {} }
|
195
|
+
end
|
196
|
+
|
197
|
+
# Get something like:
|
198
|
+
# Override how code sorts with:
|
199
|
+
# { 'on_call_list' => { code: "ORDER BY STRING_TO_ARRAY(code, '.')::int[]" } }
|
200
|
+
# Specify default thing to order_by with:
|
201
|
+
# { 'on_call_list' => { _brick_default: [:last_name, :first_name] } }
|
202
|
+
# { 'on_call_list' => { _brick_default: :sequence } }
|
203
|
+
def order=(orders)
|
204
|
+
@mutex.synchronize do
|
205
|
+
case (brick_default = orders.fetch(:_brick_default, nil))
|
206
|
+
when NilClass
|
207
|
+
orders[:_brick_default] = orders.keys.reject { |k| k == :_brick_default }.first
|
208
|
+
when String
|
209
|
+
orders[:_brick_default] = [brick_default.to_sym]
|
210
|
+
when Symbol
|
211
|
+
orders[:_brick_default] = [brick_default]
|
212
|
+
end
|
213
|
+
@order = orders
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
193
217
|
def metadata_columns
|
194
218
|
@mutex.synchronize { @metadata_columns }
|
195
219
|
end
|
data/lib/brick/extensions.rb
CHANGED
@@ -221,6 +221,62 @@ module ActiveRecord
|
|
221
221
|
template
|
222
222
|
end
|
223
223
|
|
224
|
+
# belongs_to DSL descriptions
|
225
|
+
def self._br_bt_descrip
|
226
|
+
@_br_bt_descrip ||= {}
|
227
|
+
end
|
228
|
+
# has_many count definitions
|
229
|
+
def self._br_hm_counts
|
230
|
+
@_br_hm_counts ||= {}
|
231
|
+
end
|
232
|
+
|
233
|
+
# Search for BT, HM, and HMT DSL stuff
|
234
|
+
def self._brick_calculate_bts_hms(translations, join_array)
|
235
|
+
bts, hms, associatives = ::Brick.get_bts_and_hms(self)
|
236
|
+
bts.each do |_k, bt|
|
237
|
+
next if bt[2] # Polymorphic?
|
238
|
+
|
239
|
+
# join_array will receive this relation name when calling #brick_parse_dsl
|
240
|
+
_br_bt_descrip[bt.first] = if bt[1].is_a?(Array)
|
241
|
+
bt[1].each_with_object({}) { |bt_class, s| s[bt_class] = bt_class.brick_parse_dsl(join_array, bt.first, translations, true) }
|
242
|
+
else
|
243
|
+
{ bt.last => bt[1].brick_parse_dsl(join_array, bt.first, translations) }
|
244
|
+
end
|
245
|
+
end
|
246
|
+
skip_klass_hms = ::Brick.config.skip_index_hms[self.name] || {}
|
247
|
+
hms.each do |k, hm|
|
248
|
+
next if skip_klass_hms.key?(k)
|
249
|
+
|
250
|
+
if hm.macro == :has_one
|
251
|
+
# For our purposes a :has_one is similar enough to a :belongs_to that we can just join forces
|
252
|
+
_br_bt_descrip[k] = { hm.klass => hm.klass.brick_parse_dsl(join_array, k, translations) }
|
253
|
+
else # Standard :has_many
|
254
|
+
_br_hm_counts[k] = hm
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def self._brick_calculate_ordering(ordering, is_do_txt = true)
|
260
|
+
quoted_table_name = table_name.split('.').map { |x| "\"#{x}\"" }.join('.')
|
261
|
+
order_by_txt = [] if is_do_txt
|
262
|
+
ordering = [ordering] if ordering && !ordering.is_a?(Array)
|
263
|
+
order_by = ordering&.map do |ord_part| # %%% If a term is also used as an eqi-condition in the WHERE clause, it can be omitted from ORDER BY
|
264
|
+
case ord_part
|
265
|
+
when String
|
266
|
+
ord_expr = ord_part.gsub('^^^', quoted_table_name)
|
267
|
+
order_by_txt&.<<("Arel.sql(#{ord_expr})")
|
268
|
+
Arel.sql(ord_expr)
|
269
|
+
else # Expecting only Symbol
|
270
|
+
ord_part = "_br_#{ord_part}_ct" if _br_hm_counts.key?(ord_part)
|
271
|
+
# Retain any reference to a bt_descrip as being a symbol
|
272
|
+
# Was: "#{quoted_table_name}.\"#{ord_part}\""
|
273
|
+
order_by_txt&.<<(_br_bt_descrip.key?(ord_part) ? ord_part : ord_part.inspect)
|
274
|
+
ord_part
|
275
|
+
end
|
276
|
+
end
|
277
|
+
[order_by, order_by_txt]
|
278
|
+
end
|
279
|
+
|
224
280
|
private
|
225
281
|
|
226
282
|
def self._brick_get_fks
|
@@ -310,13 +366,12 @@ module ActiveRecord
|
|
310
366
|
end
|
311
367
|
end
|
312
368
|
|
313
|
-
def brick_select(params, selects = nil,
|
314
|
-
# , is_add_bts, is_add_hms
|
315
|
-
)
|
316
|
-
is_add_bts = is_add_hms = true
|
369
|
+
def brick_select(params, selects = nil, order_by = nil, translations = {}, join_array = ::Brick::JoinArray.new)
|
317
370
|
is_distinct = nil
|
318
371
|
wheres = {}
|
319
372
|
params.each do |k, v|
|
373
|
+
next if ['_brick_schema', '_brick_order'].include?(k)
|
374
|
+
|
320
375
|
case (ks = k.split('.')).length
|
321
376
|
when 1
|
322
377
|
next unless klass._brick_get_fks.include?(k)
|
@@ -345,33 +400,6 @@ module ActiveRecord
|
|
345
400
|
end
|
346
401
|
end
|
347
402
|
|
348
|
-
# Search for BT, HM, and HMT DSL stuff
|
349
|
-
translations = {}
|
350
|
-
if is_add_bts || is_add_hms
|
351
|
-
bts, hms, associatives = ::Brick.get_bts_and_hms(klass)
|
352
|
-
bts.each do |_k, bt|
|
353
|
-
next if bt[2] # Polymorphic?
|
354
|
-
|
355
|
-
# join_array will receive this relation name when calling #brick_parse_dsl
|
356
|
-
bt_descrip[bt.first] = if bt[1].is_a?(Array)
|
357
|
-
bt[1].each_with_object({}) { |bt_class, s| s[bt_class] = bt_class.brick_parse_dsl(join_array, bt.first, translations, true) }
|
358
|
-
else
|
359
|
-
{ bt.last => bt[1].brick_parse_dsl(join_array, bt.first, translations) }
|
360
|
-
end
|
361
|
-
end
|
362
|
-
skip_klass_hms = ::Brick.config.skip_index_hms[klass.name] || {}
|
363
|
-
hms.each do |k, hm|
|
364
|
-
next if skip_klass_hms.key?(k)
|
365
|
-
|
366
|
-
if hm.macro == :has_one
|
367
|
-
# For our purposes a :has_one is similar enough to a :belongs_to that we can just join forces
|
368
|
-
bt_descrip[k] = { hm.klass => hm.klass.brick_parse_dsl(join_array, k, translations) }
|
369
|
-
else # Standard :has_many
|
370
|
-
hm_counts[k] = hm
|
371
|
-
end
|
372
|
-
end
|
373
|
-
end
|
374
|
-
|
375
403
|
if join_array.present?
|
376
404
|
left_outer_joins!(join_array)
|
377
405
|
# Without working from a duplicate, touching the AREL ast tree sets the @arel instance variable, which causes the relation to be immutable.
|
@@ -380,7 +408,7 @@ module ActiveRecord
|
|
380
408
|
chains = rel_dupe._brick_chains
|
381
409
|
id_for_tables = Hash.new { |h, k| h[k] = [] }
|
382
410
|
field_tbl_names = Hash.new { |h, k| h[k] = {} }
|
383
|
-
bt_columns =
|
411
|
+
bt_columns = klass._br_bt_descrip.each_with_object([]) do |v, s|
|
384
412
|
v.last.each do |k1, v1| # k1 is class, v1 is array of columns to snag
|
385
413
|
next if chains[k1].nil?
|
386
414
|
|
@@ -416,7 +444,7 @@ module ActiveRecord
|
|
416
444
|
end
|
417
445
|
end
|
418
446
|
# Add derived table JOIN for the has_many counts
|
419
|
-
|
447
|
+
klass._br_hm_counts.each do |k, hm|
|
420
448
|
associative = nil
|
421
449
|
count_column = if hm.options[:through]
|
422
450
|
fk_col = (associative = associatives[hm.name])&.foreign_key
|
@@ -450,12 +478,31 @@ JOIN (SELECT #{selects.join(', ')}, COUNT(#{'DISTINCT ' if hm.options[:through]}
|
|
450
478
|
joins!("#{join_clause} ON #{on_clause.join(' AND ')}")
|
451
479
|
end
|
452
480
|
where!(wheres) unless wheres.empty?
|
481
|
+
# Must parse the order_by and see if there are any symbols which refer to BT associations
|
482
|
+
# as they must be expanded to find the corresponding _br_model__column naming for each.
|
483
|
+
if order_by.present?
|
484
|
+
final_order_by = *order_by.each_with_object([]) do |v, s|
|
485
|
+
if v.is_a?(Symbol)
|
486
|
+
# Add the ordered series of columns derived from the BT based on its DSL
|
487
|
+
if (bt_cols = klass._br_bt_descrip[v])
|
488
|
+
bt_cols.values.each do |v1|
|
489
|
+
v1.each { |v2| s << v2.last if v2.length > 1 }
|
490
|
+
end
|
491
|
+
else
|
492
|
+
s << v
|
493
|
+
end
|
494
|
+
else # String stuff just comes straight through
|
495
|
+
s << v
|
496
|
+
end
|
497
|
+
end
|
498
|
+
order!(*final_order_by)
|
499
|
+
end
|
453
500
|
limit!(1000) # Don't want to get too carried away just yet
|
454
501
|
wheres unless wheres.empty? # Return the specific parameters that we did use
|
455
502
|
end
|
456
503
|
|
457
504
|
private
|
458
|
-
|
505
|
+
|
459
506
|
def shift_or_first(ary)
|
460
507
|
ary.length > 1 ? ary.shift : ary.first
|
461
508
|
end
|
@@ -926,21 +973,26 @@ class Object
|
|
926
973
|
(namespace || Object).const_set(class_name.to_sym, new_controller_class)
|
927
974
|
|
928
975
|
# Brick-specific pages
|
929
|
-
|
976
|
+
case plural_class_name
|
977
|
+
when 'BrickGem'
|
930
978
|
self.define_method :orphans do
|
931
979
|
instance_variable_set(:@orphans, ::Brick.find_orphans(::Brick.set_db_schema(params)))
|
932
980
|
end
|
933
981
|
return [new_controller_class, code + ' # BrickGem controller']
|
982
|
+
when 'BrickSwagger'
|
983
|
+
is_swagger = true # if request.format == :json)
|
934
984
|
end
|
935
985
|
|
936
|
-
unless (is_swagger = plural_class_name == 'BrickSwagger') # && request.format == :json)
|
937
|
-
code << " def index\n"
|
938
|
-
code << " @#{table_name} = #{model.name}#{pk&.present? ? ".order(#{pk.inspect})" : '.all'}\n"
|
939
|
-
code << " @#{table_name}.brick_select(params)\n"
|
940
|
-
code << " end\n"
|
941
|
-
end
|
942
986
|
self.protect_from_forgery unless: -> { self.request.format.js? }
|
943
987
|
self.define_method :index do
|
988
|
+
# We do all of this now so that bt_descrip and hm_counts are available on the model early in case the user
|
989
|
+
# wants to do an ORDER BY based on any of that
|
990
|
+
translations = {}
|
991
|
+
join_array = ::Brick::JoinArray.new
|
992
|
+
is_add_bts = is_add_hms = true
|
993
|
+
# This builds out bt_descrip and hm_counts on the model
|
994
|
+
model._brick_calculate_bts_hms(translations, join_array) if is_add_bts || is_add_hms
|
995
|
+
|
944
996
|
if is_swagger
|
945
997
|
json = { 'openapi': '3.0.1', 'info': { 'title': 'API V1', 'version': 'v1' },
|
946
998
|
'servers': [
|
@@ -990,6 +1042,32 @@ class Object
|
|
990
1042
|
render inline: json.to_json, content_type: request.format
|
991
1043
|
return
|
992
1044
|
end
|
1045
|
+
|
1046
|
+
# Normal (non-swagger) request
|
1047
|
+
|
1048
|
+
# %%% Allow params to define which columns to use for order_by
|
1049
|
+
ordering = if (order_tbl = ::Brick.config.order[table_name])
|
1050
|
+
case (order_default = order_tbl[:_brick_default])
|
1051
|
+
when Array
|
1052
|
+
order_default.map { |od_part| order_tbl[od_part] || od_part }
|
1053
|
+
when Symbol
|
1054
|
+
order_tbl[order_default] || order_default
|
1055
|
+
else
|
1056
|
+
pk
|
1057
|
+
end
|
1058
|
+
else
|
1059
|
+
pk # If it's not a custom ORDER BY, just use the key
|
1060
|
+
end
|
1061
|
+
order_by, order_by_txt = model._brick_calculate_ordering(ordering)
|
1062
|
+
if (order_params = params['_brick_order']&.split(',')&.map(&:to_sym)) # Overriding the default by providing a querystring param?
|
1063
|
+
order_by, _ = model._brick_calculate_ordering(order_params, true) # Don't do the txt part
|
1064
|
+
end
|
1065
|
+
|
1066
|
+
code << " def index\n"
|
1067
|
+
code << " @#{table_name} = #{model.name}#{pk&.present? ? ".order(#{order_by_txt.join(', ')})" : '.all'}\n"
|
1068
|
+
code << " @#{table_name}.brick_select(params)\n"
|
1069
|
+
code << " end\n"
|
1070
|
+
|
993
1071
|
::Brick.set_db_schema(params)
|
994
1072
|
if request.format == :csv # Asking for a template?
|
995
1073
|
require 'csv'
|
@@ -1003,19 +1081,16 @@ class Object
|
|
1003
1081
|
return
|
1004
1082
|
end
|
1005
1083
|
|
1006
|
-
|
1007
|
-
order = pk.each_with_object([]) { |pk_part, s| s << "#{quoted_table_name}.\"#{pk_part}\"" }
|
1008
|
-
ar_relation = order.present? ? model.order("#{order.join(', ')}") : model.all
|
1009
|
-
@_brick_params = ar_relation.brick_select(params, (selects = []), (bt_descrip = {}), (hm_counts = {}), (join_array = ::Brick::JoinArray.new))
|
1084
|
+
@_brick_params = (ar_relation = model.all).brick_select(params, (selects = []), order_by, translations, join_array)
|
1010
1085
|
# %%% Add custom HM count columns
|
1011
1086
|
# %%% What happens when the PK is composite?
|
1012
|
-
counts =
|
1087
|
+
counts = model._br_hm_counts.each_with_object([]) { |v, s| s << "_br_#{v.first}._ct_ AS _br_#{v.first}_ct" }
|
1013
1088
|
instance_variable_set("@#{table_name}".to_sym, ar_relation.dup._select!(*selects, *counts))
|
1014
1089
|
if namespace && (idx = lookup_context.prefixes.index(table_name))
|
1015
1090
|
lookup_context.prefixes[idx] = "#{namespace.name.underscore}/#{lookup_context.prefixes[idx]}"
|
1016
1091
|
end
|
1017
|
-
@_brick_bt_descrip =
|
1018
|
-
@_brick_hm_counts =
|
1092
|
+
@_brick_bt_descrip = model._br_bt_descrip
|
1093
|
+
@_brick_hm_counts = model._br_hm_counts
|
1019
1094
|
@_brick_join_array = join_array
|
1020
1095
|
end
|
1021
1096
|
|
@@ -33,6 +33,9 @@ module Brick
|
|
33
33
|
# Additional references (virtual foreign keys)
|
34
34
|
::Brick.additional_references = app.config.brick.fetch(:additional_references, nil)
|
35
35
|
|
36
|
+
# When table names have specific prefixes, automatically place them in their own module with a table_name_prefix.
|
37
|
+
::Brick.order = app.config.brick.fetch(:order, {})
|
38
|
+
|
36
39
|
# Skip creating a has_many association for these
|
37
40
|
::Brick.exclude_hms = app.config.brick.fetch(:exclude_hms, nil)
|
38
41
|
|
@@ -199,6 +202,9 @@ table thead tr th, table tr th {
|
|
199
202
|
color: #fff;
|
200
203
|
text-align: left;
|
201
204
|
}
|
205
|
+
#headerTop th:hover, #headerTop th:hover {
|
206
|
+
background-color: #18B090;
|
207
|
+
}
|
202
208
|
table thead tr th a, table tr th a {
|
203
209
|
color: #80FFB8;
|
204
210
|
}
|
@@ -547,30 +553,33 @@ if (headerTop) {
|
|
547
553
|
<br>
|
548
554
|
<table id=\"headerTop\">
|
549
555
|
<table id=\"#{table_name}\">
|
550
|
-
<thead><tr>#{
|
556
|
+
<thead><tr>#{"<th x-order=\"#{pk.join(',')}\"></th>" if pk.present?}<%
|
551
557
|
col_order = []
|
552
558
|
@#{table_name}.columns.each do |col|
|
553
559
|
next if (#{(pk || []).inspect}.include?(col_name = col.name) && col.type == :integer && !bts.key?(col_name)) ||
|
554
560
|
::Brick.config.metadata_columns.include?(col_name) || poly_cols.include?(col_name)
|
555
561
|
|
556
562
|
col_order << col_name
|
557
|
-
%><th<%= \" title
|
563
|
+
%><th<%= \" title=\\\"#\{col.comment}\\\"\".html_safe if col.respond_to?(:comment) && !col.comment.blank? %><%
|
558
564
|
if (bt = bts[col_name]) %>
|
559
|
-
|
565
|
+
<%= \" x-order=\\\"#\{bt.first}\\\"\".html_safe if true # Currently we always allow click to sort
|
566
|
+
%>>BT <%
|
560
567
|
bt[1].each do |bt_pair| %><%=
|
561
568
|
bt_pair.first.bt_link(bt.first) %> <%
|
562
569
|
end %><%
|
563
|
-
else %><%=
|
564
|
-
col_name %><%
|
570
|
+
else %><%= \" x-order=\\\"#\{col_name}\\\"\".html_safe if true # Currently we always allow click to sort
|
571
|
+
%>><%= col_name %><%
|
565
572
|
end
|
566
573
|
%></th><%
|
567
574
|
end
|
568
575
|
# Consider getting the name from the association -- h.first.name -- if a more \"friendly\" alias should be used for a screwy table name
|
569
576
|
%>#{hms_headers.map do |h|
|
577
|
+
# Currently we always allow click to sort
|
578
|
+
"<th#{" x-order=\"#{h.first.name}\"" if true}>" +
|
570
579
|
if h.first.options[:through] && !h.first.through_reflection
|
571
|
-
"
|
580
|
+
"#{h[1]} #{h[2]} %></th>" # %%% Would be able to remove this when multiple foreign keys to same destination becomes bulletproof
|
572
581
|
else
|
573
|
-
"
|
582
|
+
"#{h[1]} <%= link_to('#{h[2]}', #{h.first.klass.name.underscore.tr('/', '_').pluralize}_path) %></th>"
|
574
583
|
end
|
575
584
|
end.join
|
576
585
|
}</tr></thead>
|
@@ -658,7 +667,7 @@ end
|
|
658
667
|
<tr>
|
659
668
|
<% next if (#{(pk || []).inspect}.include?(k) && !bts.key?(k)) ||
|
660
669
|
::Brick.config.metadata_columns.include?(k) %>
|
661
|
-
<th class=\"show-field\"<%= \" title
|
670
|
+
<th class=\"show-field\"<%= \" title=\\\"#\{col.comment}\\\"\".html_safe if col.respond_to?(:comment) && !col.comment.blank? %>>
|
662
671
|
<% has_fields = true
|
663
672
|
if (bt = bts[k])
|
664
673
|
# Add a final member in this array with descriptive options to be used in <select> drop-downs
|
@@ -729,9 +738,14 @@ end
|
|
729
738
|
<% when :uuid %>
|
730
739
|
<%=
|
731
740
|
# Postgres naturally uses the +uuid_generate_v4()+ function from the uuid-ossp extension
|
732
|
-
# If it's not yet enabled then:
|
741
|
+
# If it's not yet enabled then: create extension \"uuid-ossp\";
|
733
742
|
# ActiveUUID gem created a new :uuid type
|
734
743
|
val %>
|
744
|
+
<% when :ltree %>
|
745
|
+
<%=
|
746
|
+
# In Postgres labels of data stored in a hierarchical tree-like structure
|
747
|
+
# If it's not yet enabled then: create extension ltree;
|
748
|
+
val %>
|
735
749
|
<% when :binary, :primary_key %>
|
736
750
|
<% end %>
|
737
751
|
<% end %>
|
@@ -789,6 +803,13 @@ flatpickr(\".timepicker\", {enableTime: true, noCalendar: true});
|
|
789
803
|
</script>
|
790
804
|
<% end %>
|
791
805
|
<script>
|
806
|
+
<% # Make column headers sort when clicked
|
807
|
+
# %%% Create a smart javascript routine which can do this client-side %>
|
808
|
+
[... document.getElementsByTagName(\"TH\")].forEach(function (th) {
|
809
|
+
th.addEventListener(\"click\", function (e) {
|
810
|
+
location.href = changeout(location.href, \"_brick_order\", this.getAttribute(\"x-order\"));
|
811
|
+
});
|
812
|
+
});
|
792
813
|
document.querySelectorAll(\"input, select\").forEach(function (inp) {
|
793
814
|
var origVal = getInpVal(),
|
794
815
|
prevVal = origVal;
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -283,6 +283,11 @@ module Brick
|
|
283
283
|
end
|
284
284
|
end
|
285
285
|
|
286
|
+
# @api public
|
287
|
+
def order=(value)
|
288
|
+
Brick.config.order = value
|
289
|
+
end
|
290
|
+
|
286
291
|
# Skip creating a has_many association for these
|
287
292
|
# (Uses the same exact three-part format as would define an additional_reference)
|
288
293
|
# @api public
|
@@ -159,6 +159,41 @@ module Brick
|
|
159
159
|
# # When table names have specific prefixes automatically place them in their own module with a table_name_prefix.
|
160
160
|
# Brick.table_name_prefixes = { 'nav_' => 'Navigation' }
|
161
161
|
|
162
|
+
# # COLUMN SEQUENCING AND INCLUSION / EXCLUSION
|
163
|
+
|
164
|
+
# # By default if there is a primary key present then rows in an index view are ordered by this primary key. To
|
165
|
+
# # use a different rule for doing ORDER BY, you can override this default ordering done by The Brick, for instance
|
166
|
+
# # to have the rows in a contact list sorted by email:
|
167
|
+
# Brick.order = { 'contacts' => { _brick_default: :email } }
|
168
|
+
# # or by last name then first name:
|
169
|
+
# Brick.order = { 'contacts' => { _brick_default: [:lastname, :firstname] } }
|
170
|
+
# # Totally legitimate to have the default order be the name of a belongs_to or has_many association instead of an
|
171
|
+
# # actual column name, in which case for has_many it just orders by the count of how many records are associated,
|
172
|
+
# # and for belongs_to it's based on the primary table's DSL if any is defined (since that is what is used to
|
173
|
+
# # calculate what is shown when a foreign table lists out related records). If contacts relates to addresses,
|
174
|
+
# # then this is perfectly fine:
|
175
|
+
# Brick.order = { 'contacts' => { _brick_default: :address } }
|
176
|
+
# # You can even have a specific custom clause used in the ORDER BY. In this case it is recommended to include a
|
177
|
+
# # special placeholder for the table name with the sequence \"^^^\". Here is an example of having the default
|
178
|
+
# # ordering happening on the \"code\" column, and also defining custom sorting to be done, in this case proper
|
179
|
+
# # ordering if that code is stored as a dotted numeric value:
|
180
|
+
# Brick.order = { 'document_trees' => { _brick_default: :code,
|
181
|
+
# code: \"ORDER BY STRING_TO_ARRAY(^^^.code, '.')::int[]\" } }
|
182
|
+
|
183
|
+
# # Sequence of columns for each model. This also allows you to add read-only calculated columns in the same
|
184
|
+
# # kind of way that they can be added in the include: portion of include/exclude columns, below.
|
185
|
+
# # Designated by { <table name> => [<column name>, <column name>] }
|
186
|
+
# Brick.column_sequence = { 'users' => ['email', 'profile.firstname', 'profile.lastname'] }
|
187
|
+
|
188
|
+
# # Specific columns to include or exclude for each model. If there are only inclusions then only those
|
189
|
+
# # columns show. If there are any exclusions then all non-excluded columns are attempted to be shown,
|
190
|
+
# # which negates the usefulness of inclusions except to add calculated column detail built from DSL.
|
191
|
+
# # Designated by <table name>.<column name>
|
192
|
+
# Brick.column_sequence = { 'users' => { include: ['email', 'profile.firstname', 'profile.lastname'] },
|
193
|
+
# 'profile' => { exclude: ['birthdate'] } }
|
194
|
+
|
195
|
+
# # EXTRA FOREIGN KEYS AND OTHER HAS_MANY SETTINGS
|
196
|
+
|
162
197
|
# # Additional table references which are used to create has_many / belongs_to associations inside auto-created
|
163
198
|
# # models. (You can consider these to be \"virtual foreign keys\" if you wish)... You only have to add these
|
164
199
|
# # in cases where your database for some reason does not have foreign key constraints defined. Sometimes for
|
@@ -176,8 +211,9 @@ module Brick
|
|
176
211
|
# Brick.exclude_hms = [['users', 'favourite_colour_id', 'colours']]
|
177
212
|
|
178
213
|
# # Skip showing counts for these specific has_many associations when building auto-generated #index views.
|
179
|
-
# # When there are related tables with a significant number of records, this can lessen
|
180
|
-
# # considerably, sometimes fixing what might appear to be an index page that just \"hangs\"
|
214
|
+
# # When there are related tables with a significant number of records (generally 100,000 or more), this can lessen
|
215
|
+
# # the load on the database considerably, sometimes fixing what might appear to be an index page that just \"hangs\"
|
216
|
+
# # for no apparent reason.
|
181
217
|
# Brick.skip_index_hms = ['User.litany_of_woes']
|
182
218
|
|
183
219
|
# # By default primary tables involved in a foreign key relationship will indicate a \"has_many\" relationship pointing
|
@@ -199,6 +235,8 @@ module Brick
|
|
199
235
|
# # Designated by <table name>.<column name>
|
200
236
|
# Brick.not_nullables = ['users.name']
|
201
237
|
|
238
|
+
# # FRIENDLY DSL
|
239
|
+
|
202
240
|
# # A simple DSL is available to allow more user-friendly display of objects. Normally a user object might be shown
|
203
241
|
# # as its first non-metadata column, or if that is not available then something like \"User #45\" where 45 is that
|
204
242
|
# # object's ID. If there is no primary key then even that is not possible, so the object's .to_s method is called.
|
@@ -206,6 +244,8 @@ module Brick
|
|
206
244
|
# # user, then you can use model_descrips like this, putting expressions with property references in square brackets:
|
207
245
|
# Brick.model_descrips = { 'User' => '[profile.firstname] [profile.lastname]' }
|
208
246
|
|
247
|
+
# # SINGLE TABLE INHERITANCE
|
248
|
+
|
209
249
|
# # Specify STI subclasses either directly by name or as a general module prefix that should always relate to a specific
|
210
250
|
# # parent STI class. The prefixed :: here for these examples is mandatory. Also having a suffixed :: means instead of
|
211
251
|
# # a class reference, this is for a general namespace reference. So in this case requests for, say, either of the
|
@@ -221,6 +261,8 @@ module Brick
|
|
221
261
|
# Brick.sti_type_column = 'sti_type'
|
222
262
|
# Brick.sti_type_column = { 'rails_type' => ['sales.specialoffer'] }
|
223
263
|
|
264
|
+
# # POLYMORPHIC ASSOCIATIONS
|
265
|
+
|
224
266
|
# # Database schema to use when analysing existing data, such as deriving a list of polymorphic classes in the case that
|
225
267
|
# # it wasn't originally specified.
|
226
268
|
# Brick.schema_behavior = :namespaced
|
@@ -231,6 +273,8 @@ module Brick
|
|
231
273
|
|
232
274
|
# # Polymorphic associations are set up by providing a model name and polymorphic association name#{poly}
|
233
275
|
|
276
|
+
# # DEFAULT ROOT ROUTE
|
277
|
+
|
234
278
|
# # If a default route is not supplied, Brick attempts to find the most \"central\" table and wires up the default
|
235
279
|
# # route to go to the :index action for what would be a controller for that table. You can specify any controller
|
236
280
|
# # name and action you wish in order to override this and have that be the default route when none other has been
|
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.49
|
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-07-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|