brick 1.0.112 → 1.0.113
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 +21 -6
- data/lib/brick/frameworks/rails/engine.rb +44 -5
- data/lib/brick/frameworks/rails/form_tags.rb +3 -2
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +233 -233
- 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: f6cede45ed1fd983a2199fb279dffad0ecd02e51c7ed31cec6d46fccbc799e7c
|
4
|
+
data.tar.gz: 65eb5df73a7869b1bbe3ac128a69b4fda257e9dc098e77dc65c75d8f593756d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e506c2b4d00a1402e232f48c9eb95fc1edfb201a4b2d46ce8fd2a29d0f6a62e5d954ba84dfad4ccab2ff2c5c972d32478873e1f5c7ddf19bdfcca24894b0d1e
|
7
|
+
data.tar.gz: ee7dd85c423043b10efb60075716e3464db2645ac642fa43f457cf1b05c98a52cb7645e58e3a8208be8fd94b3a4b74f6b7d5e3102d890d087542a04b7e8cc7ec
|
data/lib/brick/extensions.rb
CHANGED
@@ -1602,11 +1602,11 @@ class Object
|
|
1602
1602
|
else
|
1603
1603
|
relation.last[:cols]
|
1604
1604
|
end
|
1605
|
-
{ :index => [:get, 'list'], :create => [:post, 'create a'] }.each do |k, v|
|
1605
|
+
{ :index => [:get, 'list', true], :create => [:post, 'create a', false] }.each do |k, v|
|
1606
1606
|
unless actions&.exclude?(k)
|
1607
1607
|
this_resource = (s["#{current_api_root}#{relation_name}"] ||= {})
|
1608
1608
|
this_resource[v.first] = {
|
1609
|
-
'summary': "#{v[1]} #{relation.first}",
|
1609
|
+
'summary': "#{v[1]} #{relation.first.send(v[2] ? :pluralize : :singularize)}",
|
1610
1610
|
'description': table_description,
|
1611
1611
|
'parameters': renamed_columns.map do |k2, v2|
|
1612
1612
|
param = { in: 'query', 'name': k2, 'schema': { 'type': v2.first } }
|
@@ -1841,7 +1841,19 @@ class Object
|
|
1841
1841
|
end
|
1842
1842
|
|
1843
1843
|
instance_variable_set("@#{singular_table_name}".to_sym, (obj = find_obj))
|
1844
|
-
|
1844
|
+
upd_params = send(params_name_sym)
|
1845
|
+
if (json_cols = model.columns.select { |c| c.type == :json }.map(&:name)).present?
|
1846
|
+
upd_hash = upd_params.to_h
|
1847
|
+
json_cols.each do |c|
|
1848
|
+
begin
|
1849
|
+
upd_hash[c] = JSON.parse(upd_hash[c]) # At least attempt to turn this into a parsed hash or array object
|
1850
|
+
rescue
|
1851
|
+
end
|
1852
|
+
end
|
1853
|
+
obj.send(:update, upd_hash)
|
1854
|
+
else
|
1855
|
+
obj.send(:update, upd_params)
|
1856
|
+
end
|
1845
1857
|
end
|
1846
1858
|
|
1847
1859
|
code << " def destroy\n"
|
@@ -1865,11 +1877,14 @@ class Object
|
|
1865
1877
|
@#{singular_table_name} = #{model.name}.find(id.is_a?(Array) && id.length == 1 ? id.first : id)
|
1866
1878
|
end\n"
|
1867
1879
|
self.define_method :find_obj do
|
1868
|
-
id = if model.columns_hash[pk.first]&.type == :string
|
1869
|
-
is_pk_string = true
|
1880
|
+
id = if pk.length == 1 # && model.columns_hash[pk.first]&.type == :string
|
1870
1881
|
params[:id].gsub('^^sl^^', '/')
|
1871
1882
|
else
|
1872
|
-
|
1883
|
+
if model.columns_hash[pk.first]&.type == :string
|
1884
|
+
params[:id]&.split('/')
|
1885
|
+
else
|
1886
|
+
params[:id]&.split(/[\/,_]/)
|
1887
|
+
end.map do |val_part|
|
1873
1888
|
val_part.gsub('^^sl^^', '/')
|
1874
1889
|
end
|
1875
1890
|
end
|
@@ -648,15 +648,19 @@ input+svg.revert {
|
|
648
648
|
</style>
|
649
649
|
|
650
650
|
<% is_includes_dates = nil
|
651
|
+
is_includes_json = nil
|
651
652
|
def is_bcrypt?(val)
|
652
653
|
val.is_a?(String) && val.length == 60 && val.start_with?('$2a$')
|
653
654
|
end
|
654
|
-
def hide_bcrypt(val, max_len = 200)
|
655
|
+
def hide_bcrypt(val, is_xml = nil, max_len = 200)
|
655
656
|
if is_bcrypt?(val)
|
656
657
|
'(hidden)'
|
657
658
|
else
|
658
659
|
if val.is_a?(String)
|
659
|
-
|
660
|
+
val = val.dup.force_encoding('UTF-8').strip
|
661
|
+
return CGI.escapeHTML(val) if is_xml
|
662
|
+
|
663
|
+
if val.length > max_len
|
660
664
|
if val[0] == '<' # Seems to be HTML?
|
661
665
|
cur_len = 0
|
662
666
|
cur_idx = 0
|
@@ -703,7 +707,6 @@ def hide_bcrypt(val, max_len = 200)
|
|
703
707
|
end
|
704
708
|
val = \"#\{val}...\"
|
705
709
|
end
|
706
|
-
val = val.dup.force_encoding('UTF-8') unless val.encoding.name == 'UTF-8'
|
707
710
|
val
|
708
711
|
else
|
709
712
|
val.to_s
|
@@ -768,7 +771,7 @@ def display_value(col_type, val)
|
|
768
771
|
display_binary(val) if val
|
769
772
|
else
|
770
773
|
if col_type
|
771
|
-
hide_bcrypt(val)
|
774
|
+
hide_bcrypt(val, col_type == :xml)
|
772
775
|
else
|
773
776
|
'?'
|
774
777
|
end
|
@@ -1439,7 +1442,7 @@ end
|
|
1439
1442
|
when :string, :text %>
|
1440
1443
|
<% if is_bcrypt?(val) # || .readonly?
|
1441
1444
|
is_revert = false %>
|
1442
|
-
<%= hide_bcrypt(val, 1000) %>
|
1445
|
+
<%= hide_bcrypt(val, nil, 1000) %>
|
1443
1446
|
<% else %>
|
1444
1447
|
<%= f.text_field(k.to_sym, html_options) %>
|
1445
1448
|
<% end %>
|
@@ -1476,6 +1479,13 @@ end
|
|
1476
1479
|
end %>
|
1477
1480
|
<% when :primary_key
|
1478
1481
|
is_revert = false %>
|
1482
|
+
<% when :json
|
1483
|
+
is_includes_json = true %>
|
1484
|
+
<%= # Because there are so danged many quotes in JSON, escape them specially by converting to backticks.
|
1485
|
+
# (and previous to this, escape backticks with our own goofy code of ^^br_btick__ )
|
1486
|
+
val_str = val.is_a?(String) ? val : val.to_json # Clean up bogus JSON if necessary
|
1487
|
+
json_field = f.hidden_field k.to_sym, { class: 'jsonpicker', value: val_str.gsub('`', '^^br_btick__').tr('\"', '`').html_safe } %>
|
1488
|
+
<div id=\"_br_json_<%= f.field_id(k) %>\"></div>
|
1479
1489
|
<% else %>
|
1480
1490
|
<%= is_revert = false
|
1481
1491
|
display_value(col_type, val).html_safe %>
|
@@ -1579,6 +1589,35 @@ flatpickr(\".timepicker\", {enableTime: true, noCalendar: true});
|
|
1579
1589
|
<link rel=\"stylesheet\" type=\"text/css\" href=\"https://cdnjs.cloudflare.com/ajax/libs/slim-select/1.27.1/slimselect.min.css\">
|
1580
1590
|
<% end %>
|
1581
1591
|
|
1592
|
+
<% # Started with v0.14.4 of vanilla-jsoneditor
|
1593
|
+
if is_includes_json %>
|
1594
|
+
<link rel=\"stylesheet\" type=\"text/css\" href=\"https://cdn.jsdelivr.net/npm/vanilla-jsoneditor/themes/jse-theme-default.min.css\">
|
1595
|
+
<script type=\"module\">
|
1596
|
+
import { JSONEditor } from \"https://cdn.jsdelivr.net/npm/vanilla-jsoneditor/index.min.js\";
|
1597
|
+
document.querySelectorAll(\"input.jsonpicker\").forEach(function (inp) {
|
1598
|
+
var jsonDiv;
|
1599
|
+
if (jsonDiv = document.getElementById(\"_br_json_\" + inp.id)) {
|
1600
|
+
new JSONEditor({
|
1601
|
+
target: jsonDiv,
|
1602
|
+
props: {
|
1603
|
+
// Instead of text can also do: { json: JSONValue }
|
1604
|
+
// Other options: name: \"taco\", mode: \"tree\", navigationBar: false, mainMenuBar: false, statusBar: false, search: false, templates:, history: false
|
1605
|
+
content: {text: inp.value.replace(/`/g, '\"').replace(/\\^\\^br_btick__/g, \"`\")},
|
1606
|
+
onChange: (function (inp2) {
|
1607
|
+
return function (updatedContent, previousContent, contentErrors, patchResult) {
|
1608
|
+
// console.log('onChange', updatedContent.json, updatedContent.text);
|
1609
|
+
inp2.value = updatedContent.text || JSON.stringify(updatedContent.json);
|
1610
|
+
};
|
1611
|
+
})(inp)
|
1612
|
+
}
|
1613
|
+
});
|
1614
|
+
} else {
|
1615
|
+
console.log(\"Could not find JSON picker for \" + inp.id);
|
1616
|
+
}
|
1617
|
+
});
|
1618
|
+
</script>
|
1619
|
+
<% end %>
|
1620
|
+
|
1582
1621
|
<% if true # @_brick_erd
|
1583
1622
|
%>
|
1584
1623
|
<script>
|
@@ -116,7 +116,7 @@ module Brick::Rails::FormTags
|
|
116
116
|
end
|
117
117
|
end
|
118
118
|
elsif (col = cols[col_name]).is_a?(ActiveRecord::ConnectionAdapters::Column)
|
119
|
-
binding.pry if col.is_a?(Array)
|
119
|
+
# binding.pry if col.is_a?(Array)
|
120
120
|
col_type = col&.sql_type == 'geography' ? col.sql_type : col&.type
|
121
121
|
out << display_value(col_type || col&.sql_type, val).to_s
|
122
122
|
elsif cust_col
|
@@ -201,7 +201,8 @@ module Brick::Rails::FormTags
|
|
201
201
|
end
|
202
202
|
filter = "?#{filter_parts.join('&')}" if filter_parts.present?
|
203
203
|
app_routes = Rails.application.routes # In case we're operating in another engine, reference the application since Brick routes are placed there.
|
204
|
-
|
204
|
+
klass = klass_or_obj.is_a?(ActiveRecord::Base) ? klass_or_obj.class : klass_or_obj
|
205
|
+
relation = ::Brick.relations.fetch(rel_name || klass.table_name, nil)
|
205
206
|
if (klass_or_obj&.is_a?(Class) && klass_or_obj < ActiveRecord::Base) ||
|
206
207
|
(klass_or_obj&.is_a?(ActiveRecord::Base) && klass_or_obj.new_record? && (klass_or_obj = klass_or_obj.class))
|
207
208
|
path = (proc = kwargs[:index_proc]) ? proc.call(klass_or_obj, relation) : "#{app_routes.path_for(controller: klass_or_obj.base_class._brick_index(nil, '/', relation), action: :index)}#{filter}"
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -654,270 +654,270 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
654
654
|
|
655
655
|
module RouteSet
|
656
656
|
def finalize!
|
657
|
-
|
658
|
-
unless
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
657
|
+
routeset_to_use = ::Rails.application.routes
|
658
|
+
return super unless self == routeset_to_use
|
659
|
+
|
660
|
+
path_prefix = ::Brick.config.path_prefix
|
661
|
+
existing_controllers = routes.each_with_object({}) do |r, s|
|
662
|
+
c = r.defaults[:controller]
|
663
|
+
s[c] = nil if c
|
664
|
+
end
|
665
|
+
append do
|
666
|
+
tables = []
|
667
|
+
views = []
|
668
|
+
table_class_length = 38 # Length of "Classes that can be built from tables:"
|
669
|
+
view_class_length = 37 # Length of "Classes that can be built from views:"
|
670
|
+
|
671
|
+
brick_namespace_create = lambda do |path_names, res_name, options|
|
672
|
+
if path_names&.present?
|
673
|
+
if (path_name = path_names.pop).is_a?(Array)
|
674
|
+
module_name = path_name[1]
|
675
|
+
path_name = path_name.first
|
676
|
+
end
|
677
|
+
send(:scope, { module: module_name || path_name, path: path_name, as: path_name }) do
|
678
|
+
brick_namespace_create.call(path_names, res_name, options)
|
679
|
+
end
|
680
|
+
else
|
681
|
+
send(:resources, res_name.to_sym, **options)
|
682
|
+
end
|
663
683
|
end
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
684
|
+
|
685
|
+
# %%% TODO: If no auto-controllers then enumerate the controllers folder in order to build matching routes
|
686
|
+
# If auto-controllers and auto-models are both enabled then this makes sense:
|
687
|
+
controller_prefix = (path_prefix ? "#{path_prefix}/" : '')
|
688
|
+
sti_subclasses = ::Brick.config.sti_namespace_prefixes.each_with_object(Hash.new { |h, k| h[k] = [] }) do |v, s|
|
689
|
+
# Turn something like {"::Spouse"=>"Person", "::Friend"=>"Person"} into {"Person"=>["Spouse", "Friend"]}
|
690
|
+
s[v.last] << v.first[2..-1] unless v.first.end_with?('::')
|
691
|
+
end
|
692
|
+
versioned_views = {} # Track which views have already been done for each api_root
|
693
|
+
::Brick.relations.each do |k, v|
|
694
|
+
if (schema_name = v.fetch(:schema, nil))
|
695
|
+
schema_prefix = "#{schema_name}."
|
696
|
+
end
|
697
|
+
|
698
|
+
next if !(resource_name = v.fetch(:resource, nil)) ||
|
699
|
+
existing_controllers.key?(
|
700
|
+
controller_prefix + (resource_name = "#{schema_prefix&.tr('.', '/')}#{resource_name}".pluralize)
|
701
|
+
)
|
702
|
+
|
703
|
+
object_name = k.split('.').last # Take off any first schema part
|
704
|
+
|
705
|
+
full_schema_prefix = if (aps = v.fetch(:auto_prefixed_schema, nil))
|
706
|
+
aps = aps[0..-2] if aps[-1] == '_'
|
707
|
+
(schema_prefix&.dup || +'') << "#{aps}."
|
708
|
+
else
|
709
|
+
schema_prefix
|
710
|
+
end
|
711
|
+
|
712
|
+
# Track routes being built
|
713
|
+
if (class_name = v.fetch(:class_name, nil))
|
714
|
+
if v.key?(:isView)
|
715
|
+
view_class_length = class_name.length if class_name.length > view_class_length
|
716
|
+
views
|
679
717
|
else
|
680
|
-
|
681
|
-
|
718
|
+
table_class_length = class_name.length if class_name.length > table_class_length
|
719
|
+
tables
|
720
|
+
end << [class_name, aps, resource_name]
|
682
721
|
end
|
683
722
|
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
723
|
+
options = {}
|
724
|
+
options[:only] = [:index, :show] if v.key?(:isView)
|
725
|
+
|
726
|
+
# First do the normal routes
|
727
|
+
prefixes = []
|
728
|
+
prefixes << [aps, v[:class_name]&.split('::')[-2]&.underscore] if aps
|
729
|
+
prefixes << schema_name if schema_name
|
730
|
+
prefixes << path_prefix if path_prefix
|
731
|
+
brick_namespace_create.call(prefixes, v[:resource], options)
|
732
|
+
sti_subclasses.fetch(class_name, nil)&.each do |sc| # Add any STI subclass routes for this relation
|
733
|
+
brick_namespace_create.call(prefixes, sc.underscore.tr('/', '_').pluralize, options)
|
734
|
+
end
|
696
735
|
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
736
|
+
# Now the API routes if necessary
|
737
|
+
full_resource = nil
|
738
|
+
::Brick.api_roots&.each do |api_root|
|
739
|
+
api_done_views = (versioned_views[api_root] ||= {})
|
740
|
+
found = nil
|
741
|
+
test_ver_num = nil
|
742
|
+
view_relation = nil
|
743
|
+
# If it's a view then see if there's a versioned one available by searching for resource names
|
744
|
+
# versioned with the closest number (equal to or less than) compared with our API version number.
|
745
|
+
if v.key?(:isView)
|
746
|
+
if (ver = object_name.match(/^v([\d_]*)/)&.captures&.first) && ver[-1] == '_'
|
747
|
+
core_object_name = object_name[ver.length + 1..-1]
|
748
|
+
next if api_done_views.key?(unversioned = "#{schema_prefix}v_#{core_object_name}")
|
749
|
+
|
750
|
+
# Expect that the last item in the path generally holds versioning information
|
751
|
+
api_ver = api_root.split('/')[-1]&.gsub('_', '.')
|
752
|
+
vn_idx = api_ver.rindex(/[^\d._]/) # Position of the first numeric digit at the end of the version number
|
753
|
+
# Was: .to_d
|
754
|
+
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
|
755
|
+
# puts [api_ver, vn_idx, api_ver_num, unversioned].inspect
|
756
|
+
|
757
|
+
next if ver.to_i > api_ver_num # Don't surface any newer views in an older API
|
758
|
+
|
759
|
+
test_ver_num -= 1 until test_ver_num.zero? ||
|
760
|
+
(view_relation = ::Brick.relations.fetch(
|
761
|
+
found = "#{schema_prefix}v#{test_ver_num}_#{core_object_name}", nil
|
762
|
+
))
|
763
|
+
api_done_views[unversioned] = nil # Mark that for this API version this view is done
|
764
|
+
|
765
|
+
# puts "Found #{found}" if view_relation
|
766
|
+
# If we haven't found "v3_view_name" or "v2_view_name" or so forth, at the last
|
767
|
+
# fall back to simply looking for "v_view_name", and then finally "view_name".
|
768
|
+
no_v_prefix_name = "#{schema_prefix}#{core_object_name}"
|
769
|
+
standard_prefix = 'v_'
|
716
770
|
else
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
prefixes = []
|
727
|
-
prefixes << [aps, v[:class_name]&.split('::')[-2]&.underscore] if aps
|
728
|
-
prefixes << schema_name if schema_name
|
729
|
-
prefixes << path_prefix if path_prefix
|
730
|
-
brick_namespace_create.call(prefixes, v[:resource], options)
|
731
|
-
sti_subclasses.fetch(class_name, nil)&.each do |sc| # Add any STI subclass routes for this relation
|
732
|
-
brick_namespace_create.call(prefixes, sc.underscore.tr('/', '_').pluralize, options)
|
771
|
+
core_object_name = object_name
|
772
|
+
end
|
773
|
+
if (rvp = ::Brick.config.api_remove_view_prefix) && core_object_name.start_with?(rvp)
|
774
|
+
core_object_name.slice!(0, rvp.length)
|
775
|
+
end
|
776
|
+
no_prefix_name = "#{schema_prefix}#{core_object_name}"
|
777
|
+
unversioned = "#{schema_prefix}#{standard_prefix}#{::Brick.config.api_add_view_prefix}#{core_object_name}"
|
778
|
+
else
|
779
|
+
unversioned = k
|
733
780
|
end
|
734
781
|
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
#
|
743
|
-
#
|
744
|
-
if
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
# puts "Found #{found}" if view_relation
|
765
|
-
# If we haven't found "v3_view_name" or "v2_view_name" or so forth, at the last
|
766
|
-
# fall back to simply looking for "v_view_name", and then finally "view_name".
|
767
|
-
no_v_prefix_name = "#{schema_prefix}#{core_object_name}"
|
768
|
-
standard_prefix = 'v_'
|
769
|
-
else
|
770
|
-
core_object_name = object_name
|
771
|
-
end
|
772
|
-
if (rvp = ::Brick.config.api_remove_view_prefix) && core_object_name.start_with?(rvp)
|
773
|
-
core_object_name.slice!(0, rvp.length)
|
782
|
+
view_relation ||= ::Brick.relations.fetch(found = unversioned, nil) ||
|
783
|
+
(no_v_prefix_name && ::Brick.relations.fetch(found = no_v_prefix_name, nil)) ||
|
784
|
+
(no_prefix_name && ::Brick.relations.fetch(found = no_prefix_name, nil))
|
785
|
+
if view_relation
|
786
|
+
actions = view_relation.key?(:isView) ? [:index, :show] : ::Brick::ALL_API_ACTIONS # By default all actions are allowed
|
787
|
+
# Call proc that limits which endpoints get surfaced based on version, table or view name, method (get list / get one / post / patch / delete)
|
788
|
+
# Returning nil makes it do nothing, false makes it skip creating this endpoint, and an array of up to
|
789
|
+
# these 3 things controls and changes the nature of the endpoint that gets built:
|
790
|
+
# (updated api_name, name of different relation to route to, allowed actions such as :index, :show, :create, etc)
|
791
|
+
proc_result = if (filter = ::Brick.config.api_filter).is_a?(Proc)
|
792
|
+
begin
|
793
|
+
num_args = filter.arity.negative? ? 6 : filter.arity
|
794
|
+
filter.call(*[unversioned, k, view_relation, actions, api_ver_num, found, test_ver_num][0...num_args])
|
795
|
+
rescue StandardError => e
|
796
|
+
puts "::Brick.api_filter Proc error: #{e.message}"
|
797
|
+
end
|
798
|
+
end
|
799
|
+
# proc_result expects to receive back: [updated_api_name, to_other_relation, allowed_actions]
|
800
|
+
|
801
|
+
case proc_result
|
802
|
+
when NilClass
|
803
|
+
# Do nothing differently than what normal behaviour would be
|
804
|
+
when FalseClass # Skip implementing this endpoint
|
805
|
+
view_relation[:api][api_ver_num] = nil
|
806
|
+
next
|
807
|
+
when Array # Did they give back an array of actions?
|
808
|
+
unless proc_result.any? { |pr| ::Brick::ALL_API_ACTIONS.exclude?(pr) }
|
809
|
+
proc_result = [unversioned, to_relation, proc_result]
|
774
810
|
end
|
775
|
-
|
776
|
-
|
811
|
+
# Otherwise don't change this array because it's probably legit
|
812
|
+
when String
|
813
|
+
proc_result = [proc_result] # Treat this as the surfaced api_name (path) they want to use for this endpoint
|
777
814
|
else
|
778
|
-
|
815
|
+
puts "::Brick.api_filter Proc warning: Unable to parse this result returned: \n #{proc_result.inspect}"
|
816
|
+
proc_result = nil # Couldn't understand what in the world was returned
|
779
817
|
end
|
780
818
|
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
# these 3 things controls and changes the nature of the endpoint that gets built:
|
789
|
-
# (updated api_name, name of different relation to route to, allowed actions such as :index, :show, :create, etc)
|
790
|
-
proc_result = if (filter = ::Brick.config.api_filter).is_a?(Proc)
|
791
|
-
begin
|
792
|
-
num_args = filter.arity.negative? ? 6 : filter.arity
|
793
|
-
filter.call(*[unversioned, k, view_relation, actions, api_ver_num, found, test_ver_num][0...num_args])
|
794
|
-
rescue StandardError => e
|
795
|
-
puts "::Brick.api_filter Proc error: #{e.message}"
|
796
|
-
end
|
797
|
-
end
|
798
|
-
# proc_result expects to receive back: [updated_api_name, to_other_relation, allowed_actions]
|
799
|
-
|
800
|
-
case proc_result
|
801
|
-
when NilClass
|
802
|
-
# Do nothing differently than what normal behaviour would be
|
803
|
-
when FalseClass # Skip implementing this endpoint
|
804
|
-
view_relation[:api][api_ver_num] = nil
|
805
|
-
next
|
806
|
-
when Array # Did they give back an array of actions?
|
807
|
-
unless proc_result.any? { |pr| ::Brick::ALL_API_ACTIONS.exclude?(pr) }
|
808
|
-
proc_result = [unversioned, to_relation, proc_result]
|
819
|
+
if proc_result&.present?
|
820
|
+
if proc_result[1] # to_other_relation
|
821
|
+
if (new_view_relation = ::Brick.relations.fetch(proc_result[1], nil))
|
822
|
+
k = proc_result[1] # Route this call over to this different relation
|
823
|
+
view_relation = new_view_relation
|
824
|
+
else
|
825
|
+
puts "::Brick.api_filter Proc warning: Unable to find new suggested relation with name #{proc_result[1]} -- sticking with #{k} instead."
|
809
826
|
end
|
810
|
-
# Otherwise don't change this array because it's probably legit
|
811
|
-
when String
|
812
|
-
proc_result = [proc_result] # Treat this as the surfaced api_name (path) they want to use for this endpoint
|
813
|
-
else
|
814
|
-
puts "::Brick.api_filter Proc warning: Unable to parse this result returned: \n #{proc_result.inspect}"
|
815
|
-
proc_result = nil # Couldn't understand what in the world was returned
|
816
827
|
end
|
817
|
-
|
818
|
-
|
819
|
-
if proc_result[1] # to_other_relation
|
820
|
-
if (new_view_relation = ::Brick.relations.fetch(proc_result[1], nil))
|
821
|
-
k = proc_result[1] # Route this call over to this different relation
|
822
|
-
view_relation = new_view_relation
|
823
|
-
else
|
824
|
-
puts "::Brick.api_filter Proc warning: Unable to find new suggested relation with name #{proc_result[1]} -- sticking with #{k} instead."
|
825
|
-
end
|
826
|
-
end
|
827
|
-
if proc_result.first&.!=(k) # updated_api_name -- a different name than this relation would normally have
|
828
|
-
found = proc_result.first
|
829
|
-
end
|
830
|
-
actions &= proc_result[2] if proc_result[2] # allowed_actions
|
828
|
+
if proc_result.first&.!=(k) # updated_api_name -- a different name than this relation would normally have
|
829
|
+
found = proc_result.first
|
831
830
|
end
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
831
|
+
actions &= proc_result[2] if proc_result[2] # allowed_actions
|
832
|
+
end
|
833
|
+
(view_relation[:api][api_ver_num] ||= {})[unversioned] = actions # Add to the list of API paths this resource responds to
|
834
|
+
|
835
|
+
# view_ver_num = if (first_part = k.split('_').first) =~ /^v[\d_]+/
|
836
|
+
# first_part[1..-1].gsub('_', '.').to_i
|
837
|
+
# end
|
838
|
+
controller_name = if (last = view_relation.fetch(:resource, nil)&.pluralize)
|
839
|
+
"#{full_schema_prefix}#{last}"
|
840
|
+
else
|
841
|
+
found
|
842
|
+
end.tr('.', '/')
|
843
|
+
|
844
|
+
{ :index => 'get', :create => 'post' }.each do |action, method|
|
845
|
+
if actions.include?(action)
|
846
|
+
# Normally goes to something like: /api/v1/employees
|
847
|
+
send(method, "#{api_root}#{unversioned.tr('.', '/')}", { to: "#{controller_prefix}#{controller_name}##{action}" })
|
848
848
|
end
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
849
|
+
end
|
850
|
+
# %%% We do not yet surface the #show action
|
851
|
+
if (id_col = view_relation[:pk]&.first) # ID-dependent stuff
|
852
|
+
{ :update => ['put', 'patch'], :destroy => ['delete'] }.each do |action, methods|
|
853
|
+
if actions.include?(action)
|
854
|
+
methods.each do |method|
|
855
|
+
send(method, "#{api_root}#{unversioned.tr('.', '/')}/:#{id_col}", { to: "#{controller_prefix}#{controller_name}##{action}" })
|
856
856
|
end
|
857
857
|
end
|
858
858
|
end
|
859
859
|
end
|
860
860
|
end
|
861
861
|
end
|
862
|
+
end
|
862
863
|
|
863
|
-
|
864
|
-
|
865
|
-
|
864
|
+
if ::Brick.config.add_status && instance_variable_get(:@set).named_routes.names.exclude?(:brick_status)
|
865
|
+
get("/#{controller_prefix}brick_status", to: 'brick_gem#status', as: 'brick_status')
|
866
|
+
end
|
866
867
|
|
867
|
-
|
868
|
-
|
869
|
-
|
868
|
+
if ::Brick.config.add_orphans && instance_variable_get(:@set).named_routes.names.exclude?(:brick_orphans)
|
869
|
+
get("/#{controller_prefix}brick_orphans", to: 'brick_gem#orphans', as: 'brick_orphans')
|
870
|
+
end
|
870
871
|
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
872
|
+
if instance_variable_get(:@set).named_routes.names.exclude?(:brick_crosstab)
|
873
|
+
get("/#{controller_prefix}brick_crosstab", to: 'brick_gem#crosstab', as: 'brick_crosstab')
|
874
|
+
get("/#{controller_prefix}brick_crosstab/data", to: 'brick_gem#crosstab_data')
|
875
|
+
end
|
875
876
|
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
else
|
890
|
-
puts "In order to make documentation available you can put this into your routes.rb:"
|
891
|
-
puts " mount Rswag::Ui::Engine => '/#{first_endpoint_parts&.find(&:present?) || 'api-docs'}'"
|
892
|
-
end
|
877
|
+
unless ::Brick.routes_done
|
878
|
+
if Object.const_defined?('Rswag::Ui')
|
879
|
+
rswag_path = routeset_to_use.routes.find { |r| r.app.app == Rswag::Ui::Engine }&.instance_variable_get(:@path_formatter)&.instance_variable_get(:@parts)&.join
|
880
|
+
first_endpoint_parts = nil
|
881
|
+
(doc_endpoints = Rswag::Ui.config.config_object[:urls])&.each do |doc_endpoint|
|
882
|
+
puts "Mounting OpenApi 3.0 documentation endpoint for \"#{doc_endpoint[:name]}\" on #{doc_endpoint[:url]}"
|
883
|
+
send(:get, doc_endpoint[:url], { to: 'brick_openapi#index' })
|
884
|
+
endpoint_parts = doc_endpoint[:url]&.split('/')
|
885
|
+
first_endpoint_parts ||= endpoint_parts
|
886
|
+
end
|
887
|
+
if doc_endpoints.present?
|
888
|
+
if rswag_path && first_endpoint_parts
|
889
|
+
puts "API documentation now available when navigating to: /#{first_endpoint_parts&.find(&:present?)}/index.html"
|
893
890
|
else
|
894
|
-
|
891
|
+
puts "In order to make documentation available you can put this into your routes.rb:"
|
892
|
+
puts " mount Rswag::Ui::Engine => '/#{first_endpoint_parts&.find(&:present?) || 'api-docs'}'"
|
893
|
+
end
|
894
|
+
else
|
895
|
+
sample_path = rswag_path || '/api-docs'
|
896
|
+
puts
|
897
|
+
puts "Brick: rswag-ui gem detected -- to make OpenAPI 3.0 documentation available from a path such as '#{sample_path}/v1/swagger.json',"
|
898
|
+
puts ' put code such as this in an initializer:'
|
899
|
+
puts ' Rswag::Ui.configure do |config|'
|
900
|
+
puts " config.swagger_endpoint '#{sample_path}/v1/swagger.json', 'API V1 Docs'"
|
901
|
+
puts ' end'
|
902
|
+
unless rswag_path
|
895
903
|
puts
|
896
|
-
puts
|
897
|
-
puts
|
898
|
-
puts ' Rswag::Ui.configure do |config|'
|
899
|
-
puts " config.swagger_endpoint '#{sample_path}/v1/swagger.json', 'API V1 Docs'"
|
900
|
-
puts ' end'
|
901
|
-
unless rswag_path
|
902
|
-
puts
|
903
|
-
puts ' and put this into your routes.rb:'
|
904
|
-
puts " mount Rswag::Ui::Engine => '/api-docs'"
|
905
|
-
end
|
904
|
+
puts ' and put this into your routes.rb:'
|
905
|
+
puts " mount Rswag::Ui::Engine => '/api-docs'"
|
906
906
|
end
|
907
907
|
end
|
908
|
+
end
|
908
909
|
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
end
|
910
|
+
::Brick.routes_done = true
|
911
|
+
puts "\n" if tables.present? || views.present?
|
912
|
+
if tables.present?
|
913
|
+
puts "Classes that can be built from tables:#{' ' * (table_class_length - 38)} Path:"
|
914
|
+
puts "======================================#{' ' * (table_class_length - 38)} ====="
|
915
|
+
::Brick.display_classes(controller_prefix, tables, table_class_length)
|
916
|
+
end
|
917
|
+
if views.present?
|
918
|
+
puts "Classes that can be built from views:#{' ' * (view_class_length - 37)} Path:"
|
919
|
+
puts "=====================================#{' ' * (view_class_length - 37)} ====="
|
920
|
+
::Brick.display_classes(controller_prefix, views, view_class_length)
|
921
921
|
end
|
922
922
|
end
|
923
923
|
end
|
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.113
|
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-02-
|
11
|
+
date: 2023-02-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|