views:

40

answers:

2

I'm attempting to send out an HTML e-mail containing a photo (handled by attachment_fu) hosted on Amazon S3 following the submission of an entry.

I keep receiving a nil object error when I try referencing the photo of an entry in ActionMailer. Here's the relevant code ...

class Entry < ActiveRecord::Base

  include AASM

  aasm_initial_state :new

  aasm_state :new
  aasm_state :pending
  aasm_state :rejected, :enter => :reject_entry
  aasm_state :approved, :enter => :approve_entry
  aasm_state :archived
  aasm_state :deleted

  has_one :photo, :dependent => :destroy

  ...

  aasm_event :pending do
    transitions :to => :pending, :from => [:new], :guard => 'process_new_entry'
  end

  ...

  def process_new_entry
    self.make_approval_code
    EntryMailer.deliver_pending_entry_notification(self)
  end
  ...
end

As you can see above the entry transitions through states using AASM. I don't think my issue is due to AASM events, but I'm putting it out there in case.

class Photo < ActiveRecord::Base

  belongs_to :entry

  has_attachment  :content_type => 'image/jpeg',
                  :storage => :s3,
                  :expires_in => 48.hours.to_i,
                  :processor=> :Rmagick,     # attachment_fu looks in this order: ImageScience, Rmagick, MiniMagick
                  :min_size => 1.megabyte,
                  :max_size => 5.megabytes,
                  :thumbnails => { 
                    :medium => '632',
                    :thumb => 'c117x117'
                  }
...
end

In my ActionMailer I have the following:

class EntryMailer < ActionMailer::Base

  helper :entries

  def pending_entry_notification(entry)
    setup_email(entry)
    @content_type = "text/html"
    ...
    @body[:photo_url] = entry.photo.authenticated_s3_url(:thumb)
  end
  ...
end

I end up receiving the following error:

You have a nil object when you didn't expect it!
The error occurred while evaluating nil.authenticated_s3_url

I can successfully get everything else about the entry (including other associations), but trying to reference entry.photo fails.

Any ideas?

A: 

it looks like entry.photo is returning nil which would be the case if that particular entry did not have a photo associated with it.

You need to check entry.photo before trying to call authenticated_s3_url(:thumb) on it.

@body[:photo_url] = entry.photo.authenticated_s3_url(:thumb) if entry.photo

or some variation might work (ymmv, I did not test that)

Thomas Brice
A photo is required in order to save the entry, so ALL entries must have a photo. Using entry.photo throughout the rest of my app works as expected, but fails in ActionMailer.
crh
A: 

It turns out my entry object is stale when the mailer fires off. Reloading the object prior to triggering the mailer solved the problem.

class Entry < ActiveRecord::Base
  ...

  def process_new_entry
    self.make_approval_code
    self.reload
    EntryMailer.deliver_pending_entry_notification(self)
  end
  ...
end
crh