brick 1.0.89 → 1.0.90

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a94d71d50a84c847db5f2c34e5aba600502ecb60d4dc7752dc65ac21f4ffe41b
4
- data.tar.gz: 6f337f6220cf5989669497e85da0d4620861b1be6e4a35720a072698d866ebe2
3
+ metadata.gz: eca72d418715811a100a44a45b3cd054ca511ed280f1d1a6f344ddaa972c220c
4
+ data.tar.gz: d712ebb5dedf75da99d8d8720f4b89e29ea2e96b498b4a59540811f5e087231c
5
5
  SHA512:
6
- metadata.gz: 703fa83ad63f9da5f4431c05db9fee57843419b62283f92f39b7b4cf9397848177f10f57af7fc03f08cf503a392676adac272a04fe4ae6becbf0e0a5eb62c550
7
- data.tar.gz: 686c752bd2ed92de4f12c4afe27389d8a6cced25b47c5a18564c5afdf51199bd148f66ec5636ee8094a0cda5ae1ccafce31bc532a9d7d6a64c4cc968013f6af3
6
+ metadata.gz: 1b3d3941f4905b7a3ce1489a6f018d958331bd4c2970a5ba5034eb0fb81683febdc8a93562be5a1505afe6d6479fb1ed068a0f21d6ea80f24460e9e9267b8ea3
7
+ data.tar.gz: c3f61b68cd2ca5790f93b82010909f65913ccecb46df24786c83db362241092824db66833b72f03708560f23b7e87f64f12b180d8e4fb9ababba32bdb9b3f9df
@@ -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].map do |part|
131
- 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}\"." if klass.nil?
133
- part_sym
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.column_names.exclude?(parts.last) &&
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?
@@ -382,6 +383,23 @@ module ActiveRecord
382
383
  end
383
384
  end
384
385
 
386
+ module AttributeMethods
387
+ module ClassMethods
388
+ alias _brick_dangerous_attribute_method? dangerous_attribute_method?
389
+ # Bypass the error "ActiveRecord::DangerousAttributeError" if this object comes from a view.
390
+ # (Allows for column names such as 'attribute', 'delete', and 'update' to still work.)
391
+ def dangerous_attribute_method?(name)
392
+ if (is_dangerous = _brick_dangerous_attribute_method?(name)) && is_view?
393
+ if column_names.include?(name.to_s)
394
+ puts "WARNING: Column \"#{name}\" in view #{table_name} conflicts with a reserved ActiveRecord method name."
395
+ end
396
+ return false
397
+ end
398
+ is_dangerous
399
+ end
400
+ end
401
+ end
402
+
385
403
  class Relation
386
404
  attr_reader :_brick_chains, :_arel_applied_aliases
387
405
 
@@ -1058,7 +1076,7 @@ Module.class_exec do
1058
1076
  # elsif base_module != Object
1059
1077
  # module_parent.const_missing(*args)
1060
1078
  elsif Rails.respond_to?(:autoloaders) && # After finding nothing else, if Zeitwerk is enabled ...
1061
- (Rails::Autoloaders.respond_to?(:zeitwerk_enabled?) ? Rails::Autoloaders.zeitwerk_enabled? : true)
1079
+ (Rails::Autoloaders.respond_to?(:zeitwerk_enabled?) ? Rails::Autoloaders.zeitwerk_enabled? : true)
1062
1080
  self._brick_const_missing(*args) # ... rely solely on Zeitwerk.
1063
1081
  else # Classic mode
1064
1082
  unless (found = base_module._brick_const_missing(*args))
@@ -1268,7 +1286,7 @@ class Object
1268
1286
  # hm.first[:inverse][:assoc_name].to_sym
1269
1287
  options[:source] = hm.last.to_sym
1270
1288
  else
1271
- through = hm.first[:alternate_name].pluralize
1289
+ through = hm.first.fetch(:alternate_chosen_name, hm.first[:alternate_name])
1272
1290
  end
1273
1291
  singular_assoc_name = hm.first[:inverse][:assoc_name].singularize
1274
1292
  "#{singular_assoc_name}_#{hmt_fk}"
@@ -1689,12 +1707,13 @@ class Object
1689
1707
  hm_assoc[:alternate_name] != (source || name.underscore)
1690
1708
  plural = "#{hm_assoc[:assoc_name]}_#{ActiveSupport::Inflector.pluralize(hm_assoc[:alternate_name])}"
1691
1709
  new_alt_name = (hm_assoc[:alternate_name] == name.underscore) ? "#{hm_assoc[:assoc_name].singularize}_#{plural}" : plural
1710
+ # %%% In rare cases might even need to add a number at the end for uniqueness
1692
1711
  # uniq = 1
1693
1712
  # while same_name = relation[:fks].find { |x| x.last[:assoc_name] == hm_assoc[:assoc_name] && x.last != hm_assoc }
1694
1713
  # hm_assoc[:assoc_name] = "#{hm_assoc_name}_#{uniq += 1}"
1695
1714
  # end
1696
1715
  # puts new_alt_name
1697
- # hm_assoc[:assoc_name] = new_alt_name
1716
+ hm_assoc[:alternate_chosen_name] = new_alt_name
1698
1717
  [new_alt_name, true]
1699
1718
  else
1700
1719
  assoc_name = ::Brick.namify(hm_assoc[:inverse_table]).pluralize
@@ -818,7 +818,16 @@ erDiagram
818
818
  end # DutyFree data export and import
819
819
  # %%% Instead of our current "for Janet Leverling (Employee)" kind of link we previously had this code that did a "where x = 123" thing:
820
820
  # (where <%= @_brick_params.each_with_object([]) { |v, s| s << \"#\{v.first\} = #\{v.last.inspect\}\" }.join(', ') %>)
821
- +"#{css}
821
+ +"<html>
822
+ <head>
823
+ #{css}
824
+ <title>#{model_name} <%
825
+ if (description = (relation = Brick.relations[#{model_name}.table_name])&.fetch(:description, nil)).present?
826
+ %> - <%= description
827
+ %><% end
828
+ %></title>
829
+ </head>
830
+ <body>
822
831
  <p style=\"color: green\"><%= notice %></p>#{"
823
832
  <select id=\"schema\">#{schema_options}</select>" if ::Brick.config.schema_behavior[:multitenant] && ::Brick.db_schemas.length > 1}
824
833
  <select id=\"tbl\">#{table_options}</select>
@@ -826,7 +835,7 @@ erDiagram
826
835
  <td><h1>#{model_name}</h1></td>
827
836
  <td id=\"imgErd\" title=\"Show ERD\"></td>
828
837
  </tr></table>#{template_link}<%
829
- if (description = (relation = Brick.relations[#{model_name}.table_name])&.fetch(:description, nil)).present? %><%=
838
+ if description.present? %><%=
830
839
  description %><br><%
831
840
  end
832
841
  # FILTER PARAMETERS
@@ -988,7 +997,10 @@ erDiagram
988
997
  </table>
989
998
 
990
999
  #{"<hr><%= link_to \"New #{obj_name}\", new_#{path_obj_name}_path %>" unless @_brick_model.is_view?}
991
- #{script}"
1000
+ #{script}
1001
+ </body>
1002
+ </html>
1003
+ "
992
1004
 
993
1005
  when 'status'
994
1006
  if is_status
@@ -1061,7 +1073,14 @@ erDiagram
1061
1073
  end
1062
1074
 
1063
1075
  when 'show', 'new', 'update'
1064
- +"#{css}
1076
+ +"<html>
1077
+ <head>
1078
+ #{css}
1079
+ <title><%=
1080
+ page_title = (\"#{model_name}: #\{(obj = @#{obj_name})&.brick_descrip || controller_name}\")
1081
+ %></title>
1082
+ </head>
1083
+ <body>
1065
1084
 
1066
1085
  <svg id=\"revertTemplate\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"
1067
1086
  width=\"32px\" height=\"32px\" viewBox=\"0 0 512 512\" xml:space=\"preserve\">
@@ -1072,7 +1091,7 @@ erDiagram
1072
1091
  <p style=\"color: green\"><%= notice %></p>#{"
1073
1092
  <select id=\"schema\">#{schema_options}</select>" if ::Brick.config.schema_behavior[:multitenant] && ::Brick.db_schemas.length > 1}
1074
1093
  <select id=\"tbl\">#{table_options}</select>
1075
- <h1>#{model_name}: <%= (obj = @#{obj_name})&.brick_descrip || controller_name %></h1><%
1094
+ <h1><%= page_title %></h1><%
1076
1095
  if (description = (relation = Brick.relations[#{model_name}.table_name])&.fetch(:description, nil)) %><%=
1077
1096
  description %><br><%
1078
1097
  end
@@ -1236,7 +1255,10 @@ end
1236
1255
  "<%= 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
1256
  end}
1238
1257
  <% end %>
1239
- #{script}"
1258
+ #{script}
1259
+ </body>
1260
+ </html>
1261
+ "
1240
1262
 
1241
1263
  end
1242
1264
  inline << "
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 89
8
+ TINY = 90
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
@@ -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 if !a.polymorphic? && (a.klass.nil? || ::Brick.config.exclude_tables.include?(a.klass.table_name))
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
- case a.macro
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
- when :has_many, :has_one # This gets has_many as well as has_many :through
209
- # %%% weed out ones that don't have an available model to reference
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) }
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.89
4
+ version: 1.0.90
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-03 00:00:00.000000000 Z
11
+ date: 2022-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord