如何使用Devise在Rails中向新注册用户发送欢迎电子邮件?

23

我正在使用Rails上的Devise,想知道是否有钩子或过滤器可以用来在Devise的用户注册过程中添加一些代码,并在账户创建后向用户发送欢迎电子邮件。如果没有Devise,就像这样...

  respond_to do |format|
      if @user.save
        Notifier.welcome_email(@user).deliver    # <======= 
  ...   

你是否正在使用Devise的确认方法? - Shreyas
很有趣,你问到这个问题,因为我在使用那个方法时遇到了麻烦。尽管我的配置正常,但它并没有发送电子邮件。不,对于欢迎电子邮件,我正在使用自己的方法。 - picardo
5个回答

32
下一个最受欢迎的答案假设您正在使用Devise的:confirmable模块,而我没有使用。
我不喜欢其他解决方案,因为您必须使用模型回调,这将在您在控制台或管理员界面中创建帐户时始终发送欢迎电子邮件。我的应用程序涉及从CSV文件批量导入用户的能力。我不希望我的应用程序逐个向所有3000个用户发送惊喜电子邮件,但我确实希望自己创建帐户的用户收到欢迎电子邮件。 解决方案:
1)覆盖Devise的注册控制器:
#registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController

  def create
    super
    UserMailer.welcome(resource).deliver unless resource.invalid?
  end

end

2)告诉Devise你重写了它的Registrations控制器:

# routes.rb
devise_for :users, controllers: { registrations: "registrations" }

2
我喜欢这种方法,它很简洁,代码量不多,逻辑也很明显。感谢您的回答! - asfallows
1
这个看起来是最好的解决方案。 - Ismael
你如何知道 @user 是可用的? - Jonathan Lin
根据我的经验,覆盖设备控制器操作只会带来痛苦和折磨。即使是看似无害的事情也会导致我升级时的困扰。这似乎是一个滚雪球的过程,你覆盖了一个方法,然后突然需要你覆盖另一个方法,以此类推。 - Jeff Gandt
@JeffGandt 我想你很难找到一个在实施这个解决方案后陷入了雪崩般混乱的人。 - Arcolye

10

https://dev59.com/iW455IYBdhLWcg3wFP9u#6133991 展示了一个不错的答案(虽然并非完美),但至少比我在这里看到的更好。它覆盖了confirm!方法:

class User < ActiveRecord::Base
  devise # ...
  # ...
  def confirm!
    welcome_message # define this method as needed
    super
  end
  # ...
end

这种做法更好,因为它不使用回调函数。回调函数存在一些问题:(1)会让模型难以测试;(2)会将太多的逻辑放入模型中。过度使用回调函数通常意味着你在模型中有一些本应该属于其他地方的行为。有关此主题的更多讨论,请参见:Rails中使用回调函数处理领域逻辑的优缺点

上述方法与confirm!方法相关,对于这个示例来说,这比使用回调函数更可取。然而,像回调一样,逻辑仍然在模型中。 :( 所以我认为这种方法并不完全令人满意。


我不知道怎么做才更好,因为邮件发送器是控制器的一部分,而不是模型。这样简单,但是不正确。 - Serge Vinogradoff

9

我通过使用回调方法解决了这个问题。这不是最干净的解决方案,不像观察者那么简洁,但我会接受它。我很幸运Mongoid实现了ActiveRecord回调函数!

  after_create :send_welcome_mail
  def send_welcome_mail
     Contact.welcome_email(self.email, self.name).deliver
  end

我如何在确认帐户后发送欢迎消息?(在restful_authentication中有一个名为recently_activated的方法吗?) - Ben Orozco
Devise 中有一个类似的方法。http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Confirmable#confirmed%3F-instance_method - picardo
2
实际上那只是检查它是否被确认。我必须实际重写confirm!方法:https://github.com/plataformatec/devise/issues/812#comment_1113176 - Ben Orozco
1
一个旁注,欢迎邮件的名字welcome_email在mailer对象上看起来还好,但理想情况下应该被命名为welcome,因为mailer只用于发送电子邮件。有何想法? - Khaja Minhajuddin
我不喜欢这种方式,因为它总是会发送邮件,即使您在控制台或管理员界面创建用户。我只希望当用户期望收到邮件时才发送这类邮件。 - Arcolye
显示剩余2条评论

6
我建议使用ActiveRecord::Observer。观察者的想法是,您将创建一个类,其中包含一个after_save方法,该方法将调用通知。您只需要创建观察者类,然后修改应用程序配置以注册观察者即可。文档描述了这个过程非常好。
使用观察者模式意味着您不需要更改控制器中的任何逻辑。

我正在使用Mongoid。是否仍然可以使用ActiveRecord观察器? - picardo
看起来在http://blog.eizesus.com/2010/03/creating-a-rails-authentication-system-on-mongoid-part-2-7-3-2010/中并没有观察者支持。你的after_create回调似乎是最好的方式。 - Rob Di Marco

2

自从一段时间以前,yield已经被添加到Devise控制器方法中,我认为这现在可能是最好的方法。

class RegistrationsController < Devise::RegistrationsController

  def create
    super do |resource|
      Notifier.welcome_email(resource).deliver if resource.persisted?
    end  
  end

end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接