brick 1.0.45 → 1.0.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 678e1295006174594606dc731cd650afa60d2cc727be08bd416c9503faeb1ca4
4
- data.tar.gz: b00802df45b7e388523b29cfab38feaaaf7c61d057cf509c71a6a08860373b15
3
+ metadata.gz: c9c3989f395bc81df36b3f295c72029e92911bd24f8d146db5627fb29c1875f4
4
+ data.tar.gz: 97ae12a1562f9f9bae5f401016e219a5ad58218068f80d7fc0e732d61c4f3f90
5
5
  SHA512:
6
- metadata.gz: 7962bbc61bd43b68062d188ac3565e38f4840d52ca76b4c675e0da55d213104f13e007578658441359323899ed881d10497bb8285384abe42a2d15bd9c26b64b
7
- data.tar.gz: 449e74d3ab9558eed77c89aac5a871927ed0842fc043c910d04d1cca29221508332a7def78940ed67048a29e4384576aa8a176beb117c0bc7ff8a48a87f64af6
6
+ metadata.gz: c64d02f90b992640698523190a920467204a2fbb40fb9e21a3e7872ae469db3506bdf7fb535e54cd33157feb93ed43c2d1c11b2bea952bc9f034ac7e7dfb6b06
7
+ data.tar.gz: 6c01156b2b35f387e531ed6835a7517f5249b72ec53bb23d5d965c4b298a443d9a62e5694f9c1b4587f6ab04ef30590d7d9077e13c66b651ee8ed12b76282932
@@ -353,7 +353,6 @@ module ActiveRecord
353
353
  next if bt[2] # Polymorphic?
354
354
 
355
355
  # join_array will receive this relation name when calling #brick_parse_dsl
356
- # binding.pry if bt.length > 2
357
356
  bt_descrip[bt.first] = if bt[1].is_a?(Array)
358
357
  bt[1].each_with_object({}) { |bt_class, s| s[bt_class] = bt_class.brick_parse_dsl(join_array, bt.first, translations, true) }
359
358
  else
@@ -597,7 +596,7 @@ Module.class_exec do
597
596
  # See if a file is there in the same way that ActiveSupport::Dependencies#load_missing_constant
598
597
  # checks for it in ~/.rvm/gems/ruby-2.7.5/gems/activesupport-5.2.6.2/lib/active_support/dependencies.rb
599
598
 
600
- if (base_model = ::Brick.config.sti_namespace_prefixes&.fetch("::#{name}::", nil)&.constantize) || # Are we part of an auto-STI namespace? ...
599
+ if (base_model = ::Brick.config.sti_namespace_prefixes&.fetch("::#{self.name}::", nil)&.constantize) || # Are we part of an auto-STI namespace? ...
601
600
  self != Object # ... or otherwise already in some namespace?
602
601
  schema_name = [(singular_schema_name = name.underscore),
603
602
  (schema_name = singular_schema_name.pluralize),
@@ -620,7 +619,7 @@ Module.class_exec do
620
619
  else
621
620
  ActiveSupport::Inflector.pluralize(singular_table_name)
622
621
  end
623
- if ::Brick.config.schema_behavior[:multitenant] && Object.const_defined?('Apartment') &&
622
+ if ::Brick.apartment_multitenant &&
624
623
  Apartment.excluded_models.include?(table_name.singularize.camelize)
625
624
  schema_name = Apartment.default_schema
626
625
  end
@@ -655,7 +654,7 @@ class Object
655
654
  private
656
655
 
657
656
  def build_model(schema_name, inheritable_name, model_name, singular_table_name, table_name, relations, matching)
658
- if ::Brick.config.schema_behavior[:multitenant] && Object.const_defined?('Apartment') &&
657
+ if ::Brick.apartment_multitenant &&
659
658
  schema_name == Apartment.default_schema
660
659
  relation = relations["#{schema_name}.#{matching}"]
661
660
  end
@@ -666,7 +665,7 @@ class Object
666
665
  schema_name
667
666
  else
668
667
  matching = "#{schema_name}.#{matching}"
669
- (Brick.db_schemas[schema_name] ||= self.const_get(schema_name.singularize.camelize))
668
+ (Brick.db_schemas[schema_name] ||= self.const_get(schema_name.camelize))
670
669
  end
671
670
  "#{schema_module&.name}::#{inheritable_name || model_name}"
672
671
  end
@@ -774,33 +773,47 @@ class Object
774
773
  end # class definition
775
774
  # Having this separate -- will this now work out better?
776
775
  built_model.class_exec do
777
- hmts&.each do |hmt_fk, fks|
776
+ hmts&.each do |hmt_fk, hms|
778
777
  hmt_fk = hmt_fk.tr('.', '_')
779
- fks.each do |fk|
780
- # %%% Will not work with custom has_many name
781
- through = ::Brick.config.schema_behavior[:multitenant] ? fk.first[:assoc_name] : fk.first[:inverse_table].tr('.', '_').pluralize
782
- hmt_name = if fks.length > 1
783
- if fks[0].first[:inverse][:assoc_name] == fks[1].first[:inverse][:assoc_name] # Same BT names pointing back to us? (Most common scenario)
784
- "#{hmt_fk}_through_#{fk.first[:assoc_name]}"
778
+ hms.each do |hm|
779
+ # %%% Need to confirm that HMTs work when they are built from has_manys with custom names
780
+ through = ::Brick.config.schema_behavior[:multitenant] ? hm.first[:assoc_name] : hm.first[:inverse_table].tr('.', '_').pluralize
781
+ options = {}
782
+ hmt_name = if hms.length > 1
783
+ if hms[0].first[:inverse][:assoc_name] == hms[1].first[:inverse][:assoc_name] # Same BT names pointing back to us? (Most common scenario)
784
+ "#{hmt_fk}_through_#{hm.first[:assoc_name]}"
785
785
  else # Use BT names to provide uniqueness
786
- through = fk.first[:alternate_name].pluralize
787
- singular_assoc_name = fk.first[:inverse][:assoc_name].singularize
786
+ if self.name.underscore.singularize == hm.first[:alternate_name]
787
+ # Has previously been:
788
+ # # If it folds back on itself then look at the other side
789
+ # # (At this point just infer the source be the inverse of the first has_many that
790
+ # # we find that is not ourselves. If there are more than two then uh oh, can't
791
+ # # yet handle that rare circumstance!)
792
+ # other = hms.find { |hm1| hm1 != hm } # .first[:fk]
793
+ # options[:source] = other.first[:inverse][:assoc_name].to_sym
794
+ # And also has been:
795
+ # hm.first[:inverse][:assoc_name].to_sym
796
+ options[:source] = hm.last.to_sym
797
+ else
798
+ through = hm.first[:alternate_name].pluralize
799
+ end
800
+ singular_assoc_name = hm.first[:inverse][:assoc_name].singularize
788
801
  "#{singular_assoc_name}_#{hmt_fk}"
789
802
  end
790
803
  else
791
804
  hmt_fk
792
805
  end
793
- options = { through: through.to_sym }
806
+ options[:through] = through.to_sym
794
807
  if relation[:fks].any? { |k, v| v[:assoc_name] == hmt_name }
795
- hmt_name = "#{hmt_name.singularize}_#{fk.first[:assoc_name]}"
808
+ hmt_name = "#{hmt_name.singularize}_#{hm.first[:assoc_name]}"
796
809
  # Was:
797
- # options[:class_name] = fk.first[:inverse_table].singularize.camelize
798
- # options[:foreign_key] = fk.first[:fk].to_sym
799
- far_assoc = relations[fk.first[:inverse_table]][:fks].find { |_k, v| v[:assoc_name] == fk.last }
810
+ # options[:class_name] = hm.first[:inverse_table].singularize.camelize
811
+ # options[:foreign_key] = hm.first[:fk].to_sym
812
+ far_assoc = relations[hm.first[:inverse_table]][:fks].find { |_k, v| v[:assoc_name] == hm.last }
800
813
  options[:class_name] = far_assoc.last[:inverse_table].singularize.camelize
801
814
  options[:foreign_key] = far_assoc.last[:fk].to_sym
802
815
  end
803
- options[:source] = fk.last.to_sym unless hmt_name.singularize == fk.last
816
+ options[:source] ||= hm.last.to_sym unless hmt_name.singularize == hm.last
804
817
  code << " has_many :#{hmt_name}#{options.map { |opt| ", #{opt.first}: #{opt.last.inspect}" }.join}\n"
805
818
  self.send(:has_many, hmt_name.to_sym, **options)
806
819
  end
@@ -831,13 +844,13 @@ class Object
831
844
  need_fk = "#{assoc_name}_id" != assoc[:fk]
832
845
  end
833
846
  if (inverse = assoc[:inverse])
834
- inverse_assoc_name, _x = _brick_get_hm_assoc_name(relations[inverse_table], inverse)
835
847
  # If it's multitenant with something like: public.____ ...
836
848
  if (it_parts = inverse_table.split('.')).length > 1 &&
837
- ::Brick.config.schema_behavior[:multitenant] && Object.const_defined?('Apartment') &&
849
+ ::Brick.apartment_multitenant &&
838
850
  it_parts.first == Apartment.default_schema
839
851
  it_parts.shift # ... then ditch the generic schema name
840
852
  end
853
+ inverse_assoc_name, _x = _brick_get_hm_assoc_name(relations[inverse_table], inverse, it_parts.join('_').singularize)
841
854
  has_ones = ::Brick.config.has_ones&.fetch(it_parts.join('/').singularize.camelize, nil)
842
855
  if has_ones&.key?(singular_inv_assoc_name = ActiveSupport::Inflector.singularize(inverse_assoc_name.tr('.', '_')))
843
856
  inverse_assoc_name = if has_ones[singular_inv_assoc_name]
@@ -1085,9 +1098,9 @@ class Object
1085
1098
  [built_controller, code]
1086
1099
  end
1087
1100
 
1088
- def _brick_get_hm_assoc_name(relation, hm_assoc)
1101
+ def _brick_get_hm_assoc_name(relation, hm_assoc, source = nil)
1089
1102
  if (relation[:hm_counts][hm_assoc[:assoc_name]]&.> 1) &&
1090
- hm_assoc[:alternate_name] != hm_assoc[:inverse][:assoc_name]
1103
+ hm_assoc[:alternate_name] != (source || name.underscore)
1091
1104
  plural = ActiveSupport::Inflector.pluralize(hm_assoc[:alternate_name])
1092
1105
  new_alt_name = (hm_assoc[:alternate_name] == name.underscore) ? "#{hm_assoc[:assoc_name].singularize}_#{plural}" : plural
1093
1106
  # uniq = 1
@@ -1129,7 +1142,8 @@ module ActiveRecord::ConnectionHandling
1129
1142
  end
1130
1143
  # Load the initializer for the Apartment gem a little early so that if .excluded_models and
1131
1144
  # .default_schema are specified then we can work with non-tenanted models more appropriately
1132
- if Object.const_defined?('Apartment') && File.exist?(apartment_initializer = Rails.root.join('config/initializers/apartment.rb'))
1145
+ apartment = Object.const_defined?('Apartment')
1146
+ if apartment && File.exist?(apartment_initializer = Rails.root.join('config/initializers/apartment.rb'))
1133
1147
  load apartment_initializer
1134
1148
  apartment_excluded = Apartment.excluded_models
1135
1149
  end
@@ -1332,17 +1346,20 @@ module ActiveRecord::ConnectionHandling
1332
1346
  end
1333
1347
  end
1334
1348
 
1335
- apartment = Object.const_defined?('Apartment') && Apartment
1336
1349
  tables = []
1337
1350
  views = []
1338
1351
  relations.each do |k, v|
1339
1352
  name_parts = k.split('.')
1353
+ idx = 1
1354
+ name_parts = name_parts.map do |x|
1355
+ ((idx += 1) < name_parts.length ? x.singularize : x).camelize
1356
+ end
1340
1357
  if v.key?(:isView)
1341
1358
  views
1342
1359
  else
1343
1360
  name_parts.shift if apartment && name_parts.length > 1 && name_parts.first == Apartment.default_schema
1344
1361
  tables
1345
- end << name_parts.map { |x| x.singularize.camelize }.join('::')
1362
+ end << name_parts.join('::')
1346
1363
  end
1347
1364
  unless tables.empty?
1348
1365
  puts "\nClasses that can be built from tables:"
@@ -1424,7 +1441,7 @@ module Brick
1424
1441
  unless (cnstr_name = fk[5])
1425
1442
  # For any appended references (those that come from config), arrive upon a definitely unique constraint name
1426
1443
  pri_tbl = is_class ? fk[4][:class].underscore : pri_tbl
1427
- pri_tbl = "#{bt_assoc_name}_#{pri_tbl}" if pri_tbl.singularize != bt_assoc_name
1444
+ pri_tbl = "#{bt_assoc_name}_#{pri_tbl}" if pri_tbl&.singularize != bt_assoc_name
1428
1445
  cnstr_base = cnstr_name = "(brick) #{for_tbl}_#{pri_tbl}"
1429
1446
  cnstr_added_num = 1
1430
1447
  cnstr_name = "#{cnstr_base}_#{cnstr_added_num += 1}" while bts&.key?(cnstr_name) || hms&.key?(cnstr_name)
@@ -1450,6 +1467,8 @@ module Brick
1450
1467
  return
1451
1468
  end
1452
1469
  end
1470
+ return unless bts # Rails 5.0 and older can have bts end up being nil
1471
+
1453
1472
  if (assoc_bt = bts[cnstr_name])
1454
1473
  if is_polymorphic
1455
1474
  # Assuming same fk (don't yet support composite keys for polymorphics)
@@ -105,13 +105,26 @@ module Brick
105
105
  hms_columns = [] # Used for 'index'
106
106
  skip_klass_hms = ::Brick.config.skip_index_hms[model_name] || {}
107
107
  hms_headers = hms.each_with_object([]) do |hm, s|
108
- hm_stuff = [(hm_assoc = hm.last), "H#{hm_assoc.macro == :has_one ? 'O' : 'M'}#{'T' if hm_assoc.options[:through]}", (assoc_name = hm.first)]
108
+ hm_stuff = [(hm_assoc = hm.last),
109
+ "H#{hm_assoc.macro == :has_one ? 'O' : 'M'}#{'T' if hm_assoc.options[:through]}",
110
+ (assoc_name = hm.first)]
109
111
  hm_fk_name = if hm_assoc.options[:through]
110
- associative = associatives[hm_assoc.name]
111
- associative && "'#{associative.name}.#{associative.foreign_key}'"
112
- else
113
- hm_assoc.foreign_key
114
- end
112
+ associative = associatives[hm.first]
113
+ tbl_nm = if hm_assoc.options[:source]
114
+ associative.klass.reflect_on_association(hm_assoc.options[:source]).inverse_of&.name
115
+ else
116
+ associative.name
117
+ end
118
+ # If there is no inverse available for the source belongs_to association, make one based on the class name
119
+ unless tbl_nm
120
+ tbl_nm = associative.class_name.underscore
121
+ tbl_nm.slice!(0) if tbl_nm[0] == ('/')
122
+ tbl_nm = tbl_nm.tr('/', '_').pluralize
123
+ end
124
+ "'#{tbl_nm}.#{associative.foreign_key}'"
125
+ else
126
+ hm_assoc.foreign_key
127
+ end
115
128
  case args.first
116
129
  when 'index'
117
130
  hms_columns << if hm_assoc.macro == :has_many
@@ -149,7 +162,7 @@ module Brick
149
162
  schema_options = ::Brick.db_schemas.keys.each_with_object(+'') { |v, s| s << "<option value=\"#{v}\">#{v}</option>" }.html_safe
150
163
  # %%% If we are not auto-creating controllers (or routes) then omit by default, and if enabled anyway, such as in a development
151
164
  # environment or whatever, then get either the controllers or routes list instead
152
- apartment_default_schema = ::Brick.config.schema_behavior[:multitenant] && Object.const_defined?('Apartment') && Apartment.default_schema
165
+ apartment_default_schema = ::Brick.apartment_multitenant && Apartment.default_schema
153
166
  table_options = (::Brick.relations.keys - ::Brick.config.exclude_tables).map do |tbl|
154
167
  if (tbl_parts = tbl.split('.')).first == apartment_default_schema
155
168
  tbl = tbl_parts.last
@@ -218,9 +231,6 @@ table tbody tr.active-row {
218
231
  color: #009879;
219
232
  }
220
233
 
221
- td.val {
222
- display: block;
223
- }
224
234
  a.show-arrow {
225
235
  font-size: 1.5em;
226
236
  text-decoration: none;
@@ -266,7 +276,6 @@ input+svg.revert {
266
276
  background-color: #004998;
267
277
  color: #FFF;
268
278
  }
269
-
270
279
  </style>
271
280
  <% is_includes_dates = nil
272
281
 
@@ -528,7 +537,7 @@ if (headerTop) {
528
537
  k, id = @_brick_params.first
529
538
  id = id.first if id.is_a?(Array) && id.length == 1
530
539
  origin = (key_parts = k.split('.')).length == 1 ? #{model_name} : #{model_name}.reflect_on_association(key_parts.first).klass
531
- if (destination_fk = Brick.relations[origin.table_name][:fks].values.find { |fk| puts fk.inspect; fk[:fk] == key_parts.last }) &&
540
+ if (destination_fk = Brick.relations[origin.table_name][:fks].values.find { |fk| fk[:fk] == key_parts.last }) &&
532
541
  (obj = (destination = origin.reflect_on_association(destination_fk[:assoc_name])&.klass)&.find(id)) %>
533
542
  <h3>for <%= link_to \"#{"#\{obj.brick_descrip\} (#\{destination.name\})\""}, send(\"#\{destination.name.underscore.tr('/', '_')\}_path\".to_sym, id) %></h3><%
534
543
  end
@@ -685,7 +694,7 @@ end
685
694
  <%= k %>
686
695
  <% end %>
687
696
  </th>
688
- <td class=\"val\">
697
+ <td>
689
698
  <% dt_pickers = { datetime: 'datetimepicker', timestamp: 'datetimepicker', time: 'timepicker', date: 'datepicker' }
690
699
  if bt
691
700
  html_options = { prompt: \"Select #\{bt_name\}\" }
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 45
8
+ TINY = 48
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
data/lib/brick.rb CHANGED
@@ -47,7 +47,6 @@ end
47
47
 
48
48
  # Add left_outer_join! to Associations::JoinDependency and Relation::QueryMethods
49
49
  if ActiveRecord.version < ::Gem::Version.new('5')
50
- is_add_left_outer_join = true
51
50
  ::Brick::Util._patch_require(
52
51
  'active_record/associations/join_dependency.rb', '/activerecord', # /associations
53
52
  ["def join_constraints(outer_joins)
@@ -140,6 +139,13 @@ module Brick
140
139
  (@relations ||= {})[ActiveRecord::Base.connection_pool.object_id] ||= Hash.new { |h, k| h[k] = Hash.new { |h, k| h[k] = {} } }
141
140
  end
142
141
 
142
+ def apartment_multitenant
143
+ if @apartment_multitenant.nil?
144
+ @apartment_multitenant = ::Brick.config.schema_behavior[:multitenant] && Object.const_defined?('Apartment')
145
+ end
146
+ @apartment_multitenant
147
+ end
148
+
143
149
  # If multitenancy is enabled, a list of non-tenanted "global" models
144
150
  def non_tenanted_models
145
151
  @pending_models ||= {}
@@ -168,8 +174,12 @@ module Brick
168
174
  skip_hms = {}
169
175
  associatives = hms.each_with_object({}) do |hmt, s|
170
176
  if (through = hmt.last.options[:through])
171
- skip_hms[through] = nil
172
- s[hmt.first] = hms[through] # End up with a hash of HMT names pointing to join-table associations
177
+ skip_hms[through] = nil # if hms[through]
178
+ # binding.pry if !hms[through]
179
+ # End up with a hash of HMT names pointing to join-table associations
180
+ # Last part was: hmt.last.name
181
+ # Changed up because looking for: hms[:issue_issue_duplicates]
182
+ s[hmt.first] = hms[through] # || hms["#{(opt = hmt.last.options)[:through].to_s.singularize}_#{opt[:source].to_s.pluralize}".to_sym]
173
183
  elsif hmt.last.inverse_of.nil?
174
184
  puts "SKIPPING #{hmt.last.name.inspect}"
175
185
  # %%% If we don't do this then below associative.name will find that associative is nil
@@ -447,7 +457,7 @@ In config/initializers/brick.rb appropriate entries would look something like:
447
457
  ::Brick.relations.each do |rel_name, v|
448
458
  rel_name = rel_name.split('.').map(&:underscore)
449
459
  schema_names = rel_name[0..-2]
450
- schema_names.shift if ::Brick.config.schema_behavior[:multitenant] && Object.const_defined?('Apartment') && schema_names.first == Apartment.default_schema
460
+ schema_names.shift if ::Brick.apartment_multitenant && schema_names.first == Apartment.default_schema
451
461
  k = rel_name.last
452
462
  unless existing_controllers.key?(controller_name = k.pluralize)
453
463
  options = {}
@@ -477,7 +487,8 @@ require 'brick/version_number'
477
487
  # Older versions of ActiveRecord would only show more serious error information from "panic" level, which is
478
488
  # a level only available in Postgres 12 and older. This patch will allow older and newer versions of Postgres
479
489
  # to work along with fairly old versions of Rails.
480
- if Object.const_defined?('PG::VERSION') && ActiveRecord.version < ::Gem::Version.new('4.2.6')
490
+ if (is_postgres = (Object.const_defined?('PG::VERSION') || Gem::Specification.find_all_by_name('pg').present?)) &&
491
+ ActiveRecord.version < ::Gem::Version.new('4.2.6')
481
492
  ::Brick::Util._patch_require(
482
493
  'active_record/connection_adapters/postgresql_adapter.rb', '/activerecord', ["'panic'", "'error'"]
483
494
  )
@@ -485,13 +496,28 @@ end
485
496
 
486
497
  require 'active_record'
487
498
  require 'active_record/relation'
488
- require 'active_record/relation/query_methods' if is_add_left_outer_join
499
+ # To support adding left_outer_join
500
+ require 'active_record/relation/query_methods' if ActiveRecord.version < ::Gem::Version.new('5')
501
+ require 'rails/railtie' if ActiveRecord.version < ::Gem::Version.new('4.2')
489
502
 
490
503
  # Rake tasks
491
504
  class Railtie < Rails::Railtie
492
505
  Dir.glob("#{File.expand_path(__dir__)}/brick/tasks/**/*.rake").each { |task| load task }
493
506
  end
494
507
 
508
+ # Rails < 4.2 does not have env
509
+ module Rails
510
+ unless respond_to?(:env)
511
+ def self.env
512
+ @_env ||= ActiveSupport::StringInquirer.new(ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development")
513
+ end
514
+
515
+ def self.env=(environment)
516
+ @_env = ActiveSupport::StringInquirer.new(environment)
517
+ end
518
+ end
519
+ end
520
+
495
521
  # Major compatibility fixes for ActiveRecord < 4.2
496
522
  # ================================================
497
523
  ActiveSupport.on_load(:active_record) do
@@ -506,6 +532,15 @@ ActiveSupport.on_load(:active_record) do
506
532
  end
507
533
  end
508
534
  end
535
+ # ActiveRecord < 4.2 does not have default_timezone
536
+ # :singleton-method:
537
+ # Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
538
+ # dates and times from the database. This is set to :utc by default.
539
+ unless respond_to?(:default_timezone)
540
+ puts "ADDING!!! 4.w"
541
+ mattr_accessor :default_timezone, instance_writer: false
542
+ self.default_timezone = :utc
543
+ end
509
544
  end
510
545
 
511
546
  # Rails < 4.0 cannot do #find_by, #find_or_create_by, or do #pluck on multiple columns, so here are the patches:
@@ -711,58 +746,60 @@ ActiveSupport.on_load(:active_record) do
711
746
  end
712
747
  end
713
748
 
714
- if is_add_left_outer_join
715
- # Final pieces for left_outer_joins support, which was derived from this commit:
716
- # https://github.com/rails/rails/commit/3f46ef1ddab87482b730a3f53987e04308783d8b
717
- module Associations
718
- class JoinDependency
719
- def make_left_outer_joins(parent, child)
720
- tables = child.tables
721
- join_type = Arel::Nodes::OuterJoin
722
- info = make_constraints parent, child, tables, join_type
723
-
724
- [info] + child.children.flat_map { |c| make_left_outer_joins(child, c) }
725
- end
749
+ # Final pieces for left_outer_joins support, which was derived from this commit:
750
+ # https://github.com/rails/rails/commit/3f46ef1ddab87482b730a3f53987e04308783d8b
751
+ module Associations
752
+ class JoinDependency
753
+ def make_left_outer_joins(parent, child)
754
+ tables = child.tables
755
+ join_type = Arel::Nodes::OuterJoin
756
+ info = make_constraints parent, child, tables, join_type
757
+
758
+ [info] + child.children.flat_map { |c| make_left_outer_joins(child, c) }
726
759
  end
727
760
  end
728
- module Querying
729
- delegate :left_outer_joins, to: :all
761
+ end
762
+ module Querying
763
+ delegate :left_outer_joins, to: :all
764
+ end
765
+ class Relation
766
+ unless MULTI_VALUE_METHODS.include?(:left_outer_joins)
767
+ _multi_value_methods = MULTI_VALUE_METHODS + [:left_outer_joins]
768
+ send(:remove_const, :MULTI_VALUE_METHODS)
769
+ MULTI_VALUE_METHODS = _multi_value_methods
730
770
  end
731
- class Relation
732
- MULTI_VALUE_METHODS = MULTI_VALUE_METHODS + [:left_outer_joins] unless MULTI_VALUE_METHODS.include?(:left_outer_joins)
771
+ end
772
+ module QueryMethods
773
+ attr_writer :left_outer_joins_values
774
+ def left_outer_joins_values
775
+ @left_outer_joins_values ||= []
733
776
  end
734
- module QueryMethods
735
- attr_writer :left_outer_joins_values
736
- def left_outer_joins_values
737
- @left_outer_joins_values ||= []
738
- end
739
777
 
740
- def left_outer_joins(*args)
741
- check_if_method_has_arguments!(:left_outer_joins, args)
778
+ def left_outer_joins(*args)
779
+ check_if_method_has_arguments!(:left_outer_joins, args)
742
780
 
743
- args.compact!
744
- args.flatten!
781
+ args.compact!
782
+ args.flatten!
745
783
 
746
- spawn.left_outer_joins!(*args)
747
- end
784
+ spawn.left_outer_joins!(*args)
785
+ end
748
786
 
749
- def left_outer_joins!(*args) # :nodoc:
750
- self.left_outer_joins_values += args
751
- self
752
- end
787
+ def left_outer_joins!(*args) # :nodoc:
788
+ self.left_outer_joins_values += args
789
+ self
790
+ end
753
791
 
754
- def build_left_outer_joins(manager, outer_joins)
755
- buckets = outer_joins.group_by do |join|
756
- case join
757
- when Hash, Symbol, Array
758
- :association_join
759
- else
760
- raise ArgumentError, 'only Hash, Symbol and Array are allowed'
761
- end
792
+ def build_left_outer_joins(manager, outer_joins)
793
+ buckets = outer_joins.group_by do |join|
794
+ case join
795
+ when Hash, Symbol, Array
796
+ :association_join
797
+ else
798
+ raise ArgumentError, 'only Hash, Symbol and Array are allowed'
762
799
  end
763
-
764
- build_join_query(manager, buckets, Arel::Nodes::OuterJoin)
765
800
  end
801
+
802
+ build_join_query(manager, buckets, Arel::Nodes::OuterJoin)
766
803
  end
767
804
  end
768
805
  # (End of left_outer_joins support)
@@ -784,7 +821,8 @@ ActiveSupport.on_load(:active_record) do
784
821
  end
785
822
 
786
823
  # Do this earlier because stuff here gets mixed into JoinDependency::JoinAssociation and AssociationScope
787
- if ActiveRecord.version < ::Gem::Version.new('5.0') && Object.const_defined?('PG::Connection')
824
+ if is_postgres && ActiveRecord.version < ::Gem::Version.new('5.0') # Was: && Object.const_defined?('PG::Connection')
825
+ require 'pg' # For ActiveRecord < 4.2
788
826
  # Avoid pg gem deprecation warning: "You should use PG::Connection, PG::Result, and PG::Error instead"
789
827
  PGconn = PG::Connection
790
828
  PGresult = PG::Result
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.45
4
+ version: 1.0.48
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-07-12 00:00:00.000000000 Z
11
+ date: 2022-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -17,9 +17,6 @@ dependencies:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '4.2'
20
- - - "<"
21
- - !ruby/object:Gem::Version
22
- version: '7.2'
23
20
  type: :runtime
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
@@ -27,9 +24,6 @@ dependencies:
27
24
  - - ">="
28
25
  - !ruby/object:Gem::Version
29
26
  version: '4.2'
30
- - - "<"
31
- - !ruby/object:Gem::Version
32
- version: '7.2'
33
27
  - !ruby/object:Gem::Dependency
34
28
  name: fancy_gets
35
29
  requirement: !ruby/object:Gem::Requirement