brick 1.0.6 → 1.0.7

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