brick 1.0.97 → 1.0.99

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c257a0a65807fa87a13d722f3cc30c38d51bde571a070df53f4277fc6db8b7ba
4
- data.tar.gz: 74d7690a968fab671d9e9e8ac92e41885ceb44a700fd1cb293f3b79af819e463
3
+ metadata.gz: 431e2aee4c3c199095d8475eeedcc46bd95e86a47c51623e3cea7fbbde59edcd
4
+ data.tar.gz: 32144a9a9ab6ec60ef297f27ae73e35cc891e5f9462b9beae4e7a0534ab77135
5
5
  SHA512:
6
- metadata.gz: 4337faa80a6f0d9c1dadcb3271aea14ec54bb91e72cd7eead7e59c860557f828ac073cab3768feaa2db2f664d63b1604bd8f8e0d53c64621b1fcf5cc041057d9
7
- data.tar.gz: 541cade2070bd0a79b21dd7155df700b2739084ae81eaa02709f9e00164f956e62e8342330a78496c4b5fbf351cac9ea40483d3cdc32c1fb1dbe8d7e34499d2d
6
+ metadata.gz: f471bc993d97e92deae3c03e6cac9db0e350e72bd070afe5bcde1d0ca18d650b546db0d018a101009e429e9870a7e2c5e566f980c9e5b1319bc18873271c5550
7
+ data.tar.gz: 95f128f0f2a29cf0d1af1b5001eae27885b7e11ce23194e4a4da0141a0bfc059edd1917036f4addf1ee2aa4b69f763962e821ca31f9473048a6934dbecd8518e
@@ -398,15 +398,27 @@ module ActiveRecord
398
398
  # Links from ActiveRecord association pathing names over to real table correlation names
399
399
  # that get chosen when the AREL AST tree is walked.
400
400
  def brick_links
401
- @brick_links ||= {}
401
+ @brick_links ||= { '' => table_name }
402
402
  end
403
403
 
404
404
  def brick_select(params, selects = [], order_by = nil, translations = {}, join_array = ::Brick::JoinArray.new)
405
405
  is_add_bts = is_add_hms = true
406
406
 
407
- # Build out cust_cols, bt_descrip and hm_counts now so that they are available on the
408
- # model early in case the user wants to do an ORDER BY based on any of that.
409
- model._brick_calculate_bts_hms(translations, join_array) if is_add_bts || is_add_hms
407
+ if selects.empty?
408
+ # Build out cust_cols, bt_descrip and hm_counts now so that they are available on the
409
+ # model early in case the user wants to do an ORDER BY based on any of that.
410
+ model._brick_calculate_bts_hms(translations, join_array) if is_add_bts || is_add_hms
411
+ else
412
+ is_api = true
413
+ # If there are any provided selects, treat them as API columns and build them as cust_cols since they
414
+ # can be built using DSL.
415
+ # false = not polymorphic, and true = yes -- please emit_dsl
416
+ selects.each do |api_col|
417
+ pieces, my_dsl = brick_parse_dsl(join_array, [], translations, false, "[#{api_col}]", true)
418
+ _br_cust_cols[api_col.tr('.', '_')] = [pieces, my_dsl]
419
+ end
420
+ selects.clear # Now these have become custom columns
421
+ end
410
422
 
411
423
  is_postgres = ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
412
424
  is_mysql = ActiveRecord::Base.connection.adapter_name == 'Mysql2'
@@ -414,7 +426,7 @@ module ActiveRecord
414
426
  is_distinct = nil
415
427
  wheres = {}
416
428
  params.each do |k, v|
417
- next if ['_brick_schema', '_brick_order', 'controller', 'action'].include?(k)
429
+ next if ['_brick_schema', '_brick_order', '_brick_api', 'controller', 'action'].include?(k)
418
430
 
419
431
  if (where_col = (ks = k.split('.')).last)[-1] == '!'
420
432
  where_col = where_col[0..-2]
@@ -436,11 +448,14 @@ module ActiveRecord
436
448
 
437
449
  # %%% Skip the metadata columns
438
450
  if selects.empty? # Default to all columns
451
+ id_parts = (id_col = klass.primary_key).is_a?(Array) ? id_col : [id_col]
439
452
  tbl_no_schema = table.name.split('.').last
440
453
  # %%% Have once gotten this error with MSSQL referring to http://localhost:3000/warehouse/cold_room_temperatures__archive
441
454
  # ActiveRecord::StatementInvalid (TinyTds::Error: DBPROCESS is dead or not enabled)
442
455
  # Relevant info here: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues/402
443
456
  columns.each do |col|
457
+ next if is_api && id_parts.exclude?(col.name) # Only keep the ID columns if this is an API request
458
+
444
459
  col_alias = " AS #{col.name}_" if (col_name = col.name) == 'class'
445
460
  selects << if is_mysql
446
461
  "`#{tbl_no_schema}`.`#{col_name}`#{col_alias}"
@@ -490,22 +505,28 @@ module ActiveRecord
490
505
  # binding.pry
491
506
  next
492
507
  end
493
-
494
508
  key_klass = nil
495
509
  key_tbl_name = nil
496
510
  dest_pk = nil
497
511
  key_alias = nil
498
512
  cc.first.each do |cc_part|
499
- dest_klass = cc_part[0..-2].inject(klass) { |kl, cc_part_term| kl.reflect_on_association(cc_part_term).klass }
513
+ dest_klass = cc_part[0..-2].inject(klass) do |kl, cc_part_term|
514
+ # %%% Clear column info properly so we can do multiple subsequent requests
515
+ # binding.pry unless kl.reflect_on_association(cc_part_term)
516
+ kl.reflect_on_association(cc_part_term)&.klass || klass
517
+ end
500
518
  tbl_name = rel_dupe.brick_links[cc_part[0..-2].map(&:to_s).join('.')]
501
519
  # Deal with the conflict if there are two parts in the custom column named the same,
502
520
  # "category.name" and "product.name" for instance will end up with aliases of "name"
503
521
  # and "product__name".
504
- cc_part_idx = cc_part.length - 1
505
- while cc_part_idx > 0 &&
506
- (col_alias = "br_cc_#{k}__#{cc_part[cc_part_idx..-1].map(&:to_s).join('__')}") &&
507
- used_col_aliases.key?(col_alias)
508
- cc_part_idx -= 1
522
+ if (cc_part_idx = cc_part.length - 1).zero?
523
+ col_alias = "br_cc_#{k}__#{table_name.tr('.', '_')}"
524
+ else
525
+ while cc_part_idx > 0 &&
526
+ (col_alias = "br_cc_#{k}__#{cc_part[cc_part_idx..-1].map(&:to_s).join('__').tr('.', '_')}") &&
527
+ used_col_aliases.key?(col_alias)
528
+ cc_part_idx -= 1
529
+ end
509
530
  end
510
531
  used_col_aliases[col_alias] = nil
511
532
  # Set up custom column links by preparing key_klass and key_alias
@@ -540,7 +561,11 @@ module ActiveRecord
540
561
  tbl_name = "\"#{tbl_name}\"" if ::Brick.is_oracle && rel_dupe.brick_links.values.include?(tbl_name)
541
562
  field_tbl_name = nil
542
563
  v1.map { |x| [x[0..-2].map(&:to_s).join('.'), x.last] }.each_with_index do |sel_col, idx|
543
- field_tbl_name = rel_dupe.brick_links[sel_col.first].split('.').last
564
+ # %%% Strangely in Rails 7.1 on a slower system then very rarely brick_link comes back nil...
565
+ brick_link = rel_dupe.brick_links[sel_col.first]
566
+ field_tbl_name = brick_link&.split('.')&.last ||
567
+ # ... so here's a best-effort guess for what the table name might be.
568
+ rel_dupe.klass.reflect_on_association(sel_col.first).klass.table_name
544
569
  # If it's Oracle, quote any AREL aliases that had been applied
545
570
  field_tbl_name = "\"#{field_tbl_name}\"" if ::Brick.is_oracle && rel_dupe.brick_links.values.include?(field_tbl_name)
546
571
 
@@ -825,80 +850,9 @@ JOIN (SELECT #{hm_selects.map { |s| "#{'br_t0.' if from_clause}#{s}" }.join(', '
825
850
  end
826
851
 
827
852
  if Object.const_defined?('ActionView')
853
+ require 'brick/frameworks/rails/form_tags'
828
854
  module ActionView::Helpers::FormTagHelper
829
- def link_to_brick(*args, **kwargs)
830
- return unless ::Brick.config.mode == :on
831
-
832
- text = (args.first.is_a?(String) && args.first) || args[1]
833
- klass_or_obj = ((args.first.is_a?(ActiveRecord::Relation) ||
834
- args.first.is_a?(ActiveRecord::Base) ||
835
- args.first.is_a?(Class)) &&
836
- args.first) ||
837
- @_brick_model
838
- # If not provided, do a best-effort to automatically determine the resource class or object
839
- filter_parts = []
840
- klass_or_obj ||= begin
841
- klass, sti_type = ::Brick.ctrl_to_klass(controller_path)
842
- if klass
843
- type_col = klass.inheritance_column # Usually 'type'
844
- filter_parts << "#{type_col}=#{sti_type}" if sti_type && klass.column_names.include?(type_col)
845
- path_params = request.path_parameters.dup
846
- path_params.delete(:controller)
847
- path_params.delete(:action)
848
- pk = (klass.primary_key || ActiveRecord::Base.primary_key).to_sym
849
- # Used to also have this but it's a bit too permissive to identify a primary key: (path_params.length == 1 && path_params.values.first) ||
850
- if ((id = (path_params[pk] || path_params[:id] || path_params["#{klass.name.underscore}_id".to_sym])) && (obj = klass.find_by(pk => id))) ||
851
- (['show', 'edit', 'update', 'destroy'].include?(action_name) && (obj = klass.first))
852
- obj
853
- else
854
- # %%% If there is a HMT that refers to some ___id then try to identify an appropriate filter
855
- # %%% If there is a polymorphic association that might relate to stuff in the path_params,
856
- # try to identify an appropriate ___able_id and ___able_type filter
857
- ((klass.column_names - [pk.to_s]) & path_params.keys.map(&:to_s)).each do |path_param|
858
- filter_parts << "#{path_param}=#{path_params[path_param.to_sym]}"
859
- end
860
- klass
861
- end
862
- end
863
- rescue
864
- end
865
- if klass_or_obj
866
- if klass_or_obj.is_a?(ActiveRecord::Relation)
867
- klass_or_obj.where_values_hash.each do |whr|
868
- filter_parts << "#{whr.first}=#{whr.last}" if whr.last && !whr.last.is_a?(Array)
869
- end
870
- klass_or_obj = klass_or_obj.klass
871
- type_col = klass_or_obj.inheritance_column
872
- if klass_or_obj.column_names.include?(type_col) && klass_or_obj.name != klass_or_obj.base_class.name
873
- filter_parts << "#{type_col}=#{klass_or_obj.name}"
874
- end
875
- elsif klass_or_obj.is_a?(ActiveRecord::Base) && klass_or_obj.new_record?
876
- klass_or_obj = klass_or_obj.class
877
- end
878
- filter = "?#{filter_parts.join('&')}" if filter_parts.present?
879
- if (klass_or_obj&.is_a?(Class) && klass_or_obj < ActiveRecord::Base) ||
880
- (klass_or_obj&.is_a?(ActiveRecord::Base) && klass_or_obj.new_record? && (klass_or_obj = klass_or_obj.class))
881
- lt_args = [text || "Index for #{klass_or_obj.name.pluralize}",
882
- "#{send("#{klass_or_obj._brick_index}_path")}#{filter}"]
883
- else
884
- # If there are multiple incoming parameters then last one is probably the actual ID, and first few might be some nested tree of stuff leading up to it
885
- lt_args = [text || "Show this #{klass_or_obj.class.name}",
886
- "#{send("#{klass_or_obj.class._brick_index(:singular)}_path", klass_or_obj)}#{filter}"]
887
- end
888
- link_to(*lt_args, **kwargs)
889
- else
890
- # puts "Warning: link_to_brick could not find a class for \"#{controller_path}\" -- consider setting @_brick_model within that controller."
891
- # if (hits = res_names.keys & instance_variables.map { |v| v.to_s[1..-1] }).present?
892
- links = instance_variables.each_with_object([]) do |name, s|
893
- iv_name = name.to_s[1..-1]
894
- case (val = instance_variable_get(name))
895
- when ActiveRecord::Relation, ActiveRecord::Base
896
- s << link_to_brick(val, iv_name) if val
897
- end
898
- end
899
- links.join(' &nbsp; ').html_safe
900
- end
901
- end
855
+ include ::Brick::Rails::FormTags
902
856
  end
903
857
  end
904
858
 
@@ -1002,6 +956,7 @@ Module.class_exec do
1002
956
  end
1003
957
  class_name = ::Brick.namify(requested)
1004
958
  relations = ::Brick.relations
959
+ # CONTROLLER
1005
960
  result = if ::Brick.enable_controllers? &&
1006
961
  is_controller && (plural_class_name = class_name[0..-11]).length.positive?
1007
962
  # Otherwise now it's up to us to fill in the gaps
@@ -1020,6 +975,8 @@ Module.class_exec do
1020
975
  # if it's a controller and no match or a model doesn't really use the same table name, eager load all models and try to find a model class of the right name.
1021
976
  Object.send(:build_controller, self, class_name, plural_class_name, model, relations)
1022
977
  end
978
+
979
+ # MODULE
1023
980
  elsif (::Brick.enable_models? || ::Brick.enable_controllers?) && # Schema match?
1024
981
  base_module == Object && # %%% This works for Person::Person -- but also limits us to not being able to allow more than one level of namespacing
1025
982
  (schema_name = [(singular_table_name = class_name.underscore),
@@ -1036,6 +993,50 @@ Module.class_exec do
1036
993
 
1037
994
  [built_module, "module #{schema_name}; end\n"]
1038
995
  # # %%% Perhaps an option to use the first module just as schema, and additional modules as namespace with a table name prefix applied
996
+
997
+ # AVO Resource
998
+ elsif base_module == Object && Object.const_defined?('Avo') && requested.end_with?('Resource') &&
999
+ ['MotorResource'].exclude?(requested) # Expect that anything called MotorResource could be from that administrative gem
1000
+ if (model = Object.const_get(requested[0..-9]))
1001
+ require 'generators/avo/resource_generator'
1002
+ field_generator = Generators::Avo::ResourceGenerator.new([''])
1003
+ field_generator.instance_variable_set(:@model, model)
1004
+ fields = field_generator.send(:generate_fields).split("\n")
1005
+ .each_with_object([]) do |f, s|
1006
+ if (f = f.strip).start_with?('field ')
1007
+ f = f[6..-1].split(',')
1008
+ s << [f.first[1..-1].to_sym, [f[1][1..-1].split(': :').map(&:to_sym)].to_h]
1009
+ end
1010
+ end
1011
+ built_resource = Class.new(Avo::BaseResource) do |new_resource_class|
1012
+ self.model_class = model
1013
+ self.title = :brick_descrip
1014
+ self.includes = []
1015
+ if (!model.is_view? && mod_pk = model.primary_key)
1016
+ field((mod_pk.is_a?(Array) ? mod_pk.first : mod_pk).to_sym, { as: :id })
1017
+ end
1018
+ # Create a call such as: field :name, as: :text
1019
+ fields.each do |f|
1020
+ # Add proper types if this is a polymorphic belongs_to
1021
+ if f.last == { as: :belongs_to } &&
1022
+ (fk = ::Brick.relations[model.table_name][:fks].find { |k, v| v[:assoc_name] == f.first.to_s }) &&
1023
+ fk.last.fetch(:polymorphic, nil)
1024
+ poly_types = fk.last.fetch(:inverse_table, nil)&.each_with_object([]) do |poly_table, s|
1025
+ s << Object.const_get(::Brick.relations[poly_table][:class_name])
1026
+ end
1027
+ if poly_types.present?
1028
+ f.last[:polymorphic_as] = f.first
1029
+ f.last[:types] = poly_types
1030
+ end
1031
+ end
1032
+ self.send(:field, *f)
1033
+ end
1034
+ end
1035
+ Object.const_set(requested.to_sym, built_resource)
1036
+ [built_resource, nil]
1037
+ end
1038
+
1039
+ # MODEL
1039
1040
  elsif ::Brick.enable_models?
1040
1041
  # Custom inheritable Brick base model?
1041
1042
  class_name = (inheritable_name = class_name)[5..-1] if class_name.start_with?('Brick')
@@ -1392,19 +1393,24 @@ class Object
1392
1393
  when Symbol
1393
1394
  order_tbl[order_default] || order_default
1394
1395
  else
1395
- pk.map(&:to_sym) # If it's not a custom ORDER BY, just use the key
1396
+ pk.map { |part| "#{table_name}.#{part}"}.join(', ') # If it's not a custom ORDER BY, just use the key
1396
1397
  end
1397
1398
  end
1398
1399
 
1399
1400
  def build_controller(namespace, class_name, plural_class_name, model, relations)
1401
+ if (is_avo = (namespace.name == 'Avo' && Object.const_defined?('Avo')))
1402
+ # Basic Avo functionality is available via its own generic controller.
1403
+ # (More information on https://docs.avohq.io/2.0/controllers.html)
1404
+ controller_base = Avo::ResourcesController
1405
+ end
1400
1406
  table_name = ActiveSupport::Inflector.underscore(plural_class_name)
1401
1407
  singular_table_name = ActiveSupport::Inflector.singularize(table_name)
1402
1408
  pk = model&._brick_primary_key(relations.fetch(table_name, nil))
1403
1409
  is_postgres = ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
1404
1410
  is_mysql = ActiveRecord::Base.connection.adapter_name == 'Mysql2'
1405
1411
 
1406
- code = +"class #{class_name} < ApplicationController\n"
1407
- built_controller = Class.new(ActionController::Base) do |new_controller_class|
1412
+ code = +"class #{class_name} < #{controller_base&.name || 'ApplicationController'}\n"
1413
+ built_controller = Class.new(controller_base || ActionController::Base) do |new_controller_class|
1408
1414
  (namespace || Object).const_set(class_name.to_sym, new_controller_class)
1409
1415
 
1410
1416
  # Brick-specific pages
@@ -1501,118 +1507,129 @@ class Object
1501
1507
  end
1502
1508
 
1503
1509
  self.protect_from_forgery unless: -> { self.request.format.js? }
1504
- self.define_method :index do
1505
- if (is_openapi || request.env['REQUEST_PATH'].start_with?(::Brick.api_root)) &&
1506
- !params&.key?('_brick_schema') &&
1507
- (referrer_params = request.env['HTTP_REFERER']&.split('?')&.last&.split('&')&.map { |x| x.split('=') }).present?
1508
- if params
1509
- referrer_params.each { |k, v| params.send(:parameters)[k] = v }
1510
- else
1511
- api_params = referrer_params&.to_h
1510
+ unless is_avo
1511
+ self.define_method :index do
1512
+ if (is_openapi || request.env['REQUEST_PATH'].start_with?(::Brick.api_root)) &&
1513
+ !params&.key?('_brick_schema') &&
1514
+ (referrer_params = request.env['HTTP_REFERER']&.split('?')&.last&.split('&')&.map { |x| x.split('=') }).present?
1515
+ if params
1516
+ referrer_params.each { |k, v| params.send(:parameters)[k] = v }
1517
+ else
1518
+ api_params = referrer_params&.to_h
1519
+ end
1512
1520
  end
1513
- end
1514
- _schema, @_is_show_schema_list = ::Brick.set_db_schema(params || api_params)
1515
-
1516
- if is_openapi
1517
- json = { 'openapi': '3.0.1', 'info': { 'title': Rswag::Ui.config.config_object[:urls].last&.fetch(:name, 'API documentation'), 'version': ::Brick.config.api_version },
1518
- 'servers': [
1519
- { 'url': '{scheme}://{defaultHost}', 'variables': {
1520
- 'scheme': { 'default': request.env['rack.url_scheme'] },
1521
- 'defaultHost': { 'default': request.env['HTTP_HOST'] }
1522
- } }
1523
- ]
1524
- }
1525
- json['paths'] = relations.inject({}) do |s, relation|
1526
- unless ::Brick.config.enable_api == false
1527
- table_description = relation.last[:description]
1528
- s["#{::Brick.config.api_root}#{relation.first.tr('.', '/')}"] = {
1529
- 'get': {
1530
- 'summary': "list #{relation.first}",
1531
- 'description': table_description,
1532
- 'parameters': relation.last[:cols].map do |k, v|
1533
- param = { 'name' => k, 'schema': { 'type': v.first } }
1534
- if (col_descrip = relation.last.fetch(:col_descrips, nil)&.fetch(k, nil))
1535
- param['description'] = col_descrip
1536
- end
1537
- param
1538
- end,
1539
- 'responses': { '200': { 'description': 'successful' } }
1540
- }
1541
- }
1542
-
1543
- s["#{::Brick.config.api_root}#{relation.first.tr('.', '/')}/{id}"] = {
1544
- 'patch': {
1545
- 'summary': "update a #{relation.first.singularize}",
1546
- 'description': table_description,
1547
- 'parameters': relation.last[:cols].reject { |k, v| Brick.config.metadata_columns.include?(k) }.map do |k, v|
1548
- param = { 'name' => k, 'schema': { 'type': v.first } }
1549
- if (col_descrip = relation.last.fetch(:col_descrips, nil)&.fetch(k, nil))
1550
- param['description'] = col_descrip
1551
- end
1552
- param
1553
- end,
1554
- 'responses': { '200': { 'description': 'successful' } }
1521
+ _schema, @_is_show_schema_list = ::Brick.set_db_schema(params || api_params)
1522
+
1523
+ if is_openapi
1524
+ json = { 'openapi': '3.0.1', 'info': { 'title': Rswag::Ui.config.config_object[:urls].last&.fetch(:name, 'API documentation'), 'version': ::Brick.config.api_version },
1525
+ 'servers': [
1526
+ { 'url': '{scheme}://{defaultHost}', 'variables': {
1527
+ 'scheme': { 'default': request.env['rack.url_scheme'] },
1528
+ 'defaultHost': { 'default': request.env['HTTP_HOST'] }
1529
+ } }
1530
+ ]
1531
+ }
1532
+ json['paths'] = relations.inject({}) do |s, relation|
1533
+ unless ::Brick.config.enable_api == false
1534
+ table_description = relation.last[:description]
1535
+ s["#{::Brick.config.api_root}#{relation.first.tr('.', '/')}"] = {
1536
+ 'get': {
1537
+ 'summary': "list #{relation.first}",
1538
+ 'description': table_description,
1539
+ 'parameters': relation.last[:cols].map do |k, v|
1540
+ param = { 'name' => k, 'schema': { 'type': v.first } }
1541
+ if (col_descrip = relation.last.fetch(:col_descrips, nil)&.fetch(k, nil))
1542
+ param['description'] = col_descrip
1543
+ end
1544
+ param
1545
+ end,
1546
+ 'responses': { '200': { 'description': 'successful' } }
1547
+ }
1555
1548
  }
1556
- } unless relation.last.fetch(:isView, nil)
1557
- s
1549
+
1550
+ s["#{::Brick.config.api_root}#{relation.first.tr('.', '/')}/{id}"] = {
1551
+ 'patch': {
1552
+ 'summary': "update a #{relation.first.singularize}",
1553
+ 'description': table_description,
1554
+ 'parameters': relation.last[:cols].reject { |k, v| Brick.config.metadata_columns.include?(k) }.map do |k, v|
1555
+ param = { 'name' => k, 'schema': { 'type': v.first } }
1556
+ if (col_descrip = relation.last.fetch(:col_descrips, nil)&.fetch(k, nil))
1557
+ param['description'] = col_descrip
1558
+ end
1559
+ param
1560
+ end,
1561
+ 'responses': { '200': { 'description': 'successful' } }
1562
+ }
1563
+ } unless relation.last.fetch(:isView, nil)
1564
+ s
1565
+ end
1558
1566
  end
1567
+ render inline: json.to_json, content_type: request.format
1568
+ return
1559
1569
  end
1560
- render inline: json.to_json, content_type: request.format
1561
- return
1562
- end
1563
1570
 
1564
- if request.format == :csv # Asking for a template?
1565
- require 'csv'
1566
- exported_csv = CSV.generate(force_quotes: false) do |csv_out|
1567
- model.df_export(model.brick_import_template).each { |row| csv_out << row }
1571
+ if request.format == :csv # Asking for a template?
1572
+ require 'csv'
1573
+ exported_csv = CSV.generate(force_quotes: false) do |csv_out|
1574
+ model.df_export(model.brick_import_template).each { |row| csv_out << row }
1575
+ end
1576
+ render inline: exported_csv, content_type: request.format
1577
+ return
1578
+ elsif request.format == :js || request.path.start_with?('/api/') # Asking for JSON?
1579
+ data = (model.is_view? || !Object.const_defined?('DutyFree')) ? model.limit(1000) : model.df_export(model.brick_import_template)
1580
+ render inline: data.to_json, content_type: request.format == '*/*' ? 'application/json' : request.format
1581
+ return
1568
1582
  end
1569
- render inline: exported_csv, content_type: request.format
1570
- return
1571
- elsif request.format == :js || request.path.start_with?('/api/') # Asking for JSON?
1572
- data = (model.is_view? || !Object.const_defined?('DutyFree')) ? model.limit(1000) : model.df_export(model.brick_import_template)
1573
- render inline: data.to_json, content_type: request.format == '*/*' ? 'application/json' : request.format
1574
- return
1575
- end
1576
1583
 
1577
- # Normal (not swagger or CSV) request
1578
-
1579
- # %%% Allow params to define which columns to use for order_by
1580
- # Overriding the default by providing a querystring param?
1581
- ordering = params['_brick_order']&.split(',')&.map(&:to_sym) || Object.send(:default_ordering, table_name, pk)
1582
- order_by, _ = model._brick_calculate_ordering(ordering, true) # Don't do the txt part
1583
-
1584
- ar_relation = ActiveRecord.version < Gem::Version.new('4') ? model.preload : model.all
1585
- @_brick_params = ar_relation.brick_select(params, (selects = []), order_by,
1586
- translations = {},
1587
- join_array = ::Brick::JoinArray.new)
1588
- # %%% Add custom HM count columns
1589
- # %%% What happens when the PK is composite?
1590
- counts = model._br_hm_counts.each_with_object([]) do |v, s|
1591
- s << if is_mysql
1592
- "`b_r_#{v.first}`.c_t_ AS \"b_r_#{v.first}_ct\""
1593
- elsif is_postgres
1594
- "\"b_r_#{v.first}\".c_t_ AS \"b_r_#{v.first}_ct\""
1595
- else
1596
- "b_r_#{v.first}.c_t_ AS \"b_r_#{v.first}_ct\""
1597
- end
1598
- end
1599
- ar_select = ar_relation.respond_to?(:_select!) ? ar_relation.dup._select!(*selects, *counts) : ar_relation.select(selects + counts)
1600
- instance_variable_set("@#{table_name.pluralize}".to_sym, ar_select)
1601
- if namespace && (idx = lookup_context.prefixes.index(table_name))
1602
- lookup_context.prefixes[idx] = "#{namespace.name.underscore}/#{lookup_context.prefixes[idx]}"
1603
- end
1604
- @_brick_excl = session[:_brick_exclude]&.split(',')&.each_with_object([]) do |excl, s|
1605
- if (excl_parts = excl.split('.')).first == table_name
1606
- s << excl_parts.last
1584
+ # Normal (not swagger or CSV) request
1585
+
1586
+ # %%% Allow params to define which columns to use for order_by
1587
+ # Overriding the default by providing a querystring param?
1588
+ ordering = params['_brick_order']&.split(',')&.map(&:to_sym) || Object.send(:default_ordering, table_name, pk)
1589
+ order_by, _ = model._brick_calculate_ordering(ordering, true) # Don't do the txt part
1590
+
1591
+ ar_relation = ActiveRecord.version < Gem::Version.new('4') ? model.preload : model.all
1592
+
1593
+ if (cc = params['_brick_api']&.split(','))
1594
+ is_api = true
1595
+ selects = cc
1596
+ counts = [] # No need for any extra HM count columns
1597
+ model._br_cust_cols.clear
1598
+ end
1599
+
1600
+ @_brick_params = ar_relation.brick_select(params, (selects ||= []), order_by,
1601
+ translations = {},
1602
+ join_array = ::Brick::JoinArray.new)
1603
+ # %%% Add custom HM count columns
1604
+ # %%% What happens when the PK is composite?
1605
+ counts = model._br_hm_counts.each_with_object([]) do |v, s|
1606
+ s << if is_mysql
1607
+ "`b_r_#{v.first}`.c_t_ AS \"b_r_#{v.first}_ct\""
1608
+ elsif is_postgres
1609
+ "\"b_r_#{v.first}\".c_t_ AS \"b_r_#{v.first}_ct\""
1610
+ else
1611
+ "b_r_#{v.first}.c_t_ AS \"b_r_#{v.first}_ct\""
1612
+ end
1613
+ end
1614
+
1615
+ ar_select = ar_relation.respond_to?(:_select!) ? ar_relation.dup._select!(*selects, *counts) : ar_relation.select(selects + counts)
1616
+ instance_variable_set("@#{table_name.pluralize}".to_sym, ar_select)
1617
+ if namespace && (idx = lookup_context.prefixes.index(table_name))
1618
+ lookup_context.prefixes[idx] = "#{namespace.name.underscore}/#{lookup_context.prefixes[idx]}"
1619
+ end
1620
+ @_brick_excl = session[:_brick_exclude]&.split(',')&.each_with_object([]) do |excl, s|
1621
+ if (excl_parts = excl.split('.')).first == table_name
1622
+ s << excl_parts.last
1623
+ end
1607
1624
  end
1608
- end
1609
- @_brick_bt_descrip = model._br_bt_descrip
1610
- @_brick_hm_counts = model._br_hm_counts
1611
- @_brick_join_array = join_array
1612
- @_brick_erd = params['_brick_erd']&.to_i
1625
+ @_brick_bt_descrip = model._br_bt_descrip
1626
+ @_brick_hm_counts = model._br_hm_counts
1627
+ @_brick_join_array = join_array
1628
+ @_brick_erd = params['_brick_erd']&.to_i
1629
+ end
1613
1630
  end
1614
1631
 
1615
- unless is_openapi
1632
+ unless is_openapi || is_avo
1616
1633
  _, order_by_txt = model._brick_calculate_ordering(default_ordering(table_name, pk)) if pk
1617
1634
  code << " def index\n"
1618
1635
  code << " @#{table_name.pluralize} = #{model.name}#{pk&.present? ? ".order(#{order_by_txt.join(', ')})" : '.all'}\n"
@@ -3,7 +3,7 @@
3
3
  module Brick
4
4
  module Rails
5
5
  # Extensions to rails controllers. Provides convenient ways to pass certain
6
- # information to the model layer, with `controller_info` and `whodunnit`.
6
+ # information to the model layer, with `controller_info`.
7
7
  # Also includes a convenient on/off switch,
8
8
  # `brick_enabled_for_controller`.
9
9
  module Controller