brick 1.0.172 → 1.0.174

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: 8a38be99462ba1e409c48be433e3ab289b971872c6a3988e28159f52cfdc4645
4
- data.tar.gz: 4af53a2029649d13b978f9ab263ce2ead02818afd807751621cf6fd38ac1b7dc
3
+ metadata.gz: 0c4dedcd4841e168876c88839c56a60b23a8d3d8799a350dc9d2445cde293b5e
4
+ data.tar.gz: 46063c6afaf4d2025c1f1b3e74481391a737ab00a710b0e1ef0e51aac3994871
5
5
  SHA512:
6
- metadata.gz: 9890e01ab3124bf1256f094569abd92c92712d440df8f3ccf9f06cf6ec57fb29bf4afa3e7acc7344253330ae80cbb17983aa4b6b508f2748b13b8926553dadd1
7
- data.tar.gz: 280c4a94f788fe459f83ea18fa858152020d952eadb0bc5cd9aee645e03faf65d3dca5edd045328366d7f67a62879341043657396c6bf35ab0e282850cd889fe
6
+ metadata.gz: 61b711584141e7625b996cf0406a4b50bc6fadb45379d6d321e94fed7b2b219a90d3007ac52514ed29316caacd5150d57bebff3ac7a92e059ed69b01c8f992c5
7
+ data.tar.gz: 88c00b72167ec0dddfa525937dcd9e6451fec52f85a64d91de46ad53d073a8d12c3f38e44e093b01f30a22fc56ef363a60d70f416dbca5329b5350965d5666d4
data/lib/brick/config.rb CHANGED
@@ -21,10 +21,11 @@ module Brick
21
21
  end
22
22
 
23
23
  def mode
24
+ rails_env = Object.const_defined?('Rails') && ::Rails.env
24
25
  @mutex.synchronize do
25
26
  case @brick_mode
26
27
  when nil, :development
27
- (::Rails.env == 'development' || ENV.key?('BRICK')) ? :on : nil
28
+ (rails_env == 'development' || ENV.key?('BRICK')) ? :on : nil
28
29
  when :diag_env
29
30
  ENV.key?('BRICK') ? :on : nil
30
31
  else
@@ -1288,6 +1288,7 @@ end
1288
1288
  end
1289
1289
  # puts "#{self.name} - #{args.first}"
1290
1290
  # Unless it's a Brick prefix looking for a TNP that should create a module ...
1291
+ relations = ::Brick.relations
1291
1292
  unless (is_tnp_module = (is_brick_prefix && !is_controller && ::Brick.config.table_name_prefixes.values.include?(requested)))
1292
1293
  # ... first look around for an existing module or class.
1293
1294
  desired_classname = (self == Object || !name) ? requested : "#{name}::#{requested}"
@@ -1309,12 +1310,16 @@ end
1309
1310
  (possible.instance_of?(Class) && possible == self)) && # Are we simply searching for ourselves?
1310
1311
  # Skip when what we found as `possible` is not related to the base class of an STI model
1311
1312
  (!sti_base || possible.is_a?(sti_base))
1313
+ # if possible.is_a?(ActiveRecord::Base) && !possible.abstract_class? && (pk = possible.primary_key) &&
1314
+ # !(relation = relations.fetch(possible.table_name, nil))&.fetch(:pks, nil)
1315
+ # binding.pry
1316
+ # x = 5
1317
+ # end
1312
1318
  return possible
1313
1319
  end
1314
1320
  end
1315
1321
  end
1316
1322
  class_name = ::Brick.namify(requested)
1317
- relations = ::Brick.relations
1318
1323
  # CONTROLLER
1319
1324
  result = if ::Brick.enable_controllers? &&
1320
1325
  is_controller && (plural_class_name = class_name[0..-11]).length.positive?
@@ -1885,7 +1890,7 @@ class Object
1885
1890
  cspd.select! { |val| val == "'self'" }
1886
1891
  cspd << style_value
1887
1892
  else
1888
- cspd << "'sha256-W2ts9oOhJ+mkUTLCn4yS7VZSGkeqfdUogX8MEjE0TSw='"
1893
+ cspd << "'sha256-Q8t+pETkz0RtyV4XprwdP+uEkVaFyMnx1mXif0wDoxw='"
1889
1894
  end
1890
1895
  cspd << 'https://cdn.jsdelivr.net'
1891
1896
  end
@@ -1908,6 +1913,8 @@ class Object
1908
1913
  end
1909
1914
  self.define_method :crosstab do
1910
1915
  @relations = ::Brick.relations.each_with_object({}) do |r, s|
1916
+ next if r.first.is_a?(Symbol)
1917
+
1911
1918
  cols = r.last[:cols].each_with_object([]) do |c, s2|
1912
1919
  s2 << [c.first] + c.last
1913
1920
  end
@@ -2030,8 +2037,10 @@ class Object
2030
2037
  }
2031
2038
  unless ::Brick.config.enable_api == false
2032
2039
  json['paths'] = relations.each_with_object({}) do |relation, s|
2033
- next if (api_vers = relation.last.fetch(:api, nil)) &&
2034
- !(api_ver_paths = api_vers[current_api_ver] || api_vers[nil])
2040
+ next if relation.first.is_a?(Symbol) || (
2041
+ (api_vers = relation.last.fetch(:api, nil)) &&
2042
+ !(api_ver_paths = api_vers[current_api_ver] || api_vers[nil])
2043
+ )
2035
2044
 
2036
2045
  schema_tag = {}
2037
2046
  if (schema_name = relation.last&.fetch(:schema, nil))
@@ -2278,10 +2287,15 @@ class Object
2278
2287
  else
2279
2288
  @_lookup_context.instance_variable_set("@#{singular_table_name}".to_sym,
2280
2289
  (created_obj = model.send(:create, send(params_name_sym))))
2281
- # %%% Surface any errors to the user in a flash message
2282
2290
  @_lookup_context.instance_variable_set(:@_brick_model, model)
2283
- index
2284
- render :index
2291
+ if created_obj.errors.empty?
2292
+ index
2293
+ render :index
2294
+ else # Surface errors to the user in a flash message
2295
+ flash.alert = (created_obj.errors.errors.map { |err| "<b>#{err.attribute}</b> #{err.message}" }.join(', '))
2296
+ new
2297
+ render :new
2298
+ end
2285
2299
  end
2286
2300
  end
2287
2301
 
@@ -2350,6 +2364,9 @@ class Object
2350
2364
  upd_hash[model.inheritance_column] = nil
2351
2365
  end
2352
2366
  obj.send(:update, upd_hash || upd_params)
2367
+ if obj.errors.any? # Surface errors to the user in a flash message
2368
+ flash.alert = (obj.errors.errors.map { |err| "<b>#{err.attribute}</b> #{err.message}" }.join(', '))
2369
+ end
2353
2370
  end
2354
2371
 
2355
2372
  code << " def destroy\n"
@@ -2587,14 +2604,14 @@ end.class_exec do
2587
2604
  # return if ActiveRecord::Base.connection.current_database == 'postgres'
2588
2605
 
2589
2606
  orig_schema = nil
2590
- if (relations = ::Brick.relations).empty?
2607
+ if (relations = ::Brick.relations).keys == [:db_name]
2591
2608
  ::Brick.remove_instance_variable(:@_additional_references_loaded) if ::Brick.instance_variable_defined?(:@_additional_references_loaded)
2592
2609
  # Very first thing, load inflections since we'll be using .pluralize and .singularize on table and model names
2593
- if File.exist?(inflections = ::Rails.root.join('config/initializers/inflections.rb'))
2610
+ if File.exist?(inflections = ::Rails.root&.join('config/initializers/inflections.rb') || '')
2594
2611
  load inflections
2595
2612
  end
2596
2613
  # Now the Brick initializer since there may be important schema things configured
2597
- if !::Brick.initializer_loaded && File.exist?(brick_initializer = ::Rails.root.join('config/initializers/brick.rb'))
2614
+ if !::Brick.initializer_loaded && File.exist?(brick_initializer = ::Rails.root&.join('config/initializers/brick.rb') || '')
2598
2615
  ::Brick.initializer_loaded = load brick_initializer
2599
2616
 
2600
2617
  # After loading the initializer, add compatibility for ActiveStorage and ActionText if those haven't already been
@@ -2660,10 +2677,9 @@ end.class_exec do
2660
2677
  s[row.first] = { dt: row.last } unless ['information_schema', 'pg_catalog', 'pg_toast', 'heroku_ext',
2661
2678
  'INFORMATION_SCHEMA', 'sys'].include?(row.first)
2662
2679
  end
2663
- if (possible_schemas = (multitenancy = ::Brick.config.schema_behavior&.[](:multitenant)) &&
2664
- multitenancy&.[](:schema_to_analyse))
2665
- possible_schemas = [possible_schemas] unless possible_schemas.is_a?(Array)
2666
- if (possible_schema = possible_schemas.find { |ps| ::Brick.db_schemas.key?(ps) })
2680
+ possible_schema, possible_schemas, multitenancy = ::Brick.get_possible_schemas
2681
+ if possible_schemas
2682
+ if possible_schema
2667
2683
  ::Brick.default_schema = ::Brick.apartment_default_tenant
2668
2684
  schema = possible_schema
2669
2685
  orig_schema = ActiveRecord::Base.execute_sql('SELECT current_schemas(true)').first['current_schemas'][1..-2].split(',')
@@ -2742,7 +2758,14 @@ end.class_exec do
2742
2758
  relation[:ukeys][r['key'] || "#{relation_name}.#{col_name}"] ||= []
2743
2759
  # key = (relation[:ukeys] = Hash.new { |h, k| h[k] = [] }) if key.is_a?(Array)
2744
2760
  # key[r['key']]
2761
+ else
2762
+ if r['data_type'] == 'uuid'
2763
+ # && r['column_name'] == ::Brick.ar_base.primary_key
2764
+ # binding.pry
2765
+ relation[:pkey][r['key'] || relation_name] ||= []
2766
+ end
2745
2767
  end
2768
+ # binding.pry if key && r['data_type'] == 'uuid'
2746
2769
  key << col_name if key
2747
2770
  cols = relation[:cols] # relation.fetch(:cols) { relation[:cols] = [] }
2748
2771
  cols[col_name] = [r['data_type'], r['max_length'], measures&.include?(col_name), r['is_nullable'] == 'NO']
@@ -2909,6 +2932,8 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
2909
2932
  end
2910
2933
 
2911
2934
  relations.each do |k, v|
2935
+ next if k.is_a?(Symbol)
2936
+
2912
2937
  rel_name = k.split('.').map { |rel_part| ::Brick.namify(rel_part, :underscore) }
2913
2938
  schema_names = rel_name[0..-2]
2914
2939
  schema_names.shift if ::Brick.apartment_multitenant && schema_names.first == ::Brick.apartment_default_tenant
@@ -3145,6 +3170,10 @@ module Brick
3145
3170
  assoc_bt[:inverse] = assoc_hm
3146
3171
  end
3147
3172
 
3173
+ def ar_base
3174
+ @ar_base ||= Object.const_defined?(:ApplicationRecord) ? ApplicationRecord : Class.new(ActiveRecord::Base)
3175
+ end
3176
+
3148
3177
  # Identify built out routes, migrations, models,
3149
3178
  # (and also soon controllers and views!)
3150
3179
  # for each resource
@@ -3171,6 +3200,8 @@ module Brick
3171
3200
  abstract_activerecord_bases = ::Brick.eager_load_classes(true)
3172
3201
  rails_root = ::Rails.root.to_s
3173
3202
  models = ::Brick.relations.each_with_object({}) do |rel, s|
3203
+ next if rel.first.is_a?(Symbol)
3204
+
3174
3205
  begin
3175
3206
  if (model = rel.last[:class_name]&.constantize) &&
3176
3207
  (inh = ActiveRecord::Base._brick_inheriteds[model]&.join(':'))
@@ -3223,7 +3254,8 @@ module Brick
3223
3254
  is_default_schema = multi_schema&.==(::Brick.apartment_default_tenant)
3224
3255
  relations.each_with_object([]) do |v, s|
3225
3256
  frn_tbl = v.first
3226
- next if (relation = v.last).key?(:isView) || config.exclude_tables.include?(frn_tbl) ||
3257
+ next if frn_tbl.is_a?(Symbol) || # Skip internal metadata entries
3258
+ (relation = v.last).key?(:isView) || config.exclude_tables.include?(frn_tbl) ||
3227
3259
  !(for_pk = (relation[:pkey].values.first&.first))
3228
3260
 
3229
3261
  is_default_frn_schema = !is_default_schema && multi_schema &&
@@ -6,7 +6,7 @@ module Brick
6
6
  def display_value(col_type, val, lat_lng = nil)
7
7
  is_mssql_geography = nil
8
8
  # Some binary thing that really looks like a Microsoft-encoded WGS84 point? (With the first two bytes, E6 10, indicating an EPSG code of 4326)
9
- if col_type == :binary && val && val.length < 31 && (val.length - 6) % 8 == 0 && val[0..5].bytes == [230, 16, 0, 0, 1, 12]
9
+ if col_type == :binary && val && ::Brick.is_geography?(val)
10
10
  col_type = 'geography'
11
11
  is_mssql_geography = true
12
12
  end
@@ -19,7 +19,7 @@ module Brick
19
19
 
20
20
  if @is_mysql || (is_mssql_geography ||=
21
21
  (@is_mssql ||
22
- (val && val.length < 31 && (val.length - 6) % 8 == 0 && val[0..5].bytes == [230, 16, 0, 0, 1, 12])
22
+ (val && ::Brick.is_geography?(val))
23
23
  )
24
24
  )
25
25
  # MySQL's \"Internal Geometry Format\" and MSSQL's Geography are like WKB, but with an initial 4 bytes that indicates the SRID.
@@ -204,7 +204,7 @@ function linkSchemas() {
204
204
  <polygon style=\"fill:#894747;\" points=\"58,31.559 19,52 19,35 58,15.831\"/>
205
205
  </g>
206
206
  </svg>
207
- ".html_safe
207
+ "
208
208
 
209
209
  # paths['app/models'] << 'lib/brick/frameworks/active_record/models'
210
210
  config.brick = ActiveSupport::OrderedOptions.new
@@ -335,20 +335,16 @@ function linkSchemas() {
335
335
  def eager_load(entity)
336
336
  _brick_eager_load(entity)
337
337
  if entity == :resources
338
- # %%% This useful logic can be DRYd up since it's very similar to what's around extensions.rb:1894
339
- if (possible_schemas = (multitenancy = ::Brick.config.schema_behavior&.[](:multitenant)) &&
340
- multitenancy&.[](:schema_to_analyse))
341
- possible_schemas = [possible_schemas] unless possible_schemas.is_a?(Array)
342
- if (possible_schema = possible_schemas.find { |ps| ::Brick.db_schemas.key?(ps) })
343
- orig_tenant = Apartment::Tenant.current
344
- Apartment::Tenant.switch!(possible_schema)
345
- end
338
+ possible_schema, _x1, _x2 = ::Brick.get_possible_schemas
339
+ if possible_schema
340
+ orig_tenant = Apartment::Tenant.current
341
+ Apartment::Tenant.switch!(possible_schema)
346
342
  end
347
343
  existing = Avo::BaseResource.descendants.each_with_object({}) do |r, s|
348
344
  s[r.name[0..-9]] = nil if r.name.end_with?('Resource')
349
345
  end
350
346
  ::Brick.relations.each do |k, v|
351
- unless existing.key?(class_name = v[:class_name]) || Brick.config.exclude_tables.include?(k) ||
347
+ unless k.is_a?(Symbol) || existing.key?(class_name = v[:class_name]) || Brick.config.exclude_tables.include?(k) ||
352
348
  class_name.blank? || class_name.include?('::')
353
349
  Object.const_get("#{class_name}Resource")
354
350
  end
@@ -403,7 +399,7 @@ window.addEventListener(\"popstate\", linkSchemas);
403
399
  end
404
400
  def to_s
405
401
  @_name.to_s.html_safe + @vc.instance_variable_get(:@__vc_helpers)&.link_to_brick(nil,
406
- BRICK_SVG,
402
+ BRICK_SVG.html_safe,
407
403
  { title: "#{@_name} in Brick" }
408
404
  )
409
405
  end
@@ -468,7 +464,7 @@ window.addEventListener(\"popstate\", linkSchemas);
468
464
  alias _brick_routes routes
469
465
  def routes(*args)
470
466
  ::Brick.relations.each do |k, v|
471
- next if k == 'active_admin_comments'
467
+ next if k.is_a?(Symbol) || k == 'active_admin_comments'
472
468
 
473
469
  begin
474
470
  if (class_name = Object.const_get(v.fetch(:class_name, nil)))
@@ -490,7 +486,7 @@ window.addEventListener(\"popstate\", linkSchemas);
490
486
  rescue
491
487
  end
492
488
  h2((@title + link_to_brick(nil,
493
- BRICK_SVG, # This would do well to be sized a bit smaller
489
+ BRICK_SVG.html_safe, # This would do well to be sized a bit smaller
494
490
  { title: "#{@_name} in Brick" }
495
491
  )).html_safe)
496
492
  else
@@ -522,7 +518,7 @@ window.addEventListener(\"popstate\", linkSchemas);
522
518
  def fetch_models
523
519
  # Auto-create Brick models
524
520
  ::Brick.relations.each do |k, v|
525
- next if k == 'active_admin_comments'
521
+ next if k.is_a?(Symbol) || k == 'active_admin_comments'
526
522
 
527
523
  begin
528
524
  v[:class_name].constantize
@@ -558,7 +554,7 @@ window.addEventListener(\"popstate\", linkSchemas);
558
554
  (::Brick.config.json_columns['motor_audits'] ||= []) << 'audited_changes' if mar_tables.include?('motor_audits')
559
555
  (::Brick.config.json_columns['motor_configs'] ||= []) << 'value' if mar_tables.include?('motor_configs')
560
556
  ::Brick.relations.each do |k, v|
561
- next if mar_tables.include?(k) || k == 'motor_audits'
557
+ next if k.is_a?(Symbol) || mar_tables.include?(k) || k == 'motor_audits'
562
558
 
563
559
  v[:class_name].constantize
564
560
  end
@@ -611,7 +607,7 @@ window.addEventListener(\"popstate\", linkSchemas);
611
607
  alias :_brick_lookup_context :lookup_context
612
608
  def lookup_context(*args)
613
609
  ret = _brick_lookup_context(*args)
614
- @_lookup_context.instance_variable_set(:@_brick_req_params, params)
610
+ @_lookup_context.instance_variable_set(:@_brick_req_params, params) if request
615
611
  ret
616
612
  end
617
613
  end
@@ -777,7 +773,7 @@ window.addEventListener(\"popstate\", linkSchemas);
777
773
  # environment or whatever, then get either the controllers or routes list instead
778
774
  prefix = "#{::Brick.config.path_prefix}/" if ::Brick.config.path_prefix
779
775
  table_options = ::Brick.relations.each_with_object({}) do |rel, s|
780
- next if ::Brick.config.exclude_tables.include?(rel.first)
776
+ next if rel.first.is_a?(Symbol) || ::Brick.config.exclude_tables.include?(rel.first)
781
777
 
782
778
  tbl_parts = rel.first.split('.')
783
779
  if (aps = rel.last.fetch(:auto_prefixed_schema, nil))
@@ -803,15 +799,26 @@ window.addEventListener(\"popstate\", linkSchemas);
803
799
  position: sticky;
804
800
  display: inline-block;
805
801
  left: 0;
802
+ z-index: 2;
806
803
  }
807
804
 
808
805
  .flashNotice {
809
806
  color: green;
810
807
  }
808
+ .flashAlert {
809
+ color: red;
810
+ }
811
811
 
812
812
  h1, h3 {
813
813
  margin-bottom: 0;
814
814
  }
815
+ #rowCount {
816
+ display: table-cell;
817
+ height: 32px;
818
+ vertical-align: middle;
819
+ font-size: 0.9em;
820
+ font-family: sans-serif;
821
+ }
815
822
  #imgErd {
816
823
  display: table-cell;
817
824
  background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE0AAABNCAMAAADU1xmCAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAARxaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA2LjAuMCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvIgogICAgICAgICAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgICAgICAgICAgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjcyPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj43MjwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHhtcE1NOkRlcml2ZWRGcm9tIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgPHN0UmVmOmluc3RhbmNlSUQ+eG1wLmlpZDoxN0U3OEI3RjAzN0MxMUU3QTZDMDhBQjVCRDc2QkZCQjwvc3RSZWY6aW5zdGFuY2VJRD4KICAgICAgICAgICAgPHN0UmVmOmRvY3VtZW50SUQ+eG1wLmRpZDoxN0U3OEI4MDAzN0MxMUU3QTZDMDhBQjVCRDc2QkZCQjwvc3RSZWY6ZG9jdW1lbnRJRD4KICAgICAgICAgPC94bXBNTTpEZXJpdmVkRnJvbT4KICAgICAgICAgPHhtcE1NOkRvY3VtZW50SUQ+eG1wLmRpZDoxN0U3OEI4MjAzN0MxMUU3QTZDMDhBQjVCRDc2QkZCQjwveG1wTU06RG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDoxN0U3OEI4MTAzN0MxMUU3QTZDMDhBQjVCRDc2QkZCQjwveG1wTU06SW5zdGFuY2VJRD4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3M8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+ChMBcXgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAL9UExURUdwTDRRc1EVG6ioqFJSUmJiYn+AgURWa2uEkauorszGwmtrawonUKzY7DMRIlFTVWV9m4qKiwaN0G1raJSQiJjV7jWh2HmizPLs6CaV0QohSmdoaVdXWLWsomFdYmIgD4WCfQWa2WIoFUxylldpekeRuGtrajhztIuLizV3qc3DvThDVEyFs31+fiRViVRNViVWjwsvWxIzXxZEekeL1FZIVVRdeEZrk359fj52ppubm3l6e4qbqJOTlBlGfM3k3Nzc3K6lnk9RWaenp0FjikGDyJGRkWJiYk2L0Li4uJubnH5+flFbeNPT02tpac3NzVBGJkCCyMvLy9LS0oxETk2U3tLS0tXV1cPDw+Xl5amDftbX19na2uLj4+jo6dzd3OXl511dXd/g31paWlZXV9TU1HBwcOvr687OzdDQ0u/u7fTx79PSzcrJx6KiooWFhujn5NvW05WUk7S1t3R1d7y9vcLCv37J68vMzVJTVOLY1gMiSpmamnt7e7K6zHq+43LQ9Vyez+Pf3LGyscXGybzD1sXDw46v02vI8I+Pj7vEtNvIx7q4ubnZ54a3it3f5s+8vGS/6L6trK+6qICs1H+33cXc6KiuwAOr48fN20ee0Fao0lyz4W6s1qyrrKKlt3XdkoqnyyFoqzuTy6ixosuVeobA4YHNl8TOv3/Ck9bc4I3P7Uqq3tDIxz2FwzN/vF+VxdDe59mIfU+OxJmovxl+wX7S9WjbhovW9jihyKGalIq31uNyY36exJCatJONhTm36nKj0B2q4Mqxsae2zc/U3tvf1cqKa7zAyJS4npqyyTh2tUhMT1drj5ixtN98cEfC8U2Y5vf39355cSN0s4mDfKaomlrG8b2cmcFvaGx/m2CeZge68HG64YCNntSgoVHUdJzKnIHIh6c+BalVVaPM5qrG2CZZkyaHH3WRtYrdn5nH2rxoP22+gN1VQTyxW1aXl0iO2GaxtFuzaCCAQyXSWDOKlDZwkxIINVZPP52Io3uldtIoC1uGVxmzRP6PHn8AAADVdFJOUwAmEf6t/v4EAQVR/oT+Hl4U/v1bR/7+Kf7+a/76Q4Y2Wf1b4j71sXm0y2hF/bBwbtXN/fyGl8Sxiu382Preqfzia9iIkdP51/Povnineu+9n6H7ov5ksLfYy/7////////+/////////////////////v/////////////////////////////////////////////////////////////////////////////+/////////////////////////////////////////////////////r5xM8kAAA0qSURBVFjDpZh3WFNnG8YDMZOiLEFEsVhn1Vq1Vq1abWv3br+dc5IQsklCSEiIyAoJyAhb9h4ishVQcCAIOLC4UBFxr7bu0X6dX6/vec8JikIptecPVrh+576f5z3vez+HQmGyKBSK28eT4SsL/fiXLiaFwmD/E5NzPmU7wG8s5l/DOXy8+vhxLg8TcN5/yw0JZPwV2GoJH+fjPI7UHBWV/8HzwGIynlkgm+vv788RiURSs06bT6WuJAQynlEgO+JaUzoWhGAWE1X1mkqlmYUEMp5JIBs7ejYz3L4iyN+gy1epVMGvaYI1K5faIIF/nsfuPDr325LMo5XpvCCFThUMrHccY2L85j2TQHZna11kZFGd19lo+4oI/yiqJiYmxtGP7kdf/gwC2bLWuix1RWTX7uzMo+PTI4KkJo0fXPSQkBDxDOc/KZBtaK3P4uLqrPXri+rcz4YjgbpgegidHhIgDhC/6/mnBLLNVTWdclzdmbYTeAMClVS6OCAgQGxnZ0cbM4dBPDKjoh2oqo309ZV3ppWV7UTAur1nw+MrIhRaRzsPsdiDRqN5v+lpO0oc0OrrirLkiWGVZVYeIXBLRFBUsNiH5kHz9vHxeZMxOhxb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);
@@ -1037,21 +1044,8 @@ callbacks = {} %>"
1037
1044
  poly_cols = #{poly_cols.inspect} %>"
1038
1045
  end
1039
1046
 
1040
- addNewLink = if !@_brick_model&.is_view?
1041
- "<% if respond_to?(:#{new_path_name = "new_#{path_obj_name}_path"}) %>
1042
- var addNew = document.createElement(\"A\");
1043
- addNew.id = \"addNew\";
1044
- addNew.href = \"<%= send(:#{new_path_name}) %>\";
1045
- addNew.title = \"New #{obj_name}\";
1046
- addNew.innerHTML = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"#fff\" d=\"M24 10h-10v-10h-4v10h-10v4h10v10h4v-10h10z\"/></svg>';
1047
- document.getElementById(\"headerButtonBox\").append(addNew);
1048
- <% end %>"
1049
- end
1050
-
1051
1047
  # %%% When doing schema select, if we're on a new page go to index
1052
1048
  script = "<script>
1053
- var #{table_name}HtColumns;
1054
-
1055
1049
  // Add \"Are you sure?\" behaviour to any data-confirm buttons out there
1056
1050
  document.querySelectorAll(\"input[type=submit][data-confirm]\").forEach(function (btn) {
1057
1051
  btn.addEventListener(\"click\", function (evt) {
@@ -1062,108 +1056,11 @@ document.querySelectorAll(\"input[type=submit][data-confirm]\").forEach(function
1062
1056
  });
1063
1057
  });
1064
1058
 
1059
+ <%= @_brick_javascripts&.fetch(:grid_scripts, nil)&.html_safe
1060
+ %>
1065
1061
  #{JS_CHANGEOUT}#{
1066
1062
  "\nbrickTestSchema = \"#{::Brick.test_schema}\";" if ::Brick.test_schema
1067
1063
  }
1068
- // Snag first TR for sticky header
1069
- var grid = document.getElementById(\"#{table_name}\");
1070
- #{table_name}HtColumns = grid && [grid.getElementsByTagName(\"TR\")[0]];
1071
- var headerTop = document.getElementById(\"headerTop\");
1072
- var headerCols;
1073
- if (grid) {
1074
- // COLUMN HEADER AND TABLE CELL HIGHLIGHTING
1075
- var gridHighHeader = null,
1076
- gridHighCell = null;
1077
- grid.addEventListener(\"mouseenter\", gridMove);
1078
- grid.addEventListener(\"mousemove\", gridMove);
1079
- grid.addEventListener(\"mouseleave\", function (evt) {
1080
- if (gridHighCell) gridHighCell.classList.remove(\"highlight\");
1081
- gridHighCell = null;
1082
- if (gridHighHeader) gridHighHeader.classList.remove(\"highlight\");
1083
- gridHighHeader = null;
1084
- });
1085
- function gridMove(evt) {
1086
- var lastHighCell = gridHighCell;
1087
- gridHighCell = document.elementFromPoint(evt.x, evt.y);
1088
- while (gridHighCell && gridHighCell.tagName !== \"TD\" && gridHighCell.tagName !== \"TH\")
1089
- gridHighCell = gridHighCell.parentElement;
1090
- if (gridHighCell) {
1091
- if (lastHighCell !== gridHighCell) {
1092
- gridHighCell.classList.add(\"highlight\");
1093
- if (lastHighCell) lastHighCell.classList.remove(\"highlight\");
1094
- }
1095
- var lastHighHeader = gridHighHeader;
1096
- if ((gridHighHeader = headerCols[gridHighCell.cellIndex]) && lastHighHeader !== gridHighHeader) {
1097
- if (gridHighHeader) gridHighHeader.classList.add(\"highlight\");
1098
- if (lastHighHeader) lastHighHeader.classList.remove(\"highlight\");
1099
- }
1100
- }
1101
- }
1102
- // // LESS TOUCHY NAVIGATION BACK OR FORWARD IN HISTORY WHEN USING MOUSE WHEEL
1103
- // grid.addEventListener(\"wheel\", function (evt) {
1104
- // grid.scrollLeft += evt.deltaX;
1105
- // document.body.scrollTop += (evt.deltaY * 0.6);
1106
- // evt.preventDefault();
1107
- // return false;
1108
- // });
1109
- }
1110
- function setHeaderSizes() {
1111
- if (grid.clientWidth > window.outerWidth)
1112
- document.getElementById(\"titleBox\").style.width = grid.clientWidth;
1113
- // console.log(\"start\");
1114
- // See if the headerTop is already populated
1115
- // %%% Grab the TRs from headerTop, clear it out, do this stuff, add them back
1116
- headerTop.innerHTML = \"\"; // %%% Would love to not have to clear it out like this every time! (Currently doing this to support resize events.)
1117
- var isEmpty = headerTop.childElementCount === 0;
1118
- var numFixed = parseInt(grid.getAttribute(\"x-num-frozen\")) || 0;
1119
- var fixedColLefts = [0];
1120
-
1121
- // Set up proper sizings of sticky column header
1122
- var node;
1123
- for (var j = 0; j < #{table_name}HtColumns.length; ++j) {
1124
- var row = #{table_name}HtColumns[j];
1125
- var tr = isEmpty ? document.createElement(\"TR\") : headerTop.childNodes[j];
1126
- tr.innerHTML = row.innerHTML.trim();
1127
- var curLeft = 0.0;
1128
- // Match up widths from the original column headers
1129
- for (var i = 0; i < row.childNodes.length; ++i) {
1130
- node = row.childNodes[i];
1131
- if (node.nodeType === 1) {
1132
- var th = tr.childNodes[i];
1133
- th.style.minWidth = th.style.maxWidth = getComputedStyle(node).width;
1134
- // Add \"left: __px\" style to the fixed-width column THs
1135
- if (i <= numFixed) {
1136
- th.style.position = \"sticky\";
1137
- th.style.backgroundColor = \"#008061\";
1138
- th.style.zIndex = \"1\";
1139
- th.style.left = curLeft + \"px\";
1140
- fixedColLefts.push(curLeft += node.clientWidth);
1141
- }
1142
- if (#{pk&.present? ? 'i > 0' : 'true'}) {
1143
- // Add <span> at the end
1144
- var span = document.createElement(\"SPAN\");
1145
- span.className = \"exclude\";
1146
- span.innerHTML = \"X\";
1147
- span.addEventListener(\"click\", function (e) {
1148
- e.stopPropagation();
1149
- doFetch(\"POST\", {_brick_exclude: this.parentElement.getAttribute(\"x-order\")});
1150
- });
1151
- th.appendChild(span);
1152
- }
1153
- }
1154
- }
1155
- headerCols = tr.childNodes;
1156
- if (isEmpty) headerTop.appendChild(tr);
1157
- }
1158
- // Add \"left: __px\" style to all fixed-width column TDs
1159
- [...grid.children[1].children].forEach(function (row) {
1160
- for (var j = 1; j <= numFixed; ++j) {
1161
- row.children[j].style.left = fixedColLefts[j] + 'px';
1162
- }
1163
- });
1164
- grid.style.marginTop = \"-\" + getComputedStyle(headerTop).height;
1165
- // console.log(\"end\");
1166
- }
1167
1064
  function doFetch(method, payload, success) {
1168
1065
  payload.authenticity_token = <%= session[:_csrf_token].inspect.html_safe %>;
1169
1066
  if (!success) {
@@ -1176,13 +1073,7 @@ function doFetch(method, payload, success) {
1176
1073
  if (payload) options.body = JSON.stringify(payload);
1177
1074
  return fetch(location.href, options).then(success);
1178
1075
  }
1179
- if (headerTop) {
1180
- setHeaderSizes();
1181
- window.addEventListener('resize', function(event) {
1182
- setHeaderSizes();
1183
- }, true);#{
1184
- addNewLink}
1185
- }
1076
+
1186
1077
  // Cause descriptive text to use the same font as the resource
1187
1078
  var brickFontFamily = document.getElementById(\"resourceName\").computedStyleMap().get(\"font-family\");
1188
1079
  if (window.brickFontFamily) {
@@ -1402,7 +1293,14 @@ erDiagram
1402
1293
  </head>
1403
1294
  <body>
1404
1295
  <div id=\"titleBox\"><div id=\"titleSticky\">
1405
- <p class=\"flashNotice\"><%= notice if request.respond_to?(:flash) %></p>#{"
1296
+ <% if request.respond_to?(:flash)
1297
+ if (alert)
1298
+ %><p class=\"flashAlert\"><%= alert.html_safe %></p><%
1299
+ end
1300
+ if (notice)
1301
+ %><p class=\"flashNotice\"><%= notice.html_safe %></p><%
1302
+ end
1303
+ end %>#{"
1406
1304
  #{schema_options}" if schema_options}
1407
1305
  <select id=\"tbl\">#{table_options}</select>
1408
1306
  <table id=\"resourceName\"><tr>
@@ -1620,13 +1518,20 @@ end
1620
1518
  c23.141-70.188,89.141-120.906,167.063-120.906c97.25,0,176,78.813,176,176C511.828,227.078,404.391,119.641,271.844,119.641z\" />
1621
1519
  </svg>
1622
1520
 
1623
- <p class=\"flashNotice\"><%= notice if request.respond_to?(:flash) %></p>#{"
1521
+ <% if request.respond_to?(:flash)
1522
+ if (alert)
1523
+ %><p class=\"flashAlert\"><%= alert.html_safe %></p><%
1524
+ end
1525
+ if (notice)
1526
+ %><p class=\"flashNotice\"><%= notice.html_safe %></p><%
1527
+ end
1528
+ end %>#{"
1624
1529
  #{schema_options}" if schema_options}
1625
1530
  <select id=\"tbl\">#{table_options}</select>
1626
1531
  <table id=\"resourceName\"><td><h1><%= page_title %></h1></td>
1627
1532
  <% if Object.const_defined?('Avo') && ::Avo.respond_to?(:railtie_namespace) %>
1628
1533
  <td><%= link_to_brick(
1629
- ::Brick::Rails::AVO_SVG,
1534
+ ::Brick::Rails::AVO_SVG.html_safe,
1630
1535
  { show_proc: Proc.new do |obj, relation|
1631
1536
  path_helper = \"resources_#\{relation.fetch(:auto_prefixed_schema, nil)}#\{obj.class.base_class.model_name.singular_route_key}_path\".to_sym
1632
1537
  ::Avo.railtie_routes_url_helpers.send(path_helper, obj) if ::Avo.railtie_routes_url_helpers.respond_to?(path_helper)
@@ -1638,7 +1543,7 @@ end
1638
1543
  if Object.const_defined?('ActiveAdmin')
1639
1544
  ActiveAdmin.application.namespaces.names.each do |ns| %>
1640
1545
  <td><%= link_to_brick(
1641
- ::Brick::Rails::AA_PNG,
1546
+ ::Brick::Rails::AA_PNG.html_safe,
1642
1547
  { show_proc: Proc.new do |aa_model, relation|
1643
1548
  path_helper = \"#\{ns}_#\{relation.fetch(:auto_prefixed_schema, nil)}#\{rk = aa_model.model_name.singular_route_key}_path\".to_sym
1644
1549
  send(path_helper, obj) if respond_to?(path_helper)
@@ -1694,12 +1599,14 @@ end
1694
1599
  end
1695
1600
  s << "<table id=\"#{hm_name}\" class=\"shadow\">
1696
1601
  <tr><th>#{hm[1]}#{' poly' if hm[0].options[:as]} #{hm[3]}
1602
+ <% if respond_to?(:new_#{partial_new_path_name = hm.first.klass._brick_index(:singular)}_path) %>
1697
1603
  <span class = \"add-hm-related\"><%=
1698
1604
  pk_val = (obj_pk = model.primary_key).is_a?(String) ? obj.send(obj_pk) : obj_pk.map { |pk_part| obj.send(pk_part) }
1699
1605
  pk_val_arr = [pk_val] unless pk_val.is_a?(Array)
1700
1606
  link_to('<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"#fff\" d=\"M24 10h-10v-10h-4v10h-10v4h10v10h4v-10h10z\"/></svg>'.html_safe,
1701
- new_#{hm.first.klass._brick_index(:singular)}_path(predicates))
1607
+ new_#{partial_new_path_name}_path(predicates))
1702
1608
  %></span>
1609
+ <% end %>
1703
1610
  </th></tr>
1704
1611
  <% if (assoc = @#{obj_name}.class.reflect_on_association(:#{hm_name})).macro == :has_one &&
1705
1612
  assoc.options&.fetch(:through, nil).nil?
@@ -91,8 +91,7 @@ module Brick::Rails::FormBuilder
91
91
  when :binary
92
92
  is_revert = false
93
93
  if val
94
- # %%% This same kind of geography check is done two other times in engine.rb ... would be great to DRY it up.
95
- out << if val.length < 31 && (val.length - 6) % 8 == 0 && val[0..5].bytes == [230, 16, 0, 0, 1, 12]
94
+ out << if ::Brick.is_geography?(val)
96
95
  ::Brick::Rails.display_value('geography', val)
97
96
  else
98
97
  ::Brick::Rails.display_binary(val)
@@ -1,7 +1,8 @@
1
1
  module Brick::Rails::FormTags
2
2
  # Our super speedy grid
3
3
  def brick_grid(relation = nil, bt_descrip = nil, sequence = nil, inclusions = nil, exclusions = nil,
4
- cols = {}, poly_cols = nil, bts = {}, hms_keys = [], hms_cols = {})
4
+ cols = {}, poly_cols = nil, bts = {}, hms_keys = [], hms_cols = {},
5
+ show_header: nil, show_row_count: nil, show_erd_button: nil, show_new_button: nil, show_avo_button: nil, show_aa_button: nil)
5
6
  # When a relation is not provided, first see if one exists which matches the controller name
6
7
  unless (relation ||= instance_variable_get("@#{controller_name}".to_sym))
7
8
  # Failing that, dig through the instance variables with hopes to find something that is an ActiveRecord::Relation
@@ -27,44 +28,57 @@ module Brick::Rails::FormTags
27
28
  nfc = Brick.config.sidescroll.fetch(relation.table_name, nil)&.fetch(:num_frozen_columns, nil) ||
28
29
  Brick.config.sidescroll.fetch(:num_frozen_columns, nil) ||
29
30
  0
31
+
32
+ # HTML for brick_grid
30
33
  out = +"<div id=\"headerTopContainer\"><table id=\"headerTop\"></table>
31
- <div id=\"headerTopAddNew\">
32
- <div id=\"headerButtonBox\">
33
- <div id=\"imgErd\" title=\"Show ERD\"></div>
34
34
  "
35
35
  klass = relation.klass
36
- if Object.const_defined?('Avo') && ::Avo.respond_to?(:railtie_namespace) && klass.name.exclude?('::')
37
- out << "
36
+ unless show_header == false
37
+ out << " <div id=\"headerTopAddNew\">
38
+ <div id=\"headerButtonBox\">
39
+ "
40
+ unless show_row_count == false
41
+ out << " <div id=\"rowCount\"></div>
42
+ "
43
+ end
44
+ unless show_erd_button == false
45
+ out << " <div id=\"imgErd\" title=\"Show ERD\"></div>
46
+ "
47
+ end
48
+ if show_avo_button != false && Object.const_defined?('Avo') && ::Avo.respond_to?(:railtie_namespace) && klass.name.exclude?('::')
49
+ out << "
38
50
  <td>#{link_to_brick(
39
- ::Brick::Rails::AVO_SVG,
40
- { index_proc: Proc.new do |_avo_model, relation|
41
- path_helper = "resources_#{relation.fetch(:auto_prefixed_schema, nil)}#{klass.model_name.route_key}_path".to_sym
42
- ::Avo.railtie_routes_url_helpers.send(path_helper) if ::Avo.railtie_routes_url_helpers.respond_to?(path_helper)
43
- end,
44
- title: "#{klass.name} in Avo" }
51
+ ::Brick::Rails::AVO_SVG.html_safe,
52
+ { index_proc: Proc.new do |_avo_model, relation|
53
+ path_helper = "resources_#{relation.fetch(:auto_prefixed_schema, nil)}#{klass.model_name.route_key}_path".to_sym
54
+ ::Avo.railtie_routes_url_helpers.send(path_helper) if ::Avo.railtie_routes_url_helpers.respond_to?(path_helper)
55
+ end,
56
+ title: "#{klass.name} in Avo" }
45
57
  )}</td>
46
58
  "
47
- end
59
+ end
48
60
 
49
- if Object.const_defined?('ActiveAdmin')
50
- ActiveAdmin.application.namespaces.names.each do |ns|
51
- out << "
52
- <td>#{link_to_brick(
53
- ::Brick::Rails::AA_PNG,
54
- { index_proc: Proc.new do |aa_model, relation|
55
- path_helper = "#{ns}_#{relation.fetch(:auto_prefixed_schema, nil)}#{rk = aa_model.model_name.route_key}_path".to_sym
56
- send(path_helper) if respond_to?(path_helper)
57
- end,
58
- title: "#{klass.name} in ActiveAdmin" }
61
+ if show_aa_button != false && Object.const_defined?('ActiveAdmin')
62
+ ActiveAdmin.application.namespaces.names.each do |ns|
63
+ out << "
64
+ <td>#{link_to_brick(
65
+ ::Brick::Rails::AA_PNG.html_safe,
66
+ { index_proc: Proc.new do |aa_model, relation|
67
+ path_helper = "#{ns}_#{relation.fetch(:auto_prefixed_schema, nil)}#{rk = aa_model.model_name.route_key}_path".to_sym
68
+ send(path_helper) if respond_to?(path_helper)
69
+ end,
70
+ title: "#{klass.name} in ActiveAdmin" }
59
71
  )}</td>
60
72
  "
73
+ end
61
74
  end
62
- end
63
-
64
75
  out << " </div>
65
76
  </div>
66
- </div>
67
- <table id=\"#{relation.table_name.split('.').last}\" class=\"shadow\"#{ " x-num-frozen=\"#{nfc}\"" if nfc.positive? }>
77
+ "
78
+ end
79
+
80
+ out << "</div>
81
+ <table id=\"#{table_name = relation.table_name.split('.').last}\" class=\"shadow\"#{ " x-num-frozen=\"#{nfc}\"" if nfc.positive? }>
68
82
  <thead><tr>"
69
83
  pk = klass.primary_key || []
70
84
  pk = [pk] unless pk.is_a?(Array)
@@ -137,6 +151,7 @@ module Brick::Rails::FormTags
137
151
  # ActiveRecord::StatementTimeout in Warehouse::ColdRoomTemperatures_Archive#index
138
152
  # TinyTds::Error: Adaptive Server connection timed out
139
153
  # (After restarting the server it worked fine again.)
154
+ rowCount = 0
140
155
  relation.each do |obj|
141
156
  out << "<tr>\n"
142
157
  out << "<td class=\"col-sticky\">#{link_to('⇛', send("#{klass._brick_index(:singular)}_path".to_sym,
@@ -152,16 +167,16 @@ module Brick::Rails::FormTags
152
167
  out << " class=\"#{classes.join(' ')}\"" if classes&.present?
153
168
  out << '>'
154
169
  if (bt || composite_bt_names[col_name])
155
- if bt[2] # Polymorphic?
156
- if (poly_id = obj.send("#{bt.first}_id"))
170
+ if bt[2] && obj.respond_to?(poly_id_col = "#{bt.first}_id") # Polymorphic?
171
+ if (poly_id = obj.send(poly_id_col))
157
172
  bt_class = obj.send(klass.brick_foreign_type(bt.first))
158
173
  base_class_underscored = (::Brick.existing_stis[bt_class] || bt_class).constantize.base_class._brick_index(:singular)
159
174
  out << link_to("#{bt_class} ##{poly_id}", send("#{base_class_underscored}_path".to_sym, poly_id))
160
175
  end
161
176
  else # BT or HOT
162
177
  bt_class = bt[1].first.first
163
- if bt_descrip
164
- descrips = bt_descrip[bt.first][bt_class]
178
+ if bt_descrip && (this_bt_descrip = bt_descrip[bt.first])
179
+ descrips = this_bt_descrip[bt_class]
165
180
  bt_id_col = if descrips.nil?
166
181
  puts "Caught it in the act for obj / #{col_name}!"
167
182
  elsif descrips.length == 1
@@ -237,10 +252,160 @@ module Brick::Rails::FormTags
237
252
  out << '</td>'
238
253
  end
239
254
  out << '</tr>'
255
+ rowCount += 1
240
256
  end
241
257
  out << " </tbody>
242
258
  </table>
259
+ <script>
260
+ var rowCount = document.getElementById(\"rowCount\");
261
+ if (rowCount) rowCount.innerHTML = \"#{pluralize(rowCount, "row")} &nbsp;\";
262
+ </script>
263
+ "
264
+
265
+ # Javascript for brick_grid
266
+ (@_brick_javascripts ||= {})[:grid_scripts] = "
267
+ var #{table_name}HtColumns;
268
+
269
+ // Snag first TR for sticky header
270
+ var grid = document.getElementById(\"#{table_name}\");
271
+ #{table_name}HtColumns = grid && [grid.getElementsByTagName(\"TR\")[0]];
272
+ var headerTop = document.getElementById(\"headerTop\");
273
+ var headerCols;
274
+ if (grid) {
275
+ // COLUMN HEADER AND TABLE CELL HIGHLIGHTING
276
+ var gridHighHeader = null,
277
+ gridHighCell = null;
278
+ grid.addEventListener(\"mouseenter\", gridMove);
279
+ grid.addEventListener(\"mousemove\", gridMove);
280
+ grid.addEventListener(\"mouseleave\", function (evt) {
281
+ if (gridHighCell) gridHighCell.classList.remove(\"highlight\");
282
+ gridHighCell = null;
283
+ if (gridHighHeader) gridHighHeader.classList.remove(\"highlight\");
284
+ gridHighHeader = null;
285
+ });
286
+ function gridMove(evt) {
287
+ var lastHighCell = gridHighCell;
288
+ gridHighCell = document.elementFromPoint(evt.x, evt.y);
289
+ while (gridHighCell && gridHighCell.tagName !== \"TD\" && gridHighCell.tagName !== \"TH\")
290
+ gridHighCell = gridHighCell.parentElement;
291
+ if (gridHighCell) {
292
+ if (lastHighCell !== gridHighCell) {
293
+ gridHighCell.classList.add(\"highlight\");
294
+ if (lastHighCell) lastHighCell.classList.remove(\"highlight\");
295
+ }
296
+ var lastHighHeader = gridHighHeader;
297
+ if ((gridHighHeader = headerCols[gridHighCell.cellIndex]) && lastHighHeader !== gridHighHeader) {
298
+ if (gridHighHeader) gridHighHeader.classList.add(\"highlight\");
299
+ if (lastHighHeader) lastHighHeader.classList.remove(\"highlight\");
300
+ }
301
+ }
302
+ }
303
+ // // LESS TOUCHY NAVIGATION BACK OR FORWARD IN HISTORY WHEN USING MOUSE WHEEL
304
+ // grid.addEventListener(\"wheel\", function (evt) {
305
+ // grid.scrollLeft += evt.deltaX;
306
+ // document.body.scrollTop += (evt.deltaY * 0.6);
307
+ // evt.preventDefault();
308
+ // return false;
309
+ // });
310
+ }
311
+ function setHeaderSizes() {
312
+ if (grid.clientWidth > window.outerWidth)
313
+ document.getElementById(\"titleBox\").style.width = grid.clientWidth;
314
+ // console.log(\"start\");
315
+ // See if the headerTop is already populated
316
+ // %%% Grab the TRs from headerTop, clear it out, do this stuff, add them back
317
+ headerTop.innerHTML = \"\"; // %%% Would love to not have to clear it out like this every time! (Currently doing this to support resize events.)
318
+ var isEmpty = headerTop.childElementCount === 0;
319
+ var numFixed = parseInt(grid.getAttribute(\"x-num-frozen\")) || 0;
320
+ var fixedColLefts = [0];
321
+
322
+ // Set up proper sizings of sticky column header
323
+ var node;
324
+ for (var j = 0; j < #{table_name}HtColumns.length; ++j) {
325
+ var row = #{table_name}HtColumns[j];
326
+ var tr = isEmpty ? document.createElement(\"TR\") : headerTop.childNodes[j];
327
+ tr.innerHTML = row.innerHTML.trim();
328
+ var curLeft = 0.0;
329
+ // Match up widths from the original column headers
330
+ for (var i = 0; i < row.childNodes.length; ++i) {
331
+ node = row.childNodes[i];
332
+ if (node.nodeType === 1) {
333
+ var th = tr.childNodes[i];
334
+ th.style.minWidth = th.style.maxWidth = getComputedStyle(node).width;
335
+ // Add \"left: __px\" style to the fixed-width column THs
336
+ if (i <= numFixed) {
337
+ th.style.position = \"sticky\";
338
+ th.style.backgroundColor = \"#008061\";
339
+ th.style.zIndex = \"1\";
340
+ th.style.left = curLeft + \"px\";
341
+ fixedColLefts.push(curLeft += node.clientWidth);
342
+ }
343
+ if (#{pk&.present? ? 'i > 0' : 'true'}) {
344
+ // Add <span> at the end
345
+ var span = document.createElement(\"SPAN\");
346
+ span.className = \"exclude\";
347
+ span.innerHTML = \"X\";
348
+ span.addEventListener(\"click\", function (e) {
349
+ e.stopPropagation();
350
+ doFetch(\"POST\", {_brick_exclude: this.parentElement.getAttribute(\"x-order\")});
351
+ });
352
+ th.appendChild(span);
353
+ }
354
+ }
355
+ }
356
+ headerCols = tr.childNodes;
357
+ if (isEmpty) headerTop.appendChild(tr);
358
+ }
359
+ // Add \"left: __px\" style to all fixed-width column TDs
360
+ [...grid.children[1].children].forEach(function (row) {
361
+ for (var j = 1; j <= numFixed; ++j) {
362
+ row.children[j].style.left = fixedColLefts[j] + 'px';
363
+ }
364
+ });
365
+ grid.style.marginTop = \"-\" + getComputedStyle(headerTop).height;
366
+ // console.log(\"end\");
367
+ }
368
+
369
+ if (headerTop) {
370
+ onImagesLoaded(function() {
371
+ setHeaderSizes();
372
+ });
373
+ window.addEventListener(\"resize\", function(event) {
374
+ setHeaderSizes();
375
+ }, true);#{
376
+ if !klass.is_view? && respond_to?(new_path_name = "new_#{klass._brick_index(:singular)}_path")
377
+ "
378
+ var headerButtonBox = document.getElementById(\"headerButtonBox\");
379
+ if (headerButtonBox) {
380
+ var addNew = document.createElement(\"A\");
381
+ addNew.id = \"addNew\";
382
+ addNew.href = \"#{send(new_path_name)}\";
383
+ addNew.title = \"New #{table_name.singularize}\";
384
+ addNew.innerHTML = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"#fff\" d=\"M24 10h-10v-10h-4v10h-10v4h10v10h4v-10h10z\"/></svg>';
385
+ headerButtonBox.append(addNew);
386
+ }
243
387
  "
388
+ end}
389
+ }
390
+
391
+ function onImagesLoaded(event) {
392
+ var images = document.getElementsByTagName(\"IMG\");
393
+ var numLoaded = images.length;
394
+ for (var i = 0; i < images.length; ++i) {
395
+ if (images[i].complete)
396
+ --numLoaded;
397
+ else {
398
+ images[i].addEventListener(\"load\", function() {
399
+ if (--numLoaded <= 0)
400
+ event();
401
+ });
402
+ }
403
+ }
404
+ if (numLoaded <= 0)
405
+ event();
406
+ }
407
+ "
408
+
244
409
  out.html_safe
245
410
  end # brick_grid
246
411
 
@@ -11,8 +11,8 @@ module ::Brick::Rails
11
11
  <path d=\"M82.812 76.8753C82.6905 76.694 82.3715 76.2207 82.2449 76.0444C82.2044 75.9739 82.2044 75.8782 82.1588 75.8127C82.1132 75.7473 82.1335 75.7724 82.1183 75.7573C79.0714 71.3971 75.1056 67.7497 70.4969 65.0692C65.8882 62.3886 60.7474 60.7393 55.4325 60.2361C54.3236 60.1354 53.1943 60.08 52.055 60.08C45.2173 60.1051 38.5214 62.022 32.7166 65.6161C26.9118 69.2102 22.2271 74.3397 19.1864 80.4308L19.151 80.5013C18.7358 81.3323 18.3458 82.1784 17.9914 83.0194L16.9786 85.2655C16.9077 85.3662 16.8419 85.472 16.771 85.5828C16.6647 85.7389 16.5584 85.9 16.4621 86.0612C15.3778 87.6439 13.8123 88.8397 11.995 89.4732C10.1776 90.1068 8.20406 90.1448 6.36344 89.5817C4.52281 89.0186 2.9119 87.884 1.76676 86.3442C0.621625 84.8044 0.00246102 82.9403 0 81.0251C0.00604053 80.0402 0.177178 79.0632 0.506372 78.1344L1.22036 76.5681C1.25084 76.5034 1.28639 76.4411 1.32669 76.3818C1.40265 76.2559 1.47861 76.135 1.56469 76.0192C1.58531 75.9789 1.60901 75.9401 1.63558 75.9034C7.06401 67.6054 14.947 61.1866 24.1977 57.5317C33.4485 53.8768 43.6114 53.166 53.2855 55.4971L48.9155 45.9286L41.9276 30.6188L33.8256 12.8263L33.6433 12.4285C32.7439 10.3058 32.6986 7.92067 33.5167 5.76573L34.0231 4.69304C34.8148 3.24136 35.9941 2.03525 37.431 1.20762C38.868 0.379997 40.5068 -0.0370045 42.1668 0.0025773C43.8268 0.0421591 45.4436 0.536787 46.839 1.43195C48.2345 2.32711 49.3543 3.58804 50.0751 5.07578L50.2523 5.47363L51.8474 8.96365L74.0974 57.708L82.812 76.8753Z\" fill=\"currentColor\" fill-opacity=\"0.22\"></path>
12
12
  <path opacity=\"0.25\" d=\"M41.9129 30.649L35.3301 45.0422C35.2023 45.3204 35.0074 45.563 34.7627 45.7484C34.518 45.9337 34.2311 46.0562 33.9274 46.1048C27.3926 47.1897 21.1567 49.6166 15.617 53.2308C15.279 53.4505 14.8783 53.555 14.4753 53.5286C14.0723 53.5022 13.6889 53.3463 13.3827 53.0844C13.0765 52.8225 12.8642 52.4688 12.7777 52.0765C12.6911 51.6842 12.7351 51.2745 12.9029 50.9092L32.0285 8.99382L33.4869 5.7959C32.6687 7.95084 32.7141 10.336 33.6135 12.4586L33.7958 12.8565L41.9129 30.649Z\" fill=\"currentColor\" fill-opacity=\"0.22\"></path>
13
13
  </svg>
14
- ".html_safe
14
+ "
15
15
 
16
16
  AA_PNG = "<img src=\"data:image/png;base64,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\">
17
- ".html_safe
17
+ "
18
18
  end
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 172
8
+ TINY = 174
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
@@ -89,7 +89,7 @@ end
89
89
  # is first established), and then automatically creates models, controllers, views,
90
90
  # and routes based on those available relations.
91
91
  require 'brick/config'
92
- if Gem::Specification.all_names.any? { |g| g.start_with?('rails-') }
92
+ if Gem::Specification.all_names.any? { |g| g.start_with?('rails-') && g[6..-1] =~ /^([0-9]|\.)+$/ }
93
93
  require 'rails'
94
94
  require 'brick/frameworks/rails'
95
95
  end
@@ -111,6 +111,15 @@ module Brick
111
111
  :is_oracle, :is_eager_loading, :auto_models, :initializer_loaded
112
112
  ::Brick.auto_models = []
113
113
 
114
+ def get_possible_schemas
115
+ if (possible_schemas = (multitenancy = ::Brick.config.schema_behavior&.[](:multitenant)) &&
116
+ multitenancy&.[](:schema_to_analyse))
117
+ possible_schemas = [possible_schemas] unless possible_schemas.is_a?(Array)
118
+ possible_schema = possible_schemas.find { |ps| ::Brick.db_schemas.key?(ps) }
119
+ end
120
+ [possible_schema, possible_schemas, multitenancy]
121
+ end
122
+
114
123
  def set_db_schema(params = nil)
115
124
  # If Apartment::Tenant.current is not still the default (usually 'public') then an elevator has brought us into
116
125
  # a different tenant. If so then don't allow schema navigation.
@@ -140,7 +149,19 @@ module Brick
140
149
  ch.connection_pool_list.blank?
141
150
 
142
151
  # Key our list of relations for this connection off of the connection pool's object_id
143
- (@relations ||= {})[ActiveRecord::Base.connection_pool.object_id] ||= Hash.new { |h, k| h[k] = Hash.new { |h, k| h[k] = {} } }
152
+ cp_objid = ActiveRecord::Base.connection_pool.object_id
153
+ @relations ||= {}
154
+
155
+ # Have we already seen this database? (Perhaps we're connecting to a replica?)
156
+ @relations[cp_objid] ||= if (db_name = ActiveRecord::Base.connection&.instance_variable_get(:@config)&.fetch(:database, nil)) &&
157
+ !@relations.key?(cp_objid) &&
158
+ (existing = @relations.find { |_k, v| v.fetch(:db_name, nil) == db_name })
159
+ existing.last
160
+ else
161
+ Hash.new { |h, k| h[k] = Hash.new { |h, k| h[k] = {} } }.tap do |h|
162
+ h[:db_name] = db_name if db_name
163
+ end
164
+ end
144
165
  end
145
166
 
146
167
  def apartment_multitenant
@@ -297,6 +318,10 @@ module Brick
297
318
  true
298
319
  end
299
320
 
321
+ def is_geography?(val)
322
+ val.length < 31 && (val.length - 6) % 8 == 0 && val[0..5].bytes == [230, 16, 0, 0, 1, 12]
323
+ end
324
+
300
325
  # @api public
301
326
  def mode=(setting)
302
327
  Brick.config.mode = setting
@@ -611,7 +636,9 @@ In config/initializers/brick.rb appropriate entries would look something like:
611
636
  end
612
637
 
613
638
  # Find associative tables that can be set up for has_many :through
614
- ::Brick.relations.each do |_key, tbl|
639
+ ::Brick.relations.each do |key, tbl|
640
+ next if key.is_a?(Symbol)
641
+
615
642
  tbl_cols = tbl[:cols].keys
616
643
  fks = tbl[:fks].each_with_object({}) { |fk, s| s[fk.last[:fk]] = [fk.last[:assoc_name], fk.last[:inverse_table]] if fk.last[:is_bt]; s }
617
644
  # Aside from the primary key and the metadata columns created_at, updated_at, and deleted_at, if this table only has
@@ -706,6 +733,8 @@ In config/initializers/brick.rb appropriate entries would look something like:
706
733
 
707
734
  if res_names.empty?
708
735
  ::Brick.relations.each_with_object({}) do |v, s|
736
+ next if v.first.is_a?(Symbol)
737
+
709
738
  v_parts = v.first.split('.')
710
739
  v_parts.shift if v_parts.first == 'public'
711
740
  res_names[v_parts.join('.')] = v.first
@@ -867,6 +896,8 @@ In config/initializers/brick.rb appropriate entries would look something like:
867
896
  end
868
897
  versioned_views = {} # Track which views have already been done for each api_root
869
898
  ::Brick.relations.each do |k, v|
899
+ next if k.is_a?(Symbol)
900
+
870
901
  if (schema_name = v.fetch(:schema, nil))
871
902
  schema_prefix = "#{schema_name}."
872
903
  end
@@ -894,7 +925,7 @@ In config/initializers/brick.rb appropriate entries would look something like:
894
925
  else
895
926
  table_class_length = class_name.length if class_name.length > table_class_length
896
927
  tables
897
- end << [class_name, aps, resource_name]
928
+ end << [class_name, aps, k.tr('.', '/')]
898
929
  end
899
930
 
900
931
  options = {}
@@ -35,6 +35,8 @@ module Brick
35
35
  end
36
36
  end
37
37
  possible_additional_references = relations.each_with_object(Hash.new { |h, k| h[k] = [] }) do |relation, s|
38
+ next if relation.first.is_a?(Symbol)
39
+
38
40
  this_tnp = tnps&.keys&.find { |tnp| relation.first.start_with?(tnp) }
39
41
  model_filename = "app/models/#{ActiveSupport::Inflector.singularize(relation.first)}.rb"
40
42
  relation.last[:cols].each do |col, type|
@@ -105,7 +105,6 @@ module Brick
105
105
  built_schemas = {} # Track all built schemas so we can place an appropriate drop_schema command only in the first
106
106
  # migration in which that schema is referenced, thereby allowing rollbacks to function properly.
107
107
  versions_to_create = [] # Resulting versions to be used when updating the schema_migrations table
108
- ar_base = Object.const_defined?(:ApplicationRecord) ? ApplicationRecord : Class.new(ActiveRecord::Base)
109
108
  # Start by making migrations for fringe tables (those with no foreign keys).
110
109
  # Continue layer by layer, creating migrations for tables that reference ones already done, until
111
110
  # no more migrations can be created. (At that point hopefully all tables are accounted for.)
@@ -126,7 +125,7 @@ module Brick
126
125
  fringe.each do |tbl|
127
126
  next unless (relation = relations.fetch(tbl, nil))&.fetch(:cols, nil)&.present?
128
127
 
129
- pkey_cols = (rpk = relation[:pkey].values.flatten) & (arpk = [ar_base.primary_key].flatten.sort)
128
+ pkey_cols = (rpk = relation[:pkey].values.flatten) & (arpk = [::Brick.ar_base.primary_key].flatten.sort)
130
129
  # In case things aren't as standard
131
130
  if pkey_cols.empty?
132
131
  pkey_cols = if rpk.empty? && relation[:cols][arpk.first]&.first == key_type
@@ -239,9 +238,9 @@ module Brick
239
238
  begin
240
239
  primary_key = relations[fk[:inverse_table]][:class_name]&.constantize&.primary_key
241
240
  rescue NameError => e
242
- primary_key = ar_base.primary_key
241
+ primary_key = ::Brick.ar_base.primary_key
243
242
  end
244
- mig << " t.references :#{fk[:assoc_name]}#{suffix}, foreign_key: { to_table: #{to_table}#{", primary_key: :#{primary_key}" if primary_key != ar_base.primary_key} }\n"
243
+ mig << " t.references :#{fk[:assoc_name]}#{suffix}, foreign_key: { to_table: #{to_table}#{", primary_key: :#{primary_key}" if primary_key != ::Brick.ar_base.primary_key} }\n"
245
244
  end
246
245
  else
247
246
  next if !id_option&.end_with?('id: false') && pkey_cols&.include?(col)
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.172
4
+ version: 1.0.174
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-09-01 00:00:00.000000000 Z
11
+ date: 2023-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord