-
Notifications
You must be signed in to change notification settings - Fork 0
HykuAddons: Database migrations
Migrations for database changes introduced by this engine are defined in db/migrate like any Rails application. These get copied into Hyku during installation when the following in run:
bundle exec rails app:hyku_addons:install:migrationsThese files are suffixed by the engine name for easy identification (e.g. 20200103172822_add_contact_email_to_sites.hyku_additions.rb). This command is safe to rerun and will only copy over missing migrations. See https://edgeguides.rubyonrails.org/engines.html#engine-setup for more details.
To perform the migration you will need to scope the command as follows:
bundle exec rails db:migrate SCOPE=hyku_addonsDon't forget to run the test migations at the same time:
RAILS_ENV=test bundle exec rails db:migrateDatabase migrations in production are not currently automatically run when the application is deployed - although this is a feature that should be added.
Because of the current way that migrations are handled it is necessary to deploy your changes, then log into your production environment, manually run db:migrate.
Log into your production environment, which for Google Cloud would be:
kubectl get pods | grep hyku
kubectl exec -it hyku-pod-name -- /bin/bash
bundle exec rails db:migrateWhen writing migration they must use the up/down syntax and check if a table has already been created. This is because migrations might be installed more than one in development, or when tenants are added in production, their migrations need to be run after the initial migration may have been executed. Checking at a per line level in the migration also assists when re-running a failed migration manually.
# Example of how to check if a table currently exists
class CreateAccountCrossSearches < ActiveRecord::Migration[5.2]
def self.up
return if table_exists?(:account_cross_searches)
create_table :account_cross_searches do |t|
t.references :search_account, foreign_key: { to_table: :accounts }
t.references :full_account, foreign_key: { to_table: :accounts }
t.timestamps
end
end
def self.down
drop_table(:account_cross_searches)
end
endWhen adding columns you must follow the same pattern. Note that when adding indicies or foreign keys they must be added after column creation, and removed before the columns are removed:
class AddDisplayProfileToUsers < ActiveRecord::Migration[5.2]
def self.up
add_column :users, :display_name, :string unless column_exists?(:users, :display_name)
add_index :users, :display_name, unique: true unless index_exists?(:users, :display_name, unique: true)
add_column :users, :jobtitle_id, :integer unless column_exists?(:users, :jobtitle_id)
add_foreign_key :users, :jobtitles unless foreign_key_exists?(:users, :jobtitles)
end
def self.down
remove_foreign_key :users, :jobtitles if foreign_key_exists?(:users, :jobtitles)
remove_index :users, :display_name if index_exists?(:users, :display_name, unique: true)
remove_column :users, :display_name if column_exists?(:users, :display_name)
remove_column :users, :jobtitle_id if column_exists?(:users, :jobtitle_id)
end
endAlso note that when checking the existence of an index or foreign key you must correctly specify options such as unique for ActiveRecord to return a match.