rails 3:如何在动作邮件中中止交付方式?

jpw*_*ynn 22 ruby-on-rails actionmailer

在我的邮件控制器中,在某些条件下(缺少数据),我们中止发送电子邮件.

在这种情况下如何在不渲染视图的情况下退出控制器方法?

如果@ some_email_data.nil返回?

没有做到这一点,因为视图仍然呈现(在我尝试使用@some_email_data的每个地方抛出一个错误,除非我添加了大量的nil检查)

即使我做了零检查,它也会抱怨没有"发送者"(因为我认为在进入我设置发送者和主题的行之前做了'返回'.

也没有 render ... return

基本上,RETURN不会在邮件方法内返回!

Boz*_*sov 26

比接受的答案更简单的解决方案是:

class SomeMailer < ActionMailer::Base
  def some_method
    if @some_email_data.nil?
      self.message.perform_deliveries = false
    else
      mail(...)  
    end  
  end
end
Run Code Online (Sandbox Code Playgroud)

如果您正在使用Rails 3.2.9(或更好的事情) - 那么您最终可以有条件地打电话mail().这是相关的GitHub线程.现在代码可以像这样重做:

class SomeMailer < ActionMailer::Base
  def some_method
    unless @some_email_data.nil?
      mail(...)  
    end  
  end
end
Run Code Online (Sandbox Code Playgroud)

  • 看起来像在Rails 3.2.9中你可能会看到`mail.should be_a_kind_of NullMail`但我仍然不知道如何在Rails 3.2.8中测试它 (2认同)

小智 18

我刚刚遇到同样的事情.

我的解决方案如下:

module BulletproofMailer
  class BlackholeMailMessage < Mail::Message
    def self.deliver
      false
    end
  end

  class AbortDeliveryError < StandardError
  end

  class Base < ActionMailer::Base

    def abort_delivery
      raise AbortDeliveryError
    end

    def process(*args)
      begin
        super *args
      rescue AbortDeliveryError
        self.message = BulletproofMailer::BlackholeMailMessage
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

使用这些包装邮件将如下所示:

class EventMailer < BulletproofMailer::Base
  include Resque::Mailer
  def event_created(event_id)
    begin
      @event = CalendarEvent.find(event_id)
    rescue ActiveRecord::RecordNotFound
      abort_delivery
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

它也发布在我的博客中.


mpo*_*red 9

我发现这种方法似乎是侵入性最小的,因为它适用于所有邮件程序方法,而不需要您记住捕获错误。在我们的例子中,我们只需要一个设置来完全禁用某些环境的邮件程序。在 Rails 6 中进行了测试,尽管我确信它在 Rails 5 中也能正常工作,甚至可能更低。

class ApplicationMailer < ActionMailer::Base
  class AbortDeliveryError < StandardError; end

  before_action :ensure_notifications_enabled
  rescue_from AbortDeliveryError, with: -> {}

  def ensure_notifications_enabled
    raise AbortDeliveryError.new unless <your_condition>
  end

  ...

end
Run Code Online (Sandbox Code Playgroud)

空的 lambda 导致 Rails 6 仅返回一个ActionMailer::Base::NullMail实例,该实例不会被传递(就像您的邮件程序方法没有调用mail或过早返回一样)。