brick 1.0.130 → 1.0.131

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 902948e0d502bc9c1b604f3e99b975ab8c7d42c378888280d84dac6aef2aa7d0
4
- data.tar.gz: 82988754dcae3ccc67eb5997531b3fa218ecf364f076ecf221fac201412baff0
3
+ metadata.gz: 6e9356edd43a6af6120f30bfbcd520383f3ae700e6ff04be11ebdd3493852ef4
4
+ data.tar.gz: a099075c53acc9bf29c718043cc619b5ab4f895366f9c7ddd14d53c8f7f432b8
5
5
  SHA512:
6
- metadata.gz: 780184ebc02c020389bc2239e115e885df056fa6895ed32bd35b5315f2e55f86deb679f2966e7290118bc54f4d50478b4240d7d77470d27a5902af22948d83f1
7
- data.tar.gz: 39c37a9db2c7c392209491e1609f8ab4c2b64d27371452b60310d326bd462b5e653196697d0faf8f4bf801793400e073bf73f2ed72a38e9c66bd9b8e98d1e778
6
+ metadata.gz: 9f9df598bad9ce128a88f4fe364d568be8c38eee57e595024866d39a255b42f513a26adc68d64d14cdecd4b5d13fb7424935f17df7dbb41c3bda2ae31057a4c7
7
+ data.tar.gz: 845e5747a916a338ee494426e4ef0ac6fd5c65c3579df0210c8a80468887fac12103407acfbaee3659b3b45763f98ef0bd109935d70920b932b4fd41cc15fdc5
@@ -670,6 +670,7 @@ module ActiveRecord
670
670
  link_back = []
671
671
  # Track polymorphic type field if necessary
672
672
  if hm.source_reflection.options[:as]
673
+ # Might be able to simplify as: hm.source_reflection.type
673
674
  poly_ft = [hm.source_reflection.inverse_of.foreign_type, hmt_assoc.source_reflection.class_name]
674
675
  end
675
676
  # link_back << hm.source_reflection.inverse_of.name
@@ -753,7 +754,8 @@ module ActiveRecord
753
754
 
754
755
  pri_tbl = hm.active_record
755
756
  pri_key = hm.options[:primary_key] || pri_tbl.primary_key
756
- unless hm.klass.column_names.include?(pri_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
757
759
  nix << k
758
760
  next
759
761
  end
@@ -874,6 +876,12 @@ JOIN (SELECT #{hm_selects.map { |s| "#{'br_t0.' if from_clause}#{s}" }.join(', '
874
876
  def brick_list
875
877
  pks = klass.primary_key.is_a?(String) ? [klass.primary_key] : klass.primary_key
876
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
877
885
  # ActiveStorage compatibility
878
886
  selects << 'service_name' if klass.name == 'ActiveStorage::Blob' && ActiveStorage::Blob.columns_hash.key?('service_name')
879
887
  selects << 'blob_id' if klass.name == 'ActiveStorage::Attachment' && ActiveStorage::Attachment.columns_hash.key?('blob_id')
@@ -1013,16 +1021,17 @@ Module.class_exec do
1013
1021
  is_controller = requested.end_with?('Controller')
1014
1022
  # self.name is nil when a model name is requested in an .erb file
1015
1023
  if self.name && ::Brick.config.path_prefix
1016
- camelize_prefix = ::Brick.config.path_prefix.camelize
1024
+ split_self_name.shift if (split_self_name = self.name.split('::')).first.blank?
1017
1025
  # Asking for the prefix module?
1026
+ camelize_prefix = ::Brick.config.path_prefix.camelize
1018
1027
  if self == Object && requested == camelize_prefix
1019
1028
  Object.const_set(args.first, (built_module = Module.new))
1020
1029
  puts "module #{camelize_prefix}; end\n"
1021
1030
  return built_module
1022
- end
1023
- split_self_name.shift if (split_self_name = self.name.split('::')).first.blank?
1024
- 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
1025
1033
  split_self_name.shift # Remove the identified path prefix from the split name
1034
+ is_brick_prefix = true
1026
1035
  if is_controller
1027
1036
  brick_root = split_self_name.empty? ? self : camelize_prefix.constantize
1028
1037
  end
@@ -1055,26 +1064,30 @@ Module.class_exec do
1055
1064
  self
1056
1065
  end
1057
1066
  # puts "#{self.name} - #{args.first}"
1058
- desired_classname = (self == Object || !name) ? requested : "#{name}::#{requested}"
1059
- if ((is_defined = self.const_defined?(args.first)) && (possible = self.const_get(args.first)) &&
1060
- # Reset `possible` if it's a controller request that's not a perfect match
1061
- # Was: (possible = nil) but changed to #local_variable_set in order to suppress the "= should be ==" warning
1062
- (possible&.name == desired_classname || (is_controller && binding.local_variable_set(:possible, nil)))) ||
1063
- # Try to require the respective Ruby file
1064
- ((filename = ActiveSupport::Dependencies.search_for_file(desired_classname.underscore) ||
1065
- (self != Object && ActiveSupport::Dependencies.search_for_file((desired_classname = requested).underscore))
1066
- ) && (require_dependency(filename) || true) &&
1067
- ((possible = self.const_get(args.first)) && possible.name == desired_classname)
1068
- ) ||
1069
- # If any class has turned up so far (and we're not in the middle of eager loading)
1070
- # then return what we've found.
1071
- (is_defined && !::Brick.is_eager_loading) # Used to also have: && possible != self
1072
- if ((!brick_root && (filename || possible.instance_of?(Class))) ||
1073
- (possible.instance_of?(Module) && possible&.module_parent == self) ||
1074
- (possible.instance_of?(Class) && possible == self)) && # Are we simply searching for ourselves?
1075
- # Skip when what we found as `possible` is not related to the base class of an STI model
1076
- (!sti_base || possible.is_a?(sti_base))
1077
- return possible
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
1078
1091
  end
1079
1092
  end
1080
1093
  class_name = ::Brick.namify(requested)
@@ -1109,7 +1122,7 @@ Module.class_exec do
1109
1122
  (plural_class_name = class_name.pluralize)].find { |s| Brick.db_schemas&.include?(s) }&.camelize ||
1110
1123
  (::Brick.config.sti_namespace_prefixes&.key?("::#{class_name}::") && class_name) ||
1111
1124
  (::Brick.config.table_name_prefixes.values.include?(class_name) && class_name))
1112
- 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)
1113
1126
 
1114
1127
  # Build out a module for the schema if it's namespaced
1115
1128
  # schema_name = schema_name.camelize
@@ -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 = app.config.brick.fetch(: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
@@ -1669,7 +1670,7 @@ end
1669
1670
  <% if (assoc = @#{obj_name}.class.reflect_on_association(:#{hm_name})).macro == :has_one &&
1670
1671
  assoc.options&.fetch(:through, nil).nil?
1671
1672
  # In order to apply DSL properly, evaluate this HO the other way around as if it were as a BT
1672
- 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})
1673
1674
  collection = collection.instance_exec(&assoc.scopes.first) if assoc.scopes.present?
1674
1675
  if assoc.klass.name == 'ActiveStorage::Attachment'
1675
1676
  br_descrip = begin
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 130
8
+ TINY = 131
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
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
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.130
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-13 00:00:00.000000000 Z
11
+ date: 2023-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord