Forum: Ruby on Rails Perplexing nested transaction issue

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Hammed M. (Guest)
on 2006-05-03 21:06
(Received via mailing list)
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
Pete Y. (Guest)
on 2006-05-03 21:06
(Received via mailing list)
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 Y.
http://9cays.com/
Hammed M. (Guest)
on 2006-05-03 21:08
(Received via mailing list)
Hi Pete,

On 5/3/06, Pete Y. <removed_email_address@domain.invalid> 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.
This topic is locked and can not be replied to.