brick 1.0.152 → 1.0.153

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: 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