brick 1.0.33 → 1.0.34

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: 7bd78c8878b1ce8e8e58fb4d8463322269d2ac065c5ed12079dcc64360dc30d5
4
- data.tar.gz: e6926fdc0ec59ad609be39361dbfe0ccea24c1b08a01ccf0a4ae8eb1aa9e2ba2
3
+ metadata.gz: 9d1e2f8b6ff7ca3fa7fcd129c33de3dfe6e674b6da154b9a64e094c65a3a152a
4
+ data.tar.gz: 30e39f62458a46854f56b2a6decbfe5ea42a4bb5325e81ed76f21400aae8e252
5
5
  SHA512:
6
- metadata.gz: 5b6ac439519209c3097c2b2651ed66f319b9c04072d2cee7262aad6c4d9907d61b5b45ee1812c1f6cea1e5e1eed2082eb15953e4e3097c9c12b4f35a1f3af703
7
- data.tar.gz: 5bb559ada7035abb062b0441578d5406e64f87b9f11fde1d5b3b880179098bafe9507a1a6cdd8e1af1cd1fb4defc1d339e0054896ca0e9c507ea831f24a0cb96
6
+ metadata.gz: 14c6bae09e34f53126e2003cbc7256c4b32f4a4219d42f1f7e94ca83211debf3704fa6c170cd6231d89e26eb168f282d1dea7eff7150ef1a013364aeb4eb65c3
7
+ data.tar.gz: 7f33aa5c89be2e8401f4cda0ea6cecb6e01639934a2df1e7b00bd88d065bf3cc9b748bebb1691d51c1b04114fba3b1739a7820c7614f4eb84d52494bd4cc769e
@@ -163,6 +163,7 @@ module ActiveRecord
163
163
  bracket_name.split('.').each do |part|
164
164
  obj_name += ".#{part}"
165
165
  this_obj = caches.fetch(obj_name) { caches[obj_name] = this_obj&.send(part.to_sym) }
166
+ break if this_obj.nil?
166
167
  end
167
168
  this_obj&.to_s || ''
168
169
  end
@@ -308,6 +309,23 @@ module ActiveRecord
308
309
  # , is_add_bts, is_add_hms
309
310
  )
310
311
  is_add_bts = is_add_hms = true
312
+ is_distinct = nil
313
+ wheres = {}
314
+ params.each do |k, v|
315
+ case (ks = k.split('.')).length
316
+ when 1
317
+ next unless klass._brick_get_fks.include?(k)
318
+ when 2
319
+ assoc_name = ks.first.to_sym
320
+ # Make sure it's a good association name and that the model has that column name
321
+ next unless klass.reflect_on_association(assoc_name)&.klass&.column_names&.any?(ks.last)
322
+
323
+ join_array[assoc_name] = nil # Store this relation name in our special collection for .joins()
324
+ is_distinct = true
325
+ distinct!
326
+ end
327
+ wheres[k] = v.split(',')
328
+ end
311
329
 
312
330
  # %%% Skip the metadata columns
313
331
  if selects&.empty? # Default to all columns
@@ -316,7 +334,9 @@ module ActiveRecord
316
334
  if (col_name = col.name) == 'class'
317
335
  col_alias = ' AS _class'
318
336
  end
319
- selects << "\"#{tbl_no_schema}\".\"#{col_name}\"#{col_alias}"
337
+ # Postgres can not use DISTINCT with any columns that are XML, so for any of those just convert to text
338
+ cast_as_text = '::text' if is_distinct && Brick.relations[klass.table_name]&.[](:cols)&.[](col.name)&.first&.start_with?('xml')
339
+ selects << "\"#{tbl_no_schema}\".\"#{col_name}\"#{cast_as_text}#{col_alias}"
320
340
  end
321
341
  end
322
342
 
@@ -342,22 +362,6 @@ module ActiveRecord
342
362
  end
343
363
  end
344
364
 
345
- wheres = {}
346
- params.each do |k, v|
347
- case (ks = k.split('.')).length
348
- when 1
349
- next unless klass._brick_get_fks.include?(k)
350
- when 2
351
- assoc_name = ks.first.to_sym
352
- # Make sure it's a good association name and that the model has that column name
353
- next unless klass.reflect_on_association(assoc_name)&.klass&.column_names&.any?(ks.last)
354
-
355
- join_array[assoc_name] = nil # Store this relation name in our special collection for .joins()
356
- distinct!
357
- end
358
- wheres[k] = v.split(',')
359
- end
360
-
361
365
  if join_array.present?
362
366
  left_outer_joins!(join_array)
363
367
  # Without working from a duplicate, touching the AREL ast tree sets the @arel instance variable, which causes the relation to be immutable.
@@ -375,7 +379,9 @@ module ActiveRecord
375
379
  v1.map { |x| [translations[x[0..-2].map(&:to_s).join('.')], x.last] }.each_with_index do |sel_col, idx|
376
380
  field_tbl_name = (field_tbl_names[v.first][sel_col.first] ||= shift_or_first(chains[sel_col.first])).split('.').last
377
381
 
378
- selects << "#{"\"#{field_tbl_name}\".\"#{sel_col.last}\""} AS \"#{(col_alias = "_brfk_#{v.first}__#{sel_col.last}")}\""
382
+ # Postgres can not use DISTINCT with any columns that are XML, so for any of those just convert to text
383
+ is_xml = is_distinct && Brick.relations[sel_col.first.table_name]&.[](:cols)&.[](sel_col.last)&.first&.start_with?('xml')
384
+ selects << "\"#{field_tbl_name}\".\"#{sel_col.last}\"#{'::text' if is_xml} AS \"#{(col_alias = "_brfk_#{v.first}__#{sel_col.last}")}\""
379
385
  v1[idx] << col_alias
380
386
  end
381
387
 
@@ -571,11 +577,13 @@ Module.class_exec do
571
577
  [built_module, "module #{schema_name}; end\n"]
572
578
  # # %%% Perhaps an option to use the first module just as schema, and additional modules as namespace with a table name prefix applied
573
579
  elsif ::Brick.enable_models?
580
+ # Custom inheritable Brick base model?
581
+ class_name = (inheritable_name = class_name)[5..-1] if class_name.start_with?('Brick')
574
582
  # See if a file is there in the same way that ActiveSupport::Dependencies#load_missing_constant
575
583
  # checks for it in ~/.rvm/gems/ruby-2.7.5/gems/activesupport-5.2.6.2/lib/active_support/dependencies.rb
576
584
 
577
- if self != Object || # Are we in some namespace? ...
578
- (base_model = ::Brick.config.sti_namespace_prefixes&.fetch("::#{name}::", nil)&.constantize) # ... or part of an auto-STI namespace?
585
+ if (base_model = ::Brick.config.sti_namespace_prefixes&.fetch("::#{name}::", nil)&.constantize) || # Are we part of an auto-STI namespace? ...
586
+ self != Object # ... or otherwise already in some namespace?
579
587
  schema_name = [(singular_schema_name = name.underscore),
580
588
  (schema_name = singular_schema_name.pluralize),
581
589
  name,
@@ -588,7 +596,7 @@ Module.class_exec do
588
596
  if base_model
589
597
  schema_name = name.underscore # For the auto-STI namespace models
590
598
  table_name = base_model.table_name
591
- Object.send(:build_model, self, model_name, singular_table_name, table_name, relations, table_name)
599
+ Object.send(:build_model, self, inheritable_name, model_name, singular_table_name, table_name, relations, table_name)
592
600
  else
593
601
  # Adjust for STI if we know of a base model for the requested model name
594
602
  # %%% Does not yet work with namespaced model names. Perhaps prefix with plural_class_name when doing the lookups here.
@@ -603,7 +611,7 @@ Module.class_exec do
603
611
  end
604
612
  # Maybe, just maybe there's a database table that will satisfy this need
605
613
  if (matching = [table_name, singular_table_name, plural_class_name, model_name].find { |m| relations.key?(schema_name ? "#{schema_name}.#{m}" : m) })
606
- Object.send(:build_model, schema_name, model_name, singular_table_name, table_name, relations, matching)
614
+ Object.send(:build_model, schema_name, inheritable_name, model_name, singular_table_name, table_name, relations, matching)
607
615
  end
608
616
  end
609
617
  end
@@ -631,12 +639,12 @@ class Object
631
639
 
632
640
  private
633
641
 
634
- def build_model(schema_name, model_name, singular_table_name, table_name, relations, matching)
642
+ def build_model(schema_name, inheritable_name, model_name, singular_table_name, table_name, relations, matching)
635
643
  full_name = if (::Brick.config.schema_behavior[:multitenant] && Object.const_defined?('Apartment') && schema_name == Apartment.default_schema)
636
644
  relation = relations["#{schema_name}.#{matching}"]
637
- model_name
645
+ inheritable_name || model_name
638
646
  elsif schema_name.blank?
639
- model_name
647
+ inheritable_name || model_name
640
648
  else # Prefix the schema to the table name + prefix the schema namespace to the class name
641
649
  schema_module = if schema_name.instance_of?(Module) # from an auto-STI namespace?
642
650
  schema_name
@@ -644,7 +652,7 @@ class Object
644
652
  matching = "#{schema_name}.#{matching}"
645
653
  (Brick.db_schemas[schema_name] ||= self.const_get(schema_name.singularize.camelize))
646
654
  end
647
- "#{schema_module&.name}::#{model_name}"
655
+ "#{schema_module&.name}::#{inheritable_name || model_name}"
648
656
  end
649
657
 
650
658
  return if ((is_view = (relation ||= relations[matching]).key?(:isView)) && ::Brick.config.skip_database_views) ||
@@ -653,12 +661,14 @@ class Object
653
661
  # Are they trying to use a pluralised class name such as "Employees" instead of "Employee"?
654
662
  if table_name == singular_table_name && !ActiveSupport::Inflector.inflections.uncountable.include?(table_name)
655
663
  unless ::Brick.config.sti_namespace_prefixes&.key?("::#{singular_table_name.camelize}::")
656
- puts "Warning: Class name for a model that references table \"#{matching}\" should be \"#{ActiveSupport::Inflector.singularize(model_name)}\"."
664
+ puts "Warning: Class name for a model that references table \"#{matching
665
+ }\" should be \"#{ActiveSupport::Inflector.singularize(inheritable_name || model_name)}\"."
657
666
  end
658
667
  return
659
668
  end
660
669
 
661
- if (base_model = ::Brick.sti_models[full_name]&.fetch(:base, nil) || ::Brick.existing_stis[full_name]&.constantize)
670
+ full_model_name = full_name.split('::').tap { |fn| fn[-1] = model_name }.join('::')
671
+ if (base_model = ::Brick.sti_models[full_model_name]&.fetch(:base, nil) || ::Brick.existing_stis[full_model_name]&.constantize)
662
672
  is_sti = true
663
673
  else
664
674
  base_model = ::Brick.config.models_inherit_from || ActiveRecord::Base
@@ -666,9 +676,21 @@ class Object
666
676
  hmts = nil
667
677
  code = +"class #{full_name} < #{base_model.name}\n"
668
678
  built_model = Class.new(base_model) do |new_model_class|
669
- (schema_module || Object).const_set(model_name.to_sym, new_model_class)
679
+ (schema_module || Object).const_set((inheritable_name || model_name).to_sym, new_model_class)
680
+ if inheritable_name
681
+ new_model_class.define_singleton_method :inherited do |subclass|
682
+ super(subclass)
683
+ if subclass.name == model_name
684
+ puts "#{full_model_name} properly extends from #{full_name}"
685
+ else
686
+ puts "should be \"class #{model_name} < #{inheritable_name}\"\n (not \"#{subclass.name} < #{inheritable_name}\")"
687
+ end
688
+ end
689
+ self.abstract_class = true
690
+ code << " self.abstract_class = true\n"
691
+ end
670
692
  # Accommodate singular or camel-cased table names such as "order_detail" or "OrderDetails"
671
- code << " self.table_name = '#{self.table_name = matching}'\n" unless table_name == matching
693
+ code << " self.table_name = '#{self.table_name = matching}'\n" if inheritable_name || table_name != matching
672
694
 
673
695
  # Override models backed by a view so they return true for #is_view?
674
696
  # (Dynamically-created controllers and view templates for such models will then act in a read-only way)
@@ -880,19 +902,19 @@ class Object
880
902
  { 'url': 'https://{defaultHost}', 'variables': { 'defaultHost': { 'default': 'www.example.com' } } }
881
903
  ]
882
904
  }
883
- json['paths'] = relations.each_with_object({}) do |v, s|
884
- # next if v.last[:is_view]
885
-
905
+ json['paths'] = relations.inject({}) do |s, v|
886
906
  s["/api/v1/#{v.first}"] = {
887
907
  'get': {
888
- 'summary': 'list #{v.first}',
908
+ 'summary': "list #{v.first}",
889
909
  'parameters': v.last[:cols].map { |k, v| { 'name' => k, 'schema': { 'type': v.first } } },
890
910
  'responses': { '200': { 'description': 'successful' } }
891
911
  }
892
912
  }
913
+ # next if v.last[:isView]
914
+
893
915
  s["/api/v1/#{v.first}/{id}"] = {
894
916
  'patch': {
895
- 'summary': 'update a #{v.first.singularize}',
917
+ 'summary': "update a #{v.first.singularize}",
896
918
  'parameters': v.last[:cols].reject { |k, v| Brick.config.metadata_columns.include?(k) }.map do |k, v|
897
919
  { 'name' => k, 'schema': { 'type': v.first } }
898
920
  end,
@@ -918,6 +940,7 @@ class Object
918
940
  # }
919
941
  # ],
920
942
  }
943
+ s
921
944
  end
922
945
  # binding.pry
923
946
  render inline: json.to_json, content_type: request.format
@@ -1090,12 +1113,14 @@ module ActiveRecord::ConnectionHandling
1090
1113
  when 'Mysql2'
1091
1114
  ::Brick.default_schema = schema = ActiveRecord::Base.connection.current_database
1092
1115
  when 'SQLite'
1116
+ # %%% Retrieve internal ActiveRecord table names like this:
1117
+ # ActiveRecord::Base.internal_metadata_table_name, ActiveRecord::Base.schema_migrations_table_name
1093
1118
  sql = "SELECT m.name AS relation_name, UPPER(m.type) AS table_type,
1094
1119
  p.name AS column_name, p.type AS data_type,
1095
1120
  CASE p.pk WHEN 1 THEN 'PRIMARY KEY' END AS const
1096
1121
  FROM sqlite_master AS m
1097
1122
  INNER JOIN pragma_table_info(m.name) AS p
1098
- WHERE m.name NOT IN ('ar_internal_metadata', 'schema_migrations')
1123
+ WHERE m.name NOT IN (?, ?)
1099
1124
  ORDER BY m.name, p.cid"
1100
1125
  else
1101
1126
  puts "Unfamiliar with connection adapter #{ActiveRecord::Base.connection.adapter_name}"
@@ -1123,6 +1148,9 @@ module ActiveRecord::ConnectionHandling
1123
1148
  end
1124
1149
  end
1125
1150
 
1151
+ # %%% Retrieve internal ActiveRecord table names like this:
1152
+ # ActiveRecord::Base.internal_metadata_table_name, ActiveRecord::Base.schema_migrations_table_name
1153
+ # For if it's not SQLite -- so this is the Postgres and MySQL version
1126
1154
  sql ||= "SELECT t.table_schema AS schema, t.table_name AS relation_name, t.table_type,
1127
1155
  c.column_name, c.data_type,
1128
1156
  COALESCE(c.character_maximum_length, c.numeric_precision) AS max_length,
@@ -1144,13 +1172,13 @@ module ActiveRecord::ConnectionHandling
1144
1172
  WHERE t.table_schema NOT IN ('information_schema', 'pg_catalog')#{"
1145
1173
  AND t.table_schema = COALESCE(current_setting('SEARCH_PATH'), 'public')" if schema }
1146
1174
  -- AND t.table_type IN ('VIEW') -- 'BASE TABLE', 'FOREIGN TABLE'
1147
- AND t.table_name NOT IN ('pg_stat_statements', 'ar_internal_metadata', 'schema_migrations')
1175
+ AND t.table_name NOT IN ('pg_stat_statements', ?, ?)
1148
1176
  ORDER BY 1, t.table_type DESC, c.ordinal_position"
1149
1177
  measures = []
1150
1178
  case ActiveRecord::Base.connection.adapter_name
1151
1179
  when 'PostgreSQL', 'SQLite' # These bring back a hash for each row because the query uses column aliases
1152
1180
  # schema ||= 'public' if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
1153
- ActiveRecord::Base.execute_sql(sql).each do |r|
1181
+ ActiveRecord::Base.execute_sql(sql, ActiveRecord::Base.internal_metadata_table_name, ActiveRecord::Base.schema_migrations_table_name).each do |r|
1154
1182
  # If Apartment gem lists the table as being associated with a non-tenanted model then use whatever it thinks
1155
1183
  # is the default schema, usually 'public'.
1156
1184
  schema_name = if ::Brick.config.schema_behavior[:multitenant]
@@ -1259,11 +1287,25 @@ module ActiveRecord::ConnectionHandling
1259
1287
  end
1260
1288
  end
1261
1289
 
1262
- puts "\nClasses that can be built from tables:"
1263
- relations.select { |_k, v| !v.key?(:isView) }.keys.each { |k| puts ActiveSupport::Inflector.singularize(k).camelize }
1264
- unless (views = relations.select { |_k, v| v.key?(:isView) }).empty?
1290
+ apartment = Object.const_defined?('Apartment') && Apartment
1291
+ tables = []
1292
+ views = []
1293
+ relations.each do |k, v|
1294
+ name_parts = k.split('.')
1295
+ if v.key?(:isView)
1296
+ views
1297
+ else
1298
+ name_parts.shift if apartment && name_parts.length > 1 && name_parts.first == Apartment.default_schema
1299
+ tables
1300
+ end << name_parts.map { |x| x.singularize.camelize }.join('::')
1301
+ end
1302
+ unless tables.empty?
1303
+ puts "\nClasses that can be built from tables:"
1304
+ tables.sort.each { |x| puts x }
1305
+ end
1306
+ unless views.empty?
1265
1307
  puts "\nClasses that can be built from views:"
1266
- views.keys.each { |k| puts ActiveSupport::Inflector.singularize(k).camelize }
1308
+ views.sort.each { |x| puts x }
1267
1309
  end
1268
1310
 
1269
1311
  ::Brick.load_additional_references if initializer_loaded
@@ -1306,7 +1348,8 @@ module Brick
1306
1348
  end
1307
1349
  # %%% Temporary schema patch
1308
1350
  for_tbl = fk[1]
1309
- fk[0] = Apartment.default_schema if Object.const_defined?('Apartment') && Apartment.excluded_models.include?(for_tbl.singularize.camelize)
1351
+ apartment = Object.const_defined?('Apartment') && Apartment
1352
+ fk[0] = Apartment.default_schema if apartment && apartment.excluded_models.include?(for_tbl.singularize.camelize)
1310
1353
  fk[1] = "#{fk[0]}.#{fk[1]}" if fk[0] # && fk[0] != ::Brick.default_schema
1311
1354
  bts = (relation = relations.fetch(fk[1], nil))&.fetch(:fks) { relation[:fks] = {} }
1312
1355
 
@@ -1321,7 +1364,7 @@ module Brick
1321
1364
  is_schema = if ::Brick.config.schema_behavior[:multitenant]
1322
1365
  # If Apartment gem lists the primary table as being associated with a non-tenanted model
1323
1366
  # then use 'public' schema for the primary table
1324
- if Object.const_defined?('Apartment') && Apartment.excluded_models.include?(fk[4].singularize.camelize)
1367
+ if apartment&.excluded_models.include?(fk[4].singularize.camelize)
1325
1368
  fk[3] = Apartment.default_schema
1326
1369
  true
1327
1370
  end
@@ -1398,7 +1441,7 @@ module Brick
1398
1441
  assoc_hm[:alternate_name] = "#{assoc_hm[:alternate_name]}_#{bt_assoc_name}" unless assoc_hm[:alternate_name] == bt_assoc_name
1399
1442
  assoc_hm[:inverse] = assoc_bt
1400
1443
  else
1401
- inv_tbl = if ::Brick.config.schema_behavior[:multitenant] && Object.const_defined?('Apartment') && fk[0] == Apartment.default_schema
1444
+ inv_tbl = if ::Brick.config.schema_behavior[:multitenant] && apartment && fk[0] == Apartment.default_schema
1402
1445
  for_tbl
1403
1446
  else
1404
1447
  fk[1]
@@ -124,8 +124,15 @@ module Brick
124
124
  schema_options = ::Brick.db_schemas.keys.each_with_object(+'') { |v, s| s << "<option value=\"#{v}\">#{v}</option>" }.html_safe
125
125
  # %%% If we are not auto-creating controllers (or routes) then omit by default, and if enabled anyway, such as in a development
126
126
  # environment or whatever, then get either the controllers or routes list instead
127
- table_options = (::Brick.relations.keys - ::Brick.config.exclude_tables).sort
128
- .each_with_object(+'') { |v, s| s << "<option value=\"#{v.underscore.gsub('.', '/').pluralize}\">#{v}</option>" }.html_safe
127
+ apartment_default_schema = ::Brick.config.schema_behavior[:multitenant] && Object.const_defined?('Apartment') && Apartment.default_schema
128
+ table_options = (::Brick.relations.keys - ::Brick.config.exclude_tables).map do |tbl|
129
+ if (tbl_parts = tbl.split('.')).first == apartment_default_schema
130
+ tbl = tbl_parts.last
131
+ end
132
+ tbl
133
+ end.sort.each_with_object(+'') do |v, s|
134
+ s << "<option value=\"#{v.underscore.gsub('.', '/').pluralize}\">#{v}</option>"
135
+ end.html_safe
129
136
  css = +"<style>
130
137
  #dropper {
131
138
  background-color: #eee;
@@ -238,9 +245,10 @@ end %>"
238
245
  poly_cols = #{poly_cols.inspect} %>"
239
246
  end
240
247
 
241
- # %%% When doing schema select, if there's an ID then remove it, or if we're on a new page go to index
248
+ # %%% When doing schema select, if we're on a new page go to index
242
249
  script = "<script>
243
250
  var schemaSelect = document.getElementById(\"schema\");
251
+ var tblSelect = document.getElementById(\"tbl\");
244
252
  var brickSchema;
245
253
  if (schemaSelect) {
246
254
  brickSchema = changeout(location.href, \"_brick_schema\");
@@ -250,7 +258,8 @@ if (schemaSelect) {
250
258
  schemaSelect.value = brickSchema || \"public\";
251
259
  schemaSelect.focus();
252
260
  schemaSelect.addEventListener(\"change\", function () {
253
- location.href = changeout(location.href, \"_brick_schema\", this.value);
261
+ // If there's an ID then remove it (trim after selected table)
262
+ location.href = changeout(location.href, \"_brick_schema\", this.value, tblSelect.value);
254
263
  });
255
264
  }
256
265
  [... document.getElementsByTagName(\"FORM\")].forEach(function (form) {
@@ -265,7 +274,6 @@ if (schemaSelect) {
265
274
  });
266
275
  });
267
276
 
268
- var tblSelect = document.getElementById(\"tbl\");
269
277
  if (tblSelect) {
270
278
  tblSelect.value = changeout(location.href)[0];
271
279
  if (tblSelect.selectedIndex < 0) tblSelect.value = changeout(location.href)[1];
@@ -277,7 +285,7 @@ if (tblSelect) {
277
285
  });
278
286
  }
279
287
 
280
- function changeout(href, param, value) {
288
+ function changeout(href, param, value, trimAfter) {
281
289
  var hrefParts = href.split(\"?\");
282
290
  if (param === undefined || param === null) {
283
291
  hrefParts = hrefParts[0].split(\"://\");
@@ -288,6 +296,11 @@ function changeout(href, param, value) {
288
296
  else
289
297
  return hrefParts[0] + \"://\" + pathParts[0] + \"/\" + value;
290
298
  }
299
+ if (trimAfter) {
300
+ var pathParts = hrefParts[0].split(\"/\");
301
+ while (pathParts.lastIndexOf(trimAfter) != pathParts.length - 1) pathParts.pop();
302
+ hrefParts[0] = pathParts.join(\"/\");
303
+ }
291
304
  var params = hrefParts.length > 1 ? hrefParts[1].split(\"&\") : [];
292
305
  params = params.reduce(function (s, v) { var parts = v.split(\"=\"); s[parts[0]] = parts[1]; return s; }, {});
293
306
  if (value === undefined) return params[param];
@@ -566,7 +579,7 @@ function changeout(href, param, value) {
566
579
  s << "<table id=\"#{hm_name}\">
567
580
  <tr><th>#{hm[3]}</th></tr>
568
581
  <% collection = @#{obj_name}.#{hm_name}
569
- collection = collection.is_a?(ActiveRecord::Associations::CollectionProxy) ? collection.order(#{pk.inspect}) : [collection]
582
+ collection = collection.is_a?(ActiveRecord::Associations::CollectionProxy) ? collection.order(#{pk.inspect}) : [collection].compact
570
583
  if collection.empty? %>
571
584
  <tr><td>(none)</td></tr>
572
585
  <% else %>
@@ -600,6 +613,7 @@ function changeout(href, param, value) {
600
613
 
601
614
  # Just in case it hadn't been done previously when we tried to load the brick initialiser,
602
615
  # go make sure we've loaded additional references (virtual foreign keys and polymorphic associations).
616
+ # (This should only happen if for whatever reason the initializer file was not exactly config/initializers/brick.rb.)
603
617
  ::Brick.load_additional_references
604
618
  end
605
619
  end
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 33
8
+ TINY = 34
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
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.33
4
+ version: 1.0.34
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lorin Thwaits
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-21 00:00:00.000000000 Z
11
+ date: 2022-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord