brick 1.0.126 → 1.0.128

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: b59690045d31108dece3222f655503a771ab860697993459a6beb92aa0ecdb07
4
- data.tar.gz: 4c83d54ddc01e03330ac82f5949cece3f21631624adb704b923bd338ac84481c
3
+ metadata.gz: 4465179ddef5435627439c7123bbb63e951abcda5bd8bd8e20952cca2fc9e274
4
+ data.tar.gz: b567eb687c8eea355ece80562a67e424629df4a8b64aae48596e6c6b01c730b4
5
5
  SHA512:
6
- metadata.gz: c12e4073de8230683825617fccabeeda71746dcf3c892a60557990777543c15a3e9a18a8c7bdcf3b1c236bf422ec74d10b98bf1341b5d472e611799c8e74de31
7
- data.tar.gz: 6e9fdb9e41ff12a1b5092226133cb7c0d8444bf330e2557da156bc7f21d4377678061bd65c5b36ad3b9d1f9bf88203594c34cf8bcaabad7b93c2609b2798e474
6
+ metadata.gz: 162cf46af2e43b2652e59f9fe8f4d2826e490def50fb868869f614aacb256cfeecee3833dfb41807bef5ea64c83e921b7e993e728e6e42730a214ec49601de67
7
+ data.tar.gz: 15fdcc9b67bc82b55a195168e020575ca04d9d1ae5830e0d1bcd2c7e04944aba90238342cabc1c93b7b7d01619a369b1bb0a0383dbbe91666e796ffa4051aa55
@@ -108,16 +108,16 @@ module ActiveRecord
108
108
  dsl
109
109
  end
110
110
 
111
- def self.brick_parse_dsl(build_array = nil, prefix = [], translations = {}, is_polymorphic = false, dsl = nil, emit_dsl = false)
112
- unless build_array.is_a?(::Brick::JoinArray)
113
- build_array = ::Brick::JoinArray.new.tap { |ary| ary.replace([build_array]) } if build_array.is_a?(::Brick::JoinHash)
114
- build_array = ::Brick::JoinArray.new unless build_array.nil? || build_array.is_a?(Array)
111
+ def self.brick_parse_dsl(join_array = nil, prefix = [], translations = {}, is_polymorphic = false, dsl = nil, emit_dsl = false)
112
+ unless join_array.is_a?(::Brick::JoinArray)
113
+ join_array = ::Brick::JoinArray.new.tap { |ary| ary.replace([join_array]) } if join_array.is_a?(::Brick::JoinHash)
114
+ join_array = ::Brick::JoinArray.new unless join_array.nil? || join_array.is_a?(Array)
115
115
  end
116
116
  prefix = [prefix] unless prefix.is_a?(Array)
117
117
  members = []
118
118
  unless dsl || (dsl = ::Brick.config.model_descrips[name] || brick_get_dsl)
119
119
  # With no DSL available, still put this prefix into the JoinArray so we can get primary key (ID) info from this table
120
- x = prefix.each_with_object(build_array) { |v, s| s[v.to_sym] }
120
+ x = prefix.each_with_object(join_array) { |v, s| s[v.to_sym] }
121
121
  x[prefix.last] = nil unless prefix.empty? # Using []= will "hydrate" any missing part(s) in our whole series
122
122
  return members
123
123
  end
@@ -141,7 +141,7 @@ module ActiveRecord
141
141
  if first_parts
142
142
  if (parts = prefix + first_parts + [parts[-1]]).length > 1 && klass
143
143
  unless is_polymorphic
144
- s = build_array
144
+ s = join_array
145
145
  parts[0..-3].each { |v| s = s[v.to_sym] }
146
146
  s[parts[-2]] = nil # unless parts[-2].empty? # Using []= will "hydrate" any missing part(s) in our whole series
147
147
  end
@@ -153,7 +153,7 @@ module ActiveRecord
153
153
  prefix << parts.shift until parts.empty?
154
154
  end
155
155
  # Expand this entry which refers to an association name
156
- members2, dsl2a = klass.brick_parse_dsl(build_array, prefix + [possible_dsl], translations, is_polymorphic, nil, true)
156
+ members2, dsl2a = klass.brick_parse_dsl(join_array, prefix + [possible_dsl], translations, is_polymorphic, nil, true)
157
157
  members += members2
158
158
  dsl2 << dsl2a
159
159
  dsl3 << dsl2a
@@ -434,7 +434,9 @@ module ActiveRecord
434
434
  @brick_links ||= { '' => table_name }
435
435
  end
436
436
 
437
- def brick_select(params, selects = [], order_by = nil, translations = {}, join_array = ::Brick::JoinArray.new)
437
+ def brick_select(params, selects = [], order_by = nil, translations = {},
438
+ join_array = ::Brick::JoinArray.new,
439
+ cust_col_override = nil)
438
440
  is_add_bts = is_add_hms = true
439
441
 
440
442
  # Build out cust_cols, bt_descrip and hm_counts now so that they are available on the
@@ -467,7 +469,7 @@ module ActiveRecord
467
469
  is_distinct = true
468
470
  distinct!
469
471
  end
470
- wheres[k] = v.split(',')
472
+ wheres[k] = v.is_a?(String) ? v.split(',') : v
471
473
  end
472
474
 
473
475
  # %%% Skip the metadata columns
@@ -506,84 +508,90 @@ module ActiveRecord
506
508
  end
507
509
  end
508
510
 
509
- if join_array.present?
510
- left_outer_joins!(join_array)
511
- # Touching AREL AST walks the JoinDependency tree, and in that process uses our
512
- # "brick_links" patch to find how every AR chain of association names relates to exact
513
- # table correlation names chosen by AREL. We use a duplicate relation object for this
514
- # because an important side-effect of referencing the AST is that the @arel instance
515
- # variable gets set, and this is a signal to ActiveRecord that a relation has now
516
- # become immutable. (We aren't quite ready for our "real deal" relation object to be
517
- # set in stone ... still need to add .select(), and possibly .where() and .order()
518
- # things ... also if there are any HM counts then an OUTER JOIN for each of them out
519
- # to a derived table to do that counting. All of these things need to know proper
520
- # table correlation names, which will now become available in brick_links on the
521
- # rel_dupe object.)
522
- (rel_dupe = dup).arel.ast
523
-
524
- core_selects = selects.dup
525
- id_for_tables = Hash.new { |h, k| h[k] = [] }
526
- field_tbl_names = Hash.new { |h, k| h[k] = {} }
527
- used_col_aliases = {} # Used to make sure there is not a name clash
528
-
529
- # CUSTOM COLUMNS
530
- # ==============
531
- klass._br_cust_cols.each do |k, cc|
532
- if rel_dupe.respond_to?(k) # Name already taken?
533
- # %%% Use ensure_unique here in this kind of fashion:
534
- # cnstr_name = ensure_unique(+"(brick) #{for_tbl}_#{pri_tbl}", bts, hms)
535
- # binding.pry
536
- next
537
- end
511
+ left_outer_joins!(join_array) if join_array.present?
512
+
513
+ # If it's a CollectionProxy (which inherits from Relation) then need to dig out the
514
+ # core Relation object which is found in the association scope.
515
+ rel_dupe = (is_a?(ActiveRecord::Associations::CollectionProxy) ? scope : self).dup
516
+
517
+ # Touching AREL AST walks the JoinDependency tree, and in that process uses our
518
+ # "brick_links" patch to find how every AR chain of association names relates to exact
519
+ # table correlation names chosen by AREL. We use a duplicate relation object for this
520
+ # because an important side-effect of referencing the AST is that the @arel instance
521
+ # variable gets set, and this is a signal to ActiveRecord that a relation has now
522
+ # become immutable. (We aren't quite ready for our "real deal" relation object to be
523
+ # set in stone ... still need to add .select(), and possibly .where() and .order()
524
+ # things ... also if there are any HM counts then an OUTER JOIN for each of them out
525
+ # to a derived table to do that counting. All of these things need to know proper
526
+ # table correlation names, which will now become available in brick_links on the
527
+ # rel_dupe object.)
528
+ rel_dupe.arel.ast
529
+
530
+ core_selects = selects.dup
531
+ id_for_tables = Hash.new { |h, k| h[k] = [] }
532
+ field_tbl_names = Hash.new { |h, k| h[k] = {} }
533
+ used_col_aliases = {} # Used to make sure there is not a name clash
534
+
535
+ # CUSTOM COLUMNS
536
+ # ==============
537
+ (cust_col_override || klass._br_cust_cols).each do |k, cc|
538
+ if rel_dupe.respond_to?(k) # Name already taken?
539
+ # %%% Use ensure_unique here in this kind of fashion:
540
+ # cnstr_name = ensure_unique(+"(brick) #{for_tbl}_#{pri_tbl}", bts, hms)
541
+ # binding.pry
542
+ next
543
+ end
538
544
 
539
- key_klass = nil
540
- key_tbl_name = nil
541
- dest_pk = nil
542
- key_alias = nil
543
- cc.first.each do |cc_part|
544
- dest_klass = cc_part[0..-2].inject(klass) do |kl, cc_part_term|
545
- # %%% Clear column info properly so we can do multiple subsequent requests
546
- # binding.pry unless kl.reflect_on_association(cc_part_term)
547
- kl.reflect_on_association(cc_part_term)&.klass || klass
548
- end
549
- tbl_name = rel_dupe.brick_links[cc_part[0..-2].map(&:to_s).join('.')]
550
- # Deal with the conflict if there are two parts in the custom column named the same,
551
- # "category.name" and "product.name" for instance will end up with aliases of "name"
552
- # and "product__name".
553
- if (cc_part_idx = cc_part.length - 1).zero?
554
- col_alias = "br_cc_#{k}__#{table_name.tr('.', '_')}"
555
- else
556
- while cc_part_idx > 0 &&
557
- (col_alias = "br_cc_#{k}__#{cc_part[cc_part_idx..-1].map(&:to_s).join('__').tr('.', '_')}") &&
558
- used_col_aliases.key?(col_alias)
559
- cc_part_idx -= 1
560
- end
561
- end
562
- used_col_aliases[col_alias] = nil
563
- # Set up custom column links by preparing key_klass and key_alias
564
- # (If there are multiple different tables referenced in the DSL, we end up creating a link to the last one)
565
- if cc[2] && (dest_pk = dest_klass.primary_key)
566
- key_klass = dest_klass
567
- key_tbl_name = tbl_name
568
- cc_part_idx = cc_part.length - 1
569
- while cc_part_idx > 0 &&
570
- (key_alias = "br_cc_#{k}__#{(cc_part[cc_part_idx..-2] + [dest_pk]).map(&:to_s).join('__')}") &&
571
- key_alias != col_alias && # We break out if this key alias does exactly match the col_alias
572
- used_col_aliases.key?(key_alias)
573
- cc_part_idx -= 1
574
- end
545
+ key_klass = nil
546
+ key_tbl_name = nil
547
+ dest_pk = nil
548
+ key_alias = nil
549
+ cc.first.each do |cc_part|
550
+ dest_klass = cc_part[0..-2].inject(klass) do |kl, cc_part_term|
551
+ # %%% Clear column info properly so we can do multiple subsequent requests
552
+ # binding.pry unless kl.reflect_on_association(cc_part_term)
553
+ kl.reflect_on_association(cc_part_term)&.klass || klass
554
+ end
555
+ tbl_name = rel_dupe.brick_links[cc_part[0..-2].map(&:to_s).join('.')]
556
+ # Deal with the conflict if there are two parts in the custom column named the same,
557
+ # "category.name" and "product.name" for instance will end up with aliases of "name"
558
+ # and "product__name".
559
+ if (cc_part_idx = cc_part.length - 1).zero?
560
+ col_alias = "br_cc_#{k}__#{table_name.tr('.', '_')}_#{cc_part.first}"
561
+ else
562
+ while cc_part_idx > 0 &&
563
+ (col_alias = "br_cc_#{k}__#{cc_part[cc_part_idx..-1].map(&:to_s).join('__').tr('.', '_')}") &&
564
+ used_col_aliases.key?(col_alias)
565
+ cc_part_idx -= 1
575
566
  end
576
- selects << "#{tbl_name}.#{cc_part.last} AS #{col_alias}"
577
- cc_part << col_alias
578
567
  end
579
- # Add a key column unless we've already got it
580
- if key_alias && !used_col_aliases.key?(key_alias)
581
- selects << "#{key_tbl_name}.#{dest_pk} AS #{key_alias}"
582
- used_col_aliases[key_alias] = nil
568
+ used_col_aliases[col_alias] = nil
569
+ # Set up custom column links by preparing key_klass and key_alias
570
+ # (If there are multiple different tables referenced in the DSL, we end up creating a link to the last one)
571
+ if cc[2] && (dest_pk = dest_klass.primary_key)
572
+ key_klass = dest_klass
573
+ key_tbl_name = tbl_name
574
+ cc_part_idx = cc_part.length - 1
575
+ while cc_part_idx > 0 &&
576
+ (key_alias = "br_cc_#{k}__#{(cc_part[cc_part_idx..-2] + [dest_pk]).map(&:to_s).join('__')}") &&
577
+ key_alias != col_alias && # We break out if this key alias does exactly match the col_alias
578
+ used_col_aliases.key?(key_alias)
579
+ cc_part_idx -= 1
580
+ end
583
581
  end
584
- cc[2] = key_alias ? [key_klass, key_alias] : nil
582
+ selects << "#{tbl_name}.#{cc_part.last} AS #{col_alias}"
583
+ cc_part << col_alias
585
584
  end
585
+ # Add a key column unless we've already got it
586
+ if key_alias && !used_col_aliases.key?(key_alias)
587
+ selects << "#{key_tbl_name}.#{dest_pk} AS #{key_alias}"
588
+ used_col_aliases[key_alias] = nil
589
+ end
590
+ cc[2] = key_alias ? [key_klass, key_alias] : nil
591
+ end
586
592
 
593
+ # LEFT OUTER JOINs
594
+ unless cust_col_override
587
595
  klass._br_bt_descrip.each do |v|
588
596
  v.last.each do |k1, v1| # k1 is class, v1 is array of columns to snag
589
597
  next unless (tbl_name = rel_dupe.brick_links[v.first.to_s]&.split('.')&.last)
@@ -644,6 +652,7 @@ module ActiveRecord
644
652
  _assoc_names[assoc_name] = [table_alias, klass]
645
653
  end
646
654
  end
655
+
647
656
  # Add derived table JOIN for the has_many counts
648
657
  nix = []
649
658
  klass._br_hm_counts.each do |k, hm|
@@ -781,7 +790,7 @@ module ActiveRecord
781
790
  JOIN (SELECT #{hm_selects.map { |s| "#{'br_t0.' if from_clause}#{s}" }.join(', ')}, COUNT(#{'DISTINCT ' if hm.options[:through]}#{count_column
782
791
  }) AS c_t_ FROM #{from_clause || hm_table_name} GROUP BY #{group_bys.join(', ')}) #{tbl_alias}"
783
792
  self.joins_values |= ["#{join_clause} ON #{on_clause.join(' AND ')}"] # Same as: joins!(...)
784
- end
793
+ end unless cust_col_override
785
794
  while (n = nix.pop)
786
795
  klass._br_hm_counts.delete(n)
787
796
  end
@@ -851,6 +860,19 @@ JOIN (SELECT #{hm_selects.map { |s| "#{'br_t0.' if from_clause}#{s}" }.join(', '
851
860
  wheres unless wheres.empty? # Return the specific parameters that we did use
852
861
  end
853
862
 
863
+ # Build out an AR relation that queries for a list of objects, and include all the appropriate JOINs to later apply DSL using #brick_descrip
864
+ def brick_list
865
+ pks = klass.primary_key.is_a?(String) ? [klass.primary_key] : klass.primary_key
866
+ selects = pks.each_with_object([]) { |pk, s| s << pk unless s.include?(pk) }
867
+ pieces, my_dsl = klass.brick_parse_dsl(join_array = ::Brick::JoinArray.new, [], translations = {}, false, nil, true)
868
+ brick_select(
869
+ where_values_hash, selects, nil, translations, join_array,
870
+ { '_br' => (descrip_cols = [pieces, my_dsl]) }
871
+ )
872
+ order_values = klass.primary_key
873
+ [self.select(selects), descrip_cols]
874
+ end
875
+
854
876
  private
855
877
 
856
878
  def shift_or_first(ary)
@@ -1254,6 +1276,11 @@ class Object
1254
1276
  end
1255
1277
  self.abstract_class = true
1256
1278
  code << " self.abstract_class = true\n"
1279
+ elsif Object.const_defined?('BCrypt') && relation[:cols].include?('password_digest') &&
1280
+ !instance_methods.include?(:password) && respond_to?(:has_secure_password)
1281
+ puts "Appears that the #{full_name} model is intended to hold user account information. Applying #has_secure_password."
1282
+ has_secure_password
1283
+ code << " has_secure_password\n"
1257
1284
  end
1258
1285
  # Accommodate singular or camel-cased table names such as "order_detail" or "OrderDetails"
1259
1286
  code << " self.table_name = '#{self.table_name = matching}'\n" if inheritable_name || table_name != matching
@@ -2718,12 +2745,17 @@ module Brick
2718
2745
  end
2719
2746
  end
2720
2747
  ::Brick.relations.map do |k, v|
2748
+ # next if Brick.config.exclude_tables.include?(k)
2749
+
2721
2750
  tbl_parts = k.split('.')
2722
2751
  tbl_parts.shift if ::Brick.apartment_multitenant && tbl_parts.length > 1 && tbl_parts.first == ::Brick.apartment_default_tenant
2723
2752
  res = tbl_parts.join('.')
2724
- [k, (model = models[res])&.last&.table_name || v[:class_name].constantize.table_name,
2725
- migrations&.fetch(res, nil),
2726
- model&.first]
2753
+ table_name = (model = models[res])&.last&.table_name
2754
+ table_name ||= begin
2755
+ v[:class_name].constantize.table_name
2756
+ rescue
2757
+ end
2758
+ [k, table_name || k, migrations&.fetch(res, nil), model&.first]
2727
2759
  end
2728
2760
  end
2729
2761
 
@@ -1602,7 +1602,15 @@ end
1602
1602
  if bt.length < 4
1603
1603
  bt << (option_detail = [[\"(No #\{bt_name\} chosen)\", '^^^brick_NULL^^^']])
1604
1604
  # %%% Accommodate composite keys for obj.pk at the end here
1605
- bt_class&.order(obj_pk = bt_class.primary_key)&.each { |obj| option_detail << [obj.brick_descrip(nil, obj_pk), obj.send(obj_pk)] }
1605
+ collection, descrip_cols = bt_class&.order(obj_pk = bt_class.primary_key).brick_list
1606
+ collection&.each do |obj|
1607
+ option_detail << [
1608
+ obj.brick_descrip(
1609
+ descrip_cols&.first&.map { |col| obj.send(col.last) },
1610
+ obj_pk
1611
+ ), obj.send(obj_pk)
1612
+ ]
1613
+ end
1606
1614
  end %>
1607
1615
  BT <%= bt_class&.bt_link(bt.first) || orig_poly_name %>
1608
1616
  <% else %>
@@ -1634,34 +1642,45 @@ end
1634
1642
  obj_pk = (pk.is_a?(Array) ? pk : [pk]).each_with_object([]) { |pk_part, s| s << "#{hm_singular_name}.#{pk_part}" }.join(', ')
1635
1643
  poly_fix = if (poly_type = (hm.first.options[:as] && hm.first.type))
1636
1644
  "
1637
- # Let's fix an unexpected \"feature\" of AR -- when going through a polymorphic has_many
1638
- # association that points to an STI model then filtering for the __able_type column is done
1639
- # with a .where(). And the polymorphic class name it points to is the base class name of
1640
- # the STI model instead of its subclass.
1641
- poly_type = #{poly_type.inspect}
1642
- #{ (inh_col = @_brick_model.inheritance_column).present? &&
1643
- " if poly_type && @#{obj_name}.respond_to?(:#{inh_col}) &&
1644
- (base_type = collection.where_values_hash[poly_type])
1645
- collection = collection.rewhere(poly_type => [base_type, @#{obj_name}.#{inh_col}])
1646
- end"}"
1645
+ # Let's fix an unexpected \"feature\" of AR -- when going through a polymorphic has_many
1646
+ # association that points to an STI model then filtering for the __able_type column is done
1647
+ # with a .where(). And the polymorphic class name it points to is the base class name of
1648
+ # the STI model instead of its subclass.
1649
+ poly_type = #{poly_type.inspect}
1650
+ #{ (inh_col = @_brick_model.inheritance_column).present? &&
1651
+ " if poly_type && @#{obj_name}.respond_to?(:#{inh_col}) &&
1652
+ (base_type = collection.where_values_hash[poly_type])
1653
+ collection = collection.rewhere(poly_type => [base_type, @#{obj_name}.#{inh_col}])
1654
+ end"}"
1647
1655
  end
1648
1656
  s << "<table id=\"#{hm_name}\" class=\"shadow\">
1649
1657
  <tr><th>#{hm[1]}#{' poly' if hm[0].options[:as]} #{hm[3]}</th></tr>
1650
- <% collection = @#{obj_name}.#{hm_name}
1651
- collection = case collection
1652
- when ActiveRecord::Associations::CollectionProxy#{
1653
- poly_fix}
1654
- collection.order(#{pk.inspect})
1655
- when ActiveRecord::Base # Object from a has_one
1656
- [collection]
1657
- else # We get an array back when AR < 4.2
1658
- collection.to_a.compact
1659
- end
1660
- if collection.empty? %>
1658
+ <% if (assoc = @#{obj_name}.class.reflect_on_association(:#{hm_name})).macro == :has_one &&
1659
+ assoc.options&.fetch(:through, nil).nil?
1660
+ # In order to apply DSL properly, evaluate this HO the other way around as if it were as a BT
1661
+ collection = assoc.klass.where(assoc.foreign_key => @#{obj_name}.#{pk})
1662
+ collection = collection.instance_exec(&assoc.scopes.first) if assoc.scopes.present?
1663
+ else
1664
+ collection = @#{obj_name}.#{hm_name}
1665
+ end
1666
+ case collection
1667
+ when ActiveRecord::Relation # has_many (which comes in as a CollectionProxy) or a has_one#{
1668
+ poly_fix}
1669
+ collection2, descrip_cols = collection.brick_list
1670
+ when ActiveRecord::Base # Object from a has_one :through
1671
+ collection2 = [collection]
1672
+ else # We get an array back when AR < 4.2
1673
+ collection2 = collection.to_a.compact
1674
+ end
1675
+ collection2 = collection2.uniq
1676
+ if collection2.empty? %>
1661
1677
  <tr><td>(none)</td></tr>
1662
- <% else %>
1663
- <% collection.uniq.each do |#{hm_singular_name}| %>
1664
- <tr><td><%= link_to(#{hm_singular_name}.brick_descrip, #{hm.first.klass._brick_index(:singular)}_path(slashify(#{obj_pk}))) %></td></tr>
1678
+ <% else
1679
+ collection2.each do |#{hm_singular_name}| %>
1680
+ <tr><td><%= br_descrip = #{hm_singular_name}.brick_descrip(
1681
+ descrip_cols&.first&.map { |col| #{hm_singular_name}.send(col.last) }
1682
+ )
1683
+ link_to(br_descrip, #{hm.first.klass._brick_index(:singular)}_path(slashify(#{obj_pk}))) %></td></tr>
1665
1684
  <% end %>
1666
1685
  <% end %>
1667
1686
  </table>"
@@ -5,7 +5,8 @@ module Brick::Rails::FormBuilder
5
5
  # @_text_fields_present - To include trix editor
6
6
  # @_date_fields_present - To include flatpickr date / time editor
7
7
  # @_json_fields_present - To include JSONEditor
8
- def brick_field(method, html_options = {}, val = nil, col = nil, bt = nil, bt_class = nil, bt_name = nil, bt_pair = nil)
8
+ def brick_field(method, html_options = {}, val = nil, col = nil,
9
+ bt = nil, bt_class = nil, bt_name = nil, bt_pair = nil)
9
10
  model = self.object.class
10
11
  col ||= model.columns_hash[method]
11
12
  out = +'<table><tr><td>'
@@ -19,15 +20,16 @@ module Brick::Rails::FormBuilder
19
20
 
20
21
  html_options[:prompt] = "Select #{bt_name}"
21
22
  out << self.select(method.to_sym, bt[3], { value: val || '^^^brick_NULL^^^' }, html_options)
22
- out << if (bt_obj = bt_class&.find_by(bt_pair[1] => val))
23
- bt_path = template.send(
24
- "#{bt_class.base_class._brick_index(:singular)}_path".to_sym,
25
- bt_obj.send(bt_class.primary_key.to_sym)
26
- )
27
- template.link_to('⇛', bt_path, { class: 'show-arrow' })
28
- elsif val
29
- "<span class=\"orphan\">Orphaned ID: #{val}</span>".html_safe
30
- end
23
+ bt_link = if (bt_obj = bt_class&.find_by(bt_pair[1] => val))
24
+ bt_path = template.send(
25
+ "#{bt_class.base_class._brick_index(:singular)}_path".to_sym,
26
+ bt_obj.send(bt_class.primary_key.to_sym)
27
+ )
28
+ template.link_to('⇛', bt_path, { class: 'show-arrow' })
29
+ elsif val
30
+ "<span class=\"orphan\">Orphaned ID: #{val}</span>".html_safe
31
+ end
32
+ out << bt_link if bt_link
31
33
  elsif @_brick_monetized_attributes&.include?(method)
32
34
  out << self.text_field(method.to_sym, html_options.merge({ value: Money.new(val.to_i).format }))
33
35
  else
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 126
8
+ TINY = 128
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = 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.126
4
+ version: 1.0.128
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lorin Thwaits
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-05 00:00:00.000000000 Z
11
+ date: 2023-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord