brick 1.0.105 → 1.0.106
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 -6
- data/lib/brick/extensions.rb +69 -49
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +74 -13
- 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: 988907627ce35c257a41cbcf4b455ec852c9635fe4f8721c5af167e416fbb4ef
|
4
|
+
data.tar.gz: c4a2fe612aa26a628f347d830197f961cf21b67c825ff968fa589e6bd342d1d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3488a28db2bf8f3c7f363e9b2eb4355e9de2d4021db9a39fb45656f896046bee412a7fd310861f522915bbc244af35a2707005757357ee6b9f9877ea331e7240
|
7
|
+
data.tar.gz: 8a44cbbadde246520b028d0e474226cdf2d43e8d51bed023e20f21a0d5b6cc0e690a397908bcdbdb9b7ef21c7743bec64130258b859d1583b6c0facffd8edf5f
|
data/lib/brick/config.rb
CHANGED
@@ -95,20 +95,19 @@ module Brick
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def api_roots
|
98
|
-
|
99
|
-
@mutex.synchronize { @api_roots || ["/api/#{ver}/"] }
|
98
|
+
@mutex.synchronize { @api_roots || ["/api/v1/"] }
|
100
99
|
end
|
101
100
|
|
102
101
|
def api_roots=(path)
|
103
102
|
@mutex.synchronize { @api_roots = path }
|
104
103
|
end
|
105
104
|
|
106
|
-
def
|
107
|
-
@mutex.synchronize { @
|
105
|
+
def api_filter
|
106
|
+
@mutex.synchronize { @api_filter }
|
108
107
|
end
|
109
108
|
|
110
|
-
def
|
111
|
-
@mutex.synchronize { @
|
109
|
+
def api_filter=(proc)
|
110
|
+
@mutex.synchronize { @api_filter = proc }
|
112
111
|
end
|
113
112
|
|
114
113
|
# Additional table associations to use (Think of these as virtual foreign keys perhaps)
|
data/lib/brick/extensions.rb
CHANGED
@@ -1526,9 +1526,10 @@ 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
|
+
request_ver = request.path.split('/')[-2]
|
1529
1530
|
current_api_root = ::Brick.config.api_roots.find do |ar|
|
1530
1531
|
request.path.start_with?(ar) || # Exact match?
|
1531
|
-
|
1532
|
+
request_ver == ar.split('/').last # Version at least matches?
|
1532
1533
|
end
|
1533
1534
|
if (current_api_root || is_openapi) &&
|
1534
1535
|
!params&.key?('_brick_schema') &&
|
@@ -1542,51 +1543,63 @@ class Object
|
|
1542
1543
|
_schema, @_is_show_schema_list = ::Brick.set_db_schema(params || api_params)
|
1543
1544
|
|
1544
1545
|
if is_openapi
|
1546
|
+
api_name = Rswag::Ui.config.config_object[:urls].find do |api_url|
|
1547
|
+
api_url[:url] == request.path
|
1548
|
+
end&.fetch(:name, 'API documentation')
|
1545
1549
|
current_api_ver = current_api_root.split('/').last&.[](1..-1).to_i
|
1546
|
-
json = { 'openapi': '3.0.1', 'info': { 'title':
|
1550
|
+
json = { 'openapi': '3.0.1', 'info': { 'title': api_name, 'version': request_ver },
|
1547
1551
|
'servers': [
|
1548
|
-
{ 'url': '{scheme}://{defaultHost}',
|
1549
|
-
'
|
1550
|
-
|
1551
|
-
|
1552
|
+
{ 'url': '{scheme}://{defaultHost}',
|
1553
|
+
'variables': {
|
1554
|
+
'scheme': { 'default': request.env['rack.url_scheme'] },
|
1555
|
+
'defaultHost': { 'default': request.env['HTTP_HOST'] }
|
1556
|
+
}
|
1557
|
+
}
|
1552
1558
|
]
|
1553
1559
|
}
|
1554
|
-
|
1555
|
-
|
1560
|
+
unless ::Brick.config.enable_api == false
|
1561
|
+
json['paths'] = relations.each_with_object({}) do |relation, s|
|
1556
1562
|
next if (api_vers = relation.last.fetch(:api, nil)) &&
|
1557
|
-
!(
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
1571
|
-
|
1572
|
-
|
1573
|
-
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1587
|
-
|
1588
|
-
|
1589
|
-
|
1563
|
+
!(api_ver_paths = api_vers[current_api_ver])
|
1564
|
+
|
1565
|
+
# binding.pry if relation.last.fetch(:isView, nil) && api_ver_paths != { relation.first => ::Brick::ALL_API_ACTIONS }
|
1566
|
+
(api_ver_paths || { relation.first => ::Brick::ALL_API_ACTIONS }).each do |api_ver_path, actions|
|
1567
|
+
relation_name = api_ver_path || relation.first.tr('.', '/')
|
1568
|
+
table_description = relation.last[:description]
|
1569
|
+
unless actions&.exclude?(:index)
|
1570
|
+
s["#{current_api_root}#{relation_name}"] = {
|
1571
|
+
'get': {
|
1572
|
+
'summary': "list #{relation.first}",
|
1573
|
+
'description': table_description,
|
1574
|
+
'parameters': relation.last[:cols].map do |k, v|
|
1575
|
+
param = { in: 'query', 'name' => k, 'schema': { 'type': v.first } }
|
1576
|
+
if (col_descrip = relation.last.fetch(:col_descrips, nil)&.fetch(k, nil))
|
1577
|
+
param['description'] = col_descrip
|
1578
|
+
end
|
1579
|
+
param
|
1580
|
+
end,
|
1581
|
+
'responses': { '200': { 'description': 'successful' } }
|
1582
|
+
}
|
1583
|
+
}
|
1584
|
+
end
|
1585
|
+
|
1586
|
+
unless actions&.exclude?(:update)
|
1587
|
+
s["#{current_api_root}#{relation_name}/{id}"] = {
|
1588
|
+
'patch': {
|
1589
|
+
'summary': "update a #{relation.first.singularize}",
|
1590
|
+
'description': table_description,
|
1591
|
+
'parameters': relation.last[:cols].reject { |k, v| Brick.config.metadata_columns.include?(k) }.map do |k, v|
|
1592
|
+
param = { 'name' => k, 'schema': { 'type': v.first } }
|
1593
|
+
if (col_descrip = relation.last.fetch(:col_descrips, nil)&.fetch(k, nil))
|
1594
|
+
param['description'] = col_descrip
|
1595
|
+
end
|
1596
|
+
param
|
1597
|
+
end,
|
1598
|
+
'responses': { '200': { 'description': 'successful' } }
|
1599
|
+
}
|
1600
|
+
} unless relation.last.fetch(:isView, nil)
|
1601
|
+
end
|
1602
|
+
end # Do multiple api_ver_paths
|
1590
1603
|
end
|
1591
1604
|
end
|
1592
1605
|
render inline: json.to_json, content_type: request.format
|
@@ -1600,11 +1613,11 @@ class Object
|
|
1600
1613
|
end
|
1601
1614
|
render inline: exported_csv, content_type: request.format
|
1602
1615
|
return
|
1603
|
-
elsif request.format == :js || current_api_root # Asking for JSON?
|
1604
|
-
|
1605
|
-
|
1606
|
-
|
1607
|
-
|
1616
|
+
# elsif request.format == :js || current_api_root # Asking for JSON?
|
1617
|
+
# # %%% Add: where, order, page, page_size, offset, limit
|
1618
|
+
# data = (model.is_view? || !Object.const_defined?('DutyFree')) ? model.limit(1000) : model.df_export(model.brick_import_template)
|
1619
|
+
# render inline: { data: data }.to_json, content_type: request.format == '*/*' ? 'application/json' : request.format
|
1620
|
+
# return
|
1608
1621
|
end
|
1609
1622
|
|
1610
1623
|
# Normal (not swagger or CSV) request
|
@@ -1616,8 +1629,15 @@ class Object
|
|
1616
1629
|
|
1617
1630
|
ar_relation = ActiveRecord.version < Gem::Version.new('4') ? model.preload : model.all
|
1618
1631
|
@_brick_params = ar_relation.brick_select(params, (selects ||= []), order_by,
|
1619
|
-
|
1620
|
-
|
1632
|
+
translations = {},
|
1633
|
+
join_array = ::Brick::JoinArray.new)
|
1634
|
+
|
1635
|
+
if request.format == :js || current_api_root # Asking for JSON?
|
1636
|
+
data = ar_relation.respond_to?(:_select!) ? ar_relation.dup._select!(*selects) : ar_relation.select(selects)
|
1637
|
+
render inline: { data: data }.to_json, content_type: request.format == '*/*' ? 'application/json' : request.format
|
1638
|
+
return
|
1639
|
+
end
|
1640
|
+
|
1621
1641
|
# %%% Add custom HM count columns
|
1622
1642
|
# %%% What happens when the PK is composite?
|
1623
1643
|
counts = model._br_hm_counts.each_with_object([]) do |v, s|
|
@@ -2127,7 +2147,7 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
2127
2147
|
# AND kcu2.TABLE_NAME = ?;", Apartment::Tenant.current, table_name
|
2128
2148
|
fk_references = ActiveRecord::Base.execute_sql(sql)
|
2129
2149
|
when 'SQLite'
|
2130
|
-
sql = "SELECT m.name, fkl.\"from\", fkl.\"table\", m.name || '_' || fkl.\"from\" AS constraint_name
|
2150
|
+
sql = "SELECT NULL AS constraint_schema, m.name, fkl.\"from\", NULL AS primary_schema, fkl.\"table\", m.name || '_' || fkl.\"from\" AS constraint_name
|
2131
2151
|
FROM sqlite_master m
|
2132
2152
|
INNER JOIN pragma_foreign_key_list(m.name) fkl ON m.type = 'table'
|
2133
2153
|
ORDER BY m.name, fkl.seq"
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -124,6 +124,8 @@ if Gem::Specification.all_names.any? { |g| g.start_with?('rails-') }
|
|
124
124
|
require 'brick/frameworks/rails'
|
125
125
|
end
|
126
126
|
module Brick
|
127
|
+
ALL_API_ACTIONS = [:index, :show, :create, :update, :destroy]
|
128
|
+
|
127
129
|
class << self
|
128
130
|
def sti_models
|
129
131
|
@sti_models ||= {}
|
@@ -347,6 +349,16 @@ module Brick
|
|
347
349
|
Brick.config.api_roots
|
348
350
|
end
|
349
351
|
|
352
|
+
# @api public
|
353
|
+
def api_filter=(proc)
|
354
|
+
Brick.config.api_filter = proc
|
355
|
+
end
|
356
|
+
|
357
|
+
# @api public
|
358
|
+
def api_filter
|
359
|
+
Brick.config.api_filter
|
360
|
+
end
|
361
|
+
|
350
362
|
# @api public
|
351
363
|
def skip_database_views=(value)
|
352
364
|
Brick.config.skip_database_views = value
|
@@ -675,6 +687,7 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
675
687
|
api_done_views = (versioned_views[api_root] ||= {})
|
676
688
|
found = nil
|
677
689
|
view_relation = nil
|
690
|
+
actions = ::Brick::ALL_API_ACTIONS # By default all actions are allowed
|
678
691
|
# If it's a view then see if there's a versioned one available by searching for resource names
|
679
692
|
# versioned with the closest number (equal to or less than) compared with our API version number.
|
680
693
|
if v.key?(:isView) && (ver = k.match(/^v([\d_]*)/).captures.first)[-1] == '_'
|
@@ -687,15 +700,15 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
687
700
|
api_ver = api_root.split('/')[-1]&.gsub('_', '.')
|
688
701
|
vn_idx = api_ver.rindex(/[^\d._]/) # Position of the first numeric digit at the end of the version number
|
689
702
|
# 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
|
703
|
+
test_ver_num = api_ver_num = api_ver[vn_idx + 1..-1].gsub('_', '.').to_i # Attempt to turn something like "v3" into the decimal value 3
|
691
704
|
# puts [api_ver, vn_idx, api_ver_num, unversioned].inspect
|
692
705
|
|
693
706
|
next if ver.to_i > api_ver_num # Don't surface any newer views in an older API
|
694
707
|
|
695
|
-
|
696
|
-
|
697
|
-
found = "v#{
|
698
|
-
|
708
|
+
test_ver_num -= 1 until test_ver_num.zero? ||
|
709
|
+
(view_relation = ::Brick.relations.fetch(
|
710
|
+
found = "v#{test_ver_num}_#{k[ver.length + 1..-1]}", nil
|
711
|
+
))
|
699
712
|
api_done_views[unversioned] = nil # Mark that for this API version this view is done
|
700
713
|
|
701
714
|
# puts "Found #{found}" if view_relation
|
@@ -705,21 +718,69 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
705
718
|
view_relation ||= ::Brick.relations.fetch(found = unversioned,
|
706
719
|
::Brick.relations.fetch(found = unversioned, nil)
|
707
720
|
)
|
708
|
-
if found && view_relation && k !=
|
709
|
-
|
721
|
+
if found && view_relation && k != unversioned
|
722
|
+
# Call proc that limits which endpoints get surfaced based on version, table or view name, method (get list / get one / post / patch / delete)
|
723
|
+
# Returning nil makes it do nothing, false makes it skip creating this endpoint, and an array of up to
|
724
|
+
# these 3 things controls and changes the nature of the endpoint that gets built:
|
725
|
+
# (updated api_name, name of different relation to route to, allowed actions such as :index, :show, :create, etc)
|
726
|
+
proc_result = if (filter = ::Brick.config.api_filter).is_a?(Proc)
|
727
|
+
begin
|
728
|
+
filter.call(unversioned, k, actions, api_ver_num, found, test_ver_num)
|
729
|
+
rescue StandardError => e
|
730
|
+
puts "::Brick.api_filter Proc error: #{e.message}"
|
731
|
+
end
|
732
|
+
end
|
733
|
+
# proc_result expects to receive back: [updated_api_name, to_other_relation, allowed_actions]
|
734
|
+
|
735
|
+
case proc_result
|
736
|
+
when NilClass
|
737
|
+
# Do nothing differently than what normal behaviour would be
|
738
|
+
when FalseClass # Skip implementing this endpoint
|
739
|
+
view_relation[:api][api_ver_num] = nil
|
740
|
+
next
|
741
|
+
when Array # Did they give back an array of actions?
|
742
|
+
unless proc_result.any? { |pr| ::Brick::ALL_API_ACTIONS.exclude?(pr) }
|
743
|
+
proc_result = [unversioned, to_relation, proc_result]
|
744
|
+
end
|
745
|
+
# Otherwise don't change this array because it's probably legit
|
746
|
+
when String
|
747
|
+
proc_result = [proc_result] # Treat this as the surfaced api_name (path) they want to use for this endpoint
|
748
|
+
else
|
749
|
+
puts "::Brick.api_filter Proc warning: Unable to parse this result returned: \n #{proc_result.inspect}"
|
750
|
+
proc_result = nil # Couldn't understand what in the world was returned
|
751
|
+
end
|
752
|
+
|
753
|
+
if proc_result&.present?
|
754
|
+
if proc_result[1] # to_other_relation
|
755
|
+
if (new_view_relation = ::Brick.relations.fetch(proc_result[1], nil))
|
756
|
+
k = proc_result[1] # Route this call over to this different relation
|
757
|
+
view_relation = new_view_relation
|
758
|
+
else
|
759
|
+
puts "::Brick.api_filter Proc warning: Unable to find new suggested relation with name #{proc_result[1]} -- sticking with #{k} instead."
|
760
|
+
end
|
761
|
+
end
|
762
|
+
if proc_result.first&.!=(k) # updated_api_name -- a different name than this relation would normally have
|
763
|
+
found = proc_result.first
|
764
|
+
end
|
765
|
+
actions &= proc_result[2] if proc_result[2] # allowed_actions
|
766
|
+
end
|
710
767
|
end
|
768
|
+
(view_relation[:api][api_ver_num] ||= {})[found] = actions # Add to the list of API paths this resource responds to
|
711
769
|
end
|
712
770
|
|
713
771
|
# view_ver_num = if (first_part = k.split('_').first) =~ /^v[\d_]+/
|
714
772
|
# first_part[1..-1].gsub('_', '.').to_i
|
715
773
|
# end
|
716
774
|
controller_name = view_relation.fetch(:resource, nil)&.pluralize if view_relation
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
775
|
+
# %%% So far we can only surface the #index action
|
776
|
+
if actions.include?(:index)
|
777
|
+
if schema_name
|
778
|
+
full_resource = "#{schema_name}/#{found || v[:resource]}"
|
779
|
+
send(:get, "#{api_root}#{full_resource}", { to: "#{controller_prefix}#{schema_name}/#{controller_name}#index" })
|
780
|
+
else
|
781
|
+
# Normally goes to something like: /api/v1/employees
|
782
|
+
send(:get, "#{api_root}#{found || v[:resource]}", { to: "#{controller_prefix}#{controller_name}#index" })
|
783
|
+
end
|
723
784
|
end
|
724
785
|
end
|
725
786
|
|
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.106
|
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-18 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: rswag-ui
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
167
181
|
- !ruby/object:Gem::Dependency
|
168
182
|
name: mysql2
|
169
183
|
requirement: !ruby/object:Gem::Requirement
|