brick 1.0.109 → 1.0.111

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1621b6af75759b90c788ce080db85608731c2bfc026c82d7bcea011a89c2162e
4
- data.tar.gz: a4242388d2fa29a12229c620d91b5d572e9e2f7688783beb6963817cf3fac340
3
+ metadata.gz: cb97e4a946526ed99a24e67b1e65d5f6490a40c97dc170dd0680166b087d1ccb
4
+ data.tar.gz: 48d9c4f2afcd737d9a857f8c771448639c1b0d2d568dc966bbe4b85a97cb4610
5
5
  SHA512:
6
- metadata.gz: fa089c1bc9663e764b783c639ca9ca24c18a5cbbc788281e11620b33277e87282b6e1a0195d12686b72f53a5ae4a5bcb9e8343e9ef9bb4d97f53fb69ad4619fe
7
- data.tar.gz: 784eed99a879191dff95b5dfd061f8025d52d3e30eb16b7a754b425c2f4ad58e03e8631949d807f130dc86e55cb3a5e08d215a3f1729b4465c58dc3cecffb96d
6
+ metadata.gz: 383d9996affbbd4fa049ab125490879143299a5477e98f921d450ea6b5b466d66a4cd210aac8db9c105a6eaf5f10eae8ac181d84d78fb6fc0b4c4151ac9dcee3
7
+ data.tar.gz: b9902fc959b0de870ef5c402fe75e76d939d0c7c5abc7b8d3c16451b87f56929eb6e329153c6b5697936f10228752ba3b2f5f2a7de6aa5c9c77c105c34dd2cfa
@@ -261,9 +261,16 @@ module ActiveRecord
261
261
  assoc_html_name ? "#{assoc_name}-#{link}".html_safe : link
262
262
  end
263
263
 
264
- def self._brick_index(mode = nil, separator = '_')
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
@@ -1005,7 +1012,8 @@ Module.class_exec do
1005
1012
 
1006
1013
  # MODULE
1007
1014
  elsif (::Brick.enable_models? || ::Brick.enable_controllers?) && # Schema match?
1008
- base_module == Object && # %%% This works for Person::Person -- but also limits us to not being able to allow more than one level of namespacing
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))) &&
1009
1017
  (schema_name = [(singular_table_name = class_name.underscore),
1010
1018
  (table_name = singular_table_name.pluralize),
1011
1019
  ::Brick.is_oracle ? class_name.upcase : class_name,
@@ -1437,7 +1445,7 @@ class Object
1437
1445
  is_postgres = ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
1438
1446
  is_mysql = ['Mysql2', 'Trilogy'].include?(ActiveRecord::Base.connection.adapter_name)
1439
1447
 
1440
- code = +"class #{class_name} < #{controller_base&.name || 'ApplicationController'}\n"
1448
+ code = +"class #{namespace}::#{class_name} < #{controller_base&.name || 'ApplicationController'}\n"
1441
1449
  built_controller = Class.new(controller_base || ActionController::Base) do |new_controller_class|
1442
1450
  (namespace || Object).const_set(class_name.to_sym, new_controller_class)
1443
1451
 
@@ -2011,6 +2019,21 @@ end.class_exec do
2011
2019
  # .default_schema are specified then we can work with non-tenanted models more appropriately
2012
2020
  if (apartment = Object.const_defined?('Apartment')) &&
2013
2021
  File.exist?(apartment_initializer = ::Rails.root.join('config/initializers/apartment.rb'))
2022
+ require 'apartment/adapters/abstract_adapter'
2023
+ Apartment::Adapters::AbstractAdapter.class_exec do
2024
+ if instance_methods.include?(:process_excluded_models)
2025
+ def process_excluded_models
2026
+ # All other models will share a connection (at Apartment.connection_class) and we can modify at will
2027
+ Apartment.excluded_models.each do |excluded_model|
2028
+ begin
2029
+ process_excluded_model(excluded_model)
2030
+ rescue NameError => e
2031
+ (@bad_models ||= []) << excluded_model
2032
+ end
2033
+ end
2034
+ end
2035
+ end
2036
+ end
2014
2037
  unless @_apartment_loaded
2015
2038
  load apartment_initializer
2016
2039
  @_apartment_loaded = true
@@ -2049,13 +2072,27 @@ end.class_exec do
2049
2072
  schema = possible_schema
2050
2073
  orig_schema = ActiveRecord::Base.execute_sql('SELECT current_schemas(true)').first['current_schemas'][1..-2].split(',')
2051
2074
  ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?", schema)
2052
- elsif Rails.env == 'test' # When testing, just find the most recently-created schema
2053
- ::Brick.default_schema = schema = ::Brick.db_schemas.to_a.sort { |a, b| b.last[:dt] <=> a.last[:dt] }.first.first
2054
- puts "While running tests, had noticed in the brick.rb initializer that the line \"::Brick.schema_behavior = ...\" refers to a schema called \"#{possible_schema}\" which does not exist. Reading table structure from the most recently-created schema, #{schema}."
2075
+ # When testing, just find the most recently-created schema
2076
+ elsif begin
2077
+ Rails.env == 'test' ||
2078
+ ActiveRecord::Base.execute_sql("SELECT value FROM ar_internal_metadata WHERE key='environment';").first&.fetch('value', nil) == 'test'
2079
+ rescue
2080
+ end
2081
+ ::Brick.default_schema = ::Brick.apartment_default_tenant
2082
+ ::Brick.test_schema = schema = ::Brick.db_schemas.to_a.sort { |a, b| b.last[:dt] <=> a.last[:dt] }.first.first
2083
+ if possible_schema.blank?
2084
+ puts "While running tests, using the most recently-created schema, #{schema}."
2085
+ else
2086
+ puts "While running tests, had noticed in the brick.rb initializer that the line \"::Brick.schema_behavior = ...\" refers to a schema called \"#{possible_schema}\" which does not exist. Reading table structure from the most recently-created schema, #{schema}."
2087
+ end
2055
2088
  orig_schema = ActiveRecord::Base.execute_sql('SELECT current_schemas(true)').first['current_schemas'][1..-2].split(',')
2089
+ ::Brick.config.schema_behavior = { multitenant: {} } # schema_to_analyse: [schema]
2056
2090
  ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?", schema)
2057
2091
  else
2058
2092
  puts "*** In the brick.rb initializer the line \"::Brick.schema_behavior = ...\" refers to schema(s) called #{possible_schemas.map { |s| "\"#{s}\"" }.join(', ')}. No mentioned schema exists. ***"
2093
+ if ::Brick.db_schemas.key?(::Brick.apartment_default_tenant)
2094
+ ::Brick.default_schema = schema = ::Brick.apartment_default_tenant
2095
+ end
2059
2096
  end
2060
2097
  end
2061
2098
  when 'Mysql2', 'Trilogy'
@@ -2272,11 +2309,20 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
2272
2309
  schema_names.shift if ::Brick.apartment_multitenant && schema_names.first == ::Brick.apartment_default_tenant
2273
2310
  v[:schema] = schema_names.join('.') unless schema_names.empty?
2274
2311
  # %%% If more than one schema has the same table name, will need to add a schema name prefix to have uniqueness
2275
- v[:resource] = rel_name.last
2276
2312
  if (singular = rel_name.last.singularize).blank?
2277
2313
  singular = rel_name.last
2278
2314
  end
2279
- v[:class_name] = (schema_names + [singular]).map(&:camelize).join('::')
2315
+ name_parts = if (tnp = ::Brick.config.table_name_prefixes
2316
+ .find { |k1, _v1| singular.start_with?(k1) && singular.length > k1.length }
2317
+ ).present?
2318
+ v[:auto_prefixed_schema] = tnp.first
2319
+ v[:resource] = rel_name.last[(tnp_length = tnp.first.length)..-1]
2320
+ [tnp.last, singular[tnp_length..-1]]
2321
+ else
2322
+ v[:resource] = rel_name.last
2323
+ [singular]
2324
+ end
2325
+ v[:class_name] = (schema_names + name_parts).map(&:camelize).join('::')
2280
2326
  end
2281
2327
  ::Brick.load_additional_references if ::Brick.initializer_loaded
2282
2328
 
@@ -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
- return [pathParts.slice(1, 3).join('/'), pathParts.slice(1, 2)[0]];
16
- else {
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
  }
@@ -33,11 +36,12 @@ module Brick
33
36
  // This PageTransitionEvent fires when the page first loads, as well as after any other history
34
37
  // transition such as when using the browser's Back and Forward buttons.
35
38
  window.addEventListener(\"pageshow\", linkSchemas);
36
- var brickSchema;
39
+ var brickSchema,
40
+ brickTestSchema;
37
41
  function linkSchemas() {
38
42
  var schemaSelect = document.getElementById(\"schema\");
39
43
  var tblSelect = document.getElementById(\"tbl\");
40
- if (tblSelect) { // Always present
44
+ if (tblSelect) { // Always present for Brick pages
41
45
  // Used to be: var i = # {::Brick.config.path_prefix ? '0' : 'schemaSelect ? 1 : 0'},
42
46
  var changeoutList = changeout(location.href);
43
47
  for (var i = 0; i < changeoutList.length; ++i) {
@@ -50,32 +54,32 @@ function linkSchemas() {
50
54
  if (brickSchema) lhr = changeout(lhr, \"_brick_schema\", schemaSelect.value);
51
55
  location.href = lhr;
52
56
  });
53
- }
54
57
 
55
- if (schemaSelect) { // First drop-down is only present if multitenant
56
- if (brickSchema = changeout(location.href, \"_brick_schema\")) {
57
- [... document.getElementsByTagName(\"A\")].forEach(function (a) { a.href = changeout(a.href, \"_brick_schema\", brickSchema); });
58
- }
59
- if (schemaSelect.options.length > 1) {
60
- schemaSelect.value = brickSchema || \"public\";
61
- schemaSelect.addEventListener(\"change\", function () {
62
- // If there's an ID then remove it (trim after selected table)
63
- location.href = changeout(location.href, \"_brick_schema\", this.value, tblSelect.value);
64
- });
58
+ if (schemaSelect) { // First drop-down is only present if multitenant
59
+ if (brickSchema = changeout(location.href, \"_brick_schema\")) {
60
+ [... document.getElementsByTagName(\"A\")].forEach(function (a) { a.href = changeout(a.href, \"_brick_schema\", brickSchema); });
61
+ }
62
+ if (schemaSelect.options.length > 1) {
63
+ schemaSelect.value = brickSchema || brickTestSchema || \"public\";
64
+ schemaSelect.addEventListener(\"change\", function () {
65
+ // If there's an ID then remove it (trim after selected table)
66
+ location.href = changeout(location.href, \"_brick_schema\", this.value, tblSelect.value);
67
+ });
68
+ }
65
69
  }
66
- }
67
- tblSelect.focus();
68
-
69
- [... document.getElementsByTagName(\"FORM\")].forEach(function (form) {
70
- if (brickSchema)
71
- form.action = changeout(form.action, \"_brick_schema\", brickSchema);
72
- form.addEventListener('submit', function (ev) {
73
- [... ev.target.getElementsByTagName(\"SELECT\")].forEach(function (select) {
74
- if (select.value === \"^^^brick_NULL^^^\") select.value = null;
70
+ tblSelect.focus();
71
+
72
+ [... document.getElementsByTagName(\"FORM\")].forEach(function (form) {
73
+ if (brickSchema)
74
+ form.action = changeout(form.action, \"_brick_schema\", brickSchema);
75
+ form.addEventListener('submit', function (ev) {
76
+ [... ev.target.getElementsByTagName(\"SELECT\")].forEach(function (select) {
77
+ if (select.value === \"^^^brick_NULL^^^\") select.value = null;
78
+ });
79
+ return true;
75
80
  });
76
- return true;
77
81
  });
78
- });
82
+ }
79
83
  };
80
84
  "
81
85
 
@@ -187,7 +191,8 @@ function linkSchemas() {
187
191
  s[r.name[0..-9]] = nil if r.name.end_with?('Resource')
188
192
  end
189
193
  ::Brick.relations.each do |k, v|
190
- unless existing.key?(class_name = v[:class_name]) || Brick.config.exclude_tables.include?(k) || class_name.blank?
194
+ unless existing.key?(class_name = v[:class_name]) || Brick.config.exclude_tables.include?(k) ||
195
+ class_name.blank? || class_name.include?('::')
191
196
  Object.const_get("#{class_name}Resource")
192
197
  end
193
198
  end
@@ -355,15 +360,11 @@ window.addEventListener(\"popstate\", linkSchemas);
355
360
  (is_status = ::Brick.config.add_status && args[0..1] == ['status', ['brick_gem']]) ||
356
361
  (is_orphans = ::Brick.config.add_orphans && args[0..1] == ['orphans', ['brick_gem']]) ||
357
362
  (is_crosstab = args[0..1] == ['crosstab', ['brick_gem']])
358
- if ActionView.version < ::Gem::Version.new('5.0') # %%% Not sure if this should be perhaps 4.2 instead
359
- begin
360
- if (possible_template = _brick_find_template(*args, **options))
361
- return possible_template
362
- end
363
- rescue
363
+ begin
364
+ if (possible_template = _brick_find_template(*args, **options))
365
+ return possible_template
364
366
  end
365
- elsif (possible_template = _brick_find_template(*args, **options))
366
- return possible_template
367
+ rescue
367
368
  end
368
369
  # Used to also have: ActionView.version < ::Gem::Version.new('5.0') &&
369
370
  model_name = (args[1].is_a?(Array) ? set_brick_model(args) : nil)&.name
@@ -452,11 +453,22 @@ window.addEventListener(\"popstate\", linkSchemas);
452
453
  # %%% If we are not auto-creating controllers (or routes) then omit by default, and if enabled anyway, such as in a development
453
454
  # environment or whatever, then get either the controllers or routes list instead
454
455
  prefix = "#{::Brick.config.path_prefix}/" if ::Brick.config.path_prefix
455
- table_options = (::Brick.relations.keys - ::Brick.config.exclude_tables).each_with_object({}) do |tbl, s|
456
- if (tbl_parts = tbl.split('.')).first == apartment_default_schema
457
- tbl = tbl_parts.last
456
+ table_options = ::Brick.relations.each_with_object({}) do |rel, s|
457
+ next if ::Brick.config.exclude_tables.include?(rel.first)
458
+
459
+ tbl_parts = rel.first.split('.')
460
+ if (aps = rel.last.fetch(:auto_prefixed_schema, nil))
461
+ tbl_parts << tbl_parts.last[aps.length..-1]
462
+ aps = aps[0..-2] if aps[-1] == '_'
463
+ tbl_parts[-2] = aps
458
464
  end
459
- s[tbl] = nil
465
+ if tbl_parts.first == apartment_default_schema
466
+ tbl_parts.shift
467
+ end
468
+ # %%% When table_name_prefixes are use then during rendering empty non-TNP
469
+ # entries get added at some point when an attempt is made to find the table.
470
+ # Will have to hunt that down at some point.
471
+ s[tbl_parts.join('.')] = nil unless rel.last[:cols].empty?
460
472
  end.keys.sort.each_with_object(+'') do |v, s|
461
473
  s << "<option value=\"#{prefix}#{v.underscore.gsub('.', '/')}\">#{v}</option>"
462
474
  end.html_safe
@@ -836,8 +848,9 @@ document.querySelectorAll(\"input[type=submit][data-confirm]\").forEach(function
836
848
  });
837
849
  });
838
850
 
839
- #{JS_CHANGEOUT}
840
-
851
+ #{JS_CHANGEOUT}#{
852
+ "\nbrickTestSchema = \"#{::Brick.test_schema}\";" if ::Brick.test_schema
853
+ }
841
854
  // Snag first TR for sticky header
842
855
  var grid = document.getElementById(\"#{table_name}\");
843
856
  #{table_name}HtColumns = grid && [grid.getElementsByTagName(\"TR\")[0]];
@@ -881,7 +894,8 @@ if (grid) {
881
894
  // });
882
895
  }
883
896
  function setHeaderSizes() {
884
- document.getElementById(\"titleBox\").style.width = grid.clientWidth;
897
+ if (grid.clientWidth > window.outerWidth)
898
+ document.getElementById(\"titleBox\").style.width = grid.clientWidth;
885
899
  // console.log(\"start\");
886
900
  // See if the headerTop is already populated
887
901
  // %%% Grab the TRs from headerTop, clear it out, do this stuff, add them back
@@ -1136,12 +1150,13 @@ erDiagram
1136
1150
  <td><h1><%= td_count = 2
1137
1151
  model.name %></h1></td>
1138
1152
  <td id=\"imgErd\" title=\"Show ERD\"></td>
1139
- <% if Object.const_defined?('Avo') && ::Avo.respond_to?(:railtie_namespace)
1153
+ <% if Object.const_defined?('Avo') && ::Avo.respond_to?(:railtie_namespace) && model.name.exclude?('::')
1140
1154
  td_count += 1 %>
1141
1155
  <td><%= link_to_brick(
1142
1156
  avo_svg,
1143
- { index_proc: Proc.new do |avo_model|
1144
- ::Avo.railtie_routes_url_helpers.send(\"resources_#\{model.model_name.route_key}_path\".to_sym)
1157
+ { index_proc: Proc.new do |avo_model, relation|
1158
+ path_helper = \"resources_#\{relation.fetch(:auto_prefixed_schema, nil)}#\{model.model_name.route_key}_path\".to_sym
1159
+ ::Avo.railtie_routes_url_helpers.send(path_helper) if ::Avo.railtie_routes_url_helpers.respond_to?(path_helper)
1145
1160
  end,
1146
1161
  title: \"#\{model.name} in Avo\" }
1147
1162
  ) %></td>
@@ -1328,8 +1343,9 @@ erDiagram
1328
1343
  <% if Object.const_defined?('Avo') && ::Avo.respond_to?(:railtie_namespace) %>
1329
1344
  <td><%= link_to_brick(
1330
1345
  avo_svg,
1331
- { show_proc: Proc.new do |obj|
1332
- ::Avo.railtie_routes_url_helpers.send(\"resources_#\{obj.class.base_class.model_name.singular_route_key}_path\".to_sym, obj)
1346
+ { show_proc: Proc.new do |obj, relation|
1347
+ path_helper = \"resources_#\{relation.fetch(:auto_prefixed_schema, nil)}#\{obj.class.base_class.model_name.singular_route_key}_path\".to_sym
1348
+ ::Avo.railtie_routes_url_helpers.send(path_helper, obj) if ::Avo.railtie_routes_url_helpers.respond_to?(path_helper)
1333
1349
  end,
1334
1350
  title: \"#\{page_title} in Avo\" }
1335
1351
  ) %></td>
@@ -1408,8 +1424,8 @@ end
1408
1424
  \"<span class=\\\"orphan\\\">Orphaned ID: #\{val}</span>\".html_safe
1409
1425
  end %>
1410
1426
  <% else
1411
- col_type = col.sql_type == 'geography' ? col.sql_type : col.type
1412
- case (col_type ||= col.sql_type)
1427
+ col_type = col&.sql_type == 'geography' ? col.sql_type : col&.type
1428
+ case (col_type ||= col&.sql_type)
1413
1429
  when :string, :text %>
1414
1430
  <% if is_bcrypt?(val) # || .readonly?
1415
1431
  is_revert = false %>
@@ -1489,9 +1505,9 @@ end
1489
1505
  # association that points to an STI model then filtering for the __able_type column is done
1490
1506
  # with a .where(). And the polymorphic class name it points to is the base class name of
1491
1507
  # the STI model instead of its subclass.
1492
- if (poly_type = #{poly_type.inspect}) &&
1493
- @#{obj_name}.respond_to?(:#{@_brick_model.inheritance_column}) &&
1494
- (base_type = collection.where_values_hash[poly_type])
1508
+ poly_type = #{poly_type.inspect}
1509
+ if poly_type && @#{obj_name}.respond_to?(:#{@_brick_model.inheritance_column}) &&
1510
+ (base_type = collection.where_values_hash[poly_type])
1495
1511
  collection = collection.rewhere(poly_type => [base_type, @#{obj_name}.#{@_brick_model.inheritance_column}])
1496
1512
  end"
1497
1513
  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)
@@ -200,13 +201,14 @@ module Brick::Rails::FormTags
200
201
  end
201
202
  filter = "?#{filter_parts.join('&')}" if filter_parts.present?
202
203
  app_routes = Rails.application.routes # In case we're operating in another engine, reference the application since Brick routes are placed there.
204
+ relation = ::Brick.relations.fetch(rel_name || args.first.table_name, nil)
203
205
  if (klass_or_obj&.is_a?(Class) && klass_or_obj < ActiveRecord::Base) ||
204
206
  (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}"
207
+ 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
208
  lt_args = [text || "Index for #{klass_or_obj.name.pluralize}", path]
207
209
  else
208
210
  # 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}"
211
+ 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
212
  lt_args = [text || "Show this #{klass_or_obj.class.name}", path]
211
213
  end
212
214
  kwargs.delete(:visited)
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 109
8
+ TINY = 111
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
data/lib/brick.rb CHANGED
@@ -135,7 +135,8 @@ 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, :initializer_loaded
138
+ attr_accessor :default_schema, :db_schemas, :test_schema,
139
+ :routes_done, :is_oracle, :is_eager_loading, :auto_models, :initializer_loaded
139
140
 
140
141
  def set_db_schema(params = nil)
141
142
  # If Apartment::Tenant.current is not still the default (usually 'public') then an elevator has brought us into
@@ -148,6 +149,10 @@ module Brick
148
149
  ::Brick.db_schemas&.key?(schema)
149
150
  Apartment::Tenant.switch!(schema)
150
151
  schema
152
+ elsif ::Brick.test_schema
153
+ is_show_schema_list = true
154
+ Apartment::Tenant.switch!(::Brick.test_schema)
155
+ ::Brick.test_schema
151
156
  else
152
157
  current_schema # Just return the current schema
153
158
  end
@@ -601,7 +606,7 @@ In config/initializers/brick.rb appropriate entries would look something like:
601
606
  def display_classes(prefix, rels, max_length)
602
607
  rels.sort.each do |rel|
603
608
  (::Brick.auto_models ||= []) << rel.first
604
- puts "#{rel.first}#{' ' * (max_length - rel.first.length)} /#{prefix}#{rel.last}"
609
+ puts "#{rel.first}#{' ' * (max_length - rel.first.length)} /#{prefix}#{"#{rel[1]}/" if rel[1]}#{rel.last}"
605
610
  end
606
611
  puts "\n"
607
612
  end
@@ -620,16 +625,21 @@ In config/initializers/brick.rb appropriate entries would look something like:
620
625
  end
621
626
 
622
627
  c_path_parts = ctrl_path.split('/')
628
+ found = nil
623
629
  while c_path_parts.present?
624
630
  possible_c_path = c_path_parts.join('.')
625
631
  possible_c_path_singular = c_path_parts[0..-2] + [c_path_parts.last.singularize]
626
632
  possible_sti = possible_c_path_singular.join('/').camelize
627
633
  break if (
628
- res_name = res_names[possible_c_path] ||
634
+ res_name = res_names[found = possible_c_path] ||
629
635
  ((klass = Brick.config.sti_namespace_prefixes.key?("::#{possible_sti}") && possible_sti.constantize) &&
630
636
  (sti_type = possible_sti)) ||
631
637
  # %%% 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('.')]
638
+ res_names[found = possible_c_path] || res_names[found = possible_c_path_singular.join('.')] ||
639
+ ((::Brick.config.table_name_prefixes.key?(tn_prefix = c_path_parts.first) ||
640
+ ::Brick.config.table_name_prefixes.key?(tn_prefix = "#{c_path_parts.first}_")) &&
641
+ res_names[found = tn_prefix + c_path_parts.last]
642
+ )
633
643
  ) &&
634
644
  (
635
645
  klass ||
@@ -638,7 +648,7 @@ In config/initializers/brick.rb appropriate entries would look something like:
638
648
  )
639
649
  c_path_parts.shift
640
650
  end
641
- [klass, sti_type]
651
+ [klass, sti_type, found]
642
652
  end
643
653
  end
644
654
 
@@ -657,10 +667,14 @@ In config/initializers/brick.rb appropriate entries would look something like:
657
667
  table_class_length = 38 # Length of "Classes that can be built from tables:"
658
668
  view_class_length = 37 # Length of "Classes that can be built from views:"
659
669
 
660
- brick_routes_create = lambda do |schema_name, res_name, options|
661
- if schema_name # && !Object.const_defined('Apartment')
662
- send(:namespace, schema_name) do
663
- send(:resources, res_name.to_sym, **options)
670
+ brick_namespace_create = lambda do |path_names, res_name, options|
671
+ if path_names&.present?
672
+ if (path_name = path_names.pop).is_a?(Array)
673
+ module_name = path_name[1]
674
+ path_name = path_name.first
675
+ end
676
+ send(:scope, { module: module_name || path_name, path: path_name, as: path_name }) do
677
+ brick_namespace_create.call(path_names, res_name, options)
664
678
  end
665
679
  else
666
680
  send(:resources, res_name.to_sym, **options)
@@ -676,13 +690,24 @@ In config/initializers/brick.rb appropriate entries would look something like:
676
690
  end
677
691
  versioned_views = {} # Track which views have already been done for each api_root
678
692
  ::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
693
  if (schema_name = v.fetch(:schema, nil))
683
694
  schema_prefix = "#{schema_name}."
684
695
  end
685
696
 
697
+ next if !(resource_name = v.fetch(:resource, nil)) ||
698
+ existing_controllers.key?(controller_name = (
699
+ resource_name = "#{schema_prefix&.tr('.', '/')}#{resource_name}"
700
+ ).pluralize)
701
+
702
+ object_name = k.split('.').last # Take off any first schema part
703
+
704
+ full_schema_prefix = if (aps = v.fetch(:auto_prefixed_schema, nil))
705
+ aps = aps[0..-2] if aps[-1] == '_'
706
+ (schema_prefix&.dup || +'') << "#{aps}."
707
+ else
708
+ schema_prefix
709
+ end
710
+
686
711
  # Track routes being built
687
712
  if (class_name = v.fetch(:class_name, nil))
688
713
  if v.key?(:isView)
@@ -691,26 +716,20 @@ In config/initializers/brick.rb appropriate entries would look something like:
691
716
  else
692
717
  table_class_length = class_name.length if class_name.length > table_class_length
693
718
  tables
694
- end << [class_name, "#{schema_prefix&.tr('.', '/')}#{v[:resource]}"]
719
+ end << [class_name, aps, resource_name]
695
720
  end
696
721
 
697
722
  options = {}
698
723
  options[:only] = [:index, :show] if v.key?(:isView)
699
724
 
700
725
  # First do the normal routes
701
- if path_prefix
702
- # Was: send(:scope, path: path_prefix) do
703
- send(:namespace, path_prefix) do
704
- brick_routes_create.call(schema_name, v[:resource], options)
705
- sti_subclasses.fetch(class_name, nil)&.each do |sc| # Add any STI subclass routes for this relation
706
- brick_routes_create.call(schema_name, sc.underscore.tr('/', '_').pluralize, options)
707
- end
708
- end
709
- else
710
- brick_routes_create.call(schema_name, v[:resource], options)
711
- sti_subclasses.fetch(class_name, nil)&.each do |sc| # Add any STI subclass routes for this relation
712
- brick_routes_create.call(schema_name, sc.underscore.tr('/', '_').pluralize, options)
713
- end
726
+ prefixes = []
727
+ prefixes << [aps, v[:class_name]&.split('::')[-2]&.underscore] if aps
728
+ prefixes << schema_name if schema_name
729
+ prefixes << path_prefix if path_prefix
730
+ brick_namespace_create.call(prefixes, v[:resource], options)
731
+ sti_subclasses.fetch(class_name, nil)&.each do |sc| # Add any STI subclass routes for this relation
732
+ brick_namespace_create.call(prefixes, sc.underscore.tr('/', '_').pluralize, options)
714
733
  end
715
734
 
716
735
  # Now the API routes if necessary
@@ -815,9 +834,8 @@ In config/initializers/brick.rb appropriate entries would look something like:
815
834
  # view_ver_num = if (first_part = k.split('_').first) =~ /^v[\d_]+/
816
835
  # first_part[1..-1].gsub('_', '.').to_i
817
836
  # end
818
-
819
837
  controller_name = if (last = view_relation.fetch(:resource, nil)&.pluralize)
820
- "#{schema_prefix}#{last}"
838
+ "#{full_schema_prefix}#{last}"
821
839
  else
822
840
  found
823
841
  end.tr('.', '/')
@@ -1484,12 +1502,12 @@ module ActiveRecord
1484
1502
  # entry in your .select().
1485
1503
  # More information: https://discuss.rubyonrails.org/t/includes-and-select-for-joined-data/81640
1486
1504
  def apply_column_aliases(relation)
1487
- if (sel_vals = relation.select_values.map(&:to_s)).first == '_brick_eager_load'
1505
+ if !(@join_root_alias = relation.select_values.empty?) &&
1506
+ relation.select_values.first.to_s == '_brick_eager_load'
1507
+ relation.select_values.shift
1488
1508
  used_cols = {}
1489
1509
  # Find and expand out all column names being used in select(...)
1490
- new_select_values = sel_vals.each_with_object([]) do |col, s|
1491
- next if col == '_brick_eager_load'
1492
-
1510
+ new_select_values = relation.select_values.map(&:to_s).each_with_object([]) do |col, s|
1493
1511
  if col.include?(' ') # Some expression? (No chance for a simple column reference)
1494
1512
  s << col # Just pass it through
1495
1513
  else
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.109
4
+ version: 1.0.111
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-27 00:00:00.000000000 Z
11
+ date: 2023-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord