brick 1.0.97 → 1.0.99
Sign up to get free protection for your applications and to get access to all the features.
- 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
|