brick 1.0.112 → 1.0.113

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 69051263cec00b3672b8d48b0c595ff6875b81f27e7995be72a03d6699ad6d02
4
- data.tar.gz: 217687ad2f6b93c33dc781f5930a0475a60fb27d782593109055beaae19f4e55
3
+ metadata.gz: f6cede45ed1fd983a2199fb279dffad0ecd02e51c7ed31cec6d46fccbc799e7c
4
+ data.tar.gz: 65eb5df73a7869b1bbe3ac128a69b4fda257e9dc098e77dc65c75d8f593756d7
5
5
  SHA512:
6
- metadata.gz: 6eff4c8a9f59673d14be1d890b067e17e631b1d6938a22b81c1ec45c3785489195d5d9e93939a38c681d36d844df2ad9a932584d8269b0fd2ef678de428c805c
7
- data.tar.gz: 723425258d449708f18e086f289147b3402f728c93fbcba3a16654c3d15b4fe715022e427cb3f87e731bf9b73d693a5d4f43a500bdbde3641b69ac61e4c35e35
6
+ metadata.gz: 0e506c2b4d00a1402e232f48c9eb95fc1edfb201a4b2d46ce8fd2a29d0f6a62e5d954ba84dfad4ccab2ff2c5c972d32478873e1f5c7ddf19bdfcca24894b0d1e
7
+ data.tar.gz: ee7dd85c423043b10efb60075716e3464db2645ac642fa43f457cf1b05c98a52cb7645e58e3a8208be8fd94b3a4b74f6b7d5e3102d890d087542a04b7e8cc7ec
@@ -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
- obj.send(:update, send(params_name_sym))
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
- params[:id]&.split(/[\/,_]/).map do |val_part|
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
- if (val = val.dup.strip).length > max_len
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
- relation = ::Brick.relations.fetch(rel_name || args.first.table_name, nil)
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}"
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 112
8
+ TINY = 113
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
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
- # %%% Was: ::Rails.application.routes.named_routes.route_defined?(:brick_status_path)
658
- unless ::Rails.application.routes.named_routes.names.include?(:brick_status)
659
- path_prefix = ::Brick.config.path_prefix
660
- existing_controllers = routes.each_with_object({}) do |r, s|
661
- c = r.defaults[:controller]
662
- s[c] = nil if c
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
- ::Rails.application.routes.append do
665
- tables = []
666
- views = []
667
- table_class_length = 38 # Length of "Classes that can be built from tables:"
668
- view_class_length = 37 # Length of "Classes that can be built from views:"
669
-
670
- brick_namespace_create = lambda do |path_names, res_name, options|
671
- if path_names&.present?
672
- if (path_name = path_names.pop).is_a?(Array)
673
- module_name = path_name[1]
674
- path_name = path_name.first
675
- end
676
- send(:scope, { module: module_name || path_name, path: path_name, as: path_name }) do
677
- brick_namespace_create.call(path_names, res_name, options)
678
- end
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
- send(:resources, res_name.to_sym, **options)
681
- end
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
- # %%% TODO: If no auto-controllers then enumerate the controllers folder in order to build matching routes
685
- # If auto-controllers and auto-models are both enabled then this makes sense:
686
- controller_prefix = (path_prefix ? "#{path_prefix}/" : '')
687
- sti_subclasses = ::Brick.config.sti_namespace_prefixes.each_with_object(Hash.new { |h, k| h[k] = [] }) do |v, s|
688
- # Turn something like {"::Spouse"=>"Person", "::Friend"=>"Person"} into {"Person"=>["Spouse", "Friend"]}
689
- s[v.last] << v.first[2..-1] unless v.first.end_with?('::')
690
- end
691
- versioned_views = {} # Track which views have already been done for each api_root
692
- ::Brick.relations.each do |k, v|
693
- if (schema_name = v.fetch(:schema, nil))
694
- schema_prefix = "#{schema_name}."
695
- end
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
- next if !(resource_name = v.fetch(:resource, nil)) ||
698
- existing_controllers.key?(controller_name = (
699
- resource_name = "#{schema_prefix&.tr('.', '/')}#{resource_name}"
700
- ).pluralize)
701
-
702
- object_name = k.split('.').last # Take off any first schema part
703
-
704
- full_schema_prefix = if (aps = v.fetch(:auto_prefixed_schema, nil))
705
- aps = aps[0..-2] if aps[-1] == '_'
706
- (schema_prefix&.dup || +'') << "#{aps}."
707
- else
708
- schema_prefix
709
- end
710
-
711
- # Track routes being built
712
- if (class_name = v.fetch(:class_name, nil))
713
- if v.key?(:isView)
714
- view_class_length = class_name.length if class_name.length > view_class_length
715
- views
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
- table_class_length = class_name.length if class_name.length > table_class_length
718
- tables
719
- end << [class_name, aps, resource_name]
720
- end
721
-
722
- options = {}
723
- options[:only] = [:index, :show] if v.key?(:isView)
724
-
725
- # First do the normal routes
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
- # Now the API routes if necessary
736
- full_resource = nil
737
- ::Brick.api_roots&.each do |api_root|
738
- api_done_views = (versioned_views[api_root] ||= {})
739
- found = nil
740
- test_ver_num = nil
741
- view_relation = nil
742
- # If it's a view then see if there's a versioned one available by searching for resource names
743
- # versioned with the closest number (equal to or less than) compared with our API version number.
744
- if v.key?(:isView)
745
- if (ver = object_name.match(/^v([\d_]*)/)&.captures&.first) && ver[-1] == '_'
746
- core_object_name = object_name[ver.length + 1..-1]
747
- next if api_done_views.key?(unversioned = "#{schema_prefix}v_#{core_object_name}")
748
-
749
- # Expect that the last item in the path generally holds versioning information
750
- api_ver = api_root.split('/')[-1]&.gsub('_', '.')
751
- vn_idx = api_ver.rindex(/[^\d._]/) # Position of the first numeric digit at the end of the version number
752
- # Was: .to_d
753
- 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
754
- # puts [api_ver, vn_idx, api_ver_num, unversioned].inspect
755
-
756
- next if ver.to_i > api_ver_num # Don't surface any newer views in an older API
757
-
758
- test_ver_num -= 1 until test_ver_num.zero? ||
759
- (view_relation = ::Brick.relations.fetch(
760
- found = "#{schema_prefix}v#{test_ver_num}_#{core_object_name}", nil
761
- ))
762
- api_done_views[unversioned] = nil # Mark that for this API version this view is done
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
- no_prefix_name = "#{schema_prefix}#{core_object_name}"
776
- unversioned = "#{schema_prefix}#{standard_prefix}#{::Brick.config.api_add_view_prefix}#{core_object_name}"
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
- unversioned = k
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
- view_relation ||= ::Brick.relations.fetch(found = unversioned, nil) ||
782
- (no_v_prefix_name && ::Brick.relations.fetch(found = no_v_prefix_name, nil)) ||
783
- (no_prefix_name && ::Brick.relations.fetch(found = no_prefix_name, nil))
784
- if view_relation
785
- actions = view_relation.key?(:isView) ? [:index, :show] : ::Brick::ALL_API_ACTIONS # By default all actions are allowed
786
- # Call proc that limits which endpoints get surfaced based on version, table or view name, method (get list / get one / post / patch / delete)
787
- # Returning nil makes it do nothing, false makes it skip creating this endpoint, and an array of up to
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
- if proc_result&.present?
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
- (view_relation[:api][api_ver_num] ||= {})[unversioned] = actions # Add to the list of API paths this resource responds to
833
-
834
- # view_ver_num = if (first_part = k.split('_').first) =~ /^v[\d_]+/
835
- # first_part[1..-1].gsub('_', '.').to_i
836
- # end
837
- controller_name = if (last = view_relation.fetch(:resource, nil)&.pluralize)
838
- "#{full_schema_prefix}#{last}"
839
- else
840
- found
841
- end.tr('.', '/')
842
-
843
- { :index => 'get', :create => 'post' }.each do |action, method|
844
- if actions.include?(action)
845
- # Normally goes to something like: /api/v1/employees
846
- send(method, "#{api_root}#{unversioned.tr('.', '/')}", { to: "#{controller_prefix}#{controller_name}##{action}" })
847
- end
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
- # %%% We do not yet surface the #show action
850
- if (id_col = view_relation[:pk]&.first) # ID-dependent stuff
851
- { :update => ['put', 'patch'], :destroy => ['delete'] }.each do |action, methods|
852
- if actions.include?(action)
853
- methods.each do |method|
854
- send(method, "#{api_root}#{unversioned.tr('.', '/')}/:#{id_col}", { to: "#{controller_prefix}#{controller_name}##{action}" })
855
- end
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
- if ::Brick.config.add_status && instance_variable_get(:@set).named_routes.names.exclude?(:brick_status)
864
- get("/#{controller_prefix}brick_status", to: 'brick_gem#status', as: 'brick_status')
865
- end
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
- if ::Brick.config.add_orphans && instance_variable_get(:@set).named_routes.names.exclude?(:brick_orphans)
868
- get("/#{controller_prefix}brick_orphans", to: 'brick_gem#orphans', as: 'brick_orphans')
869
- end
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
- if instance_variable_get(:@set).named_routes.names.exclude?(:brick_crosstab)
872
- get("/#{controller_prefix}brick_crosstab", to: 'brick_gem#crosstab', as: 'brick_crosstab')
873
- get("/#{controller_prefix}brick_crosstab/data", to: 'brick_gem#crosstab_data')
874
- end
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
- unless ::Brick.routes_done
877
- if Object.const_defined?('Rswag::Ui')
878
- rswag_path = ::Rails.application.routes.routes.find { |r| r.app.app == Rswag::Ui::Engine }&.instance_variable_get(:@path_formatter)&.instance_variable_get(:@parts)&.join
879
- first_endpoint_parts = nil
880
- (doc_endpoints = Rswag::Ui.config.config_object[:urls])&.each do |doc_endpoint|
881
- puts "Mounting OpenApi 3.0 documentation endpoint for \"#{doc_endpoint[:name]}\" on #{doc_endpoint[:url]}"
882
- send(:get, doc_endpoint[:url], { to: 'brick_openapi#index' })
883
- endpoint_parts = doc_endpoint[:url]&.split('/')
884
- first_endpoint_parts ||= endpoint_parts
885
- end
886
- if doc_endpoints.present?
887
- if rswag_path && first_endpoint_parts
888
- puts "API documentation now available when navigating to: /#{first_endpoint_parts&.find(&:present?)}/index.html"
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
- sample_path = rswag_path || '/api-docs'
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 "Brick: rswag-ui gem detected -- to make OpenAPI 3.0 documentation available from a path such as '#{sample_path}/v1/swagger.json',"
897
- puts ' put code such as this in an initializer:'
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
- ::Brick.routes_done = true
910
- puts "\n" if tables.present? || views.present?
911
- if tables.present?
912
- puts "Classes that can be built from tables:#{' ' * (table_class_length - 38)} Path:"
913
- puts "======================================#{' ' * (table_class_length - 38)} ====="
914
- ::Brick.display_classes(controller_prefix, tables, table_class_length)
915
- end
916
- if views.present?
917
- puts "Classes that can be built from views:#{' ' * (view_class_length - 37)} Path:"
918
- puts "=====================================#{' ' * (view_class_length - 37)} ====="
919
- ::Brick.display_classes(controller_prefix, views, view_class_length)
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.112
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-14 00:00:00.000000000 Z
11
+ date: 2023-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord