Skip to content

Instantly share code, notes, and snippets.

@Svenskunganka
Last active June 19, 2017 08:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Svenskunganka/27d7831187520bc63609ea6eceaed97c to your computer and use it in GitHub Desktop.
Save Svenskunganka/27d7831187520bc63609ea6eceaed97c to your computer and use it in GitHub Desktop.
require "../migration"
module Project
ver = 1
migration = Migration.new ver
migration.register_up { |db|
db.exec "create table version (version int)"
db.exec "insert into version values (?)", ver
true # TODO: Replace with error-checking
}
migration.register_down { |db|
db.exec "drop table version"
true # TODO: Replace with error-checking
}
migration.register
end
require "db"
require "sqlite3"
require "./migration/migrations/*"
module Project
class Database
@conn : DB::Database
def initialize(path : String)
@conn = DB.open `sqlite3://#{path}`
cur_version = get_version()
Migration.migrate(cur_version, DB_VERSION, @conn)
end
def get_version()
begin
version = @conn.query_one("select version from version limit 1", as: Int32)
rescue
version = 0
end
return version
end
end
end
Error in src/project.cr:25: instantiating 'Project::Database:Class#new(String)'
db = Database.new(db_path)
^~~
in src/project/database/database.cr:15: instantiating 'Project::Migration:Class#migrate(Int32, Int32, DB::Database)'
Migration.migrate(cur_version, DB_VERSION, @conn)
^~~~~~~
in src/project/database/migration/migration.cr:22: instantiating 'Project::Migration#up(DB::Database)'
result = @@migrations[from_version += 1].up(conn)
^~
in src/project/database/migration/migration.cr:58: undefined method 'call' for Nil (compile-time type is (Proc(DB::Database, Bool) | Nil))
result = @up.call(conn)
^~~~
require "db"
require "sqlite3"
module Project
class Migration
@@migrations = {} of Int32 => Migration
def initialize(@version : Int32)
end
# Registers the current instance and its version to
# the list of migrations
def register()
@@migrations[@version] = self
end
def self.migrate(from_version, to_version : Int32, conn : DB::Database)
while from_version < to_version
migration = @@migrations[from_version =+ 1]
migration.up(conn) unless migration == nil
end
end
# Registers a callback that will be called when the `up`-method is called.
# The callback must return either `true` for a successful migration,
# or `false` for a failed migration. If an `up` migration has
# failed, the `down` migration will be called to restore the database
# back to its previous state.
# The callback will receive an instance of `DB::Database`
#
# Example:
#
# ```
# migration = Migration.new(1)
#
# migration.register_up |db| do
# # Advance migration
# end
#
# migration.register_down |db| do
# # Recede migration
# end
# ```
def register_up(&block : DB::Database -> Bool)
@up = block
end
# Registers a callback that will be called when the `down`-method is called.
# See the `register_up` method for more information
def register_down(&block : DB::Database -> Bool)
@down = block
end
# Advances DB to the next version
def up(conn : DB::Database)
result = @up.call(conn)
unless result
# Failed migration, rollback
@down.call(conn)
raise Exception.new(`Failed to migrate database to version: #{@version}. Rolling back.`)
end
end
# Recedes DB to the previous version
def down(conn : DB::Database)
result = @down.call(conn)
unless result
# Failed migration, rollback
@up.call(conn)
raise Exception.new(`Failed to migrate database to version: #{@version - 1}. Rolling back.`)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment