brick 1.0.40 → 1.0.41
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/brick/config.rb +5 -0
- data/lib/brick/extensions.rb +84 -3
- data/lib/brick/frameworks/rails/engine.rb +71 -33
- data/lib/brick/tasks/orphans.rake +15 -43
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +7 -1
- 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: 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/config.rb
CHANGED
data/lib/brick/extensions.rb
CHANGED
@@ -415,14 +415,16 @@ module ActiveRecord
|
|
415
415
|
hm_counts.each do |k, hm|
|
416
416
|
associative = nil
|
417
417
|
count_column = if hm.options[:through]
|
418
|
-
fk_col = (associative = associatives[hm.name])
|
419
|
-
hm.foreign_key
|
418
|
+
fk_col = (associative = associatives[hm.name])&.foreign_key
|
419
|
+
hm.foreign_key if fk_col
|
420
420
|
else
|
421
421
|
fk_col = hm.foreign_key
|
422
422
|
poly_type = hm.inverse_of.foreign_type if hm.options.key?(:as)
|
423
423
|
pk = hm.klass.primary_key
|
424
424
|
(pk.is_a?(Array) ? pk.first : pk) || '*'
|
425
425
|
end
|
426
|
+
next unless count_column # %%% Would be able to remove this when multiple foreign keys to same destination becomes bulletproof
|
427
|
+
|
426
428
|
tbl_alias = "_br_#{hm.name}"
|
427
429
|
pri_tbl = hm.active_record
|
428
430
|
on_clause = []
|
@@ -565,7 +567,9 @@ Module.class_exec do
|
|
565
567
|
full_class_name = +''
|
566
568
|
full_class_name << "::#{self.name}" unless self == Object
|
567
569
|
full_class_name << "::#{plural_class_name.underscore.singularize.camelize}"
|
568
|
-
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))
|
569
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.
|
570
574
|
Object.send(:build_controller, self, class_name, plural_class_name, model, relations)
|
571
575
|
end
|
@@ -897,6 +901,16 @@ class Object
|
|
897
901
|
built_controller = Class.new(ActionController::Base) do |new_controller_class|
|
898
902
|
(namespace || Object).const_set(class_name.to_sym, new_controller_class)
|
899
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
|
+
|
900
914
|
unless (is_swagger = plural_class_name == 'BrickSwagger') # && request.format == :json)
|
901
915
|
code << " def index\n"
|
902
916
|
code << " @#{table_name} = #{model.name}#{pk&.present? ? ".order(#{pk.inspect})" : '.all'}\n"
|
@@ -1475,5 +1489,72 @@ module Brick
|
|
1475
1489
|
end
|
1476
1490
|
assoc_bt[:inverse] = assoc_hm
|
1477
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
|
1478
1559
|
end
|
1479
1560
|
end
|
@@ -53,7 +53,9 @@ module Brick
|
|
53
53
|
# Used by Rails 5.0 and above
|
54
54
|
alias :_brick_template_exists? :template_exists?
|
55
55
|
def template_exists?(*args, **options)
|
56
|
-
|
56
|
+
(::Brick.config.add_orphans && args.first == 'orphans') ||
|
57
|
+
_brick_template_exists?(*args, **options) ||
|
58
|
+
set_brick_model(args)
|
57
59
|
end
|
58
60
|
|
59
61
|
def set_brick_model(find_args)
|
@@ -88,44 +90,55 @@ module Brick
|
|
88
90
|
unless (model_name = (
|
89
91
|
@_brick_model ||
|
90
92
|
(ActionView.version < ::Gem::Version.new('5.0') && args[1].is_a?(Array) ? set_brick_model(args) : nil)
|
91
|
-
)&.name)
|
93
|
+
)&.name) ||
|
94
|
+
(is_orphans = ::Brick.config.add_orphans && args[0..1] == ['orphans', ['brick_gem']])
|
92
95
|
return _brick_find_template(*args, **options)
|
93
96
|
end
|
94
97
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
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
|
120
125
|
"<%= ct = #{set_ct}
|
121
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"
|
122
|
-
|
127
|
+
else
|
128
|
+
"#{assoc_name}\n"
|
129
|
+
end
|
130
|
+
else # has_one
|
123
131
|
"<%= obj = #{obj_name}.#{hm.first}; link_to(obj.brick_descrip, obj) if obj %>\n"
|
124
|
-
|
125
|
-
|
126
|
-
|
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
|
127
141
|
end
|
128
|
-
s << hm_stuff
|
129
142
|
end
|
130
143
|
|
131
144
|
schema_options = ::Brick.db_schemas.keys.each_with_object(+'') { |v, s| s << "<option value=\"#{v}\">#{v}</option>" }.html_safe
|
@@ -140,6 +153,7 @@ module Brick
|
|
140
153
|
end.sort.each_with_object(+'') do |v, s|
|
141
154
|
s << "<option value=\"#{v.underscore.gsub('.', '/').pluralize}\">#{v}</option>"
|
142
155
|
end.html_safe
|
156
|
+
table_options << '<option value="brick_orphans">(Orphans)</option>'.html_safe if is_orphans
|
143
157
|
css = +"<style>
|
144
158
|
#dropper {
|
145
159
|
background-color: #eee;
|
@@ -507,7 +521,13 @@ if (headerTop) {
|
|
507
521
|
%></th><%
|
508
522
|
end
|
509
523
|
# Consider getting the name from the association -- h.first.name -- if a more \"friendly\" alias should be used for a screwy table name
|
510
|
-
%>#{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
|
511
531
|
}</tr></thead>
|
512
532
|
|
513
533
|
<tbody>
|
@@ -547,6 +567,22 @@ if (headerTop) {
|
|
547
567
|
|
548
568
|
#{"<hr><%= link_to \"New #{obj_name}\", new_#{path_obj_name}_path %>" unless @_brick_model.is_view?}
|
549
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
|
+
|
550
586
|
when 'show', 'update'
|
551
587
|
"#{css}
|
552
588
|
<p style=\"color: green\"><%= notice %></p>#{"
|
@@ -646,6 +682,8 @@ end
|
|
646
682
|
<% end %>
|
647
683
|
|
648
684
|
#{hms_headers.each_with_object(+'') do |hm, s|
|
685
|
+
next if hm.first.options[:through] && !hm.first.through_reflection
|
686
|
+
|
649
687
|
if (pk = hm.first.klass.primary_key)
|
650
688
|
hm_singular_name = (hm_name = hm.first.name.to_s).singularize.underscore
|
651
689
|
obj_pk = (pk.is_a?(Array) ? pk : [pk]).each_with_object([]) { |pk_part, s| s << "#{hm_singular_name}.#{pk_part}" }.join(', ')
|
@@ -4,53 +4,25 @@ if Object.const_defined?('::Rake::TaskManager')
|
|
4
4
|
namespace :brick do
|
5
5
|
desc 'Find any seemingly-orphaned records'
|
6
6
|
task orphans: :environment do
|
7
|
-
def class_pk(dotted_name, multitenant)
|
8
|
-
Object.const_get((multitenant ? [dotted_name.split('.').last] : dotted_name.split('.')).map { |nm| "::#{nm.singularize.camelize}" }.join).primary_key
|
9
|
-
end
|
10
|
-
|
11
7
|
schema_list = ((multi = ::Brick.config.schema_behavior[:multitenant]) && ::Brick.db_schemas.keys.sort) || []
|
12
|
-
if schema_list.length
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
elsif schema_list.length.positive?
|
20
|
-
schema = schema_list.first
|
21
|
-
end
|
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
|
22
15
|
ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?", schema) if schema
|
23
|
-
orphans =
|
24
|
-
|
25
|
-
|
26
|
-
!(pri_pk = v[:pkey].values.first&.first) ||
|
27
|
-
!(pri_pk = class_pk(k, multi))
|
28
|
-
v[:fks].each do |k1, v1|
|
29
|
-
next if v1[:is_bt] ||
|
30
|
-
!(for_rel = ::Brick.relations.fetch(v1[:inverse_table], nil)) ||
|
31
|
-
v1[:inverse]&.key?(:polymorphic) ||
|
32
|
-
!(for_pk = for_rel.fetch(:pkey, nil)&.values&.first&.first) ||
|
33
|
-
!(for_pk = class_pk(v1[:inverse_table], multi))
|
34
|
-
begin
|
35
|
-
ActiveRecord::Base.execute_sql(
|
36
|
-
"SELECT DISTINCT frn.#{v1[:fk]} AS pri_id, frn.#{for_pk} AS fk_id
|
37
|
-
FROM #{v1[:inverse_table]} AS frn
|
38
|
-
LEFT OUTER JOIN #{k} AS pri ON pri.#{pri_pk} = frn.#{v1[:fk]}
|
39
|
-
WHERE frn.#{v1[:fk]} IS NOT NULL AND pri.#{pri_pk} IS NULL
|
40
|
-
ORDER BY 1, 2"
|
41
|
-
).each do |o|
|
42
|
-
orphans << "#{v1[:inverse_table]} #{o['fk_id']} refers to non-existant #{k} #{o['pri_id']}\n"
|
43
|
-
end
|
44
|
-
rescue StandardError => err
|
45
|
-
puts "Strange -- #{err.inspect}"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
puts "For #{schema}:\n#{'=' * (schema.length + 5)}" if schema
|
50
|
-
if orphans.blank?
|
16
|
+
orphans = ::Brick.find_orphans(schema)
|
17
|
+
puts "Orphans in #{schema}:\n#{'=' * (schema.length + 12)}" if schema
|
18
|
+
if orphans.empty?
|
51
19
|
puts "No orphans!"
|
52
20
|
else
|
53
|
-
|
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
|
54
26
|
end
|
55
27
|
end
|
56
28
|
end
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -128,7 +128,10 @@ module Brick
|
|
128
128
|
|
129
129
|
def set_db_schema(params)
|
130
130
|
schema = params['_brick_schema'] || 'public'
|
131
|
-
|
131
|
+
if schema && ::Brick.db_schemas&.include?(schema)
|
132
|
+
ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?;", schema)
|
133
|
+
schema
|
134
|
+
end
|
132
135
|
end
|
133
136
|
|
134
137
|
# All tables and views (what Postgres calls "relations" including column and foreign key info)
|
@@ -457,6 +460,9 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
457
460
|
send(:resources, controller_name.to_sym, **options)
|
458
461
|
end
|
459
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
|
460
466
|
end
|
461
467
|
send(:get, '/api-docs/v1/swagger.json', { to: 'brick_swagger#index' }) if Object.const_defined?('Rswag::Ui')
|
462
468
|
end
|
@@ -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-07-
|
11
|
+
date: 2022-07-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|