brick 1.0.16 → 1.0.17

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: 30eeeb5fb81003f790234885589b29f227b7f4f2d498accb07da5cd8ea425084
4
- data.tar.gz: 1841386c2750c2aef744a7ee555b649e2fc0298367684d261faf64297b8430c0
3
+ metadata.gz: 7f1a45a5262526e69cf49f16773049eb348e3971bddf09ecf05927002a265019
4
+ data.tar.gz: e9566a423a19ab55d44522b44e8b4abfcc39e92335b6093fe782c6344644bbbe
5
5
  SHA512:
6
- metadata.gz: 64c5747800aaa5469f2ff2b0be3ae5056fa383c6d246e7aff15b19eb4a588e15e72f5d1ecb384879b3b7f175cab28961fb4984e11d5994085b215f442d722389
7
- data.tar.gz: ec3418092244d97b3006086aaf0484ee1ab4342cf2c16716239f7127c8e23056dc25e1714e51523bdb8f87fb6b88c322dabefb096fe7bf0b1f695568b636d4b8
6
+ metadata.gz: cb89dff96dccc7051bc854fe523b03f818255d81e4f2e2a65eb9808115e719b8bad98e38114f15ee79b32b1f035c95c364a74392948cd2e99f4030e6988e0217
7
+ data.tar.gz: cd5507fde2f1f23481696ab051d14f89e5e7e7d3fc2be97af947ff287313b7ada8ca7b4e3f9e0e54dc2ab7f14e7f39a3c18f78cf7fc995c58b3d60cf68487973
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
@@ -629,7 +629,11 @@ module ActiveRecord::ConnectionHandling
629
629
  puts "\nClasses that can be built from views:"
630
630
  views.keys.each { |k| puts ActiveSupport::Inflector.singularize(k).camelize }
631
631
  end
632
- # pp relations; nil
632
+ # Try to load the initializer pretty danged early
633
+ if File.exist?(brick_initialiser = Rails.root.join('config/initializers/brick.rb'))
634
+ load brick_initialiser
635
+ ::Brick.load_additional_references
636
+ end
633
637
 
634
638
  # relations.keys.each { |k| ActiveSupport::Inflector.singularize(k).camelize.constantize }
635
639
  # Layout table describes permissioned hierarchy throughout
@@ -708,7 +712,7 @@ module Brick
708
712
  # assoc_bt[:inverse_of] = primary_class.reflect_on_all_associations.find { |a| a.foreign_key == bt[1] }
709
713
  end
710
714
 
711
- unless is_class || ::Brick.config.skip_hms&.any? { |skip| fk[0] == skip[0] && fk[1] == skip[1] && primary_table == skip[2] }
715
+ unless is_class || ::Brick.config.exclude_hms&.any? { |exclusion| fk[0] == exclusion[0] && fk[1] == exclusion[1] && primary_table == exclusion[2] }
712
716
  cnstr_name = "hm_#{cnstr_name}"
713
717
  if (assoc_hm = hms.fetch(cnstr_name, nil))
714
718
  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,33 +76,34 @@ 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.each_with_object(+'') { |v, s| s << "<option value=\"#{v}\">#{v}</option>" }.html_safe
92
93
  hms_columns = +'' # Used for 'index'
93
94
  hms_headers = hms.each_with_object([]) do |hm, s|
94
- next if skip_hms.key?(hm.last.name)
95
+ next if exclude_hms.key?((hm_assoc = hm.last).name)
95
96
 
96
97
  if args.first == 'index'
97
- hm_fk_name = if hm.last.options[:through]
98
- associative = associatives[hm.last.name]
98
+ hm_fk_name = if hm_assoc.options[:through]
99
+ associative = associatives[hm_assoc.name]
99
100
  "'#{associative.name}.#{associative.foreign_key}'"
100
101
  else
101
- hm.last.foreign_key
102
+ hm_assoc.foreign_key
102
103
  end
103
- hms_columns << if hm.last.macro == :has_many
104
+ hms_columns << if hm_assoc.macro == :has_many
104
105
  "<td>
105
- <%= 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? %>
106
+ <%= 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? %>
106
107
  </td>\n"
107
108
  else # has_one
108
109
  "<td>
@@ -110,7 +111,7 @@ module Brick
110
111
  </td>\n"
111
112
  end
112
113
  end
113
- s << [hm.last, "H#{hm.last.macro == :has_one ? 'O' : 'M'}#{'T' if hm.last.options[:through]} #{hm.first}"]
114
+ s << [hm_assoc, "H#{hm_assoc.macro == :has_one ? 'O' : 'M'}#{'T' if hm_assoc.options[:through]} #{hm.first}"]
114
115
  end
115
116
 
116
117
  css = "<style>
@@ -155,10 +156,20 @@ table tbody tr.active-row {
155
156
  }
156
157
 
157
158
  a.show-arrow {
159
+ font-size: 1.5em;
160
+ text-decoration: none;
161
+ }
162
+ a.big-arrow {
158
163
  font-size: 2.5em;
159
164
  text-decoration: none;
160
165
  }
161
- </style>"
166
+ </style>
167
+ <% def is_bcrypt?(val)
168
+ val.is_a?(String) && val.length == 60 && val.start_with?('$2a$')
169
+ end
170
+ def hide_bcrypt(val)
171
+ is_bcrypt?(val) ? '(hidden)' : val
172
+ end %>"
162
173
 
163
174
  script = "<script>
164
175
  var schemaSelect = document.getElementById(\"schema\");
@@ -173,8 +184,28 @@ if (schemaSelect) {
173
184
  location.href = changeout(location.href, \"_brick_schema\", this.value);
174
185
  });
175
186
  }
187
+
188
+ var tblSelect = document.getElementById(\"tbl\");
189
+ if (tblSelect) {
190
+ tblSelect.value = changeout(location.href);
191
+ tblSelect.addEventListener(\"change\", function () {
192
+ var lhr = changeout(location.href, null, this.value);
193
+ if (brickSchema)
194
+ lhr = changeout(lhr, \"_brick_schema\", schemaSelect.value);
195
+ location.href = lhr;
196
+ });
197
+ }
198
+
176
199
  function changeout(href, param, value) {
177
200
  var hrefParts = href.split(\"?\");
201
+ if (param === undefined || param === null) {
202
+ hrefParts = hrefParts[0].split(\"://\");
203
+ var pathParts = hrefParts[hrefParts.length - 1].split(\"/\");
204
+ if (value === undefined)
205
+ return pathParts[1];
206
+ else
207
+ return hrefParts[0] + \"://\" + pathParts[0] + \"/\" + value;
208
+ }
178
209
  var params = hrefParts.length > 1 ? hrefParts[1].split(\"&\") : [];
179
210
  params = params.reduce(function (s, v) { var parts = v.split(\"=\"); s[parts[0]] = parts[1]; return s; }, {});
180
211
  if (value === undefined) return params[param];
@@ -188,6 +219,7 @@ function changeout(href, param, value) {
188
219
  "#{css}
189
220
  <p style=\"color: green\"><%= notice %></p>#{"
190
221
  <select id=\"schema\">#{schema_options}</select>" if ::Brick.db_schemas.length > 1}
222
+ <select id=\"tbl\">#{table_options}</select>
191
223
  <h1>#{model_name.pluralize}</h1>
192
224
  <% if @_brick_params&.present? %><h3>where <%= @_brick_params.each_with_object([]) { |v, s| s << \"#\{v.first\} = #\{v.last.inspect\}\" }.join(', ') %></h3><% end %>
193
225
  <table id=\"#{table_name}\">
@@ -209,7 +241,7 @@ function changeout(href, param, value) {
209
241
  <tbody>
210
242
  <% @#{table_name}.each do |#{obj_name}| %>
211
243
  <tr>#{"
212
- <td><%= link_to '⇛', #{obj_name}_path(#{obj_name}.#{pk}), { class: 'show-arrow' } %></td>" if pk }
244
+ <td><%= link_to '⇛', #{obj_name}_path(#{obj_name}.#{pk}), { class: 'big-arrow' } %></td>" if pk }
213
245
  <% #{obj_name}.attributes.each do |k, val| %>
214
246
  <% next if k == '#{pk}' || ::Brick.config.metadata_columns.include?(k) %>
215
247
  <td>
@@ -218,9 +250,9 @@ function changeout(href, param, value) {
218
250
  # send(\"#\{bt_obj_class = bt[1].name.underscore\}_path\".to_sym, bt_obj.send(bt[1].primary_key.to_sym))
219
251
  # Otherwise we get stuff like:
220
252
  # ActionView::Template::Error (undefined method `vehicle_path' for #<ActionView::Base:0x0000000033a888>) %>
221
- <%= 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 %>
253
+ <%= 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 %>
222
254
  <% else %>
223
- <%= val %>
255
+ <%= hide_bcrypt(val) %>
224
256
  <% end %>
225
257
  </td>
226
258
  <% end %>
@@ -237,40 +269,51 @@ function changeout(href, param, value) {
237
269
  "#{css}
238
270
  <p style=\"color: green\"><%= notice %></p>#{"
239
271
  <select id=\"schema\">#{schema_options}</select>" if ::Brick.db_schemas.length > 1}
272
+ <select id=\"tbl\">#{table_options}</select>
240
273
  <h1>#{model_name}: <%= (obj = @#{obj_name}.first).brick_descrip %></h1>
241
274
  <%= link_to '(See all #{obj_name.pluralize})', #{table_name}_path %>
275
+ <%= form_for obj do |f| %>
242
276
  <table>
243
277
  <% 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(', ')} }
244
278
  @#{obj_name}.first.attributes.each do |k, val| %>
245
279
  <tr>
246
280
  <% next if k == '#{pk}' || ::Brick.config.metadata_columns.include?(k) %>
247
281
  <th class=\"show-field\">
248
- <% if (bt = bts[k]) %>
282
+ <% if (bt = bts[k])
283
+ # Add a final member in this array with descriptive options to be used in <select> drop-downs
284
+ # %%% Only do this if the user has permissions to edit this bt field
285
+ bt << bt[1].order(:#{pk}).map { |obj| [obj.brick_descrip, obj.#{pk}] } if bt.length < 4 %>
249
286
  BT <%= \"#\{bt.first\}-\" unless bt[1].name.underscore == bt.first.to_s %><%= bt[1].name %>
250
287
  <% else %>
251
288
  <%= k %>
252
289
  <% end %>
253
290
  </th>
254
291
  <td>
255
- <% if (bt = bts[k]) %>
256
- <%= 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 %>
292
+ <% if (bt = bts[k]) # bt_obj.brick_descrip %>
293
+ <%= f.select k.to_sym, bt[3], {}, prompt: 'Select #{model_name}' %>
294
+ <%= bt_obj = bt[1].find_by(bt[2] => val); link_to('⇛', send(\"#\{bt_obj_class = bt[1].name.underscore\}_path\".to_sym, bt_obj.send(bt[1].primary_key.to_sym)), { class: 'show-arrow' }) if bt_obj %>
295
+ <% elsif is_bcrypt?(val) %>
296
+ <%= hide_bcrypt(val) %>
257
297
  <% else %>
258
- <%= val %>
298
+ <%= f.text_field k.to_sym %>
259
299
  <% end %>
260
300
  </td>
261
301
  </tr>
262
302
  <% end %>
263
303
  </table>
304
+ <% end %>
264
305
 
265
306
  #{hms_headers.map do |hm|
266
307
  next unless (pk = hm.first.klass.primary_key)
267
308
  "<table id=\"#{hm_name = hm.first.name.to_s}\">
268
309
  <tr><th>#{hm.last}</th></tr>
269
- <% if (collection = @#{obj_name}.first.#{hm_name}).empty? %>
310
+ <% collection = @#{obj_name}.first.#{hm_name}
311
+ collection = collection.is_a?(ActiveRecord::Associations::CollectionProxy) ? collection.order(#{pk.inspect}) : [collection]
312
+ if collection.empty? %>
270
313
  <tr><td>(none)</td></tr>
271
314
  <% else %>
272
- <% collection.order(#{pk.inspect}).uniq.each do |#{hm_singular_name = hm_name.singularize.underscore}| %>
273
- <tr><td><%= link_to(#{hm_singular_name}.brick_descrip, #{hm_singular_name}_path(#{hm_singular_name}.#{pk})) %></td></tr>
315
+ <% collection.uniq.each do |#{hm_singular_name = hm_name.singularize.underscore}| %>
316
+ <tr><td><%= link_to(#{hm_singular_name}.brick_descrip, #{hm.first.klass.name.underscore}_path(#{hm_singular_name}.#{pk})) %></td></tr>
274
317
  <% end %>
275
318
  <% end %>
276
319
  </table>" end.join}
@@ -295,12 +338,9 @@ function changeout(href, param, value) {
295
338
  end
296
339
  end
297
340
 
298
- # Additional references (virtual foreign keys)
299
- if (ars = ::Brick.config.additional_references)
300
- ars.each do |fk|
301
- ::Brick._add_bt_and_hm(fk[0..2])
302
- end
303
- end
341
+ # Just in case it hadn't been done previously when we tried to load the brick initialiser,
342
+ # go make sure we've loaded additional references (virtual foreign keys).
343
+ ::Brick.load_additional_references
304
344
 
305
345
  # Find associative tables that can be set up for has_many :through
306
346
  ::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 = 16
8
+ TINY = 17
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`.
@@ -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.16
4
+ version: 1.0.17
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