brick 1.0.243 → 1.0.244

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: 00e544ab1972840fa5a6e9c3261fb65ed0591f677ad1cb9c1992dd7447bc3e06
4
- data.tar.gz: 54bdcb8c8834736a98b331e494011e798a9d3b5bbd912113a73391a7a8bf3e72
3
+ metadata.gz: 4de3ef8371e163df0913a1fe70d55666010abefcdcc77d26813a27ea3b72967f
4
+ data.tar.gz: 73dffd4bb0f5c5e9f57d1e19550cc212a67b4cc9636dd6eed53bee458cd155ee
5
5
  SHA512:
6
- metadata.gz: 51e3caffcc7e19b44ca7dba5ac75454a03a5eba7ee79c862e5288542d6695b47bdbeb1000fcc257e5d251c4b1e84f82420081367ad9b8e06446c699b5fd8bf4f
7
- data.tar.gz: 8a184a598c46f8162770a5b91b496cb56fc12d1ccfa6598185922a4a038e47ba3168bba24c8e9ccac764c6625a3bf309a9a5ab5022600ec883579630bbb7fd69
6
+ metadata.gz: 948aaae186933b70b69b8df65ac2081168edd4d3badc9cf7bcdfb2d2a49243be376bb70c3c15aef7e00fdbf42f5be5c51185a91e01e4728332e0e0a476382403
7
+ data.tar.gz: 500f395af03a898ed11ee8e3caad5fa0571568b19f1183a4f7b90793a8324e5d87870220b8a60b7e91d61e73ad7855d450a46711e8404c519bded7599b761866
@@ -146,6 +146,31 @@ module ActiveRecord
146
146
  self.primary_key.is_a?(Array) ? self.primary_key : [self.primary_key]
147
147
  end
148
148
 
149
+ def _brick_deserialized_value(obj, descrip_cols)
150
+ descrip_cols.map do |descrip_part|
151
+ # 0..62 because Postgres column names are limited to 63 characters
152
+ if (val = obj.send(descrip_part[-1][0..62])) &&
153
+ ActiveRecord::ConnectionAdapters::Column.instance_methods.include?(:cast_type)
154
+ cast_type = self.columns_hash[descrip_part[-2]]&.send(:cast_type)
155
+ val = cast_type.deserialize(val)
156
+ val = val.force_encoding('UTF-8') if val.is_a?(String)
157
+ end
158
+ val
159
+ end
160
+ end
161
+
162
+ def _brick_deserialized_id(obj, id_col)
163
+ id = []
164
+ self._pk_as_array.each_with_index do |pk_part, idx|
165
+ id << if obj.respond_to?(id_sym = id_col[idx].to_sym)
166
+ self._brick_deserialized_value(obj, [[pk_part, id_col[idx]]])&.first
167
+ else
168
+ id_col[idx]
169
+ end
170
+ end
171
+ id
172
+ end
173
+
149
174
  def _br_quoted_name(name)
150
175
  name = name.join('.') if name.is_a?(Array)
151
176
  if name == '*'
@@ -189,17 +214,22 @@ module ActiveRecord
189
214
 
190
215
  # Used to show a little prettier name for an object
191
216
  def brick_get_dsl
192
- # If there's no DSL yet specified, just try to find the first usable column on this model
193
- unless (dsl = ::Brick.config.model_descrips[name])
194
- skip_columns = _brick_get_fks + (::Brick.config.metadata_columns || []) + [primary_key]
195
- dsl = if table_exists? && (descrip_col = columns.find { |c| [:boolean, :binary, :xml].exclude?(c.type) && skip_columns.exclude?(c.name) })
196
- "[#{descrip_col.name}]"
197
- else
198
- "#{name} ##{_pk_as_array.map { |pk_part| "[#{pk_part}]" }.join(', ')}"
217
+ if ::Brick.config.model_descrips.key?(name)
218
+ ::Brick.config.model_descrips[name]
219
+ else
220
+ # If there's no DSL yet specified, just try to find the first usable column on this model
221
+ dsl = if table_exists?
222
+ skip_columns = _brick_get_fks + (::Brick.config.metadata_columns || []) + [primary_key]
223
+ if (descrip_col = columns.find { |c| c.type == :string && skip_columns.exclude?(c.name) })
224
+ "[#{descrip_col.name}]"
225
+ elsif (descrip_col = columns.find { |c| [:boolean, :binary, :xml].exclude?(c.type) && skip_columns.exclude?(c.name) })
226
+ "[#{descrip_col.name}]"
227
+ else
228
+ "#{name} ##{_pk_as_array.map { |pk_part| "[#{pk_part}]" }.join(', ')}"
229
+ end
199
230
  end
200
231
  ::Brick.config.model_descrips[name] = dsl
201
232
  end
202
- dsl
203
233
  end
204
234
 
205
235
  def _brick_monetized_attributes
@@ -1447,12 +1477,12 @@ end
1447
1477
  ) ||
1448
1478
 
1449
1479
  # Try to require the respective Ruby file
1450
- # ((filename = ActiveSupport::Dependencies.search_for_file(desired_classname.underscore)) &&
1451
- # (require_dependency(filename) || true) &&
1452
1480
  (!anonymous? && # Don't try to find classes first mentioned in .erb or .haml templates
1453
1481
  (filename = ActiveSupport::Dependencies.search_for_file(desired_classname.underscore) ||
1454
1482
  (self != Object && ActiveSupport::Dependencies.search_for_file((desired_classname = requested).underscore))
1455
- ) && (require_dependency(filename) || true) &&
1483
+ ) &&
1484
+ # Replicate the functionality of ActiveSupport::Depenencies#require_dependency to support Rails >= v9.0
1485
+ (((abspath = ActiveSupport::Dependencies.search_for_file(filename)) ? (require abspath) : (require filename)) || true) &&
1456
1486
  (filename != Module.instance_variable_get(:@_brick_last_filename) || # Avoid trying the same exact file twice in a row
1457
1487
  Module.instance_variable_set(:@_brick_last_filename, nil)) &&
1458
1488
  Module.instance_variable_set(:@_brick_last_filename, filename) &&
@@ -1833,7 +1863,7 @@ class Object
1833
1863
  end
1834
1864
 
1835
1865
  # Enable Elasticsearch based on the table name?
1836
- if (@_brick_es_crud = ::Brick.elasticsearch_models&.fetch(matching, nil))
1866
+ if (@_brick_es_crud = ::Brick.elasticsearch_models.is_a?(Hash) && ::Brick.elasticsearch_models&.fetch(matching, nil))
1837
1867
  include ::Elasticsearch::Model
1838
1868
  if @_brick_es_crud.index('i') # Enable auto-creation of indexes on import?
1839
1869
  class << self
@@ -2159,34 +2189,11 @@ class Object
2159
2189
  built_controller = Class.new(controller_base) do |new_controller_class|
2160
2190
  (namespace || ::Object).const_set(class_name.to_sym, new_controller_class)
2161
2191
 
2162
- # Add a hash for the inline style to the content-security-policy if one is present
2163
- self.define_method(:add_csp_hash) do |style_value = nil|
2164
- if request.respond_to?(:content_security_policy) && (csp = request.content_security_policy)
2165
- if (cspd = csp.directives.fetch('style-src'))
2166
- if style_value
2167
- if (nonce = ::ActionDispatch::ContentSecurityPolicy::Request::NONCE)
2168
- request.env[nonce] = '' # Generally 'action_dispatch.content_security_policy_nonce'
2169
- end
2170
- # Keep only self, if present, and also add this value
2171
- cspd.select! { |val| val == "'self'" }
2172
- cspd << style_value
2173
- else
2174
- cspd << "'sha256-#{Base64.encode64(Digest.const_get(:SHA256).digest(::Brick::Rails::BRICK_CSS)).chomp}'"
2175
- end
2176
- cspd << 'https://cdn.jsdelivr.net'
2177
- end
2178
- if (cspd = csp.directives.fetch('script-src'))
2179
- cspd << 'https://cdn.jsdelivr.net'
2180
- end
2181
- end
2182
- end
2183
-
2184
2192
  # Brick-specific pages
2185
2193
  case plural_class_name
2186
2194
  when 'BrickGem'
2187
2195
  self.define_method :status do
2188
2196
  instance_variable_set(:@resources, ::Brick.get_status_of_resources)
2189
- add_csp_hash
2190
2197
  end
2191
2198
  # # if ::Brick.config.add_schema
2192
2199
  # # Currently can only do adding columns
@@ -2197,7 +2204,6 @@ class Object
2197
2204
  # base_class.reset_column_information
2198
2205
  # ::Brick.relations[base_class.table_name]&.fetch(:cols, nil)&.[]=(col_name, [col_type, nil, false, false])
2199
2206
  # # instance_variable_set(:@schema, ::Brick.find_schema(::Brick.set_db_schema(params).first))
2200
- # add_csp_hash
2201
2207
  # end
2202
2208
  # end
2203
2209
 
@@ -2206,20 +2212,17 @@ class Object
2206
2212
  if (base_class = (model = params['modelName']&.constantize).base_class)
2207
2213
  args = params['args']
2208
2214
  record = base_class.create(args[0] => args[1], args[2] => args[3])
2209
- add_csp_hash
2210
2215
  render json: { data: record.id }
2211
2216
  end
2212
2217
  end
2213
2218
  self.define_method :unassociate do
2214
2219
  if (base_class = (model = params['modelName']&.constantize).base_class)
2215
2220
  base_class.find_by(base_class._pk_as_array&.first => params['id']).delete
2216
- add_csp_hash
2217
2221
  end
2218
2222
  end
2219
2223
 
2220
2224
  self.define_method :orphans do
2221
2225
  instance_variable_set(:@orphans, ::Brick.find_orphans(::Brick.set_db_schema(params).first))
2222
- add_csp_hash
2223
2226
  end
2224
2227
  self.define_method :crosstab do
2225
2228
  @relations = ::Brick.relations.each_with_object({}) do |r, s|
@@ -2460,7 +2463,16 @@ class Object
2460
2463
  if request.format == :csv # Asking for a template?
2461
2464
  require 'csv'
2462
2465
  exported_csv = CSV.generate(force_quotes: false) do |csv_out|
2463
- real_model.df_export(real_model.brick_import_template).each { |row| csv_out << row }
2466
+ real_model.df_export(true, real_model.brick_import_template, false, wheres, order_by).each do |row|
2467
+ row.each do |d|
2468
+ row.each_with_index do |d, idx|
2469
+ # "false" disallows HTML encoding the descriptions of binary content
2470
+ # Max length for text is only 10,000 characters
2471
+ row[idx] = ::Brick::Rails.hide_bcrypt(d, false, 10_000) if d.encoding != CSV::ConverterEncoding
2472
+ end
2473
+ end
2474
+ csv_out << row
2475
+ end
2464
2476
  end
2465
2477
  render inline: exported_csv, content_type: request.format
2466
2478
  return
@@ -2551,7 +2563,6 @@ class Object
2551
2563
  @_brick_hm_counts = real_model._br_hm_counts
2552
2564
  @_brick_join_array = join_array
2553
2565
  @_brick_erd = params['_brick_erd']&.to_i
2554
- add_csp_hash
2555
2566
  end
2556
2567
 
2557
2568
  _, order_by_txt = model._brick_calculate_ordering(default_ordering(table_name, pk, true)) if pk
@@ -2593,7 +2604,6 @@ class Object
2593
2604
  _schema, @_is_show_schema_list = ::Brick.set_db_schema(params)
2594
2605
  _, real_singular_table_name = model.real_singular(params)
2595
2606
  instance_variable_set("@#{real_singular_table_name}".to_sym, send(find_obj))
2596
- add_csp_hash("'unsafe-inline'")
2597
2607
  end
2598
2608
  end
2599
2609
 
@@ -2629,7 +2639,6 @@ class Object
2629
2639
  end if Object.const_defined?('ActiveStorage')
2630
2640
  end
2631
2641
  instance_variable_set("@#{real_singular_table_name}".to_sym, new_obj)
2632
- add_csp_hash
2633
2642
  end
2634
2643
 
2635
2644
  code << " def create\n"
@@ -2705,7 +2714,6 @@ class Object
2705
2714
  _schema, @_is_show_schema_list = ::Brick.set_db_schema(params)
2706
2715
  _, real_singular_table_name = model.real_singular(params)
2707
2716
  instance_variable_set("@#{real_singular_table_name}".to_sym, send(find_obj))
2708
- add_csp_hash
2709
2717
  end
2710
2718
 
2711
2719
  code << " def update\n"
@@ -640,7 +640,14 @@ window.addEventListener(\"popstate\", linkSchemas);
640
640
  keys = if hm_assoc.macro == :has_and_belongs_to_many
641
641
  # %%% Can a HABTM use composite keys?
642
642
  # (If so then this should be rewritten to do a .zip() )
643
- name_from_other_direction = hm_assoc.klass.reflect_on_all_associations.find { |a| a.join_table == hm_assoc.join_table }&.name
643
+ name_from_other_direction = hm_assoc.klass.reflect_on_all_associations.find do |a|
644
+ begin
645
+ a.join_table == hm_assoc.join_table
646
+ rescue NameError => ee
647
+ # Can be something like: Missing model class AssignedCard for the User#assigned_cards association. You can specify a different model class with the :class_name option.
648
+ # (Happens when referencing the Fizzy Filter model.)
649
+ end
650
+ end&.name
644
651
  [["#{name_from_other_direction}.#{pk.first}", pk.first]]
645
652
  else
646
653
  if fk_name.is_a?(Array) && pk.is_a?(Array) # Composite keys?
@@ -819,15 +826,56 @@ window.addEventListener(\"popstate\", linkSchemas);
819
826
  ['Crosstab', is_crosstab]].each do |table_option, show_it|
820
827
  table_options << "<option value=\"#{prefix}brick_#{table_option.downcase}\">(#{table_option})</option>".html_safe if show_it
821
828
  end
822
- css = +'<style>'
823
- css << ::Brick::Rails::BRICK_CSS
824
- css << "</style>
829
+ css = +"<style>#{::Brick::Rails::BRICK_CSS}</style>
825
830
  <script>
826
831
  if (window.history.state && window.history.state.turbo)
827
832
  window.addEventListener(\"popstate\", function () { location.reload(true); });
828
833
  </script>
829
834
 
830
835
  <%
836
+ if @_request.respond_to?(:content_security_policy)
837
+ @_request.env['_is_brick'] = true
838
+ if (csp = @_request.content_security_policy).instance_variables.exclude?(:@_brick_style_shas)
839
+ csp.instance_variable_set(:@_brick_style_shas, [
840
+ \"'sha256-#\{Base64.encode64(Digest.const_get(:SHA256).digest(::Brick::Rails::BRICK_CSS)).chomp}'\",
841
+ \"'sha256-#\{Base64.encode64(Digest.const_get(:SHA256).digest(::Brick::Rails::IN_APP_STYLE)).chomp}'\"
842
+ ])
843
+ end
844
+ if !@_request.respond_to?(:_brick_content_security_policy)
845
+ ::ActionDispatch::ContentSecurityPolicy::Request.module_exec do
846
+ alias :_brick_content_security_policy :content_security_policy
847
+ def content_security_policy
848
+ # Add appropriate hashes for inline styles to the content-security-policy if needed
849
+ if (cspd = (csp = _brick_content_security_policy).directives.fetch('style-src', nil)) && env['_is_brick']
850
+ cspd.select! { |val| val == \"'self'\" }
851
+ if params['action'] == 'show'
852
+ cspd << \"'unsafe-inline'\"
853
+ else
854
+ csp.instance_variable_get(:@_brick_style_shas).each { |s| cspd << s }
855
+ cspd << \"'unsafe-hashes'\"
856
+ end
857
+ cspd << 'https://cdn.jsdelivr.net'
858
+ end
859
+ if (cspsd = csp.directives.fetch('script-src', nil))
860
+ cspsd.select! { |val| val == \"'self'\" }
861
+ cspsd << \"'unsafe-inline'\"
862
+ cspsd << 'https://cdn.jsdelivr.net'
863
+ end
864
+ if (cspcd = csp.directives.fetch('connect-src', nil))
865
+ cspcd.select! { |val| val == \"'self'\" }
866
+ cspcd << 'https://cdn.jsdelivr.net'
867
+ end
868
+ csp
869
+ end
870
+
871
+ alias :_brick_content_security_policy_nonce :content_security_policy_nonce
872
+ def content_security_policy_nonce
873
+ _brick_content_security_policy_nonce unless env['_is_brick']
874
+ end
875
+ end
876
+ end
877
+ end
878
+
831
879
  # Accommodate composite primary keys that include strings with forward-slash characters
832
880
  def slashify(*vals)
833
881
  vals.map { |val_part| val_part.is_a?(String) ? val_part.gsub('/', '^^sl^^') : val_part }
@@ -1091,7 +1139,7 @@ end
1091
1139
  </script>
1092
1140
  <% end
1093
1141
  # SEARCH BOX
1094
- if @_brick_es&.index('r') # Must have at least Elasticsearch Read access %>
1142
+ if @_brick_es && @_brick_es&.index('r') # Must have at least Elasticsearch Read access %>
1095
1143
  <input type=\"text\" id=\"esSearch\" class=\"dimmed\">
1096
1144
  <script>
1097
1145
  var esSearch = document.getElementById(\"esSearch\");
@@ -1498,9 +1546,9 @@ end
1498
1546
  <tr><td<%= ' class=\"orphan\"'.html_safe if err_msg %>><%= err_msg || '(none)' %></td></tr>
1499
1547
  <% else
1500
1548
  collection2.each do |br_#{hm_singular_name}| %>
1501
- <tr><td><%= br_descrip = if (dc = descrip_cols&.first&.first&.last) && br_#{hm_singular_name}.respond_to?(dc)
1549
+ <tr><td><%= br_descrip = if br_#{hm_singular_name}.respond_to?(descrip_cols&.first&.first&.last)
1502
1550
  br_#{hm_singular_name}.brick_descrip(
1503
- descrip_cols&.first&.map { |col| br_#{hm_singular_name}.send(col.last) }
1551
+ #{hm.first.klass.name}._brick_deserialized_value(br_#{hm_singular_name}, descrip_cols&.first)
1504
1552
  )
1505
1553
  else # If the HM association has a scope, might not have picked up our SELECT detail
1506
1554
  pks = (klass = br_#{hm_singular_name}.class).primary_key
@@ -150,12 +150,11 @@ module Brick::Rails::FormTags
150
150
  end
151
151
  end
152
152
  br_descrip_args = [obj]
153
- # 0..62 because Postgres column names are limited to 63 characters
154
- br_descrip_args += [descrips[0..-2].map { |id| obj.send(id.last[0..62]) }, bt_id_col] if descrips
153
+ br_descrip_args += [bt_class._brick_deserialized_value(obj, descrips[0..-2]), bt_id_col] if descrips
155
154
  bt_txt = bt_class.brick_descrip(*br_descrip_args)
156
155
  bt_txt = ::Brick::Rails.display_binary(bt_txt).html_safe if bt_txt&.encoding&.name == 'ASCII-8BIT'
157
156
  bt_txt ||= "<span class=\"orphan\">&lt;&lt; Orphaned ID: #{val} >></span>" if val
158
- bt_id = bt_id_col&.map { |id_col| obj.respond_to?(id_sym = id_col.to_sym) ? obj.send(id_sym) : id_col }
157
+ bt_id = bt_class._brick_deserialized_id(obj, bt_id_col)
159
158
  out << (bt_id&.first ? link_to(bt_txt, send("#{bt_class.base_class._brick_index(:singular)}_path".to_sym, bt_id)) : bt_txt || '')
160
159
  end
161
160
  elsif (hms_col = hms_cols[col_name])
@@ -165,15 +164,16 @@ module Brick::Rails::FormTags
165
164
  hm_klass = (col = cols[col_name])[1]
166
165
  if col[2] == 'HO'
167
166
  descrips = bt_descrip[col_name.to_sym][hm_klass]
168
- if (ho_id = (ho_id_col = descrips.last).map { |id_col| obj.send(id_col.to_sym) })&.first
167
+ if (descrip_parts = hm_klass._brick_deserialized_value(obj, descrips[0..-2]))&.first
169
168
  ho_txt = if hm_klass.name == 'ActiveStorage::Attachment'
170
169
  begin
171
170
  ::Brick::Rails.display_binary(obj.send(col[3])&.blob&.download)&.html_safe
172
171
  rescue
173
172
  end
174
173
  else
175
- hm_klass.brick_descrip(obj, descrips[0..-2].map { |id| obj.send(id.last[0..62]) }, ho_id_col)
174
+ hm_klass.brick_descrip(obj, descrip_parts, ho_id_col = descrips.last)
176
175
  end
176
+ ho_id = hm_klass._brick_deserialized_id(obj, ho_id_col)
177
177
  out << link_to(ho_txt, send("#{hm_klass.base_class._brick_index(:singular)}_path".to_sym, ho_id))
178
178
  end
179
179
  elsif obj.respond_to?(ct_col = hms_col[1].to_sym) && (ct = obj.send(ct_col)&.to_i)&.positive?
@@ -267,11 +267,15 @@ module Brick::Rails::FormTags
267
267
  { sql_type: 'binary', type: :files }
268
268
  elsif rtans&.key?(k) # has_rich_text
269
269
  k = rtans[k]
270
- { sql_type: 'varchar', type: :text }
270
+ { sql_type: ActiveRecord::Base.connection.adapter_name == 'SQLite' ? 'string' : 'varchar', type: :text }
271
271
  end
272
- col = (ActiveRecord::ConnectionAdapters::Column.new(
273
- '', nil, ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(**kwargs)
274
- )) if kwargs
272
+ if kwargs
273
+ last_params = [nil, ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(**kwargs)]
274
+ # Rails 8.1 introduces the "cast_type" parameter coming in second after the name, making a total of 4 parameters
275
+ # (See: https://github.com/rails/rails/commit/9ad36e067222478090b36a985090475bb03e398c)
276
+ last_params.unshift(ActiveRecord::Type.lookup(kwargs[:sql_type].to_sym)) if ActiveRecord::ConnectionAdapters::Column.instance_methods.include?(:cast_type)
277
+ col = ActiveRecord::ConnectionAdapters::Column.new('', *last_params)
278
+ end
275
279
  end
276
280
  val = obj.attributes[k]
277
281
  out << "
@@ -309,7 +313,7 @@ module Brick::Rails::FormTags
309
313
  collection&.brick_(:each) do |obj|
310
314
  option_detail << [
311
315
  obj.brick_descrip(
312
- descrip_cols&.first&.map { |col2| obj.send(col2.last) },
316
+ bt_class._brick_deserialized_value(obj, descrip_cols&.first),
313
317
  obj_pk
314
318
  ), obj.send(obj_pk)
315
319
  ]
data/lib/brick/rails.rb CHANGED
@@ -179,7 +179,7 @@ erDiagram
179
179
  'timestamp without time zone' => 'timestamp',
180
180
  'timestamp with time zone' => 'timestamp',
181
181
  'time without time zone' => 'time',
182
- 'time with time zone' => 'time' }[dt] || dt&.tr(' ', '_') || 'int'
182
+ 'time with time zone' => 'time' }[dt] || dt&.tr(' (', '_').tr(')', '') || 'int'
183
183
  end
184
184
  callbacks.merge({#{model_short_name.inspect} => ::#{model.name}}).each do |cb_k, cb_class|
185
185
  cb_relation = ::Brick.relations[cb_class.table_name]
@@ -541,10 +541,10 @@ input+svg.revert {
541
541
 
542
542
  AA_PNG = "<img src=\"data:image/png;base64,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\">
543
543
  "
544
-
544
+ IN_APP_STYLE = 'fill:rgb(31,147,209);'
545
545
  IN_APP = "<svg height=\"36px\" viewBox=\"0 0 214 274\" xmlns=\"http://www.w3.org/2000/svg\">
546
546
  <g transform=\"matrix(4.16667,0,0,4.16667,-1049.47,-789.371)\">
547
- <path d=\"M281.386,193.134L287.086,193.134C287.433,193.134 287.716,193.417 287.716,193.764C287.716,194.11 287.433,194.394 287.086,194.394L281.386,194.394C281.04,194.394 280.756,194.11 280.756,193.764C280.756,193.417 281.04,193.134 281.386,193.134ZM284.252,245.638C282.456,245.638 281.008,247.086 281.008,248.851C281.008,250.645 282.456,252.094 284.252,252.094C286.047,252.094 287.496,250.645 287.496,248.851C287.496,247.086 286.047,245.638 284.252,245.638ZM284.252,246.331C282.835,246.331 281.701,247.465 281.701,248.851C281.701,250.268 282.835,251.401 284.252,251.401C285.638,251.401 286.803,250.268 286.803,248.851C286.803,247.465 285.638,246.331 284.252,246.331ZM275.843,208.63L287.559,218.11L275.843,227.622L275.843,221.858L251.874,221.858L251.874,214.394L275.843,214.394L275.843,208.63ZM278.866,239.906L278.866,233.102C278.866,232.851 278.677,232.693 278.456,232.693L271.622,232.693C271.401,232.693 271.212,232.851 271.212,233.102L271.212,239.906C271.212,240.157 271.401,240.314 271.622,240.314L278.456,240.314C278.677,240.314 278.866,240.157 278.866,239.906ZM280.41,233.102L280.41,239.906C280.41,240.157 280.599,240.314 280.819,240.314L287.653,240.314C287.874,240.314 288.063,240.157 288.063,239.906L288.063,233.102C288.063,232.851 287.874,232.693 287.653,232.693L280.819,232.693C280.599,232.693 280.41,232.851 280.41,233.102ZM289.606,233.102L289.606,239.906C289.606,240.157 289.795,240.314 290.047,240.314L296.851,240.314C297.071,240.314 297.26,240.157 297.26,239.906L297.26,233.102C297.26,232.851 297.071,232.693 296.851,232.693L290.047,232.693C289.795,232.693 289.606,232.851 289.606,233.102ZM269.197,189.449L299.276,189.449C301.354,189.449 303.055,191.149 303.055,193.197L303.055,251.275C303.055,253.355 301.354,255.055 299.276,255.055L269.197,255.055C267.118,255.055 265.449,253.355 265.449,251.275L265.449,223.496L267.842,223.496L267.842,242.488L300.63,242.488L300.63,198.394L267.842,198.394L267.842,212.725L265.449,212.725L265.449,193.197C265.449,191.149 267.118,189.449 269.197,189.449Z\" style=\"fill:rgb(31,147,209);\"/>
547
+ <path d=\"M281.386,193.134L287.086,193.134C287.433,193.134 287.716,193.417 287.716,193.764C287.716,194.11 287.433,194.394 287.086,194.394L281.386,194.394C281.04,194.394 280.756,194.11 280.756,193.764C280.756,193.417 281.04,193.134 281.386,193.134ZM284.252,245.638C282.456,245.638 281.008,247.086 281.008,248.851C281.008,250.645 282.456,252.094 284.252,252.094C286.047,252.094 287.496,250.645 287.496,248.851C287.496,247.086 286.047,245.638 284.252,245.638ZM284.252,246.331C282.835,246.331 281.701,247.465 281.701,248.851C281.701,250.268 282.835,251.401 284.252,251.401C285.638,251.401 286.803,250.268 286.803,248.851C286.803,247.465 285.638,246.331 284.252,246.331ZM275.843,208.63L287.559,218.11L275.843,227.622L275.843,221.858L251.874,221.858L251.874,214.394L275.843,214.394L275.843,208.63ZM278.866,239.906L278.866,233.102C278.866,232.851 278.677,232.693 278.456,232.693L271.622,232.693C271.401,232.693 271.212,232.851 271.212,233.102L271.212,239.906C271.212,240.157 271.401,240.314 271.622,240.314L278.456,240.314C278.677,240.314 278.866,240.157 278.866,239.906ZM280.41,233.102L280.41,239.906C280.41,240.157 280.599,240.314 280.819,240.314L287.653,240.314C287.874,240.314 288.063,240.157 288.063,239.906L288.063,233.102C288.063,232.851 287.874,232.693 287.653,232.693L280.819,232.693C280.599,232.693 280.41,232.851 280.41,233.102ZM289.606,233.102L289.606,239.906C289.606,240.157 289.795,240.314 290.047,240.314L296.851,240.314C297.071,240.314 297.26,240.157 297.26,239.906L297.26,233.102C297.26,232.851 297.071,232.693 296.851,232.693L290.047,232.693C289.795,232.693 289.606,232.851 289.606,233.102ZM269.197,189.449L299.276,189.449C301.354,189.449 303.055,191.149 303.055,193.197L303.055,251.275C303.055,253.355 301.354,255.055 299.276,255.055L269.197,255.055C267.118,255.055 265.449,253.355 265.449,251.275L265.449,223.496L267.842,223.496L267.842,242.488L300.63,242.488L300.63,198.394L267.842,198.394L267.842,212.725L265.449,212.725L265.449,193.197C265.449,191.149 267.118,189.449 269.197,189.449Z\" style=\"#{IN_APP_STYLE}\"/>
548
548
  </g>
549
549
  </svg>"
550
550
  end
@@ -517,7 +517,7 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
517
517
  end
518
518
  end
519
519
 
520
- if (ems = ::Brick.elasticsearch_models)
520
+ if (ems = ::Brick.elasticsearch_models && Object.const_defined?('Elastic'))
521
521
  access = case ems
522
522
  when Hash, String # Hash is a list of resource names and ES permissions such as 'r' or 'icr'
523
523
  ems
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 243
8
+ TINY = 244
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
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.243
4
+ version: 1.0.244
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lorin Thwaits
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-04-13 00:00:00.000000000 Z
11
+ date: 2026-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord