brick 1.0.66 → 1.0.69
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/extensions.rb +156 -48
- data/lib/brick/frameworks/rails/engine.rb +77 -56
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +4 -4
- data/lib/generators/brick/install_generator.rb +2 -2
- data/lib/generators/brick/migrations_generator.rb +27 -18
- 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: 7399b8731b349e5c2a053956c5e6aa9998eb5a2010b5a0e7c081e87f9cac843e
|
4
|
+
data.tar.gz: bc3f65bb32230c05c63f7ef585a825de315ce2979d03b8db6efc6df0d0a5c143
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8681ca78d035e6c727fcb6b60d17a5658841bb28e8a4f3dd7405563d5c7cb3e9739984cfe09ce741fd70d5334b949b786e929a1ce4232cf77568621c2813c9d
|
7
|
+
data.tar.gz: 39a9586ea23107b66ab3d461e93eed2defc459231b26d4b25961a7e2e4df9b04167ff620ac570ad07040681e19ad6b313969e822d6fdd8b492b5f4c1fded4c1c
|
data/lib/brick/extensions.rb
CHANGED
@@ -266,18 +266,27 @@ module ActiveRecord
|
|
266
266
|
quoted_table_name = table_name.split('.').map { |x| "\"#{x}\"" }.join('.')
|
267
267
|
order_by_txt = [] if is_do_txt
|
268
268
|
ordering = [ordering] if ordering && !ordering.is_a?(Array)
|
269
|
-
order_by = ordering&.
|
269
|
+
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
|
270
270
|
case ord_part
|
271
271
|
when String
|
272
272
|
ord_expr = ord_part.gsub('^^^', quoted_table_name)
|
273
273
|
order_by_txt&.<<("Arel.sql(#{ord_expr})")
|
274
|
-
Arel.sql(ord_expr)
|
274
|
+
s << Arel.sql(ord_expr)
|
275
275
|
else # Expecting only Symbol
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
276
|
+
if _br_hm_counts.key?(ord_part)
|
277
|
+
ord_part = "\"b_r_#{ord_part}_ct\""
|
278
|
+
elsif !_br_bt_descrip.key?(ord_part) && !column_names.include?(ord_part.to_s)
|
279
|
+
# Disallow ordering by a bogus column
|
280
|
+
# %%% Note this bogus entry so that Javascript can remove any bogus _brick_order
|
281
|
+
# parameter from the querystring, pushing it into the browser history.
|
282
|
+
ord_part = nil
|
283
|
+
end
|
284
|
+
if ord_part
|
285
|
+
# Retain any reference to a bt_descrip as being a symbol
|
286
|
+
# Was: "#{quoted_table_name}.\"#{ord_part}\""
|
287
|
+
order_by_txt&.<<(_br_bt_descrip.key?(ord_part) ? ord_part : ord_part.inspect)
|
288
|
+
s << ord_part
|
289
|
+
end
|
281
290
|
end
|
282
291
|
end
|
283
292
|
[order_by, order_by_txt]
|
@@ -373,6 +382,7 @@ module ActiveRecord
|
|
373
382
|
end
|
374
383
|
|
375
384
|
def brick_select(params, selects = nil, order_by = nil, translations = {}, join_array = ::Brick::JoinArray.new)
|
385
|
+
is_postgres = ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
|
376
386
|
is_mysql = ActiveRecord::Base.connection.adapter_name == 'Mysql2'
|
377
387
|
is_distinct = nil
|
378
388
|
wheres = {}
|
@@ -401,10 +411,12 @@ module ActiveRecord
|
|
401
411
|
col_alias = " AS _#{col.name}" if (col_name = col.name) == 'class'
|
402
412
|
selects << if is_mysql
|
403
413
|
"`#{tbl_no_schema}`.`#{col_name}`#{col_alias}"
|
404
|
-
|
414
|
+
elsif is_postgres
|
405
415
|
# Postgres can not use DISTINCT with any columns that are XML, so for any of those just convert to text
|
406
416
|
cast_as_text = '::text' if is_distinct && Brick.relations[klass.table_name]&.[](:cols)&.[](col.name)&.first&.start_with?('xml')
|
407
417
|
"\"#{tbl_no_schema}\".\"#{col_name}\"#{cast_as_text}#{col_alias}"
|
418
|
+
else # Sqlite or Oracle
|
419
|
+
"#{tbl_no_schema}.#{col_name}#{col_alias}"
|
408
420
|
end
|
409
421
|
end
|
410
422
|
end
|
@@ -430,13 +442,15 @@ module ActiveRecord
|
|
430
442
|
# Postgres can not use DISTINCT with any columns that are XML, so for any of those just convert to text
|
431
443
|
is_xml = is_distinct && Brick.relations[sel_col.first.table_name]&.[](:cols)&.[](sel_col.last)&.first&.start_with?('xml')
|
432
444
|
# If it's not unique then also include the belongs_to association name before the column name
|
433
|
-
if used_col_aliases.key?(col_alias = "
|
434
|
-
col_alias = "
|
445
|
+
if used_col_aliases.key?(col_alias = "br_fk_#{v.first}__#{sel_col.last}")
|
446
|
+
col_alias = "br_fk_#{v.first}__#{v1[idx][-2..-1].map(&:to_s).join('__')}"
|
435
447
|
end
|
436
448
|
selects << if is_mysql
|
437
449
|
"`#{field_tbl_name}`.`#{sel_col.last}` AS `#{col_alias}`"
|
438
|
-
|
450
|
+
elsif is_postgres
|
439
451
|
"\"#{field_tbl_name}\".\"#{sel_col.last}\"#{'::text' if is_xml} AS \"#{col_alias}\""
|
452
|
+
else
|
453
|
+
"#{field_tbl_name}.#{sel_col.last} AS \"#{col_alias}\""
|
440
454
|
end
|
441
455
|
used_col_aliases[col_alias] = nil
|
442
456
|
v1[idx] << col_alias
|
@@ -447,9 +461,11 @@ module ActiveRecord
|
|
447
461
|
((id_col = k1.primary_key).is_a?(Array) ? id_col : [id_col]).each do |id_part|
|
448
462
|
id_for_tables[v.first] << if id_part
|
449
463
|
selects << if is_mysql
|
450
|
-
"#{"`#{tbl_name}`.`#{id_part}`"} AS `#{(id_alias = "
|
464
|
+
"#{"`#{tbl_name}`.`#{id_part}`"} AS `#{(id_alias = "br_fk_#{v.first}__#{id_part}")}`"
|
465
|
+
elsif is_postgres
|
466
|
+
"#{"\"#{tbl_name}\".\"#{id_part}\""} AS \"#{(id_alias = "br_fk_#{v.first}__#{id_part}")}\""
|
451
467
|
else
|
452
|
-
"#{"
|
468
|
+
"#{"#{tbl_name}.#{id_part}"} AS \"#{(id_alias = "br_fk_#{v.first}__#{id_part}")}\""
|
453
469
|
end
|
454
470
|
id_alias
|
455
471
|
end
|
@@ -479,9 +495,22 @@ module ActiveRecord
|
|
479
495
|
end
|
480
496
|
next unless count_column # %%% Would be able to remove this when multiple foreign keys to same destination becomes bulletproof
|
481
497
|
|
482
|
-
tbl_alias = is_mysql
|
498
|
+
tbl_alias = if is_mysql
|
499
|
+
"`b_r_#{hm.name}`"
|
500
|
+
elsif is_postgres
|
501
|
+
"\"b_r_#{hm.name}\""
|
502
|
+
else
|
503
|
+
"b_r_#{hm.name}"
|
504
|
+
end
|
483
505
|
pri_tbl = hm.active_record
|
484
506
|
pri_tbl_name = is_mysql ? "`#{pri_tbl.table_name}`" : "\"#{pri_tbl.table_name.gsub('.', '"."')}\""
|
507
|
+
pri_tbl_name = if is_mysql
|
508
|
+
"`#{pri_tbl.table_name}`"
|
509
|
+
elsif is_postgres
|
510
|
+
"\"#{pri_tbl.table_name.gsub('.', '"."')}\""
|
511
|
+
else
|
512
|
+
pri_tbl.table_name
|
513
|
+
end
|
485
514
|
on_clause = []
|
486
515
|
if fk_col.is_a?(Array) # Composite key?
|
487
516
|
fk_col.each_with_index { |fk_col_part, idx| on_clause << "#{tbl_alias}.#{fk_col_part} = #{pri_tbl_name}.#{pri_tbl.primary_key[idx]}" }
|
@@ -494,22 +523,29 @@ module ActiveRecord
|
|
494
523
|
selects << poly_type
|
495
524
|
on_clause << "#{tbl_alias}.#{poly_type} = '#{name}'"
|
496
525
|
end
|
497
|
-
hm_table_name = is_mysql
|
526
|
+
hm_table_name = if is_mysql
|
527
|
+
"`#{associative&.table_name || hm.klass.table_name}`"
|
528
|
+
elsif is_postgres
|
529
|
+
"\"#{(associative&.table_name || hm.klass.table_name).gsub('.', '"."')}\""
|
530
|
+
else
|
531
|
+
associative&.table_name || hm.klass.table_name
|
532
|
+
end
|
533
|
+
group_bys = ::Brick.is_oracle ? selects : (1..selects.length).to_a
|
498
534
|
join_clause = "LEFT OUTER
|
499
535
|
JOIN (SELECT #{selects.join(', ')}, COUNT(#{'DISTINCT ' if hm.options[:through]}#{count_column
|
500
|
-
}) AS
|
536
|
+
}) AS c_t_ FROM #{hm_table_name} GROUP BY #{group_bys.join(', ')}) #{tbl_alias}"
|
501
537
|
joins!("#{join_clause} ON #{on_clause.join(' AND ')}")
|
502
538
|
end
|
503
539
|
where!(wheres) unless wheres.empty?
|
504
540
|
# Must parse the order_by and see if there are any symbols which refer to BT associations
|
505
|
-
# as they must be expanded to find the corresponding
|
541
|
+
# as they must be expanded to find the corresponding b_r_model__column naming for each.
|
506
542
|
if order_by.present?
|
507
543
|
final_order_by = *order_by.each_with_object([]) do |v, s|
|
508
544
|
if v.is_a?(Symbol)
|
509
545
|
# Add the ordered series of columns derived from the BT based on its DSL
|
510
546
|
if (bt_cols = klass._br_bt_descrip[v])
|
511
547
|
bt_cols.values.each do |v1|
|
512
|
-
v1.each { |v2| s << v2.last if v2.length > 1 }
|
548
|
+
v1.each { |v2| s << "\"#{v2.last}\"" if v2.length > 1 }
|
513
549
|
end
|
514
550
|
else
|
515
551
|
s << v
|
@@ -657,9 +693,12 @@ Module.class_exec do
|
|
657
693
|
full_class_name = +''
|
658
694
|
full_class_name << "::#{self.name}" unless self == Object
|
659
695
|
full_class_name << "::#{plural_class_name.underscore.singularize.camelize}"
|
660
|
-
if
|
661
|
-
(
|
662
|
-
|
696
|
+
if plural_class_name == 'BrickSwagger' ||
|
697
|
+
(
|
698
|
+
(::Brick.config.add_status || ::Brick.config.add_orphans) &&
|
699
|
+
plural_class_name == 'BrickGem'
|
700
|
+
) ||
|
701
|
+
model = self.const_get(full_class_name)
|
663
702
|
# if it's a controller and no match or a model doesn't really use the same table name, eager load all models and try to find a model class of the right name.
|
664
703
|
Object.send(:build_controller, self, class_name, plural_class_name, model, relations)
|
665
704
|
end
|
@@ -1017,6 +1056,7 @@ class Object
|
|
1017
1056
|
table_name = ActiveSupport::Inflector.underscore(plural_class_name)
|
1018
1057
|
singular_table_name = ActiveSupport::Inflector.singularize(table_name)
|
1019
1058
|
pk = model&._brick_primary_key(relations.fetch(table_name, nil))
|
1059
|
+
is_postgres = ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
|
1020
1060
|
is_mysql = ActiveRecord::Base.connection.adapter_name == 'Mysql2'
|
1021
1061
|
|
1022
1062
|
namespace_name = "#{namespace.name}::" if namespace
|
@@ -1033,7 +1073,7 @@ class Object
|
|
1033
1073
|
self.define_method :orphans do
|
1034
1074
|
instance_variable_set(:@orphans, ::Brick.find_orphans(::Brick.set_db_schema(params)))
|
1035
1075
|
end
|
1036
|
-
return [new_controller_class, code +
|
1076
|
+
return [new_controller_class, code + "end # BrickGem controller\n"]
|
1037
1077
|
when 'BrickSwagger'
|
1038
1078
|
is_swagger = true # if request.format == :json)
|
1039
1079
|
end
|
@@ -1122,7 +1162,13 @@ class Object
|
|
1122
1162
|
# %%% Add custom HM count columns
|
1123
1163
|
# %%% What happens when the PK is composite?
|
1124
1164
|
counts = model._br_hm_counts.each_with_object([]) do |v, s|
|
1125
|
-
s <<
|
1165
|
+
s << if is_mysql
|
1166
|
+
"`b_r_#{v.first}`.c_t_ AS \"b_r_#{v.first}_ct\""
|
1167
|
+
elsif is_postgres
|
1168
|
+
"\"b_r_#{v.first}\".c_t_ AS \"b_r_#{v.first}_ct\""
|
1169
|
+
else
|
1170
|
+
"b_r_#{v.first}.c_t_ AS \"b_r_#{v.first}_ct\""
|
1171
|
+
end
|
1126
1172
|
end
|
1127
1173
|
instance_variable_set("@#{table_name}".to_sym, ar_relation.dup._select!(*selects, *counts))
|
1128
1174
|
if namespace && (idx = lookup_context.prefixes.index(table_name))
|
@@ -1193,6 +1239,8 @@ class Object
|
|
1193
1239
|
else
|
1194
1240
|
instance_variable_set("@#{singular_table_name}".to_sym,
|
1195
1241
|
model.send(:create, send(params_name_sym)))
|
1242
|
+
index
|
1243
|
+
render :index
|
1196
1244
|
end
|
1197
1245
|
end
|
1198
1246
|
|
@@ -1352,15 +1400,18 @@ module ActiveRecord::ConnectionHandling
|
|
1352
1400
|
end
|
1353
1401
|
when 'Mysql2'
|
1354
1402
|
::Brick.default_schema = schema = ActiveRecord::Base.connection.current_database
|
1403
|
+
when 'OracleEnhanced'
|
1404
|
+
# ActiveRecord::Base.connection.current_database will be something like "XEPDB1"
|
1405
|
+
::Brick.default_schema = schema = ActiveRecord::Base.connection.raw_connection.username
|
1406
|
+
::Brick.db_schemas = {}
|
1407
|
+
execute_oracle("SELECT username FROM sys.all_users WHERE ORACLE_MAINTAINED != 'Y'").each { |s| ::Brick.db_schemas[s.first] = nil }
|
1355
1408
|
when 'SQLite'
|
1356
|
-
# %%% Retrieve internal ActiveRecord table names like this:
|
1357
|
-
# ActiveRecord::Base.internal_metadata_table_name, ActiveRecord::Base.schema_migrations_table_name
|
1358
1409
|
sql = "SELECT m.name AS relation_name, UPPER(m.type) AS table_type,
|
1359
1410
|
p.name AS column_name, p.type AS data_type,
|
1360
1411
|
CASE p.pk WHEN 1 THEN 'PRIMARY KEY' END AS const
|
1361
1412
|
FROM sqlite_master AS m
|
1362
1413
|
INNER JOIN pragma_table_info(m.name) AS p
|
1363
|
-
WHERE m.name NOT IN (?, ?)
|
1414
|
+
WHERE m.name NOT IN ('sqlite_sequence', ?, ?)
|
1364
1415
|
ORDER BY m.name, p.cid"
|
1365
1416
|
else
|
1366
1417
|
puts "Unfamiliar with connection adapter #{ActiveRecord::Base.connection.adapter_name}"
|
@@ -1412,9 +1463,31 @@ module ActiveRecord::ConnectionHandling
|
|
1412
1463
|
cols[col_name] = [r['data_type'], r['max_length'], measures&.include?(col_name), r['is_nullable'] == 'NO']
|
1413
1464
|
# puts "KEY! #{r['relation_name']}.#{col_name} #{r['key']} #{r['const']}" if r['key']
|
1414
1465
|
end
|
1415
|
-
else # MySQL2
|
1416
|
-
ActiveRecord::Base.
|
1417
|
-
|
1466
|
+
else # MySQL2 and OracleEnhanced act a little differently, bringing back an array for each row
|
1467
|
+
schema_and_tables = if ActiveRecord::Base.connection.adapter_name == 'OracleEnhanced'
|
1468
|
+
sql =
|
1469
|
+
"SELECT c.owner AS schema, c.table_name AS relation_name, 'BASE_TABLE' AS table_type,
|
1470
|
+
LOWER(c.column_name) AS column_name, c.data_type,
|
1471
|
+
COALESCE(c.data_length, c.data_precision) AS max_length,
|
1472
|
+
CASE ac.constraint_type WHEN 'P' THEN 'PRIMARY KEY' END AS const,
|
1473
|
+
ac.constraint_name AS \"key\",
|
1474
|
+
CASE c.nullable WHEN 'Y' THEN 'YES' ELSE 'NO' END AS is_nullable
|
1475
|
+
FROM all_tab_cols c
|
1476
|
+
LEFT OUTER JOIN all_cons_columns acc ON acc.owner = c.owner AND acc.table_name = c.table_name AND acc.column_name = c.column_name
|
1477
|
+
LEFT OUTER JOIN all_constraints ac ON ac.owner = acc.owner AND ac.table_name = acc.table_name AND ac.constraint_name = acc.constraint_name AND constraint_type = 'P'
|
1478
|
+
WHERE c.owner IN (#{::Brick.db_schemas.keys.map { |s| "'#{s}'" }.join(', ')})
|
1479
|
+
ORDER BY 1, 2, c.internal_column_id, acc.position"
|
1480
|
+
execute_oracle(sql, *ar_tables)
|
1481
|
+
else
|
1482
|
+
ActiveRecord::Base.retrieve_schema_and_tables(sql)
|
1483
|
+
end
|
1484
|
+
schema_and_tables.each do |r|
|
1485
|
+
next if r[1].index('$') # Oracle can have goofy table names with $
|
1486
|
+
|
1487
|
+
if (relation_name = r[1]) =~ /^[A-Z_]+$/
|
1488
|
+
relation_name.downcase!
|
1489
|
+
end
|
1490
|
+
relation = relations[relation_name] # here relation represents a table or view from the database
|
1418
1491
|
relation[:isView] = true if r[2] == 'VIEW' # table_type
|
1419
1492
|
col_name = r[3]
|
1420
1493
|
key = case r[6] # constraint type
|
@@ -1471,32 +1544,53 @@ module ActiveRecord::ConnectionHandling
|
|
1471
1544
|
AND kcu2.ORDINAL_POSITION = kcu1.ORDINAL_POSITION#{"
|
1472
1545
|
WHERE kcu1.CONSTRAINT_SCHEMA = COALESCE(current_setting('SEARCH_PATH'), 'public')" if is_postgres && schema }"
|
1473
1546
|
# AND kcu2.TABLE_NAME = ?;", Apartment::Tenant.current, table_name
|
1547
|
+
fk_references = ActiveRecord::Base.execute_sql(sql)
|
1474
1548
|
when 'SQLite'
|
1475
1549
|
sql = "SELECT m.name, fkl.\"from\", fkl.\"table\", m.name || '_' || fkl.\"from\" AS constraint_name
|
1476
1550
|
FROM sqlite_master m
|
1477
1551
|
INNER JOIN pragma_foreign_key_list(m.name) fkl ON m.type = 'table'
|
1478
1552
|
ORDER BY m.name, fkl.seq"
|
1553
|
+
fk_references = ActiveRecord::Base.execute_sql(sql)
|
1554
|
+
when 'OracleEnhanced'
|
1555
|
+
schemas = ::Brick.db_schemas.keys.map { |s| "'#{s}'" }.join(', ')
|
1556
|
+
sql =
|
1557
|
+
"SELECT -- fk
|
1558
|
+
ac.owner AS constraint_schema, acc_fk.table_name, LOWER(acc_fk.column_name),
|
1559
|
+
-- referenced pk
|
1560
|
+
ac.r_owner AS primary_schema, acc_pk.table_name AS primary_table, acc_fk.constraint_name AS constraint_schema_fk
|
1561
|
+
-- , LOWER(acc_pk.column_name)
|
1562
|
+
FROM all_cons_columns acc_fk
|
1563
|
+
INNER JOIN all_constraints ac ON acc_fk.owner = ac.owner
|
1564
|
+
AND acc_fk.constraint_name = ac.constraint_name
|
1565
|
+
INNER JOIN all_cons_columns acc_pk ON ac.r_owner = acc_pk.owner
|
1566
|
+
AND ac.r_constraint_name = acc_pk.constraint_name
|
1567
|
+
WHERE ac.constraint_type = 'R'
|
1568
|
+
AND ac.owner IN (#{schemas})
|
1569
|
+
AND ac.r_owner IN (#{schemas})"
|
1570
|
+
fk_references = ActiveRecord::Base.execute_oracle(sql)
|
1479
1571
|
else
|
1572
|
+
binding.pry
|
1480
1573
|
end
|
1481
|
-
if
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
|
1489
|
-
|
1490
|
-
|
1491
|
-
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
end
|
1498
|
-
::Brick._add_bt_and_hm(fk, relations)
|
1574
|
+
::Brick.is_oracle = true if ActiveRecord::Base.connection.adapter_name == 'OracleEnhanced'
|
1575
|
+
# ::Brick.default_schema ||= schema ||= 'public' if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
|
1576
|
+
fk_references&.each do |fk|
|
1577
|
+
fk = fk.values unless fk.is_a?(Array)
|
1578
|
+
# Multitenancy makes things a little more general overall, except for non-tenanted tables
|
1579
|
+
if apartment_excluded&.include?(fk[1].singularize.camelize)
|
1580
|
+
fk[0] = Apartment.default_schema
|
1581
|
+
elsif is_postgres && (fk[0] == 'public' || (is_multitenant && fk[0] == schema)) ||
|
1582
|
+
!is_postgres && ['mysql', 'performance_schema', 'sys'].exclude?(fk[0])
|
1583
|
+
fk[0] = nil
|
1584
|
+
end
|
1585
|
+
if apartment_excluded&.include?(fk[4].singularize.camelize)
|
1586
|
+
fk[3] = Apartment.default_schema
|
1587
|
+
elsif is_postgres && (fk[3] == 'public' || (is_multitenant && fk[3] == schema)) ||
|
1588
|
+
!is_postgres && ['mysql', 'performance_schema', 'sys'].exclude?(fk[3])
|
1589
|
+
fk[3] = nil
|
1499
1590
|
end
|
1591
|
+
fk[1].downcase! if ::Brick.is_oracle && fk[1] =~ /^[A-Z_]+$/
|
1592
|
+
fk[4].downcase! if ::Brick.is_oracle && fk[4] =~ /^[A-Z_]+$/
|
1593
|
+
::Brick._add_bt_and_hm(fk, relations)
|
1500
1594
|
end
|
1501
1595
|
end
|
1502
1596
|
|
@@ -1557,13 +1651,27 @@ module ActiveRecord::ConnectionHandling
|
|
1557
1651
|
-- AND t.table_type IN ('VIEW') -- 'BASE TABLE', 'FOREIGN TABLE'
|
1558
1652
|
AND t.table_name NOT IN ('pg_stat_statements', ?, ?)
|
1559
1653
|
ORDER BY 1, t.table_type DESC, 2, c.ordinal_position"
|
1654
|
+
ActiveRecord::Base.execute_sql(sql, *ar_tables)
|
1655
|
+
end
|
1656
|
+
|
1657
|
+
def ar_tables
|
1560
1658
|
ar_smtn = if ActiveRecord::Base.respond_to?(:schema_migrations_table_name)
|
1561
1659
|
ActiveRecord::Base.schema_migrations_table_name
|
1562
1660
|
else
|
1563
1661
|
'schema_migrations'
|
1564
1662
|
end
|
1565
1663
|
ar_imtn = ActiveRecord.version >= ::Gem::Version.new('5.0') ? ActiveRecord::Base.internal_metadata_table_name : ''
|
1566
|
-
|
1664
|
+
[ar_smtn, ar_imtn]
|
1665
|
+
end
|
1666
|
+
|
1667
|
+
def execute_oracle(*sql_args)
|
1668
|
+
cursor = ActiveRecord::Base.execute_sql(*sql_args)
|
1669
|
+
result = []
|
1670
|
+
while row = cursor.fetch()
|
1671
|
+
result << row
|
1672
|
+
end
|
1673
|
+
cursor.close
|
1674
|
+
result
|
1567
1675
|
end
|
1568
1676
|
end
|
1569
1677
|
|
@@ -96,16 +96,15 @@ module Brick
|
|
96
96
|
|
97
97
|
alias :_brick_find_template :find_template
|
98
98
|
def find_template(*args, **options)
|
99
|
-
unless (model_name =
|
100
|
-
@_brick_model ||
|
101
|
-
(ActionView.version < ::Gem::Version.new('5.0') && args[1].is_a?(Array) ? set_brick_model(args) : nil)
|
102
|
-
)&.name) ||
|
99
|
+
unless (model_name = @_brick_model&.name) ||
|
103
100
|
(is_status = ::Brick.config.add_status && args[0..1] == ['status', ['brick_gem']]) ||
|
104
|
-
(is_orphans = ::Brick.config.add_orphans && args[0..1] == ['orphans', ['brick_gem']])
|
101
|
+
(is_orphans = ::Brick.config.add_orphans && args[0..1] == ['orphans', ['brick_gem']]) ||
|
102
|
+
# Used to also have: ActionView.version < ::Gem::Version.new('5.0') &&
|
103
|
+
(model_name = (args[1].is_a?(Array) ? set_brick_model(args) : nil)&.name)
|
105
104
|
return _brick_find_template(*args, **options)
|
106
105
|
end
|
107
106
|
|
108
|
-
|
107
|
+
if @_brick_model
|
109
108
|
pk = @_brick_model._brick_primary_key(::Brick.relations.fetch(model_name, nil))
|
110
109
|
obj_name = model_name.split('::').last.underscore
|
111
110
|
path_obj_name = model_name.underscore.tr('/', '_')
|
@@ -146,7 +145,7 @@ module Brick
|
|
146
145
|
'nil'
|
147
146
|
else
|
148
147
|
# Postgres column names are limited to 63 characters
|
149
|
-
"#{obj_name}.#{"
|
148
|
+
"#{obj_name}.#{"b_r_#{assoc_name}_ct"[0..62]} || 0"
|
150
149
|
end
|
151
150
|
", #{set_ct}, #{path_keys(hm_assoc, hm_fk_name, obj_name, pk)}"
|
152
151
|
end
|
@@ -156,7 +155,7 @@ module Brick
|
|
156
155
|
end
|
157
156
|
hm_entry << ']'
|
158
157
|
hms_columns << hm_entry
|
159
|
-
when 'show', 'update'
|
158
|
+
when 'show', 'new', 'update'
|
160
159
|
hm_stuff << if hm_fk_name
|
161
160
|
"<%= link_to '#{assoc_name}', #{hm_assoc.klass.name.underscore.tr('/', '_').pluralize}_path({ #{path_keys(hm_assoc, hm_fk_name, "@#{obj_name}", pk)} }) %>\n"
|
162
161
|
else # %%% Would be able to remove this when multiple foreign keys to same destination becomes bulletproof
|
@@ -179,6 +178,7 @@ module Brick
|
|
179
178
|
end.keys.sort.each_with_object(+'') do |v, s|
|
180
179
|
s << "<option value=\"#{v.underscore.gsub('.', '/').pluralize}\">#{v}</option>"
|
181
180
|
end.html_safe
|
181
|
+
table_options << '<option value="brick_status">(Status)</option>'.html_safe if ::Brick.config.add_status
|
182
182
|
table_options << '<option value="brick_orphans">(Orphans)</option>'.html_safe if is_orphans
|
183
183
|
css = +"<style>
|
184
184
|
h1, h3 {
|
@@ -275,7 +275,7 @@ tr th, tr td {
|
|
275
275
|
color: #80B8D2;
|
276
276
|
}
|
277
277
|
|
278
|
-
table.shadow tbody tr {
|
278
|
+
table.shadow > tbody > tr {
|
279
279
|
border-bottom: thin solid #dddddd;
|
280
280
|
}
|
281
281
|
|
@@ -283,7 +283,7 @@ table tbody tr:nth-of-type(even) {
|
|
283
283
|
background-color: #f3f3f3;
|
284
284
|
}
|
285
285
|
|
286
|
-
table.shadow tbody tr:last-of-type {
|
286
|
+
table.shadow > tbody > tr:last-of-type {
|
287
287
|
border-bottom: 2px solid #009879;
|
288
288
|
}
|
289
289
|
|
@@ -300,14 +300,6 @@ a.big-arrow {
|
|
300
300
|
font-size: 2.5em;
|
301
301
|
text-decoration: none;
|
302
302
|
}
|
303
|
-
.wide-input {
|
304
|
-
display: block;
|
305
|
-
overflow: hidden;
|
306
|
-
}
|
307
|
-
.wide-input input[type=text] {
|
308
|
-
display: inline-block;
|
309
|
-
width: 90%;
|
310
|
-
}
|
311
303
|
.dimmed {
|
312
304
|
background-color: #C0C0C0;
|
313
305
|
text-align: center;
|
@@ -324,9 +316,6 @@ svg.revert {
|
|
324
316
|
display: none;
|
325
317
|
margin-left: 0.25em;
|
326
318
|
}
|
327
|
-
.wide-input > svg.revert {
|
328
|
-
float: right;
|
329
|
-
}
|
330
319
|
input+svg.revert {
|
331
320
|
top: 0.5em;
|
332
321
|
}
|
@@ -379,9 +368,10 @@ def display_value(col_type, val)
|
|
379
368
|
'?'
|
380
369
|
end
|
381
370
|
end
|
382
|
-
end
|
371
|
+
end
|
372
|
+
callbacks = {} %>"
|
383
373
|
|
384
|
-
if ['index', 'show', 'update'].include?(args.first)
|
374
|
+
if ['index', 'show', 'new', 'update'].include?(args.first)
|
385
375
|
poly_cols = []
|
386
376
|
css << "<% bts = { #{
|
387
377
|
bt_items = bts.each_with_object([]) do |v, s|
|
@@ -537,17 +527,18 @@ if (headerTop) {
|
|
537
527
|
}
|
538
528
|
</script>"
|
539
529
|
|
540
|
-
erd_markup =
|
530
|
+
erd_markup = if @_brick_model
|
531
|
+
"<div id=\"mermaidErd\" class=\"mermaid\">
|
541
532
|
erDiagram
|
542
533
|
<% model_short_name = #{@_brick_model.name.split('::').last.inspect}
|
543
|
-
callbacks = {}
|
544
534
|
@_brick_bt_descrip&.each do |bt|
|
545
535
|
bt_class = bt[1].first.first
|
546
536
|
callbacks[bt_name = bt_class.name.split('::').last] = bt_class
|
547
537
|
is_has_one = #{@_brick_model.name}.reflect_on_association(bt.first).inverse_of&.macro == :has_one ||
|
548
538
|
::Brick.config.has_ones&.fetch('#{@_brick_model.name}', nil)&.key?(bt.first.to_s)
|
549
539
|
%> <%= \"#\{model_short_name} #\{is_has_one ? '||' : '}o'}--|| #\{bt_name} : \\\"#\{
|
550
|
-
|
540
|
+
bt_underscored = bt[1].first.first.name.underscore.singularize
|
541
|
+
bt.first unless bt.first.to_s == bt_underscored.split('/').last # Was: bt_underscored.tr('/', '_')
|
551
542
|
}\\\"\".html_safe %>
|
552
543
|
<% end
|
553
544
|
last_through = nil
|
@@ -557,14 +548,15 @@ erDiagram
|
|
557
548
|
|
558
549
|
callbacks[hm_name = hm_class.name.split('::').last] = hm_class
|
559
550
|
if (through = hm.last.options[:through]&.to_s) # has_many :through (HMT)
|
560
|
-
|
551
|
+
through_name = (through_assoc = hm.last.source_reflection).active_record.name.split('::').last
|
552
|
+
callbacks[through_name] = through_assoc.active_record
|
561
553
|
if last_through == through # Same HM, so no need to build it again, and for clarity just put in a blank line
|
562
554
|
%><%= \"\n\"
|
563
555
|
%><% else
|
564
|
-
%> <%= \"#\{model_short_name} ||--o{ #\{
|
556
|
+
%> <%= \"#\{model_short_name} ||--o{ #\{through_name}\".html_safe %> : \"\"
|
565
557
|
<% last_through = through
|
566
558
|
end
|
567
|
-
%> <%= \"#\{
|
559
|
+
%> <%= \"#\{through_name} }o--|| #\{hm_name}\".html_safe %> : \"\"
|
568
560
|
<%= \"#\{model_short_name} }o..o{ #\{hm_name} : \\\"#\{hm.first}\\\"\".html_safe %><%
|
569
561
|
else # has_many
|
570
562
|
%> <%= \"#\{model_short_name} ||--o{ #\{hm_name} : \\\"#\{
|
@@ -572,21 +564,25 @@ erDiagram
|
|
572
564
|
}\\\"\".html_safe %><%
|
573
565
|
end %>
|
574
566
|
<% end
|
567
|
+
def dt_lookup(dt)
|
568
|
+
{ 'integer' => 'int', }[dt] || dt.tr(' ', '_')
|
569
|
+
end
|
575
570
|
callbacks.merge({model_short_name => #{@_brick_model.name}}).each do |cb_k, cb_class|
|
576
571
|
cb_relation = ::Brick.relations[cb_class.table_name]
|
577
572
|
pkeys = cb_relation[:pkey]&.first&.last
|
578
573
|
fkeys = cb_relation[:fks]&.values&.each_with_object([]) { |fk, s| s << fk[:fk] if fk.fetch(:is_bt, nil) }
|
574
|
+
cols = cb_relation[:cols]
|
579
575
|
%> <%= cb_k %> {<%
|
580
576
|
pkeys&.each do |pk| %>
|
581
|
-
<%= \"
|
577
|
+
<%= \"#\{dt_lookup(cols[pk].first)} #\{pk} \\\"PK#\{' fk' if fkeys&.include?(pk)}\\\"\".html_safe %><%
|
582
578
|
end %><%
|
583
579
|
fkeys&.each do |fk|
|
584
580
|
if fk.is_a?(Array)
|
585
581
|
fk.each do |fk_part| %>
|
586
|
-
<%= \"
|
582
|
+
<%= \"#\{dt_lookup(cols[fk_part].first)} #\{fk_part} \\\" fk\\\"\".html_safe unless pkeys&.include?(fk_part) %><%
|
587
583
|
end
|
588
584
|
else %>
|
589
|
-
<%= \"
|
585
|
+
<%= \"#\{dt_lookup(cols[fk].first)} #\{fk} \\\" fk\\\"\".html_safe unless pkeys&.include?(fk) %><%
|
590
586
|
end
|
591
587
|
end %>
|
592
588
|
}
|
@@ -595,6 +591,7 @@ erDiagram
|
|
595
591
|
%>
|
596
592
|
</div>
|
597
593
|
"
|
594
|
+
end
|
598
595
|
inline = case args.first
|
599
596
|
when 'index'
|
600
597
|
obj_pk = if pk&.is_a?(Array) # Composite primary key?
|
@@ -690,7 +687,7 @@ erDiagram
|
|
690
687
|
</script>
|
691
688
|
<script async defer src=\"https://apis.google.com/js/api.js\" onload=\"gapiLoaded()\"></script>
|
692
689
|
"
|
693
|
-
end
|
690
|
+
end # DutyFree data export and import
|
694
691
|
# %%% Instead of our current "for Janet Leverling (Employee)" kind of link we previously had this code that did a "where x = 123" thing:
|
695
692
|
# (where <%= @_brick_params.each_with_object([]) { |v, s| s << \"#\{v.first\} = #\{v.last.inspect\}\" }.join(', ') %>)
|
696
693
|
+"#{css}
|
@@ -829,6 +826,7 @@ erDiagram
|
|
829
826
|
#{script}"
|
830
827
|
|
831
828
|
when 'status'
|
829
|
+
if is_status
|
832
830
|
# Status page - list of all resources and 5 things they do or don't have present, and what is turned on and off
|
833
831
|
# Must load all models, and then find what table names are represented
|
834
832
|
# Easily could be multiple files involved (STI for instance)
|
@@ -852,7 +850,7 @@ erDiagram
|
|
852
850
|
@resources.each do |r|
|
853
851
|
%>
|
854
852
|
<tr>
|
855
|
-
<td><%= link_to(r[0], \"/#\{r[0].tr('.', '/')}\") %></td>
|
853
|
+
<td><%= link_to(r[0], \"/#\{r[0].underscore.tr('.', '/')}\") %></td>
|
856
854
|
<td<%= if r[1]
|
857
855
|
' class=\"orphan\"' unless ::Brick.relations.key?(r[1])
|
858
856
|
else
|
@@ -873,6 +871,7 @@ erDiagram
|
|
873
871
|
<% end %>
|
874
872
|
</tbody></table>
|
875
873
|
#{script}"
|
874
|
+
end
|
876
875
|
|
877
876
|
when 'orphans'
|
878
877
|
if is_orphans
|
@@ -890,7 +889,7 @@ erDiagram
|
|
890
889
|
#{script}"
|
891
890
|
end
|
892
891
|
|
893
|
-
when 'show', 'update'
|
892
|
+
when 'show', 'new', 'update'
|
894
893
|
+"#{css}
|
895
894
|
|
896
895
|
<svg id=\"revertTemplate\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"
|
@@ -958,38 +957,41 @@ end
|
|
958
957
|
<% end %>
|
959
958
|
</th>
|
960
959
|
<td>
|
960
|
+
<table><tr><td>
|
961
961
|
<% dt_pickers = { datetime: 'datetimepicker', timestamp: 'datetimepicker', time: 'timepicker', date: 'datepicker' }
|
962
|
+
html_options = {}
|
963
|
+
html_options[:class] = 'dimmed' unless val
|
964
|
+
is_revert = true
|
962
965
|
if bt
|
963
|
-
html_options =
|
964
|
-
html_options[:class] = 'dimmed' unless val %>
|
966
|
+
html_options[:prompt] = \"Select #\{bt_name\}\" %>
|
965
967
|
<%= f.select k.to_sym, bt[3], { value: val || '^^^brick_NULL^^^' }, html_options %>
|
966
968
|
<%= if (bt_obj = bt_class&.find_by(bt_pair[1] => val))
|
967
969
|
link_to('⇛', send(\"#\{bt_class.base_class.name.underscore.tr('/', '_')\}_path\".to_sym, bt_obj.send(bt_class.primary_key.to_sym)), { class: 'show-arrow' })
|
968
970
|
elsif val
|
969
971
|
\"<span class=\\\"orphan\\\">Orphaned ID: #\{val}</span>\".html_safe
|
970
|
-
end
|
972
|
+
end %>
|
971
973
|
<% else
|
972
|
-
|
973
|
-
html_options[:class] = 'dimmed' unless val
|
974
|
-
case (col_type = col.type || col.sql_type)
|
974
|
+
case (col_type = col.type || col.sql_type)
|
975
975
|
when :string, :text %>
|
976
|
-
<% if is_bcrypt?(val) # || .readonly?
|
976
|
+
<% if is_bcrypt?(val) # || .readonly?
|
977
|
+
is_revert = false %>
|
977
978
|
<%= hide_bcrypt(val, 1000) %>
|
978
979
|
<% else %>
|
979
|
-
|
980
|
+
<%= f.text_field(k.to_sym, html_options) %>
|
980
981
|
<% end %>
|
981
982
|
<% when :boolean %>
|
982
|
-
<%= f.check_box k.to_sym
|
983
|
+
<%= f.check_box k.to_sym %>
|
983
984
|
<% when :integer, :decimal, :float %>
|
984
985
|
<%= if col_type == :integer
|
985
986
|
f.text_field k.to_sym, { pattern: '\\d*', class: 'check-validity' }
|
986
987
|
else
|
987
988
|
f.number_field k.to_sym
|
988
|
-
end
|
989
|
+
end %>
|
989
990
|
<% when *dt_pickers.keys
|
990
991
|
is_includes_dates = true %>
|
991
|
-
<%= f.text_field k.to_sym, { class: dt_pickers[col_type] }
|
992
|
-
<% when :uuid
|
992
|
+
<%= f.text_field k.to_sym, { class: dt_pickers[col_type] } %>
|
993
|
+
<% when :uuid
|
994
|
+
is_revert = false %>
|
993
995
|
<%=
|
994
996
|
# Postgres naturally uses the +uuid_generate_v4()+ function from the uuid-ossp extension
|
995
997
|
# If it's not yet enabled then: create extension \"uuid-ossp\";
|
@@ -1000,11 +1002,18 @@ end
|
|
1000
1002
|
# In Postgres labels of data stored in a hierarchical tree-like structure
|
1001
1003
|
# If it's not yet enabled then: create extension ltree;
|
1002
1004
|
val %>
|
1003
|
-
<% when :binary, :primary_key
|
1005
|
+
<% when :binary, :primary_key
|
1006
|
+
is_revert = false %>
|
1004
1007
|
<% else %>
|
1005
|
-
<%= display_value(col_type, val)
|
1008
|
+
<%= display_value(col_type, val)
|
1009
|
+
is_revert = false %>
|
1010
|
+
<% end
|
1011
|
+
end
|
1012
|
+
if is_revert
|
1013
|
+
%></td>
|
1014
|
+
<td><svg class=\"revert\" width=\"1.5em\" viewBox=\"0 0 512 512\"><use xlink:href=\"#revertPath\" /></svg>
|
1006
1015
|
<% end %>
|
1007
|
-
|
1016
|
+
</td></tr></table>
|
1008
1017
|
</td>
|
1009
1018
|
</tr>
|
1010
1019
|
<% end
|
@@ -1066,7 +1075,7 @@ flatpickr(\".timepicker\", {enableTime: true, noCalendar: true});
|
|
1066
1075
|
var mermaidErd = document.getElementById(\"mermaidErd\");
|
1067
1076
|
var mermaidCode;
|
1068
1077
|
var cbs = {<%= callbacks.map { |k, v| \"#\{k}: \\\"#\{v.name.underscore.pluralize}\\\"\" }.join(', ').html_safe %>};
|
1069
|
-
imgErd.addEventListener(\"click\", showErd);
|
1078
|
+
if (imgErd) imgErd.addEventListener(\"click\", showErd);
|
1070
1079
|
function showErd() {
|
1071
1080
|
imgErd.style.display = \"none\";
|
1072
1081
|
mermaidErd.style.display = \"inline-block\";
|
@@ -1087,7 +1096,9 @@ flatpickr(\".timepicker\", {enableTime: true, noCalendar: true});
|
|
1087
1096
|
gErd.setAttribute(\"class\", \"relatedModel\");
|
1088
1097
|
gErd.addEventListener(\"click\",
|
1089
1098
|
function (evt) {
|
1090
|
-
location.href = changeout(changeout(
|
1099
|
+
location.href = changeout(changeout(
|
1100
|
+
changeout(location.href, '_brick_order', null), // Remove any ordering
|
1101
|
+
-1, cbs[this.id]), \"_brick_erd\", \"1\");
|
1091
1102
|
}
|
1092
1103
|
);
|
1093
1104
|
}
|
@@ -1127,9 +1138,12 @@ document.querySelectorAll(\"input, select\").forEach(function (inp) {
|
|
1127
1138
|
var origVal = getInpVal(),
|
1128
1139
|
prevVal = origVal;
|
1129
1140
|
var revert;
|
1130
|
-
if (
|
1131
|
-
|
1132
|
-
|
1141
|
+
if (inp.getAttribute(\"type\") == \"hidden\" || inp.getAttribute(\"type\") == \"submit\") return;
|
1142
|
+
|
1143
|
+
var svgTd = null;
|
1144
|
+
if ((revert = ((inp.tagName === \"SELECT\" && (svgTd = inp.parentElement.nextElementSibling) && svgTd.firstElementChild) ||
|
1145
|
+
((svgTd = inp.parentElement.nextElementSibling) && svgTd.firstElementChild))
|
1146
|
+
) && revert.tagName.toLowerCase() === \"svg\")
|
1133
1147
|
revert.addEventListener(\"click\", function (e) {
|
1134
1148
|
if (inp.type === \"checkbox\")
|
1135
1149
|
inp.checked = origVal;
|
@@ -1160,7 +1174,7 @@ document.querySelectorAll(\"input, select\").forEach(function (inp) {
|
|
1160
1174
|
prevVal = getInpVal();
|
1161
1175
|
}
|
1162
1176
|
// Show or hide the revert button
|
1163
|
-
if (revert) revert.style.display = getInpVal() === origVal ? \"none\" : \"
|
1177
|
+
if (revert) revert.style.display = getInpVal() === origVal ? \"none\" : \"block\";
|
1164
1178
|
});
|
1165
1179
|
function getInpVal() {
|
1166
1180
|
return inp.type === \"checkbox\" ? inp.checked : inp.value;
|
@@ -1180,6 +1194,13 @@ document.querySelectorAll(\"input, select\").forEach(function (inp) {
|
|
1180
1194
|
# In order to defer auto-creation of any routes that already exist, calculate Brick routes only after having loaded all others
|
1181
1195
|
prepend ::Brick::RouteSet
|
1182
1196
|
end
|
1197
|
+
# Do the root route before the Rails Welcome one would otherwise take precedence
|
1198
|
+
unless (route = ::Brick.config.default_route_fallback).blank? ||
|
1199
|
+
::Rails.application.routes.named_routes.send(:routes)[:root]
|
1200
|
+
::Rails.application.routes.append do
|
1201
|
+
send(:root, "#{route}#{'#index' unless route.index('#')}")
|
1202
|
+
end
|
1203
|
+
end
|
1183
1204
|
end
|
1184
1205
|
|
1185
1206
|
# Just in case it hadn't been done previously when we tried to load the brick initialiser,
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -123,7 +123,7 @@ module Brick
|
|
123
123
|
end
|
124
124
|
|
125
125
|
class << self
|
126
|
-
attr_accessor :default_schema, :db_schemas
|
126
|
+
attr_accessor :default_schema, :db_schemas, :routes_done, :is_oracle
|
127
127
|
|
128
128
|
def set_db_schema(params)
|
129
129
|
schema = params['_brick_schema'] || 'public'
|
@@ -461,11 +461,11 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
461
461
|
|
462
462
|
module RouteSet
|
463
463
|
def finalize!
|
464
|
+
return super if ::Brick.routes_done
|
465
|
+
|
466
|
+
::Brick.routes_done = true
|
464
467
|
existing_controllers = routes.each_with_object({}) { |r, s| c = r.defaults[:controller]; s[c] = nil if c }
|
465
468
|
::Rails.application.routes.append do
|
466
|
-
unless ::Brick.config.default_route_fallback.blank? || ::Rails.application.routes.named_routes.send(:routes)[:root]
|
467
|
-
send(:root, "#{::Brick.config.default_route_fallback}#index")
|
468
|
-
end
|
469
469
|
# %%% TODO: If no auto-controllers then enumerate the controllers folder in order to build matching routes
|
470
470
|
# If auto-controllers and auto-models are both enabled then this makes sense:
|
471
471
|
::Brick.relations.each do |rel_name, v|
|
@@ -279,8 +279,8 @@ module Brick
|
|
279
279
|
# # route to go to the :index action for what would be a controller for that table. You can specify any controller
|
280
280
|
# # name and action you wish in order to override this and have that be the default route when none other has been
|
281
281
|
# # specified in routes.rb or elsewhere. (Or just use an empty string in order to disable this behaviour.)
|
282
|
-
# Brick.default_route_fallback = 'customers' # This defaults to \"customers
|
283
|
-
# Brick.default_route_fallback = 'orders
|
282
|
+
# Brick.default_route_fallback = 'customers' # This defaults to \"customers#index\"
|
283
|
+
# Brick.default_route_fallback = 'orders#outstanding' # Example of a non-RESTful route
|
284
284
|
# Brick.default_route_fallback = '' # Omits setting a default route in the absence of any other
|
285
285
|
")
|
286
286
|
end
|
@@ -22,7 +22,16 @@ module Brick
|
|
22
22
|
'time without time zone' => 'time',
|
23
23
|
'time with time zone' => 'time',
|
24
24
|
'double precision' => 'float',
|
25
|
-
'smallint' => 'integer'
|
25
|
+
'smallint' => 'integer', # %%% Need to put in "limit: 2"
|
26
|
+
# Sqlite data types
|
27
|
+
'TEXT' => 'text',
|
28
|
+
'' => 'string',
|
29
|
+
'INTEGER' => 'integer',
|
30
|
+
'REAL' => 'float',
|
31
|
+
'BLOB' => 'binary',
|
32
|
+
'TIMESTAMP' => 'timestamp',
|
33
|
+
'DATETIME' => 'timestamp'
|
34
|
+
}
|
26
35
|
# (Still need to find what "inet" and "json" data types map to.)
|
27
36
|
|
28
37
|
desc 'Auto-generates migration files for an existing database.'
|
@@ -38,7 +47,8 @@ module Brick
|
|
38
47
|
return
|
39
48
|
end
|
40
49
|
|
41
|
-
|
50
|
+
is_sqlite = ActiveRecord::Base.connection.adapter_name == 'SQLite'
|
51
|
+
key_type = ((is_sqlite || ActiveRecord.version < ::Gem::Version.new('5.1')) ? 'integer' : 'bigint')
|
42
52
|
is_4x_rails = ActiveRecord.version < ::Gem::Version.new('5.0')
|
43
53
|
ar_version = "[#{ActiveRecord.version.segments[0..1].join('.')}]" unless is_4x_rails
|
44
54
|
is_insert_versions = true
|
@@ -142,21 +152,20 @@ module Brick
|
|
142
152
|
# if this one has come in as bigint or integer.
|
143
153
|
pk_is_also_fk = fkey_cols.any? { |assoc| pkey_cols&.first == assoc[:fk] } ? pkey_cols&.first : nil
|
144
154
|
# Support missing primary key (by adding: ,id: false)
|
145
|
-
id_option = if pk_is_also_fk ||
|
146
|
-
|
147
|
-
|
155
|
+
id_option = if pk_is_also_fk || !pkey_cols&.present?
|
156
|
+
', id: false'
|
157
|
+
elsif ((pkey_col_first = relation[:cols][pkey_cols&.first]&.first) &&
|
158
|
+
(pkey_col_first = SQL_TYPES[pkey_col_first] || pkey_col_first) != key_type)
|
159
|
+
case pkey_col_first
|
160
|
+
when 'integer'
|
161
|
+
', id: :serial'
|
162
|
+
when 'bigint'
|
163
|
+
', id: :bigserial'
|
148
164
|
else
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
', id: :bigserial'
|
154
|
-
else
|
155
|
-
", id: :#{SQL_TYPES[pkey_col_first] || pkey_col_first}" # Something like: id: :integer, primary_key: :businessentityid
|
156
|
-
end +
|
157
|
-
(pkey_cols.first ? ", primary_key: :#{pkey_cols.first}" : '') +
|
158
|
-
(!is_4x_rails && (comment = relation&.fetch(:description, nil))&.present? ? ", comment: #{comment.inspect}" : '')
|
159
|
-
end
|
165
|
+
", id: :#{pkey_col_first}" # Something like: id: :integer, primary_key: :businessentityid
|
166
|
+
end +
|
167
|
+
(pkey_cols.first ? ", primary_key: :#{pkey_cols.first}" : '') +
|
168
|
+
(!is_4x_rails && (comment = relation&.fetch(:description, nil))&.present? ? ", comment: #{comment.inspect}" : '')
|
160
169
|
end
|
161
170
|
# Find the ActiveRecord class in order to see if the columns have comments
|
162
171
|
unless is_4x_rails
|
@@ -208,7 +217,7 @@ module Brick
|
|
208
217
|
mig << " t.references :#{fk[:assoc_name]}#{suffix}, foreign_key: { to_table: #{to_table} }\n"
|
209
218
|
end
|
210
219
|
else
|
211
|
-
next if !id_option&.end_with?('id: false') && pkey_cols
|
220
|
+
next if !id_option&.end_with?('id: false') && pkey_cols&.include?(col)
|
212
221
|
|
213
222
|
# See if there are generic timestamps
|
214
223
|
if sql_type == 'timestamp' && ['created_at','updated_at'].include?(col)
|
@@ -244,7 +253,7 @@ module Brick
|
|
244
253
|
mig << " #{'# ' if is_commented}add_foreign_key #{tbl_code}, #{add_fk[0]}, column: :#{add_fk[1]}, primary_key: :#{pk}\n"
|
245
254
|
end
|
246
255
|
mig << " end\n"
|
247
|
-
versions_to_create << migration_file_write(mig_path, "create_#{tbl_parts.join('_')}", current_mig_time += 1.minute, ar_version, mig)
|
256
|
+
versions_to_create << migration_file_write(mig_path, "create_#{tbl_parts.map(&:underscore).join('_')}", current_mig_time += 1.minute, ar_version, mig)
|
248
257
|
end
|
249
258
|
done.concat(fringe)
|
250
259
|
chosen -= done
|
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.69
|
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-
|
11
|
+
date: 2022-09-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|