brick 1.0.84 → 1.0.86

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: 07b4deda161c3a94822dd4c953d1c3983eb7c4eeed3106c7037a5f6b5c006f9d
4
- data.tar.gz: bd5bcd1255bd5e3c13da8abca6bc9b73b5cd17880f90bbbb6b3b6e01c7f9331d
3
+ metadata.gz: 67cdd41b9c4a3a235e4d88a151149a7c2c9345a4280efe31c3fbd983b65fbdd4
4
+ data.tar.gz: 12f80d33a0360cfa67fb703ed59b65b9216cafa07a18d9283baf9df584067896
5
5
  SHA512:
6
- metadata.gz: 0da12600c16ad515c1be1129940eba12e99754afebb206784384084dfee66c657ee2e6c9319f3b8f5d3a57c42f0f501ae55d967dd51b3f12b608579f98b5141d
7
- data.tar.gz: 75a9e6de7852fb5aab7c6b7a4a72e2e2af733ad18432fe91f04207138e6192dcbc716e5a38e18819d22cfe2370acdd55c87d25e54b49f86493e52b1f3625dfa3
6
+ metadata.gz: e95aefd208502dfa2ae724d178a29d15ccad4d00522ecbb865019823ba331c0d9f6e4026aea1b634f57f1d7945d8f522e35361d42d9de972698de91c0b9bd129
7
+ data.tar.gz: 99d0df87ae591bf836f6040aa237863fb1535774cb6fae515bb1c25edd284b4f37d5a1c01584138df81cfbb66a535ef8bec9aaf2550c96a42c02dee7e48aada1
@@ -10,12 +10,27 @@ unless ActiveRecord.respond_to?(:version)
10
10
  end
11
11
  end
12
12
 
13
- require 'action_view'
14
- # Older ActionView didn't have #version
15
- unless ActionView.respond_to?(:version)
16
- module ActionView
13
+ # ActiveSupport, ActionPack, and ActionView before 4.0 didn't have #version
14
+ unless ActiveSupport.respond_to?(:version)
15
+ module ActiveSupport
17
16
  def self.version
18
- ActionPack.version
17
+ ::Gem::Version.new(ActiveSupport::VERSION::STRING)
18
+ end
19
+ end
20
+ end
21
+ if Object.const_defined?('ActionPack')
22
+ unless ActionPack.respond_to?(:version)
23
+ module ActionPack
24
+ def self.version
25
+ ::Gem::Version.new(ActionPack::VERSION::STRING)
26
+ end
27
+ end
28
+ end
29
+ if Object.const_defined?('ActionView') && !ActionView.respond_to?(:version)
30
+ module ActionView
31
+ def self.version
32
+ ActionPack.version
33
+ end
19
34
  end
20
35
  end
21
36
  end
data/lib/brick/config.rb CHANGED
@@ -20,6 +20,23 @@ module Brick
20
20
  @serializer = Brick::Serializers::YAML
21
21
  end
22
22
 
23
+ def mode
24
+ @mutex.synchronize do
25
+ case @brick_mode
26
+ when nil, :development
27
+ (::Rails.env == 'development' || ENV.key?('BRICK')) ? :on : nil
28
+ when :diag_env
29
+ ENV.key?('BRICK') ? :on : nil
30
+ else
31
+ @brick_mode
32
+ end
33
+ end
34
+ end
35
+
36
+ def mode=(setting)
37
+ @mutex.synchronize { @brick_mode = setting unless @brick_mode == :on }
38
+ end
39
+
23
40
  # Any path prefixing to apply to all auto-generated Brick routes
24
41
  def path_prefix
25
42
  @mutex.synchronize { @path_prefix }
@@ -31,7 +48,8 @@ module Brick
31
48
 
32
49
  # Indicates whether Brick models are on or off. Default: true.
33
50
  def enable_models
34
- @mutex.synchronize { !!@enable_models }
51
+ brick_mode = mode
52
+ @mutex.synchronize { brick_mode == :on && (@enable_models.nil? || @enable_models) }
35
53
  end
36
54
 
37
55
  def enable_models=(enable)
@@ -40,7 +58,8 @@ module Brick
40
58
 
41
59
  # Indicates whether Brick controllers are on or off. Default: true.
42
60
  def enable_controllers
43
- @mutex.synchronize { !!@enable_controllers }
61
+ brick_mode = mode
62
+ @mutex.synchronize { brick_mode == :on && (@enable_controllers.nil? || @enable_controllers) }
44
63
  end
45
64
 
46
65
  def enable_controllers=(enable)
@@ -49,7 +68,8 @@ module Brick
49
68
 
50
69
  # Indicates whether Brick views are on or off. Default: true.
51
70
  def enable_views
52
- @mutex.synchronize { !!@enable_views }
71
+ brick_mode = mode
72
+ @mutex.synchronize { brick_mode == :on && (@enable_views.nil? || @enable_views) }
53
73
  end
54
74
 
55
75
  def enable_views=(enable)
@@ -58,7 +78,8 @@ module Brick
58
78
 
59
79
  # Indicates whether Brick routes are on or off. Default: true.
60
80
  def enable_routes
61
- @mutex.synchronize { !!@enable_routes }
81
+ brick_mode = mode
82
+ @mutex.synchronize { brick_mode == :on && (@enable_routes.nil? || @enable_routes) }
62
83
  end
63
84
 
64
85
  def enable_routes=(enable)
@@ -239,7 +239,7 @@ module ActiveRecord
239
239
  pk_alias = [pk_alias] unless pk_alias.is_a?(Array)
240
240
  id = []
241
241
  pk_alias.each do |pk_alias_part|
242
- if (pk_part = obj.send(pk_alias_part))
242
+ if (pk_part = obj.respond_to?(pk_alias_part) ? obj.send(pk_alias_part) : nil)
243
243
  id << pk_part
244
244
  end
245
245
  end
@@ -608,7 +608,11 @@ module ActiveRecord
608
608
  # %%% Need to support {user: :profile}
609
609
  next unless assoc_name.is_a?(Symbol)
610
610
 
611
- table_alias = shift_or_first(chains[klass = reflect_on_association(assoc_name)&.klass])
611
+ table_alias = if (chain = chains[klass = reflect_on_association(assoc_name)&.klass])
612
+ shift_or_first(chain)
613
+ else
614
+ klass.table_name # ActiveRecord < 4.2 can't (yet) use the cool chains thing
615
+ end
612
616
  _assoc_names[assoc_name] = [table_alias, klass]
613
617
  end
614
618
  end
@@ -706,7 +710,7 @@ module ActiveRecord
706
710
  join_clause = "LEFT OUTER
707
711
  JOIN (SELECT #{hm_selects.map { |s| "#{'br_t0.' if from_clause}#{s}" }.join(', ')}, COUNT(#{'DISTINCT ' if hm.options[:through]}#{count_column
708
712
  }) AS c_t_ FROM #{from_clause || hm_table_name} GROUP BY #{group_bys.join(', ')}) #{tbl_alias}"
709
- joins!("#{join_clause} ON #{on_clause.join(' AND ')}")
713
+ self.joins_values |= ["#{join_clause} ON #{on_clause.join(' AND ')}"] # Same as: joins!(...)
710
714
  end
711
715
  while (n = nix.pop)
712
716
  klass._br_hm_counts.delete(n)
@@ -723,7 +727,11 @@ JOIN (SELECT #{hm_selects.map { |s| "#{'br_t0.' if from_clause}#{s}" }.join(', '
723
727
  s["#{tbl_name}.#{v_parts.last}"] = v.last
724
728
  end
725
729
  end
726
- where!(wheres2)
730
+ if respond_to?(:where!)
731
+ where!(wheres2)
732
+ else # AR < 4.0
733
+ self.where_values << build_where(wheres2)
734
+ end
727
735
  end
728
736
  # Must parse the order_by and see if there are any symbols which refer to BT associations
729
737
  # or custom columns as they must be expanded to find the corresponding b_r_model__column
@@ -747,9 +755,10 @@ JOIN (SELECT #{hm_selects.map { |s| "#{'br_t0.' if from_clause}#{s}" }.join(', '
747
755
  selects << v if is_distinct
748
756
  end
749
757
  end
750
- order!(*final_order_by)
758
+ self.order_values |= final_order_by # Same as: order!(*final_order_by)
751
759
  end
752
- limit!(1000) # Don't want to get too carried away just yet
760
+ # Don't want to get too carried away just yet
761
+ self.limit_value = 1000 # Same as: limit!(1000)
753
762
  wheres unless wheres.empty? # Return the specific parameters that we did use
754
763
  end
755
764
 
@@ -766,7 +775,7 @@ JOIN (SELECT #{hm_selects.map { |s| "#{'br_t0.' if from_clause}#{s}" }.join(', '
766
775
 
767
776
  alias _brick_find_sti_class find_sti_class
768
777
  def find_sti_class(type_name)
769
- if ::Brick.sti_models.key?(type_name)
778
+ if ::Brick.sti_models.key?(type_name ||= name)
770
779
  _brick_find_sti_class(type_name)
771
780
  else
772
781
  # This auto-STI is more of a brute-force approach, building modules where needed
@@ -816,6 +825,8 @@ end
816
825
  if Object.const_defined?('ActionView')
817
826
  module ActionView::Helpers::FormTagHelper
818
827
  def link_to_brick(*args, **kwargs)
828
+ return unless ::Brick.config.mode == :on
829
+
819
830
  text = (args.first.is_a?(String) && args.first) || args[1]
820
831
  klass_or_obj = ((args.first.is_a?(ActiveRecord::Relation) ||
821
832
  args.first.is_a?(ActiveRecord::Base) ||
@@ -860,7 +871,7 @@ if Object.const_defined?('ActionView')
860
871
  pk = (klass.primary_key || ActiveRecord::Base.primary_key).to_sym
861
872
  # Used to also have this but it's a bit too permissive to identify a primary key: (path_params.length == 1 && path_params.values.first) ||
862
873
  if ((id = (path_params[pk] || path_params[:id] || path_params["#{klass.name.underscore}_id".to_sym])) && (obj = klass.find_by(pk => id))) ||
863
- (['show', 'edit'].include?(action_name) && (obj = klass.first))
874
+ (['show', 'edit', 'update', 'destroy'].include?(action_name) && (obj = klass.first))
864
875
  obj
865
876
  else
866
877
  # %%% If there is a HMT that refers to some ___id then try to identify an appropriate filter
@@ -933,8 +944,13 @@ if ActiveSupport::Dependencies.respond_to?(:autoload_module!) # %%% Only works w
933
944
  autoloaded_constants << qualified_name unless autoloaded_constants.include?(qualified_name)
934
945
  klass
935
946
  elsif (base_class = ::Brick.config.sti_namespace_prefixes&.fetch("::#{const_name}", nil)&.constantize)
936
- # Build subclass and place it into Object
937
- Object.const_set(const_name.to_sym, klass = Class.new(base_class))
947
+ begin
948
+ # Attempt to find an existing implementation for this subclass
949
+ base_class.module_parent.const_get(const_name)
950
+ rescue
951
+ # Build subclass and place it in the same module as its parent
952
+ base_class.module_parent.const_set(const_name.to_sym, klass = Class.new(base_class))
953
+ end
938
954
  else
939
955
  _brick_autoload_module!(*args)
940
956
  end
@@ -1507,9 +1523,10 @@ class Object
1507
1523
  ordering = params['_brick_order']&.split(',')&.map(&:to_sym) || Object.send(:default_ordering, table_name, pk)
1508
1524
  order_by, _ = model._brick_calculate_ordering(ordering, true) # Don't do the txt part
1509
1525
 
1510
- @_brick_params = (ar_relation = model.all).brick_select(params, (selects = []), order_by,
1511
- translations = {},
1512
- join_array = ::Brick::JoinArray.new)
1526
+ ar_relation = ActiveRecord.version < Gem::Version.new('4') ? model.preload : model.all
1527
+ @_brick_params = ar_relation.brick_select(params, (selects = []), order_by,
1528
+ translations = {},
1529
+ join_array = ::Brick::JoinArray.new)
1513
1530
  # %%% Add custom HM count columns
1514
1531
  # %%% What happens when the PK is composite?
1515
1532
  counts = model._br_hm_counts.each_with_object([]) do |v, s|
@@ -1521,7 +1538,8 @@ class Object
1521
1538
  "b_r_#{v.first}.c_t_ AS \"b_r_#{v.first}_ct\""
1522
1539
  end
1523
1540
  end
1524
- instance_variable_set("@#{table_name.pluralize}".to_sym, ar_relation.dup._select!(*selects, *counts))
1541
+ ar_select = ar_relation.respond_to?(:_select!) ? ar_relation.dup._select!(*selects, *counts) : ar_relation.select(selects + counts)
1542
+ instance_variable_set("@#{table_name.pluralize}".to_sym, ar_select)
1525
1543
  if namespace && (idx = lookup_context.prefixes.index(table_name))
1526
1544
  lookup_context.prefixes[idx] = "#{namespace.name.underscore}/#{lookup_context.prefixes[idx]}"
1527
1545
  end
@@ -1633,7 +1651,11 @@ class Object
1633
1651
  code << " end\n"
1634
1652
  self.define_method :destroy do
1635
1653
  ::Brick.set_db_schema(params)
1636
- instance_variable_set("@#{singular_table_name}".to_sym, find_obj.send(:destroy))
1654
+ if (obj = find_obj).send(:destroy)
1655
+ redirect_to send("#{model._brick_index}_path".to_sym)
1656
+ else
1657
+ redirect_to send("#{model._brick_index(:singular)}_path".to_sym, obj)
1658
+ end
1637
1659
  end
1638
1660
  end
1639
1661
 
@@ -1732,10 +1754,16 @@ end
1732
1754
  # Get info on all relations during first database connection
1733
1755
  # ==========================================================
1734
1756
 
1735
- module ActiveRecord::ConnectionHandling
1757
+ if ActiveRecord.const_defined?('ConnectionHandling')
1758
+ ActiveRecord::ConnectionHandling
1759
+ else
1760
+ ActiveRecord::ConnectionAdapters::ConnectionHandler
1761
+ end.class_exec do
1736
1762
  alias _brick_establish_connection establish_connection
1737
1763
  def establish_connection(*args)
1738
1764
  conn = _brick_establish_connection(*args)
1765
+ return conn unless ::Brick.config.mode == :on
1766
+
1739
1767
  begin
1740
1768
  # Overwrite SQLite's #begin_db_transaction so it opens in IMMEDIATE mode instead of
1741
1769
  # the default DEFERRED mode.
@@ -1866,7 +1894,7 @@ module ActiveRecord::ConnectionHandling
1866
1894
  case ActiveRecord::Base.connection.adapter_name
1867
1895
  when 'PostgreSQL', 'SQLite' # These bring back a hash for each row because the query uses column aliases
1868
1896
  # schema ||= 'public' if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
1869
- ActiveRecord::Base.retrieve_schema_and_tables(sql, is_postgres, is_mssql, schema).each do |r|
1897
+ retrieve_schema_and_tables(sql, is_postgres, is_mssql, schema).each do |r|
1870
1898
  # If Apartment gem lists the table as being associated with a non-tenanted model then use whatever it thinks
1871
1899
  # is the default schema, usually 'public'.
1872
1900
  schema_name = if ::Brick.config.schema_behavior[:multitenant]
@@ -1915,7 +1943,7 @@ WHERE c.owner IN (#{::Brick.db_schemas.keys.map { |s| "'#{s}'" }.join(', ')})
1915
1943
  ORDER BY 1, 2, c.internal_column_id, acc.position"
1916
1944
  ActiveRecord::Base.execute_sql(sql, *ar_tables)
1917
1945
  else
1918
- ActiveRecord::Base.retrieve_schema_and_tables(sql)
1946
+ retrieve_schema_and_tables(sql)
1919
1947
  end
1920
1948
 
1921
1949
  schema_and_tables.each do |r|
@@ -2016,6 +2044,7 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
2016
2044
  end
2017
2045
  ::Brick.is_oracle = true if ActiveRecord::Base.connection.adapter_name == 'OracleEnhanced'
2018
2046
  # ::Brick.default_schema ||= schema ||= 'public' if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
2047
+ ::Brick.default_schema ||= 'public' if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
2019
2048
  fk_references&.each do |fk|
2020
2049
  fk = fk.values unless fk.is_a?(Array)
2021
2050
  # Multitenancy makes things a little more general overall, except for non-tenanted tables
@@ -2113,7 +2142,7 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
2113
2142
  else
2114
2143
  'schema_migrations'
2115
2144
  end
2116
- ar_imtn = ActiveRecord.version >= ::Gem::Version.new('5.0') ? ActiveRecord::Base.internal_metadata_table_name : ''
2145
+ ar_imtn = ActiveRecord.version >= ::Gem::Version.new('5.0') ? ActiveRecord::Base.internal_metadata_table_name : 'ar_internal_metadata'
2117
2146
  [ar_smtn, ar_imtn]
2118
2147
  end
2119
2148
 
@@ -8,10 +8,16 @@ module Brick
8
8
  # `brick_enabled_for_controller`.
9
9
  module Controller
10
10
  def self.included(controller)
11
- controller.before_action(
12
- :set_brick_enabled_for_controller,
13
- :set_brick_controller_info
14
- )
11
+ if controller.respond_to?(:before_action)
12
+ controller.before_action(
13
+ :set_brick_enabled_for_controller,
14
+ :set_brick_controller_info
15
+ )
16
+ else
17
+ controller.before_filter(
18
+ :set_brick_enabled_for_controller,
19
+ :set_brick_controller_info
20
+ )
15
21
  end
16
22
 
17
23
  protected
@@ -103,12 +103,18 @@ module Brick
103
103
  unless (model_name = @_brick_model&.name) ||
104
104
  (is_status = ::Brick.config.add_status && args[0..1] == ['status', ['brick_gem']]) ||
105
105
  (is_orphans = ::Brick.config.add_orphans && args[0..1] == ['orphans', ['brick_gem']])
106
- if (possible_template = _brick_find_template(*args, **options))
106
+ if ActionView.version < ::Gem::Version.new('5.0') # %%% Not sure if this should be perhaps 4.2 instead
107
+ begin
108
+ if (possible_template = _brick_find_template(*args, **options))
109
+ return possible_template
110
+ end
111
+ rescue
112
+ end
113
+ elsif (possible_template = _brick_find_template(*args, **options))
107
114
  return possible_template
108
- else
109
- # Used to also have: ActionView.version < ::Gem::Version.new('5.0') &&
110
- model_name = (args[1].is_a?(Array) ? set_brick_model(args) : nil)&.name
111
115
  end
116
+ # Used to also have: ActionView.version < ::Gem::Version.new('5.0') &&
117
+ model_name = (args[1].is_a?(Array) ? set_brick_model(args) : nil)&.name
112
118
  end
113
119
 
114
120
  if @_brick_model
@@ -154,7 +160,7 @@ module Brick
154
160
  'nil'
155
161
  else
156
162
  # Postgres column names are limited to 63 characters
157
- "#{obj_name}.#{"b_r_#{assoc_name}_ct"[0..62]} || 0"
163
+ "#{obj_name}.#{"b_r_#{assoc_name}_ct"[0..62]}&.to_i || 0"
158
164
  end
159
165
  ", #{set_ct}, #{path_keys(hm_assoc, hm_fk_name, obj_name, pk)}"
160
166
  end
@@ -181,10 +187,15 @@ module Brick
181
187
  end
182
188
  end
183
189
 
184
- schema_options = ::Brick.db_schemas.keys.each_with_object(+'') { |v, s| s << "<option value=\"#{v}\">#{v}</option>" }.html_safe
190
+ apartment_default_schema = ::Brick.apartment_multitenant && Apartment.default_schema
191
+ schema_options = if ::Brick.apartment_multitenant &&
192
+ (cur_schema = Apartment::Tenant.current) != apartment_default_schema
193
+ "<option selected value=\"#{cur_schema}\">#{cur_schema}</option>"
194
+ else
195
+ ::Brick.db_schemas.keys.each_with_object(+'') { |v, s| s << "<option value=\"#{v}\">#{v}</option>" }
196
+ end.html_safe
185
197
  # %%% If we are not auto-creating controllers (or routes) then omit by default, and if enabled anyway, such as in a development
186
198
  # environment or whatever, then get either the controllers or routes list instead
187
- apartment_default_schema = ::Brick.apartment_multitenant && Apartment.default_schema
188
199
  prefix = "#{::Brick.config.path_prefix}/" if ::Brick.config.path_prefix
189
200
  table_options = (::Brick.relations.keys - ::Brick.config.exclude_tables).each_with_object({}) do |tbl, s|
190
201
  binding.pry if tbl.is_a?(Symbol)
@@ -329,6 +340,10 @@ a.big-arrow {
329
340
  color: red;
330
341
  white-space: nowrap;
331
342
  }
343
+ .danger {
344
+ background-color: red;
345
+ color: white;
346
+ }
332
347
 
333
348
  #revertTemplate {
334
349
  display: none;
@@ -446,7 +461,7 @@ var #{table_name}HtColumns;
446
461
  // This PageTransitionEvent fires when the page first loads, as well as after any other history
447
462
  // transition such as when using the browser's Back and Forward buttons.
448
463
  window.addEventListener(\"pageshow\", function() {
449
- if (schemaSelect) { // First drop-down is only present if multitenant
464
+ if (schemaSelect && schemaSelect.options.length > 1) { // First drop-down is only present if multitenant
450
465
  brickSchema = changeout(location.href, \"_brick_schema\");
451
466
  if (brickSchema) {
452
467
  [... document.getElementsByTagName(\"A\")].forEach(function (a) { a.href = changeout(a.href, \"_brick_schema\", brickSchema); });
@@ -910,12 +925,19 @@ erDiagram
910
925
  %><%= link_to(\"#\{bt_class} ##\{poly_id}\", send(\"#\{base_class_underscored}_path\".to_sym, poly_id)) if poly_id %><%
911
926
  else
912
927
  # binding.pry if @_brick_bt_descrip[bt.first][bt[1].first.first].nil?
913
- bt_txt = (bt_class = bt[1].first.first).brick_descrip(
928
+ bt_class = bt[1].first.first
929
+ descrips = @_brick_bt_descrip[bt.first][bt_class]
930
+ bt_id_col = if descrips.length == 1
931
+ [#{obj_name}.class.reflect_on_association(bt.first)&.foreign_key]
932
+ else
933
+ descrips.last
934
+ end
935
+ bt_txt = bt_class.brick_descrip(
914
936
  # 0..62 because Postgres column names are limited to 63 characters
915
- #{obj_name}, (descrips = @_brick_bt_descrip[bt.first][bt_class])[0..-2].map { |id| #{obj_name}.send(id.last[0..62]) }, (bt_id_col = descrips.last)
937
+ #{obj_name}, descrips[0..-2].map { |id| #{obj_name}.send(id.last[0..62]) }, bt_id_col
916
938
  )
917
939
  bt_txt ||= \"<span class=\\\"orphan\\\">&lt;&lt; Orphaned ID: #\{val} >></span>\".html_safe if val
918
- bt_id = bt_id_col.map { |id_col| #{obj_name}.send(id_col.to_sym) } %>
940
+ bt_id = bt_id_col&.map { |id_col| #{obj_name}.respond_to?(id_sym = id_col.to_sym) ? #{obj_name}.send(id_sym) : id_col } %>
919
941
  <%= bt_id&.first ? link_to(bt_txt, send(\"#\{bt_class.base_class._brick_index(:singular)}_path\".to_sym, bt_id)) : bt_txt %>
920
942
  <% end
921
943
  elsif (hms_col = hms_cols[col_name])
@@ -1163,6 +1185,7 @@ end
1163
1185
  <% end %>
1164
1186
 
1165
1187
  #{unless args.first == 'new'
1188
+ confirm_are_you_sure = ActionView.version < ::Gem::Version.new('7.0') ? "data: { confirm: 'Are you sure?' }" : "form: { data: { turbo_confirm: 'Are you sure?' } }"
1166
1189
  hms_headers.each_with_object(+'') do |hm, s|
1167
1190
  # %%% Would be able to remove this when multiple foreign keys to same destination becomes bulletproof
1168
1191
  next if hm.first.options[:through] && !hm.first.through_reflection
@@ -1173,7 +1196,7 @@ end
1173
1196
  s << "<table id=\"#{hm_name}\" class=\"shadow\">
1174
1197
  <tr><th>#{hm[3]}</th></tr>
1175
1198
  <% collection = @#{obj_name}.#{hm_name}
1176
- collection = collection.is_a?(ActiveRecord::Associations::CollectionProxy) ? collection.order(#{pk.inspect}) : [collection].compact
1199
+ collection = collection.is_a?(ActiveRecord::Associations::CollectionProxy) ? collection.order(#{pk.inspect}) : collection.to_a.compact
1177
1200
  if collection.empty? %>
1178
1201
  <tr><td>(none)</td></tr>
1179
1202
  <% else %>
@@ -1185,7 +1208,8 @@ end
1185
1208
  else
1186
1209
  s
1187
1210
  end
1188
- end
1211
+ end +
1212
+ "<%= 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} }) %>"
1189
1213
  end}
1190
1214
  <% end %>
1191
1215
  #{script}"
@@ -1193,7 +1217,7 @@ end}
1193
1217
  end
1194
1218
  inline << "
1195
1219
  <% if is_includes_dates %>
1196
- <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css\">
1220
+ <link rel=\"stylesheet\" type=\"text/css\" href=\"https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css\">
1197
1221
  <style>
1198
1222
  .flatpickr-calendar {
1199
1223
  background: #A0FFA0;
@@ -1207,6 +1231,11 @@ flatpickr(\".timepicker\", {enableTime: true, noCalendar: true});
1207
1231
  </script>
1208
1232
  <% end %>
1209
1233
 
1234
+ <% if false # is_includes_dropdowns %>
1235
+ <script src=\"https://cdnjs.cloudflare.com/ajax/libs/slim-select/1.27.1/slimselect.min.js\"></script>
1236
+ <link rel=\"stylesheet\" type=\"text/css\" href=\"https://cdnjs.cloudflare.com/ajax/libs/slim-select/1.27.1/slimselect.min.css\">
1237
+ <% end %>
1238
+
1210
1239
  <% if true # @_brick_erd
1211
1240
  %>
1212
1241
  <script>
data/lib/brick/util.rb CHANGED
@@ -84,6 +84,7 @@ module Brick
84
84
 
85
85
  def self._custom_require_dir
86
86
  unless (custom_require_dir = ::Brick::Util.instance_variable_get(:@_custom_require_dir))
87
+ require 'tmpdir'
87
88
  ::Brick::Util.instance_variable_set(:@_custom_require_dir, (custom_require_dir = Dir.mktmpdir))
88
89
  # So normal Ruby require will now pick this one up
89
90
  $LOAD_PATH.unshift(custom_require_dir)
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 84
8
+ TINY = 86
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
@@ -26,27 +26,38 @@ end
26
26
  require 'brick/util'
27
27
 
28
28
  # Allow ActiveRecord < 3.2 to work with Ruby 2.7 and later
29
- if (ruby_version = ::Gem::Version.new(RUBY_VERSION)) >= ::Gem::Version.new('2.7') &&
30
- ActiveRecord.version < ::Gem::Version.new('3.2')
31
- # Remove circular reference for "now"
32
- ::Brick::Util._patch_require(
33
- 'active_support/values/time_zone.rb', '/activesupport',
34
- [' def parse(str, now=now)',
35
- ' def parse(str, now=now())']
36
- )
37
- # Remove circular reference for "reflection" for ActiveRecord 3.1
38
- if ActiveRecord.version >= ::Gem::Version.new('3.1')
29
+ if (ruby_version = ::Gem::Version.new(RUBY_VERSION)) >= ::Gem::Version.new('2.7')
30
+ if ActiveRecord.version < ::Gem::Version.new('3.2')
31
+ # Remove circular reference for "now"
39
32
  ::Brick::Util._patch_require(
40
- 'active_record/associations/has_many_association.rb', '/activerecord',
41
- ['reflection = reflection)',
42
- 'reflection = reflection())'],
43
- :HasManyAssociation # Make sure the path for this guy is available to be autoloaded
33
+ 'active_support/values/time_zone.rb', '/activesupport',
34
+ [' def parse(str, now=now)',
35
+ ' def parse(str, now=now())']
44
36
  )
37
+ # Remove circular reference for "reflection" for ActiveRecord 3.1
38
+ if ActiveRecord.version >= ::Gem::Version.new('3.1')
39
+ ::Brick::Util._patch_require(
40
+ 'active_record/associations/has_many_association.rb', '/activerecord',
41
+ ['reflection = reflection)',
42
+ 'reflection = reflection())'],
43
+ :HasManyAssociation # Make sure the path for this guy is available to be autoloaded
44
+ )
45
+ end
45
46
  end
47
+
48
+ # # Create unfrozen route path in Rails 3.2
49
+ # if ActiveRecord.version < ::Gem::Version.new('4')
50
+ # ::Brick::Util._patch_require(
51
+ # 'action_dispatch/routing/route_set.rb', '/actiondispatch',
52
+ # ["script_name.chomp('/')).to_s",
53
+ # "script_name.chomp('/')).to_s.dup"],
54
+ # :RouteSet # Make sure the path for this guy is available to be autoloaded
55
+ # )
56
+ # end
46
57
  end
47
58
 
48
59
  # Add left_outer_join! to Associations::JoinDependency and Relation::QueryMethods
49
- if ActiveRecord.version < ::Gem::Version.new('5')
60
+ if ActiveRecord.version >= ::Gem::Version.new('4') && ActiveRecord.version < ::Gem::Version.new('5')
50
61
  ::Brick::Util._patch_require(
51
62
  'active_record/associations/join_dependency.rb', '/activerecord', # /associations
52
63
  ["def join_constraints(outer_joins)
@@ -126,7 +137,7 @@ module Brick
126
137
 
127
138
  def set_db_schema(params = nil)
128
139
  schema = (params ? params['_brick_schema'] : ::Brick.default_schema)
129
- if schema && ::Brick.db_schemas&.key?(schema)
140
+ chosen = if schema && ::Brick.db_schemas&.key?(schema)
130
141
  ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?;", schema)
131
142
  schema
132
143
  elsif ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
@@ -135,6 +146,7 @@ module Brick
135
146
  # ::Brick.apartment_multitenant && tbl_parts.first == Apartment.default_schema
136
147
  (orig_schema - ['pg_catalog']).first
137
148
  end
149
+ chosen == ::Brick.default_schema ? nil : chosen
138
150
  end
139
151
 
140
152
  # All tables and views (what Postgres calls "relations" including column and foreign key info)
@@ -207,7 +219,7 @@ module Brick
207
219
  skip_hms[through] = nil if hms[through] && model.is_brick?
208
220
  # End up with a hash of HMT names pointing to join-table associations
209
221
  model._br_associatives[hmt.first] = hms[through] # || hms["#{(opt = hmt.last.options)[:through].to_s.singularize}_#{opt[:source].to_s.pluralize}".to_sym]
210
- elsif hmt.last.inverse_of.nil?
222
+ elsif hmt.last.inverse_of.nil? && ActiveRecord.version >= ::Gem::Version.new('4.2')
211
223
  puts "SKIPPING #{hmt.last.name.inspect}"
212
224
  # %%% If we don't do this then below associative.name will find that associative is nil
213
225
  skip_hms[hmt.last.name] = nil
@@ -226,6 +238,11 @@ module Brick
226
238
  true
227
239
  end
228
240
 
241
+ # @api public
242
+ def mode=(setting)
243
+ Brick.config.mode = setting
244
+ end
245
+
229
246
  # Any path prefixing to apply to all auto-generated Brick routes
230
247
  # @api public
231
248
  def path_prefix=(path)
@@ -433,7 +450,7 @@ module Brick
433
450
  # This is attempted early if a brick initialiser file is found, and then again as a failsafe at the end of our engine's initialisation
434
451
  # %%% Maybe look for differences the second time 'round and just add new stuff instead of entirely deferring
435
452
  def load_additional_references
436
- return if @_additional_references_loaded
453
+ return if @_additional_references_loaded || ::Brick.config.mode != :on
437
454
 
438
455
  relations = ::Brick.relations
439
456
  if (ars = ::Brick.config.additional_references) || ::Brick.config.polymorphics
@@ -524,7 +541,11 @@ In config/initializers/brick.rb appropriate entries would look something like:
524
541
  ::Brick.is_eager_loading = true
525
542
  if ::ActiveSupport.version < ::Gem::Version.new('6') ||
526
543
  ::Rails.configuration.instance_variable_get(:@autoloader) == :classic
527
- ::Rails.configuration.eager_load_namespaces.select { |ns| ns < ::Rails::Application }.each(&:eager_load!)
544
+ if ::ActiveSupport.version < ::Gem::Version.new('4')
545
+ ::Rails.application.eager_load!
546
+ else
547
+ ::Rails.configuration.eager_load_namespaces.select { |ns| ns < ::Rails::Application }.each(&:eager_load!)
548
+ end
528
549
  else
529
550
  Zeitwerk::Loader.eager_load_all
530
551
  end
@@ -546,7 +567,8 @@ In config/initializers/brick.rb appropriate entries would look something like:
546
567
 
547
568
  module RouteSet
548
569
  def finalize!
549
- unless ::Rails.application.routes.named_routes.route_defined?(:brick_status_path)
570
+ # %%% Was: ::Rails.application.routes.named_routes.route_defined?(:brick_status_path)
571
+ unless ::Rails.application.routes.named_routes.names.include?(:brick_status)
550
572
  path_prefix = ::Brick.config.path_prefix
551
573
  existing_controllers = routes.each_with_object({}) do |r, s|
552
574
  c = r.defaults[:controller]
@@ -821,13 +843,21 @@ ActiveSupport.on_load(:active_record) do
821
843
  end
822
844
  end
823
845
 
824
- # This only gets added for ActiveRecord < 3.2
825
846
  module Reflection
847
+ # This only gets added for ActiveRecord < 3.2
826
848
  unless AssociationReflection.instance_methods.include?(:foreign_key)
827
849
  class AssociationReflection < MacroReflection
828
850
  alias foreign_key association_foreign_key
829
851
  end
830
852
  end
853
+ # And this for ActiveRecord < 4.0
854
+ unless AssociationReflection.instance_methods.include?(:polymorphic?)
855
+ class AssociationReflection < MacroReflection
856
+ def polymorphic?
857
+ options[:polymorphic]
858
+ end
859
+ end
860
+ end
831
861
  end
832
862
 
833
863
  # ActiveRecord 3.1 and 3.2 didn't try to bring in &block for the .extending() convenience thing
@@ -1006,6 +1036,7 @@ ActiveSupport.on_load(:active_record) do
1006
1036
  delegate :left_outer_joins, to: :all
1007
1037
  end
1008
1038
  class Relation
1039
+ alias :model :klass unless respond_to?(:model) # To support AR < 4.2
1009
1040
  unless MULTI_VALUE_METHODS.include?(:left_outer_joins)
1010
1041
  _multi_value_methods = MULTI_VALUE_METHODS + [:left_outer_joins]
1011
1042
  send(:remove_const, :MULTI_VALUE_METHODS)
@@ -136,10 +136,16 @@ module Brick
136
136
 
137
137
  create_file(filename, "# frozen_string_literal: true
138
138
 
139
- # # Settings for the Brick gem
140
- # # (By default this auto-creates models, controllers, views, and routes on-the-fly.)
139
+ # Settings for the Brick gem
140
+ # (By default this auto-creates models, controllers, views, and routes on-the-fly.)
141
141
 
142
142
  if Object.const_defined?('Brick')
143
+ # Mode -- generally :on or :off, or only in :development. Also available is :diag_env which enables only
144
+ # when the environment variable BRICK is set.
145
+ Brick.mode = :development
146
+ # Can be further overridden by placing this line in development.rb / test.rb / production.rb:
147
+ # # Brick.mode = :on # (or :off to entirely disable)
148
+
143
149
  # # Custom path prefix to apply to all auto-generated Brick routes. Also causes auto-generated controllers
144
150
  # # to be created inside a module with the same name.
145
151
  # ::Brick.path_prefix = 'admin'
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.84
4
+ version: 1.0.86
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-10-24 00:00:00.000000000 Z
11
+ date: 2022-10-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '3.1'
19
+ version: '3.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '3.1'
26
+ version: '3.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: fancy_gets
29
29
  requirement: !ruby/object:Gem::Requirement