14

我正在寻找一种解决方案,以允许我的应用程序上的用户拥有超过 1 封电子邮件。这应该类似于 Facebook、LinkedIn 和 Quora。一个帐户可以有多个电子邮件,其中 1 个作为主要电子邮件。

是否有可供设计的交钥匙解决方案?我希望不必从头开始写这个,因为它很常见。

想法?谢谢

4

7 回答 7

15

嗯...我建议创建新模型,你会做这样的事情:

例如模型将是UserEmail.

class UserEmail < ActiveRecord::Base
    belongs_to :user
end

class User < ActiveRecord::Base
    has_many :user_emails
end

并覆盖设计的方法以在User模型中查找记录:

def self.find_first_by_auth_conditions(warden_conditions)
  conditions = warden_conditions.dup
  if email = conditions.delete(:email)
    User.includes(:user_emails).where('user_emails.email = ?', email).first
  else
    super(warden_conditions)
  end

在此处阅读有关覆盖的更多信息:https ://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address

于 2013-04-29T18:14:40.573 回答
8

Bob 的答案很接近,但它有一个潜在的危险错误。该find_first_by_auth_conditions方法应如下所示:

def self.find_first_by_auth_conditions(warden_conditions)
  conditions = warden_conditions.dup
  if email = conditions.delete(:email)
    User.includes(:user_emails).where('user_emails.email = ?', email).first
  else
    super(warden_conditions)
  end
end

电子邮件检查和调用super很重要,因为 Devise 也使用这种方法来查找Users confirmation_tokenunlock_tokenreset_token。如果没有 else 分支,对该方法的任何没有email参数的调用都将失败,或者使用nil电子邮件加载用户。

于 2013-05-15T20:40:53.130 回答
4

我建议你创建一个新模型SecondaryEmail
一个User可以has_many :secondary_emails,每个SecondaryEmail belongs_to :user

您必须为 中的每封电子邮件添加唯一性验证SecondaryEmail,并且还必须确保没有新的 SecondaryEmail 已经是任何用户的主要电子邮件。
提供接口,以便 aUser可以使用这些验证添加他的 secondary_emails。

下一步将SessionController覆盖Devise。在任何登录过程中,只要在用户的主要电子邮件中找不到电子邮件,就
设置您的登录过程。SecondaryEmail.where(:email => params[:email])如果存在,则使用该用户的密码进行身份验证,否则,用户不存在。

这是我到目前为止想出的。我真的很想知道专家对此的看法和方法。:)

于 2013-04-29T18:15:26.787 回答
3

我不久前遇到了这个问题 - 并在我的博客中概述了解决方案。

步骤总结如下:

  • 电子邮件信息必须存储在附加模型中,例如Email. 所以 aUser有很多相关的Email实例。
  • 我们很可能希望将一封电子邮件指定为可用于与用户通信的默认电子邮件。
  • User该类的类方法find_first_by_auth_conditions用于查找用户提供的凭据 - 因此我们必须覆盖该方法才能使用Email模型进行搜索。
  • 我们将不得不更改默认视图,因为它们隐含地假定存在email用户方法。我们可以使用为电子邮件添加代理访问器,而不是完全重写视图,以委托给用户的默认电子邮件。
  • 如果允许用户拥有多封电子邮件 - 我们还希望为用户提供在帐户编辑页面中添加/删除电子邮件的功能。
  • 如果您需要omniauth 集成——那么User.from_omniauth必须修改设计wiki 中概述的库存实现以支持多个电子邮件。

我的实现在 Github上可用。

于 2014-09-13T18:42:48.633 回答
1

Bob 的回答在 rails 4.1.5 中为我抛出了一个 SQL 错误-根据http://guides.rubyonrails.org/active_record_querying.html#specifying-conditions-on-eager-loaded-associations ,以下更改使其正常工作:

def self.find_first_by_auth_conditions(warden_conditions)
  conditions = warden_conditions.dup
  if email = conditions.delete(:email)
    User.includes(:user_emails).where(user_emails: {email: email}).first
  else
    super(warden_conditions)
  end
end
于 2014-11-24T18:46:20.760 回答
1

这里给出的答案非常好,应该可以解决您的问题。要回答您的最后一个问题,我认为您不会为此找到宝石,因为即使它很常见,它也太简单了。只需按照建议从头开始,它不应该做太多工作:)

于 2013-05-10T08:39:31.440 回答
0

您可以使用 devise-multi_email gem:https ://github.com/allenwq/devise-multi_email

替换devise :authenticatabledevise :multi_email_authenticatable, 使您的模型可能如下所示:

class User < ActiveRecord::Base
  has_many :emails

  # Replace :database_authenticatable, with :multi_email_authenticatable
  devise :multi_email_authenticatable, :registerable
end

class Email < ActiveRecord::Base
  belongs_to :user
end

如果您希望所有电子邮件都可以确认并从您的任何电子邮件中恢复您的密码,只需

devise :multi_email_authenticatable, :multi_email_confirmable, :confirmable

于 2016-03-04T11:06:13.580 回答