È possibile utilizzare una transazione in un controller se si desidera veramente. Come hai notato, è una cattiva pratica, ma se vuoi farlo, chiama il numero Product.transaction do
anziché transaction do
. transaction
è un metodo di classe su ActiveRecord::Base
, quindi è necessario chiamarlo su una classe derivata da ActiveRecord. Qualsiasi classe di modello nella tua applicazione farà (caveat picking: se ti connetti a database diversi per modelli diversi, potrebbe non essere vero ... ma probabilmente non lo farai).
Il motivo per cui questa è una cattiva pratica è che non separa correttamente le preoccupazioni secondo il paradigma MVC. Il tuo controllore non dovrebbe essere così preoccupato dell'implementazione della persistenza dei dati. Un approccio migliore sarebbe aggiungere un metodo a Product
. Forse qualcosa di simile:
def save_and_update_create_time
transaction do
if save
client.update_attribute(:product_create, Time.now)
end
end
end
Poi invece di chiamare product.save
nel controller, chiamano product.save_and_update_client_create_time
. Potrebbe essere necessario passare anche a ; non è chiaro dal tuo codice da cui proviene . Se si tratta di un attributo su product
, il metodo sopra dovrebbe funzionare.
Ci sono modi migliori, più Railsy per fare anche questo, soprattutto se uno product
conosce il suo client
senza bisogno di dati del controller. Poi si può semplicemente utilizzare un callback after_save
, come questo (aggiungi al Product
classe):
after_save :update_client
private
def update_client(product)
product.client.update_attribute(:product_create, Time.now)
end
Poi ogni volta che un Product
viene salvato, il campo sul client associato sarà aggiornato. Probabilmente dovrai prima introdurre un codice per verificare l'esistenza di uno client
.
Il vantaggio dell'utilizzo di callback, oltre al codice più pulito, è che l'intera catena di callback viene eseguita in un'unica transazione insieme al salvataggio; non è necessario creare manualmente la transazione. Puoi leggere ulteriori informazioni sui callback nello Rails documentation.
fonte
2013-03-27 13:13:55
Grazie mille Jim, mi aiuti davvero con la tua spiegazione! – user1364684
Se la logica transazionale è inserita in un modello, le transazioni non saranno limitate a un modello quindi, per non rompere la regola delle preoccupazioni separate? Di solito c'è un'alta probabilità che le transazioni si estendano su più Modelli, che non sono necessariamente correlati l'uno all'altro a livello di DB. – xSNRG
Sì, ho avuto un cambiamento di cuore su quel particolare aspetto del mio commento. Mi piace l'idea di tenerlo fuori dal controller, ma le interazioni multi-modello dovrebbero essere avvolte da qualche parte.Forse un'altra classe, ma in alcune situazioni il controller potrebbe essere il posto giusto dopo tutto. –