brick 1.0.31 → 1.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/lib/brick/extensions.rb +342 -220
 - data/lib/brick/frameworks/rails/engine.rb +27 -10
 - data/lib/brick/version_number.rb +1 -1
 - data/lib/brick.rb +12 -6
 - data/lib/generators/brick/install_generator.rb +1 -1
 - metadata +2 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 9d1e2f8b6ff7ca3fa7fcd129c33de3dfe6e674b6da154b9a64e094c65a3a152a
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 30e39f62458a46854f56b2a6decbfe5ea42a4bb5325e81ed76f21400aae8e252
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 14c6bae09e34f53126e2003cbc7256c4b32f4a4219d42f1f7e94ca83211debf3704fa6c170cd6231d89e26eb168f282d1dea7eff7150ef1a013364aeb4eb65c3
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 7f33aa5c89be2e8401f4cda0ea6cecb6e01639934a2df1e7b00bd88d065bf3cc9b748bebb1691d51c1b04114fba3b1739a7820c7614f4eb84d52494bd4cc769e
         
     | 
    
        data/lib/brick/extensions.rb
    CHANGED
    
    | 
         @@ -86,7 +86,11 @@ module ActiveRecord 
     | 
|
| 
       86 
86 
     | 
    
         
             
                    descrip_col = (columns.map(&:name) - _brick_get_fks -
         
     | 
| 
       87 
87 
     | 
    
         
             
                                  (::Brick.config.metadata_columns || []) -
         
     | 
| 
       88 
88 
     | 
    
         
             
                                  [primary_key]).first
         
     | 
| 
       89 
     | 
    
         
            -
                    dsl = ::Brick.config.model_descrips[name] =  
     | 
| 
      
 89 
     | 
    
         
            +
                    dsl = ::Brick.config.model_descrips[name] = if descrip_col
         
     | 
| 
      
 90 
     | 
    
         
            +
                                                                  "[#{descrip_col}]"
         
     | 
| 
      
 91 
     | 
    
         
            +
                                                                elsif (pk_parts = self.primary_key.is_a?(Array) ? self.primary_key : [self.primary_key])
         
     | 
| 
      
 92 
     | 
    
         
            +
                                                                  "#{name} ##{pk_parts.map { |pk_part| "[#{pk_part}]" }.join(', ')}"
         
     | 
| 
      
 93 
     | 
    
         
            +
                                                                end
         
     | 
| 
       90 
94 
     | 
    
         
             
                  end
         
     | 
| 
       91 
95 
     | 
    
         
             
                  dsl
         
     | 
| 
       92 
96 
     | 
    
         
             
                end
         
     | 
| 
         @@ -104,7 +108,8 @@ module ActiveRecord 
     | 
|
| 
       104 
108 
     | 
    
         
             
                        if ch == ']' # Time to process a bracketed thing?
         
     | 
| 
       105 
109 
     | 
    
         
             
                          parts = bracket_name.split('.')
         
     | 
| 
       106 
110 
     | 
    
         
             
                          first_parts = parts[0..-2].map do |part|
         
     | 
| 
       107 
     | 
    
         
            -
                            klass = klass.reflect_on_association(part_sym = part.to_sym) 
     | 
| 
      
 111 
     | 
    
         
            +
                            klass = (orig_class = klass).reflect_on_association(part_sym = part.to_sym)&.klass
         
     | 
| 
      
 112 
     | 
    
         
            +
                            puts "Couldn't reference #{orig_class.name}##{part} that's part of the DSL \"#{dsl}\"." if klass.nil?
         
     | 
| 
       108 
113 
     | 
    
         
             
                            part_sym
         
     | 
| 
       109 
114 
     | 
    
         
             
                          end
         
     | 
| 
       110 
115 
     | 
    
         
             
                          parts = prefix + first_parts + [parts[-1]]
         
     | 
| 
         @@ -128,7 +133,7 @@ module ActiveRecord 
     | 
|
| 
       128 
133 
     | 
    
         
             
                    end
         
     | 
| 
       129 
134 
     | 
    
         
             
                  else # With no DSL available, still put this prefix into the JoinArray so we can get primary key (ID) info from this table
         
     | 
| 
       130 
135 
     | 
    
         
             
                    x = prefix.each_with_object(build_array) { |v, s| s[v.to_sym] }
         
     | 
| 
       131 
     | 
    
         
            -
                    x[prefix 
     | 
| 
      
 136 
     | 
    
         
            +
                    x[prefix.last] = nil unless prefix.empty? # Using []= will "hydrate" any missing part(s) in our whole series
         
     | 
| 
       132 
137 
     | 
    
         
             
                  end
         
     | 
| 
       133 
138 
     | 
    
         
             
                  members
         
     | 
| 
       134 
139 
     | 
    
         
             
                end
         
     | 
| 
         @@ -158,6 +163,7 @@ module ActiveRecord 
     | 
|
| 
       158 
163 
     | 
    
         
             
                                    bracket_name.split('.').each do |part|
         
     | 
| 
       159 
164 
     | 
    
         
             
                                      obj_name += ".#{part}"
         
     | 
| 
       160 
165 
     | 
    
         
             
                                      this_obj = caches.fetch(obj_name) { caches[obj_name] = this_obj&.send(part.to_sym) }
         
     | 
| 
      
 166 
     | 
    
         
            +
                                      break if this_obj.nil?
         
     | 
| 
       161 
167 
     | 
    
         
             
                                    end
         
     | 
| 
       162 
168 
     | 
    
         
             
                                    this_obj&.to_s || ''
         
     | 
| 
       163 
169 
     | 
    
         
             
                                  end
         
     | 
| 
         @@ -251,13 +257,12 @@ module ActiveRecord 
     | 
|
| 
       251 
257 
     | 
    
         
             
                      names << [piece.right._arel_table_type, (piece.right.table_alias || piece.right.name)]
         
     | 
| 
       252 
258 
     | 
    
         
             
                    else # "Normal" setup, fed from a JoinSource which has an array of JOINs
         
     | 
| 
       253 
259 
     | 
    
         
             
                      # The left side is the "JOIN" table
         
     | 
| 
       254 
     | 
    
         
            -
                      names += _recurse_arel(piece.left)
         
     | 
| 
      
 260 
     | 
    
         
            +
                      names += _recurse_arel(table = piece.left)
         
     | 
| 
       255 
261 
     | 
    
         
             
                      # The expression on the right side is the "ON" clause
         
     | 
| 
       256 
262 
     | 
    
         
             
                      # on = piece.right.expr
         
     | 
| 
       257 
263 
     | 
    
         
             
                      # # Find the table which is not ourselves, and thus must be the "path" that led us here
         
     | 
| 
       258 
264 
     | 
    
         
             
                      # parent = piece.left == on.left.relation ? on.right.relation : on.left.relation
         
     | 
| 
       259 
265 
     | 
    
         
             
                      # binding.pry if piece.left.is_a?(Arel::Nodes::TableAlias)
         
     | 
| 
       260 
     | 
    
         
            -
                      table = piece.left
         
     | 
| 
       261 
266 
     | 
    
         
             
                      if table.is_a?(Arel::Nodes::TableAlias)
         
     | 
| 
       262 
267 
     | 
    
         
             
                        alias_name = table.right
         
     | 
| 
       263 
268 
     | 
    
         
             
                        table = table.left
         
     | 
| 
         @@ -276,7 +281,8 @@ module ActiveRecord 
     | 
|
| 
       276 
281 
     | 
    
         
             
                    @_brick_chains = {}
         
     | 
| 
       277 
282 
     | 
    
         
             
                    # The left side is the "FROM" table
         
     | 
| 
       278 
283 
     | 
    
         
             
                    # names += _recurse_arel(piece.left)
         
     | 
| 
       279 
     | 
    
         
            -
                    names << [piece.left._arel_table_type, (piece.left.table_alias || piece.left.name)]
         
     | 
| 
      
 284 
     | 
    
         
            +
                    names << (this_name = [piece.left._arel_table_type, (piece.left.table_alias || piece.left.name)])
         
     | 
| 
      
 285 
     | 
    
         
            +
                    (_brick_chains[this_name.first] ||= []) << this_name.last
         
     | 
| 
       280 
286 
     | 
    
         
             
                    # The right side is an array of all JOINs
         
     | 
| 
       281 
287 
     | 
    
         
             
                    piece.right.each { |join| names << _recurse_arel(join) }
         
     | 
| 
       282 
288 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -303,6 +309,23 @@ module ActiveRecord 
     | 
|
| 
       303 
309 
     | 
    
         
             
                  # , is_add_bts, is_add_hms
         
     | 
| 
       304 
310 
     | 
    
         
             
                )
         
     | 
| 
       305 
311 
     | 
    
         
             
                  is_add_bts = is_add_hms = true
         
     | 
| 
      
 312 
     | 
    
         
            +
                  is_distinct = nil
         
     | 
| 
      
 313 
     | 
    
         
            +
                  wheres = {}
         
     | 
| 
      
 314 
     | 
    
         
            +
                  params.each do |k, v|
         
     | 
| 
      
 315 
     | 
    
         
            +
                    case (ks = k.split('.')).length
         
     | 
| 
      
 316 
     | 
    
         
            +
                    when 1
         
     | 
| 
      
 317 
     | 
    
         
            +
                      next unless klass._brick_get_fks.include?(k)
         
     | 
| 
      
 318 
     | 
    
         
            +
                    when 2
         
     | 
| 
      
 319 
     | 
    
         
            +
                      assoc_name = ks.first.to_sym
         
     | 
| 
      
 320 
     | 
    
         
            +
                      # Make sure it's a good association name and that the model has that column name
         
     | 
| 
      
 321 
     | 
    
         
            +
                      next unless klass.reflect_on_association(assoc_name)&.klass&.column_names&.any?(ks.last)
         
     | 
| 
      
 322 
     | 
    
         
            +
             
     | 
| 
      
 323 
     | 
    
         
            +
                      join_array[assoc_name] = nil # Store this relation name in our special collection for .joins()
         
     | 
| 
      
 324 
     | 
    
         
            +
                      is_distinct = true
         
     | 
| 
      
 325 
     | 
    
         
            +
                      distinct!
         
     | 
| 
      
 326 
     | 
    
         
            +
                    end
         
     | 
| 
      
 327 
     | 
    
         
            +
                    wheres[k] = v.split(',')
         
     | 
| 
      
 328 
     | 
    
         
            +
                  end
         
     | 
| 
       306 
329 
     | 
    
         | 
| 
       307 
330 
     | 
    
         
             
                  # %%% Skip the metadata columns
         
     | 
| 
       308 
331 
     | 
    
         
             
                  if selects&.empty? # Default to all columns
         
     | 
| 
         @@ -311,7 +334,9 @@ module ActiveRecord 
     | 
|
| 
       311 
334 
     | 
    
         
             
                      if (col_name = col.name) == 'class'
         
     | 
| 
       312 
335 
     | 
    
         
             
                        col_alias = ' AS _class'
         
     | 
| 
       313 
336 
     | 
    
         
             
                      end
         
     | 
| 
       314 
     | 
    
         
            -
                       
     | 
| 
      
 337 
     | 
    
         
            +
                      # Postgres can not use DISTINCT with any columns that are XML, so for any of those just convert to text
         
     | 
| 
      
 338 
     | 
    
         
            +
                      cast_as_text = '::text' if is_distinct && Brick.relations[klass.table_name]&.[](:cols)&.[](col.name)&.first&.start_with?('xml')
         
     | 
| 
      
 339 
     | 
    
         
            +
                      selects << "\"#{tbl_no_schema}\".\"#{col_name}\"#{cast_as_text}#{col_alias}"
         
     | 
| 
       315 
340 
     | 
    
         
             
                    end
         
     | 
| 
       316 
341 
     | 
    
         
             
                  end
         
     | 
| 
       317 
342 
     | 
    
         | 
| 
         @@ -337,21 +362,6 @@ module ActiveRecord 
     | 
|
| 
       337 
362 
     | 
    
         
             
                    end
         
     | 
| 
       338 
363 
     | 
    
         
             
                  end
         
     | 
| 
       339 
364 
     | 
    
         | 
| 
       340 
     | 
    
         
            -
                  wheres = {}
         
     | 
| 
       341 
     | 
    
         
            -
                  params.each do |k, v|
         
     | 
| 
       342 
     | 
    
         
            -
                    case (ks = k.split('.')).length
         
     | 
| 
       343 
     | 
    
         
            -
                    when 1
         
     | 
| 
       344 
     | 
    
         
            -
                      next unless klass._brick_get_fks.include?(k)
         
     | 
| 
       345 
     | 
    
         
            -
                    when 2
         
     | 
| 
       346 
     | 
    
         
            -
                      assoc_name = ks.first.to_sym
         
     | 
| 
       347 
     | 
    
         
            -
                      # Make sure it's a good association name and that the model has that column name
         
     | 
| 
       348 
     | 
    
         
            -
                      next unless klass.reflect_on_association(assoc_name)&.klass&.column_names&.any?(ks.last)
         
     | 
| 
       349 
     | 
    
         
            -
             
     | 
| 
       350 
     | 
    
         
            -
                      join_array[assoc_name] = nil # Store this relation name in our special collection for .joins()
         
     | 
| 
       351 
     | 
    
         
            -
                    end
         
     | 
| 
       352 
     | 
    
         
            -
                    wheres[k] = v.split(',')
         
     | 
| 
       353 
     | 
    
         
            -
                  end
         
     | 
| 
       354 
     | 
    
         
            -
             
     | 
| 
       355 
365 
     | 
    
         
             
                  if join_array.present?
         
     | 
| 
       356 
366 
     | 
    
         
             
                    left_outer_joins!(join_array)
         
     | 
| 
       357 
367 
     | 
    
         
             
                    # Without working from a duplicate, touching the AREL ast tree sets the @arel instance variable, which causes the relation to be immutable.
         
     | 
| 
         @@ -369,7 +379,9 @@ module ActiveRecord 
     | 
|
| 
       369 
379 
     | 
    
         
             
                        v1.map { |x| [translations[x[0..-2].map(&:to_s).join('.')], x.last] }.each_with_index do |sel_col, idx|
         
     | 
| 
       370 
380 
     | 
    
         
             
                          field_tbl_name = (field_tbl_names[v.first][sel_col.first] ||= shift_or_first(chains[sel_col.first])).split('.').last
         
     | 
| 
       371 
381 
     | 
    
         | 
| 
       372 
     | 
    
         
            -
                           
     | 
| 
      
 382 
     | 
    
         
            +
                          # Postgres can not use DISTINCT with any columns that are XML, so for any of those just convert to text
         
     | 
| 
      
 383 
     | 
    
         
            +
                          is_xml = is_distinct && Brick.relations[sel_col.first.table_name]&.[](:cols)&.[](sel_col.last)&.first&.start_with?('xml')
         
     | 
| 
      
 384 
     | 
    
         
            +
                          selects << "\"#{field_tbl_name}\".\"#{sel_col.last}\"#{'::text' if is_xml} AS \"#{(col_alias = "_brfk_#{v.first}__#{sel_col.last}")}\""
         
     | 
| 
       373 
385 
     | 
    
         
             
                          v1[idx] << col_alias
         
     | 
| 
       374 
386 
     | 
    
         
             
                        end
         
     | 
| 
       375 
387 
     | 
    
         | 
| 
         @@ -397,6 +409,7 @@ module ActiveRecord 
     | 
|
| 
       397 
409 
     | 
    
         
             
                  hm_counts.each do |k, hm|
         
     | 
| 
       398 
410 
     | 
    
         
             
                    associative = nil
         
     | 
| 
       399 
411 
     | 
    
         
             
                    count_column = if hm.options[:through]
         
     | 
| 
      
 412 
     | 
    
         
            +
                      # binding.pry if associatives[hm.name].nil?
         
     | 
| 
       400 
413 
     | 
    
         
             
                                     fk_col = (associative = associatives[hm.name]).foreign_key
         
     | 
| 
       401 
414 
     | 
    
         
             
                                     hm.foreign_key
         
     | 
| 
       402 
415 
     | 
    
         
             
                                   else
         
     | 
| 
         @@ -420,11 +433,13 @@ module ActiveRecord 
     | 
|
| 
       420 
433 
     | 
    
         
             
                      on_clause << "#{tbl_alias}.#{poly_type} = '#{name}'"
         
     | 
| 
       421 
434 
     | 
    
         
             
                    end
         
     | 
| 
       422 
435 
     | 
    
         
             
                    join_clause = "LEFT OUTER
         
     | 
| 
       423 
     | 
    
         
            -
            JOIN (SELECT #{selects.join(', ')}, COUNT(#{ 
     | 
| 
      
 436 
     | 
    
         
            +
            JOIN (SELECT #{selects.join(', ')}, COUNT(#{'DISTINCT ' if hm.options[:through]}#{count_column
         
     | 
| 
      
 437 
     | 
    
         
            +
                      }) AS _ct_ FROM #{associative&.table_name || hm.klass.table_name
         
     | 
| 
      
 438 
     | 
    
         
            +
                      } GROUP BY #{(1..selects.length).to_a.join(', ')}) AS #{tbl_alias}"
         
     | 
| 
       424 
439 
     | 
    
         
             
                    joins!("#{join_clause} ON #{on_clause.join(' AND ')}")
         
     | 
| 
       425 
440 
     | 
    
         
             
                  end
         
     | 
| 
       426 
441 
     | 
    
         
             
                  where!(wheres) unless wheres.empty?
         
     | 
| 
       427 
     | 
    
         
            -
                  limit(1000) # Don't want to get too carried away just yet
         
     | 
| 
      
 442 
     | 
    
         
            +
                  limit!(1000) # Don't want to get too carried away just yet
         
     | 
| 
       428 
443 
     | 
    
         
             
                  wheres unless wheres.empty? # Return the specific parameters that we did use
         
     | 
| 
       429 
444 
     | 
    
         
             
                end
         
     | 
| 
       430 
445 
     | 
    
         | 
| 
         @@ -485,7 +500,9 @@ if ActiveSupport::Dependencies.respond_to?(:autoload_module!) # %%% Only works w 
     | 
|
| 
       485 
500 
     | 
    
         
             
                  alias _brick_autoload_module! autoload_module!
         
     | 
| 
       486 
501 
     | 
    
         
             
                  def autoload_module!(*args)
         
     | 
| 
       487 
502 
     | 
    
         
             
                    into, const_name, qualified_name, path_suffix = args
         
     | 
| 
       488 
     | 
    
         
            -
                     
     | 
| 
      
 503 
     | 
    
         
            +
                    base_class_name = ::Brick.config.sti_namespace_prefixes&.fetch("::#{into.name}::", nil)
         
     | 
| 
      
 504 
     | 
    
         
            +
                    base_class_name = "::#{base_class_name}" unless base_class_name.start_with?('::')
         
     | 
| 
      
 505 
     | 
    
         
            +
                    if (base_class = base_class_name&.constantize)
         
     | 
| 
       489 
506 
     | 
    
         
             
                      ::Brick.sti_models[qualified_name] = { base: base_class }
         
     | 
| 
       490 
507 
     | 
    
         
             
                      # Build subclass and place it into the specially STI-namespaced module
         
     | 
| 
       491 
508 
     | 
    
         
             
                      into.const_set(const_name.to_sym, klass = Class.new(base_class))
         
     | 
| 
         @@ -506,8 +523,13 @@ end 
     | 
|
| 
       506 
523 
     | 
    
         
             
            Module.class_exec do
         
     | 
| 
       507 
524 
     | 
    
         
             
              alias _brick_const_missing const_missing
         
     | 
| 
       508 
525 
     | 
    
         
             
              def const_missing(*args)
         
     | 
| 
       509 
     | 
    
         
            -
                if (self.const_defined?(args.first) && (possible = self.const_get(args.first)) != self) ||
         
     | 
| 
       510 
     | 
    
         
            -
                   (self != Object && Object.const_defined?(args.first) && 
     | 
| 
      
 526 
     | 
    
         
            +
                if (self.const_defined?(args.first) && (possible = self.const_get(args.first)) && possible != self) ||
         
     | 
| 
      
 527 
     | 
    
         
            +
                   (self != Object && Object.const_defined?(args.first) &&
         
     | 
| 
      
 528 
     | 
    
         
            +
                     (
         
     | 
| 
      
 529 
     | 
    
         
            +
                       (possible = Object.const_get(args.first)) &&
         
     | 
| 
      
 530 
     | 
    
         
            +
                       (possible != self || (possible == self && possible.is_a?(Class)))
         
     | 
| 
      
 531 
     | 
    
         
            +
                     )
         
     | 
| 
      
 532 
     | 
    
         
            +
                   )
         
     | 
| 
       511 
533 
     | 
    
         
             
                  return possible
         
     | 
| 
       512 
534 
     | 
    
         
             
                end
         
     | 
| 
       513 
535 
     | 
    
         
             
                class_name = args.first.to_s
         
     | 
| 
         @@ -533,51 +555,64 @@ Module.class_exec do 
     | 
|
| 
       533 
555 
     | 
    
         
             
                result = if ::Brick.enable_controllers? && class_name.end_with?('Controller') && (plural_class_name = class_name[0..-11]).length.positive?
         
     | 
| 
       534 
556 
     | 
    
         
             
                           # Otherwise now it's up to us to fill in the gaps
         
     | 
| 
       535 
557 
     | 
    
         
             
                           # (Go over to underscores for a moment so that if we have something come in like VABCsController then the model name ends up as
         
     | 
| 
       536 
     | 
    
         
            -
                           #  
     | 
| 
      
 558 
     | 
    
         
            +
                           # Vabc instead of VABC)
         
     | 
| 
       537 
559 
     | 
    
         
             
                           full_class_name = +''
         
     | 
| 
       538 
560 
     | 
    
         
             
                           full_class_name << "::#{self.name}" unless self == Object
         
     | 
| 
       539 
561 
     | 
    
         
             
                           full_class_name << "::#{plural_class_name.underscore.singularize.camelize}"
         
     | 
| 
       540 
     | 
    
         
            -
                           if (model = self.const_get(full_class_name))
         
     | 
| 
      
 562 
     | 
    
         
            +
                           if (plural_class_name == 'BrickSwagger' || model = self.const_get(full_class_name))
         
     | 
| 
       541 
563 
     | 
    
         
             
                             # if it's a controller and no match or a model doesn't really use the same table name, eager load all models and try to find a model class of the right name.
         
     | 
| 
       542 
564 
     | 
    
         
             
                             Object.send(:build_controller, self, class_name, plural_class_name, model, relations)
         
     | 
| 
       543 
565 
     | 
    
         
             
                           end
         
     | 
| 
       544 
566 
     | 
    
         
             
                         elsif (::Brick.enable_models? || ::Brick.enable_controllers?) && # Schema match?
         
     | 
| 
       545 
567 
     | 
    
         
             
                               self == Object && # %%% This works for Person::Person -- but also limits us to not being able to allow more than one level of namespacing
         
     | 
| 
       546 
     | 
    
         
            -
                               schema_name = [(singular_table_name = class_name.underscore),
         
     | 
| 
       547 
     | 
    
         
            -
             
     | 
| 
       548 
     | 
    
         
            -
             
     | 
| 
       549 
     | 
    
         
            -
             
     | 
| 
      
 568 
     | 
    
         
            +
                               (schema_name = [(singular_table_name = class_name.underscore),
         
     | 
| 
      
 569 
     | 
    
         
            +
                                               (table_name = singular_table_name.pluralize),
         
     | 
| 
      
 570 
     | 
    
         
            +
                                               class_name,
         
     | 
| 
      
 571 
     | 
    
         
            +
                                               (plural_class_name = class_name.pluralize)].find { |s| Brick.db_schemas.include?(s) }&.camelize ||
         
     | 
| 
      
 572 
     | 
    
         
            +
                                              (::Brick.config.sti_namespace_prefixes&.key?("::#{class_name}::") && class_name))
         
     | 
| 
       550 
573 
     | 
    
         
             
                           # Build out a module for the schema if it's namespaced
         
     | 
| 
       551 
     | 
    
         
            -
                           schema_name = schema_name.camelize
         
     | 
| 
      
 574 
     | 
    
         
            +
                           # schema_name = schema_name.camelize
         
     | 
| 
       552 
575 
     | 
    
         
             
                           self.const_set(schema_name.to_sym, (built_module = Module.new))
         
     | 
| 
       553 
576 
     | 
    
         | 
| 
       554 
577 
     | 
    
         
             
                           [built_module, "module #{schema_name}; end\n"]
         
     | 
| 
       555 
578 
     | 
    
         
             
                           #  # %%% Perhaps an option to use the first module just as schema, and additional modules as namespace with a table name prefix applied
         
     | 
| 
       556 
579 
     | 
    
         
             
                         elsif ::Brick.enable_models?
         
     | 
| 
      
 580 
     | 
    
         
            +
                           # Custom inheritable Brick base model?
         
     | 
| 
      
 581 
     | 
    
         
            +
                           class_name = (inheritable_name = class_name)[5..-1] if class_name.start_with?('Brick')
         
     | 
| 
       557 
582 
     | 
    
         
             
                           # See if a file is there in the same way that ActiveSupport::Dependencies#load_missing_constant
         
     | 
| 
       558 
583 
     | 
    
         
             
                           # checks for it in ~/.rvm/gems/ruby-2.7.5/gems/activesupport-5.2.6.2/lib/active_support/dependencies.rb
         
     | 
| 
       559 
584 
     | 
    
         | 
| 
       560 
     | 
    
         
            -
                            
     | 
| 
      
 585 
     | 
    
         
            +
                           if (base_model = ::Brick.config.sti_namespace_prefixes&.fetch("::#{name}::", nil)&.constantize) || # Are we part of an auto-STI namespace? ...
         
     | 
| 
      
 586 
     | 
    
         
            +
                              self != Object # ... or otherwise already in some namespace?
         
     | 
| 
       561 
587 
     | 
    
         
             
                             schema_name = [(singular_schema_name = name.underscore),
         
     | 
| 
       562 
588 
     | 
    
         
             
                                            (schema_name = singular_schema_name.pluralize),
         
     | 
| 
       563 
589 
     | 
    
         
             
                                            name,
         
     | 
| 
       564 
590 
     | 
    
         
             
                                            name.pluralize].find { |s| Brick.db_schemas.include?(s) }
         
     | 
| 
       565 
591 
     | 
    
         
             
                           end
         
     | 
| 
       566 
     | 
    
         
            -
             
     | 
| 
       567 
592 
     | 
    
         
             
                           plural_class_name = ActiveSupport::Inflector.pluralize(model_name = class_name)
         
     | 
| 
       568 
593 
     | 
    
         
             
                           # If it's namespaced then we turn the first part into what would be a schema name
         
     | 
| 
       569 
     | 
    
         
            -
                           singular_table_name = ActiveSupport::Inflector.underscore(model_name).gsub(' 
     | 
| 
       570 
     | 
    
         
            -
             
     | 
| 
       571 
     | 
    
         
            -
                            
     | 
| 
       572 
     | 
    
         
            -
             
     | 
| 
       573 
     | 
    
         
            -
             
     | 
| 
       574 
     | 
    
         
            -
             
     | 
| 
       575 
     | 
    
         
            -
             
     | 
| 
       576 
     | 
    
         
            -
             
     | 
| 
       577 
     | 
    
         
            -
             
     | 
| 
       578 
     | 
    
         
            -
             
     | 
| 
       579 
     | 
    
         
            -
             
     | 
| 
       580 
     | 
    
         
            -
             
     | 
| 
      
 594 
     | 
    
         
            +
                           singular_table_name = ActiveSupport::Inflector.underscore(model_name).gsub('/', '.')
         
     | 
| 
      
 595 
     | 
    
         
            +
             
     | 
| 
      
 596 
     | 
    
         
            +
                           if base_model
         
     | 
| 
      
 597 
     | 
    
         
            +
                             schema_name = name.underscore # For the auto-STI namespace models
         
     | 
| 
      
 598 
     | 
    
         
            +
                             table_name = base_model.table_name
         
     | 
| 
      
 599 
     | 
    
         
            +
                             Object.send(:build_model, self, inheritable_name, model_name, singular_table_name, table_name, relations, table_name)
         
     | 
| 
      
 600 
     | 
    
         
            +
                           else
         
     | 
| 
      
 601 
     | 
    
         
            +
                             # Adjust for STI if we know of a base model for the requested model name
         
     | 
| 
      
 602 
     | 
    
         
            +
                             # %%% Does not yet work with namespaced model names.  Perhaps prefix with plural_class_name when doing the lookups here.
         
     | 
| 
      
 603 
     | 
    
         
            +
                             table_name = if (base_model = ::Brick.sti_models[model_name]&.fetch(:base, nil) || ::Brick.existing_stis[model_name]&.constantize)
         
     | 
| 
      
 604 
     | 
    
         
            +
                                            base_model.table_name
         
     | 
| 
      
 605 
     | 
    
         
            +
                                          else
         
     | 
| 
      
 606 
     | 
    
         
            +
                                            ActiveSupport::Inflector.pluralize(singular_table_name)
         
     | 
| 
      
 607 
     | 
    
         
            +
                                          end
         
     | 
| 
      
 608 
     | 
    
         
            +
                             if ::Brick.config.schema_behavior[:multitenant] && Object.const_defined?('Apartment') &&
         
     | 
| 
      
 609 
     | 
    
         
            +
                                Apartment.excluded_models.include?(table_name.singularize.camelize)
         
     | 
| 
      
 610 
     | 
    
         
            +
                               schema_name = Apartment.default_schema
         
     | 
| 
      
 611 
     | 
    
         
            +
                             end
         
     | 
| 
      
 612 
     | 
    
         
            +
                             # Maybe, just maybe there's a database table that will satisfy this need
         
     | 
| 
      
 613 
     | 
    
         
            +
                             if (matching = [table_name, singular_table_name, plural_class_name, model_name].find { |m| relations.key?(schema_name ? "#{schema_name}.#{m}" : m) })
         
     | 
| 
      
 614 
     | 
    
         
            +
                               Object.send(:build_model, schema_name, inheritable_name, model_name, singular_table_name, table_name, relations, matching)
         
     | 
| 
      
 615 
     | 
    
         
            +
                             end
         
     | 
| 
       581 
616 
     | 
    
         
             
                           end
         
     | 
| 
       582 
617 
     | 
    
         
             
                         end
         
     | 
| 
       583 
618 
     | 
    
         
             
                if result
         
     | 
| 
         @@ -593,7 +628,7 @@ Module.class_exec do 
     | 
|
| 
       593 
628 
     | 
    
         
             
                elsif self != Object
         
     | 
| 
       594 
629 
     | 
    
         
             
                  module_parent.const_missing(*args)
         
     | 
| 
       595 
630 
     | 
    
         
             
                else
         
     | 
| 
       596 
     | 
    
         
            -
                  puts "MISSING!  
     | 
| 
      
 631 
     | 
    
         
            +
                  puts "MISSING! #{self.name} #{args.inspect} #{table_name}"
         
     | 
| 
       597 
632 
     | 
    
         
             
                  self._brick_const_missing(*args)
         
     | 
| 
       598 
633 
     | 
    
         
             
                end
         
     | 
| 
       599 
634 
     | 
    
         
             
              end
         
     | 
| 
         @@ -601,123 +636,39 @@ end 
     | 
|
| 
       601 
636 
     | 
    
         | 
| 
       602 
637 
     | 
    
         
             
            class Object
         
     | 
| 
       603 
638 
     | 
    
         
             
              class << self
         
     | 
| 
       604 
     | 
    
         
            -
            #     alias _brick_const_missing const_missing
         
     | 
| 
       605 
     | 
    
         
            -
            #     def const_missing(*args)
         
     | 
| 
       606 
     | 
    
         
            -
            #       # return self.const_get(args.first) if self.const_defined?(args.first)
         
     | 
| 
       607 
     | 
    
         
            -
            #       # return Object.const_get(args.first) if Object.const_defined?(args.first) unless self == Object
         
     | 
| 
       608 
     | 
    
         
            -
            #       if self.const_defined?(args.first) && (possible = self.const_get(args.first)) != self
         
     | 
| 
       609 
     | 
    
         
            -
            #         return possible
         
     | 
| 
       610 
     | 
    
         
            -
            #       end
         
     | 
| 
       611 
     | 
    
         
            -
            #       if self != Object && Object.const_defined?(args.first) && (possible = Object.const_get(args.first)) != self
         
     | 
| 
       612 
     | 
    
         
            -
            #         return possible
         
     | 
| 
       613 
     | 
    
         
            -
            #       end
         
     | 
| 
       614 
     | 
    
         
            -
              
         
     | 
| 
       615 
     | 
    
         
            -
            #       class_name = args.first.to_s
         
     | 
| 
       616 
     | 
    
         
            -
            #       # See if a file is there in the same way that ActiveSupport::Dependencies#load_missing_constant
         
     | 
| 
       617 
     | 
    
         
            -
            #       # checks for it in ~/.rvm/gems/ruby-2.7.5/gems/activesupport-5.2.6.2/lib/active_support/dependencies.rb
         
     | 
| 
       618 
     | 
    
         
            -
            #       # that is, checking #qualified_name_for with:  from_mod, const_name
         
     | 
| 
       619 
     | 
    
         
            -
            #       # If we want to support namespacing in the future, might have to utilise something like this:
         
     | 
| 
       620 
     | 
    
         
            -
            #       # path_suffix = ActiveSupport::Dependencies.qualified_name_for(Object, args.first).underscore
         
     | 
| 
       621 
     | 
    
         
            -
            #       # return self._brick_const_missing(*args) if ActiveSupport::Dependencies.search_for_file(path_suffix)
         
     | 
| 
       622 
     | 
    
         
            -
            #       # If the file really exists, go and snag it:
         
     | 
| 
       623 
     | 
    
         
            -
            #       if !(is_found = ActiveSupport::Dependencies.search_for_file(class_name.underscore)) && (filepath = (self.name || class_name)&.split('::'))
         
     | 
| 
       624 
     | 
    
         
            -
            #         filepath = (filepath[0..-2] + [class_name]).join('/').underscore + '.rb'
         
     | 
| 
       625 
     | 
    
         
            -
            #       end
         
     | 
| 
       626 
     | 
    
         
            -
            #       if is_found
         
     | 
| 
       627 
     | 
    
         
            -
            #         return self._brick_const_missing(*args)
         
     | 
| 
       628 
     | 
    
         
            -
            #       elsif ActiveSupport::Dependencies.search_for_file(filepath) # Last-ditch effort to pick this thing up before we fill in the gaps on our own
         
     | 
| 
       629 
     | 
    
         
            -
            #         my_const = parent.const_missing(class_name) # ends up having:  MyModule::MyClass
         
     | 
| 
       630 
     | 
    
         
            -
            #         return my_const
         
     | 
| 
       631 
     | 
    
         
            -
            #       end
         
     | 
| 
       632 
     | 
    
         
            -
            #       relations = ::Brick.instance_variable_get(:@relations)[ActiveRecord::Base.connection_pool.object_id] || {}
         
     | 
| 
       633 
     | 
    
         
            -
            #       result = if ::Brick.enable_controllers? && class_name.end_with?('Controller') && (plural_class_name = class_name[0..-11]).length.positive?
         
     | 
| 
       634 
     | 
    
         
            -
            #                  # Otherwise now it's up to us to fill in the gaps
         
     | 
| 
       635 
     | 
    
         
            -
            #                  # (Go over to underscores for a moment so that if we have something come in like VABCsController then the model name ends up as
         
     | 
| 
       636 
     | 
    
         
            -
            #                  # VAbc instead of VABC)
         
     | 
| 
       637 
     | 
    
         
            -
            #                  if (model = Object.const_get(plural_class_name.underscore.singularize.camelize))
         
     | 
| 
       638 
     | 
    
         
            -
            #                    # if it's a controller and no match or a model doesn't really use the same table name, eager load all models and try to find a model class of the right name.
         
     | 
| 
       639 
     | 
    
         
            -
            #                    build_controller(nil, class_name, plural_class_name, model, relations)
         
     | 
| 
       640 
     | 
    
         
            -
            #                  end
         
     | 
| 
       641 
     | 
    
         
            -
            #                elsif (::Brick.enable_models? || ::Brick.enable_controllers?) && # Schema match?
         
     | 
| 
       642 
     | 
    
         
            -
            #                      db_schema_name = [(singular_table_name = class_name.underscore),
         
     | 
| 
       643 
     | 
    
         
            -
            #                                       (table_name = singular_table_name.pluralize),
         
     | 
| 
       644 
     | 
    
         
            -
            #                                       class_name,
         
     | 
| 
       645 
     | 
    
         
            -
            #                                       (plural_class_name = class_name.pluralize)].find { |s| Brick.db_schemas.include?(s) }
         
     | 
| 
       646 
     | 
    
         
            -
            #                  # Build out a module for the schema if it's namespaced
         
     | 
| 
       647 
     | 
    
         
            -
            #                  schema_name = db_schema_name.camelize
         
     | 
| 
       648 
     | 
    
         
            -
            #                  unless Object.const_defined?(schema_name.to_sym)
         
     | 
| 
       649 
     | 
    
         
            -
            #                    Object.const_set(schema_name.to_sym, (built_module = Module.new))
         
     | 
| 
       650 
     | 
    
         
            -
            #                    Brick.db_schemas[db_schema_name] = built_module
         
     | 
| 
       651 
     | 
    
         
            -
            #                    [built_module, "module #{schema_name}; end\n"]
         
     | 
| 
       652 
     | 
    
         
            -
            #                  end
         
     | 
| 
       653 
     | 
    
         
            -
            #                  #  # %%% Perhaps an option to use the first module just as schema, and additional modules as namespace with a table name prefix applied
         
     | 
| 
       654 
     | 
    
         
            -
            #                  #  schema_name, model_name = 
         
     | 
| 
       655 
     | 
    
         
            -
            #                  #  code = +''
         
     | 
| 
       656 
     | 
    
         
            -
            #                  #  mod_tree = +''
         
     | 
| 
       657 
     | 
    
         
            -
            #                  #  model_name.split('::')[0..-2].each do |mod_name|
         
     | 
| 
       658 
     | 
    
         
            -
            #                  #    mod_tree << "::#{mod_name}"
         
     | 
| 
       659 
     | 
    
         
            -
            #                  #    Module.new(mod_tree)
         
     | 
| 
       660 
     | 
    
         
            -
            #                  #    code << "module #{mod_tree}; end\n"
         
     | 
| 
       661 
     | 
    
         
            -
            #                  #  end
         
     | 
| 
       662 
     | 
    
         
            -
            #                elsif ::Brick.enable_models?
         
     | 
| 
       663 
     | 
    
         
            -
            #                  # See if a file is there in the same way that ActiveSupport::Dependencies#load_missing_constant
         
     | 
| 
       664 
     | 
    
         
            -
            #                  # checks for it in ~/.rvm/gems/ruby-2.7.5/gems/activesupport-5.2.6.2/lib/active_support/dependencies.rb
         
     | 
| 
       665 
     | 
    
         
            -
            #                  plural_class_name = ActiveSupport::Inflector.pluralize(model_name = class_name)
         
     | 
| 
       666 
     | 
    
         
            -
            #                  singular_table_name = ActiveSupport::Inflector.underscore(model_name)
         
     | 
| 
       667 
     | 
    
         
            -
             
     | 
| 
       668 
     | 
    
         
            -
            #                  # Adjust for STI if we know of a base model for the requested model name
         
     | 
| 
       669 
     | 
    
         
            -
            #                  table_name = if (base_model = ::Brick.sti_models[model_name]&.fetch(:base, nil) || ::Brick.existing_stis[model_name]&.constantize)
         
     | 
| 
       670 
     | 
    
         
            -
            #                                 base_model.table_name
         
     | 
| 
       671 
     | 
    
         
            -
            #                               else
         
     | 
| 
       672 
     | 
    
         
            -
            #                                 ActiveSupport::Inflector.pluralize(singular_table_name)
         
     | 
| 
       673 
     | 
    
         
            -
            #                               end
         
     | 
| 
       674 
     | 
    
         
            -
             
     | 
| 
       675 
     | 
    
         
            -
            #                  # Maybe, just maybe there's a database table that will satisfy this need
         
     | 
| 
       676 
     | 
    
         
            -
            #                  if (matching = [table_name, singular_table_name, plural_class_name, model_name].find { |m| relations.key?(m) })
         
     | 
| 
       677 
     | 
    
         
            -
            #                    build_model(nil, model_name, singular_table_name, table_name, relations, matching)
         
     | 
| 
       678 
     | 
    
         
            -
            #                  end
         
     | 
| 
       679 
     | 
    
         
            -
            #                end
         
     | 
| 
       680 
     | 
    
         
            -
            #       if result
         
     | 
| 
       681 
     | 
    
         
            -
            #         built_class, code = result
         
     | 
| 
       682 
     | 
    
         
            -
            #         puts "\n#{code}"
         
     | 
| 
       683 
     | 
    
         
            -
            #         built_class
         
     | 
| 
       684 
     | 
    
         
            -
            #       elsif ::Brick.config.sti_namespace_prefixes&.key?("::#{class_name}") && !schema_name
         
     | 
| 
       685 
     | 
    
         
            -
            # #         module_prefixes = type_name.split('::')
         
     | 
| 
       686 
     | 
    
         
            -
            # #         path = self.name.split('::')[0..-2] + []
         
     | 
| 
       687 
     | 
    
         
            -
            # #         module_prefixes.unshift('') unless module_prefixes.first.blank?
         
     | 
| 
       688 
     | 
    
         
            -
            # #         candidate_file = Rails.root.join('app/models' + module_prefixes.map(&:underscore).join('/') + '.rb')
         
     | 
| 
       689 
     | 
    
         
            -
            #         self._brick_const_missing(*args)
         
     | 
| 
       690 
     | 
    
         
            -
            #       elsif self != Object
         
     | 
| 
       691 
     | 
    
         
            -
            #         module_parent.const_missing(*args)
         
     | 
| 
       692 
     | 
    
         
            -
            #       else
         
     | 
| 
       693 
     | 
    
         
            -
            #         puts "MISSING! obj #{self.name}/#{schema_name}  #{args.inspect} #{table_name}"
         
     | 
| 
       694 
     | 
    
         
            -
            #         self._brick_const_missing(*args)
         
     | 
| 
       695 
     | 
    
         
            -
            #       end
         
     | 
| 
       696 
     | 
    
         
            -
            #     end
         
     | 
| 
       697 
639 
     | 
    
         | 
| 
       698 
640 
     | 
    
         
             
              private
         
     | 
| 
       699 
641 
     | 
    
         | 
| 
       700 
     | 
    
         
            -
                def build_model(schema_name, model_name, singular_table_name, table_name, relations, matching)
         
     | 
| 
       701 
     | 
    
         
            -
                  full_name = if schema_name. 
     | 
| 
       702 
     | 
    
         
            -
                                 
     | 
| 
      
 642 
     | 
    
         
            +
                def build_model(schema_name, inheritable_name, model_name, singular_table_name, table_name, relations, matching)
         
     | 
| 
      
 643 
     | 
    
         
            +
                  full_name = if (::Brick.config.schema_behavior[:multitenant] && Object.const_defined?('Apartment') && schema_name == Apartment.default_schema)
         
     | 
| 
      
 644 
     | 
    
         
            +
                                relation = relations["#{schema_name}.#{matching}"]
         
     | 
| 
      
 645 
     | 
    
         
            +
                                inheritable_name || model_name
         
     | 
| 
      
 646 
     | 
    
         
            +
                              elsif schema_name.blank?
         
     | 
| 
      
 647 
     | 
    
         
            +
                                inheritable_name || model_name
         
     | 
| 
       703 
648 
     | 
    
         
             
                              else # Prefix the schema to the table name + prefix the schema namespace to the class name
         
     | 
| 
       704 
     | 
    
         
            -
                                schema_module =  
     | 
| 
       705 
     | 
    
         
            -
             
     | 
| 
       706 
     | 
    
         
            -
             
     | 
| 
      
 649 
     | 
    
         
            +
                                schema_module = if schema_name.instance_of?(Module) # from an auto-STI namespace?
         
     | 
| 
      
 650 
     | 
    
         
            +
                                                  schema_name
         
     | 
| 
      
 651 
     | 
    
         
            +
                                                else
         
     | 
| 
      
 652 
     | 
    
         
            +
                                                  matching = "#{schema_name}.#{matching}"
         
     | 
| 
      
 653 
     | 
    
         
            +
                                                  (Brick.db_schemas[schema_name] ||= self.const_get(schema_name.singularize.camelize))
         
     | 
| 
      
 654 
     | 
    
         
            +
                                                end
         
     | 
| 
      
 655 
     | 
    
         
            +
                                "#{schema_module&.name}::#{inheritable_name || model_name}"
         
     | 
| 
       707 
656 
     | 
    
         
             
                              end
         
     | 
| 
       708 
657 
     | 
    
         | 
| 
       709 
     | 
    
         
            -
                  return if ((is_view = (relation  
     | 
| 
      
 658 
     | 
    
         
            +
                  return if ((is_view = (relation ||= relations[matching]).key?(:isView)) && ::Brick.config.skip_database_views) ||
         
     | 
| 
       710 
659 
     | 
    
         
             
                            ::Brick.config.exclude_tables.include?(matching)
         
     | 
| 
       711 
660 
     | 
    
         | 
| 
       712 
661 
     | 
    
         
             
                  # Are they trying to use a pluralised class name such as "Employees" instead of "Employee"?
         
     | 
| 
       713 
662 
     | 
    
         
             
                  if table_name == singular_table_name && !ActiveSupport::Inflector.inflections.uncountable.include?(table_name)
         
     | 
| 
       714 
     | 
    
         
            -
                    unless ::Brick.config.sti_namespace_prefixes&.key?("::#{singular_table_name. 
     | 
| 
       715 
     | 
    
         
            -
                      puts "Warning: Class name for a model that references table \"#{matching 
     | 
| 
      
 663 
     | 
    
         
            +
                    unless ::Brick.config.sti_namespace_prefixes&.key?("::#{singular_table_name.camelize}::")
         
     | 
| 
      
 664 
     | 
    
         
            +
                      puts "Warning: Class name for a model that references table \"#{matching
         
     | 
| 
      
 665 
     | 
    
         
            +
                           }\" should be \"#{ActiveSupport::Inflector.singularize(inheritable_name || model_name)}\"."
         
     | 
| 
       716 
666 
     | 
    
         
             
                    end
         
     | 
| 
       717 
667 
     | 
    
         
             
                    return
         
     | 
| 
       718 
668 
     | 
    
         
             
                  end
         
     | 
| 
       719 
669 
     | 
    
         | 
| 
       720 
     | 
    
         
            -
                   
     | 
| 
      
 670 
     | 
    
         
            +
                  full_model_name = full_name.split('::').tap { |fn| fn[-1] = model_name }.join('::')
         
     | 
| 
      
 671 
     | 
    
         
            +
                  if (base_model = ::Brick.sti_models[full_model_name]&.fetch(:base, nil) || ::Brick.existing_stis[full_model_name]&.constantize)
         
     | 
| 
       721 
672 
     | 
    
         
             
                    is_sti = true
         
     | 
| 
       722 
673 
     | 
    
         
             
                  else
         
     | 
| 
       723 
674 
     | 
    
         
             
                    base_model = ::Brick.config.models_inherit_from || ActiveRecord::Base
         
     | 
| 
         @@ -725,9 +676,21 @@ class Object 
     | 
|
| 
       725 
676 
     | 
    
         
             
                  hmts = nil
         
     | 
| 
       726 
677 
     | 
    
         
             
                  code = +"class #{full_name} < #{base_model.name}\n"
         
     | 
| 
       727 
678 
     | 
    
         
             
                  built_model = Class.new(base_model) do |new_model_class|
         
     | 
| 
       728 
     | 
    
         
            -
                    (schema_module || Object).const_set(model_name.to_sym, new_model_class)
         
     | 
| 
      
 679 
     | 
    
         
            +
                    (schema_module || Object).const_set((inheritable_name || model_name).to_sym, new_model_class)
         
     | 
| 
      
 680 
     | 
    
         
            +
                    if inheritable_name
         
     | 
| 
      
 681 
     | 
    
         
            +
                      new_model_class.define_singleton_method :inherited do |subclass|
         
     | 
| 
      
 682 
     | 
    
         
            +
                        super(subclass)
         
     | 
| 
      
 683 
     | 
    
         
            +
                        if subclass.name == model_name
         
     | 
| 
      
 684 
     | 
    
         
            +
                          puts "#{full_model_name} properly extends from #{full_name}"
         
     | 
| 
      
 685 
     | 
    
         
            +
                        else
         
     | 
| 
      
 686 
     | 
    
         
            +
                          puts "should be \"class #{model_name} < #{inheritable_name}\"\n           (not \"#{subclass.name} < #{inheritable_name}\")"
         
     | 
| 
      
 687 
     | 
    
         
            +
                        end
         
     | 
| 
      
 688 
     | 
    
         
            +
                      end
         
     | 
| 
      
 689 
     | 
    
         
            +
                      self.abstract_class = true
         
     | 
| 
      
 690 
     | 
    
         
            +
                      code << "  self.abstract_class = true\n"
         
     | 
| 
      
 691 
     | 
    
         
            +
                    end
         
     | 
| 
       729 
692 
     | 
    
         
             
                    # Accommodate singular or camel-cased table names such as "order_detail" or "OrderDetails"
         
     | 
| 
       730 
     | 
    
         
            -
                    code << "  self.table_name = '#{self.table_name = matching}'\n"  
     | 
| 
      
 693 
     | 
    
         
            +
                    code << "  self.table_name = '#{self.table_name = matching}'\n" if inheritable_name || table_name != matching
         
     | 
| 
       731 
694 
     | 
    
         | 
| 
       732 
695 
     | 
    
         
             
                    # Override models backed by a view so they return true for #is_view?
         
     | 
| 
       733 
696 
     | 
    
         
             
                    # (Dynamically-created controllers and view templates for such models will then act in a read-only way)
         
     | 
| 
         @@ -755,6 +718,9 @@ class Object 
     | 
|
| 
       755 
718 
     | 
    
         
             
                        code << "  self.primary_key = #{pk_sym.inspect}\n"
         
     | 
| 
       756 
719 
     | 
    
         
             
                      end
         
     | 
| 
       757 
720 
     | 
    
         
             
                      _brick_primary_key(relation) # Set the newly-found PK in the instance variable
         
     | 
| 
      
 721 
     | 
    
         
            +
                    elsif (possible_pk = ActiveRecord::Base.get_primary_key(base_class.name)) && relation[:cols][possible_pk]
         
     | 
| 
      
 722 
     | 
    
         
            +
                      new_model_class.primary_key = (possible_pk = possible_pk.to_sym)
         
     | 
| 
      
 723 
     | 
    
         
            +
                      code << "  self.primary_key = #{possible_pk.inspect}\n"
         
     | 
| 
       758 
724 
     | 
    
         
             
                    else
         
     | 
| 
       759 
725 
     | 
    
         
             
                      code << "  # Could not identify any column(s) to use as a primary key\n" unless is_view
         
     | 
| 
       760 
726 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -792,10 +758,11 @@ class Object 
     | 
|
| 
       792 
758 
     | 
    
         
             
                  end # class definition
         
     | 
| 
       793 
759 
     | 
    
         
             
                  # Having this separate -- will this now work out better?
         
     | 
| 
       794 
760 
     | 
    
         
             
                    built_model.class_exec do
         
     | 
| 
       795 
     | 
    
         
            -
                      hmts 
     | 
| 
      
 761 
     | 
    
         
            +
                      hmts&.each do |hmt_fk, fks|
         
     | 
| 
       796 
762 
     | 
    
         
             
                        hmt_fk = hmt_fk.tr('.', '_')
         
     | 
| 
       797 
763 
     | 
    
         
             
                        fks.each do |fk|
         
     | 
| 
       798 
     | 
    
         
            -
                           
     | 
| 
      
 764 
     | 
    
         
            +
                          # %%% Will not work with custom has_many name
         
     | 
| 
      
 765 
     | 
    
         
            +
                          through = ::Brick.config.schema_behavior[:multitenant] ? fk.first[:assoc_name] : fk.first[:inverse_table].tr('.', '_').pluralize
         
     | 
| 
       799 
766 
     | 
    
         
             
                          hmt_name = if fks.length > 1
         
     | 
| 
       800 
767 
     | 
    
         
             
                                       if fks[0].first[:inverse][:assoc_name] == fks[1].first[:inverse][:assoc_name] # Same BT names pointing back to us? (Most common scenario)
         
     | 
| 
       801 
768 
     | 
    
         
             
                                         "#{hmt_fk}_through_#{fk.first[:assoc_name]}"
         
     | 
| 
         @@ -807,10 +774,15 @@ class Object 
     | 
|
| 
       807 
774 
     | 
    
         
             
                                     else
         
     | 
| 
       808 
775 
     | 
    
         
             
                                       hmt_fk
         
     | 
| 
       809 
776 
     | 
    
         
             
                                     end
         
     | 
| 
       810 
     | 
    
         
            -
                           
     | 
| 
       811 
     | 
    
         
            -
                           
     | 
| 
       812 
     | 
    
         
            -
             
     | 
| 
       813 
     | 
    
         
            -
             
     | 
| 
      
 777 
     | 
    
         
            +
                          options = { through: through.to_sym }
         
     | 
| 
      
 778 
     | 
    
         
            +
                          if relation[:fks].any? { |k, v| v[:assoc_name] == hmt_name }
         
     | 
| 
      
 779 
     | 
    
         
            +
                            hmt_name = "#{hmt_name.singularize}_#{fk.first[:assoc_name]}"
         
     | 
| 
      
 780 
     | 
    
         
            +
                            # binding.pry if relation[:fks].any? { |k, v| v[:assoc_name] == hmt_name }
         
     | 
| 
      
 781 
     | 
    
         
            +
                            options[:class_name] = fk.first[:inverse_table].singularize.camelize
         
     | 
| 
      
 782 
     | 
    
         
            +
                            options[:foreign_key] = fk.first[:fk].to_sym
         
     | 
| 
      
 783 
     | 
    
         
            +
                          end
         
     | 
| 
      
 784 
     | 
    
         
            +
                          options[:source] = fk.last.to_sym unless hmt_name.singularize == fk.last
         
     | 
| 
      
 785 
     | 
    
         
            +
                          code << "  has_many :#{hmt_name}#{options.map { |opt| ", #{opt.first}: #{opt.last.inspect}" }.join}\n"
         
     | 
| 
       814 
786 
     | 
    
         
             
                          self.send(:has_many, hmt_name.to_sym, **options)
         
     | 
| 
       815 
787 
     | 
    
         
             
                        end
         
     | 
| 
       816 
788 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -832,6 +804,7 @@ class Object 
     | 
|
| 
       832 
804 
     | 
    
         
             
                                         else
         
     | 
| 
       833 
805 
     | 
    
         
             
                                           assoc[:assoc_name]
         
     | 
| 
       834 
806 
     | 
    
         
             
                                         end
         
     | 
| 
      
 807 
     | 
    
         
            +
                            options[:optional] = true if assoc.key?(:optional)
         
     | 
| 
       835 
808 
     | 
    
         
             
                            if assoc.key?(:polymorphic)
         
     | 
| 
       836 
809 
     | 
    
         
             
                              options[:polymorphic] = true
         
     | 
| 
       837 
810 
     | 
    
         
             
                            else
         
     | 
| 
         @@ -875,7 +848,11 @@ class Object 
     | 
|
| 
       875 
848 
     | 
    
         
             
                          end
         
     | 
| 
       876 
849 
     | 
    
         
             
                  # Figure out if we need to specially call out the class_name and/or foreign key
         
     | 
| 
       877 
850 
     | 
    
         
             
                  # (and if either of those then definitely also a specific inverse_of)
         
     | 
| 
       878 
     | 
    
         
            -
                   
     | 
| 
      
 851 
     | 
    
         
            +
                  if (singular_table_parts = singular_table_name.split('.')).length > 1 &&
         
     | 
| 
      
 852 
     | 
    
         
            +
                     ::Brick.config.schema_behavior[:multitenant] && singular_table_parts.first == 'public'
         
     | 
| 
      
 853 
     | 
    
         
            +
                    singular_table_parts.shift
         
     | 
| 
      
 854 
     | 
    
         
            +
                  end
         
     | 
| 
      
 855 
     | 
    
         
            +
                  options[:class_name] = "::#{assoc[:primary_class]&.name || singular_table_parts.map(&:camelize).join('::')}" if need_class_name
         
     | 
| 
       879 
856 
     | 
    
         
             
                  # Work around a bug in CPK where self-referencing belongs_to associations double up their foreign keys
         
     | 
| 
       880 
857 
     | 
    
         
             
                  if need_fk # Funky foreign key?
         
     | 
| 
       881 
858 
     | 
    
         
             
                    options[:foreign_key] = if assoc[:fk].is_a?(Array)
         
     | 
| 
         @@ -889,7 +866,6 @@ class Object 
     | 
|
| 
       889 
866 
     | 
    
         | 
| 
       890 
867 
     | 
    
         
             
                  # Prepare a list of entries for "has_many :through"
         
     | 
| 
       891 
868 
     | 
    
         
             
                  if macro == :has_many
         
     | 
| 
       892 
     | 
    
         
            -
                    puts [inverse_table, relations[inverse_table].length].inspect
         
     | 
| 
       893 
869 
     | 
    
         
             
                    relations[inverse_table][:hmt_fks].each do |k, hmt_fk|
         
     | 
| 
       894 
870 
     | 
    
         
             
                      next if k == assoc[:fk]
         
     | 
| 
       895 
871 
     | 
    
         | 
| 
         @@ -905,19 +881,71 @@ class Object 
     | 
|
| 
       905 
881 
     | 
    
         
             
                def build_controller(namespace, class_name, plural_class_name, model, relations)
         
     | 
| 
       906 
882 
     | 
    
         
             
                  table_name = ActiveSupport::Inflector.underscore(plural_class_name)
         
     | 
| 
       907 
883 
     | 
    
         
             
                  singular_table_name = ActiveSupport::Inflector.singularize(table_name)
         
     | 
| 
       908 
     | 
    
         
            -
                  pk = model 
     | 
| 
      
 884 
     | 
    
         
            +
                  pk = model&._brick_primary_key(relations.fetch(table_name, nil))
         
     | 
| 
       909 
885 
     | 
    
         | 
| 
       910 
886 
     | 
    
         
             
                  namespace_name = "#{namespace.name}::" if namespace
         
     | 
| 
       911 
887 
     | 
    
         
             
                  code = +"class #{namespace_name}#{class_name} < ApplicationController\n"
         
     | 
| 
       912 
888 
     | 
    
         
             
                  built_controller = Class.new(ActionController::Base) do |new_controller_class|
         
     | 
| 
       913 
889 
     | 
    
         
             
                    (namespace || Object).const_set(class_name.to_sym, new_controller_class)
         
     | 
| 
       914 
890 
     | 
    
         | 
| 
       915 
     | 
    
         
            -
                     
     | 
| 
       916 
     | 
    
         
            -
             
     | 
| 
       917 
     | 
    
         
            -
             
     | 
| 
       918 
     | 
    
         
            -
             
     | 
| 
      
 891 
     | 
    
         
            +
                    unless (is_swagger = plural_class_name == 'BrickSwagger') # && request.format == :json)
         
     | 
| 
      
 892 
     | 
    
         
            +
                      code << "  def index\n"
         
     | 
| 
      
 893 
     | 
    
         
            +
                      code << "    @#{table_name} = #{model.name}#{pk&.present? ? ".order(#{pk.inspect})" : '.all'}\n"
         
     | 
| 
      
 894 
     | 
    
         
            +
                      code << "    @#{table_name}.brick_select(params)\n"
         
     | 
| 
      
 895 
     | 
    
         
            +
                      code << "  end\n"
         
     | 
| 
      
 896 
     | 
    
         
            +
                    end
         
     | 
| 
       919 
897 
     | 
    
         
             
                    self.protect_from_forgery unless: -> { self.request.format.js? }
         
     | 
| 
       920 
898 
     | 
    
         
             
                    self.define_method :index do
         
     | 
| 
      
 899 
     | 
    
         
            +
                      if is_swagger
         
     | 
| 
      
 900 
     | 
    
         
            +
                        json = { 'openapi': '3.0.1', 'info': { 'title': 'API V1', 'version': 'v1' },
         
     | 
| 
      
 901 
     | 
    
         
            +
                                 'servers': [
         
     | 
| 
      
 902 
     | 
    
         
            +
                                   { 'url': 'https://{defaultHost}', 'variables': { 'defaultHost': { 'default': 'www.example.com' } } }
         
     | 
| 
      
 903 
     | 
    
         
            +
                                 ]
         
     | 
| 
      
 904 
     | 
    
         
            +
                               }
         
     | 
| 
      
 905 
     | 
    
         
            +
                        json['paths'] = relations.inject({}) do |s, v|
         
     | 
| 
      
 906 
     | 
    
         
            +
                          s["/api/v1/#{v.first}"] = {
         
     | 
| 
      
 907 
     | 
    
         
            +
                            'get': {
         
     | 
| 
      
 908 
     | 
    
         
            +
                              'summary': "list #{v.first}",
         
     | 
| 
      
 909 
     | 
    
         
            +
                              'parameters': v.last[:cols].map { |k, v| { 'name' => k, 'schema': { 'type': v.first } } },
         
     | 
| 
      
 910 
     | 
    
         
            +
                              'responses': { '200': { 'description': 'successful' } }
         
     | 
| 
      
 911 
     | 
    
         
            +
                            }
         
     | 
| 
      
 912 
     | 
    
         
            +
                          }
         
     | 
| 
      
 913 
     | 
    
         
            +
                          # next if v.last[:isView]
         
     | 
| 
      
 914 
     | 
    
         
            +
             
     | 
| 
      
 915 
     | 
    
         
            +
                          s["/api/v1/#{v.first}/{id}"] = {
         
     | 
| 
      
 916 
     | 
    
         
            +
                            'patch': {
         
     | 
| 
      
 917 
     | 
    
         
            +
                              'summary': "update a #{v.first.singularize}",
         
     | 
| 
      
 918 
     | 
    
         
            +
                              'parameters': v.last[:cols].reject { |k, v| Brick.config.metadata_columns.include?(k) }.map do |k, v|
         
     | 
| 
      
 919 
     | 
    
         
            +
                                { 'name' => k, 'schema': { 'type': v.first } }
         
     | 
| 
      
 920 
     | 
    
         
            +
                              end,
         
     | 
| 
      
 921 
     | 
    
         
            +
                              'responses': { '200': { 'description': 'successful' } }
         
     | 
| 
      
 922 
     | 
    
         
            +
                            }
         
     | 
| 
      
 923 
     | 
    
         
            +
                            # "/api/v1/books/{id}": {
         
     | 
| 
      
 924 
     | 
    
         
            +
                            #   "parameters": [
         
     | 
| 
      
 925 
     | 
    
         
            +
                            #     {
         
     | 
| 
      
 926 
     | 
    
         
            +
                            #       "name": "id",
         
     | 
| 
      
 927 
     | 
    
         
            +
                            #       "in": "path",
         
     | 
| 
      
 928 
     | 
    
         
            +
                            #       "description": "id",
         
     | 
| 
      
 929 
     | 
    
         
            +
                            #       "required": true,
         
     | 
| 
      
 930 
     | 
    
         
            +
                            #       "schema": {
         
     | 
| 
      
 931 
     | 
    
         
            +
                            #         "type": "string"
         
     | 
| 
      
 932 
     | 
    
         
            +
                            #       }
         
     | 
| 
      
 933 
     | 
    
         
            +
                            #     },
         
     | 
| 
      
 934 
     | 
    
         
            +
                            #     {
         
     | 
| 
      
 935 
     | 
    
         
            +
                            #       "name": "Authorization",
         
     | 
| 
      
 936 
     | 
    
         
            +
                            #       "in": "header",
         
     | 
| 
      
 937 
     | 
    
         
            +
                            #       "schema": {
         
     | 
| 
      
 938 
     | 
    
         
            +
                            #         "type": "string"
         
     | 
| 
      
 939 
     | 
    
         
            +
                            #       }
         
     | 
| 
      
 940 
     | 
    
         
            +
                            #     }
         
     | 
| 
      
 941 
     | 
    
         
            +
                            #   ],
         
     | 
| 
      
 942 
     | 
    
         
            +
                          }
         
     | 
| 
      
 943 
     | 
    
         
            +
                          s
         
     | 
| 
      
 944 
     | 
    
         
            +
                        end
         
     | 
| 
      
 945 
     | 
    
         
            +
                        # binding.pry
         
     | 
| 
      
 946 
     | 
    
         
            +
                        render inline: json.to_json, content_type: request.format
         
     | 
| 
      
 947 
     | 
    
         
            +
                        return
         
     | 
| 
      
 948 
     | 
    
         
            +
                      end
         
     | 
| 
       921 
949 
     | 
    
         
             
                      ::Brick.set_db_schema(params)
         
     | 
| 
       922 
950 
     | 
    
         
             
                      if request.format == :csv # Asking for a template?
         
     | 
| 
       923 
951 
     | 
    
         
             
                        require 'csv'
         
     | 
| 
         @@ -946,7 +974,7 @@ class Object 
     | 
|
| 
       946 
974 
     | 
    
         
             
                      @_brick_join_array = join_array
         
     | 
| 
       947 
975 
     | 
    
         
             
                    end
         
     | 
| 
       948 
976 
     | 
    
         | 
| 
       949 
     | 
    
         
            -
                    if model 
     | 
| 
      
 977 
     | 
    
         
            +
                    if model&.primary_key
         
     | 
| 
       950 
978 
     | 
    
         
             
                      code << "  def show\n"
         
     | 
| 
       951 
979 
     | 
    
         
             
                      code << (find_by_id = "    id = params[:id]&.split(/[\\/,_]/)
         
     | 
| 
       952 
980 
     | 
    
         
             
                id = id.first if id.is_a?(Array) && id.length == 1
         
     | 
| 
         @@ -961,7 +989,7 @@ class Object 
     | 
|
| 
       961 
989 
     | 
    
         
             
                    end
         
     | 
| 
       962 
990 
     | 
    
         | 
| 
       963 
991 
     | 
    
         
             
                    # By default, views get marked as read-only
         
     | 
| 
       964 
     | 
    
         
            -
                    unless  
     | 
| 
      
 992 
     | 
    
         
            +
                    unless is_swagger # model.readonly # (relation = relations[model.table_name]).key?(:isView)
         
     | 
| 
       965 
993 
     | 
    
         
             
                      code << "  # (Define :new, :create)\n"
         
     | 
| 
       966 
994 
     | 
    
         | 
| 
       967 
995 
     | 
    
         
             
                      if model.primary_key
         
     | 
| 
         @@ -993,7 +1021,9 @@ class Object 
     | 
|
| 
       993 
1021 
     | 
    
         
             
                          #   return
         
     | 
| 
       994 
1022 
     | 
    
         
             
                          end
         
     | 
| 
       995 
1023 
     | 
    
         | 
| 
       996 
     | 
    
         
            -
                           
     | 
| 
      
 1024 
     | 
    
         
            +
                          id = params[:id]&.split(/[\/,_]/)
         
     | 
| 
      
 1025 
     | 
    
         
            +
                          id = id.first if id.is_a?(Array) && id.length == 1
         
     | 
| 
      
 1026 
     | 
    
         
            +
                          instance_variable_set("@#{singular_table_name}".to_sym, (obj = model.find(id)))
         
     | 
| 
       997 
1027 
     | 
    
         
             
                          obj = obj.first if obj.is_a?(Array)
         
     | 
| 
       998 
1028 
     | 
    
         
             
                          obj.send(:update, send(params_name = params_name.to_sym))
         
     | 
| 
       999 
1029 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -1018,10 +1048,23 @@ class Object 
     | 
|
| 
       1018 
1048 
     | 
    
         | 
| 
       1019 
1049 
     | 
    
         
             
                def _brick_get_hm_assoc_name(relation, hm_assoc)
         
     | 
| 
       1020 
1050 
     | 
    
         
             
                  if relation[:hm_counts][hm_assoc[:assoc_name]]&.> 1
         
     | 
| 
      
 1051 
     | 
    
         
            +
                    # binding.pry if (same_name = relation[:fks].find { |x| x.last[:assoc_name] == hm_assoc[:assoc_name] && x.last != hm_assoc }) #&&
         
     | 
| 
      
 1052 
     | 
    
         
            +
                                                # x.last[:alternate_name] == hm_assoc[:alternate_name] })
         
     | 
| 
      
 1053 
     | 
    
         
            +
                    # relation[:fks].any? { |k, v| v[:assoc_name] == new_alt_name }
         
     | 
| 
       1021 
1054 
     | 
    
         
             
                    plural = ActiveSupport::Inflector.pluralize(hm_assoc[:alternate_name])
         
     | 
| 
       1022 
     | 
    
         
            -
                     
     | 
| 
      
 1055 
     | 
    
         
            +
                    # binding.pry if hm_assoc[:assoc_name] == 'issue_issue_duplicates'
         
     | 
| 
      
 1056 
     | 
    
         
            +
                    new_alt_name = (hm_assoc[:alternate_name] == name.underscore) ? "#{hm_assoc[:assoc_name].singularize}_#{plural}" : plural
         
     | 
| 
      
 1057 
     | 
    
         
            +
                    # uniq = 1
         
     | 
| 
      
 1058 
     | 
    
         
            +
                    # while same_name = relation[:fks].find { |x| x.last[:assoc_name] == hm_assoc[:assoc_name] && x.last != hm_assoc }
         
     | 
| 
      
 1059 
     | 
    
         
            +
                    #   hm_assoc[:assoc_name] = "#{hm_assoc_name}_#{uniq += 1}"
         
     | 
| 
      
 1060 
     | 
    
         
            +
                    # end
         
     | 
| 
      
 1061 
     | 
    
         
            +
                    # puts new_alt_name
         
     | 
| 
      
 1062 
     | 
    
         
            +
                    # binding.pry if new_alt_name == 'issue_duplicates'
         
     | 
| 
      
 1063 
     | 
    
         
            +
                    # hm_assoc[:assoc_name] = new_alt_name
         
     | 
| 
      
 1064 
     | 
    
         
            +
                    [new_alt_name, true]
         
     | 
| 
       1023 
1065 
     | 
    
         
             
                  else
         
     | 
| 
       1024 
1066 
     | 
    
         
             
                    assoc_name = hm_assoc[:inverse_table].pluralize
         
     | 
| 
      
 1067 
     | 
    
         
            +
                    # hm_assoc[:assoc_name] = assoc_name
         
     | 
| 
       1025 
1068 
     | 
    
         
             
                    [assoc_name, assoc_name.include?('.')]
         
     | 
| 
       1026 
1069 
     | 
    
         
             
                  end
         
     | 
| 
       1027 
1070 
     | 
    
         
             
                end
         
     | 
| 
         @@ -1040,11 +1083,20 @@ module ActiveRecord::ConnectionHandling 
     | 
|
| 
       1040 
1083 
     | 
    
         
             
                conn
         
     | 
| 
       1041 
1084 
     | 
    
         
             
              end
         
     | 
| 
       1042 
1085 
     | 
    
         | 
| 
      
 1086 
     | 
    
         
            +
              # This is done separately so that during testing it can be called right after a migration
         
     | 
| 
      
 1087 
     | 
    
         
            +
              # in order to make sure everything is good.
         
     | 
| 
       1043 
1088 
     | 
    
         
             
              def _brick_reflect_tables
         
     | 
| 
      
 1089 
     | 
    
         
            +
                initializer_loaded = false
         
     | 
| 
       1044 
1090 
     | 
    
         
             
                if (relations = ::Brick.relations).empty?
         
     | 
| 
       1045 
     | 
    
         
            -
                  #  
     | 
| 
      
 1091 
     | 
    
         
            +
                  # If there's schema things configured then we only expect our initializer to be named exactly this
         
     | 
| 
       1046 
1092 
     | 
    
         
             
                  if File.exist?(brick_initializer = Rails.root.join('config/initializers/brick.rb'))
         
     | 
| 
       1047 
     | 
    
         
            -
                    load brick_initializer
         
     | 
| 
      
 1093 
     | 
    
         
            +
                    initializer_loaded = load brick_initializer
         
     | 
| 
      
 1094 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1095 
     | 
    
         
            +
                  # Load the initializer for the Apartment gem a little early so that if .excluded_models and
         
     | 
| 
      
 1096 
     | 
    
         
            +
                  # .default_schema are specified then we can work with non-tenanted models more appropriately
         
     | 
| 
      
 1097 
     | 
    
         
            +
                  if Object.const_defined?('Apartment') && File.exist?(apartment_initializer = Rails.root.join('config/initializers/apartment.rb'))
         
     | 
| 
      
 1098 
     | 
    
         
            +
                    load apartment_initializer
         
     | 
| 
      
 1099 
     | 
    
         
            +
                    apartment_excluded = Apartment.excluded_models
         
     | 
| 
       1048 
1100 
     | 
    
         
             
                  end
         
     | 
| 
       1049 
1101 
     | 
    
         
             
                  # Only for Postgres?  (Doesn't work in sqlite3)
         
     | 
| 
       1050 
1102 
     | 
    
         
             
                  # puts ActiveRecord::Base.execute_sql("SELECT current_setting('SEARCH_PATH')").to_a.inspect
         
     | 
| 
         @@ -1052,24 +1104,53 @@ module ActiveRecord::ConnectionHandling 
     | 
|
| 
       1052 
1104 
     | 
    
         
             
                  schema_sql = 'SELECT NULL AS table_schema;'
         
     | 
| 
       1053 
1105 
     | 
    
         
             
                  case ActiveRecord::Base.connection.adapter_name
         
     | 
| 
       1054 
1106 
     | 
    
         
             
                  when 'PostgreSQL'
         
     | 
| 
       1055 
     | 
    
         
            -
                    if ( 
     | 
| 
      
 1107 
     | 
    
         
            +
                    if (is_multitenant = (multitenancy = ::Brick.config.schema_behavior[:multitenant]) &&
         
     | 
| 
      
 1108 
     | 
    
         
            +
                       (sta = multitenancy[:schema_to_analyse]) != 'public')
         
     | 
| 
      
 1109 
     | 
    
         
            +
                      ::Brick.default_schema = schema = sta
         
     | 
| 
       1056 
1110 
     | 
    
         
             
                      ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?", schema)
         
     | 
| 
       1057 
1111 
     | 
    
         
             
                    end
         
     | 
| 
       1058 
1112 
     | 
    
         
             
                    schema_sql = 'SELECT DISTINCT table_schema FROM INFORMATION_SCHEMA.tables;'
         
     | 
| 
       1059 
1113 
     | 
    
         
             
                  when 'Mysql2'
         
     | 
| 
       1060 
1114 
     | 
    
         
             
                    ::Brick.default_schema = schema = ActiveRecord::Base.connection.current_database
         
     | 
| 
       1061 
1115 
     | 
    
         
             
                  when 'SQLite'
         
     | 
| 
      
 1116 
     | 
    
         
            +
                    # %%% Retrieve internal ActiveRecord table names like this:
         
     | 
| 
      
 1117 
     | 
    
         
            +
                    # ActiveRecord::Base.internal_metadata_table_name, ActiveRecord::Base.schema_migrations_table_name
         
     | 
| 
       1062 
1118 
     | 
    
         
             
                    sql = "SELECT m.name AS relation_name, UPPER(m.type) AS table_type,
         
     | 
| 
       1063 
1119 
     | 
    
         
             
                      p.name AS column_name, p.type AS data_type,
         
     | 
| 
       1064 
1120 
     | 
    
         
             
                      CASE p.pk WHEN 1 THEN 'PRIMARY KEY' END AS const
         
     | 
| 
       1065 
1121 
     | 
    
         
             
                    FROM sqlite_master AS m
         
     | 
| 
       1066 
1122 
     | 
    
         
             
                      INNER JOIN pragma_table_info(m.name) AS p
         
     | 
| 
       1067 
     | 
    
         
            -
                    WHERE m.name NOT IN ( 
     | 
| 
      
 1123 
     | 
    
         
            +
                    WHERE m.name NOT IN (?, ?)
         
     | 
| 
       1068 
1124 
     | 
    
         
             
                    ORDER BY m.name, p.cid"
         
     | 
| 
       1069 
1125 
     | 
    
         
             
                  else
         
     | 
| 
       1070 
1126 
     | 
    
         
             
                    puts "Unfamiliar with connection adapter #{ActiveRecord::Base.connection.adapter_name}"
         
     | 
| 
       1071 
1127 
     | 
    
         
             
                  end
         
     | 
| 
       1072 
1128 
     | 
    
         | 
| 
      
 1129 
     | 
    
         
            +
                  unless (db_schemas = ActiveRecord::Base.execute_sql(schema_sql)).is_a?(Array)
         
     | 
| 
      
 1130 
     | 
    
         
            +
                    db_schemas = db_schemas.to_a
         
     | 
| 
      
 1131 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1132 
     | 
    
         
            +
                  unless db_schemas.empty?
         
     | 
| 
      
 1133 
     | 
    
         
            +
                    ::Brick.db_schemas = db_schemas.each_with_object({}) do |row, s|
         
     | 
| 
      
 1134 
     | 
    
         
            +
                      row = row.is_a?(String) ? row : row['table_schema']
         
     | 
| 
      
 1135 
     | 
    
         
            +
                      # Remove any system schemas
         
     | 
| 
      
 1136 
     | 
    
         
            +
                      s[row] = nil unless ['information_schema', 'pg_catalog'].include?(row)
         
     | 
| 
      
 1137 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1138 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1139 
     | 
    
         
            +
             
     | 
| 
      
 1140 
     | 
    
         
            +
                  if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
         
     | 
| 
      
 1141 
     | 
    
         
            +
                    if (possible_schema = ::Brick.config.schema_behavior&.[](:multitenant)&.[](:schema_to_analyse))
         
     | 
| 
      
 1142 
     | 
    
         
            +
                      if ::Brick.db_schemas.key?(possible_schema)
         
     | 
| 
      
 1143 
     | 
    
         
            +
                        ::Brick.default_schema = schema = possible_schema
         
     | 
| 
      
 1144 
     | 
    
         
            +
                        ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?", schema)
         
     | 
| 
      
 1145 
     | 
    
         
            +
                      else
         
     | 
| 
      
 1146 
     | 
    
         
            +
                        puts "*** In the brick.rb initializer the line \"::Brick.schema_behavior = ...\" refers to a schema called \"#{possible_schema}\".  This schema does not exist. ***"
         
     | 
| 
      
 1147 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1148 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1149 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1150 
     | 
    
         
            +
             
     | 
| 
      
 1151 
     | 
    
         
            +
                  # %%% Retrieve internal ActiveRecord table names like this:
         
     | 
| 
      
 1152 
     | 
    
         
            +
                  # ActiveRecord::Base.internal_metadata_table_name, ActiveRecord::Base.schema_migrations_table_name
         
     | 
| 
      
 1153 
     | 
    
         
            +
                  # For if it's not SQLite -- so this is the Postgres and MySQL version
         
     | 
| 
       1073 
1154 
     | 
    
         
             
                  sql ||= "SELECT t.table_schema AS schema, t.table_name AS relation_name, t.table_type,
         
     | 
| 
       1074 
1155 
     | 
    
         
             
                      c.column_name, c.data_type,
         
     | 
| 
       1075 
1156 
     | 
    
         
             
                      COALESCE(c.character_maximum_length, c.numeric_precision) AS max_length,
         
     | 
| 
         @@ -1091,19 +1172,21 @@ module ActiveRecord::ConnectionHandling 
     | 
|
| 
       1091 
1172 
     | 
    
         
             
                    WHERE t.table_schema NOT IN ('information_schema', 'pg_catalog')#{"
         
     | 
| 
       1092 
1173 
     | 
    
         
             
                      AND t.table_schema = COALESCE(current_setting('SEARCH_PATH'), 'public')" if schema }
         
     | 
| 
       1093 
1174 
     | 
    
         
             
              --          AND t.table_type IN ('VIEW') -- 'BASE TABLE', 'FOREIGN TABLE'
         
     | 
| 
       1094 
     | 
    
         
            -
                      AND t.table_name NOT IN ('pg_stat_statements',  
     | 
| 
      
 1175 
     | 
    
         
            +
                      AND t.table_name NOT IN ('pg_stat_statements', ?, ?)
         
     | 
| 
       1095 
1176 
     | 
    
         
             
                    ORDER BY 1, t.table_type DESC, c.ordinal_position"
         
     | 
| 
       1096 
1177 
     | 
    
         
             
                  measures = []
         
     | 
| 
       1097 
1178 
     | 
    
         
             
                  case ActiveRecord::Base.connection.adapter_name
         
     | 
| 
       1098 
1179 
     | 
    
         
             
                  when 'PostgreSQL', 'SQLite' # These bring back a hash for each row because the query uses column aliases
         
     | 
| 
       1099 
     | 
    
         
            -
                    schema ||= 'public' if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
         
     | 
| 
       1100 
     | 
    
         
            -
                    ActiveRecord::Base.execute_sql(sql).each do |r|
         
     | 
| 
       1101 
     | 
    
         
            -
                      #  
     | 
| 
       1102 
     | 
    
         
            -
                       
     | 
| 
       1103 
     | 
    
         
            -
             
     | 
| 
       1104 
     | 
    
         
            -
                                       
     | 
| 
       1105 
     | 
    
         
            -
             
     | 
| 
       1106 
     | 
    
         
            -
                                       
     | 
| 
      
 1180 
     | 
    
         
            +
                    # schema ||= 'public' if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
         
     | 
| 
      
 1181 
     | 
    
         
            +
                    ActiveRecord::Base.execute_sql(sql, ActiveRecord::Base.internal_metadata_table_name, ActiveRecord::Base.schema_migrations_table_name).each do |r|
         
     | 
| 
      
 1182 
     | 
    
         
            +
                      # If Apartment gem lists the table as being associated with a non-tenanted model then use whatever it thinks
         
     | 
| 
      
 1183 
     | 
    
         
            +
                      # is the default schema, usually 'public'.
         
     | 
| 
      
 1184 
     | 
    
         
            +
                      schema_name = if ::Brick.config.schema_behavior[:multitenant]
         
     | 
| 
      
 1185 
     | 
    
         
            +
                                      Apartment.default_schema if apartment_excluded&.include?(r['relation_name'].singularize.camelize)
         
     | 
| 
      
 1186 
     | 
    
         
            +
                                    elsif ![schema, 'public'].include?(r['schema'])
         
     | 
| 
      
 1187 
     | 
    
         
            +
                                      r['schema']
         
     | 
| 
      
 1188 
     | 
    
         
            +
                                    end
         
     | 
| 
      
 1189 
     | 
    
         
            +
                      relation_name = schema_name ? "#{schema_name}.#{r['relation_name']}" : r['relation_name']
         
     | 
| 
       1107 
1190 
     | 
    
         
             
                      relation = relations[relation_name]
         
     | 
| 
       1108 
1191 
     | 
    
         
             
                      relation[:isView] = true if r['table_type'] == 'VIEW'
         
     | 
| 
       1109 
1192 
     | 
    
         
             
                      col_name = r['column_name']
         
     | 
| 
         @@ -1122,7 +1205,6 @@ module ActiveRecord::ConnectionHandling 
     | 
|
| 
       1122 
1205 
     | 
    
         
             
                    end
         
     | 
| 
       1123 
1206 
     | 
    
         
             
                  else # MySQL2 acts a little differently, bringing back an array for each row
         
     | 
| 
       1124 
1207 
     | 
    
         
             
                    ActiveRecord::Base.execute_sql(sql).each do |r|
         
     | 
| 
       1125 
     | 
    
         
            -
                      # next if internal_views.include?(r['relation_name']) # Skip internal views such as v_all_assessments
         
     | 
| 
       1126 
1208 
     | 
    
         
             
                      relation = relations[(relation_name = r[0])] # here relation represents a table or view from the database
         
     | 
| 
       1127 
1209 
     | 
    
         
             
                      relation[:isView] = true if r[1] == 'VIEW' # table_type
         
     | 
| 
       1128 
1210 
     | 
    
         
             
                      col_name = r[2]
         
     | 
| 
         @@ -1161,7 +1243,7 @@ module ActiveRecord::ConnectionHandling 
     | 
|
| 
       1161 
1243 
     | 
    
         
             
                  #     end
         
     | 
| 
       1162 
1244 
     | 
    
         
             
                  #   end
         
     | 
| 
       1163 
1245 
     | 
    
         
             
                  # end
         
     | 
| 
       1164 
     | 
    
         
            -
                  schema = ::Brick.default_schema # Reset back for this next round of fun
         
     | 
| 
      
 1246 
     | 
    
         
            +
                  # schema = ::Brick.default_schema # Reset back for this next round of fun
         
     | 
| 
       1165 
1247 
     | 
    
         
             
                  case ActiveRecord::Base.connection.adapter_name
         
     | 
| 
       1166 
1248 
     | 
    
         
             
                  when 'PostgreSQL', 'Mysql2'
         
     | 
| 
       1167 
1249 
     | 
    
         
             
                    sql = "SELECT kcu1.CONSTRAINT_SCHEMA, kcu1.TABLE_NAME, kcu1.COLUMN_NAME,
         
     | 
| 
         @@ -1176,7 +1258,7 @@ module ActiveRecord::ConnectionHandling 
     | 
|
| 
       1176 
1258 
     | 
    
         
             
                          AND kcu2.CONSTRAINT_SCHEMA = rc.UNIQUE_CONSTRAINT_SCHEMA
         
     | 
| 
       1177 
1259 
     | 
    
         
             
                          AND kcu2.CONSTRAINT_NAME = rc.UNIQUE_CONSTRAINT_NAME
         
     | 
| 
       1178 
1260 
     | 
    
         
             
                          AND kcu2.ORDINAL_POSITION = kcu1.ORDINAL_POSITION#{"
         
     | 
| 
       1179 
     | 
    
         
            -
             
     | 
| 
      
 1261 
     | 
    
         
            +
                      WHERE kcu1.CONSTRAINT_SCHEMA = COALESCE(current_setting('SEARCH_PATH'), 'public')" if schema }"
         
     | 
| 
       1180 
1262 
     | 
    
         
             
                      # AND kcu2.TABLE_NAME = ?;", Apartment::Tenant.current, table_name
         
     | 
| 
       1181 
1263 
     | 
    
         
             
                  when 'SQLite'
         
     | 
| 
       1182 
1264 
     | 
    
         
             
                    sql = "SELECT m.name, fkl.\"from\", fkl.\"table\", m.name || '_' || fkl.\"from\" AS constraint_name
         
     | 
| 
         @@ -1186,36 +1268,47 @@ module ActiveRecord::ConnectionHandling 
     | 
|
| 
       1186 
1268 
     | 
    
         
             
                  else
         
     | 
| 
       1187 
1269 
     | 
    
         
             
                  end
         
     | 
| 
       1188 
1270 
     | 
    
         
             
                  if sql
         
     | 
| 
       1189 
     | 
    
         
            -
                    ::Brick.default_schema ||= schema ||= 'public' if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
         
     | 
| 
       1190 
     | 
    
         
            -
                    unless (db_schemas = ActiveRecord::Base.execute_sql(schema_sql)).is_a?(Array)
         
     | 
| 
       1191 
     | 
    
         
            -
                      db_schemas = db_schemas.to_a
         
     | 
| 
       1192 
     | 
    
         
            -
                    end
         
     | 
| 
       1193 
     | 
    
         
            -
                    unless db_schemas.empty?
         
     | 
| 
       1194 
     | 
    
         
            -
                      ::Brick.db_schemas = db_schemas.each_with_object({}) do |row, s|
         
     | 
| 
       1195 
     | 
    
         
            -
                        row = row.is_a?(String) ? row : row['table_schema']
         
     | 
| 
       1196 
     | 
    
         
            -
                        # Remove whatever default schema we're using and other system schemas
         
     | 
| 
       1197 
     | 
    
         
            -
                        s[row] = nil unless ['information_schema', 'pg_catalog', schema].include?(row)
         
     | 
| 
       1198 
     | 
    
         
            -
                      end
         
     | 
| 
       1199 
     | 
    
         
            -
                    end
         
     | 
| 
      
 1271 
     | 
    
         
            +
                    # ::Brick.default_schema ||= schema ||= 'public' if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
         
     | 
| 
       1200 
1272 
     | 
    
         
             
                    ActiveRecord::Base.execute_sql(sql).each do |fk|
         
     | 
| 
       1201 
1273 
     | 
    
         
             
                      fk = fk.values unless fk.is_a?(Array)
         
     | 
| 
      
 1274 
     | 
    
         
            +
                      # Multitenancy makes things a little more general overall, except for non-tenanted tables
         
     | 
| 
      
 1275 
     | 
    
         
            +
                      if apartment_excluded&.include?(fk[1].singularize.camelize)
         
     | 
| 
      
 1276 
     | 
    
         
            +
                        fk[0] = Apartment.default_schema
         
     | 
| 
      
 1277 
     | 
    
         
            +
                      elsif fk[0] == 'public' || (is_multitenant && fk[0] == schema)
         
     | 
| 
      
 1278 
     | 
    
         
            +
                        fk[0] = nil
         
     | 
| 
      
 1279 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1280 
     | 
    
         
            +
                      if apartment_excluded&.include?(fk[4].singularize.camelize)
         
     | 
| 
      
 1281 
     | 
    
         
            +
                        fk[3] = Apartment.default_schema
         
     | 
| 
      
 1282 
     | 
    
         
            +
                      elsif fk[3] == 'public' || (is_multitenant && fk[3] == schema)
         
     | 
| 
      
 1283 
     | 
    
         
            +
                        fk[3] = nil
         
     | 
| 
      
 1284 
     | 
    
         
            +
                      end
         
     | 
| 
       1202 
1285 
     | 
    
         
             
                      ::Brick._add_bt_and_hm(fk, relations)
         
     | 
| 
       1203 
1286 
     | 
    
         
             
                    end
         
     | 
| 
       1204 
1287 
     | 
    
         
             
                  end
         
     | 
| 
       1205 
1288 
     | 
    
         
             
                end
         
     | 
| 
       1206 
1289 
     | 
    
         | 
| 
       1207 
     | 
    
         
            -
                 
     | 
| 
       1208 
     | 
    
         
            -
                 
     | 
| 
       1209 
     | 
    
         
            -
                 
     | 
| 
      
 1290 
     | 
    
         
            +
                apartment = Object.const_defined?('Apartment') && Apartment
         
     | 
| 
      
 1291 
     | 
    
         
            +
                tables = []
         
     | 
| 
      
 1292 
     | 
    
         
            +
                views = []
         
     | 
| 
      
 1293 
     | 
    
         
            +
                relations.each do |k, v|
         
     | 
| 
      
 1294 
     | 
    
         
            +
                  name_parts = k.split('.')
         
     | 
| 
      
 1295 
     | 
    
         
            +
                  if v.key?(:isView)
         
     | 
| 
      
 1296 
     | 
    
         
            +
                    views
         
     | 
| 
      
 1297 
     | 
    
         
            +
                  else
         
     | 
| 
      
 1298 
     | 
    
         
            +
                    name_parts.shift if apartment && name_parts.length > 1 && name_parts.first == Apartment.default_schema
         
     | 
| 
      
 1299 
     | 
    
         
            +
                    tables
         
     | 
| 
      
 1300 
     | 
    
         
            +
                  end << name_parts.map { |x| x.singularize.camelize }.join('::')
         
     | 
| 
      
 1301 
     | 
    
         
            +
                end
         
     | 
| 
      
 1302 
     | 
    
         
            +
                unless tables.empty?
         
     | 
| 
      
 1303 
     | 
    
         
            +
                  puts "\nClasses that can be built from tables:"
         
     | 
| 
      
 1304 
     | 
    
         
            +
                  tables.sort.each { |x| puts x }
         
     | 
| 
      
 1305 
     | 
    
         
            +
                end
         
     | 
| 
      
 1306 
     | 
    
         
            +
                unless views.empty?
         
     | 
| 
       1210 
1307 
     | 
    
         
             
                  puts "\nClasses that can be built from views:"
         
     | 
| 
       1211 
     | 
    
         
            -
                  views. 
     | 
| 
      
 1308 
     | 
    
         
            +
                  views.sort.each { |x| puts x }
         
     | 
| 
       1212 
1309 
     | 
    
         
             
                end
         
     | 
| 
       1213 
1310 
     | 
    
         | 
| 
       1214 
     | 
    
         
            -
                 
     | 
| 
       1215 
     | 
    
         
            -
                if File.exist?(brick_initialiser = Rails.root.join('config/initializers/brick.rb'))
         
     | 
| 
       1216 
     | 
    
         
            -
                  load brick_initialiser
         
     | 
| 
       1217 
     | 
    
         
            -
                  ::Brick.load_additional_references
         
     | 
| 
       1218 
     | 
    
         
            -
                end
         
     | 
| 
      
 1311 
     | 
    
         
            +
                ::Brick.load_additional_references if initializer_loaded
         
     | 
| 
       1219 
1312 
     | 
    
         
             
              end
         
     | 
| 
       1220 
1313 
     | 
    
         
             
            end
         
     | 
| 
       1221 
1314 
     | 
    
         | 
| 
         @@ -1242,31 +1335,52 @@ module Brick 
     | 
|
| 
       1242 
1335 
     | 
    
         
             
              # rubocop:enable Style/CommentedKeyword
         
     | 
| 
       1243 
1336 
     | 
    
         | 
| 
       1244 
1337 
     | 
    
         
             
              class << self
         
     | 
| 
       1245 
     | 
    
         
            -
                def _add_bt_and_hm(fk, relations, is_polymorphic = false)
         
     | 
| 
       1246 
     | 
    
         
            -
                   
     | 
| 
       1247 
     | 
    
         
            -
             
     | 
| 
       1248 
     | 
    
         
            -
             
     | 
| 
       1249 
     | 
    
         
            -
             
     | 
| 
       1250 
     | 
    
         
            -
             
     | 
| 
       1251 
     | 
    
         
            -
             
     | 
| 
      
 1338 
     | 
    
         
            +
                def _add_bt_and_hm(fk, relations, is_polymorphic = false, is_optional = false)
         
     | 
| 
      
 1339 
     | 
    
         
            +
                  bt_assoc_name = fk[2]
         
     | 
| 
      
 1340 
     | 
    
         
            +
                  unless is_polymorphic
         
     | 
| 
      
 1341 
     | 
    
         
            +
                    bt_assoc_name = if bt_assoc_name.underscore.end_with?('_id')
         
     | 
| 
      
 1342 
     | 
    
         
            +
                                      bt_assoc_name[0..-4]
         
     | 
| 
      
 1343 
     | 
    
         
            +
                                    elsif bt_assoc_name.downcase.end_with?('id') && bt_assoc_name.exclude?('_')
         
     | 
| 
      
 1344 
     | 
    
         
            +
                                      bt_assoc_name[0..-3] # Make the bold assumption that we can just peel off any final ID part
         
     | 
| 
      
 1345 
     | 
    
         
            +
                                    else
         
     | 
| 
      
 1346 
     | 
    
         
            +
                                      "#{bt_assoc_name}_bt"
         
     | 
| 
      
 1347 
     | 
    
         
            +
                                    end
         
     | 
| 
       1252 
1348 
     | 
    
         
             
                  end
         
     | 
| 
       1253 
1349 
     | 
    
         
             
                  # %%% Temporary schema patch
         
     | 
| 
       1254 
     | 
    
         
            -
                   
     | 
| 
       1255 
     | 
    
         
            -
                   
     | 
| 
      
 1350 
     | 
    
         
            +
                  for_tbl = fk[1]
         
     | 
| 
      
 1351 
     | 
    
         
            +
                  apartment = Object.const_defined?('Apartment') && Apartment
         
     | 
| 
      
 1352 
     | 
    
         
            +
                  fk[0] = Apartment.default_schema if apartment && apartment.excluded_models.include?(for_tbl.singularize.camelize)
         
     | 
| 
      
 1353 
     | 
    
         
            +
                  fk[1] = "#{fk[0]}.#{fk[1]}" if fk[0] # && fk[0] != ::Brick.default_schema
         
     | 
| 
       1256 
1354 
     | 
    
         
             
                  bts = (relation = relations.fetch(fk[1], nil))&.fetch(:fks) { relation[:fks] = {} }
         
     | 
| 
      
 1355 
     | 
    
         
            +
             
     | 
| 
       1257 
1356 
     | 
    
         
             
                  # %%% Do we miss out on has_many :through or even HM based on constantizing this model early?
         
     | 
| 
       1258 
1357 
     | 
    
         
             
                  # Maybe it's already gotten this info because we got as far as to say there was a unique class
         
     | 
| 
       1259 
1358 
     | 
    
         
             
                  primary_table = if (is_class = fk[4].is_a?(Hash) && fk[4].key?(:class))
         
     | 
| 
       1260 
1359 
     | 
    
         
             
                                    pri_tbl = (primary_class = fk[4][:class].constantize).table_name
         
     | 
| 
      
 1360 
     | 
    
         
            +
                                    if (pri_tbl_parts = pri_tbl.split('.')).length > 1
         
     | 
| 
      
 1361 
     | 
    
         
            +
                                      fk[3] = pri_tbl_parts.first
         
     | 
| 
      
 1362 
     | 
    
         
            +
                                    end
         
     | 
| 
       1261 
1363 
     | 
    
         
             
                                  else
         
     | 
| 
      
 1364 
     | 
    
         
            +
                                    is_schema = if ::Brick.config.schema_behavior[:multitenant]
         
     | 
| 
      
 1365 
     | 
    
         
            +
                                                  # If Apartment gem lists the primary table as being associated with a non-tenanted model
         
     | 
| 
      
 1366 
     | 
    
         
            +
                                                  # then use 'public' schema for the primary table
         
     | 
| 
      
 1367 
     | 
    
         
            +
                                                  if apartment&.excluded_models.include?(fk[4].singularize.camelize)
         
     | 
| 
      
 1368 
     | 
    
         
            +
                                                    fk[3] = Apartment.default_schema
         
     | 
| 
      
 1369 
     | 
    
         
            +
                                                    true
         
     | 
| 
      
 1370 
     | 
    
         
            +
                                                  end
         
     | 
| 
      
 1371 
     | 
    
         
            +
                                                else
         
     | 
| 
      
 1372 
     | 
    
         
            +
                                                  fk[3] && fk[3] != ::Brick.default_schema && fk[3] != 'public'
         
     | 
| 
      
 1373 
     | 
    
         
            +
                                                end
         
     | 
| 
       1262 
1374 
     | 
    
         
             
                                    pri_tbl = fk[4]
         
     | 
| 
       1263 
     | 
    
         
            -
                                     
     | 
| 
      
 1375 
     | 
    
         
            +
                                    is_schema ? "#{fk[3]}.#{pri_tbl}" : pri_tbl
         
     | 
| 
       1264 
1376 
     | 
    
         
             
                                  end
         
     | 
| 
       1265 
1377 
     | 
    
         
             
                  hms = (relation = relations.fetch(primary_table, nil))&.fetch(:fks) { relation[:fks] = {} } unless is_class
         
     | 
| 
       1266 
1378 
     | 
    
         | 
| 
       1267 
1379 
     | 
    
         
             
                  unless (cnstr_name = fk[5])
         
     | 
| 
       1268 
1380 
     | 
    
         
             
                    # For any appended references (those that come from config), arrive upon a definitely unique constraint name
         
     | 
| 
       1269 
     | 
    
         
            -
                     
     | 
| 
      
 1381 
     | 
    
         
            +
                    pri_tbl = is_class ? fk[4][:class].underscore : pri_tbl
         
     | 
| 
      
 1382 
     | 
    
         
            +
                    pri_tbl = "#{bt_assoc_name}_#{pri_tbl}" if pri_tbl.singularize != bt_assoc_name
         
     | 
| 
      
 1383 
     | 
    
         
            +
                    cnstr_base = cnstr_name = "(brick) #{for_tbl}_#{pri_tbl}"
         
     | 
| 
       1270 
1384 
     | 
    
         
             
                    cnstr_added_num = 1
         
     | 
| 
       1271 
1385 
     | 
    
         
             
                    cnstr_name = "#{cnstr_base}_#{cnstr_added_num += 1}" while bts&.key?(cnstr_name) || hms&.key?(cnstr_name)
         
     | 
| 
       1272 
1386 
     | 
    
         
             
                    missing = []
         
     | 
| 
         @@ -1306,6 +1420,7 @@ module Brick 
     | 
|
| 
       1306 
1420 
     | 
    
         
             
                  else
         
     | 
| 
       1307 
1421 
     | 
    
         
             
                    inverse_table = [primary_table] if is_polymorphic
         
     | 
| 
       1308 
1422 
     | 
    
         
             
                    assoc_bt = bts[cnstr_name] = { is_bt: true, fk: fk[2], assoc_name: bt_assoc_name, inverse_table: inverse_table || primary_table }
         
     | 
| 
      
 1423 
     | 
    
         
            +
                    assoc_bt[:optional] = true if is_optional
         
     | 
| 
       1309 
1424 
     | 
    
         
             
                    assoc_bt[:polymorphic] = true if is_polymorphic
         
     | 
| 
       1310 
1425 
     | 
    
         
             
                  end
         
     | 
| 
       1311 
1426 
     | 
    
         
             
                  if is_class
         
     | 
| 
         @@ -1326,7 +1441,14 @@ module Brick 
     | 
|
| 
       1326 
1441 
     | 
    
         
             
                    assoc_hm[:alternate_name] = "#{assoc_hm[:alternate_name]}_#{bt_assoc_name}" unless assoc_hm[:alternate_name] == bt_assoc_name
         
     | 
| 
       1327 
1442 
     | 
    
         
             
                    assoc_hm[:inverse] = assoc_bt
         
     | 
| 
       1328 
1443 
     | 
    
         
             
                  else
         
     | 
| 
       1329 
     | 
    
         
            -
                     
     | 
| 
      
 1444 
     | 
    
         
            +
                    inv_tbl = if ::Brick.config.schema_behavior[:multitenant] && apartment && fk[0] == Apartment.default_schema
         
     | 
| 
      
 1445 
     | 
    
         
            +
                                for_tbl
         
     | 
| 
      
 1446 
     | 
    
         
            +
                              else
         
     | 
| 
      
 1447 
     | 
    
         
            +
                                fk[1]
         
     | 
| 
      
 1448 
     | 
    
         
            +
                              end
         
     | 
| 
      
 1449 
     | 
    
         
            +
                              # binding.pry if inv_tbl == 'issue_issue_duplicates' # inverse_table goofed?
         
     | 
| 
      
 1450 
     | 
    
         
            +
                    assoc_hm = hms[hm_cnstr_name] = { is_bt: false, fk: fk[2], assoc_name: for_tbl.pluralize, alternate_name: bt_assoc_name,
         
     | 
| 
      
 1451 
     | 
    
         
            +
                                                      inverse_table: inv_tbl, inverse: assoc_bt }
         
     | 
| 
       1330 
1452 
     | 
    
         
             
                    assoc_hm[:polymorphic] = true if is_polymorphic
         
     | 
| 
       1331 
1453 
     | 
    
         
             
                    hm_counts = relation.fetch(:hm_counts) { relation[:hm_counts] = {} }
         
     | 
| 
       1332 
1454 
     | 
    
         
             
                    hm_counts[fk[1]] = hm_counts.fetch(fk[1]) { 0 } + 1
         
     | 
| 
         @@ -124,8 +124,15 @@ module Brick 
     | 
|
| 
       124 
124 
     | 
    
         
             
                          schema_options = ::Brick.db_schemas.keys.each_with_object(+'') { |v, s| s << "<option value=\"#{v}\">#{v}</option>" }.html_safe
         
     | 
| 
       125 
125 
     | 
    
         
             
                          # %%% If we are not auto-creating controllers (or routes) then omit by default, and if enabled anyway, such as in a development
         
     | 
| 
       126 
126 
     | 
    
         
             
                          # environment or whatever, then get either the controllers or routes list instead
         
     | 
| 
       127 
     | 
    
         
            -
                           
     | 
| 
       128 
     | 
    
         
            -
             
     | 
| 
      
 127 
     | 
    
         
            +
                          apartment_default_schema = ::Brick.config.schema_behavior[:multitenant] && Object.const_defined?('Apartment') && Apartment.default_schema
         
     | 
| 
      
 128 
     | 
    
         
            +
                          table_options = (::Brick.relations.keys - ::Brick.config.exclude_tables).map do |tbl|
         
     | 
| 
      
 129 
     | 
    
         
            +
                                            if (tbl_parts = tbl.split('.')).first == apartment_default_schema
         
     | 
| 
      
 130 
     | 
    
         
            +
                                              tbl = tbl_parts.last
         
     | 
| 
      
 131 
     | 
    
         
            +
                                            end
         
     | 
| 
      
 132 
     | 
    
         
            +
                                            tbl
         
     | 
| 
      
 133 
     | 
    
         
            +
                                          end.sort.each_with_object(+'') do |v, s|
         
     | 
| 
      
 134 
     | 
    
         
            +
                                            s << "<option value=\"#{v.underscore.gsub('.', '/').pluralize}\">#{v}</option>"
         
     | 
| 
      
 135 
     | 
    
         
            +
                                          end.html_safe
         
     | 
| 
       129 
136 
     | 
    
         
             
                          css = +"<style>
         
     | 
| 
       130 
137 
     | 
    
         
             
            #dropper {
         
     | 
| 
       131 
138 
     | 
    
         
             
              background-color: #eee;
         
     | 
| 
         @@ -222,7 +229,7 @@ end %>" 
     | 
|
| 
       222 
229 
     | 
    
         
             
                          if ['index', 'show', 'update'].include?(args.first)
         
     | 
| 
       223 
230 
     | 
    
         
             
                            poly_cols = []
         
     | 
| 
       224 
231 
     | 
    
         
             
                            css << "<% bts = { #{
         
     | 
| 
       225 
     | 
    
         
            -
                              bts.each_with_object([]) do |v, s|
         
     | 
| 
      
 232 
     | 
    
         
            +
                              bt_items = bts.each_with_object([]) do |v, s|
         
     | 
| 
       226 
233 
     | 
    
         
             
                                foreign_models = if v.last[2] # Polymorphic?
         
     | 
| 
       227 
234 
     | 
    
         
             
                                                   poly_cols << @_brick_model.reflect_on_association(v[1].first).foreign_type
         
     | 
| 
       228 
235 
     | 
    
         
             
                                                   v.last[1].each_with_object([]) { |x, s| s << "[#{x.name}, #{x.primary_key.inspect}]" }.join(', ')
         
     | 
| 
         @@ -230,14 +237,18 @@ end %>" 
     | 
|
| 
       230 
237 
     | 
    
         
             
                                                   "[#{v.last[1].name}, #{v.last[1].primary_key.inspect}]"
         
     | 
| 
       231 
238 
     | 
    
         
             
                                                 end
         
     | 
| 
       232 
239 
     | 
    
         
             
                                s << "#{v.first.inspect} => [#{v.last.first.inspect}, [#{foreign_models}], #{v.last[2].inspect}]"
         
     | 
| 
       233 
     | 
    
         
            -
                              end 
     | 
| 
      
 240 
     | 
    
         
            +
                              end
         
     | 
| 
      
 241 
     | 
    
         
            +
                              # # %%% Need to fix poly going to an STI class
         
     | 
| 
      
 242 
     | 
    
         
            +
                              # binding.pry unless poly_cols.empty?
         
     | 
| 
      
 243 
     | 
    
         
            +
                              bt_items.join(', ')
         
     | 
| 
       234 
244 
     | 
    
         
             
                            } }
         
     | 
| 
       235 
245 
     | 
    
         
             
                            poly_cols = #{poly_cols.inspect} %>"
         
     | 
| 
       236 
246 
     | 
    
         
             
                          end
         
     | 
| 
       237 
247 
     | 
    
         | 
| 
       238 
     | 
    
         
            -
                          # %%% When doing schema select, if  
     | 
| 
      
 248 
     | 
    
         
            +
                          # %%% When doing schema select, if we're on a new page go to index
         
     | 
| 
       239 
249 
     | 
    
         
             
                          script = "<script>
         
     | 
| 
       240 
250 
     | 
    
         
             
            var schemaSelect = document.getElementById(\"schema\");
         
     | 
| 
      
 251 
     | 
    
         
            +
            var tblSelect = document.getElementById(\"tbl\");
         
     | 
| 
       241 
252 
     | 
    
         
             
            var brickSchema;
         
     | 
| 
       242 
253 
     | 
    
         
             
            if (schemaSelect) {
         
     | 
| 
       243 
254 
     | 
    
         
             
              brickSchema = changeout(location.href, \"_brick_schema\");
         
     | 
| 
         @@ -247,7 +258,8 @@ if (schemaSelect) { 
     | 
|
| 
       247 
258 
     | 
    
         
             
              schemaSelect.value = brickSchema || \"public\";
         
     | 
| 
       248 
259 
     | 
    
         
             
              schemaSelect.focus();
         
     | 
| 
       249 
260 
     | 
    
         
             
              schemaSelect.addEventListener(\"change\", function () {
         
     | 
| 
       250 
     | 
    
         
            -
                 
     | 
| 
      
 261 
     | 
    
         
            +
                // If there's an ID then remove it (trim after selected table)
         
     | 
| 
      
 262 
     | 
    
         
            +
                location.href = changeout(location.href, \"_brick_schema\", this.value, tblSelect.value);
         
     | 
| 
       251 
263 
     | 
    
         
             
              });
         
     | 
| 
       252 
264 
     | 
    
         
             
            }
         
     | 
| 
       253 
265 
     | 
    
         
             
            [... document.getElementsByTagName(\"FORM\")].forEach(function (form) {
         
     | 
| 
         @@ -262,7 +274,6 @@ if (schemaSelect) { 
     | 
|
| 
       262 
274 
     | 
    
         
             
              });
         
     | 
| 
       263 
275 
     | 
    
         
             
            });
         
     | 
| 
       264 
276 
     | 
    
         | 
| 
       265 
     | 
    
         
            -
            var tblSelect = document.getElementById(\"tbl\");
         
     | 
| 
       266 
277 
     | 
    
         
             
            if (tblSelect) {
         
     | 
| 
       267 
278 
     | 
    
         
             
              tblSelect.value = changeout(location.href)[0];
         
     | 
| 
       268 
279 
     | 
    
         
             
              if (tblSelect.selectedIndex < 0) tblSelect.value = changeout(location.href)[1];
         
     | 
| 
         @@ -274,7 +285,7 @@ if (tblSelect) { 
     | 
|
| 
       274 
285 
     | 
    
         
             
              });
         
     | 
| 
       275 
286 
     | 
    
         
             
            }
         
     | 
| 
       276 
287 
     | 
    
         | 
| 
       277 
     | 
    
         
            -
            function changeout(href, param, value) {
         
     | 
| 
      
 288 
     | 
    
         
            +
            function changeout(href, param, value, trimAfter) {
         
     | 
| 
       278 
289 
     | 
    
         
             
              var hrefParts = href.split(\"?\");
         
     | 
| 
       279 
290 
     | 
    
         
             
              if (param === undefined || param === null) {
         
     | 
| 
       280 
291 
     | 
    
         
             
                hrefParts = hrefParts[0].split(\"://\");
         
     | 
| 
         @@ -285,6 +296,11 @@ function changeout(href, param, value) { 
     | 
|
| 
       285 
296 
     | 
    
         
             
                else
         
     | 
| 
       286 
297 
     | 
    
         
             
                  return hrefParts[0] + \"://\" + pathParts[0] + \"/\" + value;
         
     | 
| 
       287 
298 
     | 
    
         
             
              }
         
     | 
| 
      
 299 
     | 
    
         
            +
              if (trimAfter) {
         
     | 
| 
      
 300 
     | 
    
         
            +
                var pathParts = hrefParts[0].split(\"/\");
         
     | 
| 
      
 301 
     | 
    
         
            +
                while (pathParts.lastIndexOf(trimAfter) != pathParts.length - 1) pathParts.pop();
         
     | 
| 
      
 302 
     | 
    
         
            +
                hrefParts[0] = pathParts.join(\"/\");
         
     | 
| 
      
 303 
     | 
    
         
            +
              }
         
     | 
| 
       288 
304 
     | 
    
         
             
              var params = hrefParts.length > 1 ? hrefParts[1].split(\"&\") : [];
         
     | 
| 
       289 
305 
     | 
    
         
             
              params = params.reduce(function (s, v) { var parts = v.split(\"=\"); s[parts[0]] = parts[1]; return s; }, {});
         
     | 
| 
       290 
306 
     | 
    
         
             
              if (value === undefined) return params[param];
         
     | 
| 
         @@ -404,7 +420,7 @@ function changeout(href, param, value) { 
     | 
|
| 
       404 
420 
     | 
    
         
             
                   origin = (key_parts = k.split('.')).length == 1 ? #{model_name} : #{model_name}.reflect_on_association(key_parts.first).klass
         
     | 
| 
       405 
421 
     | 
    
         
             
                  #  binding.pry
         
     | 
| 
       406 
422 
     | 
    
         
             
                   if (destination_fk = Brick.relations[origin.table_name][:fks].values.find { |fk| puts fk.inspect; fk[:fk] == key_parts.last }) &&
         
     | 
| 
       407 
     | 
    
         
            -
             
     | 
| 
      
 423 
     | 
    
         
            +
                      (obj = (destination = origin.reflect_on_association(destination_fk[:assoc_name])&.klass)&.find(id)) %>
         
     | 
| 
       408 
424 
     | 
    
         
             
                     <h3>for <%= link_to \"#{"#\{obj.brick_descrip\} (#\{destination.name\})\""}, send(\"#\{destination.name.underscore.tr('/', '_')\}_path\".to_sym, id) %></h3><%
         
     | 
| 
       409 
425 
     | 
    
         
             
                   end
         
     | 
| 
       410 
426 
     | 
    
         
             
                 end %>
         
     | 
| 
         @@ -563,7 +579,7 @@ function changeout(href, param, value) { 
     | 
|
| 
       563 
579 
     | 
    
         
             
                  s << "<table id=\"#{hm_name}\">
         
     | 
| 
       564 
580 
     | 
    
         
             
                    <tr><th>#{hm[3]}</th></tr>
         
     | 
| 
       565 
581 
     | 
    
         
             
                    <% collection = @#{obj_name}.#{hm_name}
         
     | 
| 
       566 
     | 
    
         
            -
                    collection = collection.is_a?(ActiveRecord::Associations::CollectionProxy) ? collection.order(#{pk.inspect}) : [collection]
         
     | 
| 
      
 582 
     | 
    
         
            +
                    collection = collection.is_a?(ActiveRecord::Associations::CollectionProxy) ? collection.order(#{pk.inspect}) : [collection].compact
         
     | 
| 
       567 
583 
     | 
    
         
             
                    if collection.empty? %>
         
     | 
| 
       568 
584 
     | 
    
         
             
                      <tr><td>(none)</td></tr>
         
     | 
| 
       569 
585 
     | 
    
         
             
                    <% else %>
         
     | 
| 
         @@ -597,6 +613,7 @@ function changeout(href, param, value) { 
     | 
|
| 
       597 
613 
     | 
    
         | 
| 
       598 
614 
     | 
    
         
             
                    # Just in case it hadn't been done previously when we tried to load the brick initialiser,
         
     | 
| 
       599 
615 
     | 
    
         
             
                    # go make sure we've loaded additional references (virtual foreign keys and polymorphic associations).
         
     | 
| 
      
 616 
     | 
    
         
            +
                    # (This should only happen if for whatever reason the initializer file was not exactly config/initializers/brick.rb.)
         
     | 
| 
       600 
617 
     | 
    
         
             
                    ::Brick.load_additional_references
         
     | 
| 
       601 
618 
     | 
    
         
             
                  end
         
     | 
| 
       602 
619 
     | 
    
         
             
                end
         
     | 
    
        data/lib/brick/version_number.rb
    CHANGED
    
    
    
        data/lib/brick.rb
    CHANGED
    
    | 
         @@ -93,16 +93,19 @@ module Brick 
     | 
|
| 
       93 
93 
     | 
    
         
             
                attr_accessor :default_schema, :db_schemas
         
     | 
| 
       94 
94 
     | 
    
         | 
| 
       95 
95 
     | 
    
         
             
                def set_db_schema(params)
         
     | 
| 
       96 
     | 
    
         
            -
                  schema = params['_brick_schema']
         
     | 
| 
      
 96 
     | 
    
         
            +
                  schema = params['_brick_schema'] || 'public'
         
     | 
| 
       97 
97 
     | 
    
         
             
                  ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?;", schema) if schema && ::Brick.db_schemas&.include?(schema)
         
     | 
| 
       98 
98 
     | 
    
         
             
                end
         
     | 
| 
       99 
99 
     | 
    
         | 
| 
       100 
100 
     | 
    
         
             
                # All tables and views (what Postgres calls "relations" including column and foreign key info)
         
     | 
| 
       101 
101 
     | 
    
         
             
                def relations
         
     | 
| 
       102 
     | 
    
         
            -
                  connections = Brick.instance_variable_get(:@relations) ||
         
     | 
| 
       103 
     | 
    
         
            -
                    Brick.instance_variable_set(:@relations, (connections = {}))
         
     | 
| 
       104 
102 
     | 
    
         
             
                  # Key our list of relations for this connection off of the connection pool's object_id
         
     | 
| 
       105 
     | 
    
         
            -
                  ( 
     | 
| 
      
 103 
     | 
    
         
            +
                  (@relations ||= {})[ActiveRecord::Base.connection_pool.object_id] ||= Hash.new { |h, k| h[k] = Hash.new { |h, k| h[k] = {} } }
         
     | 
| 
      
 104 
     | 
    
         
            +
                end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                # If multitenancy is enabled, a list of non-tenanted "global" models
         
     | 
| 
      
 107 
     | 
    
         
            +
                def non_tenanted_models
         
     | 
| 
      
 108 
     | 
    
         
            +
                  @pending_models ||= {}
         
     | 
| 
       106 
109 
     | 
    
         
             
                end
         
     | 
| 
       107 
110 
     | 
    
         | 
| 
       108 
111 
     | 
    
         
             
                def get_bts_and_hms(model)
         
     | 
| 
         @@ -129,6 +132,7 @@ module Brick 
     | 
|
| 
       129 
132 
     | 
    
         
             
                  associatives = hms.each_with_object({}) do |hmt, s|
         
     | 
| 
       130 
133 
     | 
    
         
             
                    if (through = hmt.last.options[:through])
         
     | 
| 
       131 
134 
     | 
    
         
             
                      skip_hms[through] = nil
         
     | 
| 
      
 135 
     | 
    
         
            +
                      # binding.pry if hmt.first == :issue_issues
         
     | 
| 
       132 
136 
     | 
    
         
             
                      s[hmt.first] = hms[through] # End up with a hash of HMT names pointing to join-table associations
         
     | 
| 
       133 
137 
     | 
    
         
             
                    elsif hmt.last.inverse_of.nil?
         
     | 
| 
       134 
138 
     | 
    
         
             
                      puts "SKIPPING #{hmt.last.name.inspect}"
         
     | 
| 
         @@ -314,7 +318,7 @@ module Brick 
     | 
|
| 
       314 
318 
     | 
    
         
             
                    if ars
         
     | 
| 
       315 
319 
     | 
    
         
             
                      ars.each do |ar|
         
     | 
| 
       316 
320 
     | 
    
         
             
                        fk = ar.length < 5 ? [nil, +ar[0], ar[1], nil, +ar[2]] : [ar[0], +ar[1], ar[2], ar[3], +ar[4], ar[5]]
         
     | 
| 
       317 
     | 
    
         
            -
                        ::Brick._add_bt_and_hm(fk, relations)
         
     | 
| 
      
 321 
     | 
    
         
            +
                        ::Brick._add_bt_and_hm(fk, relations, false, true)
         
     | 
| 
       318 
322 
     | 
    
         
             
                      end
         
     | 
| 
       319 
323 
     | 
    
         
             
                    end
         
     | 
| 
       320 
324 
     | 
    
         
             
                    if (polys = ::Brick.config.polymorphics)
         
     | 
| 
         @@ -327,7 +331,7 @@ module Brick 
     | 
|
| 
       327 
331 
     | 
    
         
             
                        v ||= ActiveRecord::Base.execute_sql("SELECT DISTINCT #{poly}_type AS typ FROM #{table_name}").each_with_object([]) { |result, s| s << result['typ'] if result['typ'] }
         
     | 
| 
       328 
332 
     | 
    
         
             
                        v.each do |type|
         
     | 
| 
       329 
333 
     | 
    
         
             
                          if relations.key?(primary_table = type.underscore.pluralize)
         
     | 
| 
       330 
     | 
    
         
            -
                            ::Brick._add_bt_and_hm([nil, table_name, poly, nil, primary_table, "(brick) #{table_name}_#{poly}"], relations, true)
         
     | 
| 
      
 334 
     | 
    
         
            +
                            ::Brick._add_bt_and_hm([nil, table_name, poly, nil, primary_table, "(brick) #{table_name}_#{poly}"], relations, true, true)
         
     | 
| 
       331 
335 
     | 
    
         
             
                          else
         
     | 
| 
       332 
336 
     | 
    
         
             
                            missing_stis[primary_table] = type unless ::Brick.existing_stis.key?(type)
         
     | 
| 
       333 
337 
     | 
    
         
             
                          end
         
     | 
| 
         @@ -406,6 +410,7 @@ In config/initializers/brick.rb appropriate entries would look something like: 
     | 
|
| 
       406 
410 
     | 
    
         
             
                    ::Brick.relations.each do |rel_name, v|
         
     | 
| 
       407 
411 
     | 
    
         
             
                      rel_name = rel_name.split('.').map(&:underscore)
         
     | 
| 
       408 
412 
     | 
    
         
             
                      schema_names = rel_name[0..-2]
         
     | 
| 
      
 413 
     | 
    
         
            +
                      schema_names.shift if ::Brick.config.schema_behavior[:multitenant] && Object.const_defined?('Apartment') && schema_names.first == Apartment.default_schema
         
     | 
| 
       409 
414 
     | 
    
         
             
                      k = rel_name.last
         
     | 
| 
       410 
415 
     | 
    
         
             
                      unless existing_controllers.key?(controller_name = k.pluralize)
         
     | 
| 
       411 
416 
     | 
    
         
             
                        options = {}
         
     | 
| 
         @@ -419,6 +424,7 @@ In config/initializers/brick.rb appropriate entries would look something like: 
     | 
|
| 
       419 
424 
     | 
    
         
             
                        end
         
     | 
| 
       420 
425 
     | 
    
         
             
                      end
         
     | 
| 
       421 
426 
     | 
    
         
             
                    end
         
     | 
| 
      
 427 
     | 
    
         
            +
                    send(:get, '/api-docs/v1/swagger.json', { to: 'brick_swagger#index' }) if Object.const_defined?('Rswag::Ui')
         
     | 
| 
       422 
428 
     | 
    
         
             
                  end
         
     | 
| 
       423 
429 
     | 
    
         
             
                  super
         
     | 
| 
       424 
430 
     | 
    
         
             
                end
         
     | 
| 
         @@ -28,7 +28,7 @@ module Brick 
     | 
|
| 
       28 
28 
     | 
    
         
             
                        col_down = col.downcase
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
30 
     | 
    
         
             
                        if (is_possible_poly = ['character varying', 'text'].include?(type.first))
         
     | 
| 
       31 
     | 
    
         
            -
                          if col_down.end_with?('_type') 
     | 
| 
      
 31 
     | 
    
         
            +
                          if col_down.end_with?('_type')
         
     | 
| 
       32 
32 
     | 
    
         
             
                            poly_type_cut_length = -6
         
     | 
| 
       33 
33 
     | 
    
         
             
                            col_down = col_down[0..-6]
         
     | 
| 
       34 
34 
     | 
    
         
             
                          elsif col_down.end_with?('type')
         
     | 
    
        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.34
         
     | 
| 
       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- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2022-06-23 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: activerecord
         
     |