brick 1.0.44 → 1.0.47

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: 0d43e8d88203f6496d0e86f57a3de2638f254a74da070d6a0f0ae107bf596a87
4
- data.tar.gz: d5ce2e3814f36fa758762e3c4774032c70ce18a101cdd1e30622dd86c757ab1a
3
+ metadata.gz: 4180c0164d7f086112339696df9d8fef2aeebcd32d9b81faf22d76ddc11815bc
4
+ data.tar.gz: 823673bcbecc342f5df15e196ee65ad6f6ac0b75415514079c055af06d0ac7f6
5
5
  SHA512:
6
- metadata.gz: 36b8bf590c1d980655b8c465e52659fdbcdf3e13b7050e46dcb41c2b3fba44ebc9ff14db823afddbb49b3e6b736a33fa1ef794ed6062aba4e35ade3cd95c5bbd
7
- data.tar.gz: d1bd0954d0400068aaf8f7c83cc599f283fbe9c75e347fd4193d1fa3973c0d2bd3198f3265990cd3d24f406cd3b55f3174518bd6a991801c75a06d1c749cc157
6
+ metadata.gz: 1d17b1abd64051066b71839095be1e672b897ad707a2d10f4ca4429131c894ee178711c873cef59957111704437b86b6322b8909ab5cc41cc955547146377dd8
7
+ data.tar.gz: e210becff69096e73b9b7fa09bb4e1be6c36cd2982305b2c803c9c00e9d2b5b085857ea6edacc62498557cde928e2afbbb42ebbd137180385ec3a8a0c5efdf85
@@ -274,7 +274,6 @@ module ActiveRecord
274
274
  table = table.left
275
275
  end
276
276
  (_brick_chains[table._arel_table_type] ||= []) << (alias_name || table.table_alias || table.name)
277
- # puts "YES! #{self.object_id}"
278
277
  end
279
278
  # rubocop:enable Style/IdenticalConditionalBranches
280
279
  when Arel::Table # Table
@@ -286,9 +285,9 @@ module ActiveRecord
286
285
  # Spin up an empty set of Brick alias name chains at the start
287
286
  @_brick_chains = {}
288
287
  # The left side is the "FROM" table
289
- # names += _recurse_arel(piece.left)
290
288
  names << (this_name = [piece.left._arel_table_type, (piece.left.table_alias || piece.left.name)])
291
- (_brick_chains[this_name.first] ||= []) << this_name.last
289
+ # # Do not currently need the root "FROM" table in our list of chains
290
+ # (_brick_chains[this_name.first] ||= []) << this_name.last
292
291
  # The right side is an array of all JOINs
293
292
  piece.right.each { |join| names << _recurse_arel(join) }
294
293
  end
@@ -354,7 +353,6 @@ module ActiveRecord
354
353
  next if bt[2] # Polymorphic?
355
354
 
356
355
  # join_array will receive this relation name when calling #brick_parse_dsl
357
- # binding.pry if bt.length > 2
358
356
  bt_descrip[bt.first] = if bt[1].is_a?(Array)
359
357
  bt[1].each_with_object({}) { |bt_class, s| s[bt_class] = bt_class.brick_parse_dsl(join_array, bt.first, translations, true) }
360
358
  else
@@ -598,7 +596,7 @@ Module.class_exec do
598
596
  # See if a file is there in the same way that ActiveSupport::Dependencies#load_missing_constant
599
597
  # checks for it in ~/.rvm/gems/ruby-2.7.5/gems/activesupport-5.2.6.2/lib/active_support/dependencies.rb
600
598
 
601
- if (base_model = ::Brick.config.sti_namespace_prefixes&.fetch("::#{name}::", nil)&.constantize) || # Are we part of an auto-STI namespace? ...
599
+ if (base_model = ::Brick.config.sti_namespace_prefixes&.fetch("::#{self.name}::", nil)&.constantize) || # Are we part of an auto-STI namespace? ...
602
600
  self != Object # ... or otherwise already in some namespace?
603
601
  schema_name = [(singular_schema_name = name.underscore),
604
602
  (schema_name = singular_schema_name.pluralize),
@@ -775,33 +773,47 @@ class Object
775
773
  end # class definition
776
774
  # Having this separate -- will this now work out better?
777
775
  built_model.class_exec do
778
- hmts&.each do |hmt_fk, fks|
776
+ hmts&.each do |hmt_fk, hms|
779
777
  hmt_fk = hmt_fk.tr('.', '_')
780
- fks.each do |fk|
781
- # %%% Will not work with custom has_many name
782
- through = ::Brick.config.schema_behavior[:multitenant] ? fk.first[:assoc_name] : fk.first[:inverse_table].tr('.', '_').pluralize
783
- hmt_name = if fks.length > 1
784
- if fks[0].first[:inverse][:assoc_name] == fks[1].first[:inverse][:assoc_name] # Same BT names pointing back to us? (Most common scenario)
785
- "#{hmt_fk}_through_#{fk.first[:assoc_name]}"
778
+ hms.each do |hm|
779
+ # %%% Need to confirm that HMTs work when they are built from has_manys with custom names
780
+ through = ::Brick.config.schema_behavior[:multitenant] ? hm.first[:assoc_name] : hm.first[:inverse_table].tr('.', '_').pluralize
781
+ options = {}
782
+ hmt_name = if hms.length > 1
783
+ if hms[0].first[:inverse][:assoc_name] == hms[1].first[:inverse][:assoc_name] # Same BT names pointing back to us? (Most common scenario)
784
+ "#{hmt_fk}_through_#{hm.first[:assoc_name]}"
786
785
  else # Use BT names to provide uniqueness
787
- through = fk.first[:alternate_name].pluralize
788
- singular_assoc_name = fk.first[:inverse][:assoc_name].singularize
786
+ if self.name.underscore.singularize == hm.first[:alternate_name]
787
+ # Has previously been:
788
+ # # If it folds back on itself then look at the other side
789
+ # # (At this point just infer the source be the inverse of the first has_many that
790
+ # # we find that is not ourselves. If there are more than two then uh oh, can't
791
+ # # yet handle that rare circumstance!)
792
+ # other = hms.find { |hm1| hm1 != hm } # .first[:fk]
793
+ # options[:source] = other.first[:inverse][:assoc_name].to_sym
794
+ # And also has been:
795
+ # hm.first[:inverse][:assoc_name].to_sym
796
+ options[:source] = hm.last.to_sym
797
+ else
798
+ through = hm.first[:alternate_name].pluralize
799
+ end
800
+ singular_assoc_name = hm.first[:inverse][:assoc_name].singularize
789
801
  "#{singular_assoc_name}_#{hmt_fk}"
790
802
  end
791
803
  else
792
804
  hmt_fk
793
805
  end
794
- options = { through: through.to_sym }
806
+ options[:through] = through.to_sym
795
807
  if relation[:fks].any? { |k, v| v[:assoc_name] == hmt_name }
796
- hmt_name = "#{hmt_name.singularize}_#{fk.first[:assoc_name]}"
808
+ hmt_name = "#{hmt_name.singularize}_#{hm.first[:assoc_name]}"
797
809
  # Was:
798
- # options[:class_name] = fk.first[:inverse_table].singularize.camelize
799
- # options[:foreign_key] = fk.first[:fk].to_sym
800
- far_assoc = relations[fk.first[:inverse_table]][:fks].find { |_k, v| v[:assoc_name] == fk.last }
810
+ # options[:class_name] = hm.first[:inverse_table].singularize.camelize
811
+ # options[:foreign_key] = hm.first[:fk].to_sym
812
+ far_assoc = relations[hm.first[:inverse_table]][:fks].find { |_k, v| v[:assoc_name] == hm.last }
801
813
  options[:class_name] = far_assoc.last[:inverse_table].singularize.camelize
802
814
  options[:foreign_key] = far_assoc.last[:fk].to_sym
803
815
  end
804
- options[:source] = fk.last.to_sym unless hmt_name.singularize == fk.last
816
+ options[:source] ||= hm.last.to_sym unless hmt_name.singularize == hm.last
805
817
  code << " has_many :#{hmt_name}#{options.map { |opt| ", #{opt.first}: #{opt.last.inspect}" }.join}\n"
806
818
  self.send(:has_many, hmt_name.to_sym, **options)
807
819
  end
@@ -832,13 +844,13 @@ class Object
832
844
  need_fk = "#{assoc_name}_id" != assoc[:fk]
833
845
  end
834
846
  if (inverse = assoc[:inverse])
835
- inverse_assoc_name, _x = _brick_get_hm_assoc_name(relations[inverse_table], inverse)
836
847
  # If it's multitenant with something like: public.____ ...
837
848
  if (it_parts = inverse_table.split('.')).length > 1 &&
838
849
  ::Brick.config.schema_behavior[:multitenant] && Object.const_defined?('Apartment') &&
839
850
  it_parts.first == Apartment.default_schema
840
851
  it_parts.shift # ... then ditch the generic schema name
841
852
  end
853
+ inverse_assoc_name, _x = _brick_get_hm_assoc_name(relations[inverse_table], inverse, it_parts.join('_').singularize)
842
854
  has_ones = ::Brick.config.has_ones&.fetch(it_parts.join('/').singularize.camelize, nil)
843
855
  if has_ones&.key?(singular_inv_assoc_name = ActiveSupport::Inflector.singularize(inverse_assoc_name.tr('.', '_')))
844
856
  inverse_assoc_name = if has_ones[singular_inv_assoc_name]
@@ -1086,9 +1098,9 @@ class Object
1086
1098
  [built_controller, code]
1087
1099
  end
1088
1100
 
1089
- def _brick_get_hm_assoc_name(relation, hm_assoc)
1101
+ def _brick_get_hm_assoc_name(relation, hm_assoc, source = nil)
1090
1102
  if (relation[:hm_counts][hm_assoc[:assoc_name]]&.> 1) &&
1091
- hm_assoc[:alternate_name] != hm_assoc[:inverse][:assoc_name]
1103
+ hm_assoc[:alternate_name] != (source || name.underscore)
1092
1104
  plural = ActiveSupport::Inflector.pluralize(hm_assoc[:alternate_name])
1093
1105
  new_alt_name = (hm_assoc[:alternate_name] == name.underscore) ? "#{hm_assoc[:assoc_name].singularize}_#{plural}" : plural
1094
1106
  # uniq = 1
@@ -105,13 +105,26 @@ module Brick
105
105
  hms_columns = [] # Used for 'index'
106
106
  skip_klass_hms = ::Brick.config.skip_index_hms[model_name] || {}
107
107
  hms_headers = hms.each_with_object([]) do |hm, s|
108
- hm_stuff = [(hm_assoc = hm.last), "H#{hm_assoc.macro == :has_one ? 'O' : 'M'}#{'T' if hm_assoc.options[:through]}", (assoc_name = hm.first)]
108
+ hm_stuff = [(hm_assoc = hm.last),
109
+ "H#{hm_assoc.macro == :has_one ? 'O' : 'M'}#{'T' if hm_assoc.options[:through]}",
110
+ (assoc_name = hm.first)]
109
111
  hm_fk_name = if hm_assoc.options[:through]
110
- associative = associatives[hm_assoc.name]
111
- associative && "'#{associative.name}.#{associative.foreign_key}'"
112
- else
113
- hm_assoc.foreign_key
114
- end
112
+ associative = associatives[hm.first]
113
+ tbl_nm = if hm_assoc.options[:source]
114
+ associative.klass.reflect_on_association(hm_assoc.options[:source]).inverse_of&.name
115
+ else
116
+ associative.name
117
+ end
118
+ # If there is no inverse available for the source belongs_to association, make one based on the class name
119
+ unless tbl_nm
120
+ tbl_nm = associative.class_name.underscore
121
+ tbl_nm.slice!(0) if tbl_nm[0] == ('/')
122
+ tbl_nm = tbl_nm.tr('/', '_').pluralize
123
+ end
124
+ "'#{tbl_nm}.#{associative.foreign_key}'"
125
+ else
126
+ hm_assoc.foreign_key
127
+ end
115
128
  case args.first
116
129
  when 'index'
117
130
  hms_columns << if hm_assoc.macro == :has_many
@@ -168,10 +181,10 @@ module Brick
168
181
  }
169
182
 
170
183
  #headerTop {
171
- position: sticky;
172
- top: 0px;
173
- background-color: white;
174
- z-index: 1;
184
+ position: sticky;
185
+ top: 0px;
186
+ background-color: white;
187
+ z-index: 1;
175
188
  }
176
189
  table {
177
190
  border-collapse: collapse;
@@ -218,9 +231,6 @@ table tbody tr.active-row {
218
231
  color: #009879;
219
232
  }
220
233
 
221
- td.val {
222
- display: block;
223
- }
224
234
  a.show-arrow {
225
235
  font-size: 1.5em;
226
236
  text-decoration: none;
@@ -240,6 +250,10 @@ a.big-arrow {
240
250
  .dimmed {
241
251
  background-color: #C0C0C0;
242
252
  }
253
+ .orphan {
254
+ color: red;
255
+ white-space: nowrap;
256
+ }
243
257
 
244
258
  #revertTemplate {
245
259
  display: none;
@@ -255,13 +269,13 @@ input+svg.revert {
255
269
  top: 0.5em;
256
270
  }
257
271
 
258
- input[type=submit] {
272
+ .update {
273
+ position: sticky;
274
+ right: 1em;
275
+ float: right;
259
276
  background-color: #004998;
260
277
  color: #FFF;
261
278
  }
262
- .right {
263
- text-align: right;
264
- }
265
279
  </style>
266
280
  <% is_includes_dates = nil
267
281
 
@@ -580,8 +594,8 @@ if (headerTop) {
580
594
  # 0..62 because Postgres column names are limited to 63 characters
581
595
  #{obj_name}, (descrips = @_brick_bt_descrip[bt.first][bt_class])[0..-2].map { |id| #{obj_name}.send(id.last[0..62]) }, (bt_id_col = descrips.last)
582
596
  )
583
- bt_txt ||= \"<< Orphaned ID: #\{val} >>\" if val
584
- bt_id = bt_id_col.map { |id_col| #{obj_name}.send(id_col.to_sym) } if bt_id_col&.present? %>
597
+ bt_txt ||= \"<span class=\\\"orphan\\\">&lt;&lt; Orphaned ID: #\{val} >></span>\".html_safe if val
598
+ bt_id = bt_id_col.map { |id_col| #{obj_name}.send(id_col.to_sym) } %>
585
599
  <%= bt_id&.first ? link_to(bt_txt, send(\"#\{bt_class.base_class.name.underscore.tr('/', '_')\}_path\".to_sym, bt_id)) : bt_txt %>
586
600
  <%#= Previously was: bt_obj = bt[1].first.first.find_by(bt[2] => val); link_to(bt_obj.brick_descrip, send(\"#\{bt[1].first.first.name.underscore\}_path\".to_sym, bt_obj.send(bt[1].first.first.primary_key.to_sym))) if bt_obj %>
587
601
  <% end %>
@@ -680,7 +694,7 @@ end
680
694
  <%= k %>
681
695
  <% end %>
682
696
  </th>
683
- <td class=\"val\">
697
+ <td>
684
698
  <% dt_pickers = { datetime: 'datetimepicker', timestamp: 'datetimepicker', time: 'timepicker', date: 'datepicker' }
685
699
  if bt
686
700
  html_options = { prompt: \"Select #\{bt_name\}\" }
@@ -689,18 +703,21 @@ end
689
703
  <%= if (bt_obj = bt_class&.find_by(bt_pair[1] => val))
690
704
  link_to('⇛', send(\"#\{bt_class.base_class.name.underscore.tr('/', '_')\}_path\".to_sym, bt_obj.send(bt_class.primary_key.to_sym)), { class: 'show-arrow' })
691
705
  elsif val
692
- \"<span>Orphaned ID: #\{val}</span>\".html_safe
706
+ \"<span class=\\\"orphan\\\">Orphaned ID: #\{val}</span>\".html_safe
693
707
  end %><svg class=\"revert\" width=\"1.5em\" viewBox=\"0 0 512 512\"><use xlink:href=\"#revertPath\" /></svg>
694
- <% else case (col_type = #{model_name}.column_for_attribute(k).type)
708
+ <% else
709
+ html_options = {}
710
+ html_options[:class] = 'dimmed' unless val
711
+ case (col_type = #{model_name}.column_for_attribute(k).type)
695
712
  when :string, :text %>
696
713
  <% if is_bcrypt?(val) # || .readonly? %>
697
714
  <%= hide_bcrypt(val, 1000) %>
698
715
  <% else %>
699
- <div class=\"wide-input\"><%= f.text_field k.to_sym %><svg class=\"revert\" width=\"1.5em\" viewBox=\"0 0 512 512\"><use xlink:href=\"#revertPath\" /></svg></div>
716
+ <div class=\"wide-input\"><%= f.text_field(k.to_sym, html_options) %><svg class=\"revert\" width=\"1.5em\" viewBox=\"0 0 512 512\"><use xlink:href=\"#revertPath\" /></svg></div>
700
717
  <% end %>
701
718
  <% when :boolean %>
702
719
  <%= f.check_box k.to_sym %><svg class=\"revert\" width=\"1.5em\" viewBox=\"0 0 512 512\"><use xlink:href=\"#revertPath\" /></svg>
703
- <% when :integer, :decimal, :float
720
+ <% when :integer, :decimal, :float %>
704
721
  <%= if col_type == :integer
705
722
  f.text_field k.to_sym, { pattern: '\\d*', class: 'check-validity' }
706
723
  else
@@ -710,10 +727,11 @@ end
710
727
  is_includes_dates = true %>
711
728
  <%= f.text_field k.to_sym, { class: dt_pickers[col_type] } %><svg class=\"revert\" width=\"1.5em\" viewBox=\"0 0 512 512\"><use xlink:href=\"#revertPath\" /></svg>
712
729
  <% when :uuid %>
713
- # Postgres naturally uses the +uuid_generate_v4()+ function from the uuid-ossp extension
714
- # If it's not yet enabled then: enable_extension 'uuid-ossp'
715
- # ActiveUUID gem created a new :uuid type %>
716
- <%= val %>
730
+ <%=
731
+ # Postgres naturally uses the +uuid_generate_v4()+ function from the uuid-ossp extension
732
+ # If it's not yet enabled then: enable_extension 'uuid-ossp'
733
+ # ActiveUUID gem created a new :uuid type
734
+ val %>
717
735
  <% when :binary, :primary_key %>
718
736
  <% end %>
719
737
  <% end %>
@@ -721,7 +739,7 @@ end
721
739
  </tr>
722
740
  <% end
723
741
  if has_fields %>
724
- <tr><td colspan=\"2\" class=\"right\"><%= f.submit %></td></tr>
742
+ <tr><td colspan=\"2\"><%= f.submit({ class: 'update' }) %></td></tr>
725
743
  <% else %>
726
744
  <tr><td colspan=\"2\">(No displayable fields)</td></tr>
727
745
  <% end %>
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 44
8
+ TINY = 47
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
@@ -168,8 +168,12 @@ module Brick
168
168
  skip_hms = {}
169
169
  associatives = hms.each_with_object({}) do |hmt, s|
170
170
  if (through = hmt.last.options[:through])
171
- skip_hms[through] = nil
172
- s[hmt.first] = hms[through] # End up with a hash of HMT names pointing to join-table associations
171
+ skip_hms[through] = nil # if hms[through]
172
+ # binding.pry if !hms[through]
173
+ # End up with a hash of HMT names pointing to join-table associations
174
+ # Last part was: hmt.last.name
175
+ # Changed up because looking for: hms[:issue_issue_duplicates]
176
+ s[hmt.first] = hms[through] # || hms["#{(opt = hmt.last.options)[:through].to_s.singularize}_#{opt[:source].to_s.pluralize}".to_sym]
173
177
  elsif hmt.last.inverse_of.nil?
174
178
  puts "SKIPPING #{hmt.last.name.inspect}"
175
179
  # %%% If we don't do this then below associative.name will find that associative is nil
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.44
4
+ version: 1.0.47
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-07-12 00:00:00.000000000 Z
11
+ date: 2022-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord