brick 1.0.152 → 1.0.153

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: 4b4101e6f3437aaf0cb79eec97a94b9df6655d9db8a4773e761768556d2ec31f
4
- data.tar.gz: 543bad78f1a359af9126373928789d868530b7ed09c17dbf18bf52a012a37763
3
+ metadata.gz: fc98614593bc4e4931a445801f4f7764c15e6032daf2765f8d78a47f61b7b3a7
4
+ data.tar.gz: 5b3ae1d718df14101c153b335a66578a5b02771714dedd7ebda1022cadebe482
5
5
  SHA512:
6
- metadata.gz: 84d77e9a74428eea4e90f0a40b6e2a6dc824623a6b8975659698b4c79b73ec2ec5f5f26409c5d3d7f0c89c33e6c0aafb73a0c69b8cb3900654d10c528f3d4699
7
- data.tar.gz: 556ad657abeb7a2368940a8b651ef85e6d3c410684e3ab7a088d741ea851e5c31b51bbe8f8baaa017231f56eb7fa177928782b68c6ee7b00c053d1267ac67a1f
6
+ metadata.gz: 15852e3d59a95d5ac8614d98a44a70796c5494610447505abe61dcd02010c3701dc9ba48da951e4639e4fa14694cfee4c7455c2a0bd63fc613738886ca908b26
7
+ data.tar.gz: bd5cc34b7c004461af1737dbcb4b746889bd7f4da7d5242c3f341793ed4675c33a50bc61108a6f1e24037585298361f8f4f6ac699a25a72c4ec860f1c272e0ba
@@ -1244,25 +1244,38 @@ end
1244
1244
  result = if ::Brick.enable_controllers? &&
1245
1245
  is_controller && (plural_class_name = class_name[0..-11]).length.positive?
1246
1246
  # Otherwise now it's up to us to fill in the gaps
1247
+ controller_class_name = +''
1247
1248
  full_class_name = +''
1248
- full_class_name << "::#{(split_self_name&.first && split_self_name.join('::')) || self.name}" unless self == Object
1249
+ unless self == Object
1250
+ controller_class_name << ((split_self_name&.first && split_self_name.join('::')) || self.name)
1251
+ full_class_name << "::#{controller_class_name}"
1252
+ controller_class_name << '::'
1253
+ end
1249
1254
  # (Go over to underscores for a moment so that if we have something come in like VABCsController then the model name ends up as
1250
1255
  # Vabc instead of VABC)
1251
1256
  singular_class_name = ::Brick.namify(plural_class_name, :underscore).singularize.camelize
1252
1257
  full_class_name << "::#{singular_class_name}"
1258
+ skip_controller = nil
1253
1259
  if plural_class_name == 'BrickOpenapi' ||
1254
1260
  (
1255
1261
  (::Brick.config.add_status || ::Brick.config.add_orphans) &&
1256
1262
  plural_class_name == 'BrickGem'
1257
1263
  ) ||
1258
- model = self.const_get(full_class_name)
1259
- # In the very rare case that we've picked up a MODULE which has the same name as what would be the
1260
- # resource's MODEL name, just build out an appropriate auto-model on-the-fly. (RailsDevs code has this in PayCustomer.)
1261
- # %%% We don't yet display the code for this new model
1262
- if model && !model.is_a?(Class)
1263
- model, _code = Object.send(:build_model, relations, model.module_parent, model.module_parent.name, singular_class_name)
1264
+ begin
1265
+ model = self.const_get(full_class_name)
1266
+
1267
+ # In the very rare case that we've picked up a MODULE which has the same name as what would be the
1268
+ # resource's MODEL name, just build out an appropriate auto-model on-the-fly. (RailsDevs code has this in PayCustomer.)
1269
+ # %%% We don't yet display the code for this new model
1270
+ if model && !model.is_a?(Class)
1271
+ model, _code = Object.send(:build_model, relations, model.module_parent, model.module_parent.name, singular_class_name)
1272
+ end
1273
+ rescue NameError # If the const_get for the model has failed...
1274
+ skip_controller = true
1275
+ # ... then just fall through and allow it to fail when trying to loading the ____Controller class normally.
1264
1276
  end
1265
- # if it's a controller and no match or a model doesn't really use the same table name, eager load all models and try to find a model class of the right name.
1277
+ end
1278
+ unless skip_controller
1266
1279
  Object.send(:build_controller, self, class_name, plural_class_name, model, relations)
1267
1280
  end
1268
1281
 
@@ -1475,7 +1488,7 @@ class Object
1475
1488
  code << " has_secure_password\n"
1476
1489
  end
1477
1490
  # Accommodate singular or camel-cased table names such as "order_detail" or "OrderDetails"
1478
- code << " self.table_name = '#{self.table_name = matching}'\n" if inheritable_name || table_name != matching
1491
+ code << " self.table_name = '#{self.table_name = matching}'\n" if inheritable_name || self.table_name != matching
1479
1492
 
1480
1493
  # Override models backed by a view so they return true for #is_view?
1481
1494
  # (Dynamically-created controllers and view templates for such models will then act in a read-only way)
@@ -2225,7 +2238,7 @@ class Object
2225
2238
  end
2226
2239
  end
2227
2240
  end
2228
- if (upd_hash ||= upd_params).fetch(model.inheritance_column, nil).strip == ''
2241
+ if (upd_hash ||= upd_params).fetch(model.inheritance_column, nil)&.strip == ''
2229
2242
  upd_hash[model.inheritance_column] = nil
2230
2243
  end
2231
2244
  obj.send(:update, upd_hash || upd_params)
@@ -2485,6 +2498,11 @@ end.class_exec do
2485
2498
  ::Brick.config.table_name_prefixes[as_tnp] = ar_extension
2486
2499
  end
2487
2500
  end
2501
+
2502
+ # Support the followability gem: https://github.com/nejdetkadir/followability
2503
+ if Object.const_defined?('Followability') && !::Brick.config.table_name_prefixes.key?('followability_')
2504
+ ::Brick.config.table_name_prefixes['followability_'] = 'Followability'
2505
+ end
2488
2506
  end
2489
2507
  # Load the initializer for the Apartment gem a little early so that if .excluded_models and
2490
2508
  # .default_schema are specified then we can work with non-tenanted models more appropriately
@@ -1686,7 +1686,7 @@ end
1686
1686
  end %>
1687
1687
  BT <%= bt_class&.bt_link(bt.first) || orig_poly_name %>
1688
1688
  <% else %>
1689
- <%= k %>
1689
+ <%= #{model_name}.human_attribute_name(k, { default: k }) %>
1690
1690
  <% end %>
1691
1691
  </th>
1692
1692
  <td>
@@ -1,7 +1,29 @@
1
1
  module Brick::Rails::FormTags
2
2
  # Our super speedy grid
3
- def brick_grid(relation, bt_descrip, sequence = nil, inclusions, exclusions,
4
- cols, poly_cols, bts, hms_keys, hms_cols)
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 = {})
5
+ # When a relation is not provided, first see if one exists which matches the controller name
6
+ unless (relation ||= instance_variable_get("@#{controller_name}".to_sym))
7
+ # Failing that, dig through the instance variables with hopes to find something that is an ActiveRecord::Relation
8
+ case (collections = _brick_resource_from_iv).length
9
+ when 0
10
+ puts '#brick_grid: Not having been provided with a collection to work from, searched through all instance variables to find an ActiveRecord::Relation. None could be found.'
11
+ return
12
+ when 1 # If there's only one type match then simply get the first one, hoping that this is what they intended
13
+ relation = instance_variable_get(iv = (chosen = collections.first).last.first)
14
+ puts "#brick_grid: Not having been provided with a collection to work from, first tried @#{controller_name}.
15
+ Failing that, have searched through instance variables and found #{iv} of type #{chosen.first.name}.
16
+ Running with it!"
17
+ else
18
+ myriad = collections.each_with_object([]) { |c, s| c.last.each { |iv| s << "#{iv} (#{c.first.name})" } }
19
+ puts "#brick_grid: Not having been provided with a collection to work from, first tried @#{controller_name}, and then searched through all instance variables.
20
+ Found ActiveRecord::Relation objects of multiple types:
21
+ #{myriad.inspect}
22
+ Not knowing which of these to render, have erred on the side of caution and simply provided this warning message."
23
+ return
24
+ end
25
+ end
26
+
5
27
  out = "<table id=\"headerTop\"></table>
6
28
  <table id=\"#{relation.table_name.split('.').last}\" class=\"shadow\">
7
29
  <thead><tr>"
@@ -14,8 +36,8 @@ module Brick::Rails::FormTags
14
36
  col_keys = relation.columns.each_with_object([]) do |col, s|
15
37
  col_name = col.name
16
38
  next if inclusions&.exclude?(col_name) ||
17
- (pk.include?(col_name) && [:integer, :uuid].include?(col.type) && !bts.key?(col_name)) ||
18
- ::Brick.config.metadata_columns.include?(col_name) || poly_cols.include?(col_name)
39
+ (pk.include?(col_name) && [:integer, :uuid].include?(col.type) && !bts&.key?(col_name)) ||
40
+ ::Brick.config.metadata_columns.include?(col_name) || poly_cols&.include?(col_name)
19
41
 
20
42
  s << col_name
21
43
  cols[col_name] = col
@@ -44,7 +66,8 @@ module Brick::Rails::FormTags
44
66
  "x-order=\"#{bt.first.to_s + '"' unless bt[2]}>BT " +
45
67
  bt[1].map { |bt_pair| bt_pair.first.bt_link(bt.first) }.join(' ')
46
68
  else # Normal column
47
- "x-order=\"#{col_name + '"' if true}>#{col_name}"
69
+ col_name_humanised = klass.human_attribute_name(col_name, { default: col_name })
70
+ "x-order=\"#{col_name + '"' if true}>#{col_name_humanised}"
48
71
  end
49
72
  elsif col # HM column
50
73
  options = {}
@@ -261,16 +284,7 @@ module Brick::Rails::FormTags
261
284
  else
262
285
  # puts "Warning: link_to_brick could not find a class for \"#{controller_path}\" -- consider setting @_brick_model within that controller."
263
286
  # if (hits = res_names.keys & instance_variables.map { |v| v.to_s[1..-1] }).present?
264
- links = instance_variables.each_with_object(Hash.new { |h, k| h[k] = [] }) do |name, s|
265
- iv_name = name.to_s[1..-1]
266
- case (val = instance_variable_get(name))
267
- when ActiveRecord::Relation
268
- s[val.klass] << iv_name
269
- when ActiveRecord::Base
270
- s[val] << iv_name
271
- end
272
- end
273
- if links.length == 1 # If there's only one match then use any text that was supplied
287
+ if (links = _brick_resource_from_iv(true)).length == 1 # If there's only one match then use any text that was supplied
274
288
  link_to_brick(text || links.first.last.join('/'), links.first.first, **kwargs)
275
289
  else
276
290
  links.each_with_object([]) { |v, s| s << link if link = link_to_brick(v.join('/'), v, **kwargs) }.join(' &nbsp; ').html_safe
@@ -278,4 +292,17 @@ module Brick::Rails::FormTags
278
292
  end
279
293
  end # link_to_brick
280
294
 
295
+ private
296
+
297
+ def _brick_resource_from_iv(trim_ampersand = false)
298
+ instance_variables.each_with_object(Hash.new { |h, k| h[k] = [] }) do |name, s|
299
+ iv_name = trim_ampersand ? name.to_s[1..-1] : name
300
+ case (val = instance_variable_get(name))
301
+ when ActiveRecord::Relation
302
+ s[val.klass] << iv_name
303
+ when ActiveRecord::Base
304
+ s[val] << iv_name
305
+ end
306
+ end
307
+ end
281
308
  end
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 152
8
+ TINY = 153
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
@@ -192,10 +192,17 @@ module Brick
192
192
  puts "Based on inclusion in ::Brick.polymorphics, marking association #{full_assoc_name} as being polymorphic."
193
193
  a.options[:polymorphic] = true
194
194
  end
195
- next unless a.polymorphic? || (!a.belongs_to? && (through = a.options[:through])) ||
196
- (a.klass && ::Brick.config.exclude_tables.exclude?(a.klass.table_name) &&
197
- (!a.belongs_to? || model_cols[a.foreign_key]&.type == pk_type)
198
- )
195
+ unless a.polymorphic? || (!a.belongs_to? && (through = a.options[:through])) ||
196
+ (a.klass && ::Brick.config.exclude_tables.exclude?(a.klass.table_name) &&
197
+ (!a.belongs_to? || (same_type = (fk_type = model_cols[a.foreign_key]&.type) == pk_type))
198
+ )
199
+ if same_type == false # We really do want to test specifically for false here, and not nil!
200
+ puts "WARNING:
201
+ Foreign key column #{a.klass.table_name}.#{a.foreign_key} is #{fk_type}, but the primary key it relates to, #{a.active_record.table_name}.#{a.active_record.primary_key}, is #{pk_type}.
202
+ These columns should both be of the same type."
203
+ end
204
+ next
205
+ end
199
206
 
200
207
  if a.belongs_to?
201
208
  if a.polymorphic?
@@ -1375,14 +1382,18 @@ ActiveSupport.on_load(:active_record) do
1375
1382
  arsc.class_exec do
1376
1383
  def self.create(connection, callable = nil, &block)
1377
1384
  relation = (callable || block).call ::ActiveRecord::StatementCache::Params.new
1378
- bind_map = ::ActiveRecord::StatementCache::BindMap.new(
1379
- # AR <= 4.2 uses relation.bind_values
1380
- relation.respond_to?(:bound_attributes) ? relation.bound_attributes : relation.bind_values
1381
- )
1382
1385
  options = [self, relation.arel]
1383
1386
  options.shift if connection.method(:cacheable_query).arity == 1 # Rails <= 5.0
1384
1387
  query_builder = connection.cacheable_query(*options)
1385
- new query_builder, bind_map
1388
+ query_builder, binds = query_builder if query_builder.is_a?(Array) # Accommodate AR < 5.2.4
1389
+
1390
+ bind_map = ::ActiveRecord::StatementCache::BindMap.new(
1391
+ # AR <= 4.2 uses relation.bind_values
1392
+ relation.respond_to?(:bound_attributes) ? relation.bound_attributes : (binds || relation.bind_values)
1393
+ )
1394
+ new_options = [query_builder, bind_map]
1395
+ new_options << relation.klass if binds # Accommodate AR < 5.2.4
1396
+ new(*new_options)
1386
1397
  end
1387
1398
  end
1388
1399
  end
@@ -19,13 +19,25 @@ module Brick
19
19
 
20
20
  def create_initializer_file
21
21
  is_brick_file = File.exist?(filename = 'config/initializers/brick.rb')
22
- if is_brick_file && ::Brick.config.schema_behavior[:multitenant] || !is_brick_file
22
+ if (is_brick_file && (tnps = ::Brick.config.table_name_prefixes).present?) ||
23
+ (::Brick.config.schema_behavior[:multitenant]
24
+ ) || !is_brick_file
23
25
  # See if we can make suggestions for additional_references and polymorphic associations
24
26
  resembles_fks = Hash.new { |h, k| h[k] = [] }
25
27
  possible_polymorphics = {}
26
- possible_additional_references = (relations = ::Brick.relations).each_with_object(Hash.new { |h, k| h[k] = [] }) do |v, s|
27
- model_filename = "app/models/#{ActiveSupport::Inflector.singularize(v.first)}.rb"
28
- v.last[:cols].each do |col, type|
28
+ relations = ::Brick.relations
29
+ if is_brick_file
30
+ # Need to remove any currently-existing additional_references so that it doesn't cloud the discovery process:
31
+ ::Brick.config.additional_references.each do |ar|
32
+ if (fks = relations.fetch(ar[0], nil)&.fetch(:fks, nil))
33
+ fks.delete(fks.find { |k, v| v[:is_bt] && k.start_with?('(brick) ') && v[:fk] == ar[1] }&.first)
34
+ end
35
+ end
36
+ end
37
+ possible_additional_references = relations.each_with_object(Hash.new { |h, k| h[k] = [] }) do |relation, s|
38
+ this_tnp = tnps&.keys.find { |tnp| relation.first.start_with?(tnp) }
39
+ model_filename = "app/models/#{ActiveSupport::Inflector.singularize(relation.first)}.rb"
40
+ relation.last[:cols].each do |col, type|
29
41
  col_down = col.downcase
30
42
 
31
43
  if (is_possible_poly = ['character varying', 'text'].include?(type.first))
@@ -40,7 +52,7 @@ module Brick
40
52
  end
41
53
  is_possible_poly = false if col_down.length < 6 # Was it simply called "type" or something else really short?
42
54
  if is_possible_poly && !File.exist?(model_filename) # Make sure a model file isn't present
43
- possible_polymorphics["#{v.first}.#{col_down}"] = "'#{v.first}.#{col[0..poly_type_cut_length]}'"
55
+ possible_polymorphics["#{relation.first}.#{col_down}"] = "'#{relation.first}.#{col[0..poly_type_cut_length]}'"
44
56
  next
45
57
  end
46
58
  end
@@ -66,16 +78,24 @@ module Brick
66
78
  col_down = col_down[2..-1]
67
79
  end
68
80
  # This possible key not really a primary key and not yet used as a foreign key?
69
- if is_possible && !(relation = relations.fetch(v.first, {}))[:pkey].first&.last&.include?(col) &&
70
- !relations.fetch(v.first, {})[:fks]&.any? { |_k, v| v[:is_bt] && v[:fk] == col }
71
- # Starting to look promising ... make sure a model file isn't present
72
- if !File.exist?(model_filename)
73
- if (relations.fetch(f_table = col_down, nil) ||
74
- relations.fetch(f_table = ActiveSupport::Inflector.pluralize(col_down), nil)) &&
75
- s["#{v.first}.#{col_down}"] << "['#{v.first}', '#{col}', '#{f_table}']"
76
- else
77
- resembles_fks["#{v.first}.#{col_down}"] << "#{v.first}.#{col}"
78
- end
81
+ if is_possible && !relation.last[:pkey].first&.last&.include?(col) &&
82
+ !relation.last[:fks]&.any? { |_k, v| v[:is_bt] && v[:fk] == col } &&
83
+ # Starting to look promising ... make sure a model file isn't present
84
+ !File.exist?(model_filename)
85
+ if (
86
+ (relations.fetch(f_table = col_down, nil) ||
87
+ relations.fetch(f_table = ActiveSupport::Inflector.pluralize(col_down), nil)
88
+ ) && s["#{relation.first}.#{col_down}"] << "['#{relation.first}', '#{col}', '#{f_table}']"
89
+ ) ||
90
+ (
91
+ this_tnp && (full_col_down = this_tnp + col_down) &&
92
+ (relations.fetch(f_table = full_col_down, nil) ||
93
+ relations.fetch(f_table = ActiveSupport::Inflector.pluralize(full_col_down), nil)
94
+ ) && s["#{relation.first}.#{full_col_down}"] << "['#{relation.first}', '#{col}', '#{f_table}']"
95
+ )
96
+ # Found a possible_additional_reference (and set as the last action of the conditional check above)
97
+ else
98
+ resembles_fks["#{relation.first}.#{col_down}"] << "#{relation.first}.#{col}"
79
99
  end
80
100
  end
81
101
  end
@@ -183,7 +203,13 @@ if ActiveRecord::Base.respond_to?(:brick_select) && !::Brick.initializer_loaded
183
203
  # ::Brick.controllers_inherit_from = 'ApplicationController'
184
204
 
185
205
  # # When table names have specific prefixes automatically place them in their own module with a table_name_prefix.
186
- # Brick.table_name_prefixes = { 'nav_' => 'Navigation' }
206
+ #{
207
+ if tnps
208
+ "Brick.table_name_prefixes = #{tnps.inspect}"
209
+ else
210
+ "# Brick.table_name_prefixes = { 'nav_' => 'Navigation' }"
211
+ end
212
+ }
187
213
 
188
214
  # # COLUMN SEQUENCING AND INCLUSION / EXCLUSION
189
215
 
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.152
4
+ version: 1.0.153
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-06-11 00:00:00.000000000 Z
11
+ date: 2023-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord