【问题标题】:Devise, how to override send_confirmation_instructions设计,如何覆盖 send_confirmation_instructions
【发布时间】:2012-10-11 02:44:54
【问题描述】:

我正在尝试覆盖方法“send_confirmation_instructions”,如下所示:

http://trackingrails.com/posts/devise-send-confirmation-mail-manually-or-delay-them

与:

def send_confirmation_instructions
    generate_confirmation_token! if self.confirmation_token.nil?
    ::Devise.mailer.delay.confirmation_instructions(self)
end

这似乎不再适用于最新版本的设计。设计文档展示了如何覆盖控制器而不是模型。关于如何覆盖设计模型的任何建议?谢谢

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 devise


    【解决方案1】:

    当您设置 Devise 时,您告诉它正在使用哪个模型(例如用户);然后它的许多/大部分方法适用于该类。所以这就是你想要覆盖的地方。

    如果我没看错的话,这是来自 lib/devise/models/authenticatable.rb 的设计代码的评论,它几乎准确地描述了您想要做什么。

      # This is an internal method called every time Devise needs
      # to send a notification/mail. This can be overriden if you
      # need to customize the e-mail delivery logic. For instance,
      # if you are using a queue to deliver e-mails (delayed job,
      # sidekiq, resque, etc), you must add the delivery to the queue
      # just after the transaction was committed. To achieve this,
      # you can override send_devise_notification to store the
      # deliveries until the after_commit callback is triggered:
      #
      #     class User
      #       devise :database_authenticatable, :confirmable
      #
      #       after_commit :send_pending_notifications
      #
      #       protected
      #
      #       def send_devise_notification(notification)
      #         pending_notifications << notification
      #       end
      #
      #       def send_pending_notifications
      #         pending_notifications.each do |n|
      #           devise_mailer.send(n, self).deliver
      #         end
      #       end
      #
      #       def pending_notifications
      #         @pending_notifications ||= []
      #       end
      #     end
      #
      def send_devise_notification(notification)
        devise_mailer.send(notification, self).deliver
      end
    

    【讨论】:

    • 谢谢,您是说将“send_devise_notification”添加到我的 user.rb 文件中?我试过了,它没有被调用......
    • 是的,在您的用户模型中覆盖 send_devise_notification。我能够使用当前版本的设计拦截通知(我只是向日志发送了一些东西以证明它有效)。但要让一切正常工作,请阅读评论——这不仅仅是定义方法的问题,您还必须添加 after_commit 过滤器来构建延迟作业(或其他)队列。
    • 谢谢,但这不是“send_confirmation_instructions”所在的地方吗?我需要修改那个方法“send_confirmation_instructions”
    • 没错,这将覆盖所有由设计管理的通知。通过将devise :confirmable(和其他able 选项)添加到您的用户模型中,您实际上是在用户中包含了他们的方法。因此,要覆盖特定方法send_confirmation_instructions(在lib/devise/models/confirmable.rb 中定义),您可以在用户模型中声明它。如果您想要延迟发送,您仍然可能需要覆盖send_devise_notification。我没有看到 Devise(当前版本)内置任何专门管理延迟发送的内容,所以这可能是没有点击的内容。
    • 谢谢,但那是我尝试过的我向 user.rb 添加了一个“send_confirmation_instructions”方法,它从未被调用
    【解决方案2】:

    为什么不使用devise-async

    Usage
    
    Devise >= 2.1.1
    
    Include Devise::Async::Model to your Devise model
    
    class User < ActiveRecord::Base
      devise :database_authenticatable, :confirmable # etc ...
    
      include Devise::Async::Model # should be below call to `devise`
    end
    
    Devise < 2.1.1
    
    Set Devise::Async::Proxy as Devise's mailer in config/initializers/devise.rb:
    
    # Configure the class responsible to send e-mails.
    config.mailer = "Devise::Async::Proxy"
    
    All
    
    Set your queuing backend by creating config/initializers/devise_async.rb:
    
    # Supported options: :resque, :sidekiq, :delayed_job
    Devise::Async.backend = :resque
    

    【讨论】:

    • 因为 devise-async 不存储您在用户 (attr_accessor) 上设置的虚拟属性。
    • 如果您想使用最新版本的 devise,这不再是一个选项,正如您在 their docs 中看到的那样,他们不支持 Devise >= 4.0
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-20
    • 1970-01-01
    相关资源
    最近更新 更多