7

我正在使用acts_as_tenant gem 来管理多租户,并且正在使用设计来管理用户。

我只为租户设置了设计用户模型和帐户模型。我可以针对多个租户创建用户——这一切都很好,除了当我尝试针对不同的租户 ID 使用相同的电子邮件创建两个用户时,我得到一个 uniqeness 错误。我正在使用所描述的 validates_uniqueness_to_tenant 选项。

用户模型

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  attr_accessible :email, :password, :password_confirmation, :remember_me

  acts_as_tenant(:account)
  validates_uniqueness_to_tenant :email
end

账户模式

class Account < ActiveRecord::Base
  attr_accessible :name
end

应用控制器

class ApplicationController < ActionController::Base
  set_current_tenant_by_subdomain(:account, :subdomain)
  protect_from_forgery
end

这看起来应该基于acts_as_tenant中的所有文档工作,我是否需要在设计级别覆盖某些东西?

编辑:经过一番摸索和休息后,我相信问题是因为默认情况下,Devise 已向电子邮件列添加了唯一索引。这显然与acts_as_tenant 想要做的事情不符......我将尝试删除索引并查看Devise 是否呕吐。

编辑2:好的,现在已经正式放弃了。我对主站点进行了手动身份验证,并且可以与acts_as_tenant 一起正常工作。我只能假设acts_as_tenant 和Devise 在某个层次之间存在一些不兼容——在这个阶段我无法找到它。

4

4 回答 4

9

这样做的唯一方法是从设计中删除可验证模块并运行您自己的验证,如下所示:

class User < ActiveRecord::Base
  acts_as_tenant :account
  attr_accessible :email, :password, :remember_me

  #remove :validatable
  devise :database_authenticatable, :registerable,
    :recoverable, :rememberable, :trackable

  #run own validations
  #I've omitted any emailformatting checks for clarity's sake.
  validates :email, 
    presence: true,
    uniqueness: { scope: :account_id, case_sensitive: false }
  validates :password,
    presence: true,
    length: { :in => 6..20 },
    :if => :password_required?

protected
  # copied from validatable module
  def password_required?
    !persisted? || !password.nil? || !password_confirmation.nil?
  end

end
于 2012-09-18T18:28:26.753 回答
0

我尚未对其进行测试,但我想知道更改顺序是否有助于acts_as_tenant 在设计接管之前完成其工作。

class User < ActiveRecord::Base

  acts_as_tenant(:account)
  validates_uniqueness_to_tenant :email

  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable

  attr_accessible :email, :password, :password_confirmation, :remember_me

end
于 2012-08-01T16:07:47.153 回答
0

刚碰到这个问题。Swam 的解决方案非常好。

但我更喜欢不覆盖默认行为。所以我想出了这个解决方案:

validate :remove_old_email_validation_error
validates_uniqueness_of :email, :allow_blank => true, :if => :email_changed?, :scope => [:account_id]

private

def remove_old_email_validation_error
  errors.delete(:email)
end

我们删除了电子邮件的默认验证错误,因此忽略了验证检查,我们再次进行自己的验证。我添加的内容来自 Validatable 模块,但我已添加:scope到其中。

保持秩序很重要。devise在命令后添加上面的代码。

于 2013-07-01T21:41:16.413 回答
0

我将其解决为:

validate :remove_old_uniquess_email_error

private

  def remove_old_uniquess_email_error
   errors.delete(:email) if self.company_id.nil? && errors[:email].present? && errors[:email] == ["already taken"]
  end
于 2019-06-09T08:44:46.687 回答