brick 1.0.16 → 1.0.17

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