brick 1.0.108 → 1.0.110
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/compatibility.rb +31 -4
- data/lib/brick/extensions.rb +49 -18
- data/lib/brick/frameworks/rails/engine.rb +37 -19
- data/lib/brick/frameworks/rails/form_tags.rb +4 -3
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +90 -60
- data/lib/generators/brick/install_generator.rb +1 -1
- 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: 3d11240139b576ead983fbe9811f4476b8819878068c46db852b515fbc0849c6
|
|
4
|
+
data.tar.gz: 2db932779fcd8517f7e5be524ce387061d4e8cab193715be76893dc1e675d1c9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dd22a1ab8d2b13f2d289fe02262ae8aecb3be921094bbb5dd0392fe5cd46ecadda259e72a18c3ecb7daea0fd5f5a50d697383a4bb949b068976e3b6007769d04
|
|
7
|
+
data.tar.gz: 39d26f6c99511d3651003c660fed495223ebd4fb34865b1eaa3b8554e294ed0fb3672b17e7dc43ca43fecbd1b7dda2ec6b9a4371025880e12c83694f45557173
|
data/lib/brick/compatibility.rb
CHANGED
|
@@ -42,9 +42,36 @@ end
|
|
|
42
42
|
# file by having the line "require 'brick/compatibility'" to be the last line in that
|
|
43
43
|
# file.
|
|
44
44
|
require 'bigdecimal'
|
|
45
|
-
if
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
if ActiveRecord.version < ::Gem::Version.new('5.0')
|
|
46
|
+
if ::Gem::Version.new(RUBY_VERSION) >= ::Gem::Version.new('2.6')
|
|
47
|
+
def BigDecimal.new(*args, **kwargs)
|
|
48
|
+
BigDecimal(*args, **kwargs)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
if ::Gem::Version.new(RUBY_VERSION) >= ::Gem::Version.new('3.1')
|
|
52
|
+
# @@schemes fix for global_id gem < 1.0
|
|
53
|
+
URI.class_variable_set(:@@schemes, {}) unless URI.class_variables.include?(:@@schemes)
|
|
54
|
+
if Gem::Specification.all_names.find { |g| g.start_with?('puma-') }
|
|
55
|
+
require 'rack/handler/puma'
|
|
56
|
+
module Rack::Handler::Puma
|
|
57
|
+
class << self
|
|
58
|
+
alias _brick_run run
|
|
59
|
+
def run(app, *args, **options)
|
|
60
|
+
options.merge!(args.pop) if args.last.is_a?(Hash)
|
|
61
|
+
_brick_run(app, **options)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
require 'json'
|
|
68
|
+
if JSON::Parser.method(:initialize).parameters.length < 2 && JSON.method(:parse).arity == -2
|
|
69
|
+
JSON.class_exec do
|
|
70
|
+
def self.parse(source, opts = {})
|
|
71
|
+
::JSON::Parser.new(source, **opts).parse
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
49
76
|
end
|
|
50
77
|
end
|
data/lib/brick/extensions.rb
CHANGED
|
@@ -261,9 +261,16 @@ module ActiveRecord
|
|
|
261
261
|
assoc_html_name ? "#{assoc_name}-#{link}".html_safe : link
|
|
262
262
|
end
|
|
263
263
|
|
|
264
|
-
|
|
264
|
+
# Providing a relation object allows auto-modules built from table name prefixes to work
|
|
265
|
+
def self._brick_index(mode = nil, separator = '_', relation = nil)
|
|
265
266
|
tbl_parts = ((mode == :singular) ? table_name.singularize : table_name).split('.')
|
|
266
267
|
tbl_parts.shift if ::Brick.apartment_multitenant && tbl_parts.length > 1 && tbl_parts.first == ::Brick.apartment_default_tenant
|
|
268
|
+
if (aps = relation&.fetch(:auto_prefixed_schema, nil)) && tbl_parts.last.start_with?(aps)
|
|
269
|
+
last_part = tbl_parts.last[aps.length..-1]
|
|
270
|
+
aps = aps[0..-2] if aps[-1] == '_'
|
|
271
|
+
tbl_parts[-1] = aps
|
|
272
|
+
tbl_parts << last_part
|
|
273
|
+
end
|
|
267
274
|
tbl_parts.unshift(::Brick.config.path_prefix) if ::Brick.config.path_prefix
|
|
268
275
|
index = tbl_parts.map(&:underscore).join(separator)
|
|
269
276
|
# Rails applies an _index suffix to that route when the resource name is singular
|
|
@@ -421,7 +428,10 @@ module ActiveRecord
|
|
|
421
428
|
is_distinct = nil
|
|
422
429
|
wheres = {}
|
|
423
430
|
params.each do |k, v|
|
|
424
|
-
next if ['_brick_schema', '_brick_order',
|
|
431
|
+
next if ['_brick_schema', '_brick_order',
|
|
432
|
+
'_brick_erd', '_brick_exclude', '_brick_unexclude',
|
|
433
|
+
'_brick_page', '_brick_page_size', '_brick_offset', '_brick_limit',
|
|
434
|
+
'_brick_is_api', 'controller', 'action'].include?(k)
|
|
425
435
|
|
|
426
436
|
if (where_col = (ks = k.split('.')).last)[-1] == '!'
|
|
427
437
|
where_col = where_col[0..-2]
|
|
@@ -448,7 +458,10 @@ module ActiveRecord
|
|
|
448
458
|
# %%% Have once gotten this error with MSSQL referring to http://localhost:3000/warehouse/cold_room_temperatures__archive
|
|
449
459
|
# ActiveRecord::StatementInvalid (TinyTds::Error: DBPROCESS is dead or not enabled)
|
|
450
460
|
# Relevant info here: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues/402
|
|
461
|
+
is_api = params['_brick_is_api']
|
|
451
462
|
columns.each do |col|
|
|
463
|
+
next if (col.type.nil? || col.type == :binary) && is_api
|
|
464
|
+
|
|
452
465
|
col_alias = " AS #{col.name}_" if (col_name = col.name) == 'class'
|
|
453
466
|
selects << if is_mysql
|
|
454
467
|
"`#{tbl_no_schema}`.`#{col_name}`#{col_alias}"
|
|
@@ -999,7 +1012,8 @@ Module.class_exec do
|
|
|
999
1012
|
|
|
1000
1013
|
# MODULE
|
|
1001
1014
|
elsif (::Brick.enable_models? || ::Brick.enable_controllers?) && # Schema match?
|
|
1002
|
-
|
|
1015
|
+
# %%% This works for Person::Person -- but also limits us to not being able to allow more than one level of namespacing
|
|
1016
|
+
(base_module == Object || (camelize_prefix && base_module == Object.const_get(camelize_prefix))) &&
|
|
1003
1017
|
(schema_name = [(singular_table_name = class_name.underscore),
|
|
1004
1018
|
(table_name = singular_table_name.pluralize),
|
|
1005
1019
|
::Brick.is_oracle ? class_name.upcase : class_name,
|
|
@@ -1431,7 +1445,7 @@ class Object
|
|
|
1431
1445
|
is_postgres = ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
|
|
1432
1446
|
is_mysql = ['Mysql2', 'Trilogy'].include?(ActiveRecord::Base.connection.adapter_name)
|
|
1433
1447
|
|
|
1434
|
-
code = +"class #{class_name} < #{controller_base&.name || 'ApplicationController'}\n"
|
|
1448
|
+
code = +"class #{namespace}::#{class_name} < #{controller_base&.name || 'ApplicationController'}\n"
|
|
1435
1449
|
built_controller = Class.new(controller_base || ActionController::Base) do |new_controller_class|
|
|
1436
1450
|
(namespace || Object).const_set(class_name.to_sym, new_controller_class)
|
|
1437
1451
|
|
|
@@ -1538,9 +1552,13 @@ class Object
|
|
|
1538
1552
|
end
|
|
1539
1553
|
if (current_api_root || is_openapi) &&
|
|
1540
1554
|
!params&.key?('_brick_schema') &&
|
|
1541
|
-
(referrer_params = request.env['HTTP_REFERER']&.split('?')&.last&.split('&')&.
|
|
1555
|
+
(referrer_params = request.env['HTTP_REFERER']&.split('?')&.last&.split('&')&.each_with_object({}) do |x, s|
|
|
1556
|
+
if (kv = x.split('=')).length > 1
|
|
1557
|
+
s[kv.first] = kv[1..-1].join('=')
|
|
1558
|
+
end
|
|
1559
|
+
end).present?
|
|
1542
1560
|
if params
|
|
1543
|
-
referrer_params.each { |k, v| params.send(:parameters)[k] = v }
|
|
1561
|
+
referrer_params.each { |k, v| (params.respond_to?(:parameters) ? send(:parameters) : params)[k] = v }
|
|
1544
1562
|
else
|
|
1545
1563
|
api_params = referrer_params&.to_h
|
|
1546
1564
|
end
|
|
@@ -1651,11 +1669,12 @@ class Object
|
|
|
1651
1669
|
order_by, _ = model._brick_calculate_ordering(ordering, true) # Don't do the txt part
|
|
1652
1670
|
|
|
1653
1671
|
ar_relation = ActiveRecord.version < Gem::Version.new('4') ? model.preload : model.all
|
|
1672
|
+
params['_brick_is_api'] = true if (is_api = request.format == :js || current_api_root)
|
|
1654
1673
|
@_brick_params = ar_relation.brick_select(params, (selects ||= []), order_by,
|
|
1655
1674
|
translations = {},
|
|
1656
1675
|
join_array = ::Brick::JoinArray.new)
|
|
1657
1676
|
|
|
1658
|
-
if
|
|
1677
|
+
if is_api # Asking for JSON?
|
|
1659
1678
|
# Apply column renaming
|
|
1660
1679
|
data = ar_relation.respond_to?(:_select!) ? ar_relation.dup._select!(*selects) : ar_relation.select(selects)
|
|
1661
1680
|
if data.present? &&
|
|
@@ -1667,13 +1686,16 @@ class Object
|
|
|
1667
1686
|
end
|
|
1668
1687
|
end
|
|
1669
1688
|
|
|
1670
|
-
# %%%
|
|
1689
|
+
# # %%% This currently only gives a window to check security and raise an exception if someone isn't
|
|
1690
|
+
# # authenticated / authorised. Still need to figure out column filtering and transformations.
|
|
1671
1691
|
# proc_result = if (column_filter = ::Brick.config.api_column_filter).is_a?(Proc)
|
|
1672
|
-
# object_columns = relation
|
|
1692
|
+
# object_columns = (relation = model&._brick_relation)[:cols]
|
|
1673
1693
|
# begin
|
|
1674
1694
|
# num_args = column_filter.arity.negative? ? 5 : column_filter.arity
|
|
1675
1695
|
# # object_name, api_version, columns, data
|
|
1676
|
-
#
|
|
1696
|
+
# api_ver_path = request.path[0..-relation[:resource].length]
|
|
1697
|
+
# # Call the api_column_filter in the context of this auto-built controller
|
|
1698
|
+
# instance_exec(*[relation[:resource], relation, api_ver_path, object_columns, data][0...num_args], &column_filter)
|
|
1677
1699
|
# rescue StandardError => e
|
|
1678
1700
|
# puts "::Brick.api_column_filter Proc error: #{e.message}"
|
|
1679
1701
|
# end
|
|
@@ -1685,7 +1707,6 @@ class Object
|
|
|
1685
1707
|
# else
|
|
1686
1708
|
# relation.last[:cols]
|
|
1687
1709
|
# end
|
|
1688
|
-
# binding.pry
|
|
1689
1710
|
|
|
1690
1711
|
render inline: { data: data }.to_json, content_type: ['*/*', 'text/html'].include?(request.format) ? 'application/json' : request.format
|
|
1691
1712
|
return
|
|
@@ -1984,7 +2005,6 @@ end.class_exec do
|
|
|
1984
2005
|
|
|
1985
2006
|
# return if ActiveRecord::Base.connection.current_database == 'postgres'
|
|
1986
2007
|
|
|
1987
|
-
initializer_loaded = false
|
|
1988
2008
|
orig_schema = nil
|
|
1989
2009
|
if (relations = ::Brick.relations).empty?
|
|
1990
2010
|
# Very first thing, load inflections since we'll be using .pluralize and .singularize on table and model names
|
|
@@ -1993,7 +2013,7 @@ end.class_exec do
|
|
|
1993
2013
|
end
|
|
1994
2014
|
# Now the Brick initializer since there may be important schema things configured
|
|
1995
2015
|
if File.exist?(brick_initializer = ::Rails.root.join('config/initializers/brick.rb'))
|
|
1996
|
-
initializer_loaded = load brick_initializer
|
|
2016
|
+
::Brick.initializer_loaded = load brick_initializer
|
|
1997
2017
|
end
|
|
1998
2018
|
# Load the initializer for the Apartment gem a little early so that if .excluded_models and
|
|
1999
2019
|
# .default_schema are specified then we can work with non-tenanted models more appropriately
|
|
@@ -2260,13 +2280,22 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
|
2260
2280
|
schema_names.shift if ::Brick.apartment_multitenant && schema_names.first == ::Brick.apartment_default_tenant
|
|
2261
2281
|
v[:schema] = schema_names.join('.') unless schema_names.empty?
|
|
2262
2282
|
# %%% If more than one schema has the same table name, will need to add a schema name prefix to have uniqueness
|
|
2263
|
-
v[:resource] = rel_name.last
|
|
2264
2283
|
if (singular = rel_name.last.singularize).blank?
|
|
2265
2284
|
singular = rel_name.last
|
|
2266
2285
|
end
|
|
2267
|
-
|
|
2286
|
+
name_parts = if (tnp = ::Brick.config.table_name_prefixes
|
|
2287
|
+
.find { |k1, _v1| singular.start_with?(k1) && singular.length > k1.length }
|
|
2288
|
+
).present?
|
|
2289
|
+
v[:auto_prefixed_schema] = tnp.first
|
|
2290
|
+
v[:resource] = rel_name.last[(tnp_length = tnp.first.length)..-1]
|
|
2291
|
+
[tnp.last, singular[tnp_length..-1]]
|
|
2292
|
+
else
|
|
2293
|
+
v[:resource] = rel_name.last
|
|
2294
|
+
[singular]
|
|
2295
|
+
end
|
|
2296
|
+
v[:class_name] = (schema_names + name_parts).map(&:camelize).join('::')
|
|
2268
2297
|
end
|
|
2269
|
-
::Brick.load_additional_references if initializer_loaded
|
|
2298
|
+
::Brick.load_additional_references if ::Brick.initializer_loaded
|
|
2270
2299
|
|
|
2271
2300
|
if orig_schema && (orig_schema = (orig_schema - ['pg_catalog', 'pg_toast', 'heroku_ext']).first)
|
|
2272
2301
|
puts "Now switching back to \"#{orig_schema}\" schema."
|
|
@@ -2648,8 +2677,10 @@ module Brick
|
|
|
2648
2677
|
end
|
|
2649
2678
|
|
|
2650
2679
|
def find_col_renaming(api_ver_path, relation_name)
|
|
2651
|
-
|
|
2652
|
-
|
|
2680
|
+
::Brick.config.api_column_renaming&.fetch(
|
|
2681
|
+
api_ver_path,
|
|
2682
|
+
::Brick.config.api_column_renaming&.fetch(relation_name, nil)
|
|
2683
|
+
)
|
|
2653
2684
|
end
|
|
2654
2685
|
|
|
2655
2686
|
def _class_pk(dotted_name, multitenant)
|
|
@@ -10,10 +10,13 @@ module Brick
|
|
|
10
10
|
if (param === undefined || param === null || param === -1) {
|
|
11
11
|
hrefParts = hrefParts[0].split(\"://\");
|
|
12
12
|
var pathParts = hrefParts[hrefParts.length - 1].split(\"/\").filter(function (pp) {return pp !== \"\";});
|
|
13
|
-
if (value === undefined)
|
|
13
|
+
if (value === undefined) {
|
|
14
14
|
// A couple possibilities if it's namespaced, starting with two parts in the path -- and then try just one
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
if (pathParts.length > 3)
|
|
16
|
+
return [pathParts.slice(1, 4).join('/'), pathParts.slice(1, 3).join('/')];
|
|
17
|
+
else
|
|
18
|
+
return [pathParts.slice(1, 3).join('/'), pathParts[1]];
|
|
19
|
+
} else {
|
|
17
20
|
var queryString = param ? \"?\" + params.join(\"&\") : \"\";
|
|
18
21
|
return hrefParts[0] + \"://\" + pathParts[0] + \"/\" + value + queryString;
|
|
19
22
|
}
|
|
@@ -187,7 +190,8 @@ function linkSchemas() {
|
|
|
187
190
|
s[r.name[0..-9]] = nil if r.name.end_with?('Resource')
|
|
188
191
|
end
|
|
189
192
|
::Brick.relations.each do |k, v|
|
|
190
|
-
unless existing.key?(class_name = v[:class_name]) || Brick.config.exclude_tables.include?(k) ||
|
|
193
|
+
unless existing.key?(class_name = v[:class_name]) || Brick.config.exclude_tables.include?(k) ||
|
|
194
|
+
class_name.blank? || class_name.include?('::')
|
|
191
195
|
Object.const_get("#{class_name}Resource")
|
|
192
196
|
end
|
|
193
197
|
end
|
|
@@ -452,11 +456,22 @@ window.addEventListener(\"popstate\", linkSchemas);
|
|
|
452
456
|
# %%% If we are not auto-creating controllers (or routes) then omit by default, and if enabled anyway, such as in a development
|
|
453
457
|
# environment or whatever, then get either the controllers or routes list instead
|
|
454
458
|
prefix = "#{::Brick.config.path_prefix}/" if ::Brick.config.path_prefix
|
|
455
|
-
table_options =
|
|
456
|
-
if
|
|
457
|
-
|
|
459
|
+
table_options = ::Brick.relations.each_with_object({}) do |rel, s|
|
|
460
|
+
next if ::Brick.config.exclude_tables.include?(rel.first)
|
|
461
|
+
|
|
462
|
+
tbl_parts = rel.first.split('.')
|
|
463
|
+
if (aps = rel.last.fetch(:auto_prefixed_schema, nil))
|
|
464
|
+
tbl_parts << tbl_parts.last[aps.length..-1]
|
|
465
|
+
aps = aps[0..-2] if aps[-1] == '_'
|
|
466
|
+
tbl_parts[-2] = aps
|
|
467
|
+
end
|
|
468
|
+
if tbl_parts.first == apartment_default_schema
|
|
469
|
+
tbl_parts.shift
|
|
458
470
|
end
|
|
459
|
-
|
|
471
|
+
# %%% When table_name_prefixes are use then during rendering empty non-TNP
|
|
472
|
+
# entries get added at some point when an attempt is made to find the table.
|
|
473
|
+
# Will have to hunt that down at some point.
|
|
474
|
+
s[tbl_parts.join('.')] = nil unless rel.last[:cols].empty?
|
|
460
475
|
end.keys.sort.each_with_object(+'') do |v, s|
|
|
461
476
|
s << "<option value=\"#{prefix}#{v.underscore.gsub('.', '/')}\">#{v}</option>"
|
|
462
477
|
end.html_safe
|
|
@@ -881,7 +896,8 @@ if (grid) {
|
|
|
881
896
|
// });
|
|
882
897
|
}
|
|
883
898
|
function setHeaderSizes() {
|
|
884
|
-
|
|
899
|
+
if (grid.clientWidth > window.outerWidth)
|
|
900
|
+
document.getElementById(\"titleBox\").style.width = grid.clientWidth;
|
|
885
901
|
// console.log(\"start\");
|
|
886
902
|
// See if the headerTop is already populated
|
|
887
903
|
// %%% Grab the TRs from headerTop, clear it out, do this stuff, add them back
|
|
@@ -1136,12 +1152,13 @@ erDiagram
|
|
|
1136
1152
|
<td><h1><%= td_count = 2
|
|
1137
1153
|
model.name %></h1></td>
|
|
1138
1154
|
<td id=\"imgErd\" title=\"Show ERD\"></td>
|
|
1139
|
-
<% if Object.const_defined?('Avo') && ::Avo.respond_to?(:railtie_namespace)
|
|
1155
|
+
<% if Object.const_defined?('Avo') && ::Avo.respond_to?(:railtie_namespace) && model.name.exclude?('::')
|
|
1140
1156
|
td_count += 1 %>
|
|
1141
1157
|
<td><%= link_to_brick(
|
|
1142
1158
|
avo_svg,
|
|
1143
|
-
{ index_proc: Proc.new do |avo_model|
|
|
1144
|
-
|
|
1159
|
+
{ index_proc: Proc.new do |avo_model, relation|
|
|
1160
|
+
path_helper = \"resources_#\{relation.fetch(:auto_prefixed_schema, nil)}#\{model.model_name.route_key}_path\".to_sym
|
|
1161
|
+
::Avo.railtie_routes_url_helpers.send(path_helper) if ::Avo.railtie_routes_url_helpers.respond_to?(path_helper)
|
|
1145
1162
|
end,
|
|
1146
1163
|
title: \"#\{model.name} in Avo\" }
|
|
1147
1164
|
) %></td>
|
|
@@ -1328,8 +1345,9 @@ erDiagram
|
|
|
1328
1345
|
<% if Object.const_defined?('Avo') && ::Avo.respond_to?(:railtie_namespace) %>
|
|
1329
1346
|
<td><%= link_to_brick(
|
|
1330
1347
|
avo_svg,
|
|
1331
|
-
{ show_proc: Proc.new do |obj|
|
|
1332
|
-
|
|
1348
|
+
{ show_proc: Proc.new do |obj, relation|
|
|
1349
|
+
path_helper = \"resources_#\{relation.fetch(:auto_prefixed_schema, nil)}#\{obj.class.base_class.model_name.singular_route_key}_path\".to_sym
|
|
1350
|
+
::Avo.railtie_routes_url_helpers.send(path_helper, obj) if ::Avo.railtie_routes_url_helpers.respond_to?(path_helper)
|
|
1333
1351
|
end,
|
|
1334
1352
|
title: \"#\{page_title} in Avo\" }
|
|
1335
1353
|
) %></td>
|
|
@@ -1408,8 +1426,8 @@ end
|
|
|
1408
1426
|
\"<span class=\\\"orphan\\\">Orphaned ID: #\{val}</span>\".html_safe
|
|
1409
1427
|
end %>
|
|
1410
1428
|
<% else
|
|
1411
|
-
col_type = col
|
|
1412
|
-
case (col_type ||= col
|
|
1429
|
+
col_type = col&.sql_type == 'geography' ? col.sql_type : col&.type
|
|
1430
|
+
case (col_type ||= col&.sql_type)
|
|
1413
1431
|
when :string, :text %>
|
|
1414
1432
|
<% if is_bcrypt?(val) # || .readonly?
|
|
1415
1433
|
is_revert = false %>
|
|
@@ -1489,9 +1507,9 @@ end
|
|
|
1489
1507
|
# association that points to an STI model then filtering for the __able_type column is done
|
|
1490
1508
|
# with a .where(). And the polymorphic class name it points to is the base class name of
|
|
1491
1509
|
# the STI model instead of its subclass.
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1510
|
+
poly_type = #{poly_type.inspect}
|
|
1511
|
+
if poly_type && @#{obj_name}.respond_to?(:#{@_brick_model.inheritance_column}) &&
|
|
1512
|
+
(base_type = collection.where_values_hash[poly_type])
|
|
1495
1513
|
collection = collection.rewhere(poly_type => [base_type, @#{obj_name}.#{@_brick_model.inheritance_column}])
|
|
1496
1514
|
end"
|
|
1497
1515
|
end
|
|
@@ -162,8 +162,9 @@ module Brick::Rails::FormTags
|
|
|
162
162
|
@_brick_model
|
|
163
163
|
# If not provided, do a best-effort to automatically determine the resource class or object
|
|
164
164
|
filter_parts = []
|
|
165
|
+
rel_name = nil
|
|
165
166
|
klass_or_obj ||= begin
|
|
166
|
-
klass, sti_type = ::Brick.ctrl_to_klass(controller_path)
|
|
167
|
+
klass, sti_type, rel_name = ::Brick.ctrl_to_klass(controller_path)
|
|
167
168
|
if klass
|
|
168
169
|
type_col = klass.inheritance_column # Usually 'type'
|
|
169
170
|
filter_parts << "#{type_col}=#{sti_type}" if sti_type && klass.column_names.include?(type_col)
|
|
@@ -202,11 +203,11 @@ module Brick::Rails::FormTags
|
|
|
202
203
|
app_routes = Rails.application.routes # In case we're operating in another engine, reference the application since Brick routes are placed there.
|
|
203
204
|
if (klass_or_obj&.is_a?(Class) && klass_or_obj < ActiveRecord::Base) ||
|
|
204
205
|
(klass_or_obj&.is_a?(ActiveRecord::Base) && klass_or_obj.new_record? && (klass_or_obj = klass_or_obj.class))
|
|
205
|
-
path = (proc = kwargs[:index_proc]) ? proc.call(klass_or_obj) : "#{app_routes.path_for(controller: klass_or_obj.base_class._brick_index(nil, '/'), action: :index)}#{filter}"
|
|
206
|
+
path = (proc = kwargs[:index_proc]) ? proc.call(klass_or_obj, relation) : "#{app_routes.path_for(controller: klass_or_obj.base_class._brick_index(nil, '/', relation), action: :index)}#{filter}"
|
|
206
207
|
lt_args = [text || "Index for #{klass_or_obj.name.pluralize}", path]
|
|
207
208
|
else
|
|
208
209
|
# If there are multiple incoming parameters then last one is probably the actual ID, and first few might be some nested tree of stuff leading up to it
|
|
209
|
-
path = (proc = kwargs[:show_proc]) ? proc.call(klass_or_obj) : "#{app_routes.path_for(controller: klass_or_obj.class.base_class._brick_index(nil, '/'), action: :show, id: klass_or_obj)}#{filter}"
|
|
210
|
+
path = (proc = kwargs[:show_proc]) ? proc.call(klass_or_obj, relation) : "#{app_routes.path_for(controller: klass_or_obj.class.base_class._brick_index(nil, '/', relation), action: :show, id: klass_or_obj)}#{filter}"
|
|
210
211
|
lt_args = [text || "Show this #{klass_or_obj.class.name}", path]
|
|
211
212
|
end
|
|
212
213
|
kwargs.delete(:visited)
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
|
@@ -135,7 +135,7 @@ module Brick
|
|
|
135
135
|
@existing_stis ||= Brick.config.sti_namespace_prefixes.each_with_object({}) { |snp, s| s[snp.first[2..-1]] = snp.last unless snp.first.end_with?('::') }
|
|
136
136
|
end
|
|
137
137
|
|
|
138
|
-
attr_accessor :default_schema, :db_schemas, :routes_done, :is_oracle, :is_eager_loading, :auto_models
|
|
138
|
+
attr_accessor :default_schema, :db_schemas, :routes_done, :is_oracle, :is_eager_loading, :auto_models, :initializer_loaded
|
|
139
139
|
|
|
140
140
|
def set_db_schema(params = nil)
|
|
141
141
|
# If Apartment::Tenant.current is not still the default (usually 'public') then an elevator has brought us into
|
|
@@ -601,7 +601,7 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
|
601
601
|
def display_classes(prefix, rels, max_length)
|
|
602
602
|
rels.sort.each do |rel|
|
|
603
603
|
(::Brick.auto_models ||= []) << rel.first
|
|
604
|
-
puts "#{rel.first}#{' ' * (max_length - rel.first.length)} /#{prefix}#{rel.last}"
|
|
604
|
+
puts "#{rel.first}#{' ' * (max_length - rel.first.length)} /#{prefix}#{"#{rel[1]}/" if rel[1]}#{rel.last}"
|
|
605
605
|
end
|
|
606
606
|
puts "\n"
|
|
607
607
|
end
|
|
@@ -620,16 +620,21 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
|
620
620
|
end
|
|
621
621
|
|
|
622
622
|
c_path_parts = ctrl_path.split('/')
|
|
623
|
+
found = nil
|
|
623
624
|
while c_path_parts.present?
|
|
624
625
|
possible_c_path = c_path_parts.join('.')
|
|
625
626
|
possible_c_path_singular = c_path_parts[0..-2] + [c_path_parts.last.singularize]
|
|
626
627
|
possible_sti = possible_c_path_singular.join('/').camelize
|
|
627
628
|
break if (
|
|
628
|
-
res_name = res_names[possible_c_path] ||
|
|
629
|
+
res_name = res_names[found = possible_c_path] ||
|
|
629
630
|
((klass = Brick.config.sti_namespace_prefixes.key?("::#{possible_sti}") && possible_sti.constantize) &&
|
|
630
631
|
(sti_type = possible_sti)) ||
|
|
631
632
|
# %%% Used to have the more flexible: (DidYouMean::SpellChecker.new(dictionary: res_names.keys).correct(possible_c_path)).first
|
|
632
|
-
res_names[possible_c_path] || res_names[possible_c_path_singular.join('.')]
|
|
633
|
+
res_names[found = possible_c_path] || res_names[found = possible_c_path_singular.join('.')] ||
|
|
634
|
+
((::Brick.config.table_name_prefixes.key?(tn_prefix = c_path_parts.first) ||
|
|
635
|
+
::Brick.config.table_name_prefixes.key?(tn_prefix = "#{c_path_parts.first}_")) &&
|
|
636
|
+
res_names[found = tn_prefix + c_path_parts.last]
|
|
637
|
+
)
|
|
633
638
|
) &&
|
|
634
639
|
(
|
|
635
640
|
klass ||
|
|
@@ -638,7 +643,7 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
|
638
643
|
)
|
|
639
644
|
c_path_parts.shift
|
|
640
645
|
end
|
|
641
|
-
[klass, sti_type]
|
|
646
|
+
[klass, sti_type, found]
|
|
642
647
|
end
|
|
643
648
|
end
|
|
644
649
|
|
|
@@ -657,10 +662,14 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
|
657
662
|
table_class_length = 38 # Length of "Classes that can be built from tables:"
|
|
658
663
|
view_class_length = 37 # Length of "Classes that can be built from views:"
|
|
659
664
|
|
|
660
|
-
|
|
661
|
-
if
|
|
662
|
-
|
|
663
|
-
|
|
665
|
+
brick_namespace_create = lambda do |path_names, res_name, options|
|
|
666
|
+
if path_names&.present?
|
|
667
|
+
if (path_name = path_names.pop).is_a?(Array)
|
|
668
|
+
module_name = path_name[1]
|
|
669
|
+
path_name = path_name.first
|
|
670
|
+
end
|
|
671
|
+
send(:scope, { module: module_name || path_name, path: path_name, as: path_name }) do
|
|
672
|
+
brick_namespace_create.call(path_names, res_name, options)
|
|
664
673
|
end
|
|
665
674
|
else
|
|
666
675
|
send(:resources, res_name.to_sym, **options)
|
|
@@ -676,15 +685,49 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
|
676
685
|
end
|
|
677
686
|
versioned_views = {} # Track which views have already been done for each api_root
|
|
678
687
|
::Brick.relations.each do |k, v|
|
|
679
|
-
next if !(controller_name = v.fetch(:resource, nil)&.pluralize) || existing_controllers.key?(controller_name)
|
|
680
|
-
|
|
681
|
-
object_name = k.split('.').last # Take off any first schema part
|
|
682
688
|
if (schema_name = v.fetch(:schema, nil))
|
|
683
689
|
schema_prefix = "#{schema_name}."
|
|
684
690
|
end
|
|
691
|
+
|
|
692
|
+
next if !(resource_name = v.fetch(:resource, nil)) ||
|
|
693
|
+
existing_controllers.key?(controller_name = (
|
|
694
|
+
resource_name = "#{schema_prefix&.tr('.', '/')}#{resource_name}"
|
|
695
|
+
).pluralize)
|
|
696
|
+
|
|
697
|
+
object_name = k.split('.').last # Take off any first schema part
|
|
698
|
+
|
|
699
|
+
full_schema_prefix = if (aps = v.fetch(:auto_prefixed_schema, nil))
|
|
700
|
+
aps = aps[0..-2] if aps[-1] == '_'
|
|
701
|
+
(schema_prefix&.dup || +'') << "#{aps}."
|
|
702
|
+
else
|
|
703
|
+
schema_prefix
|
|
704
|
+
end
|
|
705
|
+
|
|
706
|
+
# Track routes being built
|
|
707
|
+
if (class_name = v.fetch(:class_name, nil))
|
|
708
|
+
if v.key?(:isView)
|
|
709
|
+
view_class_length = class_name.length if class_name.length > view_class_length
|
|
710
|
+
views
|
|
711
|
+
else
|
|
712
|
+
table_class_length = class_name.length if class_name.length > table_class_length
|
|
713
|
+
tables
|
|
714
|
+
end << [class_name, aps, resource_name]
|
|
715
|
+
end
|
|
716
|
+
|
|
685
717
|
options = {}
|
|
686
718
|
options[:only] = [:index, :show] if v.key?(:isView)
|
|
687
|
-
|
|
719
|
+
|
|
720
|
+
# First do the normal routes
|
|
721
|
+
prefixes = []
|
|
722
|
+
prefixes << [aps, v[:class_name]&.split('::')[-2]&.underscore] if aps
|
|
723
|
+
prefixes << schema_name if schema_name
|
|
724
|
+
prefixes << path_prefix if path_prefix
|
|
725
|
+
brick_namespace_create.call(prefixes, v[:resource], options)
|
|
726
|
+
sti_subclasses.fetch(class_name, nil)&.each do |sc| # Add any STI subclass routes for this relation
|
|
727
|
+
brick_namespace_create.call(prefixes, sc.underscore.tr('/', '_').pluralize, options)
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
# Now the API routes if necessary
|
|
688
731
|
full_resource = nil
|
|
689
732
|
::Brick.api_roots&.each do |api_root|
|
|
690
733
|
api_done_views = (versioned_views[api_root] ||= {})
|
|
@@ -742,7 +785,7 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
|
742
785
|
proc_result = if (filter = ::Brick.config.api_filter).is_a?(Proc)
|
|
743
786
|
begin
|
|
744
787
|
num_args = filter.arity.negative? ? 6 : filter.arity
|
|
745
|
-
filter.call(*[unversioned, k, actions, api_ver_num, found, test_ver_num][0...num_args])
|
|
788
|
+
filter.call(*[unversioned, k, view_relation, actions, api_ver_num, found, test_ver_num][0...num_args])
|
|
746
789
|
rescue StandardError => e
|
|
747
790
|
puts "::Brick.api_filter Proc error: #{e.message}"
|
|
748
791
|
end
|
|
@@ -786,9 +829,8 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
|
786
829
|
# view_ver_num = if (first_part = k.split('_').first) =~ /^v[\d_]+/
|
|
787
830
|
# first_part[1..-1].gsub('_', '.').to_i
|
|
788
831
|
# end
|
|
789
|
-
|
|
790
832
|
controller_name = if (last = view_relation.fetch(:resource, nil)&.pluralize)
|
|
791
|
-
"#{
|
|
833
|
+
"#{full_schema_prefix}#{last}"
|
|
792
834
|
else
|
|
793
835
|
found
|
|
794
836
|
end.tr('.', '/')
|
|
@@ -811,33 +853,6 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
|
811
853
|
end
|
|
812
854
|
end
|
|
813
855
|
end
|
|
814
|
-
|
|
815
|
-
# Track routes being built
|
|
816
|
-
if (class_name = v.fetch(:class_name, nil))
|
|
817
|
-
if v.key?(:isView)
|
|
818
|
-
view_class_length = class_name.length if class_name.length > view_class_length
|
|
819
|
-
views
|
|
820
|
-
else
|
|
821
|
-
table_class_length = class_name.length if class_name.length > table_class_length
|
|
822
|
-
tables
|
|
823
|
-
end << [class_name, "#{schema_prefix&.tr('.', '/')}#{v[:resource]}"]
|
|
824
|
-
end
|
|
825
|
-
|
|
826
|
-
# Now the normal routes
|
|
827
|
-
if path_prefix
|
|
828
|
-
# Was: send(:scope, path: path_prefix) do
|
|
829
|
-
send(:namespace, path_prefix) do
|
|
830
|
-
brick_routes_create.call(schema_name, v[:resource], options)
|
|
831
|
-
sti_subclasses.fetch(class_name, nil)&.each do |sc| # Add any STI subclass routes for this relation
|
|
832
|
-
brick_routes_create.call(schema_name, sc.underscore.tr('/', '_').pluralize, options)
|
|
833
|
-
end
|
|
834
|
-
end
|
|
835
|
-
else
|
|
836
|
-
brick_routes_create.call(schema_name, v[:resource], options)
|
|
837
|
-
sti_subclasses.fetch(class_name, nil)&.each do |sc| # Add any STI subclass routes for this relation
|
|
838
|
-
brick_routes_create.call(schema_name, sc.underscore.tr('/', '_').pluralize, options)
|
|
839
|
-
end
|
|
840
|
-
end
|
|
841
856
|
end
|
|
842
857
|
|
|
843
858
|
if ::Brick.config.add_status && instance_variable_get(:@set).named_routes.names.exclude?(:brick_status)
|
|
@@ -857,7 +872,7 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
|
857
872
|
if Object.const_defined?('Rswag::Ui')
|
|
858
873
|
rswag_path = ::Rails.application.routes.routes.find { |r| r.app.app == Rswag::Ui::Engine }&.instance_variable_get(:@path_formatter)&.instance_variable_get(:@parts)&.join
|
|
859
874
|
first_endpoint_parts = nil
|
|
860
|
-
(doc_endpoints = Rswag::Ui.config.config_object[:urls]
|
|
875
|
+
(doc_endpoints = Rswag::Ui.config.config_object[:urls])&.each do |doc_endpoint|
|
|
861
876
|
puts "Mounting OpenApi 3.0 documentation endpoint for \"#{doc_endpoint[:name]}\" on #{doc_endpoint[:url]}"
|
|
862
877
|
send(:get, doc_endpoint[:url], { to: 'brick_openapi#index' })
|
|
863
878
|
endpoint_parts = doc_endpoint[:url]&.split('/')
|
|
@@ -1192,8 +1207,13 @@ ActiveSupport.on_load(:active_record) do
|
|
|
1192
1207
|
arsc.class_exec do
|
|
1193
1208
|
def self.create(connection, callable = nil, &block)
|
|
1194
1209
|
relation = (callable || block).call ::ActiveRecord::StatementCache::Params.new
|
|
1195
|
-
bind_map = ::ActiveRecord::StatementCache::BindMap.new
|
|
1196
|
-
|
|
1210
|
+
bind_map = ::ActiveRecord::StatementCache::BindMap.new(
|
|
1211
|
+
# AR <= 4.2 uses relation.bind_values
|
|
1212
|
+
relation.respond_to?(:bound_attributes) ? relation.bound_attributes : relation.bind_values
|
|
1213
|
+
)
|
|
1214
|
+
options = [self, relation.arel]
|
|
1215
|
+
options.shift if connection.method(:cacheable_query).arity == 1 # Rails <= 5.0
|
|
1216
|
+
query_builder = connection.cacheable_query(*options)
|
|
1197
1217
|
new query_builder, bind_map
|
|
1198
1218
|
end
|
|
1199
1219
|
end
|
|
@@ -1237,7 +1257,8 @@ ActiveSupport.on_load(:active_record) do
|
|
|
1237
1257
|
end
|
|
1238
1258
|
end
|
|
1239
1259
|
|
|
1240
|
-
if
|
|
1260
|
+
if ActiveRecord.version < ::Gem::Version.new('6.1') &&
|
|
1261
|
+
Psych.method(:load).parameters.any? { |param| param.first == :key && param.last == :aliases }
|
|
1241
1262
|
Psych.class_exec do
|
|
1242
1263
|
class << self
|
|
1243
1264
|
alias _original_load load
|
|
@@ -1279,7 +1300,9 @@ ActiveSupport.on_load(:active_record) do
|
|
|
1279
1300
|
def initialize(base, associations, joins, eager_loading: true)
|
|
1280
1301
|
araat = ::ActiveRecord::Associations::AliasTracker
|
|
1281
1302
|
if araat.respond_to?(:create_with_joins) # Rails 5.0 and 5.1
|
|
1282
|
-
|
|
1303
|
+
cwj_options = [base.connection, base.table_name, joins]
|
|
1304
|
+
cwj_options << base.type_caster if araat.method(:create_with_joins).arity > 3 # Rails <= 5.1
|
|
1305
|
+
@alias_tracker = araat.create_with_joins(*cwj_options)
|
|
1283
1306
|
@eager_loading = eager_loading # (Unused in Rails 5.0)
|
|
1284
1307
|
else # Rails 4.2
|
|
1285
1308
|
@alias_tracker = araat.create(base.connection, joins)
|
|
@@ -1648,21 +1671,24 @@ if ActiveRecord.version < ::Gem::Version.new('6.0') && ruby_version >= ::Gem::Ve
|
|
|
1648
1671
|
end
|
|
1649
1672
|
|
|
1650
1673
|
require 'active_model'
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1674
|
+
begin
|
|
1675
|
+
require 'active_model/type'
|
|
1676
|
+
require 'active_model/type/value'
|
|
1677
|
+
class ActiveModel::Type::Value
|
|
1678
|
+
def initialize(*args, precision: nil, limit: nil, scale: nil)
|
|
1679
|
+
@precision = precision
|
|
1680
|
+
@scale = scale
|
|
1681
|
+
@limit = limit
|
|
1682
|
+
end
|
|
1658
1683
|
end
|
|
1684
|
+
rescue LoadError => e # AR <= 4.2 doesn't have ActiveModel::Type
|
|
1659
1685
|
end
|
|
1660
1686
|
|
|
1661
1687
|
if Object.const_defined?('I18n')
|
|
1662
1688
|
module I18n::Base
|
|
1663
1689
|
alias _brick_translate translate
|
|
1664
1690
|
def translate(key = nil, *args, throw: false, raise: false, locale: nil, **options)
|
|
1665
|
-
options.merge!(args.pop) if args.
|
|
1691
|
+
options.merge!(args.pop) if args.last.is_a?(Hash)
|
|
1666
1692
|
_brick_translate(key = nil, throw: false, raise: false, locale: nil, **options)
|
|
1667
1693
|
end
|
|
1668
1694
|
end
|
|
@@ -1673,8 +1699,12 @@ if ActiveRecord.version < ::Gem::Version.new('6.0') && ruby_version >= ::Gem::Ve
|
|
|
1673
1699
|
|
|
1674
1700
|
# Creates the authenticity token for the current request.
|
|
1675
1701
|
def form_authenticity_token(*args, form_options: {}) # :doc:
|
|
1676
|
-
|
|
1677
|
-
|
|
1702
|
+
if method(:masked_authenticity_token).arity == 1
|
|
1703
|
+
masked_authenticity_token(session) # AR <= 4.2 doesn't use form_options
|
|
1704
|
+
else
|
|
1705
|
+
form_options.merge!(args.pop) if args.last.is_a?(Hash)
|
|
1706
|
+
masked_authenticity_token(session, form_options: form_options)
|
|
1707
|
+
end
|
|
1678
1708
|
end
|
|
1679
1709
|
end
|
|
1680
1710
|
|
|
@@ -1684,7 +1714,7 @@ if ActiveRecord.version < ::Gem::Version.new('6.0') && ruby_version >= ::Gem::Ve
|
|
|
1684
1714
|
encrypted = if method(:_encrypt).arity == 1
|
|
1685
1715
|
_encrypt(value) # Rails <= 5.1
|
|
1686
1716
|
else
|
|
1687
|
-
if args.
|
|
1717
|
+
if args.last.is_a?(Hash)
|
|
1688
1718
|
expires_at ||= args.last[:expires_at]
|
|
1689
1719
|
expires_in ||= args.last[:expires_in]
|
|
1690
1720
|
purpose ||= args.last[:purpose]
|
|
@@ -1697,7 +1727,7 @@ if ActiveRecord.version < ::Gem::Version.new('6.0') && ruby_version >= ::Gem::Ve
|
|
|
1697
1727
|
if const_defined?('Messages')
|
|
1698
1728
|
class Messages::Metadata
|
|
1699
1729
|
def self.wrap(message, *args, expires_at: nil, expires_in: nil, purpose: nil)
|
|
1700
|
-
if args.
|
|
1730
|
+
if args.last.is_a?(Hash)
|
|
1701
1731
|
expires_at ||= args.last[:expires_at]
|
|
1702
1732
|
expires_in ||= args.last[:expires_in]
|
|
1703
1733
|
purpose ||= args.last[:purpose]
|
|
@@ -139,7 +139,7 @@ module Brick
|
|
|
139
139
|
# Settings for the Brick gem
|
|
140
140
|
# (By default this auto-creates models, controllers, views, and routes on-the-fly.)
|
|
141
141
|
|
|
142
|
-
if ActiveRecord::Base.respond_to?(:brick_select)
|
|
142
|
+
if ActiveRecord::Base.respond_to?(:brick_select) && !::Brick.initializer_loaded
|
|
143
143
|
# Mode -- generally :on or :off, or only in :development. Also available is :diag_env which enables only
|
|
144
144
|
# when the environment variable BRICK is set.
|
|
145
145
|
Brick.mode = :development
|
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.110
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Lorin Thwaits
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-01-
|
|
11
|
+
date: 2023-01-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|