O ciclo de vida dos callbacks, em ordem

Prévia grátis 3 min de leitura

Onde o curso de validações parou

Validações ActiveRecord avançadas terminou com uma pergunta: este registro pode ser salvo? O que acontece antes, durante e depois do save ficou para este curso. Então este curso abre com uma pergunta direta: quando .save roda, em que ordem o Rails faz tudo o que fica em volta dele?

Os models deste app já dependem da resposta. Identity::User declara before_save :downcase_email e after_create :create_default_preference. Enrollment::UserBadge, Enrollment::LessonCompletion e Partners::Partner declaram cada um um before_validation, e Catalog::Lesson declara um after_save. Nenhuma aula explicou essas linhas ainda, e este curso começa descobrindo a ordem em vez de supor qual é.

Um callback em cada etapa

class ScratchPost < ApplicationRecord
  before_validation { log("before_validation") }
  after_validation  { log("after_validation") }
  before_save       { log("before_save") }
  before_create     { log("before_create") }
  after_create      { log("after_create") }
  after_save        { log("after_save") }
  before_update     { log("before_update") }
  after_update      { log("after_update") }
  before_destroy    { log("before_destroy") }
  after_destroy     { log("after_destroy") }
  around_save   :around_save_wrap
  around_create :around_create_wrap
  around_update :around_update_wrap

  def log(name) = ($order << name)
  def around_save_wrap
    log("around_save (before yield)"); yield; log("around_save (after yield)")
  end
  def around_create_wrap
    log("around_create (before yield)"); yield; log("around_create (after yield)")
  end
  def around_update_wrap
    log("around_update (before yield)"); yield; log("around_update (after yield)")
  end
end

Numa tabela de rascunho, com cada callback acrescentando seu nome em $order, ScratchPost.create!(title: "Hello") produziu isto:

1. before_validation
2. after_validation
3. before_save
4. around_save (before yield)
5. before_create
6. around_create (before yield)
7. around_create (after yield)
8. after_create
9. around_save (after yield)
10. after_save

Lendo o formato

A validação roda primeiro e é separada do save. before_validation e after_validation disparam antes de qualquer escrita. Quando a validação passa, before_save dispara, e daí em diante as etapas se aninham. around_save abre, e as etapas próprias do create rodam dentro dele: before_create, depois around_create abrindo, o INSERT, around_create fechando, e então after_create. around_save só fecha depois de tudo isso, e after_save roda por último.

before_save e after_save disparam em todo save, seja create ou update. before_create e after_create disparam uma vez só, quando a linha é nova. Dentro de uma mesma etapa, before_create e around_create rodam na ordem em que o model os declara; esta classe declara before_create primeiro.

O mesmo registro, atualizado

Chamar .update!(title: "Hello Updated") no mesmo post, já salvo, produziu o mesmo formato. O par de update ocupa o lugar do par de create:

1. before_validation
2. after_validation
3. before_save
4. around_save (before yield)
5. before_update
6. around_update (before yield)
7. around_update (after yield)
8. after_update
9. around_save (after yield)
10. after_save

destroy pula a validação

1. before_destroy
2. after_destroy

Chamar .destroy no post rodou duas etapas e nada mais. Não há before_validation nem before_save. Apagar uma linha não depende de os atributos dela serem válidos, então o Rails não roda essa parte.

Pontos-chave

  • Numa tabela de rascunho, criar um registro rodou dez etapas de callback numa ordem fixa, de before_validation a after_save, com before_create/after_create aninhados dentro de before_save/after_save.
  • Atualizar um registro salvo roda o mesmo formato, com before_update/after_update no lugar do par de create. before_save/after_save disparam nos dois casos.
  • .destroy pula a validação: só before_destroy e depois after_destroy rodam.
  • Identity::User (before_save, after_create), UserBadge/LessonCompletion (before_validation) e outros models deste projeto já usam essas etapas. O resto do curso trata de cada uma.
Aula 1 de 7 · grátis

Continue com a aula 2

before_save vs. after_create neste app

Explica por que Identity::User normaliza o email em before_save e cria as preferências em after_create.

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

Digite para buscar...