brick 1.0.186 → 1.0.187
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 +4 -4
- data/lib/brick/compatibility.rb +1 -1
- data/lib/brick/extensions.rb +77 -65
- data/lib/brick/frameworks/rails/engine.rb +1 -1
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +23 -11
- data/lib/generators/brick/install_generator.rb +4 -0
- data/lib/generators/brick/migration_builder.rb +1 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72ed0bc43d9ca9ae52dd6641bd5ba400bcb9a4fdb4e13953f931f2b7e1f0d46a
|
4
|
+
data.tar.gz: e5e56338e6e980ccfd733697e4cc9efaa8929e38b7f154c8d668ddc784bd55bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06321d9f6ca977150dcc5458d85cb3a329955bbe961b26a273581392e8219bebbc669ad3373d2c57030b0c9b6df07e5c8cef0bdb6bcb7f14379e3ddf73ddb23e
|
7
|
+
data.tar.gz: d3432a3ba5983e1ac69d9dde0c5fb6a186d838e32007e0db5ca0af2497f4e918c7f58d9c10db23218c2c7fd605a64e86b50ab8002130845f993fae3a6232a08c
|
data/lib/brick/compatibility.rb
CHANGED
@@ -160,7 +160,7 @@ if ActiveRecord.version < ::Gem::Version.new('5.0') && ::Gem::Version.new(RUBY_V
|
|
160
160
|
if ::Gem::Version.new(RUBY_VERSION) >= ::Gem::Version.new('3.1')
|
161
161
|
# @@schemes fix for global_id gem < 1.0
|
162
162
|
URI.class_variable_set(:@@schemes, {}) unless URI.class_variables.include?(:@@schemes)
|
163
|
-
if Gem::
|
163
|
+
if Gem::Dependency.new('puma').matching_specs.present?
|
164
164
|
require 'rack/handler/puma'
|
165
165
|
module Rack::Handler::Puma
|
166
166
|
class << self
|
data/lib/brick/extensions.rb
CHANGED
@@ -96,38 +96,60 @@ module ActiveRecord
|
|
96
96
|
end
|
97
97
|
columns_hash.keys.map(&:to_sym) + (rtans || [])
|
98
98
|
end
|
99
|
-
end
|
100
99
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
if relation && pk.present?
|
112
|
-
@_brick_primary_key ||= pk.any? { |pk_part| !relation[:cols].key?(pk_part) } ? [] : pk
|
113
|
-
else # No definitive key yet, so return what we can without setting the instance variable
|
114
|
-
pk
|
100
|
+
def _br_quoted_name(name)
|
101
|
+
if name == '*'
|
102
|
+
name
|
103
|
+
elsif is_mysql
|
104
|
+
"`#{name.gsub('.', '`.`')}`"
|
105
|
+
elsif is_postgres || is_mssql
|
106
|
+
"\"#{name.gsub('.', '"."')}\""
|
107
|
+
else
|
108
|
+
name
|
109
|
+
end
|
115
110
|
end
|
116
|
-
end
|
117
111
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
112
|
+
def is_postgres
|
113
|
+
@is_postgres ||= connection.adapter_name == 'PostgreSQL'
|
114
|
+
end
|
115
|
+
def is_mysql
|
116
|
+
@is_mysql ||= ['Mysql2', 'Trilogy'].include?(connection.adapter_name)
|
117
|
+
end
|
118
|
+
def is_mssql
|
119
|
+
@is_mssql ||= connection.adapter_name == 'SQLServer'
|
120
|
+
end
|
121
|
+
|
122
|
+
def _brick_primary_key(relation = nil)
|
123
|
+
return @_brick_primary_key if instance_variable_defined?(:@_brick_primary_key)
|
124
|
+
|
125
|
+
pk = begin
|
126
|
+
primary_key.is_a?(String) ? [primary_key] : primary_key.dup || []
|
127
|
+
rescue
|
128
|
+
[]
|
129
|
+
end
|
130
|
+
pk.map! { |pk_part| pk_part =~ /^[A-Z0-9_]+$/ ? pk_part.downcase : pk_part } unless connection.adapter_name == 'MySQL2'
|
131
|
+
# Just return [] if we're missing any part of the primary key. (PK is usually just "id")
|
132
|
+
if relation && pk.present?
|
133
|
+
@_brick_primary_key ||= pk.any? { |pk_part| !relation[:cols].key?(pk_part) } ? [] : pk
|
134
|
+
else # No definitive key yet, so return what we can without setting the instance variable
|
135
|
+
pk
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Used to show a little prettier name for an object
|
140
|
+
def brick_get_dsl
|
141
|
+
# If there's no DSL yet specified, just try to find the first usable column on this model
|
142
|
+
unless (dsl = ::Brick.config.model_descrips[name])
|
143
|
+
skip_columns = _brick_get_fks + (::Brick.config.metadata_columns || []) + [primary_key]
|
144
|
+
dsl = if (descrip_col = columns.find { |c| [:boolean, :binary, :xml].exclude?(c.type) && skip_columns.exclude?(c.name) })
|
145
|
+
"[#{descrip_col.name}]"
|
146
|
+
elsif (pk_parts = self.primary_key.is_a?(Array) ? self.primary_key : [self.primary_key])
|
147
|
+
"#{name} ##{pk_parts.map { |pk_part| "[#{pk_part}]" }.join(', ')}"
|
148
|
+
end
|
149
|
+
::Brick.config.model_descrips[name] = dsl
|
150
|
+
end
|
151
|
+
dsl
|
129
152
|
end
|
130
|
-
dsl
|
131
153
|
end
|
132
154
|
|
133
155
|
def self.brick_parse_dsl(join_array = nil, prefix = [], translations = {}, is_polymorphic = false, dsl = nil, emit_dsl = false)
|
@@ -420,15 +442,18 @@ module ActiveRecord
|
|
420
442
|
end
|
421
443
|
|
422
444
|
def self._brick_calculate_ordering(ordering, is_do_txt = true)
|
423
|
-
quoted_table_name = table_name.split('.').map { |x| "\"#{x}\"" }.join('.')
|
424
445
|
order_by_txt = [] if is_do_txt
|
425
446
|
ordering = [ordering] if ordering && !ordering.is_a?(Array)
|
426
447
|
order_by = ordering&.each_with_object([]) do |ord_part, s| # %%% If a term is also used as an eqi-condition in the WHERE clause, it can be omitted from ORDER BY
|
427
448
|
case ord_part
|
428
449
|
when String
|
429
|
-
|
430
|
-
|
431
|
-
|
450
|
+
if ord_part.index('^^^')
|
451
|
+
ord_expr = ord_part.gsub('^^^', _br_quoted_name(table_name))
|
452
|
+
s << Arel.sql(ord_expr)
|
453
|
+
else
|
454
|
+
s << Arel.sql(_br_quoted_name(ord_expr))
|
455
|
+
end
|
456
|
+
order_by_txt&.<<("Arel.sql(#{ord_expr.inspect})")
|
432
457
|
else # Expecting only Symbol
|
433
458
|
ord_part = ord_part.to_s
|
434
459
|
if ord_part[0] == '-' # First char '-' means descending order
|
@@ -438,15 +463,14 @@ module ActiveRecord
|
|
438
463
|
if ord_part[0] == '~' # Char '~' means order NULLs as highest values instead of lowest
|
439
464
|
ord_part.slice!(0)
|
440
465
|
# (Unfortunately SQLServer does not support NULLS FIRST / NULLS LAST, so leave them out.)
|
441
|
-
is_nulls_switch =
|
442
|
-
when 'PostgreSQL', 'OracleEnhanced', 'SQLite'
|
443
|
-
:pg
|
444
|
-
when 'Mysql2', 'Trilogy'
|
466
|
+
is_nulls_switch = if is_mysql
|
445
467
|
:mysql
|
468
|
+
else # PostgreSQL, OracleEnhanced, SQLite
|
469
|
+
:pg
|
446
470
|
end
|
447
471
|
end
|
448
472
|
if _br_hm_counts.key?(ord_part_sym = ord_part.to_sym)
|
449
|
-
ord_part =
|
473
|
+
ord_part = _br_quoted_name("b_r_#{ord_part}_ct")
|
450
474
|
elsif _br_bt_descrip.key?(ord_part_sym)
|
451
475
|
ord_part = _br_bt_descrip.fetch(ord_part_sym, nil)&.first&.last&.first&.last&.dup
|
452
476
|
elsif !_br_cust_cols.key?(ord_part_sym) && !column_names.include?(ord_part)
|
@@ -1080,28 +1104,6 @@ Might want to add this in your brick.rb:
|
|
1080
1104
|
def shift_or_first(ary)
|
1081
1105
|
ary.length > 1 ? ary.shift : ary.first
|
1082
1106
|
end
|
1083
|
-
|
1084
|
-
def _br_quoted_name(name)
|
1085
|
-
if name == '*'
|
1086
|
-
name
|
1087
|
-
elsif is_mysql
|
1088
|
-
"`#{name.gsub('.', '`.`')}`"
|
1089
|
-
elsif is_postgres || is_mssql
|
1090
|
-
"\"#{(name).gsub('.', '"."')}\""
|
1091
|
-
else
|
1092
|
-
name
|
1093
|
-
end
|
1094
|
-
end
|
1095
|
-
|
1096
|
-
def is_postgres
|
1097
|
-
@is_postgres ||= ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
|
1098
|
-
end
|
1099
|
-
def is_mysql
|
1100
|
-
@is_mysql ||= ['Mysql2', 'Trilogy'].include?(ActiveRecord::Base.connection.adapter_name)
|
1101
|
-
end
|
1102
|
-
def is_mssql
|
1103
|
-
@is_mssql ||= ActiveRecord::Base.connection.adapter_name == 'SQLServer'
|
1104
|
-
end
|
1105
1107
|
end
|
1106
1108
|
|
1107
1109
|
module Inheritance
|
@@ -1505,7 +1507,8 @@ class Object
|
|
1505
1507
|
schema_name = ::Brick.apartment_default_tenant
|
1506
1508
|
end
|
1507
1509
|
# Maybe, just maybe there's a database table that will satisfy this need
|
1508
|
-
|
1510
|
+
matching = ::Brick.table_name_lookup&.fetch(class_name, nil)
|
1511
|
+
if (matching ||= [table_name, singular_table_name, plural_class_name, model_name, table_name.titleize].find { |m| relations.key?(schema_name ? "#{schema_name}.#{m}" : m) })
|
1509
1512
|
build_model_worker(schema_name, inheritable_name, model_name, singular_table_name, table_name, relations, matching)
|
1510
1513
|
end
|
1511
1514
|
end
|
@@ -1711,7 +1714,7 @@ class Object
|
|
1711
1714
|
# options[:class_name] = hm.first[:inverse_table].singularize.camelize
|
1712
1715
|
# options[:foreign_key] = hm.first[:fk].to_sym
|
1713
1716
|
far_assoc = relations[hm.first[:inverse_table]][:fks].find { |_k, v| v[:assoc_name] == hm[1] }
|
1714
|
-
options[:class_name] = far_assoc.last[:inverse_table].
|
1717
|
+
options[:class_name] = ::Brick.namify(far_assoc.last[:inverse_table], :underscore).camelize
|
1715
1718
|
options[:foreign_key] = far_assoc.last[:fk].to_sym
|
1716
1719
|
end
|
1717
1720
|
options[:source] ||= hm[1].to_sym unless hmt_name.singularize == hm[1]
|
@@ -1798,7 +1801,9 @@ class Object
|
|
1798
1801
|
::Brick.config.schema_behavior[:multitenant] && singular_table_parts.first == 'public'
|
1799
1802
|
singular_table_parts.shift
|
1800
1803
|
end
|
1801
|
-
options[:class_name] = "::#{assoc[:primary_class]&.name ||
|
1804
|
+
options[:class_name] = "::#{assoc[:primary_class]&.name ||
|
1805
|
+
singular_table_parts.map { |p| ::Brick.namify(p, :underscore).camelize}.join('::')
|
1806
|
+
}" if need_class_name
|
1802
1807
|
if need_fk # Funky foreign key?
|
1803
1808
|
options_fk_key = :foreign_key
|
1804
1809
|
if assoc[:fk].is_a?(Array)
|
@@ -2547,10 +2552,14 @@ class Object
|
|
2547
2552
|
[new_alt_name, true]
|
2548
2553
|
else
|
2549
2554
|
assoc_name = ::Brick.namify(hm_assoc[:inverse_table]).pluralize
|
2550
|
-
|
2551
|
-
|
2555
|
+
assoc_parts = assoc_name.split('.')
|
2556
|
+
if (needs_class = assoc_parts.length > 1) # If there is a schema name present, use a downcased version for the :has_many
|
2552
2557
|
assoc_parts[0].downcase! if assoc_parts[0] =~ /^[A-Z0-9_]+$/
|
2553
2558
|
assoc_name = assoc_parts.join('.')
|
2559
|
+
else
|
2560
|
+
class_name_parts = ::Brick.namify(hm_assoc[:inverse_table], :underscore).split('.')
|
2561
|
+
real_name = class_name_parts.map(&:camelize).join('::')
|
2562
|
+
needs_class = (real_name != hm_assoc[:inverse_table].camelize)
|
2554
2563
|
end
|
2555
2564
|
# hm_assoc[:assoc_name] = assoc_name
|
2556
2565
|
[assoc_name, needs_class]
|
@@ -2960,6 +2969,7 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
2960
2969
|
end
|
2961
2970
|
end
|
2962
2971
|
|
2972
|
+
table_name_lookup = (::Brick.table_name_lookup ||= {})
|
2963
2973
|
relations.each do |k, v|
|
2964
2974
|
next if k.is_a?(Symbol)
|
2965
2975
|
|
@@ -2981,7 +2991,9 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
2981
2991
|
v[:resource] = rel_name.last
|
2982
2992
|
[singular]
|
2983
2993
|
end
|
2984
|
-
v[:class_name] = (schema_names + name_parts).map(
|
2994
|
+
v[:class_name] = (schema_names + name_parts).map { |p| ::Brick.namify(p, :underscore).camelize }.join('::')
|
2995
|
+
# Track anything that's out-of-the-ordinary
|
2996
|
+
table_name_lookup[v[:class_name]] = k unless v[:class_name].underscore.pluralize == k
|
2985
2997
|
end
|
2986
2998
|
::Brick.load_additional_references if ::Brick.initializer_loaded
|
2987
2999
|
|
@@ -636,7 +636,7 @@ window.addEventListener(\"popstate\", linkSchemas);
|
|
636
636
|
resource_parts[-1] = class_name # Make sure the last part, defining the class name, is singular
|
637
637
|
begin
|
638
638
|
resource_parts.shift if resource_parts.first == ::Brick.config.path_prefix
|
639
|
-
if (model = Object.const_get(resource_parts.map(
|
639
|
+
if (model = Object.const_get(resource_parts.map { |p| ::Brick.namify(p, :underscore).camelize }.join('::')))&.is_a?(Class) && (
|
640
640
|
['index', 'show'].include?(find_args.first) || # Everything has index and show
|
641
641
|
# Only CUD stuff has create / update / destroy
|
642
642
|
(!model.is_view? && ['new', 'create', 'edit', 'update', 'destroy'].include?(find_args.first))
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -89,7 +89,7 @@ end
|
|
89
89
|
# is first established), and then automatically creates models, controllers, views,
|
90
90
|
# and routes based on those available relations.
|
91
91
|
require 'brick/config'
|
92
|
-
if Gem::
|
92
|
+
if Gem::Dependency.new('rails').matching_specs.present?
|
93
93
|
require 'rails'
|
94
94
|
require 'brick/frameworks/rails'
|
95
95
|
end
|
@@ -108,7 +108,8 @@ module Brick
|
|
108
108
|
|
109
109
|
attr_accessor :default_schema, :db_schemas, :test_schema,
|
110
110
|
:routes_done, :established_drf,
|
111
|
-
:is_oracle, :is_eager_loading, :auto_models, :initializer_loaded
|
111
|
+
:is_oracle, :is_eager_loading, :auto_models, :initializer_loaded,
|
112
|
+
:table_name_lookup
|
112
113
|
::Brick.auto_models = []
|
113
114
|
|
114
115
|
def get_possible_schemas
|
@@ -213,12 +214,19 @@ module Brick
|
|
213
214
|
if (through = a.options[:through]) && !a.through_reflection
|
214
215
|
puts "WARNING: In model #{model.name}, unable to utilise: has_many #{a.name}, through: #{through.inspect}"
|
215
216
|
end
|
216
|
-
|
217
|
-
|
217
|
+
primary_klass = if a.belongs_to?
|
218
|
+
a.polymorphic? ? nil : a.klass
|
219
|
+
else
|
220
|
+
a.active_record
|
221
|
+
end
|
222
|
+
a_pk = a.options.fetch(:primary_key, nil)&.to_s ||
|
223
|
+
primary_klass&.primary_key # Was: a.klass.primary_key
|
224
|
+
if !a.polymorphic? && (a.belongs_to? || (through && (thr = a.through_reflection))) &&
|
225
|
+
!((kls = thr&.klass || a.klass) && ::Brick.config.exclude_tables.exclude?(kls.table_name) &&
|
218
226
|
(!a.belongs_to? ||
|
219
227
|
((fk_type = a.foreign_key.is_a?(Array) ? a.foreign_key.map { |fk_part| model_cols[fk_part.to_s].type } : model_cols[a.foreign_key.to_s].type) &&
|
220
|
-
(primary_cols =
|
221
|
-
(pk_type =
|
228
|
+
(primary_cols = primary_klass.columns_hash) &&
|
229
|
+
(pk_type = a_pk.is_a?(Array) ? a_pk.map { |pk_part| primary_cols[pk_part.to_s].type } : primary_cols[a_pk].type) &&
|
222
230
|
(same_type = (pk_type == fk_type))
|
223
231
|
)
|
224
232
|
)
|
@@ -229,7 +237,7 @@ module Brick
|
|
229
237
|
# )
|
230
238
|
if same_type == false # We really do want to test specifically for false here, and not nil!
|
231
239
|
puts "WARNING:
|
232
|
-
Foreign key column #{a.klass.table_name}.#{a.foreign_key} is #{fk_type}, but the primary key it relates to, #{
|
240
|
+
Foreign key column #{a.klass.table_name}.#{a.foreign_key} is #{fk_type}, but the primary key it relates to, #{primary_klass.table_name}.#{a_pk}, is #{pk_type}.
|
233
241
|
These columns should both be of the same type."
|
234
242
|
end
|
235
243
|
next
|
@@ -1166,7 +1174,11 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
1166
1174
|
puts " mount Rswag::Ui::Engine => '/#{last_endpoint_parts&.find(&:present?) || 'api-docs'}'"
|
1167
1175
|
end
|
1168
1176
|
else
|
1169
|
-
puts
|
1177
|
+
puts "Having this exposed, one easy way to leverage this to create HTML-based API documentation is to use Scalar.
|
1178
|
+
It will jump to life when you put these two lines into a view template or other HTML resource:
|
1179
|
+
<script id=\"api-reference\" data-url=\"#{last_endpoint_parts.join('/')}\"></script>
|
1180
|
+
<script src=\"https://cdn.jsdelivr.net/@scalar/api-reference\"></script>
|
1181
|
+
Alternatively you can add the rswag-ui gem."
|
1170
1182
|
end
|
1171
1183
|
elsif rswag_ui_present
|
1172
1184
|
sample_path = rswag_path || '/api-docs'
|
@@ -1792,7 +1804,7 @@ end
|
|
1792
1804
|
|
1793
1805
|
# By default the awesome_nested_set gem from CollectiveIdea does not prefix the ORDER BY column with its table name.
|
1794
1806
|
# You can see this snag in action in the popular Spree project -- check out the Taxonomy model. Here is a fix:
|
1795
|
-
if Gem::
|
1807
|
+
if Gem::Dependency.new('awesome_nested_set').matching_specs.present?
|
1796
1808
|
require 'awesome_nested_set/columns'
|
1797
1809
|
::CollectiveIdea::Acts::NestedSet::Columns.class_exec do
|
1798
1810
|
alias _brick_order_column_name order_column_name
|
@@ -1935,7 +1947,7 @@ module ActiveRecord
|
|
1935
1947
|
# %%% Pretty much have to flat-out replace this guy (I think anyway)
|
1936
1948
|
# Good with Rails 5.2.4 through 7.1 on this
|
1937
1949
|
# Ransack gem includes Polyamorous which replaces #build in a different way (which we handle below)
|
1938
|
-
|
1950
|
+
if Gem::Dependency.new('ransack').matching_specs.empty?
|
1939
1951
|
def build(associations, base_klass, root = nil, path = '')
|
1940
1952
|
root ||= associations
|
1941
1953
|
associations.map do |name, right|
|
@@ -1991,7 +2003,7 @@ module ActiveRecord
|
|
1991
2003
|
end
|
1992
2004
|
|
1993
2005
|
# Now the Ransack Polyamorous version of #build
|
1994
|
-
if Gem::
|
2006
|
+
if Gem::Dependency.new('ransack').matching_specs.present?
|
1995
2007
|
require "polyamorous/activerecord_#{::ActiveRecord::VERSION::STRING[0, 3]}_ruby_2/join_dependency"
|
1996
2008
|
module Polyamorous::JoinDependencyExtensions
|
1997
2009
|
def build(associations, base_klass, root = nil, path = '')
|
@@ -190,6 +190,10 @@ if ActiveRecord::Base.respond_to?(:brick_select) && !::Brick.initializer_loaded
|
|
190
190
|
# config.swagger_endpoint '/api-docs/v1/swagger.json', 'API V1 Docs'
|
191
191
|
# end
|
192
192
|
|
193
|
+
# # To establish OpenAPI 3.0 documentation endpoints without use of Rswag, such as if you want to use fancier
|
194
|
+
# # tooling such as Scalar API or similar, the Brick also allows you to establish endpoints directly:
|
195
|
+
# ::Brick.swagger_endpoint '/api-docs/v1/swagger.json', 'API V1 Docs'
|
196
|
+
|
193
197
|
# # By default models are auto-created for database views, and set to be read-only. This can be skipped.
|
194
198
|
# Brick.skip_database_views = true
|
195
199
|
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module Brick
|
2
2
|
module MigrationBuilder
|
3
|
-
include FancyGets
|
4
|
-
|
5
3
|
# Many SQL types are the same as their migration data type name:
|
6
4
|
# text, integer, bigint, date, boolean, decimal, float
|
7
5
|
# These however are not:
|
@@ -48,6 +46,7 @@ module Brick
|
|
48
46
|
# (Still need to find what "inet" and "json" data types map to.)
|
49
47
|
|
50
48
|
class << self
|
49
|
+
include FancyGets
|
51
50
|
def check_folder(is_insert_versions = true, is_delete_versions = false)
|
52
51
|
versions_to_delete_or_append = nil
|
53
52
|
if Dir.exist?(mig_path = ActiveRecord::Migrator.migrations_paths.first || "#{::Rails.root}/db/migrate")
|
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.
|
4
|
+
version: 1.0.187
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lorin Thwaits
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-11-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|