12

次のオブジェクトを使用して自分で作成した簡単なソリューションがあります。

  • アカウント(認証時に返され、API呼び出しで使用されるトークンフィールドがあります)
  • 認証(auth_type / auth_idとアカウントへの参照があります)

いくつかのログイン方法(デバイスUUID、電子メール/パスワード、ツイッター、フェイスブックなど)に接続できるように、別の認証モデルがあります。しかし、Deviseのすべての例で、ユーザーアカウント)モデルで使用しているようです。

それは柔軟性が低いのではないですか?たとえば、OmniAuthモジュールはユーザーモデルにプロバイダーとIDを格納しますが、TwitterとFacebookの両方からログインできるようにしたい場合は、プロバイダーが1つしかありません。

アカウントモデルまたは認証モデルでDeviseを使用する必要がありますか?

4

2 に答える 2

8

最近、さまざまなサービスのユーザートークンを保持するためにDeviseを使用していたプロジェクトに取り組んでいます。少し違うケースですが、それでもあなたの質問は私にしばらく考えさせました。

とにかく、Deviseをアカウントモデルにバインドします。なんで?どれどれ。

私の電子メールは私をユーザーとして識別できる唯一のものであるため(そしてあなたはアカウントをユーザーと呼びます)、私はそれをaccountsパスワードと組み合わせてテーブルに配置し、最初は基本的な電子メール/パスワード認証を使用できるようにします。また、APIトークンをに保持しますauthentications

あなたが述べたように、OmniAuthモジュールはプロバイダーとIDを保存する必要があります。ユーザーが同時に異なるサービスに接続できるようにしたい場合(そして何らかの理由で接続できるようにする場合)、明らかに両方のプロバイダーIDペアをどこかに保持する必要があります。そうしないと、1人のユーザーが1人のユーザーごとに1つが上書きされるだけです。認証します。これにより、すでにそれに適していて、アカウントへの参照がある認証モデルにつながります。

したがって、プロバイダーとIDのペアを探すときは、authenticationsテーブルではなくテーブルをチェックする必要がありaccountsます。見つかった場合は、accountそれに関連付けられているものを返すだけです。そうでない場合は、そのような電子メールを含むアカウントが存在するかどうかを確認します。答えが「はい」の場合は新規作成authenticationし、そうでない場合は作成してから作成authenticationします。

具体的には:

#callbacks_controller.rb
controller Callbacks < Devise::OmniauthCallbacksContoller
  def omniauth_callback
    auth = request.env['omniauth.auth']
    authentication =  Authentication.where(provider: auth.prodiver, uid: auth.uid).first
    if authentication
      @account = authentication.account
    else
      @account = Account.where(email: auth.info.email).first
      if @account
        @account.authentication.create(provider: auth.provider, uid: auth.uid,
         token: auth.credentials[:token], secret: auth.credentials[:secret])
      else
        @account = Account.create(email: auth.info.email, password: Devise.friendly_token[0,20])
        @account.authentication.create(provider: auth.provider, uid: auth.uid,
         token: auth.credentials[:token], secret: auth.credentials[:secret])
      end
    end
    sign_in_and_redirect @account, :event => :authentication
  end
end

#authentication.rb
class Authentication < ActiveRecord::Base
  attr_accessible :provider, :uid, :token, :secret, :account_id
  belongs_to :account
end

#account.rb
class Account < ActiveRecord::Base
  devise :database_authenticatable
  attr_accessible :email, :password
  has_many :authentications
end

#routes.rb
devise_for :accounts, controllers: { omniauth_callbacks: 'callbacks' }
devise_scope :accounts do
  get 'auth/:provider/callback' => 'callbacks#omniauth_callback'
end

それはあなたが望む柔軟性を保ちながらあなたが必要とするものをあなたに与えるはずです。

于 2013-02-09T15:40:06.920 に答える
1

すべての共通ロジックをモジュールに分離し、同じテーブルのみを使用できます。

module UserMethods
  #...
end

class User < ActiveRecord::Base
  include UserMethods
  devise ...

end  

class Admin < ActiveRecord::Base
  include UserMethods
  self.table_name = "users"
  devise ...
end

また、すべてのデバイスモデルをルート、ビューで個別に構成します(必要に応じて、ビューの構成を参照してください)。この場合、すべての異なるロジックを簡単に処理できます。

また、デバイスがユーザーモデル専用であると確信している場合は、間違っていることにも注意してください。

例:-rails g devise Admin

これにより、管理モデルのデバイスが作成されます。

詳細はこちら

于 2013-02-01T14:24:22.977 に答える