I''ve been struggling with a strange nested transaction problem for a
while.
I have a two objects with the following relationships:
Mail has_many :recipients
Recipients belong_to :mail
I''d like to update the status of the Mail object while sending mails
for
each of it''s recipients. Following is a simplified example that
I''m having
problems with:
def send_mail
@mail = Mail.find params[:id]
@recipients = Recipient.find_all_by_mail_id @mail.id
processed = 0
logger.info "__Loop Start"
@recipients.each do |recipient|
recipient.status = ''ok''
logger.info "==Recipient Saved - #{recipient.save}"
@mail.status = (processed += 1)
@mail.save
logger.info "--Mail Saved"
end
logger.info "__Loop End"
render :text => "done"
end
The problem is that with the above setup, the status of the recipient
isn''t
updated within the .each loop. Looking at the log, I noticed that the UPDATE
statement which would update the recipient status is missing. Through trial
and error I found that if I remove the line that saves the mail status
within the loop, the recipients are saved correctly. It looks like
there''s
an issue with nested transactions but I can''t figure out
what''s going on.
Following is the relevan section of the log formatted for clarity. I''ve
pointed out the spots where the update statement for recipients is missing
with ??? UPDATE RECIPIENT MISSING:
__Loop Start
SQL (0.000315) BEGIN
Mail Load (0.000446) SELECT * FROM mails WHERE (mails.id = 62) LIMIT
1
??? UPDATE RECIPIENT MISSING
SQL (0.000180) COMMIT
==Recipient Saved - false
SQL (0.000157) BEGIN
SQL (0.002060) SELECT count(*) AS count_all FROM recipients WHERE (
recipients.mail_id = 62)
Mail Update (0.000386) UPDATE mails SET ... `status` = 1 WHERE id 62
Recipient Load (0.004454) SELECT * FROM recipients WHERE (
recipients.mail_id = 62) ORDER BY name
SQL (0.001372) COMMIT
--Mail Saved
SQL (0.000273) BEGIN
Mail Load (0.000559) SELECT * FROM mails WHERE (mails.id = 62) LIMIT
1
??? UPDATE RECIPIENT MISSING
SQL (0.000166) COMMIT
==Recipient Saved - false
SQL (0.000099) BEGIN
SQL (0.002693) SELECT count(*) AS count_all FROM recipients WHERE (
recipients.mail_id = 62)
Mail Update (0.000372) UPDATE mails SET ... `status` = 2 WHERE id 62
SQL (0.000868) COMMIT
--Mail Saved
__Loop End
Any tips will be appreciated. Thanks
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
http://wrath.rubyonrails.org/pipermail/rails/attachments/20060503/b639c607/attachment.html
Hammed, The fact that recipient.save is returning false indicates that the validations for the recipient are failing. Try having a look at recipient.errors after the save to work out what''s happening. Pete Yandell http://9cays.com/ On 03/05/2006, at 1:13 PM, Hammed Malik wrote:> I''ve been struggling with a strange nested transaction problem for > a while. I have a two objects with the following relationships: > > Mail has_many :recipients > Recipients belong_to :mail > > I''d like to update the status of the Mail object while sending > mails for each of it''s recipients. Following is a simplified > example that I''m having problems with: > > def send_mail > @mail = Mail.find params[:id] > @recipients = Recipient.find_all_by_mail_id @mail.id > processed = 0 > logger.info "__Loop Start" > @recipients.each do |recipient| > recipient.status = ''ok'' > logger.info "==Recipient Saved - #{ recipient.save}" > @mail.status = (processed += 1) > @mail.save > logger.info "--Mail Saved" > end > logger.info "__Loop End" > render :text => "done" > end > > The problem is that with the above setup, the status of the > recipient isn''t updated within the .each loop. Looking at the log, > I noticed that the UPDATE statement which would update the > recipient status is missing. Through trial and error I found that > if I remove the line that saves the mail status within the loop, > the recipients are saved correctly. It looks like there''s an issue > with nested transactions but I can''t figure out what''s going on. > > Following is the relevan section of the log formatted for clarity. > I''ve pointed out the spots where the update statement for > recipients is missing with ??? UPDATE RECIPIENT MISSING: > > __Loop Start > SQL (0.000315) BEGIN > Mail Load (0.000446) SELECT * FROM mails WHERE (mails.id = > 62) LIMIT 1 > ??? UPDATE RECIPIENT MISSING > SQL (0.000180) COMMIT > ==Recipient Saved - false > SQL (0.000157) BEGIN > SQL (0.002060) SELECT count(*) AS count_all FROM recipients > WHERE (recipients.mail_id = 62) > Mail Update ( 0.000386) UPDATE mails SET ... `status` = 1 > WHERE id = 62 > Recipient Load (0.004454) SELECT * FROM recipients WHERE > ( recipients.mail_id = 62) ORDER BY name > SQL (0.001372) COMMIT > --Mail Saved > > SQL (0.000273) BEGIN > Mail Load (0.000559) SELECT * FROM mails WHERE ( mails.id = > 62) LIMIT 1 > ??? UPDATE RECIPIENT MISSING > SQL (0.000166) COMMIT > ==Recipient Saved - false > SQL (0.000099) BEGIN > SQL (0.002693) SELECT count(*) AS count_all FROM recipients > WHERE (recipients.mail_id = 62) > Mail Update ( 0.000372) UPDATE mails SET ... `status` = 2 > WHERE id = 62 > SQL (0.000868) COMMIT > --Mail Saved > __Loop End > > Any tips will be appreciated. Thanks > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails
Hi Pete, On 5/3/06, Pete Yandell <pete@notahat.com> wrote:> The fact that recipient.save is returning false indicates that the > validations for the recipient are failing. Try having a look at > recipient.errors after the save to work out what''s happening.I printed out the errors for the recipient object and didn''t find any. For some reason, the update statement for recipients never gets called if I like the update statement is never called if I save the @mail object afterwards. If I comment out the part that saves @mail, recipient gets updated.