How to avoid ActionMailer::Preview committing data to development database?

actionmailer, ruby-on-rails

Solution

Cleaner/Easier (based on other answers) and tested with Rails 7: Do not change Rails' classes but create your own. Id addition to not change the controller but the `call` method of `ActionMailer::Preview`.

# app/mailers/preview_mailer.rb

class PreviewMailer < ActionMailer::Preview
  def self.call(...)
    message = nil
    ActiveRecord::Base.transaction do
      message = super(...)
      raise ActiveRecord::Rollback
    end
    message
  end
end

# inherit from `PreviewController` for your previews

class EventInvitationPreview < PreviewController
  def invitation_email
    ...
  end
end

OLD:

You can simply use a transaction around email previews, just put this inside your `lib/monkey_mailers_controller.rb` (and require it):

# lib/monkey_mailers_controller.rb
class Rails::MailersController
  alias_method :preview_orig, :preview

  def preview
    ActiveRecord::Base.transaction do
      preview_orig
      raise ActiveRecord::Rollback
    end
  end
end

Then you can call `.create` etc. in your mailer previews but nothing will be saved to database. Works in `Rails 4.2.3`.

Problem

I'm using `Rails 4.1.0.beta1`'s new Action Mailer previews and have the following code: ``` class EventInvitationPreview < ActionMailer::Preview def invitation_email invite = FactoryGirl.create :event_invitation, :for_match, :from_user, :to_user EventInvitationMailer.invitation_email(invite) end end ``` This is all good until I actually try to preview my email and get an error saying that validation on a User object failed due to duplicate email addresses. Turns out that ActionMailer::Preview is writing to my development database. While I could work around the validation failure or use fixtures instead of factories, is there any way to avoid ActionMailer::Preview writing to the development database, e.g. use the test database instead? Or am I just doing it wrong?

Original source