brick 1.0.40 → 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/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
|