brick 1.0.61 → 1.0.64
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 +5 -2
- data/lib/brick/frameworks/rails/engine.rb +192 -20
- data/lib/brick/version_number.rb +1 -1
- data/lib/generators/brick/migrations_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: c48ee6a2f143563e2e443f6edf0dc0e04e800e8fae6951e05b0362956129e950
|
4
|
+
data.tar.gz: f632f6e795dcf9b3aeb97e36a37c8074302c5967206b5f415a9a4b862bb4fda7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0cd5e05899a2f780a0bbf378f8f49e49f604b90cf122f2cd7efe34839c434af814c9a228f36bd18b112cd8e40b6736e88742ea0f2a1a0b55ac3f8f573e614918
|
7
|
+
data.tar.gz: a34a9f47746159f6b4b39f8a3cd994055e022be9eefe8737b73c63e5d475b283ae3b99a6a11e3faf140ca6efbf67d7f400e03147a757c237c8875f11ea2c0ea4
|
data/lib/brick/extensions.rb
CHANGED
@@ -1132,6 +1132,7 @@ class Object
|
|
1132
1132
|
@_brick_bt_descrip = model._br_bt_descrip
|
1133
1133
|
@_brick_hm_counts = model._br_hm_counts
|
1134
1134
|
@_brick_join_array = join_array
|
1135
|
+
@_brick_erd = params['_brick_erd']&.to_i
|
1135
1136
|
end
|
1136
1137
|
|
1137
1138
|
_, order_by_txt = model._brick_calculate_ordering(default_ordering(table_name, pk))
|
@@ -1542,8 +1543,10 @@ module ActiveRecord::ConnectionHandling
|
|
1542
1543
|
ON kcu.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA
|
1543
1544
|
AND kcu.TABLE_NAME = tc.TABLE_NAME
|
1544
1545
|
AND kcu.CONSTRAINT_NAME = tc.constraint_name
|
1545
|
-
WHERE t.table_schema #{
|
1546
|
-
|
1546
|
+
WHERE t.table_schema #{is_postgres ?
|
1547
|
+
"NOT IN ('information_schema', 'pg_catalog')"
|
1548
|
+
:
|
1549
|
+
"= '#{ActiveRecord::Base.connection.current_database.tr("'", "''")}'"}#{"
|
1547
1550
|
AND t.table_schema = COALESCE(current_setting('SEARCH_PATH'), 'public')" if is_postgres && schema }
|
1548
1551
|
-- AND t.table_type IN ('VIEW') -- 'BASE TABLE', 'FOREIGN TABLE'
|
1549
1552
|
AND t.table_name NOT IN ('pg_stat_statements', ?, ?)
|
@@ -47,7 +47,10 @@ module Brick
|
|
47
47
|
end
|
48
48
|
|
49
49
|
# After we're initialized and before running the rest of stuff, put our configuration in place
|
50
|
-
ActiveSupport.on_load(:after_initialize) do
|
50
|
+
ActiveSupport.on_load(:after_initialize) do |app|
|
51
|
+
assets_path = File.expand_path("#{__dir__}/../../../../vendor/assets")
|
52
|
+
(app.config.assets.precompile ||= []) << "#{assets_path}/images/brick_erd.png"
|
53
|
+
(app.config.assets.paths ||= []) << assets_path
|
51
54
|
# ====================================
|
52
55
|
# Dynamically create generic templates
|
53
56
|
# ====================================
|
@@ -179,6 +182,28 @@ module Brick
|
|
179
182
|
h1, h3 {
|
180
183
|
margin-bottom: 0;
|
181
184
|
}
|
185
|
+
#imgErd {
|
186
|
+
background-image:url(assets/brick_erd.png);
|
187
|
+
background-size: 100% 100%;
|
188
|
+
width: 2.2em;
|
189
|
+
height: 2.2em;
|
190
|
+
cursor: pointer;
|
191
|
+
}
|
192
|
+
#mermaidErd {
|
193
|
+
position: relative;
|
194
|
+
display: none;
|
195
|
+
}
|
196
|
+
#mermaidErd .exclude {
|
197
|
+
position: absolute;
|
198
|
+
color: red;
|
199
|
+
top: 0;
|
200
|
+
right: 0;
|
201
|
+
cursor: pointer;
|
202
|
+
}
|
203
|
+
.relatedModel {
|
204
|
+
cursor: pointer;
|
205
|
+
}
|
206
|
+
|
182
207
|
#dropper {
|
183
208
|
background-color: #eee;
|
184
209
|
}
|
@@ -196,6 +221,8 @@ table {
|
|
196
221
|
border-collapse: collapse;
|
197
222
|
font-size: 0.9em;
|
198
223
|
font-family: sans-serif;
|
224
|
+
}
|
225
|
+
table.shadow {
|
199
226
|
min-width: 400px;
|
200
227
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
|
201
228
|
}
|
@@ -213,6 +240,7 @@ tr th {
|
|
213
240
|
display: none;
|
214
241
|
top: 0;
|
215
242
|
right: 0;
|
243
|
+
cursor: pointer;
|
216
244
|
}
|
217
245
|
#headerTop tr th:hover {
|
218
246
|
background-color: #18B090;
|
@@ -245,7 +273,7 @@ tr th, tr td {
|
|
245
273
|
color: #80B8D2;
|
246
274
|
}
|
247
275
|
|
248
|
-
table tbody tr {
|
276
|
+
table.shadow tbody tr {
|
249
277
|
border-bottom: thin solid #dddddd;
|
250
278
|
}
|
251
279
|
|
@@ -253,7 +281,7 @@ table tbody tr:nth-of-type(even) {
|
|
253
281
|
background-color: #f3f3f3;
|
254
282
|
}
|
255
283
|
|
256
|
-
table tbody tr:last-of-type {
|
284
|
+
table.shadow tbody tr:last-of-type {
|
257
285
|
border-bottom: 2px solid #009879;
|
258
286
|
}
|
259
287
|
|
@@ -327,6 +355,28 @@ def hide_bcrypt(val, max_len = 200)
|
|
327
355
|
end
|
328
356
|
val
|
329
357
|
end
|
358
|
+
end
|
359
|
+
def display_value(col_type, val)
|
360
|
+
case col_type
|
361
|
+
when 'geometry'
|
362
|
+
if Object.const_defined?('RGeo')
|
363
|
+
@is_mysql = ActiveRecord::Base.connection.adapter_name == 'Mysql2' if @is_mysql.nil?
|
364
|
+
if @is_mysql
|
365
|
+
# MySQL's \"Internal Geometry Format\" is like WKB, but with an initial 4 bytes that indicates the SRID.
|
366
|
+
srid = val[..3].unpack('I')
|
367
|
+
val = val[4..]
|
368
|
+
end
|
369
|
+
RGeo::WKRep::WKBParser.new.parse(val)
|
370
|
+
else
|
371
|
+
'(Add RGeo gem to parse geometry detail)'
|
372
|
+
end
|
373
|
+
else
|
374
|
+
if col_type
|
375
|
+
hide_bcrypt(val)
|
376
|
+
else
|
377
|
+
'?'
|
378
|
+
end
|
379
|
+
end
|
330
380
|
end %>"
|
331
381
|
|
332
382
|
if ['index', 'show', 'update'].include?(args.first)
|
@@ -401,25 +451,28 @@ window.addEventListener(\"pageshow\", function() {
|
|
401
451
|
|
402
452
|
function changeout(href, param, value, trimAfter) {
|
403
453
|
var hrefParts = href.split(\"?\");
|
404
|
-
|
454
|
+
var params = hrefParts.length > 1 ? hrefParts[1].split(\"&\") : [];
|
455
|
+
if (param === undefined || param === null || param === -1) {
|
405
456
|
hrefParts = hrefParts[0].split(\"://\");
|
406
457
|
var pathParts = hrefParts[hrefParts.length - 1].split(\"/\");
|
407
458
|
if (value === undefined)
|
408
459
|
// A couple possibilities if it's namespaced, starting with two parts in the path -- and then try just one
|
409
460
|
return [pathParts.slice(1, 3).join('/'), pathParts.slice(1, 2)[0]];
|
410
|
-
else
|
411
|
-
|
461
|
+
else {
|
462
|
+
var queryString = param ? \"?\" + params.join(\"&\") : \"\";
|
463
|
+
return hrefParts[0] + \"://\" + pathParts[0] + \"/\" + value + queryString;
|
464
|
+
}
|
412
465
|
}
|
413
466
|
if (trimAfter) {
|
414
467
|
var pathParts = hrefParts[0].split(\"/\");
|
415
468
|
while (pathParts.lastIndexOf(trimAfter) !== pathParts.length - 1) pathParts.pop();
|
416
469
|
hrefParts[0] = pathParts.join(\"/\");
|
417
470
|
}
|
418
|
-
|
419
|
-
params = params.reduce(function (s, v) { var parts = v.split(\"=\"); s[parts[0]] = parts[1]; return s; }, {});
|
471
|
+
params = params.reduce(function (s, v) { var parts = v.split(\"=\"); if (parts[1]) s[parts[0]] = parts[1]; return s; }, {});
|
420
472
|
if (value === undefined) return params[param];
|
421
473
|
params[param] = value;
|
422
|
-
|
474
|
+
var finalParams = Object.keys(params).reduce(function (s, v) { if (params[v]) s.push(v + \"=\" + params[v]); return s; }, []).join(\"&\");
|
475
|
+
return hrefParts[0] + (finalParams.length > 0 ? \"?\" + finalParams : \"\");
|
423
476
|
}
|
424
477
|
|
425
478
|
// Snag first TR for sticky header
|
@@ -583,7 +636,10 @@ if (headerTop) {
|
|
583
636
|
<p style=\"color: green\"><%= notice %></p>#{"
|
584
637
|
<select id=\"schema\">#{schema_options}</select>" if ::Brick.config.schema_behavior[:multitenant] && ::Brick.db_schemas.length > 1}
|
585
638
|
<select id=\"tbl\">#{table_options}</select>
|
586
|
-
<
|
639
|
+
<table id=\"resourceName\"><tr>
|
640
|
+
<td><h1>#{model_plural = model_name.pluralize}</h1></td>
|
641
|
+
<td id=\"imgErd\" title=\"Show ERD\"></td>
|
642
|
+
</tr></table>#{template_link}<%
|
587
643
|
if (description = (relation = Brick.relations[#{model_name}.table_name])&.fetch(:description, nil)) %><%=
|
588
644
|
description %><br><%
|
589
645
|
end
|
@@ -614,10 +670,69 @@ if (headerTop) {
|
|
614
670
|
});
|
615
671
|
});
|
616
672
|
</script>
|
673
|
+
<% end
|
674
|
+
if true # @_brick_erd
|
675
|
+
%><div id=\"mermaidErd\" class=\"mermaid\">
|
676
|
+
erDiagram
|
677
|
+
<% model_short_name = #{@_brick_model.name.split('::').last.inspect}
|
678
|
+
callbacks = {}
|
679
|
+
@_brick_bt_descrip.each do |bt|
|
680
|
+
bt_class = bt[1].first.first
|
681
|
+
callbacks[bt_name = bt_class.name.split('::').last] = bt_class
|
682
|
+
is_has_one = #{@_brick_model.name}.reflect_on_association(bt.first).inverse_of&.macro == :has_one ||
|
683
|
+
::Brick.config.has_ones&.fetch('#{@_brick_model.name}', nil)&.key?(bt.first.to_s)
|
684
|
+
%> <%= \"#\{model_short_name} #\{is_has_one ? '||' : '}o'}--|| #\{bt_name} : \\\"#\{
|
685
|
+
bt.first unless bt.first.to_s == bt[1].first.first.name.underscore.singularize.tr('/', '_')
|
686
|
+
}\\\"\".html_safe %>
|
687
|
+
<% end
|
688
|
+
last_through = nil
|
689
|
+
@_brick_hm_counts.each do |hm|
|
690
|
+
# Skip showing self-referencing HM links since they would have already been drawn while evaluating the BT side
|
691
|
+
next if (hm_class = hm.last.klass) == #{@_brick_model.name}
|
692
|
+
|
693
|
+
callbacks[hm_name = hm_class.name.split('::').last] = hm_class
|
694
|
+
if (through = hm.last.options[:through]&.to_s) # has_many :through (HMT)
|
695
|
+
callbacks[through.singularize.camelize] = (through_assoc = hm.last.source_reflection).active_record
|
696
|
+
if last_through == through # Same HM, so no need to build it again, and for clarity just put in a blank line
|
697
|
+
%><%= \"\n\"
|
698
|
+
%><% else
|
699
|
+
%> <%= \"#\{model_short_name} ||--o{ #\{through_assoc.active_record.name}\".html_safe %> : \"\"
|
700
|
+
<% last_through = through
|
701
|
+
end
|
702
|
+
%> <%= \"#\{through_assoc.active_record.name} }o--|| #\{hm_name}\".html_safe %> : \"\"
|
703
|
+
<%= \"#\{model_short_name} }o..o{ #\{hm_name} : \\\"#\{hm.first}\\\"\".html_safe %><%
|
704
|
+
else # has_many
|
705
|
+
%> <%= \"#\{model_short_name} ||--o{ #\{hm_name} : \\\"#\{
|
706
|
+
hm_name unless hm.first.to_s == hm_class.name.underscore.pluralize.tr('/', '_')
|
707
|
+
}\\\"\".html_safe %><%
|
708
|
+
end %>
|
709
|
+
<% end
|
710
|
+
callbacks.merge({model_short_name => #{@_brick_model.name}}).each do |cb_k, cb_class|
|
711
|
+
cb_relation = ::Brick.relations[cb_class.table_name]
|
712
|
+
pkeys = cb_relation[:pkey]&.first&.last
|
713
|
+
fkeys = cb_relation[:fks]&.values&.each_with_object([]) { |fk, s| s << fk[:fk] if fk.fetch(:is_bt, nil) }
|
714
|
+
%> <%= cb_k %> {<%
|
715
|
+
pkeys&.each do |pk| %>
|
716
|
+
<%= \"int #\{pk} \\\"PK#\{' fk' if fkeys&.include?(pk)}\\\"\".html_safe %><%
|
717
|
+
end %><%
|
718
|
+
fkeys&.each do |fk|
|
719
|
+
if fk.is_a?(Array)
|
720
|
+
fk.each do |fk_part| %>
|
721
|
+
<%= \"int #\{fk_part} \\\" fk\\\"\".html_safe unless pkeys&.include?(fk_part) %><%
|
722
|
+
end
|
723
|
+
else %>
|
724
|
+
<%= \"int #\{fk} \\\" fk\\\"\".html_safe unless pkeys&.include?(fk) %><%
|
725
|
+
end
|
726
|
+
end %>
|
727
|
+
}
|
728
|
+
<% end
|
729
|
+
# callback < %= cb_k % > erdClick
|
730
|
+
%>
|
731
|
+
</div>
|
617
732
|
<% end
|
618
733
|
|
619
|
-
%><table id=\"headerTop\">
|
620
|
-
<table id=\"#{table_name}\">
|
734
|
+
%><table id=\"headerTop\"></table>
|
735
|
+
<table id=\"#{table_name}\" class=\"shadow\">
|
621
736
|
<thead><tr>#{"<th x-order=\"#{pk.join(',')}\"></th>" if pk.present?}<%=
|
622
737
|
# Consider getting the name from the association -- hm.first.name -- if a more \"friendly\" alias should be used for a screwy table name
|
623
738
|
cols = {#{hms_keys = []
|
@@ -683,7 +798,7 @@ if (headerTop) {
|
|
683
798
|
<% end
|
684
799
|
elsif (hms_col = hms_cols[col_name])
|
685
800
|
if hms_col.length == 1 %>
|
686
|
-
|
801
|
+
<%= hms_col.first %>
|
687
802
|
<% else
|
688
803
|
klass = (col = cols[col_name])[1]
|
689
804
|
txt = if col[2] == 'HO'
|
@@ -696,8 +811,8 @@ if (headerTop) {
|
|
696
811
|
end %>
|
697
812
|
<%= link_to txt, send(\"#\{klass.name.underscore.tr('/', '_').pluralize}_path\".to_sym, hms_col[2]) unless hms_col[1]&.zero? %>
|
698
813
|
<% end
|
699
|
-
elsif cols
|
700
|
-
|
814
|
+
elsif (col = cols[col_name])
|
815
|
+
%><%= display_value(col&.type || col&.sql_type, val) %><%
|
701
816
|
else # Bad column name!
|
702
817
|
%>?<%
|
703
818
|
end
|
@@ -720,7 +835,7 @@ if (headerTop) {
|
|
720
835
|
<select id=\"schema\">#{schema_options}</select>" if ::Brick.config.schema_behavior[:multitenant] && ::Brick.db_schemas.length > 1}
|
721
836
|
<select id=\"tbl\">#{table_options}</select>
|
722
837
|
<h1>Status</h1>
|
723
|
-
<table id=\"status\"><thead><tr>
|
838
|
+
<table id=\"status\" class=\"shadow\"><thead><tr>
|
724
839
|
<th>Resource</th>
|
725
840
|
<th>Table</th>
|
726
841
|
<th>Migration</th>
|
@@ -754,7 +869,7 @@ if (headerTop) {
|
|
754
869
|
%></td>
|
755
870
|
<tr>
|
756
871
|
<% end %>
|
757
|
-
</tbody
|
872
|
+
</tbody></table>
|
758
873
|
#{script}"
|
759
874
|
|
760
875
|
when 'orphans'
|
@@ -796,7 +911,7 @@ end
|
|
796
911
|
# path_options << { '_brick_schema': } if
|
797
912
|
# url = send(:#{model_name.underscore}_path, obj.#{pk})
|
798
913
|
form_for(obj.becomes(#{model_name})) do |f| %>
|
799
|
-
<table>
|
914
|
+
<table class=\"shadow\">
|
800
915
|
<% has_fields = false
|
801
916
|
@#{obj_name}.attributes.each do |k, val|
|
802
917
|
col = #{model_name}.columns_hash[k] %>
|
@@ -853,7 +968,7 @@ end
|
|
853
968
|
<% else
|
854
969
|
html_options = {}
|
855
970
|
html_options[:class] = 'dimmed' unless val
|
856
|
-
case (col_type =
|
971
|
+
case (col_type = col.type || col.sql_type)
|
857
972
|
when :string, :text %>
|
858
973
|
<% if is_bcrypt?(val) # || .readonly? %>
|
859
974
|
<%= hide_bcrypt(val, 1000) %>
|
@@ -883,6 +998,8 @@ end
|
|
883
998
|
# If it's not yet enabled then: create extension ltree;
|
884
999
|
val %>
|
885
1000
|
<% when :binary, :primary_key %>
|
1001
|
+
<% else %>
|
1002
|
+
<%= display_value(col_type, val) %>
|
886
1003
|
<% end %>
|
887
1004
|
<% end %>
|
888
1005
|
</td>
|
@@ -903,7 +1020,7 @@ end
|
|
903
1020
|
if (pk = hm.first.klass.primary_key)
|
904
1021
|
hm_singular_name = (hm_name = hm.first.name.to_s).singularize.underscore
|
905
1022
|
obj_pk = (pk.is_a?(Array) ? pk : [pk]).each_with_object([]) { |pk_part, s| s << "#{hm_singular_name}.#{pk_part}" }.join(', ')
|
906
|
-
s << "<table id=\"#{hm_name}\">
|
1023
|
+
s << "<table id=\"#{hm_name}\" class=\"shadow\">
|
907
1024
|
<tr><th>#{hm[3]}</th></tr>
|
908
1025
|
<% collection = @#{obj_name}.#{hm_name}
|
909
1026
|
collection = collection.is_a?(ActiveRecord::Associations::CollectionProxy) ? collection.order(#{pk.inspect}) : [collection].compact
|
@@ -938,7 +1055,62 @@ flatpickr(\".datetimepicker\", {enableTime: true});
|
|
938
1055
|
flatpickr(\".timepicker\", {enableTime: true, noCalendar: true});
|
939
1056
|
</script>
|
940
1057
|
<% end %>
|
1058
|
+
|
1059
|
+
<% if true # @_brick_erd
|
1060
|
+
%>
|
941
1061
|
<script>
|
1062
|
+
var imgErd = document.getElementById(\"imgErd\");
|
1063
|
+
var mermaidErd = document.getElementById(\"mermaidErd\");
|
1064
|
+
var mermaidCode;
|
1065
|
+
var cbs = {<%= callbacks.map { |k, v| \"#\{k}: \\\"#\{v.name.underscore.pluralize}\\\"\" }.join(', ').html_safe %>};
|
1066
|
+
imgErd.addEventListener(\"click\", showErd);
|
1067
|
+
function showErd() {
|
1068
|
+
imgErd.style.display = \"none\";
|
1069
|
+
mermaidErd.style.display = \"inline-block\";
|
1070
|
+
if (mermaidCode) return; // Cut it short if we've already rendered the diagram
|
1071
|
+
|
1072
|
+
mermaidCode = document.createElement(\"SCRIPT\");
|
1073
|
+
mermaidCode.setAttribute(\"src\", \"https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js\");
|
1074
|
+
mermaidCode.addEventListener(\"load\", function () {
|
1075
|
+
mermaid.initialize({
|
1076
|
+
startOnLoad: true,
|
1077
|
+
securityLevel: \"loose\",
|
1078
|
+
mermaid: {callback: function(objId) {
|
1079
|
+
var svg = document.getElementById(objId);
|
1080
|
+
svg.removeAttribute(\"width\");
|
1081
|
+
var cb;
|
1082
|
+
for(cb in cbs) {
|
1083
|
+
var gErd = svg.getElementById(cb);
|
1084
|
+
gErd.setAttribute(\"class\", \"relatedModel\");
|
1085
|
+
gErd.addEventListener(\"click\",
|
1086
|
+
function (evt) {
|
1087
|
+
location.href = changeout(changeout(location.href, -1, cbs[this.id]), \"_brick_erd\", \"1\");
|
1088
|
+
}
|
1089
|
+
);
|
1090
|
+
}
|
1091
|
+
}}
|
1092
|
+
});
|
1093
|
+
mermaid.contentLoaded();
|
1094
|
+
// Add <span> at the end
|
1095
|
+
var span = document.createElement(\"SPAN\");
|
1096
|
+
span.className = \"exclude\";
|
1097
|
+
span.innerHTML = \"X\";
|
1098
|
+
span.addEventListener(\"click\", function (e) {
|
1099
|
+
e.stopPropagation();
|
1100
|
+
imgErd.style.display = \"table-cell\";
|
1101
|
+
mermaidErd.style.display = \"none\";
|
1102
|
+
window.history.pushState({}, '', changeout(location.href, '_brick_erd', null));
|
1103
|
+
});
|
1104
|
+
mermaidErd.appendChild(span);
|
1105
|
+
});
|
1106
|
+
document.body.appendChild(mermaidCode);
|
1107
|
+
}
|
1108
|
+
<%= \" showErd();\n\" if (@_brick_erd || 0) > 0
|
1109
|
+
%></script>
|
1110
|
+
|
1111
|
+
<% end
|
1112
|
+
|
1113
|
+
%><script>
|
942
1114
|
<% # Make column headers sort when clicked
|
943
1115
|
# %%% Create a smart javascript routine which can do this client-side %>
|
944
1116
|
[... document.getElementsByTagName(\"TH\")].forEach(function (th) {
|
data/lib/brick/version_number.rb
CHANGED
@@ -21,7 +21,7 @@ module Brick
|
|
21
21
|
'timestamp with time zone' => 'timestamp',
|
22
22
|
'time without time zone' => 'time',
|
23
23
|
'time with time zone' => 'time',
|
24
|
-
'double precision' => 'float',
|
24
|
+
'double precision' => 'float',
|
25
25
|
'smallint' => 'integer' } # %%% Need to put in "limit: 2"
|
26
26
|
# (Still need to find what "inet" and "json" data types map to.)
|
27
27
|
|
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.64
|
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-08-
|
11
|
+
date: 2022-08-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|