Zoeken…


Opmerkingen

Transacties zijn beschermende blokken waarbij SQL-instructies alleen permanent zijn als ze allemaal als één atomaire actie kunnen slagen. Het klassieke voorbeeld is een overdracht tussen twee accounts waarbij u alleen een storting kunt doen als de opname is gelukt en vice versa. Transacties versterken de integriteit van de database en beschermen de gegevens tegen programmafouten of database-uitval. Dus in principe moet u transactieblokken gebruiken wanneer u een aantal overzichten hebt die samen moeten worden uitgevoerd of helemaal niet.

Basis voorbeeld

Bijvoorbeeld:

ActiveRecord::Base.transaction do
  david.withdrawal(100)
  mary.deposit(100)
end

Dit voorbeeld neemt alleen geld aan van David en geeft het aan Mary als noch opname noch storting een uitzondering oproept. Uitzonderingen dwingen een ROLLBACK af die de database terugzet naar de status voordat de transactie begon. Houd er echter rekening mee dat de instantiegegevens van de objecten niet worden hersteld.

Verschillende ActiveRecord-klassen in één transactie

Hoewel de transactieklasse methode wordt aangeroepen op een ActiveRecord-klasse, hoeven de objecten in het transactieblok niet alle exemplaren van die klasse te zijn. Dit komt omdat transacties per databaseverbinding zijn en niet per model.

In dit voorbeeld wordt een balansrecord per transactie opgeslagen, ook al wordt de transactie aangeroepen in de klasse Account:

Account.transaction do
  balance.save!
  account.save!
end

De transactiemethode is ook beschikbaar als modelinstellingsmethode. U kunt dit bijvoorbeeld ook doen:

balance.transaction do
  balance.save!
  account.save!
end

Meerdere database verbindingen

Een transactie werkt op een enkele databaseverbinding. Als u meerdere klassespecifieke databases hebt, beschermt de transactie de interactie daartussen niet. Een oplossing is om een transactie te starten voor elke klasse waarvan u de modellen wijzigt:

Student.transaction do
  Course.transaction do
    course.enroll(student)
    student.units += course.units
  end
end

Dit is een slechte oplossing, maar volledig gedistribueerde transacties vallen buiten het bereik van ActiveRecord.

opslaan en vernietigen worden automatisch verpakt in een transactie

Zowel #save als #destroy zijn verpakt in een transactie die ervoor zorgt dat alles wat u doet in validaties of callbacks gebeurt onder de beschermde dekking. U kunt dus validaties gebruiken om te controleren op waarden waarvan de transactie afhankelijk is of u kunt uitzonderingen in de callbacks tot rollback maken, inclusief after_* callbacks.

Als gevolg hiervan worden wijzigingen in de database niet buiten uw verbinding gezien totdat de bewerking is voltooid. Als u bijvoorbeeld probeert de index van een zoekmachine bij te werken in after_save de indexer het bijgewerkte record niet. De after_commit callback is de enige die wordt geactiveerd zodra de update is after_commit .

callbacks

Er zijn twee soorten callbacks verbonden aan het plegen en terugdraaien van transacties: after_commit en after_rollback .

after_commit callbacks worden opgeroepen voor elk record dat is opgeslagen of vernietigd binnen een transactie onmiddellijk nadat de transactie is vastgelegd. after_rollback callbacks worden op elk record opgeslagen of vernietigd binnen een transactie onmiddellijk nadat de transactie of het opslagpunt is teruggedraaid.

Deze callbacks zijn nuttig voor interactie met andere systemen, omdat u er zeker van kunt zijn dat de callback alleen wordt uitgevoerd wanneer de database permanent is. after_commit is bijvoorbeeld een goede plek om het cachegeheugen te verwijderen, omdat het wissen vanuit een transactie ertoe kan leiden dat het cachegeheugen opnieuw wordt gegenereerd voordat de database wordt bijgewerkt.

Een transactie terugdraaien

ActiveRecord::Base.transaction gebruikt de uitzondering ActiveRecord::Rollback om opzettelijke rollback te onderscheiden van andere uitzonderlijke situaties. Normaal gesproken zorgt het verhogen van een uitzondering ervoor dat de .transaction methode de database-transactie .transaction en de uitzondering doorgeeft. Maar als u een ActiveRecord::Rollback uitzondering ActiveRecord::Rollback , wordt de database-transactie teruggedraaid, zonder de uitzondering door te geven.

U kunt dit bijvoorbeeld in uw controller doen om een transactie ongedaan te maken:

class BooksController < ActionController::Base
  def create
    Book.transaction do
      book = Book.new(params[:book])
      book.save!
      if today_is_friday?
        # The system must fail on Friday so that our support department
        # won't be out of job. We silently rollback this transaction
        # without telling the user.
        raise ActiveRecord::Rollback, "Call tech support!"
      end
    end
    # ActiveRecord::Rollback is the only exception that won't be passed on
    # by ActiveRecord::Base.transaction, so this line will still be reached
    # even on Friday.
    redirect_to root_url
  end
end


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow