brick 1.0.89 → 1.0.91
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 +61 -13
- data/lib/brick/frameworks/rails/engine.rb +40 -8
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +23 -10
- data/lib/generators/brick/install_generator.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81eaa518a99452286bdaf1e5ed33b83962ede9f9c6509f0b472fd0fe19a8eceb
|
4
|
+
data.tar.gz: 06f5653ce40eb6ee1568b380cf3063073ac7735add8aab6c5873a343e8018a70
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e0a678885c927a7a80c8758d265c2ff351f67ea44e8e1b2c128e123df441f4f72a62f775b9785615eeacbdbff99427e9d1590890bdffd06165ae7b2339fe1af
|
7
|
+
data.tar.gz: 7bd3e424225e435bab4517fb14aeaa3ca128041a746aaf413ecdb17a771444c3413f058ff28cc5e303d074fdd7cc7d21ff66f842667c14226d1849e96d4b3a98
|
data/lib/brick/extensions.rb
CHANGED
@@ -127,13 +127,14 @@ module ActiveRecord
|
|
127
127
|
if bracket_name
|
128
128
|
if ch == ']' # Time to process a bracketed thing?
|
129
129
|
parts = bracket_name.split('.')
|
130
|
-
first_parts = parts[0..-2].
|
131
|
-
klass = (orig_class = klass).reflect_on_association(part_sym = part.to_sym)&.klass
|
132
|
-
|
133
|
-
|
130
|
+
first_parts = parts[0..-2].each_with_object([]) do |part, s|
|
131
|
+
unless (klass = (orig_class = klass).reflect_on_association(part_sym = part.to_sym)&.klass)
|
132
|
+
puts "Couldn't reference #{orig_class.name}##{part} that's part of the DSL \"#{dsl}\"."
|
133
|
+
break
|
134
|
+
end
|
135
|
+
s << part_sym
|
134
136
|
end
|
135
|
-
parts = prefix + first_parts + [parts[-1]]
|
136
|
-
if parts.length > 1
|
137
|
+
if (parts = prefix + first_parts + [parts[-1]]).length > 1 && klass
|
137
138
|
unless is_polymorphic
|
138
139
|
s = build_array
|
139
140
|
parts[0..-3].each { |v| s = s[v.to_sym] }
|
@@ -141,7 +142,7 @@ module ActiveRecord
|
|
141
142
|
end
|
142
143
|
translations[parts[0..-2].join('.')] = klass
|
143
144
|
end
|
144
|
-
if klass
|
145
|
+
if klass&.column_names.exclude?(parts.last) &&
|
145
146
|
(klass = (orig_class = klass).reflect_on_association(possible_dsl = parts.pop.to_sym)&.klass)
|
146
147
|
if prefix.empty? # Custom columns start with an empty prefix
|
147
148
|
prefix << parts.shift until parts.empty?
|
@@ -308,9 +309,15 @@ module ActiveRecord
|
|
308
309
|
def self._brick_calculate_bts_hms(translations, join_array)
|
309
310
|
# Add any custom columns
|
310
311
|
::Brick.config.custom_columns&.fetch(table_name, nil)&.each do |k, cc|
|
312
|
+
if cc.is_a?(Array)
|
313
|
+
fk_col = cc.last unless cc.last.blank?
|
314
|
+
cc = cc.first
|
315
|
+
else
|
316
|
+
fk_col = true
|
317
|
+
end
|
311
318
|
# false = not polymorphic, and true = yes -- please emit_dsl
|
312
319
|
pieces, my_dsl = brick_parse_dsl(join_array, [], translations, false, cc, true)
|
313
|
-
_br_cust_cols[k] = [pieces, my_dsl]
|
320
|
+
_br_cust_cols[k] = [pieces, my_dsl, fk_col]
|
314
321
|
end
|
315
322
|
bts, hms, associatives = ::Brick.get_bts_and_hms(self)
|
316
323
|
bts.each do |_k, bt|
|
@@ -382,6 +389,23 @@ module ActiveRecord
|
|
382
389
|
end
|
383
390
|
end
|
384
391
|
|
392
|
+
module AttributeMethods
|
393
|
+
module ClassMethods
|
394
|
+
alias _brick_dangerous_attribute_method? dangerous_attribute_method?
|
395
|
+
# Bypass the error "ActiveRecord::DangerousAttributeError" if this object comes from a view.
|
396
|
+
# (Allows for column names such as 'attribute', 'delete', and 'update' to still work.)
|
397
|
+
def dangerous_attribute_method?(name)
|
398
|
+
if (is_dangerous = _brick_dangerous_attribute_method?(name)) && is_view?
|
399
|
+
if column_names.include?(name.to_s)
|
400
|
+
puts "WARNING: Column \"#{name}\" in view #{table_name} conflicts with a reserved ActiveRecord method name."
|
401
|
+
end
|
402
|
+
return false
|
403
|
+
end
|
404
|
+
is_dangerous
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
385
409
|
class Relation
|
386
410
|
attr_reader :_brick_chains, :_arel_applied_aliases
|
387
411
|
|
@@ -539,6 +563,10 @@ module ActiveRecord
|
|
539
563
|
next
|
540
564
|
end
|
541
565
|
|
566
|
+
key_klass = nil
|
567
|
+
key_tbl_name = nil
|
568
|
+
dest_pk = nil
|
569
|
+
key_alias = nil
|
542
570
|
cc.first.each do |cc_part|
|
543
571
|
dest_klass = cc_part[0..-2].inject(klass) { |kl, cc_part_term| kl.reflect_on_association(cc_part_term).klass }
|
544
572
|
tbl_name = (field_tbl_names[k][cc_part.last] ||= shift_or_first(chains[dest_klass])).split('.').last
|
@@ -551,10 +579,29 @@ module ActiveRecord
|
|
551
579
|
used_col_aliases.key?(col_alias)
|
552
580
|
cc_part_idx -= 1
|
553
581
|
end
|
582
|
+
used_col_aliases[col_alias] = nil
|
583
|
+
# Set up custom column links by preparing key_klass and key_alias
|
584
|
+
# (If there are multiple different tables referenced in the DSL, we end up creating a link to the last one)
|
585
|
+
if cc[2] && (dest_pk = dest_klass.primary_key)
|
586
|
+
key_klass = dest_klass
|
587
|
+
key_tbl_name = tbl_name
|
588
|
+
cc_part_idx = cc_part.length - 1
|
589
|
+
while cc_part_idx > 0 &&
|
590
|
+
(key_alias = "br_cc_#{k}__#{(cc_part[cc_part_idx..-2] + [dest_pk]).map(&:to_s).join('__')}") &&
|
591
|
+
key_alias != col_alias && # We break out if this key alias does exactly match the col_alias
|
592
|
+
used_col_aliases.key?(key_alias)
|
593
|
+
cc_part_idx -= 1
|
594
|
+
end
|
595
|
+
end
|
554
596
|
selects << "#{tbl_name}.#{cc_part.last} AS #{col_alias}"
|
555
597
|
cc_part << col_alias
|
556
|
-
used_col_aliases[col_alias] = nil
|
557
598
|
end
|
599
|
+
# Add a key column unless we've already got it
|
600
|
+
if key_alias && !used_col_aliases.key?(key_alias)
|
601
|
+
selects << "#{key_tbl_name}.#{dest_pk} AS #{key_alias}"
|
602
|
+
used_col_aliases[key_alias] = nil
|
603
|
+
end
|
604
|
+
cc[2] = key_alias ? [key_klass, key_alias] : nil
|
558
605
|
end
|
559
606
|
|
560
607
|
klass._br_bt_descrip.each do |v|
|
@@ -1058,7 +1105,7 @@ Module.class_exec do
|
|
1058
1105
|
# elsif base_module != Object
|
1059
1106
|
# module_parent.const_missing(*args)
|
1060
1107
|
elsif Rails.respond_to?(:autoloaders) && # After finding nothing else, if Zeitwerk is enabled ...
|
1061
|
-
|
1108
|
+
(Rails::Autoloaders.respond_to?(:zeitwerk_enabled?) ? Rails::Autoloaders.zeitwerk_enabled? : true)
|
1062
1109
|
self._brick_const_missing(*args) # ... rely solely on Zeitwerk.
|
1063
1110
|
else # Classic mode
|
1064
1111
|
unless (found = base_module._brick_const_missing(*args))
|
@@ -1149,7 +1196,7 @@ class Object
|
|
1149
1196
|
if (base_model = ::Brick.sti_models[full_model_name]&.fetch(:base, nil) || ::Brick.existing_stis[full_model_name]&.constantize)
|
1150
1197
|
is_sti = true
|
1151
1198
|
else
|
1152
|
-
base_model = ::Brick.config.models_inherit_from
|
1199
|
+
base_model = ::Brick.config.models_inherit_from
|
1153
1200
|
end
|
1154
1201
|
hmts = nil
|
1155
1202
|
code = +"class #{full_name} < #{base_model.name}\n"
|
@@ -1268,7 +1315,7 @@ class Object
|
|
1268
1315
|
# hm.first[:inverse][:assoc_name].to_sym
|
1269
1316
|
options[:source] = hm.last.to_sym
|
1270
1317
|
else
|
1271
|
-
through = hm.first[:alternate_name]
|
1318
|
+
through = hm.first.fetch(:alternate_chosen_name, hm.first[:alternate_name])
|
1272
1319
|
end
|
1273
1320
|
singular_assoc_name = hm.first[:inverse][:assoc_name].singularize
|
1274
1321
|
"#{singular_assoc_name}_#{hmt_fk}"
|
@@ -1689,12 +1736,13 @@ class Object
|
|
1689
1736
|
hm_assoc[:alternate_name] != (source || name.underscore)
|
1690
1737
|
plural = "#{hm_assoc[:assoc_name]}_#{ActiveSupport::Inflector.pluralize(hm_assoc[:alternate_name])}"
|
1691
1738
|
new_alt_name = (hm_assoc[:alternate_name] == name.underscore) ? "#{hm_assoc[:assoc_name].singularize}_#{plural}" : plural
|
1739
|
+
# %%% In rare cases might even need to add a number at the end for uniqueness
|
1692
1740
|
# uniq = 1
|
1693
1741
|
# while same_name = relation[:fks].find { |x| x.last[:assoc_name] == hm_assoc[:assoc_name] && x.last != hm_assoc }
|
1694
1742
|
# hm_assoc[:assoc_name] = "#{hm_assoc_name}_#{uniq += 1}"
|
1695
1743
|
# end
|
1696
1744
|
# puts new_alt_name
|
1697
|
-
|
1745
|
+
hm_assoc[:alternate_chosen_name] = new_alt_name
|
1698
1746
|
[new_alt_name, true]
|
1699
1747
|
else
|
1700
1748
|
assoc_name = ::Brick.namify(hm_assoc[:inverse_table]).pluralize
|
@@ -19,7 +19,12 @@ module Brick
|
|
19
19
|
::Brick.exclude_tables = app.config.brick.fetch(:exclude_tables, [])
|
20
20
|
|
21
21
|
# Class for auto-generated models to inherit from
|
22
|
-
::Brick.models_inherit_from = app.config.brick.fetch(:models_inherit_from,
|
22
|
+
::Brick.models_inherit_from = app.config.brick.fetch(:models_inherit_from, nil) ||
|
23
|
+
begin
|
24
|
+
::ApplicationRecord
|
25
|
+
rescue StandardError => ex
|
26
|
+
::ActiveRecord::Base
|
27
|
+
end
|
23
28
|
|
24
29
|
# When table names have specific prefixes, automatically place them in their own module with a table_name_prefix.
|
25
30
|
::Brick.table_name_prefixes = app.config.brick.fetch(:table_name_prefixes, [])
|
@@ -818,7 +823,16 @@ erDiagram
|
|
818
823
|
end # DutyFree data export and import
|
819
824
|
# %%% Instead of our current "for Janet Leverling (Employee)" kind of link we previously had this code that did a "where x = 123" thing:
|
820
825
|
# (where <%= @_brick_params.each_with_object([]) { |v, s| s << \"#\{v.first\} = #\{v.last.inspect\}\" }.join(', ') %>)
|
821
|
-
+"
|
826
|
+
+"<html>
|
827
|
+
<head>
|
828
|
+
#{css}
|
829
|
+
<title>#{model_name} <%
|
830
|
+
if (description = (relation = Brick.relations[#{model_name}.table_name])&.fetch(:description, nil)).present?
|
831
|
+
%> - <%= description
|
832
|
+
%><% end
|
833
|
+
%></title>
|
834
|
+
</head>
|
835
|
+
<body>
|
822
836
|
<p style=\"color: green\"><%= notice %></p>#{"
|
823
837
|
<select id=\"schema\">#{schema_options}</select>" if ::Brick.config.schema_behavior[:multitenant] && ::Brick.db_schemas.length > 1}
|
824
838
|
<select id=\"tbl\">#{table_options}</select>
|
@@ -826,7 +840,7 @@ erDiagram
|
|
826
840
|
<td><h1>#{model_name}</h1></td>
|
827
841
|
<td id=\"imgErd\" title=\"Show ERD\"></td>
|
828
842
|
</tr></table>#{template_link}<%
|
829
|
-
if
|
843
|
+
if description.present? %><%=
|
830
844
|
description %><br><%
|
831
845
|
end
|
832
846
|
# FILTER PARAMETERS
|
@@ -976,7 +990,12 @@ erDiagram
|
|
976
990
|
%><%= display_value(col_type || col&.sql_type, val) %><%
|
977
991
|
elsif cust_col
|
978
992
|
data = cust_col.first.map { |cc_part| #{obj_name}.send(cc_part.last) }
|
979
|
-
|
993
|
+
cust_txt = #{model_name}.brick_descrip(cust_col[-2], data)
|
994
|
+
if (link_id = #{obj_name}.send(cust_col.last[1]) if cust_col.last)
|
995
|
+
%><%= link_to(cust_txt, send(\"#\{cust_col.last.first._brick_index(:singular)}_path\", link_id)) %><%
|
996
|
+
else
|
997
|
+
%><%= cust_txt %><%
|
998
|
+
end
|
980
999
|
else # Bad column name!
|
981
1000
|
%>?<%
|
982
1001
|
end
|
@@ -988,7 +1007,10 @@ erDiagram
|
|
988
1007
|
</table>
|
989
1008
|
|
990
1009
|
#{"<hr><%= link_to \"New #{obj_name}\", new_#{path_obj_name}_path %>" unless @_brick_model.is_view?}
|
991
|
-
#{script}
|
1010
|
+
#{script}
|
1011
|
+
</body>
|
1012
|
+
</html>
|
1013
|
+
"
|
992
1014
|
|
993
1015
|
when 'status'
|
994
1016
|
if is_status
|
@@ -1061,7 +1083,14 @@ erDiagram
|
|
1061
1083
|
end
|
1062
1084
|
|
1063
1085
|
when 'show', 'new', 'update'
|
1064
|
-
+"
|
1086
|
+
+"<html>
|
1087
|
+
<head>
|
1088
|
+
#{css}
|
1089
|
+
<title><%=
|
1090
|
+
page_title = (\"#{model_name}: #\{(obj = @#{obj_name})&.brick_descrip || controller_name}\")
|
1091
|
+
%></title>
|
1092
|
+
</head>
|
1093
|
+
<body>
|
1065
1094
|
|
1066
1095
|
<svg id=\"revertTemplate\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"
|
1067
1096
|
width=\"32px\" height=\"32px\" viewBox=\"0 0 512 512\" xml:space=\"preserve\">
|
@@ -1072,7 +1101,7 @@ erDiagram
|
|
1072
1101
|
<p style=\"color: green\"><%= notice %></p>#{"
|
1073
1102
|
<select id=\"schema\">#{schema_options}</select>" if ::Brick.config.schema_behavior[:multitenant] && ::Brick.db_schemas.length > 1}
|
1074
1103
|
<select id=\"tbl\">#{table_options}</select>
|
1075
|
-
<h1
|
1104
|
+
<h1><%= page_title %></h1><%
|
1076
1105
|
if (description = (relation = Brick.relations[#{model_name}.table_name])&.fetch(:description, nil)) %><%=
|
1077
1106
|
description %><br><%
|
1078
1107
|
end
|
@@ -1236,7 +1265,10 @@ end
|
|
1236
1265
|
"<%= button_to(\"Delete #\{@#{obj_name}.brick_descrip}\", send(\"#\{#{model_name}._brick_index(:singular)}_path\".to_sym, @#{obj_name}), { method: 'delete', class: 'danger', #{confirm_are_you_sure} }) %>"
|
1237
1266
|
end}
|
1238
1267
|
<% end %>
|
1239
|
-
#{script}
|
1268
|
+
#{script}
|
1269
|
+
</body>
|
1270
|
+
</html>
|
1271
|
+
"
|
1240
1272
|
|
1241
1273
|
end
|
1242
1274
|
inline << "
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -186,10 +186,10 @@ module Brick
|
|
186
186
|
|
187
187
|
def get_bts_and_hms(model)
|
188
188
|
bts, hms = model.reflect_on_all_associations.each_with_object([{}, {}]) do |a, s|
|
189
|
-
next
|
189
|
+
next unless a.polymorphic? || (!a.belongs_to? && (through = a.options[:through])) ||
|
190
|
+
(a.klass && ::Brick.config.exclude_tables.exclude?(a.klass.table_name))
|
190
191
|
|
191
|
-
|
192
|
-
when :belongs_to
|
192
|
+
if a.belongs_to?
|
193
193
|
if a.polymorphic?
|
194
194
|
rel_poly_bt = relations[model.table_name][:fks].find { |_k, fk| fk[:assoc_name] == a.name.to_s }
|
195
195
|
if (primary_tables = rel_poly_bt&.last&.fetch(:inverse_table, [])).is_a?(Array)
|
@@ -205,8 +205,24 @@ module Brick
|
|
205
205
|
else
|
206
206
|
s.first[a.foreign_key.to_s] = [a.name, a.klass]
|
207
207
|
end
|
208
|
-
|
209
|
-
|
208
|
+
else # This gets has_many as well as has_one and has_many :through
|
209
|
+
if through
|
210
|
+
is_invalid_source = nil
|
211
|
+
begin
|
212
|
+
if a.through_reflection&.belongs_to?
|
213
|
+
puts "WARNING: HMT relationship :#{a.name} in model #{model.name} tries to go through belongs_to association :#{through}. This is not possible."
|
214
|
+
next
|
215
|
+
elsif !a.source_reflection # Had considered: a.active_record.reflect_on_association(a.source_reflection_name).nil?
|
216
|
+
is_invalid_source = true
|
217
|
+
end
|
218
|
+
rescue
|
219
|
+
is_invalid_source = true
|
220
|
+
end
|
221
|
+
if is_invalid_source
|
222
|
+
puts "WARNING: HMT relationship :#{a.name} in model #{model.name} has invalid source :#{a.source_reflection_name}."
|
223
|
+
next
|
224
|
+
end
|
225
|
+
end
|
210
226
|
s.last[a.name] = a
|
211
227
|
end
|
212
228
|
end
|
@@ -216,13 +232,10 @@ module Brick
|
|
216
232
|
hms.each do |hmt|
|
217
233
|
if (through = hmt.last.options[:through])
|
218
234
|
# ::Brick.relations[hmt.last.through_reflection.table_name]
|
219
|
-
skip_hms[through] = nil if hms[through] && model.is_brick?
|
235
|
+
skip_hms[through] = nil if hms[through] && model.is_brick? &&
|
236
|
+
hmt.last.klass != hmt.last.active_record # Don't pull HMs for HMTs that point back to the same table
|
220
237
|
# End up with a hash of HMT names pointing to join-table associations
|
221
238
|
model._br_associatives[hmt.first] = hms[through] # || hms["#{(opt = hmt.last.options)[:through].to_s.singularize}_#{opt[:source].to_s.pluralize}".to_sym]
|
222
|
-
elsif hmt.last.inverse_of.nil? && ActiveRecord.version >= ::Gem::Version.new('4.2')
|
223
|
-
puts "SKIPPING #{hmt.last.name.inspect}"
|
224
|
-
# %%% If we don't do this then below associative.name will find that associative is nil
|
225
|
-
skip_hms[hmt.last.name] = nil
|
226
239
|
end
|
227
240
|
end
|
228
241
|
skip_hms.each { |k, _v| hms.delete(k) }
|
@@ -139,7 +139,7 @@ module Brick
|
|
139
139
|
# Settings for the Brick gem
|
140
140
|
# (By default this auto-creates models, controllers, views, and routes on-the-fly.)
|
141
141
|
|
142
|
-
if
|
142
|
+
if ActiveRecord::Base.respond_to?(:brick_select)
|
143
143
|
# Mode -- generally :on or :off, or only in :development. Also available is :diag_env which enables only
|
144
144
|
# when the environment variable BRICK is set.
|
145
145
|
Brick.mode = :development
|
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.91
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lorin Thwaits
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-11-
|
11
|
+
date: 2022-11-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|