brick 1.0.138 → 1.0.140
Sign up to get free protection for your applications and to get access to all the features.
- 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
|