2012-07-18 7 views
6

私はacts_as_tenant gemを使用してマルチテナントを管理しています。私はdeviseを使用してユーザーを管理しています。レールでdevisとacts_as_tenantを持つユーザーの一意性3

テナント用のユーザーモデルと勘定モデルのみを設定しています。 複数のテナントに対してユーザーを作成することができます。異なるテナントIDに対して同じ電子メールで2人のユーザーを作成しようとする場合を除いて、これはうまく動作します。 説明したようにvalidates_uniqueness_to_tenantオプションを使用しています。

Userモデル

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がpukesかどうかを調べます。

編集2:OK、正式にこれを今すぐ中止しました。私はメインサイトの認証を手動で行いましたが、これはacts_as_tenantで適切に動作しています。 私は、acts_as_tenantとDeviseの間にいくつかの層で互換性がないと仮定することができます。この段階で私を超えて見つけることができます。

答えて

8

これを行うための唯一の方法が工夫からvalidatableモジュールを取り外すことであるので、のような独自の検証を実行します。

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 
+3

良い答え - 誰にも気づく価値があることは、忘れずに追加する電子メールのユニークなインデックスを削除することを忘れないでください。 –

+0

FYI:AaTはスコープ付きバリデータ:validates_uniqueness_to_tenant:email'を提供します。また、電子メールフォーマットは、 'validates_format_of:email、with:Devise.email_regexp'を使って簡単に行うことができます – Besi

0

私はそれをテストしていませんが、注文を変更すると、出来上がる前にそのことを行うのに役立つかもしれないのだろうかと思います。

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 
+0

申し訳ありませんが、動作しません。 –

+0

あなたがdevise indexで何かにいるようなサウンド。それが助けであれば、私のシステムでは、複数のテナントにバインドして現在のテナントを切り替えることができます。これはあなたの特定のニーズにはうまくいかないかもしれません。 – ob1

0

はちょうどこの質問に出くわしました。 Sweamのソリューションはかなり良いです。

しかし、私はデフォルトの動作を上書きしない方がよいです。だから私はこの解決策を考え出した:

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コマンドの後に上記のコードを追加します。

関連する問題