Um arquivo, uma transação, uma mudança relacionada

Prévia grátis 4 min de leitura

Além de um add_index, além de uma tabela

"Migrations ActiveRecord" ensinou o que é uma migration. Migrations ActiveRecord: índices ensinou a tornar um único add_index seguro numa tabela que já tem linhas reais. Os dois ficaram numa operação, numa tabela existente. Nenhum perguntou o que acontece quando uma funcionalidade precisa de várias tabelas novas ao mesmo tempo, ligadas entre si, que precisam entrar juntas ou não entrar. Este curso trata desse "ou não entrar": o que ele garante, e o que precisa valer dentro de um arquivo de migration para ele se sustentar.

O padrão em que este curso se apoia

O disable_ddl_transaction! do curso anterior tirava uma migration de algo que existe por padrão. O Rails envolve o método change (ou up) inteiro de uma migration comum numa única transação de banco. Este curso nunca chama disable_ddl_transaction!, de propósito, porque a propriedade que ele remove é aquela de que este curso depende.

O que significa "um envio só"

Imagine uma funcionalidade que precisa de uma tabela partners e de uma tabela partner_perks que a referencia com chave estrangeira. Este app montou a funcionalidade de parceiros em dois arquivos. 20260830200000_create_partners.rb criou partners. Um arquivo posterior, 20260830210000_add_partner_perks.rb, acrescentou colunas de benefícios e criou partner_course_sponsorships e partner_roles, as duas referenciando partners. Os exemplos deste curso usam uma tabela partner_perks inventada, mais simples, com o mesmo formato.

Escreva as duas tabelas numa migration só, dentro da transação padrão do Rails. Se um comando posterior falhar, digamos um erro de digitação num tipo de coluna ou uma restrição impossível de cumprir, o PostgreSQL desfaz tudo o que rodou antes. Nenhuma tabela partners fica sem sua partner_perks, e nenhum schema pela metade fica esperando a próxima requisição tropeçar nele. rails db:migrate termina o arquivo inteiro ou deixa o schema como estava.

Dois arquivos separados, rodados como duas migrations, não ganham isso de graça. Se o primeiro dá certo e o segundo falha, as mudanças do primeiro já estão confirmadas de vez. Existe uma tabela partners sem partner_perks, e alguém precisa perceber e escrever uma terceira migration para limpar. O limite da transação é o limite do arquivo, e por isso mudanças de schema relacionadas que precisam entrar juntas ficam num arquivo só.

Onde isso choca com o curso anterior

Isto está em tensão direta com o curso anterior. algorithm: :concurrently precisa que a transação suma, e a premissa deste curso precisa dela. Um arquivo de migration não pode ter ao mesmo tempo um índice com algorithm: :concurrently e várias chamadas create_table relacionadas que precisam entrar tudo ou nada, porque disable_ddl_transaction! vale para o arquivo inteiro, não para um comando. Na prática os dois raramente colidem. O curso anterior tratava de acrescentar um índice a uma tabela grande já em uso. Este trata de criar tabelas novas e vazias para uma funcionalidade nova, onde a duração da trava que preocupava Migrations ActiveRecord: índices ainda não importa: não há dados contra os quais bloquear escritas.

Pontos-chave

  • "Migrations ActiveRecord" tratou do que é uma migration, e o curso anterior de tornar um add_index seguro numa tabela em uso. Este curso começa onde os dois param: várias mudanças de schema relacionadas que precisam entrar juntas ou não entrar.
  • Por padrão, o Rails envolve o change/up de uma migration comum numa transação de banco. O disable_ddl_transaction! do curso anterior desliga isso; este curso depende de isso continuar ligado.
  • O limite da transação é o limite do arquivo. Mudanças relacionadas divididas em arquivos de migration separados não ganham o tudo ou nada: se um arquivo posterior falha, as mudanças do anterior continuam confirmadas e órfãs.
  • A premissa deste curso e algorithm: :concurrently puxam para lados opostos, um precisando da transação e o outro precisando que ela suma. Isso costuma estar tudo bem, porque eles resolvem problemas diferentes: tabelas novas e vazias contra um índice numa tabela em uso.
Aula 1 de 7 · grátis

Continue com a aula 2

Ordenação: uma tabela não pode referenciar outra que ainda não existe

O create_table da tabela referenciada precisa vir antes no arquivo, senão o PostgreSQL levanta PG::UndefinedTable.

Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.

Digite para buscar...