Adicionando um gancho de pós-execução à tarefa db: migrate do Rails

Prefácio: O artigo original deste post foi movido para aqui no meu blog pessoal .

Pode ser muito útil fazer com que o rake execute automaticamente outra tarefa após a execução de db: migrate. Essa tarefa pode ser usada para verificar rapidamente a exatidão do conjunto de caracteres e o agrupamento das tabelas do banco de dados. Isso pode ser um salva-vidas nos casos em que uma atualização imperfeita do banco de dados alterou discretamente o conjunto de caracteres padrão e os valores de agrupamento.

Anexar a uma tarefa de rake existente pode ser feito redefinindo-a. Embora o código abaixo possa dar a impressão de estar sobrescrevendo a tarefa db: migrate, o novo código está, na verdade, apenas sendo anexado a ela.

namespace :db do
def my_appended_code
puts
'this code gets run after the original rails db:migrate task'
puts
'it only runs if the migration did not throw any exceptions'
end

task
:migrate do
my_appended_code

end
end

No entanto, o exemplo acima só executa o código anexado se a tarefa db: migrate original não lançar nenhuma exceção. Precisamos adotar uma abordagem ligeiramente diferente se quisermos garantir que nosso código anexado sempre seja executado. Em vez de anexar nosso código, vamos anexá-lo.

namespace :db do
def my_appended_code
puts
'this code gets run after the original rails db:migrate task'
puts
'it will ALWAYS run'
end

task
:post_migration_hook do
at_exit
{ my_appended_code }
end
end

Rake::Task['db:migrate'].enhance(['db:post_migration_hook'])

Aqui, usamos o método de aprimoramento para adicionar uma tarefa de pré-requisito ao db: migrate. Esta tarefa de pré-requisito adiciona um gancho at_exit que faz com que nosso código anexado seja chamado quando a tarefa db: migrate termina. Além disso, poderíamos fazer com que esse gancho fosse executado apenas em certas exceções usando o $! variável para acessar o objeto de exceção.

Como um aparte, o método de aprimoramento também pode ser usado para anexar código a uma determinada tarefa de rake quando usado conforme mostrado abaixo. Observe que essa abordagem faz com que o código anexado não seja executado no caso de uma exceção.

Rake::Task['db:migrate'].enhance do
my_appended_code

end