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