2011-12-14 20 views
9

È possibile impostare un'applicazione Rails in modo che tutte le azioni del controller vengano automaticamente integrate da una transazione, che viene automaticamente ripristinata in caso di eccezioni non ridotte?Avvolgere tutte le azioni del controller nelle transazioni in Rails

Sto lavorando a un'applicazione Rails 3, attualmente per un'azione abbastanza complessa che rende numerose le modifiche al database. E mi sono sbagliato, molte volte! Dopo un po 'ho capito che il mio codice non funzionava perché avevo finito con dati inconsistenti nel database.

Posso tranquillamente concludere questo con una transazione (è un chiaro istanza dove è necessario!). Tuttavia mi ha fatto pensare che, almeno in fase di sviluppo, sarebbe utile applicare questa idea a tutte le azioni del controller.

Supponendo che sia possibile, c'è qualche aspetto negativo a questo?

risposta

5

Si può fare? probabilmente. Dovrebbe essere fatto? probabilmente no, altrimenti questo sarebbe parte delle rotaie, o ci sarebbe già una grande gemma per questo.

Se si dispone di particolari azioni di controller complesse che eseguono molte attività di db e si desidera che si trovino in una transazione, il mio consiglio è di ottenere questa logica di business e persistenza in un metodo di modello e inserire la transazione lì. Questo ti dà anche più controllo per i casi in cui potresti non voler sempre che ciò accada.

Se davvero, vuole veramente fare questo comunque, ci avrei scommesso che si possa fare con Rack middleware, come questo (non testato) un https://gist.github.com/1477287:

# make this class in lib/transactional_requests.rb, and load it on start 
require 'activerecord' 

class TransactionalRequests 
    def initialize(app) 
    @app = app 
    end 

    def call(env) 
    ActiveRecord::Base.transaction do 
     @app.call(env) 
    end 
    end 
end 

# and in the app config 
config.middleware.use "TransactionalRequest" 
+0

Grazie. Ho intenzione di pensare se questa è una buona idea. Immagino che il problema sia che tutte le transazioni che uso all'interno dell'applicazione verranno semplicemente raggruppate nella transazione esterna. Tuttavia, per qualche ragione vedendo ciò, mi ha dato l'idea di come farlo. Pubblicherò con la mia soluzione in modo che il codice sia più facilmente leggibile! – asc99c

16

Per info, ho fatto questo con un around_filter nel mio controller applicazione:

around_filter :wrap_in_transaction 

def wrap_in_transaction 
    ActiveRecord::Base.transaction do 
    yield 
    end 
end 

Questo rotola appena la transazione su ogni eccezione non gestita, e ri-solleva l'eccezione.

+0

Mi piace questa idea, ma come faccio ad accedere ai callback after_commit e after_rollback usando questo? – nexar

+1

Suggerisco caldamente di aggiungere un rand di sonno prima di restituirlo nuovamente: questa cosa può esplodere la macchina se si hanno molte transazioni simultanee. – fotanus

Problemi correlati