2016-05-06 6 views
2

omni-auth認証に使用したUserモデルがあります。 Facebook、Googleアカウントなどのさまざまなプロバイダがサインインに使用できるように設定しました。これらのプロバイダを使用してサインアップしているときに電子メールがデータベースに既に存在する場合、そのアカウントにユーザがサインインされます。mongoidにembeds_manyアソシエーションを持つfirst_or_createメソッド

class User include Mongoid::Document embeds_many :providers field :email,type: String, default: "" end class Provider include Mongoid::Document field :name, type: String field :uid, type: String embedded_in :user end

そして私は、認証情報に基づいてユーザーを見つけることfrom_omniauthメソッドを使用しています。

def from_omniauth(auth) user=User.find_by(email: auth.info.email) return user if user where(:"providers.name" => auth.provider, :"provider.uid" => auth.uid).first_or_create do |user| user.email = auth.info.email user.password = Devise.friendly_token[0,20] end end

しかし、それは1を作成するには、ユーザーと試行を見つける傾けるとき、私はエラーを取得しています。 Mongoid::Errors::UnknownAttribute: message: Attempted to set a value for 'providers.name' which is not allowed on the model User.

しかし、これは私がすでに関連付けを定義しているので、なぜこれを動的フィールド生成と見なしますか?私もfind_or_initializeメソッドを試したが、同じエラー。

誰かが私にそれを理解させるのに役立つことができますか?前もって感謝します。

答えて

0

ここにはいくつかの魔法があります。

あなたが上記の基準に#first_or_createを呼び出している:

where(:"providers.name" => auth.provider, :"provider.uid" => auth.uid).first_or_create do |user| 
    user.email = auth.info.email 
    user.password = Devise.friendly_token[0,20] 
end 

これは実際にはもっとこのような何かに脱糖なっている:

found_user_with_provider = where(:"providers.name" => auth.provider, :"provider.uid" => auth.uid).first 
if found_user_with_provider.nil? 
    new_user = User.new 
    new_user.set(:"providers.name", auth.provider) 
    new_user.set(:"providers.uid", auth.uid) 
    new_user.email = auth.info.email 
    new_user.password = Devise.friendly_token[0,20] 
else 
    found_user_with_provider.email = auth.info.email 
    found_user_with_provider.password = Devise.friendly_token[0,20] 
end 

お知らせの値を設定する試み"provider.name"と "provider.uid" はユーザーインスタンスの属性としてです。これは実際にあなたが望むものではなく、Mongoidが不平を言っているものです。あなたが実際におそらくよりこのような何かしたい

:もちろん

def from_omniauth(auth) 
    user = User.find_by(email: auth.info.email) 
    return user if user 
    found_user_with_provider = where(:"providers.name" => auth.provider, :"provider.uid" => auth.uid).first 
    if found_user_with_provider 
    found_user_with_provider.update_attributes!(
     :email => auth.info.email, 
     :password => Devise.friendly_token[0,20] 
    ) 
    return found_user_with_provider 
    end 
    User.create!({ 
    :providers => [ 
     Provider.new({ 
      :name => auth.provider, 
      :uid => auth.uid 
     }) 
    ], 
    :email => auth.info.email, 
    :password => Devise.friendly_token[0,20] 
    }) 
end 

をもう一つの問題はまだあります、それはあなたのユーザーインスタンス上#password属性を設定していることです。追加してください:

field :password,type: String, default: "" 

ユーザーモデルに - そうでなければ、以前のように動的なフィールドについて同じ苦情を取得します - 別のフィールドについてちょうどこの時間。

関連する問題