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 +4 -4
- data/lib/brick/extensions.rb +47 -28
- data/lib/brick/frameworks/rails/engine.rb +22 -13
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +86 -48
- metadata +2 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9c3989f395bc81df36b3f295c72029e92911bd24f8d146db5627fb29c1875f4
|
4
|
+
data.tar.gz: 97ae12a1562f9f9bae5f401016e219a5ad58218068f80d7fc0e732d61c4f3f90
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c64d02f90b992640698523190a920467204a2fbb40fb9e21a3e7872ae469db3506bdf7fb535e54cd33157feb93ed43c2d1c11b2bea952bc9f034ac7e7dfb6b06
|
7
|
+
data.tar.gz: 6c01156b2b35f387e531ed6835a7517f5249b72ec53bb23d5d965c4b298a443d9a62e5694f9c1b4587f6ab04ef30590d7d9077e13c66b651ee8ed12b76282932
|
data/lib/brick/extensions.rb
CHANGED
@@ -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.
|
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.
|
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.
|
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,
|
776
|
+
hmts&.each do |hmt_fk, hms|
|
778
777
|
hmt_fk = hmt_fk.tr('.', '_')
|
779
|
-
|
780
|
-
# %%%
|
781
|
-
through = ::Brick.config.schema_behavior[:multitenant] ?
|
782
|
-
|
783
|
-
|
784
|
-
|
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
|
-
|
787
|
-
|
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 =
|
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}_#{
|
808
|
+
hmt_name = "#{hmt_name.singularize}_#{hm.first[:assoc_name]}"
|
796
809
|
# Was:
|
797
|
-
# options[:class_name] =
|
798
|
-
# options[:foreign_key] =
|
799
|
-
far_assoc = relations[
|
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]
|
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.
|
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] !=
|
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
|
-
|
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.
|
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
|
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),
|
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
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
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.
|
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|
|
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
|
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\}\" }
|
data/lib/brick/version_number.rb
CHANGED
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
|
-
|
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.
|
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')
|
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
|
-
|
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
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
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
|
-
|
729
|
-
|
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
|
-
|
732
|
-
|
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
|
-
|
741
|
-
|
778
|
+
def left_outer_joins(*args)
|
779
|
+
check_if_method_has_arguments!(:left_outer_joins, args)
|
742
780
|
|
743
|
-
|
744
|
-
|
781
|
+
args.compact!
|
782
|
+
args.flatten!
|
745
783
|
|
746
|
-
|
747
|
-
|
784
|
+
spawn.left_outer_joins!(*args)
|
785
|
+
end
|
748
786
|
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
787
|
+
def left_outer_joins!(*args) # :nodoc:
|
788
|
+
self.left_outer_joins_values += args
|
789
|
+
self
|
790
|
+
end
|
753
791
|
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
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.
|
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-
|
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
|