brick 1.0.77 → 1.0.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e113470d473585f716cfa5b835f503448a0d160b60de20f884bf3ce2cc14c08
4
- data.tar.gz: 40064f980dd6893cb4e7e47861e00b184983d1a4bbc11b7cbd16fd6caddfab87
3
+ metadata.gz: 52f0716e20661f909922bdcddf3401b79b87c33c7b118d1581dfdf9861dd702c
4
+ data.tar.gz: 45323c512a8c7490b0ac715595ead6e6299d06a442b9c723318b90bcdce6106d
5
5
  SHA512:
6
- metadata.gz: 4219dfee478a845a949b1ac9b03d0a135504723a892b571ca068af70c2b58ca52025f5e1f2fedb6a97a5b2dcd97280c5f54132b854e285e6daf7bc95d0c2d357
7
- data.tar.gz: 67ae65b0de3801bbb2a1817d16b4023116ee7d41491b6d45927bd8197a8f800151f8ce79de34732a55f3dfcabbe301dc69b276899cfd544604d6a64e61220c99
6
+ metadata.gz: 2ef6ac2089e1150bc9c74c6625fc3e7627f5ee06a42d1a2d5fe43790d99156abacc27ba2e042044ee42171f352718d99ae8b468ec9dca4350cd6631bead51ce7
7
+ data.tar.gz: 8c4da365eb99677930a9f35f0cd5981b91adc790a13ecf55b5369da03fdf1592cccd01f911457cf204aa8769767d5a8537d856ff7080dec75543524b3e680904
@@ -258,7 +258,7 @@ module ActiveRecord
258
258
 
259
259
  def self._brick_index(mode = nil)
260
260
  tbl_parts = ((mode == :singular) ? table_name.singularize : table_name).split('.')
261
- tbl_parts.shift if ::Brick.apartment_multitenant && tbl_parts.first == Apartment.default_schema
261
+ tbl_parts.shift if ::Brick.apartment_multitenant && tbl_parts.length > 1 && tbl_parts.first == Apartment.default_schema
262
262
  tbl_parts.unshift(::Brick.config.path_prefix) if ::Brick.config.path_prefix
263
263
  index = tbl_parts.map(&:underscore).join('_')
264
264
  # Rails applies an _index suffix to that route when the resource name is singular
@@ -555,7 +555,10 @@ module ActiveRecord
555
555
  tbl_name = "\"#{tbl_name}\"" if ::Brick.is_oracle && rel_dupe._arel_applied_aliases.include?(tbl_name)
556
556
  field_tbl_name = nil
557
557
  v1.map { |x| [translations[x[0..-2].map(&:to_s).join('.')], x.last] }.each_with_index do |sel_col, idx|
558
- # binding.pry if chains[sel_col.first].nil?
558
+ # unless chains[sel_col.first]
559
+ # puts 'You might have some bogus DSL in your brick.rb file'
560
+ # next
561
+ # end
559
562
  field_tbl_name = (field_tbl_names[v.first][sel_col.first] ||= shift_or_first(chains[sel_col.first])).split('.').last
560
563
  # If it's Oracle, quote any AREL aliases that had been applied
561
564
  field_tbl_name = "\"#{field_tbl_name}\"" if ::Brick.is_oracle && rel_dupe._arel_applied_aliases.include?(field_tbl_name)
@@ -606,15 +609,42 @@ module ActiveRecord
606
609
  end
607
610
  end
608
611
  # Add derived table JOIN for the has_many counts
612
+ nix = []
609
613
  klass._br_hm_counts.each do |k, hm|
610
- associative = nil
611
614
  count_column = if hm.options[:through]
612
- if (fk_col = (associative = klass._br_associatives&.[](hm.name))&.foreign_key)
613
- if hm.source_reflection.macro == :belongs_to # Traditional HMT using an associative table
614
- hm.foreign_key
615
- else # A HMT that goes HM -> HM, something like Categories -> Products -> LineItems
616
- hm.source_reflection.active_record.primary_key
617
- end
615
+ # Build the chain of JOINs going to the final destination HMT table
616
+ # (Usually just one JOIN, but could be many.)
617
+ x = [hmt_assoc = hm]
618
+ x.unshift(hmt_assoc) while hmt_assoc.options[:through] && (hmt_assoc = klass.reflect_on_association(hmt_assoc.options[:through]))
619
+ from_clause = +"#{x.first.klass.table_name} br_t0"
620
+ fk_col = x.shift.foreign_key
621
+ link_back = [klass.primary_key] # %%% Inverse path back to the original object -- used to build out a link with a filter
622
+ idx = 0
623
+ bail_out = nil
624
+ x[0..-2].map do |a|
625
+ from_clause << "\n LEFT OUTER JOIN #{a.klass.table_name} br_t#{idx += 1} "
626
+ from_clause << if (src_ref = a.source_reflection).macro == :belongs_to
627
+ "ON br_t#{idx}.id = br_t#{idx - 1}.#{a.foreign_key}"
628
+ elsif src_ref.options[:as]
629
+ "ON br_t#{idx}.#{src_ref.type} = '#{src_ref.active_record.name}'" + # "polymorphable_type"
630
+ " AND br_t#{idx}.#{src_ref.foreign_key} = br_t#{idx - 1}.id"
631
+ elsif src_ref.options[:source_type]
632
+ print "Skipping #{hm.name} --HMT-> #{hm.source_reflection.name} as it uses source_type which is not supported"
633
+ nix << k
634
+ bail_out = true
635
+ break
636
+ else # Standard has_many
637
+ "ON br_t#{idx}.#{a.foreign_key} = br_t#{idx - 1}.id"
638
+ end
639
+ link_back.unshift(a.source_reflection.name)
640
+ [a.klass.table_name, a.foreign_key, a.source_reflection.macro]
641
+ end
642
+ next if bail_out
643
+ # count_column is determined from the last HMT member
644
+ if (src_ref = x.last.source_reflection).macro == :belongs_to # Traditional HMT using an associative table
645
+ "br_t#{idx}.#{x.last.foreign_key}"
646
+ else # A HMT that goes HM -> HM, something like Categories -> Products -> LineItems
647
+ "br_t#{idx}.#{src_ref.active_record.primary_key}"
618
648
  end
619
649
  else
620
650
  fk_col = hm.foreign_key
@@ -652,20 +682,38 @@ module ActiveRecord
652
682
  selects << poly_type
653
683
  on_clause << "#{tbl_alias}.#{poly_type} = '#{name}'"
654
684
  end
655
- hm_table_name = if is_mysql
656
- "`#{associative&.table_name || hm.klass.table_name}`"
657
- elsif is_postgres || is_mssql
658
- "\"#{(associative&.table_name || hm.klass.table_name).gsub('.', '"."')}\""
659
- else
660
- associative&.table_name || hm.klass.table_name
661
- end
685
+ unless from_clause
686
+ hm_table_name = if is_mysql
687
+ "`#{hm.klass.table_name}`"
688
+ elsif is_postgres || is_mssql
689
+ "\"#{(hm.klass.table_name).gsub('.', '"."')}\""
690
+ else
691
+ hm.klass.table_name
692
+ end
693
+ end
662
694
  group_bys = ::Brick.is_oracle || is_mssql ? selects : (1..selects.length).to_a
663
695
  join_clause = "LEFT OUTER
664
- JOIN (SELECT #{selects.join(', ')}, COUNT(#{'DISTINCT ' if hm.options[:through]}#{count_column
665
- }) AS c_t_ FROM #{hm_table_name} GROUP BY #{group_bys.join(', ')}) #{tbl_alias}"
696
+ JOIN (SELECT #{selects.map { |s| "#{'br_t0.' if from_clause}#{s}" }.join(', ')}, COUNT(#{'DISTINCT ' if hm.options[:through]}#{count_column
697
+ }) AS c_t_ FROM #{from_clause || hm_table_name} GROUP BY #{group_bys.join(', ')}) #{tbl_alias}"
666
698
  joins!("#{join_clause} ON #{on_clause.join(' AND ')}")
667
699
  end
668
- where!(wheres) unless wheres.empty?
700
+ while (n = nix.pop)
701
+ klass._br_hm_counts.delete(n)
702
+ end
703
+
704
+ unless wheres.empty?
705
+ # Rewrite the wheres to reference table and correlation names built out by AREL
706
+ wheres2 = wheres.each_with_object({}) do |v, s|
707
+ if (v_parts = v.first.split('.')).length == 1
708
+ s[v.first] = v.last
709
+ else
710
+ k1 = klass.reflect_on_association(v_parts.first)&.klass
711
+ tbl_name = (field_tbl_names[v_parts.first][k1] ||= shift_or_first(chains[k1])).split('.').last
712
+ s["#{tbl_name}.#{v_parts.last}"] = v.last
713
+ end
714
+ end
715
+ where!(wheres2)
716
+ end
669
717
  # Must parse the order_by and see if there are any symbols which refer to BT associations
670
718
  # or custom columns as they must be expanded to find the corresponding b_r_model__column
671
719
  # or br_cc_column naming for each.
@@ -805,12 +853,30 @@ Module.class_exec do
805
853
  end
806
854
  base_module = if self < ActiveRecord::Migration || !self.name
807
855
  brick_root || Object
808
- elsif (split_self_name || self.name.split('::')).length > 1
809
- return self._brick_const_missing(*args)
856
+ elsif (split_self_name || self.name.split('::')).length > 1 # Classic mode
857
+ begin
858
+ return self._brick_const_missing(*args)
859
+
860
+ rescue NameError # %%% Avoid the error "____ cannot be autoloaded from an anonymous class or module"
861
+ return self.const_get(args.first) if self.const_defined?(args.first)
862
+
863
+ # unless self == (prnt = (respond_to?(:parent) ? parent : module_parent))
864
+ unless self == Object
865
+ begin
866
+ return Object._brick_const_missing(*args)
867
+
868
+ rescue NameError
869
+ return Object.const_get(args.first) if Object.const_defined?(args.first)
870
+
871
+ end
872
+ end
873
+ end
874
+ Object
810
875
  else
811
876
  self
812
877
  end
813
- desired_classname = (self == Object) ? requested : "#{name}::#{requested}"
878
+ # puts "#{self.name} - #{args.first}"
879
+ desired_classname = (self == Object || !name) ? requested : "#{name}::#{requested}"
814
880
  if ((is_defined = self.const_defined?(args.first)) && (possible = self.const_get(args.first)) && possible.name == desired_classname) ||
815
881
  # Try to require the respective Ruby file
816
882
  ((filename = ActiveSupport::Dependencies.search_for_file(desired_classname.underscore) ||
@@ -822,9 +888,7 @@ Module.class_exec do
822
888
  # then return what we've found.
823
889
  (is_defined && !::Brick.is_eager_loading) # Used to also have: && possible != self
824
890
  if (!brick_root && (filename || possible.instance_of?(Class))) ||
825
- (possible.instance_of?(Module) &&
826
- ((possible.respond_to?(:module_parent) ? possible.module_parent : possible.parent) == self)
827
- ) ||
891
+ (possible.instance_of?(Module) && possible.module_parent == self) ||
828
892
  (possible.instance_of?(Class) && possible == self) # Are we simply searching for ourselves?
829
893
  return possible
830
894
  end
@@ -881,9 +945,21 @@ Module.class_exec do
881
945
  base_module._brick_const_missing(*args)
882
946
  # elsif base_module != Object
883
947
  # module_parent.const_missing(*args)
884
- else
885
- puts "MISSING! #{base_module.name} #{args.inspect} #{table_name}"
886
- base_module._brick_const_missing(*args)
948
+ elsif Rails.respond_to?(:autoloaders) && # After finding nothing else, if Zeitwerk is enabled ...
949
+ (Rails::Autoloaders.respond_to?(:zeitwerk_enabled?) ? Rails::Autoloaders.zeitwerk_enabled? : true)
950
+ self._brick_const_missing(*args) # ... rely solely on Zeitwerk.
951
+ else # Classic mode
952
+ unless (found = base_module._brick_const_missing(*args))
953
+ puts "MISSING! #{base_module.name} #{args.inspect} #{table_name}"
954
+ end
955
+ found
956
+ end
957
+ end
958
+
959
+ # Support Rails < 6.0 which adds #parent instead of #module_parent
960
+ unless respond_to?(:module_parent)
961
+ def module_parent # Weirdly for Grape::API does NOT come in with the proper class, but some anonymous Class thing
962
+ parent
887
963
  end
888
964
  end
889
965
  end
@@ -940,9 +1016,7 @@ class Object
940
1016
  schema_name
941
1017
  else
942
1018
  matching = "#{schema_name}.#{matching}"
943
- # %%% Coming up with integers when tables are in schemas
944
- # ::Brick.db_schemas[schema_name] ||= self.const_get(schema_name.camelize.to_sym)
945
- self.const_get(schema_name.camelize)
1019
+ (::Brick.db_schemas[schema_name] || {})[:class] ||= self.const_get(schema_name.camelize.to_sym)
946
1020
  end
947
1021
  "#{schema_module&.name}::#{inheritable_name || model_name}"
948
1022
  end
@@ -952,10 +1026,10 @@ class Object
952
1026
 
953
1027
  # Are they trying to use a pluralised class name such as "Employees" instead of "Employee"?
954
1028
  if table_name == singular_table_name && !ActiveSupport::Inflector.inflections.uncountable.include?(table_name)
955
- unless ::Brick.config.sti_namespace_prefixes&.key?("::#{singular_table_name.camelize}::")
956
- puts "Warning: Class name for a model that references table \"#{matching
957
- }\" should be \"#{ActiveSupport::Inflector.singularize(inheritable_name || model_name)}\"."
958
- end
1029
+ # unless ::Brick.config.sti_namespace_prefixes&.key?("::#{singular_table_name.camelize}::")
1030
+ # puts "Warning: Class name for a model that references table \"#{matching
1031
+ # }\" should be \"#{ActiveSupport::Inflector.singularize(inheritable_name || model_name)}\"."
1032
+ # end
959
1033
  return
960
1034
  end
961
1035
 
@@ -1393,7 +1467,7 @@ class Object
1393
1467
  end
1394
1468
 
1395
1469
  if pk.present?
1396
- # if (schema = ::Brick.config.schema_behavior[:multitenant]&.fetch(:schema_to_analyse, nil)) && ::Brick.db_schemas&.include?(schema)
1470
+ # if (schema = ::Brick.config.schema_behavior[:multitenant]&.fetch(:schema_to_analyse, nil)) && ::Brick.db_schemas&.key?(schema)
1397
1471
  # ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?;", schema)
1398
1472
  # end
1399
1473
 
@@ -1574,6 +1648,7 @@ module ActiveRecord::ConnectionHandling
1574
1648
  # return if ActiveRecord::Base.connection.current_database == 'postgres'
1575
1649
 
1576
1650
  initializer_loaded = false
1651
+ orig_schema = nil
1577
1652
  if (relations = ::Brick.relations).empty?
1578
1653
  # If there's schema things configured then we only expect our initializer to be named exactly this
1579
1654
  if File.exist?(brick_initializer = ::Rails.root.join('config/initializers/brick.rb'))
@@ -1607,12 +1682,14 @@ module ActiveRecord::ConnectionHandling
1607
1682
  [row['table_schema'], row['dt']]
1608
1683
  end
1609
1684
  # Remove any system schemas
1610
- s[row.first] = row.last unless ['information_schema', 'pg_catalog', 'pg_toast',
1611
- 'INFORMATION_SCHEMA', 'sys'].include?(row.first)
1685
+ s[row.first] = { dt: row.last } unless ['information_schema', 'pg_catalog', 'pg_toast', 'heroku_ext',
1686
+ 'INFORMATION_SCHEMA', 'sys'].include?(row.first)
1612
1687
  end
1613
1688
  if (is_multitenant = (multitenancy = ::Brick.config.schema_behavior[:multitenant]) &&
1614
1689
  (sta = multitenancy[:schema_to_analyse]) != 'public') &&
1615
- ::Brick.db_schemas.include?(sta)
1690
+ ::Brick.db_schemas.key?(sta)
1691
+ # Take note of the current schema so we can go back to it at the end of all this
1692
+ orig_schema = ActiveRecord::Base.execute_sql('SELECT current_schemas(true)').first['current_schemas'][1..-2].split(',')
1616
1693
  ::Brick.default_schema = schema = sta
1617
1694
  ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?", schema)
1618
1695
  end
@@ -1622,7 +1699,7 @@ module ActiveRecord::ConnectionHandling
1622
1699
  # ActiveRecord::Base.connection.current_database will be something like "XEPDB1"
1623
1700
  ::Brick.default_schema = schema = ActiveRecord::Base.connection.raw_connection.username
1624
1701
  ::Brick.db_schemas = {}
1625
- ActiveRecord::Base.execute_sql("SELECT username FROM sys.all_users WHERE ORACLE_MAINTAINED != 'Y'").each { |s| ::Brick.db_schemas[s.first] = nil }
1702
+ ActiveRecord::Base.execute_sql("SELECT username FROM sys.all_users WHERE ORACLE_MAINTAINED != 'Y'").each { |s| ::Brick.db_schemas[s.first] = {} }
1626
1703
  when 'SQLite'
1627
1704
  sql = "SELECT m.name AS relation_name, UPPER(m.type) AS table_type,
1628
1705
  p.name AS column_name, p.type AS data_type,
@@ -1641,10 +1718,12 @@ module ActiveRecord::ConnectionHandling
1641
1718
  if (possible_schema = ::Brick.config.schema_behavior&.[](:multitenant)&.[](:schema_to_analyse))
1642
1719
  if ::Brick.db_schemas.key?(possible_schema)
1643
1720
  ::Brick.default_schema = schema = possible_schema
1721
+ orig_schema = ActiveRecord::Base.execute_sql('SELECT current_schemas(true)').first['current_schemas'][1..-2].split(',')
1644
1722
  ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?", schema)
1645
1723
  elsif Rails.env == 'test' # When testing, just find the most recently-created schema
1646
- ::Brick.default_schema = schema = ::Brick.db_schemas.to_a.sort { |a, b| b.last <=> a.last }.first.first
1647
- puts "While running tests, had noticed that in the brick.rb initializer the line \"::Brick.schema_behavior = ...\" refers to a schema called \"#{possible_schema}\" which does not exist. Reverting to instead use the most recently-created schema, #{schema}."
1724
+ ::Brick.default_schema = schema = ::Brick.db_schemas.to_a.sort { |a, b| b.last[:dt] <=> a.last[:dt] }.first.first
1725
+ puts "While running tests, had noticed in the brick.rb initializer that the line \"::Brick.schema_behavior = ...\" refers to a schema called \"#{possible_schema}\" which does not exist. Reading table structure from the most recently-created schema, #{schema}."
1726
+ orig_schema = ActiveRecord::Base.execute_sql('SELECT current_schemas(true)').first['current_schemas'][1..-2].split(',')
1648
1727
  ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?", schema)
1649
1728
  else
1650
1729
  puts "*** In the brick.rb initializer the line \"::Brick.schema_behavior = ...\" refers to a schema called \"#{possible_schema}\". This schema does not exist. ***"
@@ -1848,6 +1927,11 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
1848
1927
  v[:class_name] = (schema_names + [rel_name.last.singularize]).map(&:camelize).join('::')
1849
1928
  end
1850
1929
  ::Brick.load_additional_references if initializer_loaded
1930
+
1931
+ if orig_schema && (orig_schema = (orig_schema - ['pg_catalog', 'heroku_ext']).first)
1932
+ puts "Now switching back to \"#{orig_schema}\" schema."
1933
+ ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?", orig_schema)
1934
+ end
1851
1935
  end
1852
1936
 
1853
1937
  def retrieve_schema_and_tables(sql = nil, is_postgres = nil, is_mssql = nil, schema = nil)
@@ -2134,7 +2218,12 @@ module Brick
2134
2218
  end
2135
2219
  end
2136
2220
  end
2137
- ::Brick.relations.keys.map { |v| [(model = models[v])&.last, model&.last&.table_name, migrations&.fetch(v, nil), model&.first] }
2221
+ ::Brick.relations.keys.map do |v|
2222
+ tbl_parts = v.split('.')
2223
+ tbl_parts.shift if ::Brick.apartment_multitenant && tbl_parts.length > 1 && tbl_parts.first == Apartment.default_schema
2224
+ res = tbl_parts.join('.')
2225
+ [v, (model = models[res])&.last&.table_name, migrations&.fetch(res, nil), model&.first]
2226
+ end
2138
2227
  end
2139
2228
 
2140
2229
  def ensure_unique(name, *sources)
@@ -125,8 +125,8 @@ module Brick
125
125
  "H#{hm_assoc.macro == :has_one ? 'O' : 'M'}#{'T' if hm_assoc.options[:through]}",
126
126
  (assoc_name = hm.first)]
127
127
  hm_fk_name = if (through = hm_assoc.options[:through])
128
- # %%% How to deal with weird self_ref type has_many -> has_one polymorphic stuff?
129
- # (or perhaps we don't need to!)
128
+ next unless @_brick_model._br_hm_counts.key?(hm_assoc.name) # Skip any weird HMTs that go through a HM with a source_type
129
+
130
130
  next unless @_brick_model.instance_methods.include?(through) &&
131
131
  (associative = @_brick_model._br_associatives.fetch(hm.first, nil))
132
132
 
@@ -353,11 +353,8 @@ def hide_bcrypt(val, max_len = 200)
353
353
  '(hidden)'
354
354
  else
355
355
  if val.is_a?(String)
356
- if val.length > max_len
357
- val = val[0...max_len]
358
- val << '...'
359
- end
360
- val.force_encoding('UTF-8') unless val.encoding.name == 'UTF-8'
356
+ val = \"#\{val[0...max_len]}...\" if val.length > max_len
357
+ val = val.dup.force_encoding('UTF-8') unless val.encoding.name == 'UTF-8'
361
358
  end
362
359
  val
363
360
  end
@@ -372,7 +369,7 @@ def display_value(col_type, val)
372
369
  if @is_mysql || @is_mssql
373
370
  # MySQL's \"Internal Geometry Format\" and MSSQL's Geography are like WKB, but with an initial 4 bytes that indicates the SRID.
374
371
  if (srid = val&.[](0..3)&.unpack('I'))
375
- val = val.force_encoding('BINARY')[4..-1].bytes
372
+ val = val.dup.force_encoding('BINARY')[4..-1].bytes
376
373
 
377
374
  # MSSQL spatial bitwise flags, often 0C for a point:
378
375
  # xxxx xxx1 = HasZValues
@@ -409,9 +406,8 @@ def display_value(col_type, val)
409
406
  end
410
407
  end
411
408
  # Accommodate composite primary keys that include strings with forward-slash characters
412
- def slashify(val)
413
- val = [val] unless val.is_a?(Array)
414
- val.map { |val_part| val_part.is_a?(String) ? val_part.gsub('/', '^^sl^^') : val_part }
409
+ def slashify(*vals)
410
+ vals.map { |val_part| val_part.is_a?(String) ? val_part.gsub('/', '^^sl^^') : val_part }
415
411
  end
416
412
  callbacks = {} %>"
417
413
 
@@ -673,7 +669,7 @@ erDiagram
673
669
  inline = case args.first
674
670
  when 'index'
675
671
  obj_pk = if pk&.is_a?(Array) # Composite primary key?
676
- "[#{pk.map { |pk_part| "#{obj_name}.#{pk_part}" }.join(', ')}]" unless pk.empty?
672
+ "#{pk.map { |pk_part| "#{obj_name}.#{pk_part}" }.join(', ')}" unless pk.empty?
677
673
  elsif pk
678
674
  "#{obj_name}.#{pk}"
679
675
  end
@@ -787,7 +783,7 @@ erDiagram
787
783
  origin = (key_parts = k.split('.')).length == 1 ? #{model_name} : #{model_name}.reflect_on_association(key_parts.first).klass
788
784
  if (destination_fk = Brick.relations[origin.table_name][:fks].values.find { |fk| fk[:fk] == key_parts.last }) &&
789
785
  (obj = (destination = origin.reflect_on_association(destination_fk[:assoc_name])&.klass)&.find(id)) %>
790
- <h3>for <%= link_to \"#{"#\{obj.brick_descrip\} (#\{destination.name\})\""}, send(\"#\{destination._brick_index\}_path\".to_sym, id) %></h3><%
786
+ <h3>for <%= link_to \"#{"#\{obj.brick_descrip\} (#\{destination.name\})\""}, send(\"#\{destination._brick_index(:singular)\}_path\".to_sym, id) %></h3><%
791
787
  end
792
788
  end %>
793
789
  (<%= link_to 'See all #{model_name.split('::').last.pluralize}', #{@_brick_model._brick_index}_path %>)
@@ -940,7 +936,11 @@ erDiagram
940
936
  @resources.each do |r|
941
937
  %>
942
938
  <tr>
943
- <td><%= link_to(r[0], r[0] && send(\"#\{r[0]&._brick_index}_path\".to_sym)) %></td>
939
+ <td><%= begin
940
+ kls = Object.const_get(::Brick.relations[r[0]].fetch(:class_name, nil))
941
+ rescue
942
+ end
943
+ kls ? link_to(r[0], send(\"#\{kls._brick_index}_path\".to_sym)) : r[0] %></td>
944
944
  <td<%= if r[1]
945
945
  ' class=\"orphan\"' unless ::Brick.relations.key?(r[1])
946
946
  else
@@ -1277,6 +1277,9 @@ document.querySelectorAll(\"input, select\").forEach(function (inp) {
1277
1277
  }
1278
1278
  });
1279
1279
  </script>"
1280
+ # puts "==============="
1281
+ # puts inline
1282
+ # puts "==============="
1280
1283
  # As if it were an inline template (see #determine_template in actionview-5.2.6.2/lib/action_view/renderer/template_renderer.rb)
1281
1284
  keys = options.has_key?(:locals) ? options[:locals].keys : []
1282
1285
  handler = ActionView::Template.handler_for_extension(options[:type] || 'erb')
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 77
8
+ TINY = 78
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
data/lib/brick.rb CHANGED
@@ -126,10 +126,15 @@ module Brick
126
126
  attr_accessor :default_schema, :db_schemas, :routes_done, :is_oracle, :is_eager_loading
127
127
 
128
128
  def set_db_schema(params = nil)
129
- schema = (params ? params['_brick_schema'] : ::Brick.default_schema) || 'public'
130
- if schema && ::Brick.db_schemas&.include?(schema)
129
+ schema = (params ? params['_brick_schema'] : ::Brick.default_schema)
130
+ if schema && ::Brick.db_schemas&.key?(schema)
131
131
  ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?;", schema)
132
132
  schema
133
+ elsif ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
134
+ # Just return the current schema
135
+ orig_schema = ActiveRecord::Base.execute_sql('SELECT current_schemas(true)').first['current_schemas'][1..-2].split(',')
136
+ # ::Brick.apartment_multitenant && tbl_parts.first == Apartment.default_schema
137
+ (orig_schema - ['pg_catalog']).first
133
138
  end
134
139
  end
135
140
 
@@ -435,7 +440,7 @@ module Brick
435
440
  end
436
441
  end
437
442
  if (polys = ::Brick.config.polymorphics)
438
- if (schema = ::Brick.config.schema_behavior[:multitenant]&.fetch(:schema_to_analyse, nil)) && ::Brick.db_schemas&.include?(schema)
443
+ if (schema = ::Brick.config.schema_behavior[:multitenant]&.fetch(:schema_to_analyse, nil)) && ::Brick.db_schemas&.key?(schema)
439
444
  ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?;", schema)
440
445
  end
441
446
  missing_stis = {}
@@ -525,9 +530,9 @@ In config/initializers/brick.rb appropriate entries would look something like:
525
530
  abstract_ar_bases
526
531
  end
527
532
 
528
- def display_classes(rels, max_length)
533
+ def display_classes(prefix, rels, max_length)
529
534
  rels.sort.each do |rel|
530
- puts "#{rel.first}#{' ' * (max_length - rel.first.length)} /#{rel.last}"
535
+ puts "#{rel.first}#{' ' * (max_length - rel.first.length)} /#{prefix}#{rel.last}"
531
536
  end
532
537
  puts "\n"
533
538
  end
@@ -556,13 +561,13 @@ In config/initializers/brick.rb appropriate entries would look something like:
556
561
 
557
562
  # %%% TODO: If no auto-controllers then enumerate the controllers folder in order to build matching routes
558
563
  # If auto-controllers and auto-models are both enabled then this makes sense:
564
+ controller_prefix = (::Brick.config.path_prefix ? "#{::Brick.config.path_prefix}/" : '')
559
565
  ::Brick.relations.each do |k, v|
560
566
  unless !(controller_name = v.fetch(:resource, nil)&.pluralize) || existing_controllers.key?(controller_name)
561
567
  options = {}
562
568
  options[:only] = [:index, :show] if v.key?(:isView)
563
569
  # First do the API routes
564
570
  full_resource = nil
565
- controller_prefix = (::Brick.config.path_prefix ? "#{::Brick.config.path_prefix}/" : '')
566
571
  if (schema_name = v.fetch(:schema, nil))
567
572
  full_resource = "#{schema_name}/#{v[:resource]}"
568
573
  send(:get, "#{::Brick.api_root}#{full_resource}", { to: "#{controller_prefix}#{schema_name}/#{controller_name}#index" }) if Object.const_defined?('Rswag::Ui')
@@ -595,19 +600,19 @@ In config/initializers/brick.rb appropriate entries would look something like:
595
600
  if tables.present?
596
601
  puts "Classes that can be built from tables:#{' ' * (table_class_length - 38)} Path:"
597
602
  puts "======================================#{' ' * (table_class_length - 38)} ====="
598
- ::Brick.display_classes(tables, table_class_length)
603
+ ::Brick.display_classes(controller_prefix, tables, table_class_length)
599
604
  end
600
605
  if views.present?
601
606
  puts "Classes that can be built from views:#{' ' * (view_class_length - 37)} Path:"
602
607
  puts "=====================================#{' ' * (view_class_length - 37)} ====="
603
- ::Brick.display_classes(views, view_class_length)
608
+ ::Brick.display_classes(controller_prefix, views, view_class_length)
604
609
  end
605
610
 
606
611
  if ::Brick.config.add_status && instance_variable_get(:@set).named_routes.names.exclude?(:brick_status)
607
- get('/brick_status', to: 'brick_gem#status', as: 'brick_status')
612
+ get("/#{controller_prefix}brick_status", to: 'brick_gem#status', as: 'brick_status')
608
613
  end
609
614
  if ::Brick.config.add_orphans && instance_variable_get(:@set).named_routes.names.exclude?(:brick_orphans)
610
- get('/brick_orphans', to: 'brick_gem#orphans', as: 'brick_orphans')
615
+ get("/#{controller_prefix}brick_orphans", to: 'brick_gem#orphans', as: 'brick_orphans')
611
616
  end
612
617
  if Object.const_defined?('Rswag::Ui') && doc_endpoint = Rswag::Ui.config.config_object[:urls].last
613
618
  # Serves JSON swagger info from a path such as '/api-docs/v1/swagger.json'
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.77
4
+ version: 1.0.78
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lorin Thwaits
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-10 00:00:00.000000000 Z
11
+ date: 2022-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord