brick 1.0.109 → 1.0.111

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