declare_schema 0.5.0.pre.2 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/declare_schema_build.yml +60 -0
  3. data/.gitignore +1 -0
  4. data/Appraisals +21 -4
  5. data/CHANGELOG.md +31 -1
  6. data/Gemfile +1 -2
  7. data/Gemfile.lock +4 -6
  8. data/README.md +4 -4
  9. data/Rakefile +17 -4
  10. data/bin/declare_schema +1 -1
  11. data/declare_schema.gemspec +1 -1
  12. data/gemfiles/rails_4_mysql.gemfile +22 -0
  13. data/gemfiles/{rails_4.gemfile → rails_4_sqlite.gemfile} +1 -2
  14. data/gemfiles/rails_5_mysql.gemfile +22 -0
  15. data/gemfiles/{rails_5.gemfile → rails_5_sqlite.gemfile} +1 -2
  16. data/gemfiles/rails_6_mysql.gemfile +22 -0
  17. data/gemfiles/{rails_6.gemfile → rails_6_sqlite.gemfile} +2 -3
  18. data/lib/declare_schema/command.rb +10 -3
  19. data/lib/declare_schema/model.rb +1 -1
  20. data/lib/declare_schema/model/field_spec.rb +18 -14
  21. data/lib/declare_schema/model/foreign_key_definition.rb +1 -1
  22. data/lib/declare_schema/model/table_options_definition.rb +8 -6
  23. data/lib/declare_schema/version.rb +1 -1
  24. data/lib/generators/declare_schema/migration/migrator.rb +80 -30
  25. data/spec/lib/declare_schema/field_spec_spec.rb +69 -0
  26. data/spec/lib/declare_schema/generator_spec.rb +25 -10
  27. data/spec/lib/declare_schema/interactive_primary_key_spec.rb +8 -2
  28. data/spec/lib/declare_schema/migration_generator_spec.rb +285 -158
  29. data/spec/lib/declare_schema/model/index_definition_spec.rb +4 -5
  30. data/spec/lib/declare_schema/model/table_options_definition_spec.rb +19 -29
  31. data/spec/lib/generators/declare_schema/migration/migrator_spec.rb +17 -22
  32. data/spec/support/acceptance_spec_helpers.rb +3 -3
  33. metadata +11 -7
  34. data/.travis.yml +0 -37
@@ -88,7 +88,7 @@ module DeclareSchema
88
88
  add_formatting_for_field(name, type)
89
89
  add_validations_for_field(name, type, args, options)
90
90
  add_index_for_field(name, args, options)
91
- field_specs[name] = ::DeclareSchema::Model::FieldSpec.new(self, name, type, options)
91
+ field_specs[name] = ::DeclareSchema::Model::FieldSpec.new(self, name, type, position: field_specs.size, **options)
92
92
  attr_order << name unless attr_order.include?(name)
93
93
  end
94
94
 
@@ -13,7 +13,6 @@ module DeclareSchema
13
13
  MYSQL_TEXT_LIMITS_ASCENDING = [MYSQL_TINYTEXT_LIMIT, MYSQL_TEXT_LIMIT, MYSQL_MEDIUMTEXT_LIMIT, MYSQL_LONGTEXT_LIMIT].freeze
14
14
 
15
15
  class << self
16
- # method for easy stubbing in tests
17
16
  def mysql_text_limits?
18
17
  if defined?(@mysql_text_limits)
19
18
  @mysql_text_limits
@@ -33,7 +32,8 @@ module DeclareSchema
33
32
 
34
33
  attr_reader :model, :name, :type, :position, :options
35
34
 
36
- def initialize(model, name, type, options = {})
35
+ def initialize(model, name, type, position: 0, **options)
36
+ # TODO: TECH-5116
37
37
  # Invoca change - searching for the primary key was causing an additional database read on every model load. Assume
38
38
  # "id" which works for invoca.
39
39
  # raise ArgumentError, "you cannot provide a field spec for the primary key" if name == model.primary_key
@@ -43,9 +43,8 @@ module DeclareSchema
43
43
  @name = name.to_sym
44
44
  type.is_a?(Symbol) or raise ArgumentError, "type must be a Symbol; got #{type.inspect}"
45
45
  @type = type
46
- position_option = options.delete(:position)
46
+ @position = position
47
47
  @options = options
48
-
49
48
  case type
50
49
  when :text
51
50
  @options[:default] and raise "default may not be given for :text field #{model}##{@name}"
@@ -54,11 +53,20 @@ module DeclareSchema
54
53
  end
55
54
  when :string
56
55
  @options[:limit] or raise "limit must be given for :string field #{model}##{@name}: #{@options.inspect}; do you want `limit: 255`?"
56
+ when :bigint
57
+ @type = :integer
58
+ @options = options.merge(limit: 8)
59
+ end
60
+
61
+ if type.in?([:text, :string])
62
+ if ActiveRecord::Base.connection.class.name.match?(/mysql/i)
63
+ @options[:charset] ||= model.table_options[:charset] || Generators::DeclareSchema::Migration::Migrator.default_charset
64
+ @options[:collation] ||= model.table_options[:collation] || Generators::DeclareSchema::Migration::Migrator.default_collation
65
+ end
57
66
  else
58
- @options[:collation] and raise "collation may only given for :string and :text fields"
59
67
  @options[:charset] and raise "charset may only given for :string and :text fields"
68
+ @options[:collation] and raise "collation may only given for :string and :text fields"
60
69
  end
61
- @position = position_option || model.field_specs.length
62
70
  end
63
71
 
64
72
  TYPE_SYNONYMS = { timestamp: :datetime }.freeze
@@ -105,16 +113,12 @@ module DeclareSchema
105
113
  @options[:default]
106
114
  end
107
115
 
108
- def collation
109
- if ActiveRecord::Base.connection.class.name.match?(/mysql/i)
110
- (@options[:collation] || model.table_options[:collation] || Generators::DeclareSchema::Migration::Migrator.default_collation).to_s
111
- end
116
+ def charset
117
+ @options[:charset]
112
118
  end
113
119
 
114
- def charset
115
- if ActiveRecord::Base.connection.class.name.match?(/mysql/i)
116
- (@options[:charset] || model.table_options[:charset] || Generators::DeclareSchema::Migration::Migrator.default_charset).to_s
117
- end
120
+ def collation
121
+ @options[:collation]
118
122
  end
119
123
 
120
124
  def same_type?(col_spec)
@@ -50,7 +50,7 @@ module DeclareSchema
50
50
 
51
51
  attr_writer :parent_table_name
52
52
 
53
- def to_add_statement
53
+ def to_add_statement(_new_table_name = nil, _existing_primary_key = nil)
54
54
  statement = "ALTER TABLE #{@child_table} ADD CONSTRAINT #{@constraint_name} FOREIGN KEY #{@index_name}(#{@foreign_key_name}) REFERENCES #{parent_table_name}(id) #{'ON DELETE CASCADE' if on_delete_cascade}"
55
55
  "execute #{statement.inspect}"
56
56
  end
@@ -26,12 +26,14 @@ module DeclareSchema
26
26
 
27
27
  def mysql_table_options(connection, table_name)
28
28
  database = connection.current_database
29
- defaults = connection.select_one(<<~EOS)
29
+ defaults = connection.select_one(<<~EOS) or raise "no defaults found for table #{table_name}"
30
30
  SELECT CCSA.character_set_name, CCSA.collation_name
31
- FROM information_schema.`TABLES` T, information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA
32
- WHERE CCSA.collation_name = T.table_collation AND
33
- T.table_schema = '#{connection.quote_string(database)}' AND
34
- T.table_name = '#{connection.quote_string(table_name)}';
31
+ FROM information_schema.TABLES as T
32
+ JOIN information_schema.COLLATION_CHARACTER_SET_APPLICABILITY as CCSA
33
+ ON CCSA.collation_name = T.table_collation
34
+ WHERE
35
+ T.table_schema = '#{connection.quote_string(database)}' AND
36
+ T.table_name = '#{connection.quote_string(table_name)}'
35
37
  EOS
36
38
 
37
39
  defaults["character_set_name"] or raise "character_set_name missing from #{defaults.inspect}"
@@ -75,7 +77,7 @@ module DeclareSchema
75
77
  alias to_s settings
76
78
 
77
79
  def alter_table_statement
78
- statement = "ALTER TABLE #{ActiveRecord::Base.connection.quote_table_name(table_name)} #{to_s};"
80
+ statement = "ALTER TABLE #{ActiveRecord::Base.connection.quote_table_name(table_name)} #{to_s}"
79
81
  "execute #{statement.inspect}"
80
82
  end
81
83
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeclareSchema
4
- VERSION = "0.5.0.pre.2"
4
+ VERSION = "0.6.2"
5
5
  end
@@ -23,6 +23,10 @@ module Generators
23
23
  end
24
24
  end
25
25
 
26
+ def table_options
27
+ {}
28
+ end
29
+
26
30
  def table_name
27
31
  join_table
28
32
  end
@@ -33,11 +37,9 @@ module Generators
33
37
 
34
38
  def field_specs
35
39
  i = 0
36
- foreign_keys.reduce({}) do |h, v|
37
- # some trickery to avoid an infinite loop when FieldSpec#initialize tries to call model.field_specs
38
- h[v] = ::DeclareSchema::Model::FieldSpec.new(self, v, :integer, position: i, null: false)
40
+ foreign_keys.each_with_object({}) do |v, result|
41
+ result[v] = ::DeclareSchema::Model::FieldSpec.new(self, v, :integer, position: i, null: false)
39
42
  i += 1
40
- h
41
43
  end
42
44
  end
43
45
 
@@ -69,8 +71,8 @@ module Generators
69
71
  class Migrator
70
72
  class Error < RuntimeError; end
71
73
 
72
- DEFAULT_CHARSET = :utf8mb4
73
- DEFAULT_COLLATION = :utf8mb4_general
74
+ DEFAULT_CHARSET = "utf8mb4"
75
+ DEFAULT_COLLATION = "utf8mb4_bin"
74
76
 
75
77
  @ignore_models = []
76
78
  @ignore_tables = []
@@ -80,9 +82,18 @@ module Generators
80
82
  @default_collation = DEFAULT_COLLATION
81
83
 
82
84
  class << self
83
- attr_accessor :ignore_models, :ignore_tables, :disable_indexing, :disable_constraints,
84
- :active_record_class, :default_charset, :default_collation
85
- attr_reader :before_generating_migration_callback
85
+ attr_accessor :ignore_models, :ignore_tables, :disable_indexing, :disable_constraints
86
+ attr_reader :active_record_class, :default_charset, :default_collation, :before_generating_migration_callback
87
+
88
+ def default_charset=(charset)
89
+ charset.is_a?(String) or raise ArgumentError, "charset must be a string (got #{charset.inspect})"
90
+ @default_charset = charset
91
+ end
92
+
93
+ def default_collation=(collation)
94
+ collation.is_a?(String) or raise ArgumentError, "collation must be a string (got #{collation.inspect})"
95
+ @default_collation = collation
96
+ end
86
97
 
87
98
  def active_record_class
88
99
  @active_record_class.is_a?(Class) or @active_record_class = @active_record_class.to_s.constantize
@@ -423,7 +434,7 @@ module Generators
423
434
  else
424
435
  [":integer"]
425
436
  end
426
- "add_column :#{new_table_name}, :#{c}, #{args.join(', ')}"
437
+ ["add_column :#{new_table_name}, :#{c}", *args].join(', ')
427
438
  end
428
439
  undo_adds = to_add.map do |c|
429
440
  "remove_column :#{new_table_name}, :#{c}"
@@ -452,8 +463,8 @@ module Generators
452
463
  change_spec[:scale] = spec.scale unless spec.scale.nil?
453
464
  change_spec[:null] = spec.null unless spec.null && col.null
454
465
  change_spec[:default] = spec.default unless spec.default.nil? && col.default.nil?
455
- change_spec[:collation] = spec.collation unless spec.collation.nil?
456
466
  change_spec[:charset] = spec.charset unless spec.charset.nil?
467
+ change_spec[:collation] = spec.collation unless spec.collation.nil?
457
468
 
458
469
  changes << "change_column :#{new_table_name}, :#{c}, " +
459
470
  ([":#{spec.sql_type}"] + format_options(change_spec, spec.sql_type, changing: true)).join(", ")
@@ -462,7 +473,7 @@ module Generators
462
473
  end
463
474
  end.compact
464
475
 
465
- index_changes, undo_index_changes = change_indexes(model, current_table_name)
476
+ index_changes, undo_index_changes = change_indexes(model, current_table_name, to_remove)
466
477
  fk_changes, undo_fk_changes = if ActiveRecord::Base.connection.class.name.match?(/SQLite3Adapter/)
467
478
  [[], []]
468
479
  else
@@ -484,7 +495,7 @@ module Generators
484
495
  undo_table_options_changes * "\n"]
485
496
  end
486
497
 
487
- def change_indexes(model, old_table_name)
498
+ def change_indexes(model, old_table_name, to_remove)
488
499
  return [[], []] if Migrator.disable_constraints
489
500
 
490
501
  new_table_name = model.table_name
@@ -497,7 +508,10 @@ module Generators
497
508
  end
498
509
  end || i
499
510
  end
500
- existing_has_primary_key = existing_indexes.any? { |i| i.name == ::DeclareSchema::Model::IndexDefinition::PRIMARY_KEY_NAME }
511
+ existing_has_primary_key = existing_indexes.any? do |i|
512
+ i.name == ::DeclareSchema::Model::IndexDefinition::PRIMARY_KEY_NAME &&
513
+ !i.fields.all? { |f| to_remove.include?(f) } # if we're removing the primary key column(s), the primary key index will be removed too
514
+ end
501
515
  model_has_primary_key = model_indexes.any? { |i| i.name == ::DeclareSchema::Model::IndexDefinition::PRIMARY_KEY_NAME }
502
516
 
503
517
  add_indexes_init = model_indexes - existing_indexes
@@ -555,12 +569,13 @@ module Generators
555
569
 
556
570
  def format_options(options, type, changing: false)
557
571
  options.map do |k, v|
558
- unless changing
559
- next if k == :limit && (type == :decimal || v == native_types[type][:limit])
560
- next if k == :null && v == true
572
+ if !changing && ((k == :limit && type == :decimal) || (k == :null && v == true))
573
+ next
561
574
  end
562
575
 
563
- next if k == :limit && type == :text && !::DeclareSchema::Model::FieldSpec.mysql_text_limits?
576
+ if !::DeclareSchema::Model::FieldSpec.mysql_text_limits? && k == :limit && type == :text
577
+ next
578
+ end
564
579
 
565
580
  if k.is_a?(Symbol)
566
581
  "#{k}: #{v.inspect}"
@@ -574,9 +589,9 @@ module Generators
574
589
  foreign_key = model.constraint_specs.find { |fk| field_name == fk.foreign_key.to_s }
575
590
  if foreign_key && (parent_table = foreign_key.parent_table_name)
576
591
  parent_columns = connection.columns(parent_table) rescue []
577
- pk_limit =
592
+ pk_limit =
578
593
  if (pk_column = parent_columns.find { |column| column.name.to_s == "id" }) # right now foreign keys assume id is the target
579
- if Rails::VERSION::MAJOR <= 4
594
+ if Rails::VERSION::MAJOR < 5
580
595
  pk_column.cast_type.limit
581
596
  else
582
597
  pk_column.limit
@@ -605,6 +620,16 @@ module Generators
605
620
  end
606
621
  end
607
622
 
623
+ # TODO: TECH-4814 remove all methods from here through end of file
624
+ def default_collation_from_charset(charset)
625
+ case charset
626
+ when "utf8"
627
+ "utf8_general_ci"
628
+ when "utf8mb4"
629
+ "utf8mb4_general_ci"
630
+ end
631
+ end
632
+
608
633
  def revert_table(table)
609
634
  res = StringIO.new
610
635
  schema_dumper_klass = case Rails::VERSION::MAJOR
@@ -614,30 +639,55 @@ module Generators
614
639
  ActiveRecord::ConnectionAdapters::SchemaDumper
615
640
  end
616
641
  schema_dumper_klass.send(:new, ActiveRecord::Base.connection).send(:table, table, res)
617
- res.string.strip.gsub("\n ", "\n")
642
+
643
+ result = res.string.strip.gsub("\n ", "\n")
644
+ if connection.class.name.match?(/mysql/i)
645
+ if !result['options: ']
646
+ result = result.sub('",', "\", options: \"DEFAULT CHARSET=#{Generators::DeclareSchema::Migration::Migrator.default_charset} "+
647
+ "COLLATE=#{Generators::DeclareSchema::Migration::Migrator.default_collation}\",")
648
+ end
649
+ default_charset = result[/CHARSET=(\w+)/, 1] or raise "unable to find charset in #{result.inspect}"
650
+ default_collation = result[/COLLATE=(\w+)/, 1] || default_collation_from_charset(default_charset) or
651
+ raise "unable to find collation in #{result.inspect} or charset #{default_charset.inspect}"
652
+ result = result.split("\n").map do |line|
653
+ if line['t.text'] || line['t.string']
654
+ if !line['charset: ']
655
+ if line['collation: ']
656
+ line = line.sub('collation: ', "charset: #{default_charset.inspect}, collation: ")
657
+ else
658
+ line += ", charset: #{default_charset.inspect}"
659
+ end
660
+ end
661
+ line['collation: '] or line += ", collation: #{default_collation.inspect}"
662
+ end
663
+ line
664
+ end.join("\n")
665
+ end
666
+ result
618
667
  end
619
668
 
620
- def column_options_from_reverted_table(table, col_name)
669
+ def column_options_from_reverted_table(table, column)
621
670
  revert = revert_table(table)
622
- if (md = revert.match(/\s*t\.column\s+"#{col_name}",\s+(:[a-zA-Z0-9_]+)(?:,\s+(.*?)$)?/m))
671
+ if (md = revert.match(/\s*t\.column\s+"#{column}",\s+(:[a-zA-Z0-9_]+)(?:,\s+(.*?)$)?/m))
623
672
  # Ugly migration
624
673
  _, type, options = *md
625
- elsif (md = revert.match(/\s*t\.([a-z_]+)\s+"#{col_name}"(?:,\s+(.*?)$)?/m))
674
+ elsif (md = revert.match(/\s*t\.([a-z_]+)\s+"#{column}"(?:,\s+(.*?)$)?/m))
626
675
  # Sexy migration
627
- _, type, options = *md
628
- type = ":#{type}"
676
+ _, string_type, options = *md
677
+ type = ":#{string_type}"
629
678
  end
679
+ type or raise "unable to find column options for #{table}.#{column} in #{revert.inspect}"
630
680
  [type, options]
631
681
  end
632
682
 
633
- def change_column_back(table, col_name)
634
- type, options = column_options_from_reverted_table(table, col_name)
635
- "change_column :#{table}, :#{col_name}, #{type}#{', ' + options.strip if options}"
683
+ def change_column_back(table, column)
684
+ type, options = column_options_from_reverted_table(table, column)
685
+ ["change_column :#{table}, :#{column}, #{type}", options&.strip].compact.join(', ')
636
686
  end
637
687
 
638
688
  def revert_column(table, column)
639
689
  type, options = column_options_from_reverted_table(table, column)
640
- "add_column :#{table}, :#{column}, #{type}#{', ' + options.strip if options}"
690
+ ["add_column :#{table}, :#{column}, #{type}", options&.strip].compact.join(', ')
641
691
  end
642
692
  end
643
693
  end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe 'DeclareSchema Model FieldSpec' do
4
+ before do
5
+ load File.expand_path('prepare_testapp.rb', __dir__)
6
+ end
7
+
8
+ context 'There are no model columns to change' do
9
+ it '#different_to should return false for int8 == int8' do
10
+ subject = DeclareSchema::Model::FieldSpec.new(Object, :price, :integer, limit: 8, null: false, position: 0)
11
+
12
+ case Rails::VERSION::MAJOR
13
+ when 4
14
+ cast_type = ActiveRecord::Type::Integer.new(limit: 8)
15
+ col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "integer(8)", false)
16
+ else
17
+ sql_type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "integer(8)", type: :integer, limit: 8)
18
+ col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, sql_type_metadata, false, "adverts")
19
+ end
20
+
21
+ expect(subject.different_to?(subject.name, col)).to eq(false)
22
+ end
23
+
24
+ it '#different_to should return false for bigint == bigint' do
25
+ subject = DeclareSchema::Model::FieldSpec.new(Object, :price, :bigint, null: false, position: 0)
26
+
27
+ case Rails::VERSION::MAJOR
28
+ when 4
29
+ cast_type = ActiveRecord::Type::BigInteger.new(limit: 8)
30
+ col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "bigint(20)", false)
31
+ else
32
+ sql_type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "bigint(20)", type: :integer, limit: 8)
33
+ col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, sql_type_metadata, false, "adverts")
34
+ end
35
+
36
+ expect(subject.different_to?(subject.name, col)).to eq(false)
37
+ end
38
+
39
+ it '#different_to should return false for int8 == bigint' do
40
+ subject = DeclareSchema::Model::FieldSpec.new(Object, :price, :integer, limit: 8, null: false, position: 0)
41
+
42
+ case Rails::VERSION::MAJOR
43
+ when 4
44
+ cast_type = ActiveRecord::Type::BigInteger.new(limit: 8)
45
+ col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "bigint(20)", false)
46
+ else
47
+ sql_type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "bigint(20)", type: :integer, limit: 8)
48
+ col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, sql_type_metadata, false, "adverts")
49
+ end
50
+
51
+ expect(subject.different_to?(subject.name, col)).to eq(false)
52
+ end
53
+
54
+ it '#different_to should return false for bigint == int8' do
55
+ subject = DeclareSchema::Model::FieldSpec.new(Object, :price, :bigint, null: false, position: 0)
56
+
57
+ case Rails::VERSION::MAJOR
58
+ when 4
59
+ cast_type = ActiveRecord::Type::Integer.new(limit: 8)
60
+ col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "integer(8)", false)
61
+ else
62
+ sql_type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "integer(8)", type: :integer, limit: 8)
63
+ col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, sql_type_metadata, false, "adverts")
64
+ end
65
+
66
+ expect(subject.different_to?(subject.name, col)).to eq(false)
67
+ end
68
+ end
69
+ end
@@ -27,15 +27,28 @@ RSpec.describe 'DeclareSchema Migration Generator' do
27
27
  end
28
28
  EOS
29
29
 
30
- expect_test_definition_to_eq('alpha/beta', <<~EOS)
31
- require 'test_helper'
32
-
33
- class Alpha::BetaTest < ActiveSupport::TestCase
34
- # test "the truth" do
35
- # assert true
36
- # end
37
- end
38
- EOS
30
+ case Rails::VERSION::MAJOR
31
+ when 4, 5
32
+ expect_test_definition_to_eq('alpha/beta', <<~EOS)
33
+ require "test_helper"
34
+
35
+ class Alpha::BetaTest < ActiveSupport::TestCase
36
+ # test "the truth" do
37
+ # assert true
38
+ # end
39
+ end
40
+ EOS
41
+ else
42
+ expect_test_definition_to_eq('alpha/beta', <<~EOS)
43
+ require "test_helper"
44
+
45
+ class Alpha::BetaTest < ActiveSupport::TestCase
46
+ # test "the truth" do
47
+ # assert true
48
+ # end
49
+ end
50
+ EOS
51
+ end
39
52
 
40
53
  case Rails::VERSION::MAJOR
41
54
  when 4
@@ -88,7 +101,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
88
101
 
89
102
  expect(File.exist?('db/schema.rb')).to be_truthy
90
103
 
91
- expect(File.exist?("db/development.sqlite3") || File.exist?("db/test.sqlite3")).to be_truthy
104
+ if defined?(SQLite3)
105
+ expect(File.exist?("db/development.sqlite3") || File.exist?("db/test.sqlite3")).to be_truthy
106
+ end
92
107
 
93
108
  module Alpha; end
94
109
  require 'alpha/beta'