brick 1.0.138 → 1.0.140
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 +4 -4
- data/lib/brick/compatibility.rb +1 -0
- data/lib/brick/config.rb +8 -0
- data/lib/brick/extensions.rb +134 -28
- data/lib/brick/frameworks/rails/engine.rb +50 -26
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +99 -21
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 995f6ed970029309b465f80193521b91c63335e12400cbb21e0ef0d60fe60dd2
|
4
|
+
data.tar.gz: c610df65f26a9e9bf4f081c8d0172fea6fc69cda350d26cf5287362237e7ceca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 534bde690d45d11d8371d0e666df86badc47879242bcf67a219aeff6dc71fb1ac668b02bba5059f2fceafa63ddb6312cf3e42e993c5ba1de47ebf276abd9bb7c
|
7
|
+
data.tar.gz: 18e0c976540749fbc93fd89be05735d2e9544db37d04a3738bc06e82fdc2811d9478398fa66881d17e9e18cb44e78720f66cc8db74660ddd6b5e23e523ea2db7
|
data/lib/brick/compatibility.rb
CHANGED
@@ -26,6 +26,7 @@ if Object.const_defined?('ActionPack') && !ActionPack.respond_to?(:version)
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
29
|
+
require 'action_view' # Needed for Rails <= 4.0
|
29
30
|
if Object.const_defined?('ActionView') && !ActionView.respond_to?(:version)
|
30
31
|
module ActionView
|
31
32
|
def self.version
|
data/lib/brick/config.rb
CHANGED
@@ -347,6 +347,14 @@ module Brick
|
|
347
347
|
@mutex.synchronize { @not_nullables = columns }
|
348
348
|
end
|
349
349
|
|
350
|
+
def always_load_fields
|
351
|
+
@mutex.synchronize { @always_load_fields || Hash.new { |h, k| h[k] = [] } }
|
352
|
+
end
|
353
|
+
|
354
|
+
def always_load_fields=(field_set)
|
355
|
+
@mutex.synchronize { @always_load_fields = field_set }
|
356
|
+
end
|
357
|
+
|
350
358
|
# Add status page showing all resources and what files have been built out for them
|
351
359
|
def add_status
|
352
360
|
true
|
data/lib/brick/extensions.rb
CHANGED
@@ -82,7 +82,7 @@ module ActiveRecord
|
|
82
82
|
|
83
83
|
def json_column?(col)
|
84
84
|
col.type == :json || ::Brick.config.json_columns[table_name]&.include?(col.name) ||
|
85
|
-
((attr_types = attribute_types[col.name]).respond_to?(:coder) &&
|
85
|
+
(respond_to?(:attribute_types) && (attr_types = attribute_types[col.name]).respond_to?(:coder) &&
|
86
86
|
(attr_types.coder.is_a?(Class) ? attr_types.coder : attr_types.coder&.class)&.name&.end_with?('JSON'))
|
87
87
|
end
|
88
88
|
end
|
@@ -235,7 +235,7 @@ module ActiveRecord
|
|
235
235
|
caches.fetch(obj_name) { caches[obj_name] = this_obj&.send(part.to_sym) }
|
236
236
|
rescue
|
237
237
|
clsnm = part.camelize
|
238
|
-
if (possible = this_obj.class.reflect_on_all_associations.select { |a| a.class_name == clsnm || a.klass.base_class.name == clsnm }.first)
|
238
|
+
if (possible = this_obj.class.reflect_on_all_associations.select { |a| !a.polymorphic? && (a.class_name == clsnm || a.klass.base_class.name == clsnm) }.first)
|
239
239
|
caches[obj_name] = this_obj&.send(possible.name)
|
240
240
|
end
|
241
241
|
end
|
@@ -286,7 +286,7 @@ module ActiveRecord
|
|
286
286
|
assoc_html_name = unless (assoc_name = assoc_name.to_s).camelize == name
|
287
287
|
CGI.escapeHTML(assoc_name)
|
288
288
|
end
|
289
|
-
model_path = ::Rails.application.routes.url_helpers.send("#{_brick_index}_path".to_sym)
|
289
|
+
model_path = ::Rails.application.routes.url_helpers.send("#{_brick_index || table_name}_path".to_sym)
|
290
290
|
model_path << "?#{self.inheritance_column}=#{self.name}" if self != base_class
|
291
291
|
av_class = Class.new.extend(ActionView::Helpers::UrlHelper)
|
292
292
|
av_class.extend(ActionView::Helpers::TagHelper) if ActionView.version < ::Gem::Version.new('7')
|
@@ -296,6 +296,8 @@ module ActiveRecord
|
|
296
296
|
|
297
297
|
# Providing a relation object allows auto-modules built from table name prefixes to work
|
298
298
|
def self._brick_index(mode = nil, separator = '_', relation = nil)
|
299
|
+
return if abstract_class
|
300
|
+
|
299
301
|
tbl_parts = ((mode == :singular) ? table_name.singularize : table_name).split('.')
|
300
302
|
tbl_parts.shift if ::Brick.apartment_multitenant && tbl_parts.length > 1 && tbl_parts.first == ::Brick.apartment_default_tenant
|
301
303
|
if (aps = relation&.fetch(:auto_prefixed_schema, nil)) && tbl_parts.last.start_with?(aps)
|
@@ -352,7 +354,7 @@ module ActiveRecord
|
|
352
354
|
pieces, my_dsl = brick_parse_dsl(join_array, [], translations, false, cc, true)
|
353
355
|
_br_cust_cols[k] = [pieces, my_dsl, fk_col]
|
354
356
|
end
|
355
|
-
bts, hms, associatives = ::Brick.get_bts_and_hms(self)
|
357
|
+
bts, hms, associatives = ::Brick.get_bts_and_hms(self, true)
|
356
358
|
bts.each do |_k, bt|
|
357
359
|
next if bt[2] # Polymorphic?
|
358
360
|
|
@@ -431,8 +433,16 @@ module ActiveRecord
|
|
431
433
|
[order_by, order_by_txt]
|
432
434
|
end
|
433
435
|
|
434
|
-
def self.brick_select(params
|
435
|
-
|
436
|
+
def self.brick_select(*args, params: {}, brick_col_names: false, **kwargs)
|
437
|
+
selects = if args[0].is_a?(Array)
|
438
|
+
other_args = args[1..-1]
|
439
|
+
args[0]
|
440
|
+
else
|
441
|
+
other_args = []
|
442
|
+
args
|
443
|
+
end
|
444
|
+
(relation = all).brick_select(selects, *other_args,
|
445
|
+
params: params, brick_col_names: brick_col_names, **kwargs)
|
436
446
|
relation.select(selects)
|
437
447
|
end
|
438
448
|
|
@@ -472,10 +482,29 @@ module ActiveRecord
|
|
472
482
|
@brick_links ||= { '' => table_name }
|
473
483
|
end
|
474
484
|
|
475
|
-
def brick_select(
|
476
|
-
join_array
|
477
|
-
cust_col_override
|
478
|
-
|
485
|
+
def brick_select(*args, params: {}, order_by: nil, translations: {},
|
486
|
+
join_array: ::Brick::JoinArray.new,
|
487
|
+
cust_col_override: nil,
|
488
|
+
brick_col_names: true)
|
489
|
+
selects = args[0].is_a?(Array) ? args[0] : args
|
490
|
+
if selects.present? && cust_col_override.nil? # See if there's any fancy ones in the select list
|
491
|
+
idx = 0
|
492
|
+
while idx < selects.length
|
493
|
+
v = selects[idx]
|
494
|
+
if v.is_a?(String) && v.index('.')
|
495
|
+
# No prefixes and not polymorphic
|
496
|
+
pieces = self.brick_parse_dsl(join_array, [], translations, false, dsl = "[#{v}]")
|
497
|
+
(cust_col_override ||= {})[v.tr('.', '_').to_sym] = [pieces, dsl, true]
|
498
|
+
selects.delete_at(idx)
|
499
|
+
else
|
500
|
+
idx += 1
|
501
|
+
end
|
502
|
+
end
|
503
|
+
elsif selects.is_a?(Hash) && params.empty? && cust_col_override.nil? # Make sense of things if they've passed in only params
|
504
|
+
params = selects
|
505
|
+
selects = []
|
506
|
+
end
|
507
|
+
is_add_bts = is_add_hms = !cust_col_override
|
479
508
|
|
480
509
|
# Build out cust_cols, bt_descrip and hm_counts now so that they are available on the
|
481
510
|
# model early in case the user wants to do an ORDER BY based on any of that.
|
@@ -487,6 +516,7 @@ module ActiveRecord
|
|
487
516
|
is_distinct = nil
|
488
517
|
wheres = {}
|
489
518
|
params.each do |k, v|
|
519
|
+
k = k.to_s # Rails < 4.2 comes in as a symbol
|
490
520
|
next if ['_brick_schema', '_brick_order',
|
491
521
|
'_brick_erd', '_brick_exclude', '_brick_unexclude',
|
492
522
|
'_brick_page', '_brick_page_size', '_brick_offset', '_brick_limit',
|
@@ -544,9 +574,19 @@ module ActiveRecord
|
|
544
574
|
"'<#{typ.end_with?('_TYP') ? typ[0..-5] : typ}>' AS #{col.name}"
|
545
575
|
end
|
546
576
|
end
|
577
|
+
else # Having some select columns chosen, add any missing always_load_fields for this model
|
578
|
+
::Brick.config.always_load_fields.fetch(klass.name, nil)&.each do |alf|
|
579
|
+
selects << alf unless selects.include?(alf)
|
580
|
+
end
|
547
581
|
end
|
548
582
|
|
549
|
-
|
583
|
+
if join_array.present?
|
584
|
+
if ActiveRecord.version < Gem::Version.new('4.2')
|
585
|
+
joins!(join_array)
|
586
|
+
else
|
587
|
+
left_outer_joins!(join_array)
|
588
|
+
end
|
589
|
+
end
|
550
590
|
|
551
591
|
# If it's a CollectionProxy (which inherits from Relation) then need to dig out the
|
552
592
|
# core Relation object which is found in the association scope.
|
@@ -594,11 +634,12 @@ module ActiveRecord
|
|
594
634
|
# Deal with the conflict if there are two parts in the custom column named the same,
|
595
635
|
# "category.name" and "product.name" for instance will end up with aliases of "name"
|
596
636
|
# and "product__name".
|
637
|
+
col_prefix = 'br_cc_' if brick_col_names
|
597
638
|
if (cc_part_idx = cc_part.length - 1).zero?
|
598
|
-
col_alias = "
|
639
|
+
col_alias = "#{col_prefix}#{k}__#{table_name.tr('.', '_')}_#{cc_part.first}"
|
599
640
|
else
|
600
641
|
while cc_part_idx > 0 &&
|
601
|
-
(col_alias = "
|
642
|
+
(col_alias = "#{col_prefix}#{k}__#{cc_part[cc_part_idx..-1].map(&:to_s).join('__').tr('.', '_')}") &&
|
602
643
|
used_col_aliases.key?(col_alias)
|
603
644
|
cc_part_idx -= 1
|
604
645
|
end
|
@@ -611,7 +652,7 @@ module ActiveRecord
|
|
611
652
|
key_tbl_name = tbl_name
|
612
653
|
cc_part_idx = cc_part.length - 1
|
613
654
|
while cc_part_idx > 0 &&
|
614
|
-
(key_alias = "
|
655
|
+
(key_alias = "#{col_prefix}#{k}__#{(cc_part[cc_part_idx..-2] + [dest_pk]).map(&:to_s).join('__')}") &&
|
615
656
|
key_alias != col_alias && # We break out if this key alias does exactly match the col_alias
|
616
657
|
used_col_aliases.key?(key_alias)
|
617
658
|
cc_part_idx -= 1
|
@@ -781,7 +822,7 @@ module ActiveRecord
|
|
781
822
|
|
782
823
|
pri_tbl = hm.active_record
|
783
824
|
pri_key = hm.options[:primary_key] || pri_tbl.primary_key
|
784
|
-
|
825
|
+
if hm.active_record.abstract_class || hm.active_record.column_names.exclude?(pri_key)
|
785
826
|
# %%% When this gets hit then if an attempt is made to display the ERD, it might end up being blank
|
786
827
|
nix << k
|
787
828
|
next
|
@@ -907,21 +948,43 @@ JOIN (SELECT #{hm_selects.map { |s| "#{'br_t0.' if from_clause}#{s}" }.join(', '
|
|
907
948
|
# Get foreign keys for anything marked to be auto-preloaded, or a self-referencing JOIN
|
908
949
|
klass_cols = klass.column_names
|
909
950
|
reflect_on_all_associations.each do |a|
|
910
|
-
selects << a.foreign_key if a.belongs_to? &&
|
911
|
-
(
|
951
|
+
selects << a.foreign_key if a.belongs_to? &&
|
952
|
+
(preload_values.include?(a.name) ||
|
953
|
+
(!a.options[:polymorphic] && a.klass == klass && klass_cols.include?(a.foreign_key))
|
954
|
+
)
|
912
955
|
end
|
913
956
|
# ActiveStorage compatibility
|
914
957
|
selects << 'service_name' if klass.name == 'ActiveStorage::Blob' && ActiveStorage::Blob.columns_hash.key?('service_name')
|
915
958
|
selects << 'blob_id' if klass.name == 'ActiveStorage::Attachment' && ActiveStorage::Attachment.columns_hash.key?('blob_id')
|
916
959
|
pieces, my_dsl = klass.brick_parse_dsl(join_array = ::Brick::JoinArray.new, [], translations = {}, false, nil, true)
|
917
960
|
brick_select(
|
918
|
-
|
919
|
-
{ '_br' => (descrip_cols = [pieces, my_dsl]) }
|
961
|
+
selects, where_values_hash, nil, translations: translations, join_array: join_array,
|
962
|
+
cust_col_override: { '_br' => (descrip_cols = [pieces, my_dsl]) }
|
920
963
|
)
|
921
|
-
order_values = klass.primary_key
|
964
|
+
order_values = "#{klass.table_name}.#{klass.primary_key}"
|
922
965
|
[self.select(selects), descrip_cols]
|
923
966
|
end
|
924
967
|
|
968
|
+
def brick_uniq
|
969
|
+
begin
|
970
|
+
uniq
|
971
|
+
rescue ActiveModel::MissingAttributeError => e
|
972
|
+
# If this model has an #after_initialize then it might try to reference attributes we haven't brought in
|
973
|
+
if (err_msg = e.message).start_with?('missing attribute: ') &&
|
974
|
+
klass.column_names.include?(col_name = e.message[19..-1])
|
975
|
+
(dup_rel = dup).select_values << col_name
|
976
|
+
ret = dup_rel.brick_uniq
|
977
|
+
puts "*** WARNING: Missing field!
|
978
|
+
Might want to add this in your brick.rb:
|
979
|
+
::Brick.always_load_fields = { #{klass.name.inspect} => [#{col_name.inspect}]}"
|
980
|
+
::Brick.config.always_load_fields[klass.name] << col_name
|
981
|
+
ret
|
982
|
+
else
|
983
|
+
[]
|
984
|
+
end
|
985
|
+
end
|
986
|
+
end
|
987
|
+
|
925
988
|
private
|
926
989
|
|
927
990
|
def shift_or_first(ary)
|
@@ -935,6 +998,8 @@ JOIN (SELECT #{hm_selects.map { |s| "#{'br_t0.' if from_clause}#{s}" }.join(', '
|
|
935
998
|
|
936
999
|
alias _brick_find_sti_class find_sti_class
|
937
1000
|
def find_sti_class(type_name)
|
1001
|
+
return if type_name.is_a?(Numeric)
|
1002
|
+
|
938
1003
|
if ::Brick.sti_models.key?(type_name ||= name)
|
939
1004
|
::Brick.sti_models[type_name].fetch(:base, nil) || _brick_find_sti_class(type_name)
|
940
1005
|
else
|
@@ -1042,7 +1107,7 @@ if ActiveSupport::Dependencies.respond_to?(:autoload_module!) # %%% Only works w
|
|
1042
1107
|
end
|
1043
1108
|
end
|
1044
1109
|
|
1045
|
-
|
1110
|
+
::Brick::ADD_CONST_MISSING = lambda do
|
1046
1111
|
alias _brick_const_missing const_missing
|
1047
1112
|
def const_missing(*args)
|
1048
1113
|
requested = args.first.to_s
|
@@ -1319,7 +1384,14 @@ class Object
|
|
1319
1384
|
if (base_model = ::Brick.sti_models[full_model_name]&.fetch(:base, nil) || ::Brick.existing_stis[full_model_name]&.constantize)
|
1320
1385
|
is_sti = true
|
1321
1386
|
else
|
1322
|
-
|
1387
|
+
# Class for auto-generated models to inherit from
|
1388
|
+
base_model = (::Brick.config.models_inherit_from ||= (app.config.brick.fetch(:models_inherit_from, nil) ||
|
1389
|
+
begin
|
1390
|
+
::ApplicationRecord
|
1391
|
+
rescue StandardError => ex
|
1392
|
+
::ActiveRecord::Base
|
1393
|
+
end))
|
1394
|
+
|
1323
1395
|
end
|
1324
1396
|
hmts = nil
|
1325
1397
|
code = +"class #{full_name} < #{base_model.name}\n"
|
@@ -1486,8 +1558,10 @@ class Object
|
|
1486
1558
|
assoc[:assoc_name]
|
1487
1559
|
end
|
1488
1560
|
options[:optional] = true if assoc.key?(:optional)
|
1489
|
-
if assoc.key?(:polymorphic)
|
1490
|
-
|
1561
|
+
if assoc.key?(:polymorphic) ||
|
1562
|
+
# If a polymorphic association is missing but could be established then go ahead and put it into place.
|
1563
|
+
relations[assoc[:inverse_table]][:class_name].constantize.reflect_on_all_associations.find { |inv_assoc| !inv_assoc.belongs_to? && inv_assoc.options[:as].to_s == assoc[:assoc_name] }
|
1564
|
+
assoc[:polymorphic] ||= (options[:polymorphic] = true)
|
1491
1565
|
else
|
1492
1566
|
need_class_name = singular_table_name.underscore != assoc_name
|
1493
1567
|
need_fk = "#{assoc_name}_id" != assoc[:fk]
|
@@ -1548,7 +1622,11 @@ class Object
|
|
1548
1622
|
assoc[:fk].to_sym
|
1549
1623
|
end
|
1550
1624
|
end
|
1551
|
-
|
1625
|
+
if inverse_assoc_name && (need_class_name || need_fk || need_inverse_of) &&
|
1626
|
+
(klass = options[:class_name]&.constantize) && (ian = inverse_assoc_name.tr('.', '_').to_sym) &&
|
1627
|
+
(klass.is_brick? || klass.reflect_on_association(ian))
|
1628
|
+
options[:inverse_of] = ian
|
1629
|
+
end
|
1552
1630
|
|
1553
1631
|
# Prepare a list of entries for "has_many :through"
|
1554
1632
|
if macro == :has_many
|
@@ -1591,14 +1669,38 @@ class Object
|
|
1591
1669
|
built_controller = Class.new(controller_base || ActionController::Base) do |new_controller_class|
|
1592
1670
|
(namespace || Object).const_set(class_name.to_sym, new_controller_class)
|
1593
1671
|
|
1672
|
+
# Add a hash for the inline style to the content-security-policy if one is present
|
1673
|
+
self.define_method(:add_csp_hash) do |style_value = nil|
|
1674
|
+
if request.respond_to?(:content_security_policy) && (csp = request.content_security_policy)
|
1675
|
+
if (cspd = csp.directives.fetch('style-src'))
|
1676
|
+
if style_value
|
1677
|
+
if (nonce = ::ActionDispatch::ContentSecurityPolicy::Request::NONCE)
|
1678
|
+
request.env[nonce] = '' # Generally 'action_dispatch.content_security_policy_nonce'
|
1679
|
+
end
|
1680
|
+
# Keep only self, if present, and also add this value
|
1681
|
+
cspd.select! { |val| val == "'self'" }
|
1682
|
+
cspd << style_value
|
1683
|
+
else
|
1684
|
+
cspd << "'sha256-QHKxqKcUq7AER1QwEu5uQXRQwC8j4iTWkE8mpOmP7ms='"
|
1685
|
+
end
|
1686
|
+
cspd << 'https://cdn.jsdelivr.net'
|
1687
|
+
end
|
1688
|
+
if (cspd = csp.directives.fetch('script-src'))
|
1689
|
+
cspd << 'https://cdn.jsdelivr.net'
|
1690
|
+
end
|
1691
|
+
end
|
1692
|
+
end
|
1693
|
+
|
1594
1694
|
# Brick-specific pages
|
1595
1695
|
case plural_class_name
|
1596
1696
|
when 'BrickGem'
|
1597
1697
|
self.define_method :status do
|
1598
1698
|
instance_variable_set(:@resources, ::Brick.get_status_of_resources)
|
1699
|
+
add_csp_hash
|
1599
1700
|
end
|
1600
1701
|
self.define_method :orphans do
|
1601
1702
|
instance_variable_set(:@orphans, ::Brick.find_orphans(::Brick.set_db_schema(params).first))
|
1703
|
+
add_csp_hash
|
1602
1704
|
end
|
1603
1705
|
self.define_method :crosstab do
|
1604
1706
|
@relations = ::Brick.relations.each_with_object({}) do |r, s|
|
@@ -1813,9 +1915,9 @@ class Object
|
|
1813
1915
|
|
1814
1916
|
ar_relation = ActiveRecord.version < Gem::Version.new('4') ? real_model.preload : real_model.all
|
1815
1917
|
params['_brick_is_api'] = true if (is_api = request.format == :js || current_api_root)
|
1816
|
-
@_brick_params = ar_relation.brick_select(
|
1817
|
-
translations = {},
|
1818
|
-
join_array = ::Brick::JoinArray.new)
|
1918
|
+
@_brick_params = ar_relation.brick_select((selects ||= []), params: params, order_by: order_by,
|
1919
|
+
translations: (translations = {}),
|
1920
|
+
join_array: (join_array = ::Brick::JoinArray.new))
|
1819
1921
|
|
1820
1922
|
if is_api # Asking for JSON?
|
1821
1923
|
# Apply column renaming
|
@@ -1881,6 +1983,7 @@ class Object
|
|
1881
1983
|
@_brick_hm_counts = real_model._br_hm_counts
|
1882
1984
|
@_brick_join_array = join_array
|
1883
1985
|
@_brick_erd = params['_brick_erd']&.to_i
|
1986
|
+
add_csp_hash
|
1884
1987
|
end
|
1885
1988
|
end
|
1886
1989
|
|
@@ -1911,6 +2014,7 @@ class Object
|
|
1911
2014
|
self.define_method :show do
|
1912
2015
|
_schema, @_is_show_schema_list = ::Brick.set_db_schema(params)
|
1913
2016
|
instance_variable_set("@#{singular_table_name}".to_sym, find_obj)
|
2017
|
+
add_csp_hash("'unsafe-inline'")
|
1914
2018
|
end
|
1915
2019
|
end
|
1916
2020
|
|
@@ -1928,6 +2032,7 @@ class Object
|
|
1928
2032
|
end if Object.const_defined?('ActiveStorage')
|
1929
2033
|
end
|
1930
2034
|
instance_variable_set("@#{singular_table_name}".to_sym, new_obj)
|
2035
|
+
add_csp_hash
|
1931
2036
|
end
|
1932
2037
|
|
1933
2038
|
params_name_sym = (params_name = "#{singular_table_name}_params").to_sym
|
@@ -1968,6 +2073,7 @@ class Object
|
|
1968
2073
|
self.define_method :edit do
|
1969
2074
|
_schema, @_is_show_schema_list = ::Brick.set_db_schema(params)
|
1970
2075
|
instance_variable_set("@#{singular_table_name}".to_sym, find_obj)
|
2076
|
+
add_csp_hash
|
1971
2077
|
end
|
1972
2078
|
|
1973
2079
|
code << " def update\n"
|
@@ -209,10 +209,15 @@ function linkSchemas() {
|
|
209
209
|
# paths['app/models'] << 'lib/brick/frameworks/active_record/models'
|
210
210
|
config.brick = ActiveSupport::OrderedOptions.new
|
211
211
|
ActiveSupport.on_load(:before_initialize) do |app|
|
212
|
+
if ::Rails.application.respond_to?(:reloader)
|
213
|
+
::Rails.application.reloader.to_prepare { Module.class_exec &::Brick::ADD_CONST_MISSING }
|
214
|
+
else # For Rails < 5.0, just load it once at the start
|
215
|
+
Module.class_exec &::Brick::ADD_CONST_MISSING
|
216
|
+
end
|
217
|
+
require 'brick/join_array'
|
212
218
|
is_development = (ENV['RAILS_ENV'] || ENV['RACK_ENV']) == 'development'
|
213
219
|
::Brick.enable_models = app.config.brick.fetch(:enable_models, true)
|
214
220
|
::Brick.enable_controllers = app.config.brick.fetch(:enable_controllers, is_development)
|
215
|
-
require 'brick/join_array' if ::Brick.enable_controllers?
|
216
221
|
::Brick.enable_views = app.config.brick.fetch(:enable_views, is_development)
|
217
222
|
::Brick.enable_routes = app.config.brick.fetch(:enable_routes, is_development)
|
218
223
|
::Brick.skip_database_views = app.config.brick.fetch(:skip_database_views, false)
|
@@ -598,12 +603,14 @@ window.addEventListener(\"popstate\", linkSchemas);
|
|
598
603
|
# ====================================
|
599
604
|
if ::Brick.enable_views?
|
600
605
|
# Add the params to the lookup_context so that we have context about STI classes when setting @_brick_model
|
601
|
-
ActionView
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
606
|
+
if ActionView.const_defined?('ViewPaths')
|
607
|
+
ActionView::ViewPaths.class_exec do
|
608
|
+
alias :_brick_lookup_context :lookup_context
|
609
|
+
def lookup_context(*args)
|
610
|
+
ret = _brick_lookup_context(*args)
|
611
|
+
@_lookup_context.instance_variable_set(:@_brick_req_params, params)
|
612
|
+
ret
|
613
|
+
end
|
607
614
|
end
|
608
615
|
end
|
609
616
|
|
@@ -678,11 +685,11 @@ window.addEventListener(\"popstate\", linkSchemas);
|
|
678
685
|
rescue StandardError => e
|
679
686
|
# Search through the routes to confirm that something might match (Devise stuff for instance, which has its own view templates),
|
680
687
|
# and bubble the same exception (probably an ActionView::MissingTemplate) if a legitimate option is found.
|
681
|
-
raise if ::Rails.application.routes.set.find { |x| args[1].include?(x.defaults[:controller]) && args[0] == x.defaults[:action] }
|
688
|
+
raise if ::Rails.application.routes.set.find { |x| args[1].include?(x.defaults[:controller]) && args[0] == x.defaults[:action] } &&
|
689
|
+
ActionView.version >= ::Gem::Version.new('5.0')
|
682
690
|
|
683
691
|
find_template_err = e
|
684
692
|
end
|
685
|
-
# Used to also have: ActionView.version < ::Gem::Version.new('5.0') &&
|
686
693
|
model_name = set_brick_model(args, @_brick_req_params)&.name
|
687
694
|
end
|
688
695
|
|
@@ -736,11 +743,11 @@ window.addEventListener(\"popstate\", linkSchemas);
|
|
736
743
|
end
|
737
744
|
when 'show', 'new', 'update'
|
738
745
|
hm_stuff << if hm_fk_name
|
739
|
-
if hm_assoc.klass.column_names.include?(hm_fk_name) ||
|
746
|
+
if hm_assoc.klass.column_names.include?(hm_fk_name.to_s) ||
|
740
747
|
(hm_fk_name.is_a?(String) && hm_fk_name.include?('.')) # HMT? (Could do a better check for this)
|
741
748
|
predicates = path_keys(hm_assoc, hm_fk_name, pk).map do |k, v|
|
742
749
|
if v == '[sti_type]'
|
743
|
-
"'#{k}': (@#{obj_name}.#{hm_assoc.active_record.inheritance_column})
|
750
|
+
"'#{k}': (@#{obj_name}.#{hm_assoc.active_record.inheritance_column})&.constantize&.base_class&.name"
|
744
751
|
else
|
745
752
|
v.is_a?(String) ? "'#{k}': '#{v}'" : "'#{k}': @#{obj_name}.#{v}"
|
746
753
|
end
|
@@ -798,6 +805,10 @@ window.addEventListener(\"popstate\", linkSchemas);
|
|
798
805
|
left: 0;
|
799
806
|
}
|
800
807
|
|
808
|
+
.flashNotice {
|
809
|
+
color: green;
|
810
|
+
}
|
811
|
+
|
801
812
|
h1, h3 {
|
802
813
|
margin-bottom: 0;
|
803
814
|
}
|
@@ -1313,7 +1324,7 @@ erDiagram
|
|
1313
1324
|
</head>
|
1314
1325
|
<body>
|
1315
1326
|
<div id=\"titleBox\"><div id=\"titleSticky\">
|
1316
|
-
<p
|
1327
|
+
<p class=\"flashNotice\"><%= notice if request.respond_to?(:flash) %></p>#{"
|
1317
1328
|
#{schema_options}" if schema_options}
|
1318
1329
|
<select id=\"tbl\">#{table_options}</select>
|
1319
1330
|
<table id=\"resourceName\"><tr>
|
@@ -1453,11 +1464,11 @@ end
|
|
1453
1464
|
# Must load all models, and then find what table names are represented
|
1454
1465
|
# Easily could be multiple files involved (STI for instance)
|
1455
1466
|
+"#{css}
|
1456
|
-
<p
|
1467
|
+
<p class=\"flashNotice\"><%= notice if request.respond_to?(:flash) %></p>#{"
|
1457
1468
|
#{schema_options}" if schema_options}
|
1458
1469
|
<select id=\"tbl\">#{table_options}</select>
|
1459
1470
|
<h1>Status</h1>
|
1460
|
-
<table id=\"
|
1471
|
+
<table id=\"resourceName\" class=\"shadow\"><thead><tr>
|
1461
1472
|
<th>Resource</th>
|
1462
1473
|
<th>Table</th>
|
1463
1474
|
<th>Migration</th>
|
@@ -1476,7 +1487,11 @@ end
|
|
1476
1487
|
kls = Object.const_get(::Brick.relations.fetch(r[0], nil)&.fetch(:class_name, nil))
|
1477
1488
|
rescue
|
1478
1489
|
end
|
1479
|
-
kls.is_a?(Class)
|
1490
|
+
if kls.is_a?(Class) && (path_helper = respond_to?(bi_path = \"#\{kls._brick_index}_path\".to_sym) ? bi_path : nil)
|
1491
|
+
link_to(r[0], send(path_helper))
|
1492
|
+
else
|
1493
|
+
r[0]
|
1494
|
+
end %></td>
|
1480
1495
|
<td<%= if r[1]
|
1481
1496
|
' class=\"orphan\"' unless ::Brick.relations.key?(r[1])
|
1482
1497
|
else
|
@@ -1503,7 +1518,7 @@ end
|
|
1503
1518
|
when 'orphans'
|
1504
1519
|
if is_orphans
|
1505
1520
|
+"#{css}
|
1506
|
-
<p
|
1521
|
+
<p class=\"flashNotice\"><%= notice if request.respond_to?(:flash) %></p>#{"
|
1507
1522
|
#{schema_options}" if schema_options}
|
1508
1523
|
<select id=\"tbl\">#{table_options}</select>
|
1509
1524
|
<h1>Orphans<%= \" for #\{}\" if false %></h1>
|
@@ -1536,9 +1551,11 @@ end
|
|
1536
1551
|
base_model = (model = (obj = @#{obj_name})&.class).base_class
|
1537
1552
|
see_all_path = send(\"#\{base_model._brick_index}_path\")
|
1538
1553
|
#{(inh_col = @_brick_model.inheritance_column).present? &&
|
1539
|
-
" if obj.respond_to?(:#{inh_col}) && (model_name = @#{obj_name}.#{inh_col})
|
1554
|
+
" if obj.respond_to?(:#{inh_col}) && (model_name = @#{obj_name}.#{inh_col}) &&
|
1555
|
+
!model_name.is_a?(Numeric) && model_name != base_model.name
|
1540
1556
|
see_all_path << \"?#{inh_col}=#\{model_name}\"
|
1541
|
-
end
|
1557
|
+
end
|
1558
|
+
model_name = base_model.name if model_name.is_a?(Numeric)"}
|
1542
1559
|
page_title = (\"#\{model_name ||= model.name}: #\{obj&.brick_descrip || controller_name}\")
|
1543
1560
|
%></title>
|
1544
1561
|
</head>
|
@@ -1550,7 +1567,7 @@ end
|
|
1550
1567
|
c23.141-70.188,89.141-120.906,167.063-120.906c97.25,0,176,78.813,176,176C511.828,227.078,404.391,119.641,271.844,119.641z\" />
|
1551
1568
|
</svg>
|
1552
1569
|
|
1553
|
-
<p
|
1570
|
+
<p class=\"flashNotice\"><%= notice if request.respond_to?(:flash) %></p>#{"
|
1554
1571
|
#{schema_options}" if schema_options}
|
1555
1572
|
<select id=\"tbl\">#{table_options}</select>
|
1556
1573
|
<table id=\"resourceName\"><td><h1><%= page_title %></h1></td>
|
@@ -1631,7 +1648,7 @@ end
|
|
1631
1648
|
if bt.length < 4
|
1632
1649
|
bt << (option_detail = [[\"(No #\{bt_name\} chosen)\", '^^^brick_NULL^^^']])
|
1633
1650
|
# %%% Accommodate composite keys for obj.pk at the end here
|
1634
|
-
collection, descrip_cols = bt_class&.order(obj_pk = bt_class.primary_key)&.brick_list
|
1651
|
+
collection, descrip_cols = bt_class&.order(Arel.sql(\"#\{bt_class.table_name}.#\{obj_pk = bt_class.primary_key}\"))&.brick_list
|
1635
1652
|
collection&.each do |obj|
|
1636
1653
|
option_detail << [
|
1637
1654
|
obj.brick_descrip(
|
@@ -1712,15 +1729,22 @@ end
|
|
1712
1729
|
else # We get an array back when AR < 4.2
|
1713
1730
|
collection2 = collection.to_a.compact
|
1714
1731
|
end
|
1715
|
-
collection2 = collection2.
|
1732
|
+
collection2 = collection2.brick_uniq
|
1716
1733
|
if collection2.empty? %>
|
1717
1734
|
<tr><td>(none)</td></tr>
|
1718
1735
|
<% else
|
1719
|
-
collection2.each do
|
1720
|
-
<tr><td><%= br_descrip = #{hm_singular_name}.
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1736
|
+
collection2.each do |br_#{hm_singular_name}| %>
|
1737
|
+
<tr><td><%= br_descrip = if br_#{hm_singular_name}.respond_to?(descrip_cols&.first&.first&.last)
|
1738
|
+
br_#{hm_singular_name}.brick_descrip(
|
1739
|
+
descrip_cols&.first&.map { |col| br_#{hm_singular_name}.send(col.last) }
|
1740
|
+
)
|
1741
|
+
else # If the HM association has a scope, might not have picked up our SELECT detail
|
1742
|
+
pks = (klass = br_#{hm_singular_name}.class).primary_key
|
1743
|
+
pks = [pks] unless pks.is_a?(Array)
|
1744
|
+
pks.map! { |pk| br_#{hm_singular_name}.send(pk).to_s }
|
1745
|
+
\"#\{klass.name} ##\{pks.join(', ')}\"
|
1746
|
+
end
|
1747
|
+
link_to(br_descrip, #{hm.first.klass._brick_index(:singular)}_path(slashify(br_#{obj_pk}))) %></td></tr>
|
1724
1748
|
<% end %>
|
1725
1749
|
<% end %>
|
1726
1750
|
</table>"
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -56,7 +56,7 @@ if (is_ruby_2_7 = (ruby_version = ::Gem::Version.new(RUBY_VERSION)) >= ::Gem::Ve
|
|
56
56
|
# end
|
57
57
|
end
|
58
58
|
|
59
|
-
# Add
|
59
|
+
# Add left_outer_joins! to Associations::JoinDependency and Relation::QueryMethods
|
60
60
|
if ActiveRecord.version >= ::Gem::Version.new('4') && ActiveRecord.version < ::Gem::Version.new('5')
|
61
61
|
::Brick::Util._patch_require(
|
62
62
|
'active_record/associations/join_dependency.rb', '/activerecord', # /associations
|
@@ -84,7 +84,7 @@ if ActiveRecord.version >= ::Gem::Version.new('4') && ActiveRecord.version < ::G
|
|
84
84
|
['build_joins(arel, joins_values.flatten) unless joins_values.empty?',
|
85
85
|
"build_joins(arel, joins_values.flatten) unless joins_values.empty?
|
86
86
|
build_left_outer_joins(arel, left_outer_joins_values.flatten) unless left_outer_joins_values.empty?"
|
87
|
-
|
87
|
+
],
|
88
88
|
# Change 2 - Line 992
|
89
89
|
["raise 'unknown class: %s' % join.class.name
|
90
90
|
end
|
@@ -99,8 +99,8 @@ if ActiveRecord.version >= ::Gem::Version.new('4') && ActiveRecord.version < ::G
|
|
99
99
|
def build_join_query(manager, buckets, join_type)"
|
100
100
|
],
|
101
101
|
# Change 3 - Line 1012
|
102
|
-
|
103
|
-
|
102
|
+
['s = join_dependency.join_constraints stashed_association_joins',
|
103
|
+
's = join_dependency.join_constraints stashed_association_joins, join_type'
|
104
104
|
]
|
105
105
|
],
|
106
106
|
:QueryMethods
|
@@ -202,7 +202,11 @@ module Brick
|
|
202
202
|
end
|
203
203
|
end
|
204
204
|
|
205
|
-
def get_bts_and_hms(model)
|
205
|
+
def get_bts_and_hms(model, recalculate = nil)
|
206
|
+
if !recalculate && (ret = model.instance_variable_get(:@_brick_bts_and_hms))
|
207
|
+
return ret
|
208
|
+
end
|
209
|
+
|
206
210
|
model_cols = model.columns_hash
|
207
211
|
pk_type = if (mpk = model.primary_key).is_a?(Array)
|
208
212
|
# Composite keys should really use: model.primary_key.map { |pk_part| model_cols[pk_part].type }
|
@@ -228,8 +232,24 @@ module Brick
|
|
228
232
|
# This will come up when using Devise invitable when invited_by_class_name is not
|
229
233
|
# specified because in that circumstance it adds a polymorphic :invited_by association,
|
230
234
|
# along with appropriate invited_by_type and invited_by_id columns.
|
231
|
-
|
232
|
-
|
235
|
+
|
236
|
+
# See if any currently-loaded models have a has_many association over to this polymorphic belongs_to
|
237
|
+
hm_models = ActiveRecord::Base.descendants.select do |m|
|
238
|
+
m.reflect_on_all_associations.any? { |assoc| !assoc.belongs_to? && assoc.options[:as]&.to_sym == a.name }
|
239
|
+
end
|
240
|
+
# No need to include subclassed models if their parent is already in the list
|
241
|
+
hm_models.reject! { |m| hm_models.any? { |parent| parent != m && m < parent } }
|
242
|
+
if hm_models.empty?
|
243
|
+
puts "Missing any real indication as to which models \"has_many\" this polymorphic BT in model #{a.active_record.name}:"
|
244
|
+
puts " belongs_to :#{a.name}, polymorphic: true"
|
245
|
+
else
|
246
|
+
puts "Having analysed all currently-loaded models to infer the various polymorphic has_many associations for #{model.name}, here are the current results:"
|
247
|
+
puts "::Brick.polymorphics = { \"#{model.table_name}.#{a.name}\" =>
|
248
|
+
#{hm_models.map(&:name).inspect}
|
249
|
+
}"
|
250
|
+
puts 'If you add the above to your brick.rb, it will "cement" these options into place, and avoid this lookup process.'
|
251
|
+
s.first[a.foreign_key.to_s] = [a.name, hm_models, true]
|
252
|
+
end
|
233
253
|
end
|
234
254
|
else
|
235
255
|
bt_key = a.foreign_key.is_a?(Array) ? a.foreign_key : a.foreign_key.to_s
|
@@ -254,7 +274,7 @@ module Brick
|
|
254
274
|
next
|
255
275
|
end
|
256
276
|
else
|
257
|
-
if !a.options.key?(:as) && a.klass.column_names.exclude?(a.foreign_key)
|
277
|
+
if !a.options.key?(:as) && a.klass.column_names.exclude?(a.foreign_key.to_s)
|
258
278
|
options = ", #{a.options.map { |k, v| "#{k.inspect} => #{v.inspect}" }.join(', ')}" if a.options.present?
|
259
279
|
puts "WARNING: Model #{model.name} has this association:
|
260
280
|
has_many :#{a.name}#{options}
|
@@ -279,7 +299,7 @@ module Brick
|
|
279
299
|
end
|
280
300
|
end
|
281
301
|
skip_hms.each { |k, _v| hms.delete(k) }
|
282
|
-
[bts, hms]
|
302
|
+
model.instance_variable_set(:@_brick_bts_and_hms, [bts, hms]) # Cache and return this result
|
283
303
|
end
|
284
304
|
|
285
305
|
def exclude_column(table, col)
|
@@ -523,6 +543,10 @@ module Brick
|
|
523
543
|
Brick.config.license = key
|
524
544
|
end
|
525
545
|
|
546
|
+
def always_load_fields=(field_set)
|
547
|
+
Brick.config.always_load_fields = field_set
|
548
|
+
end
|
549
|
+
|
526
550
|
# Load additional references (virtual foreign keys)
|
527
551
|
# 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
|
528
552
|
# %%% Maybe look for differences the second time 'round and just add new stuff instead of entirely deferring
|
@@ -922,11 +946,19 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
922
946
|
end
|
923
947
|
end
|
924
948
|
|
925
|
-
if ::Brick.config.add_status &&
|
926
|
-
|
949
|
+
if ::Brick.config.add_status && (status_as = "#{controller_prefix.tr('/', '_')}brick_status".to_sym)
|
950
|
+
(
|
951
|
+
!(status_route = instance_variable_get(:@set).named_routes.find { |route| route.first == status_as }&.last) ||
|
952
|
+
!status_route.ast.to_s.include?("/#{controller_prefix}brick_status/")
|
953
|
+
)
|
954
|
+
get("/#{controller_prefix}brick_status", to: 'brick_gem#status', as: status_as.to_s)
|
927
955
|
end
|
928
956
|
|
929
|
-
if ::Brick.config.add_orphans &&
|
957
|
+
if ::Brick.config.add_orphans && (orphans_as = "#{controller_prefix.tr('/', '_')}brick_orphans".to_sym)
|
958
|
+
(
|
959
|
+
!(orphans_route = instance_variable_get(:@set).named_routes.find { |route| route.first == orphans_as }&.last) ||
|
960
|
+
!orphans_route.ast.to_s.include?("/#{controller_prefix}brick_orphans/")
|
961
|
+
)
|
930
962
|
get("/#{controller_prefix}brick_orphans", to: 'brick_gem#orphans', as: 'brick_orphans')
|
931
963
|
end
|
932
964
|
|
@@ -1286,7 +1318,8 @@ ActiveSupport.on_load(:active_record) do
|
|
1286
1318
|
# rubocop:enable Lint/ConstantDefinitionInBlock
|
1287
1319
|
|
1288
1320
|
arsc = ::ActiveRecord::StatementCache
|
1289
|
-
if is_ruby_2_7 &&
|
1321
|
+
if is_ruby_2_7 && arsc.respond_to?(:create) &&
|
1322
|
+
(params = arsc.method(:create).parameters).length == 2 && params.last == [:opt, :block]
|
1290
1323
|
arsc.class_exec do
|
1291
1324
|
def self.create(connection, callable = nil, &block)
|
1292
1325
|
relation = (callable || block).call ::ActiveRecord::StatementCache::Params.new
|
@@ -1379,7 +1412,7 @@ ActiveSupport.on_load(:active_record) do
|
|
1379
1412
|
# def aliased_table_for(table_name, aliased_name, type_caster)
|
1380
1413
|
|
1381
1414
|
class ActiveRecord::Associations::JoinDependency
|
1382
|
-
if JoinBase.instance_method(:initialize).arity
|
1415
|
+
if JoinBase.instance_method(:initialize).arity < 3 # Older ActiveRecord <= 5.1?
|
1383
1416
|
def initialize(base, associations, joins, eager_loading: true)
|
1384
1417
|
araat = ::ActiveRecord::Associations::AliasTracker
|
1385
1418
|
if araat.respond_to?(:create_with_joins) # Rails 5.0 and 5.1
|
@@ -1387,17 +1420,28 @@ ActiveSupport.on_load(:active_record) do
|
|
1387
1420
|
cwj_options << base.type_caster if araat.method(:create_with_joins).arity > 3 # Rails <= 5.1
|
1388
1421
|
@alias_tracker = araat.create_with_joins(*cwj_options)
|
1389
1422
|
@eager_loading = eager_loading # (Unused in Rails 5.0)
|
1390
|
-
|
1423
|
+
elsif araat.respond_to?(:create) # Rails 4.1 and 4.2
|
1391
1424
|
@alias_tracker = araat.create(base.connection, joins)
|
1392
1425
|
@alias_tracker.aliased_table_for(base, base.table_name) # Updates the count for base.table_name to 1
|
1426
|
+
else # Rails 4.0
|
1427
|
+
is_rails_4 = true
|
1428
|
+
@base_klass = base
|
1429
|
+
@table_joins = joins
|
1430
|
+
@join_parts = [JoinBase.new(base)]
|
1431
|
+
@associations = {}
|
1432
|
+
@reflections = []
|
1433
|
+
@alias_tracker = araat.new(base.connection, joins)
|
1434
|
+
@alias_tracker.aliased_name_for(base.table_name) # Updates the count for base.table_name to 1
|
1435
|
+
tree = build(associations)
|
1393
1436
|
end
|
1394
|
-
tree
|
1437
|
+
tree ||= self.class.make_tree associations
|
1395
1438
|
|
1396
1439
|
# Provide a way to find the original relation that this tree is being used for
|
1397
1440
|
# (so that we can maintain a list of links for all tables used in JOINs)
|
1398
1441
|
if (relation = associations.instance_variable_get(:@relation))
|
1399
1442
|
tree.instance_variable_set(:@relation, relation)
|
1400
1443
|
end
|
1444
|
+
return if is_rails_4 # Rails 4.0 doesn't know about the rest
|
1401
1445
|
|
1402
1446
|
@join_root = JoinBase.new base, build(tree, base)
|
1403
1447
|
@join_root.children.each { |child| construct_tables! @join_root, child }
|
@@ -1530,6 +1574,21 @@ if ActiveRecord.version < ::Gem::Version.new('5.2')
|
|
1530
1574
|
end
|
1531
1575
|
end
|
1532
1576
|
|
1577
|
+
# By default the awesome_nested_set gem from CollectiveIdea does not prefix the ORDER BY column with its table name.
|
1578
|
+
# You can see this snag in action in the popular Spree project -- check out the Taxonomy model. Here is a fix:
|
1579
|
+
if Gem::Specification.all_names.find { |g| g.start_with?('awesome_nested_set-') }
|
1580
|
+
require 'awesome_nested_set/columns'
|
1581
|
+
::CollectiveIdea::Acts::NestedSet::Columns.class_exec do
|
1582
|
+
alias _brick_order_column_name order_column_name
|
1583
|
+
def order_column_name
|
1584
|
+
unless (ord_col = _brick_order_column_name).start_with?(tbl_prefix = "#{table_name}.")
|
1585
|
+
ord_col = tbl_prefix << ord_col
|
1586
|
+
end
|
1587
|
+
ord_col
|
1588
|
+
end
|
1589
|
+
end
|
1590
|
+
end
|
1591
|
+
|
1533
1592
|
# The "brick_links" patch -- this finds how every AR chain of association names
|
1534
1593
|
# relates back to an exact table correlation name chosen by AREL when the AST tree is
|
1535
1594
|
# walked. For instance, from a Customer model there could be a join_tree such as
|
@@ -1559,21 +1618,40 @@ module ActiveRecord
|
|
1559
1618
|
_brick_build_join_query(manager, buckets, *args) # , **kwargs)
|
1560
1619
|
end
|
1561
1620
|
|
1562
|
-
else
|
1563
|
-
|
1621
|
+
else # elsif private_instance_methods.include?(:select_association_list)
|
1564
1622
|
alias _brick_select_association_list select_association_list
|
1565
1623
|
def select_association_list(associations, stashed_joins = nil)
|
1566
1624
|
result = _brick_select_association_list(associations, stashed_joins)
|
1567
1625
|
result.instance_variable_set(:@relation, self)
|
1568
1626
|
result
|
1569
1627
|
end
|
1628
|
+
|
1629
|
+
# else # Rails 4.1 ? and older
|
1630
|
+
# alias _brick_build_joins build_joins
|
1631
|
+
# def build_joins(manager, joins)
|
1632
|
+
# result = _brick_build_joins(manager, joins)
|
1633
|
+
# result.instance_variable_set(:@relation, self)
|
1634
|
+
# result
|
1635
|
+
# end
|
1570
1636
|
end
|
1571
1637
|
end
|
1572
1638
|
|
1573
1639
|
# require 'active_record/associations/join_dependency'
|
1574
1640
|
module Associations
|
1575
|
-
#
|
1576
|
-
|
1641
|
+
if self.const_defined?('JoinHelper') # ActiveRecord < 4.1
|
1642
|
+
module JoinHelper
|
1643
|
+
alias _brick_construct_tables construct_tables
|
1644
|
+
def construct_tables
|
1645
|
+
result = _brick_construct_tables
|
1646
|
+
# Capture the table alias name that was chosen
|
1647
|
+
# if (relation = node.instance_variable_get(:@assocs)&.instance_variable_get(:@relation))
|
1648
|
+
# link_path = node.instance_variable_get(:@link_path)
|
1649
|
+
# relation.brick_links[link_path] = result.first.table_alias || result.first.table_name
|
1650
|
+
# end
|
1651
|
+
result
|
1652
|
+
end
|
1653
|
+
end
|
1654
|
+
else # For AR >= 4.2
|
1577
1655
|
class JoinDependency
|
1578
1656
|
# An intelligent .eager_load() and .includes() that creates t0_r0 style aliases only for the columns
|
1579
1657
|
# used in .select(). To enable this behaviour, include the flag :_brick_eager_load as the first
|
@@ -1647,7 +1725,7 @@ module ActiveRecord
|
|
1647
1725
|
associations.map do |name, right|
|
1648
1726
|
reflection = find_reflection base_klass, name
|
1649
1727
|
reflection.check_validity!
|
1650
|
-
reflection.check_eager_loadable!
|
1728
|
+
reflection.check_eager_loadable! if reflection.respond_to?(:check_eager_loadable!) # Used in AR >= 4.2
|
1651
1729
|
|
1652
1730
|
if reflection.polymorphic?
|
1653
1731
|
raise EagerLoadPolymorphicError.new(reflection)
|
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.
|
4
|
+
version: 1.0.140
|
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-05-
|
11
|
+
date: 2023-05-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|