Skip to content

Commit

Permalink
Customize defaults and primary key in migrations
Browse files Browse the repository at this point in the history
Part of #96 #97

This covers just the migration side
  • Loading branch information
paulcsmith committed Jun 30, 2019
1 parent 8ac00ba commit 20e2cb6
Show file tree
Hide file tree
Showing 21 changed files with 129 additions and 36 deletions.
2 changes: 2 additions & 0 deletions db/migrations/20170127143149_create_users.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
class CreateUsers::V20170127143149 < Avram::Migrator::Migration::V1
def migrate
create :users do
primary_key id : Int32
add_timestamps
add name : String
add nickname : String?
add age : Int32
Expand Down
2 changes: 2 additions & 0 deletions db/migrations/20170127143150_create_admins.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
class CreateAdmins::V20170127143150 < Avram::Migrator::Migration::V1
def migrate
create :admins do
primary_key id : Int32
add_timestamps
add name : String
end
end
Expand Down
2 changes: 2 additions & 0 deletions db/migrations/20170127143151_create_sign_in_credentials.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
class CreateSignInCredentials::V20170127143151 < Avram::Migrator::Migration::V1
def migrate
create :sign_in_credentials do
primary_key id : Int32
add_timestamps
add user_id : Int32
end
end
Expand Down
4 changes: 4 additions & 0 deletions db/migrations/20171006163153_create_posts_and_comments.cr
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
class CreatePostsAndComments::V20171006163153 < Avram::Migrator::Migration::V1
def migrate
create :posts do
primary_key id : Int32
add_timestamps
add title : String
end

create :comments do
primary_key id : Int32
add_timestamps
add body : String
add post_id : Int32
end
Expand Down
4 changes: 4 additions & 0 deletions db/migrations/20171130064637_create_managers_and_employees.cr
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
class CreateManagersAndEmployees::V20171130064637 < Avram::Migrator::Migration::V1
def migrate
create :managers do
primary_key id : Int32
add_timestamps
add name : String
end

create :employees do
primary_key id : Int32
add_timestamps
add name : String
add manager_id : Int32?
end
Expand Down
2 changes: 2 additions & 0 deletions db/migrations/20180113081408_create_companies.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
class CreateCompanies::V20180113081408 < Avram::Migrator::Migration::V1
def migrate
create :companies do
primary_key id : Int32
add_timestamps
add sales : Int64
add earnings : Float
end
Expand Down
4 changes: 4 additions & 0 deletions db/migrations/20180115194734_create_taggings.cr
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
class CreateTaggings::V20180115194734 < Avram::Migrator::Migration::V1
def migrate
create :tags do
primary_key id : Int32
add_timestamps
add name : String
end

create :taggings do
primary_key id : Int32
add_timestamps
add_belongs_to tag : Tag, on_delete: :cascade
add_belongs_to post : Post, on_delete: :cascade
end
Expand Down
6 changes: 6 additions & 0 deletions db/migrations/20180612221318_create_businesses.cr
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
class CreateBusinesses::V20180612221318 < Avram::Migrator::Migration::V1
def migrate
create :businesses do
primary_key id : Int32
add_timestamps
add name : String
end

create :tax_ids do
primary_key id : Int32
add_timestamps
add number : Int32
add_belongs_to business : Business, on_delete: :cascade
end

create :email_addresses do
primary_key id : Int32
add_timestamps
add address : String
add_belongs_to business : Business?, on_delete: :cascade
end
Expand Down
4 changes: 3 additions & 1 deletion db/migrations/20180625202051_create_line_item.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
class CreateLineItem::V20180625202051 < Avram::Migrator::Migration::V1
def migrate
create :line_items, primary_key_type: :uuid do
create :line_items do
primary_key id : UUID
add_timestamps
add name : String
end
end
Expand Down
5 changes: 4 additions & 1 deletion db/migrations/20180628193054_create_product.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
class CreateProduct::V20180628193054 < Avram::Migrator::Migration::V1
def migrate
create :products, primary_key_type: :uuid
create :products do
primary_key id : UUID
add_timestamps
end
end

def rollback
Expand Down
2 changes: 2 additions & 0 deletions db/migrations/20180802180356_create_blobs.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
class CreateBlobs::V20180802180356 < Avram::Migrator::Migration::V1
def migrate
create :blobs do
primary_key id : Int32
add_timestamps
add doc : JSON::Any?, default: JSON::Any.new({ "defa'ult" => JSON::Any.new("val'ue") })
end
end
Expand Down
2 changes: 2 additions & 0 deletions db/migrations/20180802180357_test_defaults.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
class TestDefaults::V20180802180357 < Avram::Migrator::Migration::V1
def migrate
create :test_defaults do
primary_key id : Int32
add_timestamps
add greeting : String, default: "Hello there!"
add drafted_at : Time, default: :now
add published_at : Time, default: 1.day.from_now
Expand Down
37 changes: 17 additions & 20 deletions spec/migrator/create_table_statement_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ describe Avram::Migrator::CreateTableStatement do

built.statements.size.should eq 1
built.statements.first.should eq <<-SQL
CREATE TABLE users (
id serial PRIMARY KEY,
created_at timestamptz NOT NULL,
updated_at timestamptz NOT NULL);
CREATE TABLE users (\n);
SQL
end

it "can create tables" do
built = Avram::Migrator::CreateTableStatement.new(:users).build do
primary_key id : Int32
add_timestamps
add name : String
add age : Int32
add completed : Bool
Expand Down Expand Up @@ -43,18 +42,25 @@ describe Avram::Migrator::CreateTableStatement do
SQL
end

it "can create tables with uuid primary keys" do
built = Avram::Migrator::CreateTableStatement.new(:users, Avram::Migrator::PrimaryKeyType::UUID).build do
add name : String
it "can create tables with other primary keys" do
built = Avram::Migrator::CreateTableStatement.new(:users).build do
primary_key id : UUID
end

built.statements.size.should eq 1
built.statements.first.should eq <<-SQL
CREATE TABLE users (
id uuid PRIMARY KEY,
created_at timestamptz NOT NULL,
updated_at timestamptz NOT NULL,
name text NOT NULL);
id uuid PRIMARY KEY);
SQL

built = Avram::Migrator::CreateTableStatement.new(:users).build do
primary_key custom_id_name : Int64
end

built.statements.size.should eq 1
built.statements.first.should eq <<-SQL
CREATE TABLE users (
custom_id_name bigserial PRIMARY KEY);
SQL
end

Expand All @@ -74,9 +80,6 @@ describe Avram::Migrator::CreateTableStatement do
built.statements.size.should eq 1
built.statements.first.should eq <<-SQL
CREATE TABLE users (
id serial PRIMARY KEY,
created_at timestamptz NOT NULL,
updated_at timestamptz NOT NULL,
name text NOT NULL DEFAULT 'name',
email text DEFAULT 'optional',
age int NOT NULL DEFAULT '1',
Expand All @@ -102,9 +105,6 @@ describe Avram::Migrator::CreateTableStatement do
built.statements.size.should eq 4
built.statements.first.should eq <<-SQL
CREATE TABLE users (
id serial PRIMARY KEY,
created_at timestamptz NOT NULL,
updated_at timestamptz NOT NULL,
name text NOT NULL,
age int NOT NULL,
email text NOT NULL);
Expand Down Expand Up @@ -144,9 +144,6 @@ describe Avram::Migrator::CreateTableStatement do

built.statements.first.should eq <<-SQL
CREATE TABLE comments (
id serial PRIMARY KEY,
created_at timestamptz NOT NULL,
updated_at timestamptz NOT NULL,
user_id int NOT NULL REFERENCES users ON DELETE CASCADE,
post_id int REFERENCES posts ON DELETE RESTRICT,
category_label_id int NOT NULL REFERENCES custom_table ON DELETE SET NULL,
Expand Down
11 changes: 11 additions & 0 deletions src/avram/migrator/columns/primary_keys/base.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
abstract class Avram::Migrator::Columns::PrimaryKeys::Base
macro inherited
private getter name : String
end

abstract def column_type

def build : String
%( #{name} #{column_type} PRIMARY KEY)
end
end
12 changes: 12 additions & 0 deletions src/avram/migrator/columns/primary_keys/int32_primary_key.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require "./base"

module Avram::Migrator::Columns::PrimaryKeys
class Int32PrimaryKey < Base
def initialize(@name)
end

def column_type : String
"serial"
end
end
end
12 changes: 12 additions & 0 deletions src/avram/migrator/columns/primary_keys/int64_primary_key.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require "./base"

module Avram::Migrator::Columns::PrimaryKeys
class Int64PrimaryKey < Base
def initialize(@name)
end

def column_type : String
"bigserial"
end
end
end
12 changes: 12 additions & 0 deletions src/avram/migrator/columns/primary_keys/uuid_primary_key.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require "./base"

module Avram::Migrator::Columns::PrimaryKeys
class UUIDPrimaryKey < Base
def initialize(@name)
end

def column_type : String
"uuid"
end
end
end
25 changes: 13 additions & 12 deletions src/avram/migrator/create_table_statement.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class Avram::Migrator::CreateTableStatement

private getter rows = [] of String

def initialize(@table_name : Symbol, @primary_key_type : PrimaryKeyType = PrimaryKeyType::Serial)
def initialize(@table_name : Symbol)
end

# Accepts a block to build a table and indices using `add` and `add_index` methods.
Expand Down Expand Up @@ -52,27 +52,28 @@ class Avram::Migrator::CreateTableStatement
private def table_statement
String.build do |statement|
statement << initial_table_statement
statement << ",\n" unless rows.empty?

statement << rows.join(",\n")
statement << ");"
end
end

private def initial_table_statement
id_column_type = if @primary_key_type == PrimaryKeyType::UUID
"uuid"
else
"serial"
end
<<-SQL
CREATE TABLE #{@table_name} (
id #{id_column_type} PRIMARY KEY,
created_at timestamptz NOT NULL,
updated_at timestamptz NOT NULL
CREATE TABLE #{@table_name} (\n
SQL
end

macro primary_key(type_declaration)
rows << Avram::Migrator::Columns::PrimaryKeys::{{ type_declaration.type }}PrimaryKey
.new(name: {{ type_declaration.var.stringify }})
.build
end

macro add_timestamps
add created_at : Time
add updated_at : Time
end

macro add(type_declaration, default = nil, index = false, unique = false, using = :btree, **type_options)
{% if type_declaration.type.is_a?(Union) %}
{% type = type_declaration.type.types.first %}
Expand Down
10 changes: 10 additions & 0 deletions src/avram/migrator/migration.cr
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ abstract class Avram::Migrator::Migration::V1
yield tx
end
end
rescue e : PQ::PQError
raise <<-ERROR
There was a problem running this statement:
#{statements.join("\n")}
Problem:
#{e.message}
ERROR
end

def reset_prepared_statements
Expand Down
4 changes: 2 additions & 2 deletions src/avram/migrator/statement_helpers.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ require "./index_statement_helpers"
module Avram::Migrator::StatementHelpers
include Avram::Migrator::IndexStatementHelpers

macro create(table_name, primary_key_type = Avram::Migrator::PrimaryKeyType::Serial)
statements = Avram::Migrator::CreateTableStatement.new({{ table_name }}, {{ primary_key_type }}).build do
macro create(table_name)
statements = Avram::Migrator::CreateTableStatement.new({{ table_name }}).build do
{{ yield }}
end.statements

Expand Down
3 changes: 3 additions & 0 deletions src/avram/tasks/gen/migration.ecr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ class <%= migration_class_name %> < Avram::Migrator::Migration::V1
<%= formatted_migrate_contents %>
<%- else -%>
# create :things do
# primary_key id : Int64
# add_timestamps
#
# add title : String
# add description : String?
# end
Expand Down

0 comments on commit 20e2cb6

Please sign in to comment.