brick 1.0.38 → 1.0.41
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/compatibility.rb +10 -1
- data/lib/brick/config.rb +5 -0
- data/lib/brick/extensions.rb +99 -9
- data/lib/brick/frameworks/rails/engine.rb +97 -47
- data/lib/brick/tasks/orphans.rake +29 -0
- data/lib/brick/util.rb +16 -9
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +145 -12
- data/lib/generators/brick/install_generator.rb +1 -1
- metadata +19 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4455ebfde80fe8a4bd51f19438171abae2614e0740adba98ab39184952843a01
|
4
|
+
data.tar.gz: d5157748c37564156fc2f823cc3c4753b536491aa2cf81175683c8241fb2a2b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a649c78c3e597004b36d6c33f1cd812a712fcfd561dfe94994de28e489de81508f9fea30b0896b4447c4ce0ffd0877fb8c5d7e20a34011212fd797a3cbd02ca
|
7
|
+
data.tar.gz: 58ecdc4acb12abb77169a8fda8cb8146fceaedeacdf77f1cec992008f98b05412e3a9e2f5b6a9721880caa710ba94792a187d3587248eea4d9946d309c91be56
|
data/lib/brick/compatibility.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'active_record/version'
|
4
|
-
|
5
4
|
# ActiveRecord before 4.0 didn't have #version
|
6
5
|
unless ActiveRecord.respond_to?(:version)
|
7
6
|
module ActiveRecord
|
@@ -11,6 +10,16 @@ unless ActiveRecord.respond_to?(:version)
|
|
11
10
|
end
|
12
11
|
end
|
13
12
|
|
13
|
+
require 'action_view'
|
14
|
+
# Older ActionView didn't have #version
|
15
|
+
unless ActionView.respond_to?(:version)
|
16
|
+
module ActionView
|
17
|
+
def self.version
|
18
|
+
ActionPack.version
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
14
23
|
# In ActiveSupport older than 5.0, the duplicable? test tries to new up a BigDecimal,
|
15
24
|
# and Ruby 2.6 and later deprecates #new. This removes the warning from BigDecimal.
|
16
25
|
# This compatibility needs to be put into place in the application's "config/boot.rb"
|
data/lib/brick/config.rb
CHANGED
data/lib/brick/extensions.rb
CHANGED
@@ -70,7 +70,11 @@ module ActiveRecord
|
|
70
70
|
def self._brick_primary_key(relation = nil)
|
71
71
|
return instance_variable_get(:@_brick_primary_key) if instance_variable_defined?(:@_brick_primary_key)
|
72
72
|
|
73
|
-
pk =
|
73
|
+
pk = begin
|
74
|
+
primary_key.is_a?(String) ? [primary_key] : primary_key || []
|
75
|
+
rescue
|
76
|
+
[]
|
77
|
+
end
|
74
78
|
# Just return [] if we're missing any part of the primary key. (PK is usually just "id")
|
75
79
|
if relation && pk.present?
|
76
80
|
@_brick_primary_key ||= pk.any? { |pk_part| !relation[:cols].key?(pk_part) } ? [] : pk
|
@@ -204,7 +208,7 @@ module ActiveRecord
|
|
204
208
|
assoc_name = CGI.escapeHTML(assoc_name.to_s)
|
205
209
|
model_path = Rails.application.routes.url_helpers.send("#{model_underscore.tr('/', '_').pluralize}_path".to_sym)
|
206
210
|
av_class = Class.new.extend(ActionView::Helpers::UrlHelper)
|
207
|
-
av_class.extend(ActionView::Helpers::TagHelper) if ActionView.version < ::Gem::Version.new('
|
211
|
+
av_class.extend(ActionView::Helpers::TagHelper) if ActionView.version < ::Gem::Version.new('7')
|
208
212
|
link = av_class.link_to(name, model_path)
|
209
213
|
model_underscore == assoc_name ? link : "#{assoc_name}-#{link}".html_safe
|
210
214
|
end
|
@@ -411,14 +415,16 @@ module ActiveRecord
|
|
411
415
|
hm_counts.each do |k, hm|
|
412
416
|
associative = nil
|
413
417
|
count_column = if hm.options[:through]
|
414
|
-
fk_col = (associative = associatives[hm.name])
|
415
|
-
hm.foreign_key
|
418
|
+
fk_col = (associative = associatives[hm.name])&.foreign_key
|
419
|
+
hm.foreign_key if fk_col
|
416
420
|
else
|
417
421
|
fk_col = hm.foreign_key
|
418
422
|
poly_type = hm.inverse_of.foreign_type if hm.options.key?(:as)
|
419
423
|
pk = hm.klass.primary_key
|
420
424
|
(pk.is_a?(Array) ? pk.first : pk) || '*'
|
421
425
|
end
|
426
|
+
next unless count_column # %%% Would be able to remove this when multiple foreign keys to same destination becomes bulletproof
|
427
|
+
|
422
428
|
tbl_alias = "_br_#{hm.name}"
|
423
429
|
pri_tbl = hm.active_record
|
424
430
|
on_clause = []
|
@@ -552,7 +558,7 @@ Module.class_exec do
|
|
552
558
|
# return my_const
|
553
559
|
end
|
554
560
|
|
555
|
-
relations = ::Brick.
|
561
|
+
relations = ::Brick.relations
|
556
562
|
# puts "ON OBJECT: #{args.inspect}" if self.module_parent == Object
|
557
563
|
result = if ::Brick.enable_controllers? && class_name.end_with?('Controller') && (plural_class_name = class_name[0..-11]).length.positive?
|
558
564
|
# Otherwise now it's up to us to fill in the gaps
|
@@ -561,7 +567,9 @@ Module.class_exec do
|
|
561
567
|
full_class_name = +''
|
562
568
|
full_class_name << "::#{self.name}" unless self == Object
|
563
569
|
full_class_name << "::#{plural_class_name.underscore.singularize.camelize}"
|
564
|
-
if (plural_class_name == 'BrickSwagger' ||
|
570
|
+
if (plural_class_name == 'BrickSwagger' ||
|
571
|
+
(::Brick.config.add_orphans && plural_class_name == 'BrickGem') ||
|
572
|
+
model = self.const_get(full_class_name))
|
565
573
|
# 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.
|
566
574
|
Object.send(:build_controller, self, class_name, plural_class_name, model, relations)
|
567
575
|
end
|
@@ -627,8 +635,8 @@ Module.class_exec do
|
|
627
635
|
# module_prefixes.unshift('') unless module_prefixes.first.blank?
|
628
636
|
# candidate_file = Rails.root.join('app/models' + module_prefixes.map(&:underscore).join('/') + '.rb')
|
629
637
|
self._brick_const_missing(*args)
|
630
|
-
elsif self != Object
|
631
|
-
|
638
|
+
# elsif self != Object
|
639
|
+
# module_parent.const_missing(*args)
|
632
640
|
else
|
633
641
|
puts "MISSING! #{self.name} #{args.inspect} #{table_name}"
|
634
642
|
self._brick_const_missing(*args)
|
@@ -893,6 +901,16 @@ class Object
|
|
893
901
|
built_controller = Class.new(ActionController::Base) do |new_controller_class|
|
894
902
|
(namespace || Object).const_set(class_name.to_sym, new_controller_class)
|
895
903
|
|
904
|
+
# Brick-specific pages
|
905
|
+
if plural_class_name == 'BrickGem'
|
906
|
+
self.define_method :orphans do
|
907
|
+
instance_variable_set(:@orphans, ::Brick.find_orphans(::Brick.set_db_schema(params)))
|
908
|
+
puts "BrickGemController #{action_name} #{params.inspect}"
|
909
|
+
# render inline: 'Brick gem!'
|
910
|
+
end
|
911
|
+
return [new_controller_class, code + ' # BrickGem controller!']
|
912
|
+
end
|
913
|
+
|
896
914
|
unless (is_swagger = plural_class_name == 'BrickSwagger') # && request.format == :json)
|
897
915
|
code << " def index\n"
|
898
916
|
code << " @#{table_name} = #{model.name}#{pk&.present? ? ".order(#{pk.inspect})" : '.all'}\n"
|
@@ -1188,8 +1206,13 @@ module ActiveRecord::ConnectionHandling
|
|
1188
1206
|
case ActiveRecord::Base.connection.adapter_name
|
1189
1207
|
when 'PostgreSQL', 'SQLite' # These bring back a hash for each row because the query uses column aliases
|
1190
1208
|
# schema ||= 'public' if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
|
1209
|
+
ar_smtn = if ActiveRecord::Base.respond_to?(:schema_migrations_table_name)
|
1210
|
+
ActiveRecord::Base.schema_migrations_table_name
|
1211
|
+
else
|
1212
|
+
'schema_migrations'
|
1213
|
+
end
|
1191
1214
|
ar_imtn = ActiveRecord.version >= ::Gem::Version.new('5.0') ? ActiveRecord::Base.internal_metadata_table_name : ''
|
1192
|
-
ActiveRecord::Base.execute_sql(sql,
|
1215
|
+
ActiveRecord::Base.execute_sql(sql, ar_smtn, ar_imtn).each do |r|
|
1193
1216
|
# If Apartment gem lists the table as being associated with a non-tenanted model then use whatever it thinks
|
1194
1217
|
# is the default schema, usually 'public'.
|
1195
1218
|
schema_name = if ::Brick.config.schema_behavior[:multitenant]
|
@@ -1466,5 +1489,72 @@ module Brick
|
|
1466
1489
|
end
|
1467
1490
|
assoc_bt[:inverse] = assoc_hm
|
1468
1491
|
end
|
1492
|
+
|
1493
|
+
# Locate orphaned records
|
1494
|
+
def find_orphans(multi_schema)
|
1495
|
+
is_default_schema = multi_schema&.==(Apartment.default_schema)
|
1496
|
+
relations.each_with_object([]) do |v, s|
|
1497
|
+
frn_tbl = v.first
|
1498
|
+
next if (relation = v.last).key?(:isView) || config.exclude_tables.include?(frn_tbl) ||
|
1499
|
+
!(for_pk = (relation[:pkey].values.first&.first))
|
1500
|
+
|
1501
|
+
is_default_frn_schema = !is_default_schema && multi_schema &&
|
1502
|
+
((frn_parts = frn_tbl.split('.')).length > 1 && frn_parts.first)&.==(Apartment.default_schema)
|
1503
|
+
relation[:fks].select { |_k, assoc| assoc[:is_bt] }.each do |_k, bt|
|
1504
|
+
begin
|
1505
|
+
if bt.key?(:polymorphic)
|
1506
|
+
pri_pk = for_pk
|
1507
|
+
pri_tables = Brick.config.polymorphics["#{frn_tbl}.#{bt[:fk]}"]
|
1508
|
+
.each_with_object(Hash.new { |h, k| h[k] = [] }) do |pri_class, s|
|
1509
|
+
s[Object.const_get(pri_class).table_name] << pri_class
|
1510
|
+
end
|
1511
|
+
fk_id_col = "#{bt[:fk]}_id"
|
1512
|
+
fk_type_col = "#{bt[:fk]}_type"
|
1513
|
+
selects = []
|
1514
|
+
pri_tables.each do |pri_tbl, pri_types|
|
1515
|
+
# Skip if database is multitenant, we're not focused on "public", and the foreign and primary tables
|
1516
|
+
# are both in the "public" schema
|
1517
|
+
next if is_default_frn_schema &&
|
1518
|
+
((pri_parts = pri_tbl&.split('.'))&.length > 1 && pri_parts.first)&.==(Apartment.default_schema)
|
1519
|
+
|
1520
|
+
selects << "SELECT '#{pri_tbl}' AS pri_tbl, frn.#{fk_type_col} AS pri_type, frn.#{fk_id_col} AS pri_id, frn.#{for_pk} AS frn_id
|
1521
|
+
FROM #{frn_tbl} AS frn
|
1522
|
+
LEFT OUTER JOIN #{pri_tbl} AS pri ON pri.#{pri_pk} = frn.#{fk_id_col}
|
1523
|
+
WHERE frn.#{fk_type_col} IN (#{
|
1524
|
+
pri_types.map { |pri_type| "'#{pri_type}'" }.join(', ')
|
1525
|
+
}) AND frn.#{bt[:fk]}_id IS NOT NULL AND pri.#{pri_pk} IS NULL\n"
|
1526
|
+
end
|
1527
|
+
ActiveRecord::Base.execute_sql(selects.join("UNION ALL\n")).each do |o|
|
1528
|
+
entry = [frn_tbl, o['frn_id'], o['pri_type'], o['pri_id'], fk_id_col]
|
1529
|
+
entry << o['pri_tbl'] if (pri_class = Object.const_get(o['pri_type'])) != pri_class.base_class
|
1530
|
+
s << entry
|
1531
|
+
end
|
1532
|
+
else
|
1533
|
+
# Skip if database is multitenant, we're not focused on "public", and the foreign and primary tables
|
1534
|
+
# are both in the "public" schema
|
1535
|
+
pri_tbl = bt.key?(:inverse_table) && bt[:inverse_table]
|
1536
|
+
next if is_default_frn_schema &&
|
1537
|
+
((pri_parts = pri_tbl&.split('.'))&.length > 1 && pri_parts.first)&.==(Apartment.default_schema)
|
1538
|
+
|
1539
|
+
pri_pk = relations[pri_tbl].fetch(:pkey, nil)&.values&.first&.first ||
|
1540
|
+
_class_pk(pri_tbl, multi_schema)
|
1541
|
+
ActiveRecord::Base.execute_sql(
|
1542
|
+
"SELECT frn.#{bt[:fk]} AS pri_id, frn.#{for_pk} AS frn_id
|
1543
|
+
FROM #{frn_tbl} AS frn
|
1544
|
+
LEFT OUTER JOIN #{pri_tbl} AS pri ON pri.#{pri_pk} = frn.#{bt[:fk]}
|
1545
|
+
WHERE frn.#{bt[:fk]} IS NOT NULL AND pri.#{pri_pk} IS NULL
|
1546
|
+
ORDER BY 1, 2"
|
1547
|
+
).each { |o| s << [frn_tbl, o['frn_id'], pri_tbl, o['pri_id'], bt[:fk]] }
|
1548
|
+
end
|
1549
|
+
rescue StandardError => err
|
1550
|
+
puts "Strange -- #{err.inspect}"
|
1551
|
+
end
|
1552
|
+
end
|
1553
|
+
end
|
1554
|
+
end
|
1555
|
+
|
1556
|
+
def _class_pk(dotted_name, multitenant)
|
1557
|
+
Object.const_get((multitenant ? [dotted_name.split('.').last] : dotted_name.split('.')).map { |nm| "::#{nm.singularize.camelize}" }.join).primary_key
|
1558
|
+
end
|
1469
1559
|
end
|
1470
1560
|
end
|
@@ -50,23 +50,28 @@ module Brick
|
|
50
50
|
# ====================================
|
51
51
|
if ::Brick.enable_views?
|
52
52
|
ActionView::LookupContext.class_exec do
|
53
|
+
# Used by Rails 5.0 and above
|
53
54
|
alias :_brick_template_exists? :template_exists?
|
54
55
|
def template_exists?(*args, **options)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
56
|
+
(::Brick.config.add_orphans && args.first == 'orphans') ||
|
57
|
+
_brick_template_exists?(*args, **options) ||
|
58
|
+
set_brick_model(args)
|
59
|
+
end
|
60
|
+
|
61
|
+
def set_brick_model(find_args)
|
62
|
+
# Need to return true if we can fill in the blanks for a missing one
|
63
|
+
# args will be something like: ["index", ["categories"]]
|
64
|
+
find_args[1] = find_args[1].each_with_object([]) { |a, s| s.concat(a.split('/')) }
|
65
|
+
if (class_name = find_args[1].last&.singularize)
|
66
|
+
find_args[1][find_args[1].length - 1] = class_name # Make sure the last item, defining the class name, is singular
|
67
|
+
if (model = find_args[1].map(&:camelize).join('::').constantize) && (
|
68
|
+
['index', 'show'].include?(find_args.first) || # Everything has index and show
|
63
69
|
# Only CUD stuff has create / update / destroy
|
64
|
-
|
70
|
+
(!model.is_view? && ['new', 'create', 'edit', 'update', 'destroy'].include?(find_args.first))
|
65
71
|
)
|
66
72
|
@_brick_model = model
|
67
73
|
end
|
68
74
|
end
|
69
|
-
is_template_exists
|
70
75
|
end
|
71
76
|
|
72
77
|
def path_keys(hm_assoc, fk_name, obj_name, pk)
|
@@ -82,43 +87,58 @@ module Brick
|
|
82
87
|
|
83
88
|
alias :_brick_find_template :find_template
|
84
89
|
def find_template(*args, **options)
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
90
|
+
unless (model_name = (
|
91
|
+
@_brick_model ||
|
92
|
+
(ActionView.version < ::Gem::Version.new('5.0') && args[1].is_a?(Array) ? set_brick_model(args) : nil)
|
93
|
+
)&.name) ||
|
94
|
+
(is_orphans = ::Brick.config.add_orphans && args[0..1] == ['orphans', ['brick_gem']])
|
95
|
+
return _brick_find_template(*args, **options)
|
96
|
+
end
|
97
|
+
|
98
|
+
unless is_orphans
|
99
|
+
pk = @_brick_model._brick_primary_key(::Brick.relations.fetch(model_name, nil))
|
100
|
+
obj_name = model_name.split('::').last.underscore
|
101
|
+
path_obj_name = model_name.underscore.tr('/', '_')
|
102
|
+
table_name = obj_name.pluralize
|
103
|
+
template_link = nil
|
104
|
+
bts, hms, associatives = ::Brick.get_bts_and_hms(@_brick_model) # This gets BT and HM and also has_many :through (HMT)
|
105
|
+
hms_columns = [] # Used for 'index'
|
106
|
+
skip_klass_hms = ::Brick.config.skip_index_hms[model_name] || {}
|
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)]
|
109
|
+
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
|
115
|
+
if args.first == 'index'
|
116
|
+
hms_columns << if hm_assoc.macro == :has_many
|
117
|
+
set_ct = if skip_klass_hms.key?(assoc_name.to_sym)
|
118
|
+
'nil'
|
119
|
+
else
|
120
|
+
# Postgres column names are limited to 63 characters
|
121
|
+
attrib_name = "_br_#{assoc_name}_ct"[0..62]
|
122
|
+
"#{obj_name}.#{attrib_name} || 0"
|
123
|
+
end
|
124
|
+
if hm_fk_name
|
113
125
|
"<%= ct = #{set_ct}
|
114
126
|
link_to \"#\{ct || 'View'\} #{assoc_name}\", #{hm_assoc.klass.name.underscore.tr('/', '_').pluralize}_path({ #{path_keys(hm_assoc, hm_fk_name, obj_name, pk)} }) unless ct&.zero? %>\n"
|
115
|
-
|
127
|
+
else
|
128
|
+
"#{assoc_name}\n"
|
129
|
+
end
|
130
|
+
else # has_one
|
116
131
|
"<%= obj = #{obj_name}.#{hm.first}; link_to(obj.brick_descrip, obj) if obj %>\n"
|
117
|
-
|
118
|
-
|
119
|
-
|
132
|
+
end
|
133
|
+
elsif args.first == 'show'
|
134
|
+
hm_stuff << if hm_fk_name
|
135
|
+
"<%= link_to '#{assoc_name}', #{hm_assoc.klass.name.underscore.tr('/', '_').pluralize}_path({ #{path_keys(hm_assoc, hm_fk_name, "@#{obj_name}", pk)} }) %>\n"
|
136
|
+
else
|
137
|
+
assoc_name
|
138
|
+
end
|
139
|
+
end
|
140
|
+
s << hm_stuff
|
120
141
|
end
|
121
|
-
s << hm_stuff
|
122
142
|
end
|
123
143
|
|
124
144
|
schema_options = ::Brick.db_schemas.keys.each_with_object(+'') { |v, s| s << "<option value=\"#{v}\">#{v}</option>" }.html_safe
|
@@ -133,6 +153,7 @@ module Brick
|
|
133
153
|
end.sort.each_with_object(+'') do |v, s|
|
134
154
|
s << "<option value=\"#{v.underscore.gsub('.', '/').pluralize}\">#{v}</option>"
|
135
155
|
end.html_safe
|
156
|
+
table_options << '<option value="brick_orphans">(Orphans)</option>'.html_safe if is_orphans
|
136
157
|
css = +"<style>
|
137
158
|
#dropper {
|
138
159
|
background-color: #eee;
|
@@ -488,7 +509,7 @@ if (headerTop) {
|
|
488
509
|
::Brick.config.metadata_columns.include?(col_name) || poly_cols.include?(col_name)
|
489
510
|
|
490
511
|
col_order << col_name
|
491
|
-
%><th<%= \" title = \\\"#\{col.comment}\\\"\".html_safe
|
512
|
+
%><th<%= \" title = \\\"#\{col.comment}\\\"\".html_safe if col.respond_to?(:comment) && !col.comment.blank? %>><%
|
492
513
|
if (bt = bts[col_name]) %>
|
493
514
|
BT <%
|
494
515
|
bt[1].each do |bt_pair| %><%=
|
@@ -500,7 +521,13 @@ if (headerTop) {
|
|
500
521
|
%></th><%
|
501
522
|
end
|
502
523
|
# Consider getting the name from the association -- h.first.name -- if a more \"friendly\" alias should be used for a screwy table name
|
503
|
-
%>#{hms_headers.map
|
524
|
+
%>#{hms_headers.map do |h|
|
525
|
+
if h.first.options[:through] && !h.first.through_reflection
|
526
|
+
"<th>#{h[1]} #{h[2]} %></th>"
|
527
|
+
else
|
528
|
+
"<th>#{h[1]} <%= link_to('#{h[2]}', #{h.first.klass.name.underscore.tr('/', '_').pluralize}_path) %></th>"
|
529
|
+
end
|
530
|
+
end.join
|
504
531
|
}</tr></thead>
|
505
532
|
|
506
533
|
<tbody>
|
@@ -522,6 +549,7 @@ if (headerTop) {
|
|
522
549
|
# 0..62 because Postgres column names are limited to 63 characters
|
523
550
|
#{obj_name}, (descrips = @_brick_bt_descrip[bt.first][bt_class])[0..-2].map { |z| #{obj_name}.send(z.last[0..62]) }, (bt_id_col = descrips.last)
|
524
551
|
)
|
552
|
+
bt_txt ||= \"<< Orphaned ID: #\{val} >>\" if val
|
525
553
|
bt_id = #{obj_name}.send(*bt_id_col) if bt_id_col&.present? %>
|
526
554
|
<%= bt_id ? link_to(bt_txt, send(\"#\{bt_class.base_class.name.underscore.tr('/', '_')\}_path\".to_sym, bt_id)) : bt_txt %>
|
527
555
|
<%#= Previously was: bt_obj = bt[1].first.first.find_by(bt[2] => val); link_to(bt_obj.brick_descrip, send(\"#\{bt[1].first.first.name.underscore\}_path\".to_sym, bt_obj.send(bt[1].first.first.primary_key.to_sym))) if bt_obj %>
|
@@ -539,6 +567,22 @@ if (headerTop) {
|
|
539
567
|
|
540
568
|
#{"<hr><%= link_to \"New #{obj_name}\", new_#{path_obj_name}_path %>" unless @_brick_model.is_view?}
|
541
569
|
#{script}"
|
570
|
+
when 'orphans'
|
571
|
+
if is_orphans
|
572
|
+
"#{css}
|
573
|
+
<p style=\"color: green\"><%= notice %></p>#{"
|
574
|
+
<select id=\"schema\">#{schema_options}</select>" if ::Brick.config.schema_behavior[:multitenant] && ::Brick.db_schemas.length > 1}
|
575
|
+
<select id=\"tbl\">#{table_options}</select>
|
576
|
+
<h1>Orphans<%= \" for #\{}\" if false %></h1>
|
577
|
+
<% @orphans.each do |o|
|
578
|
+
via = \" (via #\{o[4]})\" unless \"#\{o[2].split('.').last.underscore.singularize}_id\" == o[4] %>
|
579
|
+
<a href=\"/<%= o[0].split('.').last %>/<%= o[1] %>\">
|
580
|
+
<%= \"#\{o[0]} #\{o[1]} refers#\{via} to non-existent #\{o[2]} #\{o[3]}#\{\" (in table \\\"#\{o[5]}\\\")\" if o[5]}\" %>
|
581
|
+
</a><br>
|
582
|
+
<% end %>
|
583
|
+
#{script}"
|
584
|
+
end
|
585
|
+
|
542
586
|
when 'show', 'update'
|
543
587
|
"#{css}
|
544
588
|
<p style=\"color: green\"><%= notice %></p>#{"
|
@@ -562,7 +606,7 @@ end
|
|
562
606
|
<tr>
|
563
607
|
<% next if (#{(pk || []).inspect}.include?(k) && !bts.key?(k)) ||
|
564
608
|
::Brick.config.metadata_columns.include?(k) %>
|
565
|
-
<th class=\"show-field\"<%= \" title = \\\"#\{col.comment}\\\"\".html_safe
|
609
|
+
<th class=\"show-field\"<%= \" title = \\\"#\{col.comment}\\\"\".html_safe if col.respond_to?(:comment) && !col.comment.blank? %>>
|
566
610
|
<% has_fields = true
|
567
611
|
if (bt = bts[k])
|
568
612
|
# Add a final member in this array with descriptive options to be used in <select> drop-downs
|
@@ -603,7 +647,11 @@ end
|
|
603
647
|
html_options = { prompt: \"Select #\{bt_name\}\" }
|
604
648
|
html_options[:class] = 'dimmed' unless val %>
|
605
649
|
<%= f.select k.to_sym, bt[3], { value: val || '^^^brick_NULL^^^' }, html_options %>
|
606
|
-
<%= bt_obj = bt_class&.find_by(bt_pair[1] => val)
|
650
|
+
<%= if (bt_obj = bt_class&.find_by(bt_pair[1] => val))
|
651
|
+
link_to('⇛', send(\"#\{bt_class.base_class.name.underscore.tr('/', '_')\}_path\".to_sym, bt_obj.send(bt_class.primary_key.to_sym)), { class: 'show-arrow' })
|
652
|
+
elsif val
|
653
|
+
\"Orphaned ID: #\{val}\"
|
654
|
+
end %>
|
607
655
|
<% else case #{model_name}.column_for_attribute(k).type
|
608
656
|
when :string, :text %>
|
609
657
|
<% if is_bcrypt?(val) # || .readonly? %>
|
@@ -634,6 +682,8 @@ end
|
|
634
682
|
<% end %>
|
635
683
|
|
636
684
|
#{hms_headers.each_with_object(+'') do |hm, s|
|
685
|
+
next if hm.first.options[:through] && !hm.first.through_reflection
|
686
|
+
|
637
687
|
if (pk = hm.first.klass.primary_key)
|
638
688
|
hm_singular_name = (hm_name = hm.first.name.to_s).singularize.underscore
|
639
689
|
obj_pk = (pk.is_a?(Array) ? pk : [pk]).each_with_object([]) { |pk_part, s| s << "#{hm_singular_name}.#{pk_part}" }.join(', ')
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
if Object.const_defined?('::Rake::TaskManager')
|
4
|
+
namespace :brick do
|
5
|
+
desc 'Find any seemingly-orphaned records'
|
6
|
+
task orphans: :environment do
|
7
|
+
schema_list = ((multi = ::Brick.config.schema_behavior[:multitenant]) && ::Brick.db_schemas.keys.sort) || []
|
8
|
+
schema = if schema_list.length == 1
|
9
|
+
schema_list.first
|
10
|
+
elsif schema_list.length.positive?
|
11
|
+
require 'fancy_gets'
|
12
|
+
include FancyGets
|
13
|
+
gets_list(list: schema_list, chosen: multi[:schema_to_analyse])
|
14
|
+
end
|
15
|
+
ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?", schema) if schema
|
16
|
+
orphans = ::Brick.find_orphans(schema)
|
17
|
+
puts "Orphans in #{schema}:\n#{'=' * (schema.length + 12)}" if schema
|
18
|
+
if orphans.empty?
|
19
|
+
puts "No orphans!"
|
20
|
+
else
|
21
|
+
orphans.each do |o|
|
22
|
+
via = " (via #{o[4]})" unless "#{o[2].split('.').last.underscore.singularize}_id" == o[4]
|
23
|
+
puts "#{o[0]} #{o[1]} refers#{via} to non-existent #{o[2]} #{o[3]}#{" (in table \"#{o[5]}\")" if o[5]}"
|
24
|
+
end
|
25
|
+
puts
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/brick/util.rb
CHANGED
@@ -5,7 +5,7 @@ module Brick
|
|
5
5
|
module Util
|
6
6
|
# ===================================
|
7
7
|
# Epic require patch
|
8
|
-
def self._patch_require(module_filename, folder_matcher,
|
8
|
+
def self._patch_require(module_filename, folder_matcher, replacements, autoload_symbol = nil, is_bundler = false)
|
9
9
|
mod_name_parts = module_filename.split('.')
|
10
10
|
extension = case mod_name_parts.last
|
11
11
|
when 'rb', 'so', 'o'
|
@@ -28,10 +28,13 @@ module Brick
|
|
28
28
|
Dir.mkdir(new_part) unless Dir.exist?(new_part)
|
29
29
|
new_part
|
30
30
|
end
|
31
|
-
if ::Brick::Util._write_patched(folder_matcher, module_filename, extension, custom_require_dir, nil,
|
31
|
+
if ::Brick::Util._write_patched(folder_matcher, module_filename, extension, custom_require_dir, nil, replacements) &&
|
32
32
|
!alp.include?(custom_require_dir)
|
33
33
|
alp.unshift(custom_require_dir)
|
34
34
|
end
|
35
|
+
# require 'pry-byebug'
|
36
|
+
# binding.pry
|
37
|
+
# z = 10
|
35
38
|
elsif is_bundler
|
36
39
|
puts "Bundler hack"
|
37
40
|
require 'pry-byebug'
|
@@ -56,13 +59,13 @@ module Brick
|
|
56
59
|
define_method(:require) do |name|
|
57
60
|
puts name if name.to_s.include?('cucu')
|
58
61
|
if (require_override = ::Brick::Util.instance_variable_get(:@_require_overrides)[name])
|
59
|
-
extension, folder_matcher,
|
62
|
+
extension, folder_matcher, replacements, autoload_symbol = require_override
|
60
63
|
patched_filename = "/patched_#{name.tr('/', '_')}#{extension}"
|
61
64
|
if $LOADED_FEATURES.find { |f| f.end_with?(patched_filename) }
|
62
65
|
false
|
63
66
|
else
|
64
67
|
is_replaced = false
|
65
|
-
if (replacement_path = ::Brick::Util._write_patched(folder_matcher, name, extension, ::Brick::Util._custom_require_dir, patched_filename,
|
68
|
+
if (replacement_path = ::Brick::Util._write_patched(folder_matcher, name, extension, ::Brick::Util._custom_require_dir, patched_filename, replacements))
|
66
69
|
is_replaced = Kernel.send(:orig_require, replacement_path)
|
67
70
|
elsif replacement_path.nil?
|
68
71
|
puts "Couldn't find #{name} to require it!"
|
@@ -75,7 +78,7 @@ module Brick
|
|
75
78
|
end
|
76
79
|
end
|
77
80
|
end
|
78
|
-
require_overrides[module_filename] = [extension, folder_matcher,
|
81
|
+
require_overrides[module_filename] = [extension, folder_matcher, replacements, autoload_symbol]
|
79
82
|
end
|
80
83
|
end
|
81
84
|
|
@@ -94,7 +97,7 @@ module Brick
|
|
94
97
|
|
95
98
|
# Returns the full path to the replaced filename, or
|
96
99
|
# false if the file already exists, and nil if it was unable to write anything.
|
97
|
-
def self._write_patched(folder_matcher, name, extension, dir, patched_filename,
|
100
|
+
def self._write_patched(folder_matcher, name, extension, dir, patched_filename, replacements)
|
98
101
|
# See if our replacement file might already exist for some reason
|
99
102
|
name = +"/#{name}" unless name.start_with?('/')
|
100
103
|
name << extension unless name.end_with?(extension)
|
@@ -111,9 +114,13 @@ module Brick
|
|
111
114
|
break if path.include?(folder_matcher) && (orig_as = File.open(orig_path))
|
112
115
|
end
|
113
116
|
puts [folder_matcher, name].inspect
|
114
|
-
if (
|
115
|
-
File.open(replacement_path, 'w') do |
|
116
|
-
|
117
|
+
if (updated_text = orig_as&.read)
|
118
|
+
File.open(replacement_path, 'w') do |replaced_file|
|
119
|
+
replacements = [replacements] unless replacements.first.is_a?(Array)
|
120
|
+
replacements.each do |search_text, replacement_text|
|
121
|
+
updated_text.gsub!(search_text, replacement_text)
|
122
|
+
end
|
123
|
+
num_written = replaced_file.write(updated_text)
|
117
124
|
end
|
118
125
|
orig_as.close
|
119
126
|
end
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
require 'brick/compatibility'
|
4
4
|
|
5
|
-
# Allow ActiveRecord 4.
|
5
|
+
# Allow ActiveRecord 4.2.7 and older to work with newer Ruby (>= 2.4) by avoiding a "stack level too deep"
|
6
6
|
# error when ActiveSupport tries to smarten up Numeric by messing with Fixnum and Bignum at the end of:
|
7
7
|
# activesupport-4.0.13/lib/active_support/core_ext/numeric/conversions.rb
|
8
|
-
if ActiveRecord.version < ::Gem::Version.new('4.2') &&
|
8
|
+
if ActiveRecord.version < ::Gem::Version.new('4.2.8') &&
|
9
9
|
ActiveRecord.version > ::Gem::Version.new('3.2') &&
|
10
10
|
Object.const_defined?('Integer') && Integer.superclass.name == 'Numeric'
|
11
11
|
class OurFixnum < Integer; end
|
@@ -31,25 +31,78 @@ if (ruby_version = ::Gem::Version.new(RUBY_VERSION)) >= ::Gem::Version.new('2.7'
|
|
31
31
|
# Remove circular reference for "now"
|
32
32
|
::Brick::Util._patch_require(
|
33
33
|
'active_support/values/time_zone.rb', '/activesupport',
|
34
|
-
' def parse(str, now=now)',
|
35
|
-
|
34
|
+
[' def parse(str, now=now)',
|
35
|
+
' def parse(str, now=now())']
|
36
36
|
)
|
37
37
|
# Remove circular reference for "reflection" for ActiveRecord 3.1
|
38
38
|
if ActiveRecord.version >= ::Gem::Version.new('3.1')
|
39
39
|
::Brick::Util._patch_require(
|
40
40
|
'active_record/associations/has_many_association.rb', '/activerecord',
|
41
|
-
'reflection = reflection)',
|
42
|
-
|
41
|
+
['reflection = reflection)',
|
42
|
+
'reflection = reflection())'],
|
43
43
|
:HasManyAssociation # Make sure the path for this guy is available to be autoloaded
|
44
44
|
)
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
# Add left_outer_join! to Associations::JoinDependency and Relation::QueryMethods
|
49
|
+
if ActiveRecord.version < ::Gem::Version.new('5')
|
50
|
+
is_add_left_outer_join = true
|
51
|
+
::Brick::Util._patch_require(
|
52
|
+
'active_record/associations/join_dependency.rb', '/activerecord', # /associations
|
53
|
+
["def join_constraints(outer_joins)
|
54
|
+
joins = join_root.children.flat_map { |child|
|
55
|
+
make_inner_joins join_root, child
|
56
|
+
}",
|
57
|
+
"def join_constraints(outer_joins, join_type)
|
58
|
+
joins = join_root.children.flat_map { |child|
|
59
|
+
|
60
|
+
if join_type == Arel::Nodes::OuterJoin
|
61
|
+
make_left_outer_joins join_root, child
|
62
|
+
else
|
63
|
+
make_inner_joins join_root, child
|
64
|
+
end
|
65
|
+
}"],
|
66
|
+
:JoinDependency # This one is in an "eager_autoload do" -- so how to handle it?
|
67
|
+
)
|
68
|
+
|
69
|
+
# Three changes all in the same file, query_methods.rb:
|
70
|
+
::Brick::Util._patch_require(
|
71
|
+
'active_record/relation/query_methods.rb', '/activerecord',
|
72
|
+
[
|
73
|
+
# Change 1 - Line 904
|
74
|
+
['build_joins(arel, joins_values.flatten) unless joins_values.empty?',
|
75
|
+
"build_joins(arel, joins_values.flatten) unless joins_values.empty?
|
76
|
+
build_left_outer_joins(arel, left_outer_joins_values.flatten) unless left_outer_joins_values.empty?"
|
77
|
+
],
|
78
|
+
# Change 2 - Line 992
|
79
|
+
["raise 'unknown class: %s' % join.class.name
|
80
|
+
end
|
81
|
+
end",
|
82
|
+
"raise 'unknown class: %s' % join.class.name
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
build_join_query(manager, buckets, Arel::Nodes::InnerJoin)
|
87
|
+
end
|
88
|
+
|
89
|
+
def build_join_query(manager, buckets, join_type)"
|
90
|
+
],
|
91
|
+
# Change 3 - Line 1012
|
92
|
+
['join_infos = join_dependency.join_constraints stashed_association_joins',
|
93
|
+
'join_infos = join_dependency.join_constraints stashed_association_joins, join_type'
|
94
|
+
]
|
95
|
+
],
|
96
|
+
:QueryMethods
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
|
48
101
|
# puts ::Brick::Util._patch_require(
|
49
102
|
# 'cucumber/cli/options.rb', '/cucumber/cli/options', # /cli/options
|
50
|
-
# ' def extract_environment_variables',
|
51
|
-
#
|
52
|
-
# puts 'Patch test!'"
|
103
|
+
# [' def extract_environment_variables',
|
104
|
+
# " def extract_environment_variables\n
|
105
|
+
# puts 'Patch test!'"]
|
53
106
|
# ).inspect
|
54
107
|
|
55
108
|
# An ActiveRecord extension that uses INFORMATION_SCHEMA views to reflect on all
|
@@ -75,7 +128,10 @@ module Brick
|
|
75
128
|
|
76
129
|
def set_db_schema(params)
|
77
130
|
schema = params['_brick_schema'] || 'public'
|
78
|
-
|
131
|
+
if schema && ::Brick.db_schemas&.include?(schema)
|
132
|
+
ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?;", schema)
|
133
|
+
schema
|
134
|
+
end
|
79
135
|
end
|
80
136
|
|
81
137
|
# All tables and views (what Postgres calls "relations" including column and foreign key info)
|
@@ -295,10 +351,11 @@ module Brick
|
|
295
351
|
|
296
352
|
relations = ::Brick.relations
|
297
353
|
if (ars = ::Brick.config.additional_references) || ::Brick.config.polymorphics
|
354
|
+
is_optional = ActiveRecord.version >= ::Gem::Version.new('5.0')
|
298
355
|
if ars
|
299
356
|
ars.each do |ar|
|
300
357
|
fk = ar.length < 5 ? [nil, +ar[0], ar[1], nil, +ar[2]] : [ar[0], +ar[1], ar[2], ar[3], +ar[4], ar[5]]
|
301
|
-
::Brick._add_bt_and_hm(fk, relations, false,
|
358
|
+
::Brick._add_bt_and_hm(fk, relations, false, is_optional)
|
302
359
|
end
|
303
360
|
end
|
304
361
|
if (polys = ::Brick.config.polymorphics)
|
@@ -311,7 +368,7 @@ module Brick
|
|
311
368
|
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'] }
|
312
369
|
v.each do |type|
|
313
370
|
if relations.key?(primary_table = type.underscore.pluralize)
|
314
|
-
::Brick._add_bt_and_hm([nil, table_name, poly, nil, primary_table, "(brick) #{table_name}_#{poly}"], relations, true,
|
371
|
+
::Brick._add_bt_and_hm([nil, table_name, poly, nil, primary_table, "(brick) #{table_name}_#{poly}"], relations, true, is_optional)
|
315
372
|
else
|
316
373
|
missing_stis[primary_table] = type unless ::Brick.existing_stis.key?(type)
|
317
374
|
end
|
@@ -403,6 +460,9 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
403
460
|
send(:resources, controller_name.to_sym, **options)
|
404
461
|
end
|
405
462
|
end
|
463
|
+
if ::Brick.config.add_orphans && instance_variable_get(:@set).named_routes.names.exclude?(:brick_orphans)
|
464
|
+
get('/brick_orphans', to: 'brick_gem#orphans', as: 'brick_orphans')
|
465
|
+
end
|
406
466
|
end
|
407
467
|
send(:get, '/api-docs/v1/swagger.json', { to: 'brick_swagger#index' }) if Object.const_defined?('Rswag::Ui')
|
408
468
|
end
|
@@ -414,7 +474,24 @@ end
|
|
414
474
|
|
415
475
|
require 'brick/version_number'
|
416
476
|
|
477
|
+
# Older versions of ActiveRecord would only show more serious error information from "panic" level, which is
|
478
|
+
# a level only available in Postgres 12 and older. This patch will allow older and newer versions of Postgres
|
479
|
+
# to work along with fairly old versions of Rails.
|
480
|
+
if Object.const_defined?('PG::VERSION') && ActiveRecord.version < ::Gem::Version.new('4.2.6')
|
481
|
+
::Brick::Util._patch_require(
|
482
|
+
'active_record/connection_adapters/postgresql_adapter.rb', '/activerecord', ["'panic'", "'error'"]
|
483
|
+
)
|
484
|
+
end
|
485
|
+
|
417
486
|
require 'active_record'
|
487
|
+
require 'active_record/relation'
|
488
|
+
require 'active_record/relation/query_methods' if is_add_left_outer_join
|
489
|
+
|
490
|
+
# Rake tasks
|
491
|
+
class Railtie < Rails::Railtie
|
492
|
+
Dir.glob("#{File.expand_path(__dir__)}/brick/tasks/**/*.rake").each { |task| load task }
|
493
|
+
end
|
494
|
+
|
418
495
|
# Major compatibility fixes for ActiveRecord < 4.2
|
419
496
|
# ================================================
|
420
497
|
ActiveSupport.on_load(:active_record) do
|
@@ -633,6 +710,62 @@ ActiveSupport.on_load(:active_record) do
|
|
633
710
|
end
|
634
711
|
end
|
635
712
|
end
|
713
|
+
|
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
|
726
|
+
end
|
727
|
+
end
|
728
|
+
module Querying
|
729
|
+
delegate :left_outer_joins, to: :all
|
730
|
+
end
|
731
|
+
class Relation
|
732
|
+
MULTI_VALUE_METHODS = MULTI_VALUE_METHODS + [:left_outer_joins] unless MULTI_VALUE_METHODS.include?(:left_outer_joins)
|
733
|
+
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
|
+
|
740
|
+
def left_outer_joins(*args)
|
741
|
+
check_if_method_has_arguments!(:left_outer_joins, args)
|
742
|
+
|
743
|
+
args.compact!
|
744
|
+
args.flatten!
|
745
|
+
|
746
|
+
spawn.left_outer_joins!(*args)
|
747
|
+
end
|
748
|
+
|
749
|
+
def left_outer_joins!(*args) # :nodoc:
|
750
|
+
self.left_outer_joins_values += args
|
751
|
+
self
|
752
|
+
end
|
753
|
+
|
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
|
762
|
+
end
|
763
|
+
|
764
|
+
build_join_query(manager, buckets, Arel::Nodes::OuterJoin)
|
765
|
+
end
|
766
|
+
end
|
767
|
+
end
|
768
|
+
# (End of left_outer_joins support)
|
636
769
|
end
|
637
770
|
end
|
638
771
|
|
@@ -209,7 +209,7 @@ module Brick
|
|
209
209
|
# # Specify STI subclasses either directly by name or as a general module prefix that should always relate to a specific
|
210
210
|
# # parent STI class. The prefixed :: here for these examples is mandatory. Also having a suffixed :: means instead of
|
211
211
|
# # a class reference, this is for a general namespace reference. So in this case requests for, say, either of the
|
212
|
-
# # non-
|
212
|
+
# # non-existent classes Animals::Cat or Animals::Goat (or anything else with the module prefix of \"Animals::\" would
|
213
213
|
# # build a model that inherits from Animal. And a request specifically for the class Snake would build a new model
|
214
214
|
# # that inherits from Reptile, and no other request would do this -- only specifically for Snake. The ending ::
|
215
215
|
# # indicates that it's a module prefix instead of a specific class name.
|
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.41
|
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-07-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,7 +16,7 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '4.2'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: '7.2'
|
@@ -26,10 +26,24 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
29
|
+
version: '4.2'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '7.2'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: fancy_gets
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
33
47
|
- !ruby/object:Gem::Dependency
|
34
48
|
name: appraisal
|
35
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -225,6 +239,7 @@ files:
|
|
225
239
|
- lib/brick/join_array.rb
|
226
240
|
- lib/brick/serializers/json.rb
|
227
241
|
- lib/brick/serializers/yaml.rb
|
242
|
+
- lib/brick/tasks/orphans.rake
|
228
243
|
- lib/brick/util.rb
|
229
244
|
- lib/brick/version_number.rb
|
230
245
|
- lib/generators/brick/USAGE
|