brick 1.0.84 → 1.0.86

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: 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