brick 1.0.15 → 1.0.18

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: 2dbd4fef7ab5c2796e75a0bce86316be00ebceb02aa5a0b8053f75b27d433c57
4
- data.tar.gz: daa2802b2fec6533ccfed8fa9178129c6633f92b83fb092fefa48a657cb36e9b
3
+ metadata.gz: add7e232024e140e2fb089ef158600e2a2a955efd787dc986769b43b4b1f6d24
4
+ data.tar.gz: a45d187a7b739f90b1fede46dfc9f63a2057a3410d052e0ad57322f4741ebfee
5
5
  SHA512:
6
- metadata.gz: 33f97461748561fb21900ccb1b4b39c13803e68e04fea807851b467587907577a10bd5b5a2470cde5f50bca019d3cc986b512545bf700477028f68751bb95e6a
7
- data.tar.gz: 97605afbe32e2509800f510ca2984651cc196c048a6267fa31d65363815bc6f4484955aacd45fae1553fe70453f1bee283766812a2f92678bc35e516ec594738
6
+ metadata.gz: '0897e041c617f0e1e695d0402784184ce2f7ec575d9b0e7a7b1b59b2efbcb40a4de28bcbe2eb124f576dddb8e7371f572c67ee3b19120cd281bf3358249b4508'
7
+ data.tar.gz: fc7a4a93a7d2409f4aa82fb3dbf23710aaad45a1dca1193c8cbcefa86d5d9061a773214c8fe0dd02375660bfb6e5a9856df3a202f57a73990e79d23850918f9b
data/lib/brick/config.rb CHANGED
@@ -66,12 +66,12 @@ module Brick
66
66
  end
67
67
 
68
68
  # Skip creating a has_many association for these
69
- def skip_hms
70
- @mutex.synchronize { @skip_hms }
69
+ def exclude_hms
70
+ @mutex.synchronize { @exclude_hms }
71
71
  end
72
72
 
73
- def skip_hms=(skips)
74
- @mutex.synchronize { @skip_hms = skips }
73
+ def exclude_hms=(skips)
74
+ @mutex.synchronize { @exclude_hms = skips }
75
75
  end
76
76
 
77
77
  # Associations to treat as a has_one
@@ -108,7 +108,7 @@ module Brick
108
108
  end
109
109
 
110
110
  def exclude_tables
111
- @mutex.synchronize { @exclude_tables }
111
+ @mutex.synchronize { @exclude_tables || [] }
112
112
  end
113
113
 
114
114
  def exclude_tables=(value)
@@ -176,25 +176,27 @@ module ActiveRecord
176
176
  end
177
177
  end
178
178
 
179
- module ActiveSupport::Dependencies
180
- class << self
181
- # %%% Probably a little more targeted than other approaches we've taken thusfar
182
- # This happens before the whole parent check
183
- alias _brick_autoload_module! autoload_module!
184
- def autoload_module!(*args)
185
- into, const_name, qualified_name, path_suffix = args
186
- if (base_class = ::Brick.config.sti_namespace_prefixes&.fetch("::#{into.name}::", nil)&.constantize)
187
- ::Brick.sti_models[qualified_name] = { base: base_class }
188
- # Build subclass and place it into the specially STI-namespaced module
189
- into.const_set(const_name.to_sym, klass = Class.new(base_class))
190
- # %%% used to also have: autoload_once_paths.include?(base_path) ||
191
- autoloaded_constants << qualified_name unless autoloaded_constants.include?(qualified_name)
192
- klass
193
- elsif (base_class = ::Brick.config.sti_namespace_prefixes&.fetch("::#{const_name}", nil)&.constantize)
194
- # Build subclass and place it into Object
195
- Object.const_set(const_name.to_sym, klass = Class.new(base_class))
196
- else
197
- _brick_autoload_module!(*args)
179
+ if ActiveSupport::Dependencies.respond_to?(:autoload_module!) # %%% Only works with previous non-zeitwerk auto-loading
180
+ module ActiveSupport::Dependencies
181
+ class << self
182
+ # %%% Probably a little more targeted than other approaches we've taken thusfar
183
+ # This happens before the whole parent check
184
+ alias _brick_autoload_module! autoload_module!
185
+ def autoload_module!(*args)
186
+ into, const_name, qualified_name, path_suffix = args
187
+ if (base_class = ::Brick.config.sti_namespace_prefixes&.fetch("::#{into.name}::", nil)&.constantize)
188
+ ::Brick.sti_models[qualified_name] = { base: base_class }
189
+ # Build subclass and place it into the specially STI-namespaced module
190
+ into.const_set(const_name.to_sym, klass = Class.new(base_class))
191
+ # %%% used to also have: autoload_once_paths.include?(base_path) ||
192
+ autoloaded_constants << qualified_name unless autoloaded_constants.include?(qualified_name)
193
+ klass
194
+ elsif (base_class = ::Brick.config.sti_namespace_prefixes&.fetch("::#{const_name}", nil)&.constantize)
195
+ # Build subclass and place it into Object
196
+ Object.const_set(const_name.to_sym, klass = Class.new(base_class))
197
+ else
198
+ _brick_autoload_module!(*args)
199
+ end
198
200
  end
199
201
  end
200
202
  end
@@ -333,7 +335,6 @@ class Object
333
335
  singular_table_name = ActiveSupport::Inflector.singularize(assoc[:inverse_table])
334
336
  macro = if assoc[:is_bt]
335
337
  # Try to take care of screwy names if this is a belongs_to going to an STI subclass
336
- # binding.pry if assoc[:fk] == 'issue_severity_id'
337
338
  if (primary_class = assoc.fetch(:primary_class, nil)) &&
338
339
  (sti_inverse_assoc = primary_class.reflect_on_all_associations.find { |a| a.macro == :has_many && a.options[:class_name] == self.name && assoc[:fk] = a.foreign_key })
339
340
  assoc_name = sti_inverse_assoc.options[:inverse_of].to_s || assoc_name
@@ -403,12 +404,13 @@ class Object
403
404
  fks.each do |fk|
404
405
  source = nil
405
406
  this_hmt_fk = if fks.length > 1
406
- singular_assoc_name = ActiveSupport::Inflector.singularize(fk.first[:inverse][:assoc_name])
407
+ singular_assoc_name = fk.first[:inverse][:assoc_name].singularize
407
408
  source = fk.last
408
- through = ActiveSupport::Inflector.pluralize(fk.first[:alternate_name])
409
+ through = fk.first[:alternate_name].pluralize
409
410
  "#{singular_assoc_name}_#{hmt_fk}"
410
411
  else
411
- through = fk.first[:assoc_name]
412
+ source = fk.last unless hmt_fk.singularize == fk.last
413
+ through = fk.first[:assoc_name].pluralize
412
414
  hmt_fk
413
415
  end
414
416
  code << " has_many :#{this_hmt_fk}, through: #{(assoc_name = through.to_sym).to_sym.inspect}#{", source: :#{source}" if source}\n"
@@ -452,7 +454,7 @@ class Object
452
454
 
453
455
  if model.primary_key
454
456
  code << " def show\n"
455
- code << " @#{singular_table_name} = #{model.name}.find(params[:id].split(','))\n"
457
+ code << (find_by_id = " @#{singular_table_name} = #{model.name}.find(params[:id].split(','))\n")
456
458
  code << " end\n"
457
459
  self.define_method :show do
458
460
  ::Brick.set_db_schema(params)
@@ -461,9 +463,36 @@ class Object
461
463
  end
462
464
 
463
465
  # By default, views get marked as read-only
464
- unless (relation = relations[model.table_name]).key?(:isView)
465
- code << " # (Define :new, :create, :edit, :update, and :destroy)\n"
466
- # Get column names for params from relations[model.table_name][:cols].keys
466
+ unless false # model.readonly # (relation = relations[model.table_name]).key?(:isView)
467
+ code << " # (Define :new, :create)\n"
468
+
469
+ if model.primary_key
470
+ is_need_params = true
471
+ # code << " # (Define :edit, and :destroy)\n"
472
+ code << " def update\n"
473
+ code << find_by_id
474
+ params_name = "#{singular_table_name}_params"
475
+ code << " @#{singular_table_name}.update(#{params_name})\n"
476
+ code << " end\n"
477
+ self.define_method :update do
478
+ ::Brick.set_db_schema(params)
479
+ instance_variable_set("@#{singular_table_name}".to_sym, (obj = model.find(params[:id].split(','))))
480
+ obj = obj.first if obj.is_a?(Array)
481
+ obj.send(:update, send(params_name = params_name.to_sym))
482
+ end
483
+ end
484
+
485
+ if is_need_params
486
+ code << "private\n"
487
+ code << " def params\n"
488
+ code << " params.require(:#{singular_table_name}).permit(#{model.columns_hash.keys.map { |c| c.to_sym.inspect }.join(', ')})\n"
489
+ code << " end\n"
490
+ self.define_method(params_name) do
491
+ params.require(singular_table_name.to_sym).permit(model.columns_hash.keys)
492
+ end
493
+ private params_name
494
+ # Get column names for params from relations[model.table_name][:cols].keys
495
+ end
467
496
  end
468
497
  code << "end # #{class_name}\n\n"
469
498
  end # class definition
@@ -627,10 +656,12 @@ module ActiveRecord::ConnectionHandling
627
656
  puts "\nClasses that can be built from views:"
628
657
  views.keys.each { |k| puts ActiveSupport::Inflector.singularize(k).camelize }
629
658
  end
630
- # pp relations; nil
631
659
 
632
- # relations.keys.each { |k| ActiveSupport::Inflector.singularize(k).camelize.constantize }
633
- # Layout table describes permissioned hierarchy throughout
660
+ # Try to load the initializer pretty danged early
661
+ if File.exist?(brick_initialiser = Rails.root.join('config/initializers/brick.rb'))
662
+ load brick_initialiser
663
+ ::Brick.load_additional_references
664
+ end
634
665
  end
635
666
  end
636
667
 
@@ -706,7 +737,7 @@ module Brick
706
737
  # assoc_bt[:inverse_of] = primary_class.reflect_on_all_associations.find { |a| a.foreign_key == bt[1] }
707
738
  end
708
739
 
709
- unless is_class || ::Brick.config.skip_hms&.any? { |skip| fk[0] == skip[0] && fk[1] == skip[1] && primary_table == skip[2] }
740
+ unless is_class || ::Brick.config.exclude_hms&.any? { |exclusion| fk[0] == exclusion[0] && fk[1] == exclusion[1] && primary_table == exclusion[2] }
710
741
  cnstr_name = "hm_#{cnstr_name}"
711
742
  if (assoc_hm = hms.fetch(cnstr_name, nil))
712
743
  assoc_hm[:fk] = assoc_hm[:fk].is_a?(String) ? [assoc_hm[:fk], fk[1]] : assoc_hm[:fk].concat(fk[1])
@@ -32,7 +32,7 @@ module Brick
32
32
  ::Brick.additional_references = app.config.brick.fetch(:additional_references, nil)
33
33
 
34
34
  # Skip creating a has_many association for these
35
- ::Brick.skip_hms = app.config.brick.fetch(:skip_hms, nil)
35
+ ::Brick.exclude_hms = app.config.brick.fetch(:exclude_hms, nil)
36
36
 
37
37
  # Has one relationships
38
38
  ::Brick.has_ones = app.config.brick.fetch(:has_ones, nil)
@@ -76,34 +76,35 @@ module Brick
76
76
  bts, hms = ::Brick.get_bts_and_hms(@_brick_model)
77
77
  # Mark has_manys that go to an associative ("join") table so that they are skipped in the UI,
78
78
  # as well as any possible polymorphic associations
79
- skip_hms = {}
79
+ exclude_hms = {}
80
80
  associatives = hms.each_with_object({}) do |hmt, s|
81
81
  if (through = hmt.last.options[:through])
82
- skip_hms[through] = nil
82
+ exclude_hms[through] = nil
83
83
  s[hmt.first] = hms[through] # End up with a hash of HMT names pointing to join-table associations
84
84
  elsif hmt.last.inverse_of.nil?
85
85
  puts "SKIPPING #{hmt.last.name.inspect}"
86
86
  # %%% If we don't do this then below associative.name will find that associative is nil
87
- skip_hms[hmt.last.name] = nil
87
+ exclude_hms[hmt.last.name] = nil
88
88
  end
89
89
  end
90
90
 
91
91
  schema_options = ::Brick.db_schemas.each_with_object(+'') { |v, s| s << "<option value=\"#{v}\">#{v}</option>" }.html_safe
92
+ table_options = (::Brick.relations.keys - ::Brick.config.exclude_tables)
93
+ .each_with_object(+'') { |v, s| s << "<option value=\"#{v}\">#{v}</option>" }.html_safe
92
94
  hms_columns = +'' # Used for 'index'
93
- # puts skip_hms.inspect
94
95
  hms_headers = hms.each_with_object([]) do |hm, s|
95
- next if skip_hms.key?(hm.last.name)
96
+ next if exclude_hms.key?((hm_assoc = hm.last).name)
96
97
 
97
98
  if args.first == 'index'
98
- hm_fk_name = if hm.last.options[:through]
99
- associative = associatives[hm.last.name]
99
+ hm_fk_name = if hm_assoc.options[:through]
100
+ associative = associatives[hm_assoc.name]
100
101
  "'#{associative.name}.#{associative.foreign_key}'"
101
102
  else
102
- hm.last.foreign_key
103
+ hm_assoc.foreign_key
103
104
  end
104
- hms_columns << if hm.last.macro == :has_many
105
+ hms_columns << if hm_assoc.macro == :has_many
105
106
  "<td>
106
- <%= link_to \"#\{#{obj_name}.#{hm.first}.count\} #{hm.first}\", #{hm.last.klass.name.underscore.pluralize}_path({ #{hm_fk_name}: #{obj_name}.#{pk} }) unless #{obj_name}.#{hm.first}.count.zero? %>
107
+ <%= link_to \"#\{#{obj_name}.#{hm.first}.count\} #{hm.first}\", #{hm_assoc.klass.name.underscore.pluralize}_path({ #{hm_fk_name}: #{obj_name}.#{pk} }) unless #{obj_name}.#{hm.first}.count.zero? %>
107
108
  </td>\n"
108
109
  else # has_one
109
110
  "<td>
@@ -111,7 +112,7 @@ module Brick
111
112
  </td>\n"
112
113
  end
113
114
  end
114
- s << [hm.last, "H#{hm.last.macro == :has_one ? 'O' : 'M'}#{'T' if hm.last.options[:through]} #{hm.first}"]
115
+ s << [hm_assoc, "H#{hm_assoc.macro == :has_one ? 'O' : 'M'}#{'T' if hm_assoc.options[:through]} #{hm.first}"]
115
116
  end
116
117
 
117
118
  css = "<style>
@@ -156,15 +157,43 @@ table tbody tr.active-row {
156
157
  }
157
158
 
158
159
  a.show-arrow {
160
+ font-size: 1.5em;
161
+ text-decoration: none;
162
+ }
163
+ a.big-arrow {
159
164
  font-size: 2.5em;
160
165
  text-decoration: none;
161
166
  }
162
- </style>"
167
+ .wide-input {
168
+ display: block;
169
+ overflow: hidden;
170
+ }
171
+ .wide-input input[type=text] {
172
+ width: 100%;
173
+ }
174
+ .dimmed {
175
+ background-color: #C0C0C0;
176
+ }
177
+ input[type=submit] {
178
+ background-color: #004998;
179
+ color: #FFF;
180
+ }
181
+ .right {
182
+ text-align: right;
183
+ }
184
+ </style>
185
+ <% def is_bcrypt?(val)
186
+ val.is_a?(String) && val.length == 60 && val.start_with?('$2a$')
187
+ end
188
+ def hide_bcrypt(val)
189
+ is_bcrypt?(val) ? '(hidden)' : val
190
+ end %>"
163
191
 
164
192
  script = "<script>
165
193
  var schemaSelect = document.getElementById(\"schema\");
194
+ var brickSchema;
166
195
  if (schemaSelect) {
167
- var brickSchema = changeout(location.href, \"_brick_schema\");
196
+ brickSchema = changeout(location.href, \"_brick_schema\");
168
197
  if (brickSchema) {
169
198
  [... document.getElementsByTagName(\"A\")].forEach(function (a) { a.href = changeout(a.href, \"_brick_schema\", brickSchema); });
170
199
  }
@@ -174,8 +203,39 @@ if (schemaSelect) {
174
203
  location.href = changeout(location.href, \"_brick_schema\", this.value);
175
204
  });
176
205
  }
206
+ [... document.getElementsByTagName(\"FORM\")].forEach(function (form) {
207
+ if (brickSchema)
208
+ form.action = changeout(form.action, \"_brick_schema\", brickSchema);
209
+ form.addEventListener('submit', function (ev) {
210
+ [... ev.target.getElementsByTagName(\"SELECT\")].forEach(function (select) {
211
+ if (select.value === \"^^^brick_NULL^^^\")
212
+ select.value = null;
213
+ });
214
+ return true;
215
+ });
216
+ });
217
+
218
+ var tblSelect = document.getElementById(\"tbl\");
219
+ if (tblSelect) {
220
+ tblSelect.value = changeout(location.href);
221
+ tblSelect.addEventListener(\"change\", function () {
222
+ var lhr = changeout(location.href, null, this.value);
223
+ if (brickSchema)
224
+ lhr = changeout(lhr, \"_brick_schema\", schemaSelect.value);
225
+ location.href = lhr;
226
+ });
227
+ }
228
+
177
229
  function changeout(href, param, value) {
178
230
  var hrefParts = href.split(\"?\");
231
+ if (param === undefined || param === null) {
232
+ hrefParts = hrefParts[0].split(\"://\");
233
+ var pathParts = hrefParts[hrefParts.length - 1].split(\"/\");
234
+ if (value === undefined)
235
+ return pathParts[1];
236
+ else
237
+ return hrefParts[0] + \"://\" + pathParts[0] + \"/\" + value;
238
+ }
179
239
  var params = hrefParts.length > 1 ? hrefParts[1].split(\"&\") : [];
180
240
  params = params.reduce(function (s, v) { var parts = v.split(\"=\"); s[parts[0]] = parts[1]; return s; }, {});
181
241
  if (value === undefined) return params[param];
@@ -189,6 +249,7 @@ function changeout(href, param, value) {
189
249
  "#{css}
190
250
  <p style=\"color: green\"><%= notice %></p>#{"
191
251
  <select id=\"schema\">#{schema_options}</select>" if ::Brick.db_schemas.length > 1}
252
+ <select id=\"tbl\">#{table_options}</select>
192
253
  <h1>#{model_name.pluralize}</h1>
193
254
  <% if @_brick_params&.present? %><h3>where <%= @_brick_params.each_with_object([]) { |v, s| s << \"#\{v.first\} = #\{v.last.inspect\}\" }.join(', ') %></h3><% end %>
194
255
  <table id=\"#{table_name}\">
@@ -210,7 +271,7 @@ function changeout(href, param, value) {
210
271
  <tbody>
211
272
  <% @#{table_name}.each do |#{obj_name}| %>
212
273
  <tr>#{"
213
- <td><%= link_to '⇛', #{obj_name}_path(#{obj_name}.#{pk}), { class: 'show-arrow' } %></td>" if pk }
274
+ <td><%= link_to '⇛', #{obj_name}_path(#{obj_name}.#{pk}), { class: 'big-arrow' } %></td>" if pk }
214
275
  <% #{obj_name}.attributes.each do |k, val| %>
215
276
  <% next if k == '#{pk}' || ::Brick.config.metadata_columns.include?(k) %>
216
277
  <td>
@@ -219,9 +280,9 @@ function changeout(href, param, value) {
219
280
  # send(\"#\{bt_obj_class = bt[1].name.underscore\}_path\".to_sym, bt_obj.send(bt[1].primary_key.to_sym))
220
281
  # Otherwise we get stuff like:
221
282
  # ActionView::Template::Error (undefined method `vehicle_path' for #<ActionView::Base:0x0000000033a888>) %>
222
- <%= bt_obj = bt[1].find_by(bt.last => val); link_to(bt_obj.brick_descrip, send(\"#\{bt_obj_class = bt[1].name.underscore\}_path\".to_sym, bt_obj.send(bt[1].primary_key.to_sym))) if bt_obj %>
283
+ <%= bt_obj = bt[1].find_by(bt[2] => val); link_to(bt_obj.brick_descrip, send(\"#\{bt_obj_class = bt[1].name.underscore\}_path\".to_sym, bt_obj.send(bt[1].primary_key.to_sym))) if bt_obj %>
223
284
  <% else %>
224
- <%= val %>
285
+ <%= hide_bcrypt(val) %>
225
286
  <% end %>
226
287
  </td>
227
288
  <% end %>
@@ -234,47 +295,78 @@ function changeout(href, param, value) {
234
295
 
235
296
  #{"<hr><%= link_to \"New #{obj_name}\", new_#{obj_name}_path %>" unless @_brick_model.is_view?}
236
297
  #{script}"
237
- when 'show'
238
- "#{css}
239
- <p style=\"color: green\"><%= notice %></p>#{"
240
- <select id=\"schema\">#{schema_options}</select>" if ::Brick.db_schemas.length > 1}
241
- <h1>#{model_name}: <%= (obj = @#{obj_name}.first).brick_descrip %></h1>
242
- <%= link_to '(See all #{obj_name.pluralize})', #{table_name}_path %>
298
+ when 'show', 'update'
299
+ "#{css}
300
+ <p style=\"color: green\"><%= notice %></p>#{"
301
+ <select id=\"schema\">#{schema_options}</select>" if ::Brick.db_schemas.length > 1}
302
+ <select id=\"tbl\">#{table_options}</select>
303
+ <h1>#{model_name}: <%= (obj = @#{obj_name}&.first)&.brick_descrip || controller_name %></h1>
304
+ <%= link_to '(See all #{obj_name.pluralize})', #{table_name}_path %>
305
+ <% if obj %>
306
+ <%= # path_options = [obj.#{pk}]
307
+ # path_options << { '_brick_schema': } if
308
+ # url = send(:#{model_name.underscore}_path, obj.#{pk})
309
+ form_for(obj) do |f| %>
243
310
  <table>
244
311
  <% bts = { #{bts.each_with_object([]) { |v, s| s << "#{v.first.inspect} => [#{v.last.first.inspect}, #{v.last[1].name}, #{v.last[1].primary_key.inspect}]"}.join(', ')} }
245
312
  @#{obj_name}.first.attributes.each do |k, val| %>
246
313
  <tr>
247
314
  <% next if k == '#{pk}' || ::Brick.config.metadata_columns.include?(k) %>
248
315
  <th class=\"show-field\">
249
- <% if (bt = bts[k]) %>
250
- BT <%= \"#\{bt.first\}-\" unless bt[1].name.underscore == bt.first.to_s %><%= bt[1].name %>
316
+ <% if (bt = bts[k])
317
+ # Add a final member in this array with descriptive options to be used in <select> drop-downs
318
+ bt_name = bt[1].name
319
+ # %%% Only do this if the user has permissions to edit this bt field
320
+ if bt.length < 4
321
+ bt << (option_detail = [[\"(No #\{bt_name\} chosen)\", '^^^brick_NULL^^^']])
322
+ bt[1].order(:#{pk}).each { |obj| option_detail << [obj.brick_descrip, obj.#{pk}] }
323
+ end %>
324
+ BT <%= \"#\{bt.first\}-\" unless bt_name.underscore == bt.first.to_s %><%= bt_name %>
251
325
  <% else %>
252
326
  <%= k %>
253
327
  <% end %>
254
328
  </th>
255
329
  <td>
256
- <% if (bt = bts[k]) %>
257
- <%= bt_obj = bt[1].find_by(bt.last => val); link_to(bt_obj.brick_descrip, send(\"#\{bt_obj_class = bt[1].name.underscore\}_path\".to_sym, bt_obj.send(bt[1].primary_key.to_sym))) if bt_obj %>
258
- <% else %>
259
- <%= val %>
330
+ <% if (bt = bts[k]) # bt_obj.brick_descrip
331
+ html_options = { prompt: \"Select #\{bt_name\}\" }
332
+ html_options[:class] = 'dimmed' unless val %>
333
+ <%= f.select k.to_sym, bt[3], { value: val || '^^^brick_NULL^^^' }, html_options %>
334
+ <%= bt_obj = bt[1].find_by(bt[2] => val); link_to('⇛', send(\"#\{bt_obj_class = bt_name.underscore\}_path\".to_sym, bt_obj.send(bt[1].primary_key.to_sym)), { class: 'show-arrow' }) if bt_obj %>
335
+ <% else case #{model_name}.column_for_attribute(k).type
336
+ when :string, :text %>
337
+ <% if is_bcrypt?(val) # || .readonly? %>
338
+ <%= hide_bcrypt(val) %>
339
+ <% else %>
340
+ <div class=\"wide-input\"><%= f.text_field k.to_sym %></div>
341
+ <% end %>
342
+ <% when :boolean %>
343
+ <%= f.check_box k.to_sym %>
344
+ <% when :integer, :date, :datetime, :decimal %>
345
+ <%= val %>
346
+ <% end %>
260
347
  <% end %>
261
348
  </td>
262
349
  </tr>
263
- <% end %>
350
+ <% end %>
351
+ <tr><td colspan=\"2\" class=\"right\"><%= f.submit %></td></tr>
264
352
  </table>
353
+ <% end %>
265
354
 
266
355
  #{hms_headers.map do |hm|
267
356
  next unless (pk = hm.first.klass.primary_key)
268
357
  "<table id=\"#{hm_name = hm.first.name.to_s}\">
269
358
  <tr><th>#{hm.last}</th></tr>
270
- <% if (collection = @#{obj_name}.first.#{hm_name}).empty? %>
359
+ <% collection = @#{obj_name}.first.#{hm_name}
360
+ collection = collection.is_a?(ActiveRecord::Associations::CollectionProxy) ? collection.order(#{pk.inspect}) : [collection]
361
+ if collection.empty? %>
271
362
  <tr><td>(none)</td></tr>
272
363
  <% else %>
273
- <% collection.order(#{pk.inspect}).uniq.each do |#{hm_singular_name = hm_name.singularize}| %>
274
- <tr><td><%= link_to(#{hm_singular_name}.brick_descrip, #{hm_singular_name}_path(#{hm_singular_name}.#{pk})) %></td></tr>
364
+ <% collection.uniq.each do |#{hm_singular_name = hm_name.singularize.underscore}| %>
365
+ <tr><td><%= link_to(#{hm_singular_name}.brick_descrip, #{hm.first.klass.name.underscore}_path(#{hm_singular_name}.#{pk})) %></td></tr>
275
366
  <% end %>
276
367
  <% end %>
277
368
  </table>" end.join}
369
+ <% end %>
278
370
  #{script}"
279
371
 
280
372
  end
@@ -296,12 +388,9 @@ function changeout(href, param, value) {
296
388
  end
297
389
  end
298
390
 
299
- # Additional references (virtual foreign keys)
300
- if (ars = ::Brick.config.additional_references)
301
- ars.each do |fk|
302
- ::Brick._add_bt_and_hm(fk[0..2])
303
- end
304
- end
391
+ # Just in case it hadn't been done previously when we tried to load the brick initialiser,
392
+ # go make sure we've loaded additional references (virtual foreign keys).
393
+ ::Brick.load_additional_references
305
394
 
306
395
  # Find associative tables that can be set up for has_many :through
307
396
  ::Brick.relations.each do |_key, tbl|
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 15
8
+ TINY = 18
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
@@ -208,12 +208,12 @@ module Brick
208
208
  # Skip creating a has_many association for these
209
209
  # (Uses the same exact three-part format as would define an additional_reference)
210
210
  # @api public
211
- def skip_hms=(skips)
211
+ def exclude_hms=(skips)
212
212
  if skips
213
213
  skips = skips.call if skips.is_a?(Proc)
214
214
  skips = skips.to_a unless skips.is_a?(Array)
215
215
  skips = [skips] unless skips.empty? || skips.first.is_a?(Array)
216
- Brick.config.skip_hms = skips
216
+ Brick.config.exclude_hms = skips
217
217
  end
218
218
  end
219
219
 
@@ -244,6 +244,18 @@ module Brick
244
244
  Brick.config.sti_namespace_prefixes = snp
245
245
  end
246
246
 
247
+ # Load additional references (virtual foreign keys)
248
+ # This is attempted early if a brick initialiser file is found, and then again as a failsafe at the end of our engine's initialisation
249
+ # %%% Maybe look for differences the second time 'round and just add new stuff instead of entirely deferring
250
+ def load_additional_references
251
+ return if @_additional_references_loaded
252
+
253
+ if (ars = ::Brick.config.additional_references)
254
+ ars.each { |fk| ::Brick._add_bt_and_hm(fk[0..2]) }
255
+ @_additional_references_loaded = true
256
+ end
257
+ end
258
+
247
259
 
248
260
  # Returns Brick's `::Gem::Version`, convenient for comparisons. This is
249
261
  # recommended over `::Brick::VERSION::STRING`.
@@ -94,7 +94,7 @@ module Brick
94
94
  # # Any tables or views you'd like to skip when auto-creating models
95
95
  # Brick.exclude_tables = ['custom_metadata', 'version_info']
96
96
 
97
- # # Class for auto-generated models to inherit from
97
+ # # Class that auto-generated models should inherit from
98
98
  # Brick.models_inherit_from = ApplicationRecord
99
99
 
100
100
  # # When table names have specific prefixes automatically place them in their own module with a table_name_prefix.
@@ -114,7 +114,7 @@ module Brick
114
114
  # # Skip creating a has_many association for these
115
115
  # # (Uses the same exact three-part format as would define an additional_reference)
116
116
  # # Say for instance that we didn't care to display the favourite colours that users have:
117
- # Brick.skip_hms = [['users', 'favourite_colour_id', 'colours']]
117
+ # Brick.exclude_hms = [['users', 'favourite_colour_id', 'colours']]
118
118
 
119
119
  # # By default primary tables involved in a foreign key relationship will indicate a \"has_many\" relationship pointing
120
120
  # # back to the foreign table. In order to represent a \"has_one\" association instead, an override can be provided
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.15
4
+ version: 1.0.18
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-03-26 00:00:00.000000000 Z
11
+ date: 2022-03-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord