brick 1.0.235 → 1.0.236
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 +38 -33
- data/lib/brick/rails/engine.rb +3 -3
- data/lib/brick/reflect_tables.rb +12 -5
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +1 -1
- data/lib/generators/brick/seeds_builder.rb +16 -19
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8397091edab4be1edd1e61eb4be3284a8c169a3207f87e92227b84d07413d241
|
4
|
+
data.tar.gz: 2ffaef636cfba92e38bf9330f04a5bd65f39eb06d62e002e5227f7261b126494
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 38d24e9e8ae60a63f6755bb5e0854880df019ce4004d3e8962c8a47cfc80bb23fcba576216e9cedf7560f37b458ce47e651ccaa206b0e92844519e2a932d7c7e
|
7
|
+
data.tar.gz: 4f33bd865494dcd1855204bd5c307f8b2fc70485bd8ce5c9fd79708df638ff0f715d44755087a0c8230589dd3679d238dfdaeea8807dc14cf4a658fae21ffa7d
|
data/lib/brick/extensions.rb
CHANGED
@@ -70,7 +70,8 @@ module ActiveRecord
|
|
70
70
|
false
|
71
71
|
end
|
72
72
|
|
73
|
-
|
73
|
+
# Accommodate STI
|
74
|
+
def find_real_model(params)
|
74
75
|
if params && ((sub_name = params.fetch(inheritance_column, nil)).present? ||
|
75
76
|
(sub_name = params[name.underscore]&.fetch(inheritance_column, nil)))
|
76
77
|
sub_name = sub_name.first if sub_name.is_a?(Array) # Support the params style that gets returned from #_brick_querying
|
@@ -83,10 +84,9 @@ module ActiveRecord
|
|
83
84
|
end
|
84
85
|
end
|
85
86
|
|
86
|
-
# Accommodate STI
|
87
87
|
def real_singular(params)
|
88
|
-
real_model =
|
89
|
-
[real_model, real_model.name.underscore.
|
88
|
+
real_model = find_real_model(params)
|
89
|
+
[real_model, real_model.name.underscore.tr('/', '_')]
|
90
90
|
end
|
91
91
|
|
92
92
|
def json_column?(col)
|
@@ -961,8 +961,12 @@ module ActiveRecord
|
|
961
961
|
fk_col = (inv = hm.inverse_of)&.foreign_key || hm.foreign_key
|
962
962
|
# %%% Might only need hm.type and not the first part :)
|
963
963
|
poly_type = inv&.foreign_type || hm.type if hm.options.key?(:as)
|
964
|
-
|
965
|
-
|
964
|
+
if hm.macro == :has_and_belongs_to_many
|
965
|
+
'*'
|
966
|
+
else
|
967
|
+
pk = hm.klass.primary_key
|
968
|
+
(pk.is_a?(Array) ? pk.first : pk) || '*'
|
969
|
+
end
|
966
970
|
end
|
967
971
|
next unless count_column # %%% Would be able to remove this when multiple foreign keys to same destination becomes bulletproof
|
968
972
|
|
@@ -1830,7 +1834,7 @@ class Object
|
|
1830
1834
|
def import(options={}, &block)
|
1831
1835
|
unless self.__elasticsearch__.index_exists?
|
1832
1836
|
self.__elasticsearch__.create_index!
|
1833
|
-
::Brick.elasticsearch_existings[self.table_name
|
1837
|
+
::Brick.elasticsearch_existings[self.table_name.tr('.', '-').pluralize] = self.table_name
|
1834
1838
|
end
|
1835
1839
|
_original_import(options={}, &block)
|
1836
1840
|
end
|
@@ -1867,7 +1871,7 @@ class Object
|
|
1867
1871
|
end
|
1868
1872
|
rescue Elastic::Transport::Transport::Errors::NotFound => e
|
1869
1873
|
self.__elasticsearch__.create_index! if @_brick_es_crud.index('i')
|
1870
|
-
::Brick.elasticsearch_existings[self.table_name
|
1874
|
+
::Brick.elasticsearch_existings[self.table_name.tr('.', '-').pluralize] = self.table_name
|
1871
1875
|
[]
|
1872
1876
|
end
|
1873
1877
|
end
|
@@ -2040,12 +2044,12 @@ class Object
|
|
2040
2044
|
(anaf.is_a?(Array) ? anaf.include?(assoc_name) : anaf == assoc_name)
|
2041
2045
|
macro
|
2042
2046
|
end
|
2043
|
-
# Figure out if we need to specially call out the class_name and/or foreign key
|
2044
|
-
# (and if either of those then definitely also a specific inverse_of)
|
2045
2047
|
if (singular_table_parts = singular_table_name.split('.')).length > 1 &&
|
2046
2048
|
::Brick.config.schema_behavior[:multitenant] && singular_table_parts.first == 'public'
|
2047
2049
|
singular_table_parts.shift
|
2048
2050
|
end
|
2051
|
+
# Figure out if we need to specially call out the class_name and/or foreign key
|
2052
|
+
# (and if either of those then definitely also a specific inverse_of)
|
2049
2053
|
if need_class_name
|
2050
2054
|
options[:class_name] = "::#{assoc[:primary_class]&.name || ::Brick.relations[inverse_table][:class_name]}"
|
2051
2055
|
end
|
@@ -2441,7 +2445,7 @@ class Object
|
|
2441
2445
|
return
|
2442
2446
|
end
|
2443
2447
|
|
2444
|
-
real_model = model.
|
2448
|
+
real_model = model.find_real_model(params)
|
2445
2449
|
|
2446
2450
|
if request.format == :csv # Asking for a template?
|
2447
2451
|
require 'csv'
|
@@ -2520,9 +2524,10 @@ class Object
|
|
2520
2524
|
end
|
2521
2525
|
end
|
2522
2526
|
ar_select = ar_relation.respond_to?(:_select!) ? ar_relation.dup._select!(*selects, *counts) : ar_relation.select(selects + counts)
|
2527
|
+
# %%% should this be real_singular_name.pluralize?
|
2523
2528
|
instance_variable_set("@#{plural_table_name}".to_sym, ar_select)
|
2524
2529
|
@_lookup_context.instance_variable_set(:@_brick_is_postgres, true) if is_postgres
|
2525
|
-
table_name_no_schema =
|
2530
|
+
table_name_no_schema = real_model.name.underscore.split('/').last.pluralize # %%% hmmm ...
|
2526
2531
|
if namespace && (idx = lookup_context.prefixes.index(table_name_no_schema))
|
2527
2532
|
lookup_context.prefixes[idx] = "#{namespace.name.underscore}/#{lookup_context.prefixes[idx]}"
|
2528
2533
|
end
|
@@ -2538,6 +2543,12 @@ class Object
|
|
2538
2543
|
@_brick_erd = params['_brick_erd']&.to_i
|
2539
2544
|
add_csp_hash
|
2540
2545
|
end
|
2546
|
+
|
2547
|
+
_, order_by_txt = model._brick_calculate_ordering(default_ordering(table_name, pk, true)) if pk
|
2548
|
+
code << " def index\n"
|
2549
|
+
code << " @#{plural_table_name} = #{model.name}#{pk&.present? ? ".order(#{order_by_txt.join(', ')})" : '.all'}\n"
|
2550
|
+
code << " @#{plural_table_name}._brick_querying(params, brick_col_names: true)\n"
|
2551
|
+
code << " end\n"
|
2541
2552
|
end
|
2542
2553
|
|
2543
2554
|
unless is_openapi || is_avo # Normal controller (non-API)
|
@@ -2561,12 +2572,6 @@ class Object
|
|
2561
2572
|
end
|
2562
2573
|
end
|
2563
2574
|
|
2564
|
-
_, order_by_txt = model._brick_calculate_ordering(default_ordering(table_name, pk, true)) if pk
|
2565
|
-
code << " def index\n"
|
2566
|
-
code << " @#{plural_table_name} = #{model.name}#{pk&.present? ? ".order(#{order_by_txt.join(', ')})" : '.all'}\n"
|
2567
|
-
code << " @#{plural_table_name}._brick_querying(params, brick_col_names: true)\n"
|
2568
|
-
code << " end\n"
|
2569
|
-
|
2570
2575
|
# ----------------------------------------------------------------------------------
|
2571
2576
|
|
2572
2577
|
if pk.present?
|
@@ -2576,8 +2581,8 @@ class Object
|
|
2576
2581
|
find_obj = "find_#{singular_table_name}"
|
2577
2582
|
self.define_method :show do
|
2578
2583
|
_schema, @_is_show_schema_list = ::Brick.set_db_schema(params)
|
2579
|
-
_,
|
2580
|
-
instance_variable_set("@#{
|
2584
|
+
_, real_singular_table_name = model.real_singular(params)
|
2585
|
+
instance_variable_set("@#{real_singular_table_name}".to_sym, send(find_obj))
|
2581
2586
|
add_csp_hash("'unsafe-inline'")
|
2582
2587
|
end
|
2583
2588
|
end
|
@@ -2595,7 +2600,7 @@ class Object
|
|
2595
2600
|
send(params_name_sym)
|
2596
2601
|
rescue
|
2597
2602
|
end
|
2598
|
-
real_model,
|
2603
|
+
real_model, real_singular_table_name = model.real_singular(params)
|
2599
2604
|
new_params ||= real_model.attribute_names.each_with_object({}) do |a, s|
|
2600
2605
|
if (val = params["__#{a}"])
|
2601
2606
|
# val = case new_obj.class.column_for_attribute(a).type
|
@@ -2613,7 +2618,7 @@ class Object
|
|
2613
2618
|
new_obj.send("#{k}=", ::ActiveStorage::Filename.new('')) if v.is_a?(::ActiveStorage::Filename) && !v.instance_variable_get(:@filename)
|
2614
2619
|
end if Object.const_defined?('ActiveStorage')
|
2615
2620
|
end
|
2616
|
-
instance_variable_set("@#{
|
2621
|
+
instance_variable_set("@#{real_singular_table_name}".to_sym, new_obj)
|
2617
2622
|
add_csp_hash
|
2618
2623
|
end
|
2619
2624
|
|
@@ -2645,9 +2650,9 @@ class Object
|
|
2645
2650
|
model.__elasticsearch__.search(q)
|
2646
2651
|
rescue Elastic::Transport::Transport::Errors::NotFound => e
|
2647
2652
|
if @_brick_es_crud.index('i')
|
2648
|
-
|
2653
|
+
model.__elasticsearch__.create_index!
|
2649
2654
|
# model.import
|
2650
|
-
::Brick.elasticsearch_existings[
|
2655
|
+
::Brick.elasticsearch_existings[model.table_name.tr('.', '-').pluralize] = model.table_name
|
2651
2656
|
model.__elasticsearch__.search(q)
|
2652
2657
|
else
|
2653
2658
|
[]
|
@@ -2656,8 +2661,7 @@ class Object
|
|
2656
2661
|
end
|
2657
2662
|
render json: { result: es_result }
|
2658
2663
|
else
|
2659
|
-
real_model = model.
|
2660
|
-
singular_table_name = real_model.name.underscore.split('/').last
|
2664
|
+
real_model, real_singular_table_name = model.real_singular(params)
|
2661
2665
|
created_obj = model.send(:new, send(params_name_sym))
|
2662
2666
|
if created_obj.respond_to?(inh_col = model.inheritance_column) && created_obj.send(inh_col) == ''
|
2663
2667
|
created_obj.send("#{inh_col}=", model.name)
|
@@ -2665,12 +2669,12 @@ class Object
|
|
2665
2669
|
created_obj.save
|
2666
2670
|
@_lookup_context.instance_variable_set(:@_brick_model, real_model)
|
2667
2671
|
if created_obj.errors.empty?
|
2668
|
-
instance_variable_set("@#{
|
2672
|
+
instance_variable_set("@#{real_singular_table_name}".to_sym, created_obj)
|
2669
2673
|
@_lookup_context.instance_variable_set(:@_brick_is_postgres, true) if is_postgres
|
2670
2674
|
index
|
2671
2675
|
render :index
|
2672
2676
|
else # Surface errors to the user in a flash message
|
2673
|
-
instance_variable_set("@#{
|
2677
|
+
instance_variable_set("@#{real_singular_table_name}".to_sym, created_obj)
|
2674
2678
|
flash.now.alert = (created_obj.errors.errors.map { |err| "<b>#{err.attribute}</b> #{err.message}" }.join(', '))
|
2675
2679
|
new
|
2676
2680
|
render :new
|
@@ -2689,8 +2693,8 @@ class Object
|
|
2689
2693
|
code << " end\n"
|
2690
2694
|
self.define_method :edit do
|
2691
2695
|
_schema, @_is_show_schema_list = ::Brick.set_db_schema(params)
|
2692
|
-
_,
|
2693
|
-
instance_variable_set("@#{
|
2696
|
+
_, real_singular_table_name = model.real_singular(params)
|
2697
|
+
instance_variable_set("@#{real_singular_table_name}".to_sym, send(find_obj))
|
2694
2698
|
add_csp_hash
|
2695
2699
|
end
|
2696
2700
|
|
@@ -2717,8 +2721,8 @@ class Object
|
|
2717
2721
|
# return
|
2718
2722
|
end
|
2719
2723
|
|
2720
|
-
_,
|
2721
|
-
instance_variable_set("@#{
|
2724
|
+
_, real_singular_table_name = model.real_singular(params)
|
2725
|
+
instance_variable_set("@#{real_singular_table_name}".to_sym, (obj = send(find_obj)))
|
2722
2726
|
upd_params = send(params_name_sym)
|
2723
2727
|
json_overrides = ::Brick.config.json_columns&.fetch(table_name, nil)
|
2724
2728
|
if model.respond_to?(:devise_modules)
|
@@ -2746,7 +2750,8 @@ class Object
|
|
2746
2750
|
end
|
2747
2751
|
# Do not clear out a has_many_attached field if it already has an entry and nothing is supplied
|
2748
2752
|
hoa, hma, rtans = model._activestorage_actiontext_fields
|
2749
|
-
|
2753
|
+
# %%% does this work with STI?
|
2754
|
+
all_params = params[real_singular_table_name]
|
2750
2755
|
hma.each do |hma_field|
|
2751
2756
|
if upd_hash.fetch(hma_field) == [''] && # No new attachments...
|
2752
2757
|
all_params&.fetch("_brick_attached_#{hma_field}", nil) # ...and there is something existing
|
data/lib/brick/rails/engine.rb
CHANGED
@@ -626,7 +626,7 @@ window.addEventListener(\"popstate\", linkSchemas);
|
|
626
626
|
# Only CUD stuff has create / update / destroy
|
627
627
|
(!model.is_view? && ['new', 'create', 'edit', 'update', 'destroy'].include?(find_args.first))
|
628
628
|
)
|
629
|
-
@_brick_model = model.
|
629
|
+
@_brick_model = model.find_real_model(params)
|
630
630
|
end
|
631
631
|
rescue
|
632
632
|
end
|
@@ -1344,8 +1344,8 @@ end
|
|
1344
1344
|
<head>
|
1345
1345
|
#{css}
|
1346
1346
|
<title><%=
|
1347
|
-
|
1348
|
-
|
1347
|
+
if (model = (obj = @#{obj_name})&.class || @lookup_context&.instance_variable_get(:@_brick_model))
|
1348
|
+
see_all_path = send(\"#\{(base_model = model.base_class)._brick_index}_path\")
|
1349
1349
|
#{(inh_col = @_brick_model.inheritance_column).present? &&
|
1350
1350
|
" if obj.respond_to?(:#{inh_col}) && (model_name = @#{obj_name}.#{inh_col}) &&
|
1351
1351
|
!model_name.is_a?(Numeric) && model_name != base_model.name
|
data/lib/brick/reflect_tables.rb
CHANGED
@@ -26,10 +26,13 @@ module Brick
|
|
26
26
|
# Auto-create when there is a missing index
|
27
27
|
alias _original_method_missing method_missing
|
28
28
|
def method_missing(name, *args, &block)
|
29
|
+
return if name == :transport # Avoid infinite loop if Elasticsearch isn't yet initialized
|
30
|
+
|
29
31
|
_original_method_missing(name, *args, &block)
|
30
32
|
rescue Elastic::Transport::Transport::Errors::NotFound => e
|
31
33
|
if (missing_index = args.last&.fetch(:defined_params, nil)&.fetch(:index, nil)) &&
|
32
|
-
::Brick.
|
34
|
+
(es_table_name = ::Brick.elasticsearch_possible&.fetch(missing_index, nil)) &&
|
35
|
+
::Brick.elasticsearch_models&.fetch(es_table_name, nil)&.include?('i')
|
33
36
|
self.indices.create({ index: missing_index,
|
34
37
|
body: { settings: {}, mappings: { properties: {} } } })
|
35
38
|
puts "Auto-creating missing index \"#{missing_index}\""
|
@@ -40,9 +43,10 @@ module Brick
|
|
40
43
|
end
|
41
44
|
end
|
42
45
|
end
|
43
|
-
if ::Elasticsearch.const_defined?('Model')
|
44
|
-
|
45
|
-
|
46
|
+
if ::Elasticsearch.const_defined?('Model') &&
|
47
|
+
# By setting the environment variable ELASTICSEARCH_URL then you can specify an Elasticsearch/Opensearch
|
48
|
+
# host that is picked up here
|
49
|
+
(host = (client = ::Elasticsearch::Model.client).transport&.hosts&.first)
|
46
50
|
es_uri = URI.parse("#{host[:protocol]}://#{host[:host]}:#{host[:port]}")
|
47
51
|
es_uri = nil if es_uri.to_s == 'http://localhost:9200'
|
48
52
|
begin
|
@@ -513,7 +517,7 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
513
517
|
end
|
514
518
|
end
|
515
519
|
|
516
|
-
if ems = ::Brick.elasticsearch_models
|
520
|
+
if (ems = ::Brick.elasticsearch_models)
|
517
521
|
access = case ems
|
518
522
|
when Hash, String # Hash is a list of resource names and ES permissions such as 'r' or 'icr'
|
519
523
|
ems
|
@@ -544,6 +548,9 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
544
548
|
next if rel.first.is_a?(Symbol)
|
545
549
|
|
546
550
|
perms = rel.last.fetch(:isView, nil) ? access.tr('cud', '') : access
|
551
|
+
unless ::Brick.elasticsearch_existings[es_index = rel.first.tr('.', '-').pluralize]
|
552
|
+
(::Brick.elasticsearch_possible ||= {})[es_index] = rel.first
|
553
|
+
end
|
547
554
|
s[rel.first] = perms
|
548
555
|
end
|
549
556
|
else # or there are specific permissions for each resource, so find the matching indexes
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -111,7 +111,7 @@ module Brick
|
|
111
111
|
:established_drf,
|
112
112
|
:is_oracle, :is_eager_loading, :auto_models, :initializer_loaded,
|
113
113
|
:table_name_lookup,
|
114
|
-
:elasticsearch_models, :elasticsearch_existings,
|
114
|
+
:elasticsearch_models, :elasticsearch_existings, :elasticsearch_possible,
|
115
115
|
:routes_done
|
116
116
|
::Brick.auto_models = []
|
117
117
|
|
@@ -38,7 +38,6 @@ module Brick
|
|
38
38
|
existing_models = ActiveRecord::Base.descendants.each_with_object({}) do |m, s|
|
39
39
|
s[m.table_name] = SeedModel.new(m.table_name, m, false) if !m.abstract_class? && !m.is_view? && m.table_exists?
|
40
40
|
end
|
41
|
-
|
42
41
|
models = (existing_models.values +
|
43
42
|
# ... then add models which can be auto-built by Brick
|
44
43
|
relations.reject do |k, v|
|
@@ -57,7 +56,6 @@ module Brick
|
|
57
56
|
end
|
58
57
|
end
|
59
58
|
end
|
60
|
-
|
61
59
|
seeds = +'# Seeds file for '
|
62
60
|
if (arbc = ActiveRecord::Base.connection).respond_to?(:current_database) # SQLite3 can't do this!
|
63
61
|
seeds << "#{arbc.current_database}:\n"
|
@@ -124,23 +122,22 @@ module Brick
|
|
124
122
|
end
|
125
123
|
end
|
126
124
|
schema = if (tbl_parts = tbl.split('.')).length > 1
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
125
|
+
if tbl_parts.first == (::Brick.default_schema || 'public')
|
126
|
+
tbl_parts.shift
|
127
|
+
nil
|
128
|
+
else
|
129
|
+
tbl_parts.first
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# # Had considered doing this for non-Airtable:
|
134
|
+
# # For the moment we're skipping polymorphics
|
135
|
+
# fkeys = klass.reflect_on_all_associations.select { |a| a.belongs_to? && !a.polymorphic? }.map do |fk|
|
136
|
+
# { fk: fk.foreign_key, assoc_name: fk.name.to_s, inverse_table: fk.table_name }
|
137
|
+
# end
|
138
|
+
# For the moment we're skipping polymorphics
|
139
|
+
fkeys = relation[:fks].values.select { |assoc| assoc[:is_bt] && !assoc[:polymorphic] }
|
134
140
|
|
135
|
-
# %%% For the moment we're skipping polymorphics
|
136
|
-
fkeys = if is_airtable
|
137
|
-
tbl = tbl.singularize
|
138
|
-
relation[:fks]&.values&.select { |assoc| assoc[:is_bt] && !assoc[:polymorphic] }
|
139
|
-
else
|
140
|
-
klass.reflect_on_all_associations.select { |a| a.belongs_to? && !a.polymorphic? }.map do |fk|
|
141
|
-
{ fk: fk.foreign_key, assoc_name: fk.name.to_s, inverse_table: fk.table_name }
|
142
|
-
end
|
143
|
-
end
|
144
141
|
# Refer to this table name as a symbol or dotted string as appropriate
|
145
142
|
# tbl_code = tbl_parts.length == 1 ? ":#{tbl_parts.first}" : "'#{tbl}'"
|
146
143
|
|
@@ -205,7 +202,7 @@ module Brick
|
|
205
202
|
if fk
|
206
203
|
fk_val = if is_airtable
|
207
204
|
# The (3..-1) is to take off the "rec___" prefix
|
208
|
-
obj.attributes_before_type_cast[fk[:assoc_name]]&.first&.[](3..-1)
|
205
|
+
obj.attributes_before_type_cast[fk[:assoc_name]]&.first&.[](3..-1)
|
209
206
|
else
|
210
207
|
brick_escape(val)
|
211
208
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brick
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.236
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lorin Thwaits
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-04-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -261,7 +261,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
261
261
|
- !ruby/object:Gem::Version
|
262
262
|
version: 1.3.6
|
263
263
|
requirements: []
|
264
|
-
rubygems_version: 3.
|
264
|
+
rubygems_version: 3.2.33
|
265
265
|
signing_key:
|
266
266
|
specification_version: 4
|
267
267
|
summary: Create a Rails app from data alone
|