brick 1.0.100 → 1.0.102
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/extensions.rb +79 -47
- data/lib/brick/frameworks/rails/engine.rb +118 -28
- data/lib/brick/frameworks/rails/form_tags.rb +11 -8
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +255 -60
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 167e29431250efc9170ec3f174cce913584c700ce8405a0d275c63636d04cf81
|
4
|
+
data.tar.gz: 34826b000c093ab4fb8d63edd4509d8244f3d5e3712066489e00076f67ba9704
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0d8d82c98b918c2a6b61c06a636ce60e2c4eaaed32b9556b09984f0b778f624cfb887cf9d82d48042cb75057b1e3688be661c05fa9c79f90052da32d029e1b2
|
7
|
+
data.tar.gz: 53c296598e9bc85ca2afd5456ff02d3c56fde7f79cd6de9f4684c5fcef0ad1be489e6ccda37c26b81a109393de1a10fa70a08d352825e69437ffdcd8b2bb2bfe
|
data/lib/brick/extensions.rb
CHANGED
@@ -119,30 +119,32 @@ module ActiveRecord
|
|
119
119
|
end
|
120
120
|
s << part_sym
|
121
121
|
end
|
122
|
-
if
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
if klass&.column_names.exclude?(parts.last) &&
|
131
|
-
(klass = (orig_class = klass).reflect_on_association(possible_dsl = parts.pop.to_sym)&.klass)
|
132
|
-
if prefix.empty? # Custom columns start with an empty prefix
|
133
|
-
prefix << parts.shift until parts.empty?
|
122
|
+
if first_parts
|
123
|
+
if (parts = prefix + first_parts + [parts[-1]]).length > 1 && klass
|
124
|
+
unless is_polymorphic
|
125
|
+
s = build_array
|
126
|
+
parts[0..-3].each { |v| s = s[v.to_sym] }
|
127
|
+
s[parts[-2]] = nil # unless parts[-2].empty? # Using []= will "hydrate" any missing part(s) in our whole series
|
128
|
+
end
|
129
|
+
translations[parts[0..-2].join('.')] = klass
|
134
130
|
end
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
131
|
+
if klass&.column_names.exclude?(parts.last) &&
|
132
|
+
(klass = (orig_class = klass).reflect_on_association(possible_dsl = parts.pop.to_sym)&.klass)
|
133
|
+
if prefix.empty? # Custom columns start with an empty prefix
|
134
|
+
prefix << parts.shift until parts.empty?
|
135
|
+
end
|
136
|
+
# Expand this entry which refers to an association name
|
137
|
+
members2, dsl2a = klass.brick_parse_dsl(build_array, prefix + [possible_dsl], translations, is_polymorphic, nil, true)
|
138
|
+
members += members2
|
139
|
+
dsl2 << dsl2a
|
140
|
+
dsl3 << dsl2a
|
141
|
+
else
|
142
|
+
dsl2 << "[#{bracket_name}]"
|
143
|
+
if emit_dsl
|
144
|
+
dsl3 << "[#{prefix[1..-1].map { |p| "#{p.to_s}." }.join if prefix.length > 1}#{bracket_name}]"
|
145
|
+
end
|
146
|
+
members << parts
|
144
147
|
end
|
145
|
-
members << parts
|
146
148
|
end
|
147
149
|
bracket_name = nil
|
148
150
|
else
|
@@ -409,7 +411,7 @@ module ActiveRecord
|
|
409
411
|
model._brick_calculate_bts_hms(translations, join_array) if is_add_bts || is_add_hms
|
410
412
|
|
411
413
|
is_postgres = ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
|
412
|
-
is_mysql = ActiveRecord::Base.connection.adapter_name
|
414
|
+
is_mysql = ['Mysql2', 'Trilogy'].include?(ActiveRecord::Base.connection.adapter_name)
|
413
415
|
is_mssql = ActiveRecord::Base.connection.adapter_name == 'SQLServer'
|
414
416
|
is_distinct = nil
|
415
417
|
wheres = {}
|
@@ -446,8 +448,13 @@ module ActiveRecord
|
|
446
448
|
selects << if is_mysql
|
447
449
|
"`#{tbl_no_schema}`.`#{col_name}`#{col_alias}"
|
448
450
|
elsif is_postgres || is_mssql
|
449
|
-
# Postgres can not use DISTINCT with any columns that are XML
|
450
|
-
|
451
|
+
if is_distinct # Postgres can not use DISTINCT with any columns that are XML or JSON
|
452
|
+
cast_as_text = if Brick.relations[klass.table_name]&.[](:cols)&.[](col_name)&.first == 'json'
|
453
|
+
'::jsonb' # Convert JSON to JSONB
|
454
|
+
elsif Brick.relations[klass.table_name]&.[](:cols)&.[](col_name)&.first&.start_with?('xml')
|
455
|
+
'::text' # Convert XML to text
|
456
|
+
end
|
457
|
+
end
|
451
458
|
"\"#{tbl_no_schema}\".\"#{col_name}\"#{cast_as_text}#{col_alias}"
|
452
459
|
elsif col.type # Could be Sqlite or Oracle
|
453
460
|
if col_alias || !(/^[a-z0-9_]+$/ =~ col_name)
|
@@ -552,7 +559,7 @@ module ActiveRecord
|
|
552
559
|
brick_link = rel_dupe.brick_links[sel_col.first]
|
553
560
|
field_tbl_name = brick_link&.split('.')&.last ||
|
554
561
|
# ... so here's a best-effort guess for what the table name might be.
|
555
|
-
rel_dupe.klass.reflect_on_association(sel_col.first)
|
562
|
+
rel_dupe.klass.reflect_on_association(sel_col.first)&.klass&.table_name
|
556
563
|
# If it's Oracle, quote any AREL aliases that had been applied
|
557
564
|
field_tbl_name = "\"#{field_tbl_name}\"" if ::Brick.is_oracle && rel_dupe.brick_links.values.include?(field_tbl_name)
|
558
565
|
|
@@ -631,19 +638,26 @@ module ActiveRecord
|
|
631
638
|
through_sources.map do |a|
|
632
639
|
from_clause << "\n LEFT OUTER JOIN #{a.table_name} br_t#{idx += 1} "
|
633
640
|
from_clause << if (src_ref = a.source_reflection).macro == :belongs_to
|
634
|
-
|
635
|
-
# binding.pry unless nm
|
641
|
+
nm = hmt_assoc.source_reflection.inverse_of&.name
|
636
642
|
link_back << nm
|
637
643
|
"ON br_t#{idx}.id = br_t#{idx - 1}.#{a.foreign_key}"
|
638
644
|
elsif src_ref.options[:as]
|
639
645
|
"ON br_t#{idx}.#{src_ref.type} = '#{src_ref.active_record.name}'" + # "polymorphable_type"
|
640
646
|
" AND br_t#{idx}.#{src_ref.foreign_key} = br_t#{idx - 1}.id"
|
641
647
|
elsif src_ref.options[:source_type]
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
648
|
+
if a == hm.source_reflection
|
649
|
+
print "Skipping #{hm.name} --HMT-> #{hm.source_reflection.name} as it uses source_type in a way which is not yet supported"
|
650
|
+
nix << k
|
651
|
+
bail_out = true
|
652
|
+
break
|
653
|
+
# "ON br_t#{idx}.#{a.foreign_type} = '#{src_ref.options[:source_type]}' AND " \
|
654
|
+
# "br_t#{idx}.#{a.foreign_key} = br_t#{idx - 1}.id"
|
655
|
+
else # Works for HMT through a polymorphic HO
|
656
|
+
link_back << hmt_assoc.source_reflection.inverse_of&.name # Some polymorphic "_able" thing
|
657
|
+
"ON br_t#{idx - 1}.#{a.foreign_type} = '#{src_ref.options[:source_type]}' AND " \
|
658
|
+
"br_t#{idx - 1}.#{a.foreign_key} = br_t#{idx}.id"
|
659
|
+
end
|
660
|
+
else # Standard has_many or has_one
|
647
661
|
# binding.pry unless (
|
648
662
|
nm = hmt_assoc.source_reflection.inverse_of&.name
|
649
663
|
# )
|
@@ -706,12 +720,13 @@ module ActiveRecord
|
|
706
720
|
on_clause << "#{tbl_alias}.#{poly_type} = '#{name}'"
|
707
721
|
end
|
708
722
|
unless from_clause
|
723
|
+
tbl_nm = hm.macro == :has_and_belongs_to_many ? hm.join_table : hm.table_name
|
709
724
|
hm_table_name = if is_mysql
|
710
|
-
"`#{
|
725
|
+
"`#{tbl_nm}`"
|
711
726
|
elsif is_postgres || is_mssql
|
712
|
-
"\"#{(
|
727
|
+
"\"#{(tbl_nm).gsub('.', '"."')}\""
|
713
728
|
else
|
714
|
-
|
729
|
+
tbl_nm
|
715
730
|
end
|
716
731
|
end
|
717
732
|
group_bys = ::Brick.is_oracle || is_mssql ? hm_selects : (1..hm_selects.length).to_a
|
@@ -790,7 +805,7 @@ JOIN (SELECT #{hm_selects.map { |s| "#{'br_t0.' if from_clause}#{s}" }.join(', '
|
|
790
805
|
alias _brick_find_sti_class find_sti_class
|
791
806
|
def find_sti_class(type_name)
|
792
807
|
if ::Brick.sti_models.key?(type_name ||= name)
|
793
|
-
_brick_find_sti_class(type_name)
|
808
|
+
::Brick.sti_models[type_name].fetch(:base, nil) || _brick_find_sti_class(type_name)
|
794
809
|
else
|
795
810
|
# This auto-STI is more of a brute-force approach, building modules where needed
|
796
811
|
# The more graceful alternative is the overload of ActiveSupport::Dependencies#autoload_module! found below
|
@@ -1390,11 +1405,11 @@ class Object
|
|
1390
1405
|
# (More information on https://docs.avohq.io/2.0/controllers.html)
|
1391
1406
|
controller_base = Avo::ResourcesController
|
1392
1407
|
end
|
1393
|
-
table_name = ActiveSupport::Inflector.underscore(plural_class_name)
|
1394
|
-
singular_table_name = ActiveSupport::Inflector.singularize(
|
1408
|
+
table_name = model&.table_name || ActiveSupport::Inflector.underscore(plural_class_name)
|
1409
|
+
singular_table_name = ActiveSupport::Inflector.singularize(ActiveSupport::Inflector.underscore(plural_class_name))
|
1395
1410
|
pk = model&._brick_primary_key(relations.fetch(table_name, nil))
|
1396
1411
|
is_postgres = ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
|
1397
|
-
is_mysql = ActiveRecord::Base.connection.adapter_name
|
1412
|
+
is_mysql = ['Mysql2', 'Trilogy'].include?(ActiveRecord::Base.connection.adapter_name)
|
1398
1413
|
|
1399
1414
|
code = +"class #{class_name} < #{controller_base&.name || 'ApplicationController'}\n"
|
1400
1415
|
built_controller = Class.new(controller_base || ActionController::Base) do |new_controller_class|
|
@@ -1576,7 +1591,6 @@ class Object
|
|
1576
1591
|
order_by, _ = model._brick_calculate_ordering(ordering, true) # Don't do the txt part
|
1577
1592
|
|
1578
1593
|
ar_relation = ActiveRecord.version < Gem::Version.new('4') ? model.preload : model.all
|
1579
|
-
|
1580
1594
|
@_brick_params = ar_relation.brick_select(params, (selects ||= []), order_by,
|
1581
1595
|
translations = {},
|
1582
1596
|
join_array = ::Brick::JoinArray.new)
|
@@ -1592,12 +1606,13 @@ class Object
|
|
1592
1606
|
end
|
1593
1607
|
end
|
1594
1608
|
ar_select = ar_relation.respond_to?(:_select!) ? ar_relation.dup._select!(*selects, *counts) : ar_relation.select(selects + counts)
|
1595
|
-
instance_variable_set("@#{table_name.
|
1596
|
-
|
1609
|
+
instance_variable_set("@#{table_name.split('.').last}".to_sym, ar_select)
|
1610
|
+
table_name_no_schema = singular_table_name.pluralize
|
1611
|
+
if namespace && (idx = lookup_context.prefixes.index(table_name_no_schema))
|
1597
1612
|
lookup_context.prefixes[idx] = "#{namespace.name.underscore}/#{lookup_context.prefixes[idx]}"
|
1598
1613
|
end
|
1599
1614
|
@_brick_excl = session[:_brick_exclude]&.split(',')&.each_with_object([]) do |excl, s|
|
1600
|
-
if (excl_parts = excl.split('.')).first ==
|
1615
|
+
if (excl_parts = excl.split('.')).first == table_name_no_schema
|
1601
1616
|
s << excl_parts.last
|
1602
1617
|
end
|
1603
1618
|
end
|
@@ -1609,6 +1624,18 @@ class Object
|
|
1609
1624
|
end
|
1610
1625
|
|
1611
1626
|
unless is_openapi || is_avo
|
1627
|
+
# Skip showing Bullet gem optimisation messages
|
1628
|
+
if Object.const_defined?('Bullet') && Bullet.respond_to?(:enable?)
|
1629
|
+
around_action :skip_bullet
|
1630
|
+
def skip_bullet
|
1631
|
+
bullet_enabled = Bullet.enable?
|
1632
|
+
Bullet.enable = false
|
1633
|
+
yield
|
1634
|
+
ensure
|
1635
|
+
Bullet.enable = bullet_enabled
|
1636
|
+
end
|
1637
|
+
end
|
1638
|
+
|
1612
1639
|
_, order_by_txt = model._brick_calculate_ordering(default_ordering(table_name, pk)) if pk
|
1613
1640
|
code << " def index\n"
|
1614
1641
|
code << " @#{table_name.pluralize} = #{model.name}#{pk&.present? ? ".order(#{order_by_txt.join(', ')})" : '.all'}\n"
|
@@ -1728,7 +1755,12 @@ class Object
|
|
1728
1755
|
val_part.gsub('^^sl^^', '/')
|
1729
1756
|
end
|
1730
1757
|
end
|
1731
|
-
|
1758
|
+
# Support friendly_id gem
|
1759
|
+
if Object.const_defined?('FriendlyId') && model.instance_variable_get(:@friendly_id_config)
|
1760
|
+
model.friendly.find(id.is_a?(Array) && id.length == 1 ? id.first : id)
|
1761
|
+
else
|
1762
|
+
model.find(id.is_a?(Array) && id.length == 1 ? id.first : id)
|
1763
|
+
end
|
1732
1764
|
end
|
1733
1765
|
end
|
1734
1766
|
|
@@ -1917,7 +1949,7 @@ end.class_exec do
|
|
1917
1949
|
puts "*** In the brick.rb initializer the line \"::Brick.schema_behavior = ...\" refers to schema(s) called #{possible_schemas.map { |s| "\"#{s}\"" }.join(', ')}. No mentioned schema exists. ***"
|
1918
1950
|
end
|
1919
1951
|
end
|
1920
|
-
when 'Mysql2'
|
1952
|
+
when 'Mysql2', 'Trilogy'
|
1921
1953
|
::Brick.default_schema = schema = ActiveRecord::Base.connection.current_database
|
1922
1954
|
when 'OracleEnhanced'
|
1923
1955
|
# ActiveRecord::Base.connection.current_database will be something like "XEPDB1"
|
@@ -2052,7 +2084,7 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
2052
2084
|
# end
|
2053
2085
|
# schema = ::Brick.default_schema # Reset back for this next round of fun
|
2054
2086
|
case ActiveRecord::Base.connection.adapter_name
|
2055
|
-
when 'PostgreSQL', 'Mysql2', 'SQLServer'
|
2087
|
+
when 'PostgreSQL', 'Mysql2', 'Trilogy', 'SQLServer'
|
2056
2088
|
sql = "SELECT kcu1.CONSTRAINT_SCHEMA, kcu1.TABLE_NAME, kcu1.COLUMN_NAME,
|
2057
2089
|
kcu2.CONSTRAINT_SCHEMA AS primary_schema, kcu2.TABLE_NAME AS primary_table, kcu1.CONSTRAINT_NAME AS CONSTRAINT_SCHEMA_FK
|
2058
2090
|
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS rc
|
@@ -197,7 +197,7 @@ function linkSchemas() {
|
|
197
197
|
class BrickTitle
|
198
198
|
def initialize(name, view_component)
|
199
199
|
@vc = view_component
|
200
|
-
@_name = name
|
200
|
+
@_name = name || ''
|
201
201
|
end
|
202
202
|
def to_s
|
203
203
|
@_name.html_safe + @vc.instance_variable_get(:@__vc_helpers)&.link_to_brick(nil,
|
@@ -313,10 +313,10 @@ function linkSchemas() {
|
|
313
313
|
end
|
314
314
|
|
315
315
|
if @_brick_model
|
316
|
-
pk = @_brick_model._brick_primary_key(::Brick.relations.fetch(@_brick_model
|
316
|
+
pk = @_brick_model._brick_primary_key(::Brick.relations.fetch((table_name = @_brick_model.table_name.split('.').last), nil))
|
317
317
|
obj_name = model_name.split('::').last.underscore
|
318
318
|
path_obj_name = @_brick_model._brick_index(:singular)
|
319
|
-
table_name
|
319
|
+
table_name ||= obj_name.pluralize
|
320
320
|
template_link = nil
|
321
321
|
bts, hms = ::Brick.get_bts_and_hms(@_brick_model) # This gets BT and HM and also has_many :through (HMT)
|
322
322
|
hms_columns = [] # Used for 'index'
|
@@ -346,13 +346,16 @@ function linkSchemas() {
|
|
346
346
|
end
|
347
347
|
case args.first
|
348
348
|
when 'index'
|
349
|
-
|
349
|
+
if !skip_klass_hms.key?(assoc_name.to_sym) && (
|
350
|
+
@_brick_model._br_hm_counts.key?(assoc_name) ||
|
351
|
+
@_brick_model._br_bt_descrip.key?(assoc_name) # Will end up here if it's a has_one
|
352
|
+
)
|
350
353
|
hm_entry = +"'#{hm_assoc.name}' => [#{assoc_name.inspect}, "
|
351
|
-
hm_entry << if hm_assoc.macro == :
|
354
|
+
hm_entry << if hm_assoc.macro == :has_one
|
355
|
+
'nil'
|
356
|
+
else # :has_many or :has_and_belongs_to_many
|
352
357
|
# Postgres column names are limited to 63 characters
|
353
358
|
"'" + "b_r_#{assoc_name}_ct"[0..62] + "'"
|
354
|
-
else # has_one
|
355
|
-
'nil'
|
356
359
|
end
|
357
360
|
hm_entry << ", #{path_keys(hm_assoc, hm_fk_name, pk).inspect}]"
|
358
361
|
hms_columns << hm_entry
|
@@ -564,17 +567,65 @@ def hide_bcrypt(val, max_len = 200)
|
|
564
567
|
'(hidden)'
|
565
568
|
else
|
566
569
|
if val.is_a?(String)
|
567
|
-
val =
|
570
|
+
if (val = val.dup.strip).length > max_len
|
571
|
+
if val[0] == '<' # Seems to be HTML?
|
572
|
+
cur_len = 0
|
573
|
+
cur_idx = 0
|
574
|
+
# Find which HTML tags we might be inside so we can apply ending tags to balance
|
575
|
+
element_name = nil
|
576
|
+
in_closing = nil
|
577
|
+
elements = []
|
578
|
+
val.each_char do |ch|
|
579
|
+
case ch
|
580
|
+
when '<'
|
581
|
+
element_name = +''
|
582
|
+
when '/' # First character of tag is '/'?
|
583
|
+
in_closing = true if element_name == ''
|
584
|
+
when '>'
|
585
|
+
if element_name
|
586
|
+
if in_closing
|
587
|
+
if (idx = elements.index { |tag| tag.downcase == element_name.downcase })
|
588
|
+
elements.delete_at(idx)
|
589
|
+
end
|
590
|
+
elsif (tag_name = element_name.split.first).present?
|
591
|
+
elements.unshift(tag_name)
|
592
|
+
end
|
593
|
+
element_name = nil
|
594
|
+
in_closing = nil
|
595
|
+
end
|
596
|
+
else
|
597
|
+
element_name << ch if element_name
|
598
|
+
end
|
599
|
+
cur_idx += 1
|
600
|
+
# Unless it's inside wickets then this is real text content, and see if we're at the limit
|
601
|
+
break if element_name.nil? && ((cur_len += 1) > max_len)
|
602
|
+
end
|
603
|
+
val = val[0..cur_idx]
|
604
|
+
# Somehow still in the middle of an opening tag right at the end? (Should never happen)
|
605
|
+
if !in_closing && (tag_name = element_name&.split&.first)&.present?
|
606
|
+
elements.unshift(tag_name)
|
607
|
+
val << '>'
|
608
|
+
end
|
609
|
+
elements.each do |closing_tag|
|
610
|
+
val << \"</#\{closing_tag}>\"
|
611
|
+
end
|
612
|
+
else # Not HTML, just cut it at the length
|
613
|
+
val = val[0...max_len]
|
614
|
+
end
|
615
|
+
val = \"#\{val}...\"
|
616
|
+
end
|
568
617
|
val = val.dup.force_encoding('UTF-8') unless val.encoding.name == 'UTF-8'
|
618
|
+
val
|
619
|
+
else
|
620
|
+
val.to_s
|
569
621
|
end
|
570
|
-
val
|
571
622
|
end
|
572
623
|
end
|
573
624
|
def display_value(col_type, val)
|
574
625
|
case col_type
|
575
626
|
when 'geometry', 'geography'
|
576
627
|
if Object.const_defined?('RGeo')
|
577
|
-
@is_mysql = ActiveRecord::Base.connection.adapter_name
|
628
|
+
@is_mysql = ['Mysql2', 'Trilogy'].include?(ActiveRecord::Base.connection.adapter_name) if @is_mysql.nil?
|
578
629
|
@is_mssql = ActiveRecord::Base.connection.adapter_name == 'SQLServer' if @is_mssql.nil?
|
579
630
|
val_err = nil
|
580
631
|
if @is_mysql || @is_mssql
|
@@ -608,6 +659,8 @@ def display_value(col_type, val)
|
|
608
659
|
else
|
609
660
|
'(Add RGeo gem to parse geometry detail)'
|
610
661
|
end
|
662
|
+
when :binary
|
663
|
+
display_binary(val) if val
|
611
664
|
else
|
612
665
|
if col_type
|
613
666
|
hide_bcrypt(val)
|
@@ -616,6 +669,40 @@ def display_value(col_type, val)
|
|
616
669
|
end
|
617
670
|
end
|
618
671
|
end
|
672
|
+
|
673
|
+
def image_signatures
|
674
|
+
@image_signatures ||= { \"\\xFF\\xD8\\xFF\\xEE\" => 'jpeg',
|
675
|
+
\"\\xFF\\xD8\\xFF\\xE0\\x00\\x10\\x4A\\x46\\x49\\x46\\x00\\x01\" => 'jpeg',
|
676
|
+
\"\\x89PNG\\r\\n\\x1A\\n\" => 'png',
|
677
|
+
'<svg' => 'svg+xml', # %%% Not yet very good detection for SVG
|
678
|
+
'BM' => 'bmp',
|
679
|
+
'GIF87a' => 'gif',
|
680
|
+
'GIF89a' => 'gif' }
|
681
|
+
end
|
682
|
+
def display_binary(val)
|
683
|
+
if val[0..1] == \"\\x15\\x1C\" # One of those goofy Microsoft OLE containers?
|
684
|
+
package_header_length = val[2..3].bytes.reverse.inject(0) {|m, b| (m << 8) + b }
|
685
|
+
# This will often be just FF FF FF FF
|
686
|
+
# object_size = val[16..19].bytes.reverse.inject(0) {|m, b| (m << 8) + b }
|
687
|
+
friendly_and_class_names = val[20...package_header_length].split(\"\\0\")
|
688
|
+
object_type_name_length = val[package_header_length + 8..package_header_length+11].bytes.reverse.inject(0) {|m, b| (m << 8) + b }
|
689
|
+
friendly_and_class_names << val[package_header_length + 12...package_header_length + 12 + object_type_name_length].strip
|
690
|
+
# friendly_and_class_names will now be something like: ['Bitmap Image', 'Paint.Picture', 'PBrush']
|
691
|
+
real_object_size = val[package_header_length + 20 + object_type_name_length..package_header_length + 23 + object_type_name_length].bytes.reverse.inject(0) {|m, b| (m << 8) + b }
|
692
|
+
object_start = package_header_length + 24 + object_type_name_length
|
693
|
+
val = val[object_start...object_start + real_object_size]
|
694
|
+
end
|
695
|
+
if (signature = image_signatures.find { |k, _v| val[0...k.length] == k })
|
696
|
+
if val.length < 500_000
|
697
|
+
\"<img src=\\\"data:image/#\{signature.last};base64,#\{Base64.encode64(val)}\\\">\"
|
698
|
+
else
|
699
|
+
\"< #\{signature.last} image, #\{val.length} bytes >\"
|
700
|
+
end
|
701
|
+
else
|
702
|
+
\"< Binary, #\{val.length} bytes >\"
|
703
|
+
end
|
704
|
+
end
|
705
|
+
|
619
706
|
# Accommodate composite primary keys that include strings with forward-slash characters
|
620
707
|
def slashify(*vals)
|
621
708
|
vals.map { |val_part| val_part.is_a?(String) ? val_part.gsub('/', '^^sl^^') : val_part }
|
@@ -994,8 +1081,12 @@ erDiagram
|
|
994
1081
|
+"<html>
|
995
1082
|
<head>
|
996
1083
|
#{css}
|
997
|
-
<title
|
998
|
-
|
1084
|
+
<title><% model = #{model_name}
|
1085
|
+
if sub_model = @_brick_params&.fetch(type_col = model.inheritance_column, nil)&.first
|
1086
|
+
model = Object.const_get(sub_model.to_sym)
|
1087
|
+
end
|
1088
|
+
%><%= model.name %><%
|
1089
|
+
if (description = (relation = Brick.relations[model.table_name])&.fetch(:description, nil)).present?
|
999
1090
|
%> - <%= description
|
1000
1091
|
%><% end
|
1001
1092
|
%></title>
|
@@ -1005,15 +1096,15 @@ erDiagram
|
|
1005
1096
|
#{schema_options}" if schema_options}
|
1006
1097
|
<select id=\"tbl\">#{table_options}</select>
|
1007
1098
|
<table id=\"resourceName\"><tr>
|
1008
|
-
<td><h1
|
1099
|
+
<td><h1><%= model.name %></h1></td>
|
1009
1100
|
<td id=\"imgErd\" title=\"Show ERD\"></td>
|
1010
1101
|
<% if Object.const_defined?('Avo') && ::Avo.respond_to?(:railtie_namespace) %>
|
1011
1102
|
<td><%= link_to_brick(
|
1012
1103
|
avo_svg,
|
1013
|
-
{ index_proc: Proc.new do |
|
1014
|
-
::Avo.railtie_routes_url_helpers.send(\"resources_#\{model.
|
1104
|
+
{ index_proc: Proc.new do |avo_model|
|
1105
|
+
::Avo.railtie_routes_url_helpers.send(\"resources_#\{model.model_name.route_key}_path\".to_sym)
|
1015
1106
|
end,
|
1016
|
-
title:
|
1107
|
+
title: \"#\{model.name} in Avo\" }
|
1017
1108
|
) %></td>
|
1018
1109
|
<% end %>
|
1019
1110
|
</tr></table>#{template_link}<%
|
@@ -1025,13 +1116,13 @@ erDiagram
|
|
1025
1116
|
<% if @_brick_params.length == 1 # %%% Does not yet work with composite keys
|
1026
1117
|
k, id = @_brick_params.first
|
1027
1118
|
id = id.first if id.is_a?(Array) && id.length == 1
|
1028
|
-
origin = (key_parts = k.split('.')).length == 1 ?
|
1119
|
+
origin = (key_parts = k.split('.')).length == 1 ? model : model.reflect_on_association(key_parts.first).klass
|
1029
1120
|
if (destination_fk = Brick.relations[origin.table_name][:fks].values.find { |fk| fk[:fk] == key_parts.last }) &&
|
1030
1121
|
(obj = (destination = origin.reflect_on_association(destination_fk[:assoc_name])&.klass)&.find(id)) %>
|
1031
1122
|
<h3>for <%= link_to \"#{"#\{obj.brick_descrip\} (#\{destination.name\})\""}, send(\"#\{destination._brick_index(:singular)\}_path\".to_sym, id) %></h3><%
|
1032
1123
|
end
|
1033
1124
|
end %>
|
1034
|
-
(<%= link_to
|
1125
|
+
(<%= link_to \"See all #\{model.base_class.name.split('::').last.pluralize}\", #{@_brick_model._brick_index}_path %>)
|
1035
1126
|
<% end
|
1036
1127
|
# COLUMN EXCLUSIONS
|
1037
1128
|
if @_brick_excl&.present? %>
|
@@ -1058,10 +1149,10 @@ erDiagram
|
|
1058
1149
|
end.join(', ')}}
|
1059
1150
|
|
1060
1151
|
# If the resource is missing, has the user simply created an inappropriately pluralised name for a table?
|
1061
|
-
@#{table_name} ||= if dym_list = instance_variables.reject do |entry|
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1152
|
+
@#{table_name} ||= if (dym_list = instance_variables.reject do |entry|
|
1153
|
+
entry.to_s.start_with?('@_') ||
|
1154
|
+
['@cache_hit', '@marked_for_same_origin_verification', '@view_renderer', '@view_flow', '@output_buffer', '@virtual_path'].include?(entry.to_s)
|
1155
|
+
end).present?
|
1065
1156
|
msg = \"Can't find resource \\\"#{table_name}\\\".\"
|
1066
1157
|
# Can't be sure otherwise of what is up, so check DidYouMean and offer a suggestion.
|
1067
1158
|
if (dym = DidYouMean::SpellChecker.new(dictionary: dym_list).correct('@#{table_name}')).present?
|
@@ -1078,7 +1169,7 @@ erDiagram
|
|
1078
1169
|
|
1079
1170
|
# Write out the mega-grid
|
1080
1171
|
brick_grid(@#{table_name}, @_brick_bt_descrip, @_brick_sequence, @_brick_incl, @_brick_excl,
|
1081
|
-
|
1172
|
+
cols, poly_cols, bts, #{hms_keys.inspect}, {#{hms_columns.join(', ')}}) %>
|
1082
1173
|
|
1083
1174
|
#{"<hr><%= link_to \"New #{obj_name}\", new_#{path_obj_name}_path %>" unless @_brick_model.is_view?}
|
1084
1175
|
#{script}
|
@@ -1521,11 +1612,10 @@ document.querySelectorAll(\"input, select\").forEach(function (inp) {
|
|
1521
1612
|
private
|
1522
1613
|
|
1523
1614
|
alias _brick_render_template render_template
|
1524
|
-
def render_template(view, template, *args)
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
end
|
1615
|
+
def render_template(view, template, layout_name, *args)
|
1616
|
+
layout_name = nil if (is_brick = template.instance_variable_get(:@is_brick)) && layout_name.is_a?(Proc)
|
1617
|
+
result = _brick_render_template(view, template, layout_name, *args)
|
1618
|
+
Apartment::Tenant.switch!(::Brick.apartment_default_tenant) if is_brick && ::Brick.apartment_multitenant
|
1529
1619
|
result
|
1530
1620
|
end
|
1531
1621
|
end # TemplateRenderer
|
@@ -3,7 +3,7 @@ module Brick::Rails::FormTags
|
|
3
3
|
def brick_grid(relation, bt_descrip, sequence = nil, inclusions, exclusions,
|
4
4
|
cols, poly_cols, bts, hms_keys, hms_cols)
|
5
5
|
out = "<table id=\"headerTop\"></table>
|
6
|
-
<table id=\"#{relation.table_name}\" class=\"shadow\">
|
6
|
+
<table id=\"#{relation.table_name.split('.').last}\" class=\"shadow\">
|
7
7
|
<thead><tr>"
|
8
8
|
pk = (klass = relation.klass).primary_key || []
|
9
9
|
pk = [pk] unless pk.is_a?(Array)
|
@@ -11,7 +11,7 @@ module Brick::Rails::FormTags
|
|
11
11
|
out << "<th x-order=\"#{pk.join(',')}\"></th>"
|
12
12
|
end
|
13
13
|
|
14
|
-
col_keys
|
14
|
+
col_keys = relation.columns.each_with_object([]) do |col, s|
|
15
15
|
col_name = col.name
|
16
16
|
next if inclusions&.exclude?(col_name) ||
|
17
17
|
(pk.include?(col_name) && [:integer, :uuid].include?(col.type) && !bts.key?(col_name)) ||
|
@@ -39,8 +39,10 @@ module Brick::Rails::FormTags
|
|
39
39
|
"#{' x-order="' + col_name + '"' if true}>#{col_name}"
|
40
40
|
end
|
41
41
|
elsif col # HM column
|
42
|
+
options = {}
|
43
|
+
options[col[1].inheritance_column] = col[1].name unless col[1] == col[1].base_class
|
42
44
|
s << "<th#{' x-order="' + col_name + '"' if true}>#{col[2]} "
|
43
|
-
s << (col.first ? "#{col[3]}" : "#{link_to(col[3], send("#{col[1]._brick_index}_path"))}")
|
45
|
+
s << (col.first ? "#{col[3]}" : "#{link_to(col[3], send("#{col[1]._brick_index}_path", options))}")
|
44
46
|
elsif cust_cols.key?(col_name) # Custom column
|
45
47
|
s << "<th x-order=\"#{col_name}\">#{col_name}"
|
46
48
|
elsif col_name.is_a?(Symbol) && (hot = bts[col_name]) # has_one :through
|
@@ -88,6 +90,7 @@ module Brick::Rails::FormTags
|
|
88
90
|
# 0..62 because Postgres column names are limited to 63 characters
|
89
91
|
obj, descrips[0..-2].map { |id| obj.send(id.last[0..62]) }, bt_id_col
|
90
92
|
)
|
93
|
+
bt_txt = display_binary(bt_txt).html_safe if bt_txt&.encoding&.name == 'ASCII-8BIT'
|
91
94
|
bt_txt ||= "<span class=\"orphan\"><< Orphaned ID: #{val} >></span>" if val
|
92
95
|
bt_id = bt_id_col&.map { |id_col| obj.respond_to?(id_sym = id_col.to_sym) ? obj.send(id_sym) : id_col }
|
93
96
|
out << (bt_id&.first ? link_to(bt_txt, send("#{bt_class.base_class._brick_index(:singular)}_path".to_sym, bt_id)) : bt_txt || '')
|
@@ -96,17 +99,17 @@ module Brick::Rails::FormTags
|
|
96
99
|
if hms_col.length == 1
|
97
100
|
out << hms_col.first
|
98
101
|
else
|
99
|
-
|
102
|
+
hm_klass = (col = cols[col_name])[1]
|
100
103
|
if col[2] == 'HO'
|
101
|
-
descrips = bt_descrip[col_name.to_sym][
|
104
|
+
descrips = bt_descrip[col_name.to_sym][hm_klass]
|
102
105
|
if (ho_id = (ho_id_col = descrips.last).map { |id_col| obj.send(id_col.to_sym) })&.first
|
103
|
-
ho_txt =
|
104
|
-
out << link_to(ho_txt, send("#{
|
106
|
+
ho_txt = hm_klass.brick_descrip(obj, descrips[0..-2].map { |id| obj.send(id.last[0..62]) }, ho_id_col)
|
107
|
+
out << link_to(ho_txt, send("#{hm_klass.base_class._brick_index(:singular)}_path".to_sym, ho_id))
|
105
108
|
end
|
106
109
|
else
|
107
110
|
if (ct = obj.send(hms_col[1].to_sym)&.to_i)&.positive?
|
108
111
|
out << "#{link_to("#{ct || 'View'} #{hms_col.first}",
|
109
|
-
send("#{
|
112
|
+
send("#{hm_klass._brick_index}_path".to_sym,
|
110
113
|
hms_col[2].each_with_object({}) { |v, s| s[v.first] = v.last.is_a?(String) ? v.last : obj.send(v.last) })
|
111
114
|
)}\n"
|
112
115
|
end
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -26,7 +26,7 @@ end
|
|
26
26
|
require 'brick/util'
|
27
27
|
|
28
28
|
# Allow ActiveRecord < 3.2 to work with Ruby 2.7 and later
|
29
|
-
if (ruby_version = ::Gem::Version.new(RUBY_VERSION)) >= ::Gem::Version.new('2.7')
|
29
|
+
if (is_ruby_2_7 = (ruby_version = ::Gem::Version.new(RUBY_VERSION)) >= ::Gem::Version.new('2.7'))
|
30
30
|
if ActiveRecord.version < ::Gem::Version.new('3.2')
|
31
31
|
# Remove circular reference for "now"
|
32
32
|
::Brick::Util._patch_require(
|
@@ -640,50 +640,62 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
640
640
|
table_class_length = 38 # Length of "Classes that can be built from tables:"
|
641
641
|
view_class_length = 37 # Length of "Classes that can be built from views:"
|
642
642
|
|
643
|
-
brick_routes_create = lambda do |schema_name,
|
643
|
+
brick_routes_create = lambda do |schema_name, res_name, options|
|
644
644
|
if schema_name # && !Object.const_defined('Apartment')
|
645
645
|
send(:namespace, schema_name) do
|
646
|
-
send(:resources,
|
646
|
+
send(:resources, res_name.to_sym, **options)
|
647
647
|
end
|
648
648
|
else
|
649
|
-
send(:resources,
|
649
|
+
send(:resources, res_name.to_sym, **options)
|
650
650
|
end
|
651
651
|
end
|
652
652
|
|
653
653
|
# %%% TODO: If no auto-controllers then enumerate the controllers folder in order to build matching routes
|
654
654
|
# If auto-controllers and auto-models are both enabled then this makes sense:
|
655
655
|
controller_prefix = (path_prefix ? "#{path_prefix}/" : '')
|
656
|
+
sti_subclasses = ::Brick.config.sti_namespace_prefixes.each_with_object(Hash.new { |h, k| h[k] = [] }) do |v, s|
|
657
|
+
# Turn something like {"::Spouse"=>"Person", "::Friend"=>"Person"} into {"Person"=>["Spouse", "Friend"]}
|
658
|
+
s[v.last] << v.first[2..-1] unless v.first.end_with?('::')
|
659
|
+
end
|
656
660
|
::Brick.relations.each do |k, v|
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
661
|
+
next if !(controller_name = v.fetch(:resource, nil)&.pluralize) || existing_controllers.key?(controller_name)
|
662
|
+
|
663
|
+
options = {}
|
664
|
+
options[:only] = [:index, :show] if v.key?(:isView)
|
665
|
+
# First do the API routes
|
666
|
+
full_resource = nil
|
667
|
+
if (schema_name = v.fetch(:schema, nil))
|
668
|
+
full_resource = "#{schema_name}/#{v[:resource]}"
|
669
|
+
send(:get, "#{::Brick.api_root}#{full_resource}", { to: "#{controller_prefix}#{schema_name}/#{controller_name}#index" }) if Object.const_defined?('Rswag::Ui')
|
670
|
+
else
|
671
|
+
# Normally goes to something like: /api/v1/employees
|
672
|
+
send(:get, "#{::Brick.api_root}#{v[:resource]}", { to: "#{controller_prefix}#{controller_name}#index" }) if Object.const_defined?('Rswag::Ui')
|
673
|
+
end
|
674
|
+
|
675
|
+
# Track routes being built
|
676
|
+
if (class_name = v.fetch(:class_name, nil))
|
677
|
+
if v.key?(:isView)
|
678
|
+
view_class_length = class_name.length if class_name.length > view_class_length
|
679
|
+
views
|
665
680
|
else
|
666
|
-
|
667
|
-
|
668
|
-
end
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
681
|
+
table_class_length = class_name.length if class_name.length > table_class_length
|
682
|
+
tables
|
683
|
+
end << [class_name, full_resource || v[:resource]]
|
684
|
+
end
|
685
|
+
|
686
|
+
# Now the normal routes
|
687
|
+
if path_prefix
|
688
|
+
# Was: send(:scope, path: path_prefix) do
|
689
|
+
send(:namespace, path_prefix) do
|
690
|
+
brick_routes_create.call(schema_name, v[:resource], options)
|
691
|
+
sti_subclasses.fetch(class_name, nil)&.each do |sc| # Add any STI subclass routes for this relation
|
692
|
+
brick_routes_create.call(schema_name, sc.underscore.tr('/', '_').pluralize, options)
|
674
693
|
end
|
675
|
-
else
|
676
|
-
brick_routes_create.call(schema_name, controller_name, v, options)
|
677
694
|
end
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
views
|
683
|
-
else
|
684
|
-
table_class_length = class_name.length if class_name.length > table_class_length
|
685
|
-
tables
|
686
|
-
end << [class_name, full_resource || v[:resource]]
|
695
|
+
else
|
696
|
+
brick_routes_create.call(schema_name, v[:resource], options)
|
697
|
+
sti_subclasses.fetch(class_name, nil)&.each do |sc| # Add any STI subclass routes for this relation
|
698
|
+
brick_routes_create.call(schema_name, sc.underscore.tr('/', '_').pluralize, options)
|
687
699
|
end
|
688
700
|
end
|
689
701
|
end
|
@@ -1031,6 +1043,18 @@ ActiveSupport.on_load(:active_record) do
|
|
1031
1043
|
end
|
1032
1044
|
# rubocop:enable Lint/ConstantDefinitionInBlock
|
1033
1045
|
|
1046
|
+
arsc = ::ActiveRecord::StatementCache
|
1047
|
+
if is_ruby_2_7 && (params = arsc.method(:create).parameters).length == 2 && params.last == [:opt, :block]
|
1048
|
+
arsc.class_exec do
|
1049
|
+
def self.create(connection, callable = nil, &block)
|
1050
|
+
relation = (callable || block).call ::ActiveRecord::StatementCache::Params.new
|
1051
|
+
bind_map = ::ActiveRecord::StatementCache::BindMap.new relation.bound_attributes
|
1052
|
+
query_builder = connection.cacheable_query(self, relation.arel)
|
1053
|
+
new query_builder, bind_map
|
1054
|
+
end
|
1055
|
+
end
|
1056
|
+
end
|
1057
|
+
|
1034
1058
|
# Rails < 4.2 is not innately compatible with Ruby 2.4 and later, and comes up with:
|
1035
1059
|
# "TypeError: Cannot visit Integer" unless we patch like this:
|
1036
1060
|
if ruby_version >= ::Gem::Version.new('2.4') &&
|
@@ -1069,11 +1093,54 @@ ActiveSupport.on_load(:active_record) do
|
|
1069
1093
|
end
|
1070
1094
|
end
|
1071
1095
|
|
1096
|
+
if Psych.respond_to?(:unsafe_load) && ActiveRecord.version < ::Gem::Version.new('6.1')
|
1097
|
+
Psych.class_exec do
|
1098
|
+
class << self
|
1099
|
+
alias _original_load load
|
1100
|
+
def load(yaml, *args, **kwargs)
|
1101
|
+
if caller.first.end_with?("`database_configuration'") && kwargs[:aliases].nil?
|
1102
|
+
kwargs[:aliases] = true
|
1103
|
+
end
|
1104
|
+
_original_load(yaml, *args, **kwargs)
|
1105
|
+
end
|
1106
|
+
end
|
1107
|
+
end
|
1108
|
+
end
|
1109
|
+
|
1110
|
+
# def aliased_table_for(arel_table, table_name = nil)
|
1111
|
+
# table_name ||= arel_table.name
|
1112
|
+
|
1113
|
+
# if aliases[table_name] == 0
|
1114
|
+
# # If it's zero, we can have our table_name
|
1115
|
+
# aliases[table_name] = 1
|
1116
|
+
# arel_table = arel_table.alias(table_name) if arel_table.name != table_name
|
1117
|
+
# else
|
1118
|
+
# # Otherwise, we need to use an alias
|
1119
|
+
# aliased_name = @connection.table_alias_for(yield)
|
1120
|
+
|
1121
|
+
# # Update the count
|
1122
|
+
# count = aliases[aliased_name] += 1
|
1123
|
+
|
1124
|
+
# aliased_name = "#{truncate(aliased_name)}_#{count}" if count > 1
|
1125
|
+
|
1126
|
+
# arel_table = arel_table.alias(aliased_name)
|
1127
|
+
# end
|
1128
|
+
|
1129
|
+
# arel_table
|
1130
|
+
# end
|
1131
|
+
# def aliased_table_for(table_name, aliased_name, type_caster)
|
1132
|
+
|
1072
1133
|
class ActiveRecord::Associations::JoinDependency
|
1073
|
-
if JoinBase.instance_method(:initialize).arity == 2 # Older ActiveRecord
|
1074
|
-
def initialize(base, associations, joins)
|
1075
|
-
|
1076
|
-
|
1134
|
+
if JoinBase.instance_method(:initialize).arity == 2 # Older ActiveRecord <= 5.1?
|
1135
|
+
def initialize(base, associations, joins, eager_loading: true)
|
1136
|
+
araat = ::ActiveRecord::Associations::AliasTracker
|
1137
|
+
if araat.respond_to?(:create_with_joins) # Rails 5.0 and 5.1
|
1138
|
+
@alias_tracker = araat.create_with_joins(base.connection, base.table_name, joins)
|
1139
|
+
@eager_loading = eager_loading # (Unused in Rails 5.0)
|
1140
|
+
else # Rails 4.2
|
1141
|
+
@alias_tracker = araat.create(base.connection, joins)
|
1142
|
+
@alias_tracker.aliased_table_for(base, base.table_name) # Updates the count for base.table_name to 1
|
1143
|
+
end
|
1077
1144
|
tree = self.class.make_tree associations
|
1078
1145
|
|
1079
1146
|
# Provide a way to find the original relation that this tree is being used for
|
@@ -1086,7 +1153,7 @@ ActiveSupport.on_load(:active_record) do
|
|
1086
1153
|
@join_root.children.each { |child| construct_tables! @join_root, child }
|
1087
1154
|
end
|
1088
1155
|
|
1089
|
-
else # For ActiveRecord 5.
|
1156
|
+
else # For ActiveRecord 5.2 - 7.1
|
1090
1157
|
|
1091
1158
|
def initialize(base, table, associations, join_type = nil)
|
1092
1159
|
tree = self.class.make_tree associations
|
@@ -1233,13 +1300,13 @@ module ActiveRecord
|
|
1233
1300
|
|
1234
1301
|
if private_instance_methods.include?(:build_join_query)
|
1235
1302
|
alias _brick_build_join_query build_join_query
|
1236
|
-
def build_join_query(manager, buckets, *args)
|
1303
|
+
def build_join_query(manager, buckets, *args) # , **kwargs)
|
1237
1304
|
# %%% Better way to bring relation into the mix
|
1238
1305
|
if (aj = buckets.fetch(:association_join, nil))
|
1239
1306
|
aj.instance_variable_set(:@relation, self)
|
1240
1307
|
end
|
1241
1308
|
|
1242
|
-
_brick_build_join_query(manager, buckets, *args)
|
1309
|
+
_brick_build_join_query(manager, buckets, *args) # , **kwargs)
|
1243
1310
|
end
|
1244
1311
|
|
1245
1312
|
else
|
@@ -1322,24 +1389,26 @@ module ActiveRecord
|
|
1322
1389
|
private
|
1323
1390
|
|
1324
1391
|
# %%% Pretty much have to flat-out replace this guy (I think anyway)
|
1325
|
-
# Good with Rails 5.24
|
1326
|
-
|
1327
|
-
|
1328
|
-
associations
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1392
|
+
# Good with Rails 5.24 through 7 on this
|
1393
|
+
# Ransack gem includes Polyamorous which replaces #build in a different way (which we handle below)
|
1394
|
+
unless Gem::Specification.all_names.any? { |g| g.start_with?('ransack-') }
|
1395
|
+
def build(associations, base_klass, root = nil, path = '')
|
1396
|
+
root ||= associations
|
1397
|
+
associations.map do |name, right|
|
1398
|
+
reflection = find_reflection base_klass, name
|
1399
|
+
reflection.check_validity!
|
1400
|
+
reflection.check_eager_loadable!
|
1401
|
+
|
1402
|
+
if reflection.polymorphic?
|
1403
|
+
raise EagerLoadPolymorphicError.new(reflection)
|
1404
|
+
end
|
1336
1405
|
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1406
|
+
link_path = path.blank? ? name.to_s : path + ".#{name}"
|
1407
|
+
ja = JoinAssociation.new(reflection, build(right, reflection.klass, root, link_path))
|
1408
|
+
ja.instance_variable_set(:@link_path, link_path) # Make note on the JoinAssociation of its AR path
|
1409
|
+
ja.instance_variable_set(:@assocs, root)
|
1410
|
+
ja
|
1411
|
+
end
|
1343
1412
|
end
|
1344
1413
|
end
|
1345
1414
|
|
@@ -1348,10 +1417,9 @@ module ActiveRecord
|
|
1348
1417
|
alias _brick_table_aliases_for table_aliases_for
|
1349
1418
|
def table_aliases_for(parent, node)
|
1350
1419
|
result = _brick_table_aliases_for(parent, node)
|
1351
|
-
|
1352
1420
|
# Capture the table alias name that was chosen
|
1353
|
-
link_path = node.instance_variable_get(:@link_path)
|
1354
1421
|
if (relation = node.instance_variable_get(:@assocs)&.instance_variable_get(:@relation))
|
1422
|
+
link_path = node.instance_variable_get(:@link_path)
|
1355
1423
|
relation.brick_links[link_path] = result.first.table_alias || result.first.table_name
|
1356
1424
|
end
|
1357
1425
|
result
|
@@ -1360,11 +1428,14 @@ module ActiveRecord
|
|
1360
1428
|
alias _brick_make_constraints make_constraints
|
1361
1429
|
def make_constraints(parent, child, join_type)
|
1362
1430
|
result = _brick_make_constraints(parent, child, join_type)
|
1363
|
-
|
1364
1431
|
# Capture the table alias name that was chosen
|
1365
|
-
link_path = child.instance_variable_get(:@link_path)
|
1366
1432
|
if (relation = child.instance_variable_get(:@assocs)&.instance_variable_get(:@relation))
|
1367
|
-
|
1433
|
+
link_path = child.instance_variable_get(:@link_path)
|
1434
|
+
relation.brick_links[link_path] = if child.table.is_a?(Arel::Nodes::TableAlias)
|
1435
|
+
child.table.right
|
1436
|
+
else
|
1437
|
+
result.first&.left&.table_alias || child.table_name
|
1438
|
+
end
|
1368
1439
|
end
|
1369
1440
|
result
|
1370
1441
|
end
|
@@ -1374,4 +1445,128 @@ module ActiveRecord
|
|
1374
1445
|
end
|
1375
1446
|
end
|
1376
1447
|
|
1448
|
+
# Now the Ransack Polyamorous version of #build
|
1449
|
+
if Gem::Specification.all_names.any? { |g| g.start_with?('ransack-') }
|
1450
|
+
require "polyamorous/activerecord_#{::ActiveRecord::VERSION::STRING[0, 3]}_ruby_2/join_dependency"
|
1451
|
+
module Polyamorous::JoinDependencyExtensions
|
1452
|
+
def build(associations, base_klass, root = nil, path = '')
|
1453
|
+
root ||= associations
|
1454
|
+
puts associations.map(&:first)
|
1455
|
+
|
1456
|
+
associations.map do |name, right|
|
1457
|
+
link_path = path.blank? ? name.to_s : path + ".#{name}"
|
1458
|
+
ja = if name.is_a? ::Polyamorous::Join
|
1459
|
+
reflection = find_reflection base_klass, name.name
|
1460
|
+
reflection.check_validity!
|
1461
|
+
reflection.check_eager_loadable!
|
1462
|
+
|
1463
|
+
klass = if reflection.polymorphic?
|
1464
|
+
name.klass || base_klass
|
1465
|
+
else
|
1466
|
+
reflection.klass
|
1467
|
+
end
|
1468
|
+
::ActiveRecord::Associations::JoinDependency::JoinAssociation.new(
|
1469
|
+
reflection, build(right, klass, root, link_path), name.klass, name.type
|
1470
|
+
)
|
1471
|
+
else
|
1472
|
+
reflection = find_reflection base_klass, name
|
1473
|
+
reflection.check_validity!
|
1474
|
+
reflection.check_eager_loadable!
|
1475
|
+
|
1476
|
+
if reflection.polymorphic?
|
1477
|
+
raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
|
1478
|
+
end
|
1479
|
+
::ActiveRecord::Associations::JoinDependency::JoinAssociation.new(
|
1480
|
+
reflection, build(right, reflection.klass, root, link_path)
|
1481
|
+
)
|
1482
|
+
end
|
1483
|
+
ja.instance_variable_set(:@link_path, link_path) # Make note on the JoinAssociation of its AR path
|
1484
|
+
ja.instance_variable_set(:@assocs, root)
|
1485
|
+
ja
|
1486
|
+
end
|
1487
|
+
end
|
1488
|
+
end
|
1489
|
+
end
|
1490
|
+
|
1491
|
+
# Keyword arguments updates for Rails <= 5.2.x and Ruby >= 3.0
|
1492
|
+
if ActiveRecord.version < ::Gem::Version.new('6.0') && ruby_version >= ::Gem::Version.new('3.0')
|
1493
|
+
admsm = ActionDispatch::MiddlewareStack::Middleware
|
1494
|
+
admsm.class_exec do
|
1495
|
+
# redefine #build
|
1496
|
+
def build(app, **kwargs)
|
1497
|
+
# puts klass.name
|
1498
|
+
if args.length > 1 && args.last.is_a?(Hash)
|
1499
|
+
kwargs.merge!(args.pop)
|
1500
|
+
end
|
1501
|
+
# binding.pry if klass == ActionDispatch::Static # ActionDispatch::Reloader
|
1502
|
+
klass.new(app, *args, **kwargs, &block)
|
1503
|
+
end
|
1504
|
+
end
|
1505
|
+
|
1506
|
+
require 'active_model'
|
1507
|
+
require 'active_model/type'
|
1508
|
+
require 'active_model/type/value'
|
1509
|
+
class ActiveModel::Type::Value
|
1510
|
+
def initialize(*args, precision: nil, limit: nil, scale: nil)
|
1511
|
+
@precision = precision
|
1512
|
+
@scale = scale
|
1513
|
+
@limit = limit
|
1514
|
+
end
|
1515
|
+
end
|
1516
|
+
|
1517
|
+
if Object.const_defined?('I18n')
|
1518
|
+
module I18n::Base
|
1519
|
+
alias _brick_translate translate
|
1520
|
+
def translate(key = nil, *args, throw: false, raise: false, locale: nil, **options)
|
1521
|
+
options.merge!(args.pop) if args.length > 0 && args.last.is_a?(Hash)
|
1522
|
+
_brick_translate(key = nil, throw: false, raise: false, locale: nil, **options)
|
1523
|
+
end
|
1524
|
+
end
|
1525
|
+
end
|
1526
|
+
|
1527
|
+
module ActionController::RequestForgeryProtection
|
1528
|
+
private
|
1529
|
+
|
1530
|
+
# Creates the authenticity token for the current request.
|
1531
|
+
def form_authenticity_token(*args, form_options: {}) # :doc:
|
1532
|
+
form_options.merge!(args.pop) if args.length > 0 && args.last.is_a?(Hash)
|
1533
|
+
masked_authenticity_token(session, form_options: form_options)
|
1534
|
+
end
|
1535
|
+
end
|
1536
|
+
|
1537
|
+
module ActiveSupport
|
1538
|
+
class MessageEncryptor
|
1539
|
+
def encrypt_and_sign(value, *args, expires_at: nil, expires_in: nil, purpose: nil)
|
1540
|
+
encrypted = if method(:_encrypt).arity == 1
|
1541
|
+
_encrypt(value) # Rails <= 5.1
|
1542
|
+
else
|
1543
|
+
if args.length > 0 && args.last.is_a?(Hash)
|
1544
|
+
expires_at ||= args.last[:expires_at]
|
1545
|
+
expires_in ||= args.last[:expires_in]
|
1546
|
+
purpose ||= args.last[:purpose]
|
1547
|
+
end
|
1548
|
+
_encrypt(value, expires_at: expires_at, expires_in: expires_in, purpose: purpose)
|
1549
|
+
end
|
1550
|
+
verifier.generate(encrypted)
|
1551
|
+
end
|
1552
|
+
end
|
1553
|
+
if const_defined?('Messages')
|
1554
|
+
class Messages::Metadata
|
1555
|
+
def self.wrap(message, *args, expires_at: nil, expires_in: nil, purpose: nil)
|
1556
|
+
if args.length > 0 && args.last.is_a?(Hash)
|
1557
|
+
expires_at ||= args.last[:expires_at]
|
1558
|
+
expires_in ||= args.last[:expires_in]
|
1559
|
+
purpose ||= args.last[:purpose]
|
1560
|
+
end
|
1561
|
+
if expires_at || expires_in || purpose
|
1562
|
+
JSON.encode new(encode(message), pick_expiry(expires_at, expires_in), purpose)
|
1563
|
+
else
|
1564
|
+
message
|
1565
|
+
end
|
1566
|
+
end
|
1567
|
+
end
|
1568
|
+
end
|
1569
|
+
end
|
1570
|
+
end
|
1571
|
+
|
1377
1572
|
require 'brick/extensions'
|
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.102
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lorin Thwaits
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -164,6 +164,20 @@ dependencies:
|
|
164
164
|
- - "~>"
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: 1.42.0
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: mysql2
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0.5'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0.5'
|
167
181
|
- !ruby/object:Gem::Dependency
|
168
182
|
name: pg
|
169
183
|
requirement: !ruby/object:Gem::Requirement
|