brick 1.0.104 → 1.0.105
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 +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
|