brick 1.0.129 → 1.0.131
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 +56 -33
- data/lib/brick/frameworks/rails/engine.rb +6 -3
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +24 -2
- 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: 6e9356edd43a6af6120f30bfbcd520383f3ae700e6ff04be11ebdd3493852ef4
|
4
|
+
data.tar.gz: a099075c53acc9bf29c718043cc619b5ab4f895366f9c7ddd14d53c8f7f432b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f9df598bad9ce128a88f4fe364d568be8c38eee57e595024866d39a255b42f513a26adc68d64d14cdecd4b5d13fb7424935f17df7dbb41c3bda2ae31057a4c7
|
7
|
+
data.tar.gz: 845e5747a916a338ee494426e4ef0ac6fd5c65c3579df0210c8a80468887fac12103407acfbaee3659b3b45763f98ef0bd109935d70920b932b4fd41cc15fdc5
|
data/lib/brick/extensions.rb
CHANGED
@@ -148,7 +148,8 @@ module ActiveRecord
|
|
148
148
|
translations[parts[0..-2].join('.')] = klass
|
149
149
|
end
|
150
150
|
if klass&.column_names.exclude?(parts.last) &&
|
151
|
-
(klass = (orig_class = klass).reflect_on_association(possible_dsl = parts.
|
151
|
+
(klass = (orig_class = klass).reflect_on_association(possible_dsl = parts.last&.to_sym)&.klass)
|
152
|
+
parts.pop
|
152
153
|
if prefix.empty? # Custom columns start with an empty prefix
|
153
154
|
prefix << parts.shift until parts.empty?
|
154
155
|
end
|
@@ -162,6 +163,7 @@ module ActiveRecord
|
|
162
163
|
if emit_dsl
|
163
164
|
dsl3 << "[#{prefix[1..-1].map { |p| "#{p.to_s}." }.join if prefix.length > 1}#{bracket_name}]"
|
164
165
|
end
|
166
|
+
parts[-1] = column_names.first if parts[-1].nil? # No primary key to be found? Grab something to display!
|
165
167
|
members << parts
|
166
168
|
end
|
167
169
|
end
|
@@ -231,7 +233,8 @@ module ActiveRecord
|
|
231
233
|
if this_obj.is_a?(ActiveRecord::Base) && (obj_descrip = this_obj.class.brick_descrip(this_obj))
|
232
234
|
this_obj = obj_descrip
|
233
235
|
end
|
234
|
-
if
|
236
|
+
if Object.const_defined?('ActiveStorage') && this_obj.is_a?(::ActiveStorage::Filename) &&
|
237
|
+
this_obj.instance_variable_get(:@filename).nil?
|
235
238
|
this_obj.instance_variable_set(:@filename, '')
|
236
239
|
end
|
237
240
|
this_obj&.to_s || ''
|
@@ -667,6 +670,7 @@ module ActiveRecord
|
|
667
670
|
link_back = []
|
668
671
|
# Track polymorphic type field if necessary
|
669
672
|
if hm.source_reflection.options[:as]
|
673
|
+
# Might be able to simplify as: hm.source_reflection.type
|
670
674
|
poly_ft = [hm.source_reflection.inverse_of.foreign_type, hmt_assoc.source_reflection.class_name]
|
671
675
|
end
|
672
676
|
# link_back << hm.source_reflection.inverse_of.name
|
@@ -741,12 +745,21 @@ module ActiveRecord
|
|
741
745
|
end
|
742
746
|
else
|
743
747
|
fk_col = (inv = hm.inverse_of)&.foreign_key || hm.foreign_key
|
744
|
-
|
748
|
+
# %%% Might only need hm.type and not the first part :)
|
749
|
+
poly_type = inv&.foreign_type || hm.type if hm.options.key?(:as)
|
745
750
|
pk = hm.klass.primary_key
|
746
751
|
(pk.is_a?(Array) ? pk.first : pk) || '*'
|
747
752
|
end
|
748
753
|
next unless count_column # %%% Would be able to remove this when multiple foreign keys to same destination becomes bulletproof
|
749
754
|
|
755
|
+
pri_tbl = hm.active_record
|
756
|
+
pri_key = hm.options[:primary_key] || pri_tbl.primary_key
|
757
|
+
unless hm.active_record.column_names.include?(pri_key)
|
758
|
+
# %%% When this gets hit then if an attempt is made to display the ERD, it might end up being blank
|
759
|
+
nix << k
|
760
|
+
next
|
761
|
+
end
|
762
|
+
|
750
763
|
tbl_alias = if is_mysql
|
751
764
|
"`b_r_#{hm.name}`"
|
752
765
|
elsif is_postgres
|
@@ -754,7 +767,6 @@ module ActiveRecord
|
|
754
767
|
else
|
755
768
|
"b_r_#{hm.name}"
|
756
769
|
end
|
757
|
-
pri_tbl = hm.active_record
|
758
770
|
pri_tbl_name = is_mysql ? "`#{pri_tbl.table_name}`" : "\"#{pri_tbl.table_name.gsub('.', '"."')}\""
|
759
771
|
pri_tbl_name = if is_mysql
|
760
772
|
"`#{pri_tbl.table_name}`"
|
@@ -765,10 +777,10 @@ module ActiveRecord
|
|
765
777
|
end
|
766
778
|
on_clause = []
|
767
779
|
hm_selects = if fk_col.is_a?(Array) # Composite key?
|
768
|
-
fk_col.each_with_index { |fk_col_part, idx| on_clause << "#{tbl_alias}.#{fk_col_part} = #{pri_tbl_name}.#{
|
780
|
+
fk_col.each_with_index { |fk_col_part, idx| on_clause << "#{tbl_alias}.#{fk_col_part} = #{pri_tbl_name}.#{pri_key[idx]}" }
|
769
781
|
fk_col.dup
|
770
782
|
else
|
771
|
-
on_clause << "#{tbl_alias}.#{fk_col} = #{pri_tbl_name}.#{
|
783
|
+
on_clause << "#{tbl_alias}.#{fk_col} = #{pri_tbl_name}.#{pri_key}"
|
772
784
|
[fk_col]
|
773
785
|
end
|
774
786
|
if poly_type
|
@@ -864,6 +876,12 @@ JOIN (SELECT #{hm_selects.map { |s| "#{'br_t0.' if from_clause}#{s}" }.join(', '
|
|
864
876
|
def brick_list
|
865
877
|
pks = klass.primary_key.is_a?(String) ? [klass.primary_key] : klass.primary_key
|
866
878
|
selects = pks.each_with_object([]) { |pk, s| s << pk unless s.include?(pk) }
|
879
|
+
# Get foreign keys for anything marked to be auto-preloaded, or a self-referencing JOIN
|
880
|
+
klass_cols = klass.column_names
|
881
|
+
reflect_on_all_associations.each do |a|
|
882
|
+
selects << a.foreign_key if a.belongs_to? && (preload_values.include?(a.name) ||
|
883
|
+
(!a.options[:polymorphic] && a.klass == klass && klass_cols.include?(a.foreign_key)))
|
884
|
+
end
|
867
885
|
# ActiveStorage compatibility
|
868
886
|
selects << 'service_name' if klass.name == 'ActiveStorage::Blob' && ActiveStorage::Blob.columns_hash.key?('service_name')
|
869
887
|
selects << 'blob_id' if klass.name == 'ActiveStorage::Attachment' && ActiveStorage::Attachment.columns_hash.key?('blob_id')
|
@@ -1003,16 +1021,17 @@ Module.class_exec do
|
|
1003
1021
|
is_controller = requested.end_with?('Controller')
|
1004
1022
|
# self.name is nil when a model name is requested in an .erb file
|
1005
1023
|
if self.name && ::Brick.config.path_prefix
|
1006
|
-
|
1024
|
+
split_self_name.shift if (split_self_name = self.name.split('::')).first.blank?
|
1007
1025
|
# Asking for the prefix module?
|
1026
|
+
camelize_prefix = ::Brick.config.path_prefix.camelize
|
1008
1027
|
if self == Object && requested == camelize_prefix
|
1009
1028
|
Object.const_set(args.first, (built_module = Module.new))
|
1010
1029
|
puts "module #{camelize_prefix}; end\n"
|
1011
1030
|
return built_module
|
1012
|
-
|
1013
|
-
|
1014
|
-
if split_self_name.first == camelize_prefix
|
1031
|
+
elsif module_parent == Object && self.name == camelize_prefix ||
|
1032
|
+
module_parent.name == camelize_prefix && module_parent.module_parent == Object
|
1015
1033
|
split_self_name.shift # Remove the identified path prefix from the split name
|
1034
|
+
is_brick_prefix = true
|
1016
1035
|
if is_controller
|
1017
1036
|
brick_root = split_self_name.empty? ? self : camelize_prefix.constantize
|
1018
1037
|
end
|
@@ -1045,26 +1064,30 @@ Module.class_exec do
|
|
1045
1064
|
self
|
1046
1065
|
end
|
1047
1066
|
# puts "#{self.name} - #{args.first}"
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1067
|
+
# Unless it's a Brick prefix looking for a TNP that should create a module ...
|
1068
|
+
unless (is_tnp_module = (is_brick_prefix && !is_controller && ::Brick.config.table_name_prefixes.values.include?(requested)))
|
1069
|
+
# ... first look around for an existing module or class.
|
1070
|
+
desired_classname = (self == Object || !name) ? requested : "#{name}::#{requested}"
|
1071
|
+
if ((is_defined = self.const_defined?(args.first)) && (possible = self.const_get(args.first)) &&
|
1072
|
+
# Reset `possible` if it's a controller request that's not a perfect match
|
1073
|
+
# Was: (possible = nil) but changed to #local_variable_set in order to suppress the "= should be ==" warning
|
1074
|
+
(possible&.name == desired_classname || (is_controller && binding.local_variable_set(:possible, nil)))) ||
|
1075
|
+
# Try to require the respective Ruby file
|
1076
|
+
((filename = ActiveSupport::Dependencies.search_for_file(desired_classname.underscore) ||
|
1077
|
+
(self != Object && ActiveSupport::Dependencies.search_for_file((desired_classname = requested).underscore))
|
1078
|
+
) && (require_dependency(filename) || true) &&
|
1079
|
+
((possible = self.const_get(args.first)) && possible.name == desired_classname)
|
1080
|
+
) ||
|
1081
|
+
# If any class has turned up so far (and we're not in the middle of eager loading)
|
1082
|
+
# then return what we've found.
|
1083
|
+
(is_defined && !::Brick.is_eager_loading) # Used to also have: && possible != self
|
1084
|
+
if ((!brick_root && (filename || possible.instance_of?(Class))) ||
|
1085
|
+
(possible.instance_of?(Module) && possible&.module_parent == self) ||
|
1086
|
+
(possible.instance_of?(Class) && possible == self)) && # Are we simply searching for ourselves?
|
1087
|
+
# Skip when what we found as `possible` is not related to the base class of an STI model
|
1088
|
+
(!sti_base || possible.is_a?(sti_base))
|
1089
|
+
return possible
|
1090
|
+
end
|
1068
1091
|
end
|
1069
1092
|
end
|
1070
1093
|
class_name = ::Brick.namify(requested)
|
@@ -1099,7 +1122,7 @@ Module.class_exec do
|
|
1099
1122
|
(plural_class_name = class_name.pluralize)].find { |s| Brick.db_schemas&.include?(s) }&.camelize ||
|
1100
1123
|
(::Brick.config.sti_namespace_prefixes&.key?("::#{class_name}::") && class_name) ||
|
1101
1124
|
(::Brick.config.table_name_prefixes.values.include?(class_name) && class_name))
|
1102
|
-
return self.const_get(schema_name) if self.const_defined?(schema_name)
|
1125
|
+
return self.const_get(schema_name) if !is_tnp_module && self.const_defined?(schema_name)
|
1103
1126
|
|
1104
1127
|
# Build out a module for the schema if it's namespaced
|
1105
1128
|
# schema_name = schema_name.camelize
|
@@ -1869,7 +1892,7 @@ class Object
|
|
1869
1892
|
# Convert any Filename objects with nil into an empty string so that #encode can be called on them
|
1870
1893
|
new_obj.serializable_hash.each do |k, v|
|
1871
1894
|
new_obj.send("#{k}=", ActiveStorage::Filename.new('')) if v.is_a?(ActiveStorage::Filename) && !v.instance_variable_get(:@filename)
|
1872
|
-
end
|
1895
|
+
end if Object.const_defined?('ActiveStorage')
|
1873
1896
|
end
|
1874
1897
|
instance_variable_set("@#{singular_table_name}".to_sym, new_obj)
|
1875
1898
|
end
|
@@ -2441,7 +2464,7 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
2441
2464
|
singular = rel_name.last
|
2442
2465
|
end
|
2443
2466
|
name_parts = if (tnp = ::Brick.config.table_name_prefixes
|
2444
|
-
|
2467
|
+
&.find { |k1, _v1| singular.start_with?(k1) && singular.length > k1.length }
|
2445
2468
|
).present?
|
2446
2469
|
v[:auto_prefixed_schema] = tnp.first
|
2447
2470
|
v[:resource] = rel_name.last[(tnp_length = tnp.first.length)..-1]
|
@@ -225,7 +225,7 @@ function linkSchemas() {
|
|
225
225
|
end
|
226
226
|
|
227
227
|
# When table names have specific prefixes, automatically place them in their own module with a table_name_prefix.
|
228
|
-
::Brick.table_name_prefixes
|
228
|
+
::Brick.config.table_name_prefixes ||= app.config.brick.fetch(:table_name_prefixes, {})
|
229
229
|
|
230
230
|
# Columns to treat as being metadata for purposes of identifying associative tables for has_many :through
|
231
231
|
::Brick.metadata_columns = app.config.brick.fetch(:metadata_columns, ['created_at', 'updated_at', 'deleted_at'])
|
@@ -625,6 +625,7 @@ window.addEventListener(\"popstate\", linkSchemas);
|
|
625
625
|
if (class_name = (resource_parts = resource_name.split('/')).last&.singularize)
|
626
626
|
resource_parts[-1] = class_name # Make sure the last part, defining the class name, is singular
|
627
627
|
begin
|
628
|
+
resource_parts.shift if resource_parts.first == ::Brick.config.path_prefix
|
628
629
|
if (model = Object.const_get(resource_parts.map(&:camelize).join('::')))&.is_a?(Class) && (
|
629
630
|
['index', 'show'].include?(find_args.first) || # Everything has index and show
|
630
631
|
# Only CUD stuff has create / update / destroy
|
@@ -652,7 +653,9 @@ window.addEventListener(\"popstate\", linkSchemas);
|
|
652
653
|
else
|
653
654
|
hm_assoc.active_record.name
|
654
655
|
end
|
655
|
-
|
656
|
+
# %%% Might only need hm_assoc.type and not the first part :)
|
657
|
+
type_col = hm_assoc.inverse_of&.foreign_type || hm_assoc.type
|
658
|
+
keys << [type_col, poly_type]
|
656
659
|
end
|
657
660
|
keys.to_h
|
658
661
|
end
|
@@ -1667,7 +1670,7 @@ end
|
|
1667
1670
|
<% if (assoc = @#{obj_name}.class.reflect_on_association(:#{hm_name})).macro == :has_one &&
|
1668
1671
|
assoc.options&.fetch(:through, nil).nil?
|
1669
1672
|
# In order to apply DSL properly, evaluate this HO the other way around as if it were as a BT
|
1670
|
-
collection = assoc.klass.where(assoc.foreign_key => @#{obj_name}.#{pk})
|
1673
|
+
collection = assoc.klass.where(assoc.foreign_key => #{pk.is_a?(String) ? "@#{obj_name}.#{pk}" : pk.map { |pk_part| "@#{obj_name}.#{pk_part}" }.inspect})
|
1671
1674
|
collection = collection.instance_exec(&assoc.scopes.first) if assoc.scopes.present?
|
1672
1675
|
if assoc.klass.name == 'ActiveStorage::Attachment'
|
1673
1676
|
br_descrip = begin
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -125,6 +125,7 @@ if Gem::Specification.all_names.any? { |g| g.start_with?('rails-') }
|
|
125
125
|
end
|
126
126
|
module Brick
|
127
127
|
ALL_API_ACTIONS = [:index, :show, :create, :update, :destroy]
|
128
|
+
CURRENCY_SYMBOLS = '$£¢₵€₠ƒ¥₿₩₪₹₫₴₱₲₳₸₺₼₽៛₡₢₣₤₥₦₧₨₭₮₯₰₶₷₻₾'
|
128
129
|
|
129
130
|
class << self
|
130
131
|
def sti_models
|
@@ -200,9 +201,20 @@ module Brick
|
|
200
201
|
end
|
201
202
|
|
202
203
|
def get_bts_and_hms(model)
|
204
|
+
model_cols = model.columns_hash
|
205
|
+
pk_type = if (mpk = model.primary_key).is_a?(Array)
|
206
|
+
# Composite keys should really use: model.primary_key.map { |pk_part| model_cols[pk_part].type }
|
207
|
+
model_cols[mpk.first].type
|
208
|
+
else
|
209
|
+
mpk && model_cols[mpk].type
|
210
|
+
end
|
203
211
|
bts, hms = model.reflect_on_all_associations.each_with_object([{}, {}]) do |a, s|
|
212
|
+
# %%% The time will come when we will support type checking of composite foreign keys!
|
213
|
+
# binding.pry if a.foreign_key.is_a?(Array)
|
204
214
|
next unless a.polymorphic? || (!a.belongs_to? && (through = a.options[:through])) ||
|
205
|
-
(a.klass && ::Brick.config.exclude_tables.exclude?(a.klass.table_name)
|
215
|
+
(a.klass && ::Brick.config.exclude_tables.exclude?(a.klass.table_name) &&
|
216
|
+
(!a.belongs_to? || model_cols[a.foreign_key]&.type == pk_type)
|
217
|
+
)
|
206
218
|
|
207
219
|
if a.belongs_to?
|
208
220
|
if a.polymorphic?
|
@@ -239,6 +251,15 @@ module Brick
|
|
239
251
|
puts "WARNING: HMT relationship :#{a.name} in model #{model.name} has invalid source :#{a.source_reflection_name}."
|
240
252
|
next
|
241
253
|
end
|
254
|
+
else
|
255
|
+
if !a.options.key?(:as) && a.klass.column_names.exclude?(a.foreign_key)
|
256
|
+
options = ", #{a.options.map { |k, v| "#{k.inspect} => #{v.inspect}" }.join(', ')}" if a.options.present?
|
257
|
+
puts "WARNING: Model #{model.name} has this association:
|
258
|
+
has_many :#{a.name}#{options}
|
259
|
+
which expects column #{a.foreign_key} to exist in table #{a.klass.table_name}. This column is missing."
|
260
|
+
next
|
261
|
+
|
262
|
+
end
|
242
263
|
end
|
243
264
|
s.last[a.name] = a
|
244
265
|
end
|
@@ -1661,7 +1682,8 @@ module ActiveRecord
|
|
1661
1682
|
relation.brick_links[link_path] = if child.table.is_a?(Arel::Nodes::TableAlias)
|
1662
1683
|
child.table.right
|
1663
1684
|
else
|
1664
|
-
result.first&.left&.table_alias || child.table_name
|
1685
|
+
# Was: result.first&.left&.table_alias || child.table_name
|
1686
|
+
child.table.table_alias || child.table_name
|
1665
1687
|
end
|
1666
1688
|
end
|
1667
1689
|
result
|
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.131
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lorin Thwaits
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-04-
|
11
|
+
date: 2023-04-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|