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