brick 1.0.6 → 1.0.7

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: 634669de2074746d62642b8c9108070b78e92b14f7924ac969404b240de2267d
4
- data.tar.gz: 7614fa456fcaeb6bc68227230088fe3adeed31278241a000f3fb19792b763d26
3
+ metadata.gz: b65cbc8bbf472c887136395afb13f9dcf6e460f0c279dda0372939da8863178f
4
+ data.tar.gz: d63ae1e8795bb788e67c05d98f245c086aa773fbfc5585f716e3371652976878
5
5
  SHA512:
6
- metadata.gz: 3b89ed9c8ffe3c63e098a3f7a8e5a9987db0c00bfe2c917b7c2acefebc30653a4a88d091852b8f8e6128daa310e7c7742d10611acfb0ffe7d06cc6c01da7068e
7
- data.tar.gz: 98d58b4461b9e85537da640e3940316553d142a341547086ce614f75d9366145c8818beb6e972ac93a77e7209b034eb64a64eb9a078f6afb91fbbd008e3ade69
6
+ metadata.gz: e27c5bc4385ae585e1904fc142aa6e0a61b1c780c6e9d68efc4b6ce1b60f985db71922466ad5dff365e3c239a0220411af90ec2f148705bdc5a993e552494c50
7
+ data.tar.gz: 2937ec1ecb167d7db208c0f46aaab60670b95403ba22b464597c254c782e9075e0245514fd950fbb4267c3e3f206b7b49969cd5052dd3d6d89db41a7883cd7d9
data/lib/brick/config.rb CHANGED
@@ -65,7 +65,7 @@ module Brick
65
65
  @mutex.synchronize { @additional_references = references }
66
66
  end
67
67
 
68
- # Associations to treat has a has_one
68
+ # Associations to treat as a has_one
69
69
  def has_ones
70
70
  @mutex.synchronize { @has_ones }
71
71
  end
@@ -194,8 +194,10 @@ class Object
194
194
  end
195
195
 
196
196
  fks = relation[:fks] || {}
197
- fks.each do |_constraint_name, assoc|
198
- assoc_name = assoc[:assoc_name]
197
+ # Do the bulk of the has_many / belongs_to processing, and store details about HMT so they can be done at the very last
198
+ hmts = fks.each_with_object(Hash.new { |h, k| h[k] = [] }) do |fk, hmts|
199
+ # The key in each hash entry (fk.first) is the constraint name
200
+ assoc_name = (assoc = fk.last)[:assoc_name]
199
201
  inverse_assoc_name = assoc[:inverse][:assoc_name]
200
202
  options = {}
201
203
  singular_table_name = ActiveSupport::Inflector.singularize(assoc[:inverse_table])
@@ -203,7 +205,7 @@ class Object
203
205
  need_class_name = singular_table_name.underscore != assoc_name
204
206
  need_fk = "#{assoc_name}_id" != assoc[:fk]
205
207
  inverse_assoc_name, _x = _brick_get_hm_assoc_name(relations[assoc[:inverse_table]], assoc[:inverse])
206
- if (has_ones = ::Brick.config.has_ones.fetch(assoc[:inverse][:alternate_name].camelize, nil))&.key?(singular_inv_assoc_name = ActiveSupport::Inflector.singularize(inverse_assoc_name))
208
+ if (has_ones = ::Brick.config.has_ones&.fetch(assoc[:inverse][:alternate_name].camelize, nil))&.key?(singular_inv_assoc_name = ActiveSupport::Inflector.singularize(inverse_assoc_name))
207
209
  inverse_assoc_name = if has_ones[singular_inv_assoc_name]
208
210
  need_inverse_of = true
209
211
  has_ones[singular_inv_assoc_name]
@@ -233,23 +235,51 @@ class Object
233
235
  # Figure out if we need to specially call out the class_name and/or foreign key
234
236
  # (and if either of those then definitely also a specific inverse_of)
235
237
  options[:class_name] = singular_table_name.camelize if need_class_name
236
- options[:foreign_key] = assoc[:fk].to_sym if need_fk # Funky foreign key?
238
+ # Work around a bug in CPK where self-referencing belongs_to associations double up their foreign keys
239
+ if need_fk # Funky foreign key?
240
+ options[:foreign_key] = if assoc[:fk].is_a?(Array)
241
+ assoc_fk = assoc[:fk].uniq
242
+ assoc_fk.length < 2 ? assoc_fk.first : assoc_fk
243
+ else
244
+ assoc[:fk].to_sym
245
+ end
246
+ end
237
247
  options[:inverse_of] = inverse_assoc_name.to_sym if need_class_name || need_fk || need_inverse_of
238
- assoc_name = assoc_name.to_sym
239
- code << " #{macro} #{assoc_name.inspect}#{options.map { |k, v| ", #{k}: #{v.inspect}" }.join}\n"
240
- self.send(macro, assoc_name, **options)
241
248
 
242
- # Look for any valid "has_many :through"
249
+ # Prepare a list of entries for "has_many :through"
243
250
  if macro == :has_many
244
251
  relations[assoc[:inverse_table]][:hmt_fks].each do |k, hmt_fk|
245
252
  next if k == assoc[:fk]
246
253
 
247
- hmt_fk = ActiveSupport::Inflector.pluralize(hmt_fk)
248
- code << " has_many :#{hmt_fk}, through: #{assoc_name.inspect}\n"
249
- self.send(:has_many, hmt_fk.to_sym, **{ through: assoc_name })
254
+ hmts[ActiveSupport::Inflector.pluralize(hmt_fk.last)] << [assoc, hmt_fk.first]
250
255
  end
251
256
  end
257
+
258
+ # And finally create a has_one, has_many, or belongs_to for this association
259
+ assoc_name = assoc_name.to_sym
260
+ code << " #{macro} #{assoc_name.inspect}#{options.map { |k, v| ", #{k}: #{v.inspect}" }.join}\n"
261
+ self.send(macro, assoc_name, **options)
262
+ hmts
252
263
  end
264
+ hmts.each do |hmt_fk, fks|
265
+ fks.each do |fk|
266
+ source = nil
267
+ this_hmt_fk = if fks.length > 1
268
+ singular_assoc_name = ActiveSupport::Inflector.singularize(fk.first[:inverse][:assoc_name])
269
+ source = fk.last
270
+ through = ActiveSupport::Inflector.pluralize(fk.first[:alternate_name])
271
+ "#{singular_assoc_name}_#{hmt_fk}"
272
+ else
273
+ through = fk.first[:assoc_name]
274
+ hmt_fk
275
+ end
276
+ code << " has_many :#{this_hmt_fk}, through: #{(assoc_name = through.to_sym).to_sym.inspect}#{", source: :#{source}" if source}\n"
277
+ options = { through: assoc_name }
278
+ options[:source] = source.to_sym if source
279
+ self.send(:has_many, this_hmt_fk.to_sym, **options)
280
+ end
281
+ end
282
+
253
283
  code << "end # model #{model_name}\n\n"
254
284
  end # class definition
255
285
  [built_model, code]
@@ -293,7 +323,7 @@ class Object
293
323
  end
294
324
 
295
325
  def _brick_get_hm_assoc_name(relation, hm_assoc)
296
- if relation[:hm_counts][hm_assoc[:assoc_name]] > 1
326
+ if relation[:hm_counts][hm_assoc[:assoc_name]]&.> 1
297
327
  [ActiveSupport::Inflector.pluralize(hm_assoc[:alternate_name]), true]
298
328
  else
299
329
  [ActiveSupport::Inflector.pluralize(hm_assoc[:inverse_table]), nil]
@@ -69,14 +69,14 @@ module Brick
69
69
  hms_headers = hms.each_with_object(+'') { |hm, s| s << "<th>H#{hm.last.macro == :has_one ? 'O' : 'M'}#{'T' if hm.last.options[:through]} #{hm.first}</th>\n" }
70
70
  hms_columns = hms.each_with_object(+'') do |hm, s|
71
71
  hm_fk_name = if hm.last.options[:through]
72
- associative = associatives[hm.last.name]
73
- "'#{associative.name}.#{associative.foreign_key}'"
74
- else
75
- hm.last.foreign_key
76
- end
72
+ associative = associatives[hm.last.name]
73
+ "'#{associative.name}.#{associative.foreign_key}'"
74
+ else
75
+ hm.last.foreign_key
76
+ end
77
77
  s << if hm.last.macro == :has_many
78
78
  "<td>
79
- <%= 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? %>
79
+ #\{#{obj_name}.#{hm.first}.count\} #{hm.first}<%= link_to \"\", #{hm.last&.klass&.name&.underscore&.pluralize}_path({ #{hm_fk_name}: #{obj_name}.#{pk} }) unless #{obj_name}.#{hm.first}.count.zero? %>
80
80
  </td>\n"
81
81
  else # has_one
82
82
  "<td>
@@ -194,7 +194,7 @@ module Brick
194
194
  # Find associative tables that can be set up for has_many :through
195
195
  ::Brick.relations.each do |_key, tbl|
196
196
  tbl_cols = tbl[:cols].keys
197
- fks = tbl[:fks].each_with_object({}) { |fk, s| s[fk.last[:fk]] = fk.last[:inverse_table] if fk.last[:is_bt]; s }
197
+ fks = tbl[:fks].each_with_object({}) { |fk, s| s[fk.last[:fk]] = [fk.last[:assoc_name], fk.last[:inverse_table]] if fk.last[:is_bt]; s }
198
198
  # Aside from the primary key and the metadata columns created_at, updated_at, and deleted_at, if this table only has
199
199
  # foreign keys then it can act as an associative table and thus be used with has_many :through.
200
200
  if fks.length > 1 && (tbl_cols - fks.keys - (::Brick.config.metadata_columns || []) - (tbl[:pkey].values.first || [])).length.zero?
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 6
8
+ TINY = 7
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
@@ -196,7 +196,7 @@ module Brick
196
196
  end
197
197
  end
198
198
 
199
- # Associations to treat has a has_one
199
+ # Associations to treat as a has_one
200
200
  # @api public
201
201
  def has_ones=(hos)
202
202
  if hos
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.6
4
+ version: 1.0.7
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-19 00:00:00.000000000 Z
11
+ date: 2022-03-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord