brick 1.0.104 → 1.0.105
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 +4 -4
- data/lib/brick/extensions.rb +17 -8
- data/lib/brick/frameworks/rails/engine.rb +4 -3
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +69 -14
- data/lib/generators/brick/install_generator.rb +3 -2
- metadata +16 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 48fc69654d7cbdf5c7feb9ba7803b7a953c6c0ccd3c176614fe9a61994bb39e1
|
|
4
|
+
data.tar.gz: f3a4837d334cf97cb491cacd658cb6e6d8e3f3a5c640f80c151a083bf6811b7a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e51134710bae78f033b9dcf7827cd7c087cfd642ef8bc6244e2429f22158a80e9f804022bc703f55fa55f85cbc009ff25440289205ade1b415f5ba0af3d44c77
|
|
7
|
+
data.tar.gz: d6069676ad70e8401f7597b92b641f0f95e3c28fffa54747f630932500c778d7b4ac967c5bbd70059647d11d398598362d9c0bb5c82ef0500b1025371104a578
|
data/lib/brick/config.rb
CHANGED
|
@@ -94,13 +94,13 @@ module Brick
|
|
|
94
94
|
@mutex.synchronize { @enable_api = enable }
|
|
95
95
|
end
|
|
96
96
|
|
|
97
|
-
def
|
|
97
|
+
def api_roots
|
|
98
98
|
ver = api_version
|
|
99
|
-
@mutex.synchronize { @
|
|
99
|
+
@mutex.synchronize { @api_roots || ["/api/#{ver}/"] }
|
|
100
100
|
end
|
|
101
101
|
|
|
102
|
-
def
|
|
103
|
-
@mutex.synchronize { @
|
|
102
|
+
def api_roots=(path)
|
|
103
|
+
@mutex.synchronize { @api_roots = path }
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
def api_version
|
data/lib/brick/extensions.rb
CHANGED
|
@@ -1526,7 +1526,11 @@ class Object
|
|
|
1526
1526
|
self.protect_from_forgery unless: -> { self.request.format.js? }
|
|
1527
1527
|
unless is_avo
|
|
1528
1528
|
self.define_method :index do
|
|
1529
|
-
|
|
1529
|
+
current_api_root = ::Brick.config.api_roots.find do |ar|
|
|
1530
|
+
request.path.start_with?(ar) || # Exact match?
|
|
1531
|
+
request.path.split('/')[-2] == ar.split('/').last # Version at least matches?
|
|
1532
|
+
end
|
|
1533
|
+
if (current_api_root || is_openapi) &&
|
|
1530
1534
|
!params&.key?('_brick_schema') &&
|
|
1531
1535
|
(referrer_params = request.env['HTTP_REFERER']&.split('?')&.last&.split('&')&.map { |x| x.split('=') }).present?
|
|
1532
1536
|
if params
|
|
@@ -1538,6 +1542,7 @@ class Object
|
|
|
1538
1542
|
_schema, @_is_show_schema_list = ::Brick.set_db_schema(params || api_params)
|
|
1539
1543
|
|
|
1540
1544
|
if is_openapi
|
|
1545
|
+
current_api_ver = current_api_root.split('/').last&.[](1..-1).to_i
|
|
1541
1546
|
json = { 'openapi': '3.0.1', 'info': { 'title': Rswag::Ui.config.config_object[:urls].last&.fetch(:name, 'API documentation'), 'version': ::Brick.config.api_version },
|
|
1542
1547
|
'servers': [
|
|
1543
1548
|
{ 'url': '{scheme}://{defaultHost}', 'variables': {
|
|
@@ -1546,15 +1551,19 @@ class Object
|
|
|
1546
1551
|
} }
|
|
1547
1552
|
]
|
|
1548
1553
|
}
|
|
1549
|
-
json['paths'] = relations.
|
|
1554
|
+
json['paths'] = relations.each_with_object({}) do |relation, s|
|
|
1550
1555
|
unless ::Brick.config.enable_api == false
|
|
1556
|
+
next if (api_vers = relation.last.fetch(:api, nil)) &&
|
|
1557
|
+
!(api_ver_path = api_vers[current_api_ver])
|
|
1558
|
+
|
|
1559
|
+
relation_name = api_ver_path || relation.first.tr('.', '/')
|
|
1551
1560
|
table_description = relation.last[:description]
|
|
1552
|
-
s["#{
|
|
1561
|
+
s["#{current_api_root}#{relation_name}"] = {
|
|
1553
1562
|
'get': {
|
|
1554
1563
|
'summary': "list #{relation.first}",
|
|
1555
1564
|
'description': table_description,
|
|
1556
1565
|
'parameters': relation.last[:cols].map do |k, v|
|
|
1557
|
-
param = { 'name' => k, 'schema': { 'type': v.first } }
|
|
1566
|
+
param = { in: 'query', 'name' => k, 'schema': { 'type': v.first } }
|
|
1558
1567
|
if (col_descrip = relation.last.fetch(:col_descrips, nil)&.fetch(k, nil))
|
|
1559
1568
|
param['description'] = col_descrip
|
|
1560
1569
|
end
|
|
@@ -1564,7 +1573,7 @@ class Object
|
|
|
1564
1573
|
}
|
|
1565
1574
|
}
|
|
1566
1575
|
|
|
1567
|
-
s["#{
|
|
1576
|
+
s["#{current_api_root}#{relation_name}/{id}"] = {
|
|
1568
1577
|
'patch': {
|
|
1569
1578
|
'summary': "update a #{relation.first.singularize}",
|
|
1570
1579
|
'description': table_description,
|
|
@@ -1578,7 +1587,6 @@ class Object
|
|
|
1578
1587
|
'responses': { '200': { 'description': 'successful' } }
|
|
1579
1588
|
}
|
|
1580
1589
|
} unless relation.last.fetch(:isView, nil)
|
|
1581
|
-
s
|
|
1582
1590
|
end
|
|
1583
1591
|
end
|
|
1584
1592
|
render inline: json.to_json, content_type: request.format
|
|
@@ -1592,9 +1600,10 @@ class Object
|
|
|
1592
1600
|
end
|
|
1593
1601
|
render inline: exported_csv, content_type: request.format
|
|
1594
1602
|
return
|
|
1595
|
-
elsif request.format == :js ||
|
|
1603
|
+
elsif request.format == :js || current_api_root # Asking for JSON?
|
|
1604
|
+
# %%% Add: where, order, page, page_size, offset, limit
|
|
1596
1605
|
data = (model.is_view? || !Object.const_defined?('DutyFree')) ? model.limit(1000) : model.df_export(model.brick_import_template)
|
|
1597
|
-
render inline: data.to_json, content_type: request.format == '*/*' ? 'application/json' : request.format
|
|
1606
|
+
render inline: { data: data }.to_json, content_type: request.format == '*/*' ? 'application/json' : request.format
|
|
1598
1607
|
return
|
|
1599
1608
|
end
|
|
1600
1609
|
|
|
@@ -464,7 +464,7 @@ window.addEventListener(\"popstate\", linkSchemas);
|
|
|
464
464
|
table_options << "<option value=\"#{prefix}brick_orphans\">(Orphans)</option>".html_safe if is_orphans
|
|
465
465
|
table_options << "<option value=\"#{prefix}brick_orphans\">(Crosstab)</option>".html_safe if is_crosstab
|
|
466
466
|
css = +"<style>
|
|
467
|
-
#
|
|
467
|
+
#titleSticky {
|
|
468
468
|
position: sticky;
|
|
469
469
|
display: inline-block;
|
|
470
470
|
left: 0;
|
|
@@ -881,6 +881,7 @@ if (grid) {
|
|
|
881
881
|
// });
|
|
882
882
|
}
|
|
883
883
|
function setHeaderSizes() {
|
|
884
|
+
document.getElementById(\"titleBox\").style.width = grid.clientWidth;
|
|
884
885
|
// console.log(\"start\");
|
|
885
886
|
// See if the headerTop is already populated
|
|
886
887
|
// %%% Grab the TRs from headerTop, clear it out, do this stuff, add them back
|
|
@@ -1127,7 +1128,7 @@ erDiagram
|
|
|
1127
1128
|
%></title>
|
|
1128
1129
|
</head>
|
|
1129
1130
|
<body>
|
|
1130
|
-
<div id=\"titleBox\">
|
|
1131
|
+
<div id=\"titleBox\"><div id=\"titleSticky\">
|
|
1131
1132
|
<p style=\"color: green\"><%= notice %></p>#{"
|
|
1132
1133
|
#{schema_options}" if schema_options}
|
|
1133
1134
|
<select id=\"tbl\">#{table_options}</select>
|
|
@@ -1182,7 +1183,7 @@ erDiagram
|
|
|
1182
1183
|
});
|
|
1183
1184
|
</script>
|
|
1184
1185
|
<% end %>
|
|
1185
|
-
</div>
|
|
1186
|
+
</div></div>
|
|
1186
1187
|
#{erd_markup}
|
|
1187
1188
|
|
|
1188
1189
|
<%= # Consider getting the name from the association -- hm.first.name -- if a more \"friendly\" alias should be used for a screwy table name
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
|
@@ -334,12 +334,17 @@ module Brick
|
|
|
334
334
|
|
|
335
335
|
# @api public
|
|
336
336
|
def api_root=(path)
|
|
337
|
-
Brick.config.
|
|
337
|
+
Brick.config.api_roots = [path]
|
|
338
338
|
end
|
|
339
339
|
|
|
340
340
|
# @api public
|
|
341
|
-
def
|
|
342
|
-
Brick.config.
|
|
341
|
+
def api_roots=(paths)
|
|
342
|
+
Brick.config.api_roots = paths
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# @api public
|
|
346
|
+
def api_roots
|
|
347
|
+
Brick.config.api_roots
|
|
343
348
|
end
|
|
344
349
|
|
|
345
350
|
# @api public
|
|
@@ -657,19 +662,65 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
|
657
662
|
# Turn something like {"::Spouse"=>"Person", "::Friend"=>"Person"} into {"Person"=>["Spouse", "Friend"]}
|
|
658
663
|
s[v.last] << v.first[2..-1] unless v.first.end_with?('::')
|
|
659
664
|
end
|
|
665
|
+
versioned_views = {} # Track which views have already been done for each api_root
|
|
660
666
|
::Brick.relations.each do |k, v|
|
|
661
667
|
next if !(controller_name = v.fetch(:resource, nil)&.pluralize) || existing_controllers.key?(controller_name)
|
|
662
668
|
|
|
669
|
+
schema_name = v.fetch(:schema, nil)
|
|
663
670
|
options = {}
|
|
664
671
|
options[:only] = [:index, :show] if v.key?(:isView)
|
|
665
|
-
# First do the API routes
|
|
672
|
+
# First do the API routes if necessary
|
|
666
673
|
full_resource = nil
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
#
|
|
672
|
-
|
|
674
|
+
::Brick.api_roots&.each do |api_root|
|
|
675
|
+
api_done_views = (versioned_views[api_root] ||= {})
|
|
676
|
+
found = nil
|
|
677
|
+
view_relation = nil
|
|
678
|
+
# If it's a view then see if there's a versioned one available by searching for resource names
|
|
679
|
+
# versioned with the closest number (equal to or less than) compared with our API version number.
|
|
680
|
+
if v.key?(:isView) && (ver = k.match(/^v([\d_]*)/).captures.first)[-1] == '_'
|
|
681
|
+
next if api_done_views.key?(unversioned = k[ver.length + 1..-1])
|
|
682
|
+
|
|
683
|
+
# # if ().length.positive? # Does it have a version number?
|
|
684
|
+
# try_num = (ver_num = (ver = ver[1..-1].gsub('_', '.')).to_d)
|
|
685
|
+
|
|
686
|
+
# Expect that the last item in the path generally holds versioning information
|
|
687
|
+
api_ver = api_root.split('/')[-1]&.gsub('_', '.')
|
|
688
|
+
vn_idx = api_ver.rindex(/[^\d._]/) # Position of the first numeric digit at the end of the version number
|
|
689
|
+
# Was: .to_d
|
|
690
|
+
api_ver_num = api_ver[vn_idx + 1..-1].gsub('_', '.').to_i # Attempt to turn something like "v3" into the decimal value 3
|
|
691
|
+
# puts [api_ver, vn_idx, api_ver_num, unversioned].inspect
|
|
692
|
+
|
|
693
|
+
next if ver.to_i > api_ver_num # Don't surface any newer views in an older API
|
|
694
|
+
|
|
695
|
+
api_ver_num -= 1 until api_ver_num.zero? ||
|
|
696
|
+
(view_relation = ::Brick.relations.fetch(
|
|
697
|
+
found = "v#{api_ver_num}_#{k[ver.length + 1..-1]}", nil
|
|
698
|
+
))
|
|
699
|
+
api_done_views[unversioned] = nil # Mark that for this API version this view is done
|
|
700
|
+
|
|
701
|
+
# puts "Found #{found}" if view_relation
|
|
702
|
+
# If we haven't found "v3_view_name" or "v2_view_name" or so forth, at the last
|
|
703
|
+
# fall back to simply looking for "v_view_name", and then finally "view_name".
|
|
704
|
+
unversioned = "v_#{unversioned}"
|
|
705
|
+
view_relation ||= ::Brick.relations.fetch(found = unversioned,
|
|
706
|
+
::Brick.relations.fetch(found = unversioned, nil)
|
|
707
|
+
)
|
|
708
|
+
if found && view_relation && k != (found = unversioned)
|
|
709
|
+
view_relation[:api][api_ver_num] = found
|
|
710
|
+
end
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
# view_ver_num = if (first_part = k.split('_').first) =~ /^v[\d_]+/
|
|
714
|
+
# first_part[1..-1].gsub('_', '.').to_i
|
|
715
|
+
# end
|
|
716
|
+
controller_name = view_relation.fetch(:resource, nil)&.pluralize if view_relation
|
|
717
|
+
if schema_name
|
|
718
|
+
full_resource = "#{schema_name}/#{found || v[:resource]}"
|
|
719
|
+
send(:get, "#{api_root}#{full_resource}", { to: "#{controller_prefix}#{schema_name}/#{controller_name}#index" })
|
|
720
|
+
else
|
|
721
|
+
# Normally goes to something like: /api/v1/employees
|
|
722
|
+
send(:get, "#{api_root}#{found || v[:resource]}", { to: "#{controller_prefix}#{controller_name}#index" })
|
|
723
|
+
end
|
|
673
724
|
end
|
|
674
725
|
|
|
675
726
|
# Track routes being built
|
|
@@ -716,15 +767,19 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
|
716
767
|
unless ::Brick.routes_done
|
|
717
768
|
if Object.const_defined?('Rswag::Ui')
|
|
718
769
|
rswag_path = ::Rails.application.routes.routes.find { |r| r.app.app == Rswag::Ui::Engine }&.instance_variable_get(:@path_formatter)&.instance_variable_get(:@parts)&.join
|
|
719
|
-
|
|
770
|
+
first_endpoint_parts = nil
|
|
771
|
+
(doc_endpoints = Rswag::Ui.config.config_object[:urls]&.uniq!)&.each do |doc_endpoint|
|
|
720
772
|
puts "Mounting OpenApi 3.0 documentation endpoint for \"#{doc_endpoint[:name]}\" on #{doc_endpoint[:url]}"
|
|
721
773
|
send(:get, doc_endpoint[:url], { to: 'brick_openapi#index' })
|
|
722
774
|
endpoint_parts = doc_endpoint[:url]&.split('/')
|
|
723
|
-
|
|
724
|
-
|
|
775
|
+
first_endpoint_parts ||= endpoint_parts
|
|
776
|
+
end
|
|
777
|
+
if doc_endpoints.present?
|
|
778
|
+
if rswag_path && first_endpoint_parts
|
|
779
|
+
puts "API documentation now available when navigating to: /#{first_endpoint_parts&.find(&:present?)}/index.html"
|
|
725
780
|
else
|
|
726
781
|
puts "In order to make documentation available you can put this into your routes.rb:"
|
|
727
|
-
puts " mount Rswag::Ui::Engine => '/#{
|
|
782
|
+
puts " mount Rswag::Ui::Engine => '/#{first_endpoint_parts&.find(&:present?) || 'api-docs'}'"
|
|
728
783
|
end
|
|
729
784
|
else
|
|
730
785
|
sample_path = rswag_path || '/api-docs'
|
|
@@ -159,8 +159,9 @@ if ActiveRecord::Base.respond_to?(:brick_select)
|
|
|
159
159
|
# Brick.enable_views = true # Setting this to \"false\" will disable views in development
|
|
160
160
|
|
|
161
161
|
# # If The Brick sees that RSwag gem is present, it allows for API resources to be automatically served out.
|
|
162
|
-
# # You can configure
|
|
163
|
-
#
|
|
162
|
+
# # You can configure one or more root path(s) for these resources, and when there are multiple then an attempt
|
|
163
|
+
# # is made to return data from that version of the view or table name, or the most recent prior to that version:
|
|
164
|
+
# ::Brick.api_roots = ['/api/v1/']
|
|
164
165
|
# # You may also want to add an OpenAPI 3.0 documentation endpoint using Rswag::Ui:
|
|
165
166
|
# Rswag::Ui.configure do |config|
|
|
166
167
|
# config.swagger_endpoint '/api-docs/v1/swagger.json', 'API V1 Docs'
|
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.105
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Lorin Thwaits
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-01-
|
|
11
|
+
date: 2023-01-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
@@ -164,6 +164,20 @@ dependencies:
|
|
|
164
164
|
- - "~>"
|
|
165
165
|
- !ruby/object:Gem::Version
|
|
166
166
|
version: 1.42.0
|
|
167
|
+
- !ruby/object:Gem::Dependency
|
|
168
|
+
name: mysql2
|
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
|
170
|
+
requirements:
|
|
171
|
+
- - "~>"
|
|
172
|
+
- !ruby/object:Gem::Version
|
|
173
|
+
version: '0.5'
|
|
174
|
+
type: :development
|
|
175
|
+
prerelease: false
|
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
177
|
+
requirements:
|
|
178
|
+
- - "~>"
|
|
179
|
+
- !ruby/object:Gem::Version
|
|
180
|
+
version: '0.5'
|
|
167
181
|
- !ruby/object:Gem::Dependency
|
|
168
182
|
name: pg
|
|
169
183
|
requirement: !ruby/object:Gem::Requirement
|