C'è qualche differenza tra:after_create: foo vs after_commit: bar,: on =>: creare
after_create :after_create
e after_commit :after_commit_on_create, :on => :create
Possono questi essere usati in modo intercambiabile?
C'è qualche differenza tra:after_create: foo vs after_commit: bar,: on =>: creare
after_create :after_create
e after_commit :after_commit_on_create, :on => :create
Possono questi essere usati in modo intercambiabile?
Non sono intercambiabili. La differenza fondamentale è quando viene eseguito il callback. Nel caso di after_create
, questo sarà sempre prima della chiamata ai ritorni save
(o create
).
Rails avvolge ogni save
all'interno di una transazione e il prima/dopo crea callback eseguiti all'interno di quella transazione (una conseguenza di ciò è che se un'eccezione viene sollevata in un after_create il salvataggio verrà eseguito il rollback). Con after_commit
, il codice non viene eseguito fino a quando non è stata eseguita la transazione più esterna. Potrebbe trattarsi dei binari di transazione creati o di quelli creati dall'utente (ad esempio se si desidera apportare diverse modifiche all'interno di una singola transazione).
Nel punto in cui viene eseguito after_save/create
, il salvataggio può ancora essere ripristinato e (per impostazione predefinita) non sarà visibile ad altre connessioni di database (ad esempio un'attività in background come sidekiq). Alcune combinazioni di questi 2 sono in genere la motivazione per l'utilizzo di after_commit
.
C'è una grande differenza tra questi due rispetto alle associazioni. after_create viene chiamato non appena viene eseguita una query di inserimento per l'oggetto specificato e prima delle query di inserimento delle associazioni dell'oggetto. Ciò significa che i valori degli oggetti associati possono essere modificati direttamente in after_create callbacks senza query di aggiornamento.
class Post < ActiveRecord::Base
has_one :post_body
after_create :change_post_body
def change_post_body
self.post_body.content = "haha"
#No need to save
end
end
Questo significa che se after_commit solleva e l'eccezione allora non sarà rollback alla precedente interrogazione impegnato –
corretta (parte di creazione?) - una volta che la transazione è stata ha commesso non può più essere il rollback –
Si noti che quando si imposta un task asincrono (ad esempio tramite sidekiq) che usa l'id 'dell'oggetto creato, dovresti usare 'after_commit, ... on:: create' perché con' after_create' potresti ottenere un'eccezione 'ActiveRecord :: RecordNotFound' . Questo è appena successo a noi. – Dschee