brick 1.0.48 → 1.0.49
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 +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
|