Hallo Gruppe,
ich werde aus der 2006’er Ausgabe der Bibel nicht ganz schlau wenn es um
transactions geht. Ich habe Models, die in keiner Beziehung stehen,
unter bestimmten Umständen aber doch in einer Transaktion gespeichert
werden müssen.
def create
@bid = Bid.new(session[:temp_bid])
if @bid.valid?
if @bid.save
if @bid.create_bid_transaction
@shipping.bidcount += 1
if @shipping.save
@message = Message.new()
@message.bla = blu
if not @message.save
redirect_to :controller => “error”, :action =>
“error_message”
end
if @settings = Setting.find(:first, :conditions => [“user_id
= ?”, session[:user_id]])
@settings.foo = bar
if not @settings.save
redirect_to :controller => “error”, :action =>
“error_settingsa”
end
end
end
else
redirect_to :controller => “error”, :action => “error_bid”
end
else
redirect_to :controller => “error”, :action =>
“error_validate_bid”
end
end
Das spannende hierbei ist, dass hier schon 4 Tables bids, shippings,
messages und settings beteiligt sind, aber in der Funktion
create_bid_transaction nochmal 2 weitere Tables betroffen sind.
David spricht jetzt zwar von “Multidatabase Transaction” und schreibt:
User.transaction(user) do
Account.transaction(account) do
account.calculate_fees
user.date_fees_last_calculated = Time.now
user.save
account.save
end
end
Aber meint hier doch eher “Multitable Transactions”, oder?
Ich weiss, dass der Code oben übel ist, aber abgesehen davon die Frage:
Muss ich meine Transaktionen nun für jedes der verwendeten Models
schachteln, um hier Transaktionssicherheit zu haben?
Grüße
Jan Rösner
jan [at] roesner.it
Jan R. schrieb:
@message.save redirect_to :controller => “error”, :action =>
David spricht jetzt zwar von “Multidatabase Transaction” und
schreibt:
User.transaction(user) do Account.transaction(account) do
account.calculate_fees user.date_fees_last_calculated = Time.now
user.save account.save end end
Aber meint hier doch eher “Multitable Transactions”, oder?
Ich weiss, dass der Code oben übel ist,
Jaaa, insbesondere das
Setting.find(:first, :conditions => [“user_id = ?”, session[:user_id]])
–>
current_user.settings.find(:first)
oder
if @bid.valid?
if @bid.save
if @bid.create_bid_transaction
Das kann in eine Methode oder zumindest valid/save zusammenfassen (save
ruft valid? auf).
aber abgesehen davon die
Frage: Muss ich meine Transaktionen nun für jedes der verwendeten
Models schachteln, um hier Transaktionssicherheit zu haben?
Nein, IMHO tut es ein
User.transaction do
User.destroy(1)
Account.create!(:foo => ‘bar’)
Setting.update_all(‘foo=bar’, ‘bar=foo’)
end
Die alte, jetzt nicht mehr gültige Schreibweise transaction(object) hat
die Object-level Transactions geboten.
Jonathan
Hallo Jonathan,
Am Dienstag, den 05.02.2008, 17:04 +0100 schrieb Jonathan W.:
Jaaa, insbesondere das
Setting.find(:first, :conditions => [“user_id = ?”, session[:user_id]])
–>
current_user.settings.find(:first)
… ich weiss, sorry, beleidigt heute auch mein Auge ;), damals hats
einfach funktioniert. Man wächst eben mit Rails, genau wie der eigene
Anspruch an schönen Code.
oder
if @bid.valid?
if @bid.save
if @bid.create_bid_transaction
Das kann in eine Methode oder zumindest valid/save zusammenfassen (save
ruft valid? auf).
Sicher, trotzdem generiere ich hier ein anderes Event, wenn die Daten
nicht valide sind, und rufe die Validierung deswegen hier separat auf.
Setting.update_all(‘foo=bar’, ‘bar=foo’)
end
Die alte, jetzt nicht mehr gültige Schreibweise transaction(object) hat
die Object-level Transactions geboten.
Ok, hört sich gut an. Die Frage ist: Gilt das auch für 1.1.6? Das vergaß
ich zu erwähnen, ich komme bei einer ProduktivApp da momentan leider
nicht von weg … jedenfalls nicht ohne nicht rechtfertigbaren
Aufwand
…
Grüße
Jan Rösner
jan [at] roesner.it
Ok, hört sich gut an. Die Frage ist: Gilt das auch für 1.1.6? Das vergaß
ich zu erwähnen, ich komme bei einer ProduktivApp da momentan leider
nicht von weg … jedenfalls nicht ohne nicht rechtfertigbaren
Aufwand
…
Ja, im Zweifel sollte dein functional Test einen Fehler schmeissen 
Jonathan
On Tuesday 05 February 2008, Jan R. wrote:
ich werde aus der 2006’er Ausgabe der Bibel nicht ganz schlau wenn es
um transactions geht. Ich habe Models, die in keiner Beziehung
stehen, unter bestimmten Umständen aber doch in einer Transaktion
gespeichert werden müssen.
In Rails gibt es keine nested transactions. (Es gibt, meine ich, ein
Plugin, das PostgreSQL-Savepoints unterstützt, was so ziemlich am
nächsten an nested transactions herankommt.) Was es gibt, das sind
geschachtelte Transaktionsblöcke, wobei nur der äußerste überhaupt eine
Wirkung hat, nämlich dass eine Datenbanktransaktion begonnen wird,
wobei auf dieser Transaktion nur dann ein Rollback ausgeführt wird,
falls der Block mit einer Exception verlassen wird, ansonsten wird die
Transaktion mit Commit beendet.
Insbesondere bedeutet das auch, dass es völlig egal ist, auf welcher
Model-Klasse #transaction { … } aufgerufen wird;
ActiveRecord::Base#transaction { … } tut’s auch.
Michael
On Tue, Feb 05, 2008 at 07:15:58PM +0100, Michael S. wrote:
On Tuesday 05 February 2008, Jan R. wrote:
ich werde aus der 2006’er Ausgabe der Bibel nicht ganz schlau wenn es
um transactions geht. Ich habe Models, die in keiner Beziehung
stehen, unter bestimmten Umständen aber doch in einer Transaktion
gespeichert werden müssen.
In Rails gibt es keine nested transactions. (Es gibt, meine ich, ein
Plugin, das PostgreSQL-Savepoints unterstützt, was so ziemlich am
nächsten an nested transactions herankommt.)
Du meinst bestimmt das da:
http://rubyforge.org/projects/arnesttransacts/
Geht auch mit MySQL, und ist sehr zu empfehlen auch wenn man in seinem
Code nur ‘einfache’ Transaktionen nutzt.
Beim Testen steht man sonst nämlich vor der Wahl die ‘transactional
fixtures’ abzuschalten, oder eben auf den Test des transaktionslastigen
Codes zu verzichten, da andernfalls die eigenen Transaktionen mit der
von Rails aufgemachten, den testcase umschließenden, Transaktion
kollidieren.
Jens
–
Jens Krämer
http://www.jkraemer.net/ - Blog
http://www.omdb.org/ - The new free film database
On Tue, 05 Feb 2008 16:37:51 +0100, “Jan R.” [email protected] said:
Hallo Gruppe,
ich werde aus der 2006’er Ausgabe der Bibel nicht ganz schlau wenn es um
transactions geht. Ich habe Models, die in keiner Beziehung stehen,
unter bestimmten Umständen aber doch in einer Transaktion gespeichert
werden müssen.
[…]
eventuell kannst Du die ganze Aktion in eine Stored Procedure auslagern?
Die Logik in Rails bleibt überschaubar - und, zumindest mit Postgres -
sollte
das alles in eine Transaktion passen.
Gruß
Torsten