mimi-db 0.2.7 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,65 +3,26 @@ require_relative 'dictate/schema_definition'
3
3
  require_relative 'dictate/schema_diff'
4
4
  require_relative 'dictate/explorer'
5
5
  require_relative 'dictate/migrator'
6
+ require_relative 'dictate/type_defaults'
6
7
 
7
8
  module Mimi
8
9
  module DB
9
10
  module Dictate
10
- TYPE_DEFAULTS = {
11
- # sqlite3: {
12
- # string: { name: 'varchar', limit: 32 }
13
- # }
14
- }.freeze
15
-
16
11
  def self.included(base)
17
12
  base.extend Mimi::DB::Dictate::DSL
18
13
  end
19
14
 
20
15
  def self.start
21
- ActiveRecord::Base.extend Mimi::DB::Dictate::DSL
22
16
  end
23
17
 
18
+ # Returns all registered schema definitions
19
+ #
20
+ # @return [Hash] a map of <table_name> -> <schema_definition>
21
+ #
24
22
  def self.schema_definitions
25
23
  @schema_definitions ||= {}
26
24
  end
27
25
 
28
- def self.adapter_type
29
- ca = ActiveRecord::ConnectionAdapters
30
- c = ActiveRecord::Base.connection
31
-
32
- # TODO: postgres???
33
- return :cockroachdb if ca.const_defined?(:CockroachDBAdapter) && c.is_a?(ca::PostgreSQLAdapter)
34
-
35
- return :postgresql if ca.const_defined?(:PostgreSQLAdapter) && c.is_a?(ca::PostgreSQLAdapter)
36
-
37
- return :mysql if ca.const_defined?(:AbstractMysqlAdapter) && c.is_a?(ca::AbstractMysqlAdapter)
38
-
39
- return :sqlite3 if ca.const_defined?(:SQLite3Adapter) && c.is_a?(ca::SQLite3Adapter)
40
-
41
- raise 'Unrecognized database adapter type'
42
- end
43
-
44
- # Returns type defaults based on given type:
45
- # :string
46
- # :text
47
- # :integer etc
48
- #
49
- def self.type_defaults(type)
50
- type = type.to_sym
51
- connection_defaults = ActiveRecord::Base.connection.native_database_types
52
- adapter_defaults = TYPE_DEFAULTS[DB::Dictate.adapter_type]
53
- d = (adapter_defaults && adapter_defaults[type]) || connection_defaults[type] || {}
54
- d = {
55
- sql_type: d.is_a?(String) ? d : d[:name],
56
- limit: d.is_a?(String) ? nil : d[:limit]
57
- }
58
- if type == :primary_key
59
- d[:primary_key] = true
60
- d[:not_null] = true
61
- end
62
- d
63
- end
64
-
65
26
  # Updates the DB schema to the target schema defined in models
66
27
  #
67
28
  # Default options from Migrator::DEFAULTS:
@@ -71,18 +32,18 @@ module Mimi
71
32
  # indexes: false
72
33
  # },
73
34
  # dry_run: false,
74
- # logger: nil # will use ActiveRecord::Base.logger
35
+ # logger: nil # will use Mimi::DB.logger
75
36
  #
76
37
  # @param opts [Hash]
77
38
  #
78
39
  def self.update_schema!(opts = {})
79
- logger = opts[:logger] || ActiveRecord::Base.logger
80
- logger.info "Mimi::DB::Dictate started updating DB schema"
40
+ logger = opts[:logger] || Mimi::DB.logger
41
+ logger.debug 'Mimi::DB::Dictate started updating DB schema'
81
42
  t_start = Time.now
82
43
  Mimi::DB.all_table_names.each { |t| Mimi::DB::Dictate::Migrator.new(t, opts).run! }
83
- logger.info 'Mimi::DB::Dictate finished updating DB schema (%.3fs)' % [Time.now - t_start]
44
+ logger.debug 'Mimi::DB::Dictate finished updating DB schema (%.3fs)' % [Time.now - t_start]
84
45
  rescue StandardError => e
85
- logger.error "DB::Dictate failed to update DB schema: #{e}"
46
+ logger.error "Mimi::DB::Dictate failed to update DB schema: #{e}"
86
47
  raise
87
48
  end
88
49
 
@@ -92,22 +53,23 @@ module Mimi
92
53
  # @return [Hash]
93
54
  #
94
55
  def self.diff_schema(opts = {})
95
- logger = opts[:logger] || ActiveRecord::Base.logger
96
- diff = { add_tables: [], change_tables: [], drop_tables: []}
56
+ logger = opts[:logger] || Mimi::DB.logger
57
+ diff = { add_tables: [], change_tables: [], drop_tables: [] }
97
58
  Mimi::DB.all_table_names.each do |t|
98
59
  m = Mimi::DB::Dictate::Migrator.new(t, opts)
99
60
  if m.from_schema && m.to_schema.nil?
100
61
  diff[:drop_tables] << t
101
62
  elsif m.from_schema && m.to_schema
63
+ logger.debug "DB::Dictate comparing '#{t}'"
102
64
  t_diff = Mimi::DB::Dictate::SchemaDiff.diff(m.from_schema, m.to_schema)
103
65
  diff[:change_tables] << t_diff unless t_diff[:columns].empty? && t_diff[:indexes].empty?
104
- elsif m.from_schema.nil? && m.to_schema
66
+ elsif m.from_schema.nil? && m.to_schema
105
67
  diff[:add_tables] << m.to_schema
106
68
  end
107
69
  end
108
70
  diff
109
71
  rescue StandardError => e
110
- logger.error "DB::Dictate failed to update DB schema: #{e}"
72
+ logger.error "DB::Dictate failed to compare schema: #{e}"
111
73
  raise
112
74
  end
113
75
  end # module Dictate
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sequel/adapters/postgres'
4
+
5
+ module Sequel
6
+ #
7
+ # A simplistic and not fully functional CockroachDB adapter
8
+ #
9
+ # TODO: to replace with a better alternative once available
10
+ #
11
+ module Cockroach
12
+ class Database < Sequel::Postgres::Database
13
+ set_adapter_scheme :cockroach
14
+ set_adapter_scheme :cockroachdb
15
+
16
+ # Cockroach DB only supports one savepoint
17
+ def supports_savepoints?
18
+ false
19
+ end
20
+
21
+ def server_version(*)
22
+ 80000 # mimics Postgres v8
23
+ # 100000 # mimics Postgres v10
24
+ end
25
+
26
+ private
27
+
28
+ def dataset_class_default
29
+ Dataset
30
+ end
31
+ end
32
+
33
+ class Dataset < Sequel::Postgres::Dataset
34
+ def default_timestamp_format
35
+ "'%Y-%m-%d %H:%M:%S%N%:z'"
36
+ end
37
+ end # class Dataset
38
+ end # module Cockroach
39
+ end # module Sequel
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sequel'
4
+
5
+ module Sequel
6
+ class Database
7
+ #
8
+ # Fixed behaviour for Sequel's log_exception()
9
+ #
10
+ # Reason:
11
+ # * handled exceptions should not be logged as errors
12
+ # * unhandled exceptions will be logged at the application level
13
+ #
14
+ def log_exception(exception, message, *)
15
+ text_message = "#{self.class}(#{exception.class}): #{exception.message}"
16
+ logger_message = { m: text_message, sql: message }
17
+
18
+ # In case logger does not support structured data, implement a #to_s method
19
+ logger_message.define_singleton_method(:to_s) { text_message }
20
+ log_each(:debug, logger_message)
21
+ end
22
+ end # class Database
23
+ end # module Sequel
@@ -0,0 +1,3 @@
1
+ # require 'sequel/adapters/postgres'
2
+
3
+ # Extensions to Postgres adapter
@@ -0,0 +1,3 @@
1
+ # require 'sequel/adapters/sqlite'
2
+
3
+ # Extensions to Postgres adapter
@@ -2,16 +2,20 @@ module Mimi
2
2
  module DB
3
3
  module Extensions
4
4
  def self.start
5
- # install DB::Dictate
6
- ActiveRecord::Base.send(:include, Mimi::DB::Dictate)
7
-
8
- # FIXME: refactor DSL for primary/foreign keys
9
- # install_primary_keys!
10
- # install_bigint_foreign_keys!
11
- end
12
-
13
- def self.install_bigint_foreign_keys!
14
- # ActiveRecord::Base.send(:include, Mimi::DB::ForeignKey)
5
+ adapter_name = Mimi::DB.sequel_config[:adapter]
6
+ require_relative 'extensions/sequel-database'
7
+ case adapter_name
8
+ when 'sqlite'
9
+ require_relative 'extensions/sequel-sqlite'
10
+ when 'postgres'
11
+ require_relative 'extensions/sequel-postgres'
12
+ when 'cockroachdb'
13
+ require_relative 'extensions/sequel-postgres'
14
+ require_relative 'extensions/sequel-cockroachdb'
15
+ else
16
+ # load nothing
17
+ end
18
+ Sequel::Model.plugin :timestamps
15
19
  end
16
20
  end # module Extensions
17
21
  end # module DB
@@ -1,20 +1,22 @@
1
1
  module Mimi
2
2
  module DB
3
3
  module ForeignKey
4
- extend ActiveSupport::Concern
4
+ # TODO: refactor and re-implement
5
5
 
6
- class_methods do
6
+ # extend ActiveSupport::Concern
7
+
8
+ # class_methods do
7
9
  #
8
10
  # Explicitly specify a (bigint) foreign key
9
11
  #
10
- def foreign_key(name, opts = {})
11
- # TODO: refactor and re-implement
12
- raise 'Not implemented'
12
+ # def foreign_key(name, opts = {})
13
+
14
+ # raise 'Not implemented'
13
15
 
14
16
  # opts = { as: :integer, limit: 8 }.merge(opts)
15
17
  # field(name, opts)
16
18
  # index(name)
17
- end
19
+ # end
18
20
 
19
21
  # Redefines .belongs_to() with explicitly specified .foreign_key
20
22
  #
@@ -25,7 +27,7 @@ module Mimi
25
27
  # # orig_belongs_to(name, opts)
26
28
  # super
27
29
  # end
28
- end
30
+ # end
29
31
  end # module ForeignKey
30
32
  end # module DB
31
33
  end # module Mimi
@@ -7,7 +7,7 @@ module Mimi
7
7
  # @return [Array<ActiveRecord::Base>]
8
8
  #
9
9
  def models
10
- ActiveRecord::Base.descendants
10
+ Mimi::DB::Model.descendants
11
11
  end
12
12
 
13
13
  # Returns a list of table names defined in models
@@ -23,7 +23,7 @@ module Mimi
23
23
  # @return [Array<String>]
24
24
  #
25
25
  def db_table_names
26
- ActiveRecord::Base.connection.tables
26
+ Mimi::DB.connection.tables
27
27
  end
28
28
 
29
29
  # Returns a list of all discovered table names,
@@ -56,6 +56,7 @@ module Mimi
56
56
  # Mimi::DB.update_schema!(destructive: true)
57
57
  #
58
58
  def update_schema!(opts = {})
59
+ Mimi::DB.start
59
60
  opts[:logger] ||= Mimi::DB.logger
60
61
  Mimi::DB::Dictate.update_schema!(opts)
61
62
  end
@@ -84,6 +85,7 @@ module Mimi
84
85
  # @return [Hash]
85
86
  #
86
87
  def diff_schema(opts = {})
88
+ Mimi::DB.start
87
89
  opts[:logger] ||= Mimi::DB.logger
88
90
  Mimi::DB::Dictate.diff_schema(opts)
89
91
  end
@@ -91,29 +93,16 @@ module Mimi
91
93
  # Creates the database specified in the current configuration.
92
94
  #
93
95
  def create!
94
- db_adapter = Mimi::DB.active_record_config['adapter']
95
- db_database = Mimi::DB.active_record_config['database']
96
- slim_url = "#{db_adapter}//<host>:<port>/#{db_database}"
97
- Mimi::DB.logger.info "Mimi::DB.create! creating database: #{slim_url}"
98
- original_stdout = $stdout
99
- original_stderr = $stderr
100
- $stdout = StringIO.new
101
- $stderr = StringIO.new
102
- ActiveRecord::Tasks::DatabaseTasks.root = Mimi.app_root_path
103
- ActiveRecord::Tasks::DatabaseTasks.create(Mimi::DB.active_record_config)
104
- Mimi::DB.logger.debug "Mimi::DB.create! out:#{$stdout.string}, err:#{$stderr.string}"
105
- ensure
106
- $stdout = original_stdout
107
- $stderr = original_stderr
96
+ raise 'Not implemented'
108
97
  end
109
98
 
110
99
  # Tries to establish connection, returns true if the database exist
111
100
  #
112
101
  def database_exist?
113
- ActiveRecord::Base.establish_connection(Mimi::DB.active_record_config)
114
- ActiveRecord::Base.connection
102
+ Mimi::DB.connection.test_connection
115
103
  true
116
- rescue ActiveRecord::NoDatabaseError
104
+ rescue StandardError => e
105
+ Mimi::DB.logger.error "DB: database_exist? failed with: #{e}"
117
106
  false
118
107
  end
119
108
 
@@ -130,31 +119,17 @@ module Mimi
130
119
  # Drops the database specified in the current configuration.
131
120
  #
132
121
  def drop!
133
- original_stdout = $stdout
134
- original_stderr = $stderr
135
- $stdout = StringIO.new
136
- $stderr = StringIO.new
137
- ActiveRecord::Tasks::DatabaseTasks.root = Mimi.app_root_path
138
- ActiveRecord::Tasks::DatabaseTasks.drop(Mimi::DB.active_record_config)
139
- Mimi::DB.logger.debug "Mimi::DB.drop! out:#{$stdout.string}, err:#{$stderr.string}"
140
- ensure
141
- $stdout = original_stdout
142
- $stderr = original_stderr
122
+ raise 'Not implemented'
143
123
  end
144
124
 
145
125
  # Clears (but not drops) the database specified in the current configuration.
146
126
  #
147
127
  def clear!
148
- original_stdout = $stdout
149
- original_stderr = $stderr
150
- $stdout = StringIO.new
151
- $stderr = StringIO.new
152
- ActiveRecord::Tasks::DatabaseTasks.root = Mimi.app_root_path
153
- ActiveRecord::Tasks::DatabaseTasks.purge(Mimi::DB.active_record_config)
154
- Mimi::DB.logger.debug "Mimi::DB.clear! out:#{$stdout.string}, err:#{$stderr.string}"
155
- ensure
156
- $stdout = original_stdout
157
- $stderr = original_stderr
128
+ Mimi::DB.start
129
+ db_table_names.each do |table_name|
130
+ Mimi::DB.logger.debug "Mimi::DB dropping table: #{table_name}"
131
+ Mimi::DB.connection.drop_table(table_name)
132
+ end
158
133
  end
159
134
 
160
135
  # Executes raw SQL, with variables interpolation.
@@ -163,8 +138,31 @@ module Mimi
163
138
  # Mimi::DB.execute('insert into table1 values(?, ?, ?)', 'foo', :bar, 123)
164
139
  #
165
140
  def execute(statement, *args)
166
- sql = ActiveRecord::Base.send(:replace_bind_variables, statement, args)
167
- ActiveRecord::Base.connection.execute(sql)
141
+ sql = Sequel.fetch(statement, *args).sql
142
+ Mimi::DB.connection.run(sql)
143
+ end
144
+
145
+ # Starts a transaction and executes a given block within the transaction
146
+ #
147
+ # @param params [Hash] parameters to Sequel #transaction() method
148
+ #
149
+ def transaction(params = {}, &_block)
150
+ unless Mimi::DB.connection
151
+ raise 'Failed to start transaction, Mimi::DB.connection not available'
152
+ end
153
+ Mimi::DB.connection.transaction(params) { yield }
154
+ end
155
+
156
+ # Executes a block with a given DB log level
157
+ #
158
+ # @param log_level [Symbol,nil] :debug, :info etc
159
+ #
160
+ def with_log_level(log_level, &_block)
161
+ current_log_level = Mimi::DB.connection.sql_log_level
162
+ Mimi::DB.connection.sql_log_level = log_level
163
+ yield
164
+ ensure
165
+ Mimi::DB.connection.sql_log_level = current_log_level
168
166
  end
169
167
  end # module Helpers
170
168
 
data/lib/mimi/db/lock.rb CHANGED
@@ -49,6 +49,10 @@ module Mimi
49
49
  end
50
50
 
51
51
  def lock!(name, opts = {}, &block)
52
+ raise 'Not implemented'
53
+
54
+ # FIXME: migrate Mimi::DB::Lock to Sequel
55
+
52
56
  opts = Mimi::DB::Lock.module_options[:default_lock_options].merge(opts.dup)
53
57
  adapter_name = ActiveRecord::Base.connection.adapter_name.downcase.to_sym
54
58
  case adapter_name
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ # NOTE: this is the way to create an abstract class that inherits from Sequel::Model
4
+ Mimi::DB::Model = Class.new(Sequel::Model)
5
+
6
+ module Mimi
7
+ module DB
8
+ class Model
9
+ include Mimi::DB::Dictate
10
+
11
+ self.require_valid_table = false
12
+ plugin :timestamps, create: :created_at, update: :updated_at, update_on_create: true
13
+ plugin :validation_helpers
14
+
15
+ # Keeps messages as error types, not human readable strings
16
+ #
17
+ def default_validation_helpers_options(type)
18
+ { message: type }
19
+ end
20
+
21
+ def before_validation
22
+ super
23
+ call_hooks(:before_validation)
24
+ end
25
+
26
+ # Defines a hook the ActiveRecord way
27
+ #
28
+ # Example:
29
+ #
30
+ # class A < Mimi::DB::Model
31
+ # before_validation :set_detaults
32
+ #
33
+ # def set_defaults
34
+ # self.name = "John Doe"
35
+ # end
36
+ # end
37
+ #
38
+ def self.before_validation(method = nil, &block)
39
+ if method && block
40
+ raise ArgumentError, '.before_validation() cannot accept both method and a block'
41
+ end
42
+ block = -> { send(method) } if method
43
+ register_hook(:before_validation, block)
44
+ end
45
+
46
+ private
47
+
48
+ def self.registered_hooks(name)
49
+ @registered_hooks ||= {}
50
+ @registered_hooks[name] ||= []
51
+ end
52
+
53
+ def self.register_hook(name, block)
54
+ registered_hooks(name) << block
55
+ end
56
+
57
+ def call_hooks(name)
58
+ self.class.registered_hooks(name).each do |block|
59
+ instance_eval(&block)
60
+ end
61
+ end
62
+ end # class Model
63
+ end # module DB
64
+ end # module Mimi
@@ -1,5 +1,5 @@
1
1
  module Mimi
2
2
  module DB
3
- VERSION = '0.2.7'.freeze
3
+ VERSION = '0.3.0'.freeze
4
4
  end
5
5
  end
data/lib/mimi/db.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'mimi/core'
2
- require 'active_record'
2
+ require 'sequel'
3
3
 
4
4
  module Mimi
5
5
  module DB
@@ -13,12 +13,8 @@ module Mimi
13
13
  db_port: nil,
14
14
  db_username: nil,
15
15
  db_password: nil,
16
- db_log_level: :info,
17
- db_pool: 15,
18
- db_primary_key_cockroachdb: nil,
19
- db_primary_key_postgresql: nil,
20
- db_primary_key_mysql: nil,
21
- db_primary_key_sqlite3: nil
16
+ db_log_level: :debug,
17
+ db_pool: 15
22
18
  # db_encoding:
23
19
  )
24
20
 
@@ -58,45 +54,75 @@ module Mimi
58
54
  },
59
55
  db_log_level: {
60
56
  desc: 'Logging level for database layer ("debug", "info" etc)',
61
- default: 'info'
57
+ default: 'debug'
62
58
  }
63
59
  }
64
60
  end
65
61
 
66
62
  def self.configure(*)
67
63
  super
68
- ActiveSupport::LogSubscriber.colorize_logging = false
69
- ActiveRecord::Base.logger = logger
70
- ActiveRecord::Base.configurations = { 'default' => active_record_config }
71
-
72
- # TODO: test and remove deprectated ...
73
- # ActiveRecord::Base.raise_in_transactional_callbacks = true
64
+ if Mimi.const_defined?(:Application)
65
+ @logger = Mimi::Application.logger
66
+ end
74
67
  end
75
68
 
76
69
  def self.logger
77
- @logger ||= Mimi::Logger.new(level: module_options[:db_log_level])
70
+ @logger ||= Mimi::Logger.new
71
+ end
72
+
73
+ # Returns active DB connection
74
+ #
75
+ # @return [Sequel::<...>::Database]
76
+ #
77
+ def self.connection
78
+ @connection
78
79
  end
79
80
 
80
81
  def self.start
81
- ActiveRecord::Base.establish_connection(:default)
82
82
  Mimi::DB::Extensions.start
83
- Mimi::DB::Dictate.start
83
+ @connection = Sequel.connect(sequel_config)
84
84
  Mimi.require_files(module_options[:require_files]) if module_options[:require_files]
85
85
  super
86
86
  end
87
87
 
88
- def self.active_record_config
88
+ # Returns a standard Sequel adapter name converted from any variation of adapter names.
89
+ #
90
+ # @example
91
+ # sequel_config_canonical_adapter_name(:sqlite3) # => 'sqlite'
92
+ #
93
+ # @param adapter_name [String,Symbol]
94
+ # @return [String]
95
+ #
96
+ def self.sequel_config_canonical_adapter_name(adapter_name)
97
+ case adapter_name.to_s.downcase
98
+ when 'sqlite', 'sqlite3'
99
+ 'sqlite'
100
+ when 'postgres', 'postgresql'
101
+ 'postgres'
102
+ when 'cockroach', 'cockroachdb'
103
+ 'cockroachdb'
104
+ else
105
+ adapter_name.to_s.downcase
106
+ end
107
+ end
108
+
109
+ # Returns Sequel connection parameters
110
+ #
111
+ # @return [Hash]
112
+ #
113
+ def self.sequel_config
89
114
  {
90
- adapter: module_options[:db_adapter],
115
+ adapter: sequel_config_canonical_adapter_name(module_options[:db_adapter]),
91
116
  database: module_options[:db_database],
92
117
  host: module_options[:db_host],
93
118
  port: module_options[:db_port],
94
- username: module_options[:db_username],
119
+ user: module_options[:db_username],
95
120
  password: module_options[:db_password],
96
121
  encoding: module_options[:db_encoding],
97
- pool: module_options[:db_pool],
98
- reaping_frequency: 15
99
- }.stringify_keys
122
+ max_connections: module_options[:db_pool],
123
+ sql_log_level: module_options[:db_log_level],
124
+ logger: logger
125
+ }
100
126
  end
101
127
  end # module DB
102
128
  end # module Mimi
@@ -106,3 +132,4 @@ require_relative 'db/extensions'
106
132
  require_relative 'db/helpers'
107
133
  require_relative 'db/foreign_key'
108
134
  require_relative 'db/dictate'
135
+ require_relative 'db/model'
data/lib/tasks/db.rake CHANGED
@@ -40,17 +40,22 @@ namespace :db do
40
40
  namespace :migrate do
41
41
  desc 'Migrate database (seeds only)'
42
42
  task seeds: :"db:start" do
43
+ logger.info "* Processing database seeds: #{Mimi::DB.module_options[:db_database]}"
44
+ t_start = Time.now
43
45
  seeds = Pathname.glob(Mimi.app_path_to('db', 'seeds', '**', '*.rb')).sort
44
46
  seeds.each do |seed_filename|
45
- logger.info "* Processing seed: #{seed_filename}"
47
+ logger.info "-- Processing seed: #{seed_filename}"
46
48
  load seed_filename
47
49
  end
50
+ logger.info '* Finished processing database seeds (%.3fs)' % (Time.now - t_start)
48
51
  end
49
52
 
50
53
  desc 'Migrate database (schema only)'
51
54
  task schema: :"db:start" do
52
55
  logger.info "* Updating database schema: #{Mimi::DB.module_options[:db_database]}"
56
+ t_start = Time.now
53
57
  Mimi::DB.update_schema!(destructive: true)
58
+ logger.info '* Finished updating database schema (%.3fs)' % (Time.now - t_start)
54
59
  end
55
60
 
56
61
  namespace :schema do
@@ -88,6 +93,9 @@ namespace :db do
88
93
  diff[:drop_tables].each do |t|
89
94
  puts "-- DROP table: #{t}"
90
95
  end
96
+ if diff[:add_tables].empty? && diff[:change_tables].empty? && diff[:drop_tables].empty?
97
+ logger.info '* Diff database schema: no changes detected'
98
+ end
91
99
  end
92
100
  end
93
101
  end
data/mimi-db.gemspec CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
29
29
 
30
30
  spec.add_dependency 'mimi-core', '~> 0.2'
31
31
  spec.add_dependency 'mimi-logger', '~> 0.2'
32
- spec.add_dependency 'activerecord', '~> 5.0'
32
+ spec.add_dependency 'sequel', '~> 5.8'
33
33
 
34
34
  spec.add_development_dependency 'bundler', '~> 1.11'
35
35
  spec.add_development_dependency 'rake', '~> 10.0'