2013-04-01 16 views

risposta

69

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.

+8

Questo significa che se after_commit solleva e l'eccezione allora non sarà rollback alla precedente interrogazione impegnato –

+9

corretta (parte di creazione?) - una volta che la transazione è stata ha commesso non può più essere il rollback –

+11

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

3

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 
Problemi correlati