brick 1.0.77 → 1.0.78

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