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 +4 -4
- data/lib/brick/extensions.rb +208 -191
- data/lib/brick/frameworks/rails/controller.rb +1 -1
- data/lib/brick/frameworks/rails/engine.rb +285 -197
- data/lib/brick/frameworks/rails/form_tags.rb +264 -0
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +7 -6
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 431e2aee4c3c199095d8475eeedcc46bd95e86a47c51623e3cea7fbbde59edcd
|
4
|
+
data.tar.gz: 32144a9a9ab6ec60ef297f27ae73e35cc891e5f9462b9beae4e7a0534ab77135
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f471bc993d97e92deae3c03e6cac9db0e350e72bd070afe5bcde1d0ca18d650b546db0d018a101009e429e9870a7e2c5e566f980c9e5b1319bc18873271c5550
|
7
|
+
data.tar.gz: 95f128f0f2a29cf0d1af1b5001eae27885b7e11ce23194e4a4da0141a0bfc059edd1917036f4addf1ee2aa4b69f763962e821ca31f9473048a6934dbecd8518e
|
data/lib/brick/extensions.rb
CHANGED
@@ -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
|
-
|
408
|
-
|
409
|
-
|
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)
|
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
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
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
|
-
|
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
|
-
|
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(' ').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(
|
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
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
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
|
-
|
1514
|
-
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
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
|
-
|
1557
|
-
|
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
|
-
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
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
|
-
|
1578
|
-
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1587
|
-
|
1588
|
-
|
1589
|
-
|
1590
|
-
|
1591
|
-
|
1592
|
-
|
1593
|
-
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1597
|
-
|
1598
|
-
|
1599
|
-
|
1600
|
-
|
1601
|
-
|
1602
|
-
|
1603
|
-
|
1604
|
-
|
1605
|
-
|
1606
|
-
|
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
|
-
|
1609
|
-
|
1610
|
-
|
1611
|
-
|
1612
|
-
|
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
|
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
|