brick 1.0.223 → 1.0.225

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: 7358b611b9073f3fafe55e9d3ac4b5d19ebba01604607f7aaf51eaa1b514ef6b
4
- data.tar.gz: 29adea32add038493e6f65ab1d426b378214861d9e2a61c0892ffee1a65e55bd
3
+ metadata.gz: 7f82da7422196469fc96ed7e6a720404547125622e4a9221b762d2797ddfa1a1
4
+ data.tar.gz: 48db61484c3899a2ee44754979eca01442d1c396e2ae10df8c5bb707d45398fa
5
5
  SHA512:
6
- metadata.gz: c3c21da00d78d98e635c8986c939530fce1f9b18326d4c40c478cb48aa04bd52617c932eea9872f1142180de351d27936f16dd943cc955b3ad714db000800608
7
- data.tar.gz: 26ddbd8d7c7378448dadae1cf6d00dad47221fe5059012fc39c0bf6b1b4745ee9fa63f88e76888ff64e873a20d6a4322099817aaadf565a32254cf0e99911dc0
6
+ metadata.gz: 33e2eb178a7eb4e7c04ea47ee7cb14b732eb43918974ef189f7423615158acae66a6135ba43373cdc30fa6dffff83388e32f3f0610450f6ae46a66dd9e672176
7
+ data.tar.gz: e7f04e018e0f21780c2d1a6705a5f39b3a62321d7314fb5b3f0924c77ca11344c5a1928231ac39b32daa858e3411cdee9eb8c09d55992677f46384f2e474cdba
@@ -1658,7 +1658,7 @@ class Object
1658
1658
  end
1659
1659
  plural_class_name = ActiveSupport::Inflector.pluralize(model_name = class_name)
1660
1660
  # gsub is so that if it's namespaced then we turn the first part into what would be a schema name
1661
- singular_table_name = ::Brick.table_name_lookup[model_name] || ActiveSupport::Inflector.underscore(model_name).gsub('/', '.')
1661
+ singular_table_name = ::Brick.table_name_lookup&.fetch(model_name, nil) || ActiveSupport::Inflector.underscore(model_name).gsub('/', '.')
1662
1662
 
1663
1663
  if base_model
1664
1664
  table_name = base_model.table_name
@@ -2099,7 +2099,7 @@ class Object
2099
2099
  def build_controller(namespace, class_name, plural_class_name, model, relations)
2100
2100
  if (is_avo = (namespace.name == 'Avo' && Object.const_defined?('Avo')))
2101
2101
  # Basic Avo functionality is available via its own generic controller.
2102
- # (More information on https://docs.avohq.io/2.0/controllers.html)
2102
+ # (More information on https://docs.avohq.io/3.0/controllers.html)
2103
2103
  controller_base = Avo::ResourcesController
2104
2104
  end
2105
2105
  if !model&.table_exists? && (tn = model&.table_name)
@@ -2117,7 +2117,6 @@ class Object
2117
2117
  puts
2118
2118
  end
2119
2119
  table_name = model&.table_name || ActiveSupport::Inflector.underscore(plural_class_name)
2120
- singular_table_name = ActiveSupport::Inflector.singularize(ActiveSupport::Inflector.underscore(plural_class_name))
2121
2120
  pk = model&._brick_primary_key(relations.fetch(table_name, nil))
2122
2121
  is_postgres = ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
2123
2122
  is_mysql = ['Mysql2', 'Trilogy'].include?(ActiveRecord::Base.connection.adapter_name)
@@ -2142,7 +2141,7 @@ class Object
2142
2141
  cspd.select! { |val| val == "'self'" }
2143
2142
  cspd << style_value
2144
2143
  else
2145
- cspd << "'sha256-0Vb7j3kDGE3oNfwMpRLClTSCUo/q74bvbt3p6kG/gkM='"
2144
+ cspd << "'sha256-#{Base64.encode64(Digest.const_get(:SHA256).digest(::Brick::Rails::BRICK_CSS)).chomp}'"
2146
2145
  end
2147
2146
  cspd << 'https://cdn.jsdelivr.net'
2148
2147
  end
@@ -2279,7 +2278,9 @@ class Object
2279
2278
  end
2280
2279
 
2281
2280
  self.protect_from_forgery unless: -> { self.request.format.js? }
2282
- plural_table_name = table_name.split('.').last.pluralize
2281
+ tn_start = (table_name_split = table_name.split('.')).length > 1 ? -2 : -1
2282
+ plural_table_name = table_name_split[tn_start..-1].join('_').pluralize
2283
+ singular_table_name = plural_table_name.singularize
2283
2284
  unless is_avo
2284
2285
  self.define_method :index do
2285
2286
  request_ver = request.path.split('/')[-2]
@@ -2518,10 +2519,11 @@ class Object
2518
2519
  code << " def show\n"
2519
2520
  code << " #{find_by_name = "find_#{singular_table_name}"}\n"
2520
2521
  code << " end\n"
2522
+ find_obj = "find_#{singular_table_name}"
2521
2523
  self.define_method :show do
2522
2524
  _schema, @_is_show_schema_list = ::Brick.set_db_schema(params)
2523
2525
  _, singular_table_name = model.real_singular(params)
2524
- instance_variable_set("@#{singular_table_name}".to_sym, find_obj)
2526
+ instance_variable_set("@#{singular_table_name}".to_sym, send(find_obj))
2525
2527
  add_csp_hash("'unsafe-inline'")
2526
2528
  end
2527
2529
  end
@@ -2614,7 +2616,7 @@ class Object
2614
2616
  self.define_method :edit do
2615
2617
  _schema, @_is_show_schema_list = ::Brick.set_db_schema(params)
2616
2618
  _, singular_table_name = model.real_singular(params)
2617
- instance_variable_set("@#{singular_table_name}".to_sym, find_obj)
2619
+ instance_variable_set("@#{singular_table_name}".to_sym, send(find_obj))
2618
2620
  add_csp_hash
2619
2621
  end
2620
2622
 
@@ -2642,7 +2644,7 @@ class Object
2642
2644
  end
2643
2645
 
2644
2646
  _, singular_table_name = model.real_singular(params)
2645
- instance_variable_set("@#{singular_table_name}".to_sym, (obj = find_obj))
2647
+ instance_variable_set("@#{singular_table_name}".to_sym, (obj = send(find_obj)))
2646
2648
  upd_params = send(params_name_sym)
2647
2649
  json_overrides = ::Brick.config.json_columns&.fetch(table_name, nil)
2648
2650
  if model.respond_to?(:devise_modules)
@@ -2688,7 +2690,7 @@ class Object
2688
2690
  code << " end\n"
2689
2691
  self.define_method :destroy do
2690
2692
  ::Brick.set_db_schema(params)
2691
- if (obj = find_obj).send(:destroy)
2693
+ if (obj = send(find_obj)).send(:destroy)
2692
2694
  redirect_to send("#{model._brick_index}_path".to_sym)
2693
2695
  else
2694
2696
  redirect_to send("#{model._brick_index(:singular)}_path".to_sym, obj)
@@ -2699,11 +2701,11 @@ class Object
2699
2701
  code << "private\n" if pk.present? || is_need_params
2700
2702
 
2701
2703
  if pk.present?
2702
- code << " def find_#{singular_table_name}
2704
+ code << " def #{find_obj}
2703
2705
  id = params[:id]&.split(/[\\/,_]/)
2704
2706
  @#{singular_table_name} = #{model.name}.find(id.is_a?(Array) && id.length == 1 ? id.first : id)
2705
2707
  end\n"
2706
- self.define_method :find_obj do
2708
+ self.define_method(find_obj) do
2707
2709
  id = if pk.length == 1 # && model.columns_hash[pk.first]&.type == :string
2708
2710
  params[:id].gsub('^^sl^^', '/')
2709
2711
  else
@@ -2723,6 +2725,7 @@ class Object
2723
2725
  model.find(id_simplified)
2724
2726
  end
2725
2727
  end
2728
+ private find_obj
2726
2729
  end
2727
2730
 
2728
2731
  if is_need_params
@@ -3164,8 +3167,10 @@ module Brick
3164
3167
  begin
3165
3168
  if bt.key?(:polymorphic)
3166
3169
  pri_pk = for_pk
3167
- pri_tables = Brick.config.polymorphics["#{frn_tbl}.#{bt[:fk]}"]
3168
- .each_with_object(Hash.new { |h, k| h[k] = [] }) do |pri_class, s|
3170
+ pri_models = ((frn_class = Object.const_get(v[1][:class_name])).respond_to?(poly_types_method = "#{bt[:assoc_name]}_types") &&
3171
+ frn_class.send(poly_types_method) # Trust what was set by #delegated_type
3172
+ ) || Brick.config.polymorphics["#{frn_tbl}.#{bt[:fk]}"]
3173
+ pri_tables = pri_models.each_with_object(Hash.new { |h, k| h[k] = [] }) do |pri_class, s|
3169
3174
  s[Object.const_get(pri_class).table_name] << pri_class
3170
3175
  end
3171
3176
  fk_id_col = "#{bt[:fk]}_id"
@@ -106,6 +106,16 @@ function linkSchemas() {
106
106
  load inflections
107
107
  end
108
108
  require 'brick/join_array'
109
+
110
+ # Load it once at the start for Rails >= 7.2 ...
111
+ Module.class_exec &::Brick::ADD_CONST_MISSING if ActiveRecord.version >= Gem::Version.new('7.2.0')
112
+ # ... and also for Rails >= 5.0, whenever the app gets reloaded
113
+ if ::Rails.application.respond_to?(:reloader)
114
+ ::Rails.application.reloader.to_prepare { Module.class_exec &::Brick::ADD_CONST_MISSING }
115
+ else
116
+ Module.class_exec &::Brick::ADD_CONST_MISSING # Older Rails -- just load at the start
117
+ end
118
+
109
119
  # Now the Brick initializer since there may be important schema things configured
110
120
  if !::Brick.initializer_loaded && File.exist?(brick_initializer = ::Rails.root&.join('config/initializers/brick.rb') || '')
111
121
  ::Brick.initializer_loaded = load brick_initializer
@@ -180,12 +190,6 @@ function linkSchemas() {
180
190
  ::Brick.established_drf = "/#{::Brick.config.path_prefix}#{action[action.index('#')..-1]}"
181
191
  end
182
192
  end
183
-
184
- Module.class_exec &::Brick::ADD_CONST_MISSING # Load it once at the start ...
185
- # ... and also for Rails >= 5.0, whenever the app gets reloaded
186
- if ::Rails.application.respond_to?(:reloader)
187
- ::Rails.application.reloader.to_prepare { Module.class_exec &::Brick::ADD_CONST_MISSING }
188
- end
189
193
  end
190
194
 
191
195
  # After we're initialized and before running the rest of stuff, put our configuration in place
@@ -632,10 +636,17 @@ window.addEventListener(\"popstate\", linkSchemas);
632
636
 
633
637
  def path_keys(hm_assoc, fk_name, pk)
634
638
  pk.map!(&:to_sym)
635
- keys = if fk_name.is_a?(Array) && pk.is_a?(Array) # Composite keys?
636
- fk_name.zip(pk)
639
+ keys = if hm_assoc.macro == :has_and_belongs_to_many
640
+ # %%% Can a HABTM use composite keys?
641
+ # (If so then this should be rewritten to do a .zip() )
642
+ 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}.#{pk.first}", pk.first]]
637
644
  else
638
- [[fk_name, pk.length == 1 ? pk.first : pk.inspect]]
645
+ if fk_name.is_a?(Array) && pk.is_a?(Array) # Composite keys?
646
+ fk_name.zip(pk)
647
+ else
648
+ [[fk_name, pk.length == 1 ? pk.first : pk.inspect]]
649
+ end
639
650
  end
640
651
  if hm_assoc.options.key?(:as) && !(hmaar = hm_assoc.active_record).abstract_class?
641
652
  poly_type = if hmaar.column_names.include?(hmaar.inheritance_column)
@@ -680,7 +691,10 @@ window.addEventListener(\"popstate\", linkSchemas);
680
691
 
681
692
  if @_brick_model
682
693
  pk = @_brick_model._brick_primary_key(::Brick.relations.fetch((table_name = @_brick_model.table_name.split('.').last), nil))
683
- obj_name = model_name.split('::').last.underscore
694
+ rn_start = (res_name_split = model_name.split('::')).length > 1 ? -2 : -1
695
+ obj_name = res_name_split[rn_start..-1].join('_').singularize
696
+ res_name = obj_name.pluralize
697
+
684
698
  path_obj_name = @_brick_model._brick_index(:singular)
685
699
  table_name ||= obj_name.pluralize
686
700
  template_link = nil
@@ -689,7 +703,14 @@ window.addEventListener(\"popstate\", linkSchemas);
689
703
  skip_klass_hms = ::Brick.config.skip_index_hms[model_name] || {}
690
704
  hms_headers = hms.each_with_object([]) do |hm, s|
691
705
  hm_stuff = [(hm_assoc = hm.last),
692
- "H#{hm_assoc.macro == :has_one ? 'O' : 'M'}#{'T' if hm_assoc.options[:through]}",
706
+ "H#{case hm_assoc.macro
707
+ when :has_one
708
+ 'O'
709
+ when :has_and_belongs_to_many
710
+ 'ABTM'
711
+ else
712
+ 'M'
713
+ end}#{'T' if hm_assoc.options[:through]}",
693
714
  (assoc_name = hm.first)]
694
715
  hm_fk_name = if (through = hm_assoc.options[:through])
695
716
  next unless @_brick_model.instance_methods.include?(through) &&
@@ -789,9 +810,10 @@ window.addEventListener(\"popstate\", linkSchemas);
789
810
  ['Crosstab', is_crosstab]].each do |table_option, show_it|
790
811
  table_options << "<option value=\"#{prefix}brick_#{table_option.downcase}\">(#{table_option})</option>".html_safe if show_it
791
812
  end
792
- css = +''
813
+ css = +'<style>'
793
814
  css << ::Brick::Rails::BRICK_CSS
794
- css << "<script>
815
+ css << "</style>
816
+ <script>
795
817
  if (window.history.state && window.history.state.turbo)
796
818
  window.addEventListener(\"popstate\", function () { location.reload(true); });
797
819
  </script>
@@ -1022,7 +1044,7 @@ end %>#{"
1022
1044
  end
1023
1045
  \"<tr><td colspan=\\\"#\{td_count}\\\">Children: #\{child_links.join(' ')}</tr>\".html_safe
1024
1046
  end
1025
- %><%= if (page_num = @#{res_name = table_name.pluralize}&._brick_page_num)
1047
+ %><%= if (page_num = @#{res_name}&._brick_page_num)
1026
1048
  \"<tr><td colspan=\\\"#\{td_count}\\\">Page #\{page_num}</td></tr>\".html_safe
1027
1049
  end %></table>#{template_link}<%
1028
1050
  if description.present? %><span class=\"__brick\"><%=
@@ -76,8 +76,12 @@ module Brick::Rails::FormBuilder
76
76
  out << self.hidden_field(method.to_sym, html_options)
77
77
  out << "<trix-editor input=\"#{self.field_id(method)}\"></trix-editor>"
78
78
  end
79
- out << self.text_field(method.to_sym, html_options) if spit_out_text_field
80
- when :boolean
79
+ if spit_out_text_field
80
+ # %%% Need to update the max-width with javascript when page width is adjusted?
81
+ html_options.merge!(style: 'min-width: 154px;field-sizing: content;') # max-width: auto;
82
+ out << self.text_field(method.to_sym, html_options)
83
+ end
84
+ when :boolean
81
85
  out << self.check_box(method.to_sym)
82
86
  when :integer, :decimal, :float
83
87
  if model.respond_to?(:attribute_types) && (enum_type = model.attribute_types[method]).is_a?(ActiveRecord::Enum::EnumType)
@@ -517,7 +517,7 @@ module Brick::Rails::FormTags
517
517
 
518
518
  # All the standard CSS with teal colouration for use with Brick
519
519
  def brick_css(theme = nil)
520
- ::Brick::Rails::BRICK_CSS.html_safe
520
+ "<style>#{::Brick::Rails::BRICK_CSS}</style>".html_safe
521
521
  end
522
522
 
523
523
  # -----------------------------------------------------------------------------------------------
data/lib/brick/rails.rb CHANGED
@@ -167,7 +167,7 @@ erDiagram
167
167
  %> <%= \"#\{through_name} }o--|| #\{hm_name}\".html_safe %> : \"\"
168
168
  <%= \"#{model_short_name} }o..o{ #\{hm_name} : \\\"#\{hm.first}\\\"\".html_safe %><%
169
169
  else # has_many
170
- %> <%= \"#{model_short_name} ||--o{ #\{hm_name} : \\\"#\{
170
+ %> <%= \"#{model_short_name} #\{hm.last.macro == :has_and_belongs_to_many ? '}o' : '||'}--o{ #\{hm_name} : \\\"#\{
171
171
  hm.first.to_s unless (last_hm = hm.first.to_s).downcase == hm_class.name.underscore.pluralize.tr('/', '_')
172
172
  }\\\"\".html_safe %><%
173
173
  end %>
@@ -289,7 +289,7 @@ erDiagram
289
289
 
290
290
  # CONSTANTS
291
291
 
292
- BRICK_CSS = "<style>
292
+ BRICK_CSS = "
293
293
  #titleSticky {
294
294
  position: sticky;
295
295
  display: inline-block;
@@ -527,7 +527,6 @@ input+svg.revert {
527
527
  background-color: #004998;
528
528
  color: #FFF;
529
529
  }
530
- </style>
531
530
  "
532
531
 
533
532
  AVO_SVG = "<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 84 90\" height=\"30\" fill=\"#3096F7\">
@@ -53,7 +53,7 @@ module Brick
53
53
  # else
54
54
  # puts "#{' ' * ind}scope #{scope_options.inspect}"
55
55
  # end
56
- send(:scope, scope_options) do
56
+ send(:scope, **scope_options) do
57
57
  brick_namespace_create.call(path_names, res_name, options, ind + 1)
58
58
  end
59
59
  else
@@ -243,7 +243,7 @@ module Brick
243
243
  { :index => 'get', :create => 'post' }.each do |action, method|
244
244
  if actions.include?(action)
245
245
  # Normally goes to something like: /api/v1/employees
246
- send(method, "#{api_root}#{unversioned.tr('.', '/')}", { to: "#{controller_prefix}#{controller_name}##{action}" })
246
+ send(method, "#{api_root}#{unversioned.tr('.', '/')}", to: "#{controller_prefix}#{controller_name}##{action}")
247
247
  end
248
248
  end
249
249
  # %%% We do not yet surface the #show action
@@ -251,7 +251,7 @@ module Brick
251
251
  { :update => ['put', 'patch'], :destroy => ['delete'] }.each do |action, methods|
252
252
  if actions.include?(action)
253
253
  methods.each do |method|
254
- send(method, "#{api_root}#{unversioned.tr('.', '/')}/:#{id_col}", { to: "#{controller_prefix}#{controller_name}##{action}" })
254
+ send(method, "#{api_root}#{unversioned.tr('.', '/')}/:#{id_col}", to: "#{controller_prefix}#{controller_name}##{action}")
255
255
  end
256
256
  end
257
257
  end
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 223
8
+ TINY = 225
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
@@ -248,10 +248,14 @@ module Brick
248
248
 
249
249
  if a.belongs_to?
250
250
  if a.polymorphic?
251
- rel_poly_bt = relations[model.table_name][:fks].find { |_k, fk| fk[:assoc_name] == a.name.to_s }
252
- if (primary_tables = rel_poly_bt&.last&.fetch(:inverse_table, [])).is_a?(Array)
253
- models = rel_poly_bt[1][:polymorphic]&.map { |table| table.singularize.camelize.constantize }
254
- s.first[a.foreign_key.to_s] = [a.name, models, true]
251
+ if (pri_models = (model.respond_to?(poly_types_method = "#{a.name}_types") &&
252
+ model.send(poly_types_method)
253
+ ) ||
254
+ (rel_poly_bt = relations[model.table_name][:fks].find { |_k, fk| fk[:assoc_name] == a.name.to_s } &&
255
+ (rel_poly_bt[1][:polymorphic] || rel_poly_bt&.last&.fetch(:inverse_table, [])&.map { |table| table.singularize.camelize })
256
+ )
257
+ ).is_a?(Array)
258
+ s.first[a.foreign_key.to_s] = [a.name, pri_models.map(&:constantize), true]
255
259
  else
256
260
  # This will come up when using Devise invitable when invited_by_class_name is not
257
261
  # specified because in that circumstance it adds a polymorphic :invited_by association,
@@ -267,11 +271,19 @@ module Brick
267
271
  puts "Missing any real indication as to which models \"has_many\" this polymorphic BT in model #{a.active_record.name}:"
268
272
  puts " belongs_to :#{a.name}, polymorphic: true"
269
273
  else
270
- puts "Having analysed all currently-loaded models to infer the various polymorphic has_many associations for #{model.name}, here are the current results:"
271
- puts "::Brick.polymorphics = { \"#{model.table_name}.#{a.name}\" =>
274
+ puts "Having analyzed all currently-loaded models to infer the various polymorphic has_many associations,"
275
+ if ActiveRecord::Base.respond_to?(:delegated_type)
276
+ puts "in your #{model.name} model file, you can change this line:
277
+ belongs_to :#{a.name}#{a.options.map { |k, v| ", #{k}: #{v}" }.join}
278
+ to instead be this:
279
+ delegated_type :#{a.name}, types: #{hm_models.map(&:name).inspect}#{a.options.reject { |k| [:polymorphic, :inverse_of].include?(k) }.map { |k, v| ", #{k}: #{v}" }.join}\n"
280
+ else
281
+ puts "to support the #{model.name} model, you can add this into your brick.rb:
282
+ ::Brick.polymorphics = { \"#{model.table_name}.#{a.name}\" =>
272
283
  #{hm_models.map(&:name).inspect}
273
284
  }"
274
- puts 'If you add the above to your brick.rb, it will "cement" these options into place, and avoid this lookup process.'
285
+ puts "and it will \"cement\" these options into place, and avoid this lookup process.\n"
286
+ end
275
287
  s.first[a.foreign_key.to_s] = [a.name, hm_models, true]
276
288
  end
277
289
  end
@@ -297,7 +309,7 @@ module Brick
297
309
  puts " due to invalid source #{a.source_reflection_name.inspect}."
298
310
  next
299
311
  end
300
- else
312
+ elsif a.macro != :has_and_belongs_to_many
301
313
  this_fks = (this_fk = a.foreign_key).is_a?(Array) ? this_fk.uniq : [this_fk.to_s]
302
314
  if !a.options.key?(:as) && a.klass.table_exists? && (this_fks - a.klass.column_names).length.positive?
303
315
  options = ", #{a.options.map { |k, v| "#{k.inspect} => #{v.inspect}" }.join(', ')}" if a.options.present?
@@ -386,6 +386,10 @@ if ActiveRecord::Base.respond_to?(:brick_select) && !::Brick.initializer_loaded
386
386
  Brick.config.schema_behavior[:multitenant]&.fetch(:schema_to_analyse, nil).inspect}" :
387
387
  " # Brick.schema_behavior = { multitenant: { schema_to_analyse: 'engineering'"
388
388
  } } }
389
+ #{"
390
+ # # Note that if you have a real polymorphic model configured then it is better to set the list of classes up in the
391
+ # # model file itself with a line like:
392
+ # delegated_type :commentable, type: ['Post', 'Comment']" if ActiveRecord::Base.respond_to?(:delegated_type)}
389
393
 
390
394
  # # DEFAULT ROOT ROUTE
391
395
 
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.223
4
+ version: 1.0.225
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lorin Thwaits
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-12-13 00:00:00.000000000 Z
11
+ date: 2025-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord