brick 1.0.56 → 1.0.57

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: b696c53c9d9d359d49de147b06b5342820ca230451c860d097f44bcae3b23bb0
4
- data.tar.gz: 7b0f6ff365f918a97d64305eabf70fcfe78cf764514ca22b3731b780da04b22c
3
+ metadata.gz: 930370b67a72b31db99cc8d50afa80d4c3be0d07e727155eb20ac5a7628bb1bb
4
+ data.tar.gz: f2d7964c79172a438800b3c69c63e62b26a4984357ca5d6c7ff9e2ef72e5308f
5
5
  SHA512:
6
- metadata.gz: 43ab6db28554fb7502d0f03267d2f5bab27d310fb988701d371232f6604090cd679767a12097a7c217401b05e938c787844ae11138a2c8143c1e675b93599656
7
- data.tar.gz: 8d2e592ba27bba30e100ea23a2bf951d6f3861c422ef355bad7cd38e146c20c2cf53380aa7ee440f40aa2d111c7f33eadc8dc09f73d1689432fff071e04228c4
6
+ metadata.gz: 03e7ba018c426517060aa6312d14a9f1e0877d82b376782ea46b4b1506433bbe3e9e4d2c3d88aaf3d5fb356c68a129fd975b1718d7b2ac826b241efab3f2cee6
7
+ data.tar.gz: 645c6b750dd870180e312ffddff1d199bb84e92cdde0309f253ec8c927f3ba5304b84ae95b066c260d0523048c607b28148d1b577a479ec661b94de05248813a
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 56
8
+ TINY = 57
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
@@ -5,12 +5,14 @@ require 'rails/generators/active_record'
5
5
  require 'fancy_gets'
6
6
 
7
7
  module Brick
8
- # Auto-generates migrations
8
+ # Auto-generates migration files
9
9
  class MigrationsGenerator < ::Rails::Generators::Base
10
10
  include FancyGets
11
11
  # include ::Rails::Generators::Migration
12
12
 
13
- # SQL types that are the same as their migration data type name: text, integer, bigint, date, boolean, decimal, float
13
+ # Many SQL types are the same as their migration data type name:
14
+ # text, integer, bigint, date, boolean, decimal, float
15
+ # These however are not:
14
16
  SQL_TYPES = { 'character varying' => 'string',
15
17
  'character' => 'string', # %%% Need to put in "limit: 1"
16
18
  'xml' => 'text',
@@ -23,15 +25,7 @@ module Brick
23
25
  'smallint' => 'integer' } # %%% Need to put in "limit: 2"
24
26
  # (Still need to find what "inet" and "json" data types map to.)
25
27
 
26
- # # source_root File.expand_path('templates', __dir__)
27
- # class_option(
28
- # :with_changes,
29
- # type: :boolean,
30
- # default: false,
31
- # desc: 'Add IMPORT_TEMPLATE to model'
32
- # )
33
-
34
- desc 'Auto-generates migrations for an existing database.'
28
+ desc 'Auto-generates migration files for an existing database.'
35
29
 
36
30
  def brick_migrations
37
31
  # If Apartment is active, see if a default schema to analyse is indicated
@@ -47,11 +41,14 @@ module Brick
47
41
  key_type = (ActiveRecord.version < ::Gem::Version.new('5.1') ? 'integer' : 'bigint')
48
42
  is_4x_rails = ActiveRecord.version < ::Gem::Version.new('5.0')
49
43
  ar_version = "[#{ActiveRecord.version.segments[0..1].join('.')}]" unless is_4x_rails
50
- default_mig_path = (mig_path = ActiveRecord::Migrator.migrations_paths.first || "#{::Rails.root}/db/migrate")
51
- if Dir.exist?(mig_path)
44
+ is_insert_versions = true
45
+ is_delete_versions = false
46
+ versions_to_delete_or_append = nil
47
+ if Dir.exist?(mig_path = ActiveRecord::Migrator.migrations_paths.first || "#{::Rails.root}/db/migrate")
52
48
  if Dir["#{mig_path}/**/*.rb"].present?
53
49
  puts "WARNING: migrations folder #{mig_path} appears to already have ruby files present."
54
50
  mig_path2 = "#{::Rails.root}/tmp/brick_migrations"
51
+ is_insert_versions = false unless mig_path == mig_path2
55
52
  if Dir.exist?(mig_path2)
56
53
  if Dir["#{mig_path2}/**/*.rb"].present?
57
54
  puts "As well, temporary folder #{mig_path2} also has ruby files present."
@@ -59,10 +56,15 @@ module Brick
59
56
  mig_path2 = gets_list(list: ['Cancel operation!', "Append migration files into #{mig_path} anyway", mig_path, mig_path2])
60
57
  return if mig_path2.start_with?('Cancel')
61
58
 
59
+ existing_mig_files = Dir["#{mig_path2}/**/*.rb"]
60
+ if (is_insert_versions = mig_path == mig_path2)
61
+ versions_to_delete_or_append = existing_mig_files.map { |ver| ver.split('/').last.split('_').first }
62
+ end
62
63
  if mig_path2.start_with?('Append migration files into ')
63
64
  mig_path2 = mig_path
64
65
  else
65
- Dir["#{mig_path2}/**/*.rb"].each { |rb| File.delete(rb) }
66
+ is_delete_versions = true
67
+ existing_mig_files.each { |rb| File.delete(rb) }
66
68
  end
67
69
  else
68
70
  puts "Using temporary folder #{mig_path2} for created migration files.\n\n"
@@ -88,7 +90,9 @@ module Brick
88
90
  fks = {}
89
91
  stuck = {}
90
92
  indexes = {} # Track index names to make sure things are unique
91
- versions = [] # Resulting versions to be used when updating the schema_migrations table
93
+ built_schemas = {} # Track all built schemas so we can place an appropriate drop_schema command only in the first
94
+ # migration in which that schema is referenced, thereby allowing rollbacks to function properly.
95
+ versions_to_create = [] # Resulting versions to be used when updating the schema_migrations table
92
96
  # Start by making migrations for fringe tables (those with no foreign keys).
93
97
  # Continue layer by layer, creating migrations for tables that reference ones already done, until
94
98
  # no more migrations can be created. (At that point hopefully all tables are accounted for.)
@@ -113,7 +117,7 @@ module Brick
113
117
  end
114
118
  end
115
119
  schema = if (tbl_parts = tbl.split('.')).length > 1
116
- if tbl_parts.first == 'public'
120
+ if tbl_parts.first == (::Brick.default_schema || 'public')
117
121
  tbl_parts.shift
118
122
  nil
119
123
  else
@@ -123,10 +127,13 @@ module Brick
123
127
  # %%% For the moment we're skipping polymorphics
124
128
  fkey_cols = relation[:fks].values.select { |assoc| assoc[:is_bt] && !assoc[:polymorphic] }
125
129
  mig = +"class Create#{(full_table_name = tbl_parts.join('_')).camelize} < ActiveRecord::Migration#{ar_version}\n"
130
+ # If the primary key is also used as a foreign key, will need to do id: false and then build out
131
+ # a column definition which includes :primary_key -- %%% also using a data type of bigserial or serial
132
+ # if this one has come in as bigint or integer.
133
+ pk_is_also_fk = fkey_cols.any? { |assoc| pkey_cols&.first == assoc[:fk] } ? pkey_cols&.first : nil
126
134
  # Support missing primary key (by adding: ,id: false)
127
- # also integer / uuid / other non-standard data types for primary key
128
- id_option = unless (pkey_col_first = relation[:cols][pkey_cols&.first]&.first) == key_type
129
- unless pkey_cols&.present?
135
+ id_option = if pk_is_also_fk || (pkey_col_first = relation[:cols][pkey_cols&.first]&.first) != key_type
136
+ if pk_is_also_fk || !pkey_cols&.present?
130
137
  ', id: false'
131
138
  else
132
139
  case pkey_col_first
@@ -157,21 +164,12 @@ module Brick
157
164
  # Refer to this table name as a symbol or dotted string as appropriate
158
165
  tbl_code = tbl_parts.length == 1 ? ":#{tbl_parts.first}" : "'#{tbl}'"
159
166
  mig << " def change\n return unless reverting? || !table_exists?(#{tbl_code})\n\n"
160
- mig << " create_schema :#{schema} unless schema_exists?(:#{schema})\n" if schema
167
+ mig << " create_schema :#{schema} unless reverting? || schema_exists?(:#{schema})\n" if schema
161
168
  mig << " create_table #{tbl_code}#{id_option} do |t|\n"
162
169
  possible_ts = [] # Track possible generic timestamps
163
170
  add_fks = [] # Track foreign keys to add after table creation
164
171
  relation[:cols].each do |col, col_type|
165
- next if !id_option&.end_with?('id: false') && pkey_cols.include?(col)
166
-
167
- # See if there are generic timestamps
168
- if (sql_type = SQL_TYPES[col_type.first]) == 'timestamp' &&
169
- ['created_at','updated_at'].include?(col)
170
- possible_ts << [col, !col_type[3]]
171
- next
172
- end
173
-
174
- sql_type ||= col_type.first
172
+ sql_type = SQL_TYPES[col_type.first] || col_type.first
175
173
  suffix = col_type[3] ? +', null: false' : +''
176
174
  if !is_4x_rails && klass && (comment = klass.columns_hash.fetch(col, nil)&.comment)&.present?
177
175
  suffix << ", comment: #{comment.inspect}"
@@ -201,7 +199,14 @@ module Brick
201
199
  mig << " t.references :#{fk[:assoc_name]}#{suffix}, foreign_key: { to_table: #{to_table} }\n"
202
200
  end
203
201
  else
204
- mig << emit_column(sql_type, col, suffix)
202
+ next if !id_option&.end_with?('id: false') && pkey_cols.include?(col)
203
+
204
+ # See if there are generic timestamps
205
+ if sql_type == 'timestamp' && ['created_at','updated_at'].include?(col)
206
+ possible_ts << [col, !col_type[3]]
207
+ else
208
+ mig << emit_column(sql_type, col, suffix)
209
+ end
205
210
  end
206
211
  end
207
212
  if possible_ts.length == 2 && # Both created_at and updated_at
@@ -212,6 +217,7 @@ module Brick
212
217
  possible_ts.each { |ts| emit_column('timestamp', ts.first, nil) }
213
218
  end
214
219
  mig << " end\n"
220
+ mig << " execute('ALTER TABLE #{tbl} ADD PRIMARY KEY (#{pk_is_also_fk});')\n" if pk_is_also_fk
215
221
  add_fks.each do |add_fk|
216
222
  is_commented = false
217
223
  # add_fk[2] holds the inverse relation
@@ -224,9 +230,13 @@ module Brick
224
230
  # to_table column
225
231
  mig << " #{'# ' if is_commented}add_foreign_key #{tbl_code}, #{add_fk[0]}, column: :#{add_fk[1]}, primary_key: :#{pk}\n"
226
232
  end
233
+ unless built_schemas.key?(schema)
234
+ mig << " drop_schema :#{schema} if reverting? && schema_exists?(:#{schema})\n"
235
+ built_schemas[schema] = nil
236
+ end
227
237
  mig << " end\nend\n"
228
238
  current_mig_time += 1.minute
229
- versions << (version = current_mig_time.strftime('%Y%m%d%H%M00'))
239
+ versions_to_create << (version = current_mig_time.strftime('%Y%m%d%H%M00')).split('_').first
230
240
  File.open("#{mig_path}/#{version}_create_#{full_table_name}.rb", "w") { |f| f.write mig }
231
241
  end
232
242
  done.concat(fringe)
@@ -250,9 +260,23 @@ module Brick
250
260
  }:"
251
261
  pp stuck_sorted[0..4]
252
262
  else # Successful, and now we can update the schema_migrations table accordingly
253
- ActiveRecord::Base.execute_sql("INSERT INTO #{ActiveRecord::Base.schema_migrations_table_name} (version) VALUES #{
254
- versions.map { |version| "('#{version}')" }.join(', ')
255
- }")
263
+ unless ActiveRecord::Migration.table_exists?(ActiveRecord::Base.schema_migrations_table_name)
264
+ ActiveRecord::SchemaMigration.create_table
265
+ end
266
+ # Remove to_delete - to_create
267
+ if ((versions_to_delete_or_append ||= []) - versions_to_create).present? && is_delete_versions
268
+ ActiveRecord::Base.execute_sql("DELETE FROM #{
269
+ ActiveRecord::Base.schema_migrations_table_name} WHERE version IN (#{
270
+ (versions_to_delete_or_append - versions_to_create).map { |vtd| "'#{vtd}'" }.join(', ')}
271
+ )")
272
+ end
273
+ # Add to_create - to_delete
274
+ if is_insert_versions && ((versions_to_create ||= []) - versions_to_delete_or_append).present?
275
+ ActiveRecord::Base.execute_sql("INSERT INTO #{
276
+ ActiveRecord::Base.schema_migrations_table_name} (version) VALUES #{
277
+ (versions_to_create - versions_to_delete_or_append).map { |vtc| "('#{vtc}')" }.join(', ')
278
+ }")
279
+ end
256
280
  end
257
281
  end
258
282
 
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.56
4
+ version: 1.0.57
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-08-09 00:00:00.000000000 Z
11
+ date: 2022-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord