【问题标题】:Devise Async / delayed jobs - send custom emails with delayed job too?设计异步/延迟作业 - 也发送带有延迟作业的自定义电子邮件?
【发布时间】:2014-10-06 22:32:39
【问题描述】:

我有一个解决方案,我可以向设计“库存电子邮件”发送默认包含在 Devise with Delayed 作业中的邮件消息。以异步方式。因此我使用以下代码:

/initializers/devise_acync.rb

module Devise


  module Models

    module Confirmable
      alias_method :send_confirmation_instructions_without_delay, :send_confirmation_instructions
      handle_asynchronously :send_confirmation_instructions
    end

    module Recoverable
      alias_method :send_reset_password_instructions_without_delay, :send_reset_password_instructions
      handle_asynchronously :send_reset_password_instructions
    end

    module Lockable
      alias_method :send_unlock_instructions_without_delay, :send_unlock_instructions
      handle_asynchronously :send_unlock_instructions
    end

    module Invitable
      alias_method :deliver_invitation_without_delay, :deliver_invitation
      handle_asynchronously :deliver_invitation
    end


  end

end

在我的用户模型中设计链接到这个模型我做

def confirm!
    welcome_message
    super
  end

private

  def welcome_message
     ::Devise.mailer.welcome_instructions(self).deliver
  end

让我眼花缭乱的大问题: 我怎样才能发送这个欢迎消息真正的延迟工作? 您将如何添加其他自定义且未包含在内的电子邮件,以便它们也发送真正的延迟工作?

【问题讨论】:

    标签: ruby-on-rails devise delayed-job


    【解决方案1】:

    我发现这是一个优雅的解决方案 - http://danseaver.com/blog/2011/10/18/sending-devise-emails-with-delayed-job

    我稍微改变了它以处理所有传出的设计电子邮件,运行 rails 3.0.7 + DJ 3.0.1

    config/initializers/devise.rb

    # override Devise::Mailer to use queue outgoing mail into DJ
    class DeviseMailer < Devise::Mailer
    
      def confirmation_instructions(record)
        Devise::Mailer.delay.confirmation_instructions(record)
      end
    
      def reset_password_instructions(record)
        Devise::Mailer.delay.reset_password_instructions(record)
      end
    
      def unlock_instructions(record)
       Devise::Mailer.delay.unlock_instructions(record)
      end
    end
    
    # Use this hook to configure devise mailer, warden hooks and so forth. The first
    # four configuration values can also be set straight in your models.
    Devise.setup do |config|
      # ==> Mailer Configuration
      # Configure the e-mail address which will be shown in DeviseMailer.
      config.mailer_sender = APP_CONFIG[:member_email]
    
      # Configure the class responsible to send e-mails.
      config.mailer = "DeviseMailer"
    ...
    

    【讨论】:

    • jackquack 的答案在下面是更好的一个
    【解决方案2】:

    最好使用devise-aync gem 或查看这个小blogpost

    【讨论】:

      【解决方案3】:

      我发现以上方法都不适合我。我正在使用Devise 2.0.4 和Rails 3.2.2 和delayed_job_active_record 0.3.2

      devise 实际上谈到在代码中的 cmets 中执行类似操作的方式是覆盖 User 类中的方法。因此,我就这样解决了,而且效果很好:

      app/models/User.rb

      def send_on_create_confirmation_instructions
        Devise::Mailer.delay.confirmation_instructions(self)
      end
      def send_reset_password_instructions
        Devise::Mailer.delay.reset_password_instructions(self)
      end
      def send_unlock_instructions
        Devise::Mailer.delay.unlock_instructions(self)
      end
      

      【讨论】:

      【解决方案4】:

      您是否尝试过这样做:

      def welcome_message
        ::Devise.mailer.delay.welcome_instructions(self)
      end
      

      【讨论】:

      • 愚蠢的没有尝试过,因为它是如此明显,我相信它至少在开发中会起作用,谢谢!
      【解决方案5】:

      (问题已经快 3 年了,但通过谷歌仍然很容易找到,所以这是我的贡献)

      最佳做法是按照源 https://github.com/plataformatec/devise/blob/master/lib/devise/models/authenticatable.rb#L129 中描述的设备说明进行操作

      class User
        devise :database_authenticatable, :confirmable
      
        after_commit :send_pending_notifications
      
        protected
      
        def send_devise_notification(notification, *args)
          # If the record is new or changed then delay the
          # delivery until the after_commit callback otherwise
          # send now because after_commit will not be called.
          if new_record? || changed?
            pending_notifications << [notification, args]
          else
            devise_mailer.send(notification, self, *args).deliver
          end
        end
      
        def send_pending_notifications
          pending_notifications.each do |notification, args|
            devise_mailer.send(notification, self, *args).deliver
          end
      
          # Empty the pending notifications array because the
          # after_commit hook can be called multiple times which
          # could cause multiple emails to be sent.
          pending_notifications.clear
        end
      
        def pending_notifications
          @pending_notifications ||= []
        end
      end
      

      你只需要替换 2 次出现的

      devise_mailer.send(notification, self, *args).deliver
      

      devise_mailer.delay.send(notification, self, *args)
      

      【讨论】:

        【解决方案6】:

        这实际上很容易通过覆盖用户模型上的单个方法来实现。 Devise 通过send_devise_notification 方法发送所有电子邮件,因此只需将那里的代码更改为异步友好。

        def send_devise_notification(notification, opts = {})
          devise_mailer.delay.send(notification, self, opts)
        end
        

        此代码假设为 Sidekiq,尽管语法可能与 Resque 或 DelayedJob 兼容。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-03-18
          • 2015-09-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-17
          • 2016-03-29
          相关资源
          最近更新 更多