{"title":"Migrations","description":"","section":"guides/models/jennifer","version":"v1.4.1","path":"guides/models/jennifer/migrations","canonical_url":"https://amberframework.org/docs/v1.4.1/guides/models/jennifer/migrations","markdown_url":"https://amberframework.org/docs/v1.4.1/guides/models/jennifer/migrations.md","inherited":false,"content_markdown":"# Migrations\n\n{% hint style=\"info\" %}\nThis section is based on [Jennifer Docs](https://github.com/imdrasil/jennifer.cr/blob/master/docs/index.md).\n{% endhint %}\n\nTo generate a migration run `crystal src/sam.cr generate:migration your_migration_name`\n\n## Migration DSL\nThe generator will create template file for you with a consistent name pattern **timestamp\\_migration\\_name.cr**. \nThe empty file looks like this:\n\n```crystal\nclass YourCamelcasedMigrationName20170119011451314 < Jennifer::Migration::Base\n  def up\n  end\n\n  def down\n  end\nend\n```\n\nThe `up` method is where your database changes go, whereas, `down` is used for reverting your changes back.\n\nExample for creating table:\n\n```crystal\ncreate_table(:addresses) do |t|\n  t.reference :contact # creates field contact_id with Int type and allows null values\n  t.string :street, {:size => 20, :sql_type => \"char\"} # creates string field with CHAR(20) db type\n  t.bool :main, {:default => false} # sets false as default value\nend\n```\n\n## Data Types and Mappings\n\n| internal alias | PostgreSQL | MySql | Crystal type |\n| :--- | :--- | :--- | :--- |\n| `#integer` | `int` | `int` | `Int32` |\n| `#string` | `varchar(254)` | `varchar(254)` | `String` |\n| `#bool` | `boolean` | `bool` | `Bool` |\n| `#char` | `char` | - | `String` |\n| `#float` | `real` | `float` | `Float32` |\n| `#double` | `double precision` | `double` | `Float64` |\n| `#short` | `smallint` | `smallint` | `Int16` |\n| `#timestamp` | `timestamp` | `timestamp` | `Time` |\n| `#date_time` | `datetime` | `datetime` | `Time` |\n| `#blob` | `blob` | `blob` | `Bytes` |\n| `#var_string` | `varchar(254)` | `varstring` | `String` |\n| `#json` | `json` | `json` | `JSON::Any` |\n| `#enum` | `enum` | `enum` | `String` |\n\nAlso if you use PostgreSQL array types are available a well: `Array(Int32)`, `Array(Char)`, `Array(Float32)`, `Array(Float64)`,`Array(Int16)`, `Array(Int32)`, `Array(Int64)`, `Array(String)`.\n\nAll of them accepts additional options:\n\n* `:sql_type`- gets exact \\(except size\\) field type;\n* `:null`- represent nullable if field \\(by default is`false`for all types and field\\);\n* `:primary`- marks field as primary key field \\(could be several ones but this provides some bugs with query generation for such model - for now try to avoid this\\).\n* `:default`- default value for field\n* `:auto_increment`- marks field to use auto increment \\(properly works only with`Int32`fields, another crystal types have cut functionality for it\\);\n* `:array`- mark field to be array type \\(Postgres only\\)\n\nAlso there is`#field`method which allows to directly define sql type \\(very suitable for enums in Postgres\\).\n\nTo drop table just write\n\n```crystal\ndrop_table(:addresses) # drops if exists\n```\n\nTo alter existing table use next methods:\n\n* `#change_column(name, [new_name], options)`- to change column definition; Postgres has slighly another implementation of this than mysql one - check source code for details;\n* `#add_column(name, type, options)`- add new column;\n* `#drop_column(name)`- drops existing column\n* `#add_index(name : String, field : Symbol, type : Symbol, order : Symbol?, length : Int32?)`- adds new index \\(Postgres doesn't support length parameter and only support`:unique`type\\);\n* `#drop_index(name : String)`- drops existing index;\n* `#rename_table(new_name)`- renames table.\n\nAlso next support methods are available:\n\n* `#table_exists?(name)`\n* `#index_exists?(table, name)`\n* `#column_exists?(table, name)`\n* `#data_type_exists?(name)`for Postgres ENUM\n\nAlso plain SQL could be executed as well:\n\n```crystal\nexecute(\"ALTER TABLE addresses CHANGE street st VARCHAR(20)\")\n```\n\nAll changes are executed one by one so you also could add data changes here \\(in`up`method\\) but if execution of`up`method fails -`down`method will be called and all process will stop - be ready for such behavior.\n\nTo be sure that your db is up to date before run tests of your application, add:\n\n```text\nJennifer::Migration::Runner.migrate\n```\n\n## Enum\n\nNow enums are supported as well but it has different implementation for adapters. For mysql is enough just write down all values:\n\n```crystal\ncreate_table(:contacts) do |t|\n  t.enum(:gender, values: [\"male\", \"female\"])\nend\n```\n\nPostgres provide much more flexible and complex behavior. Using it you need to create it firstly:\n\n```crystal\ncreate_enum(:gender_enum, [\"male\", \"female\"])\ncreate_table(:contacts) do |t|\n  t.string :name, {:size => 30}\n  t.integer :age\n  t.field :gender, :gender_enum\n  t.timestamps\nend\nchange_enum(:gender_enum, {:add_values => [\"unknown\"]})\nchange_enum(:gender_enum, {:rename_values => [\"unknown\", \"other\"]})\nchange_enum(:gender_enum, {:remove_values => [\"other\"]})\n```\n\nFor more details check source code and PostgreSQL docs."}