1

omniauth-facebookユーザーモデルのRailsアプリケーションでFacebookで認証するためにdeviseでgemを使用しています

def self.from_omniauth(auth)
  # immediately get 60 day auth token
  oauth = Koala::Facebook::OAuth.new("App Key",  "App secrets" )
  new_access_info = oauth.exchange_access_token_info auth.credentials.token
  new_access_token = new_access_info["access_token"]
  new_access_expires_at = DateTime.now + new_access_info["expires"].to_i.seconds
  begin
    where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
      user.provider = auth.provider
      user.uid = auth.uid
      user.username = auth.info.first_name
      user.lastname =auth.info.last_name
      user.email =auth.info.email
      user.authentication_token = new_access_token 
      user.oauth_expires_at = new_access_expires_at 
      user.save!
    end
  rescue  ActiveRecord::RecordInvalid
  end
end

#interact with facebook
def facebook
  @facebook ||= Koala::Facebook::API.new(authentication_token)
  block_given? ? yield(@facebook) : @facebook
rescue Koala::Facebook::APIError => e
  logger.info e.to_s
  nil # or consider a custom null object
end


def self.new_with_session(params, session)
  if session["devise.user_attributes"]
    new(session["devise.user_attributes"], :without_protection=> true) do |user|
      user.attributes = params
      user.valid?
    end
  else
    super
  end
end

私のomniauth_callbacksコントローラーには、次のメソッドがあります。

def all
  user = User.from_omniauth(request.env["omniauth.auth"])
  if user.persisted?
    flash.notice = "Signed in!"
    sign_in_and_redirect user
  else
    session["devise.user_attributes"] = user.attributes
    redirect_to new_user_registration_url
  end
end
alias_method :facebook, :all

これらのメソッドは、Facebook 経由で最初からユーザーを認証するために使用されます。通常のデバイス登録方法で登録した場合、既存のユーザーを新しいアカウントではなく Facebook アカウントに接続する方法が必要です

既存のユーザーがサインインしようとするとFacebook、次のエラーが発生します。

A `NoMethodError` occurred in `omniauth_callbacks#facebook`:

undefined method `persisted?' for nil:NilClass
 app/controllers/omniauth_callbacks_controller.rb:4:in `all'
4

3 に答える 3

1

Rails 4およびdevise 3.4.xの回答の更新バージョンを追加するためだけに

これは、更新された omniauth がどのように見えるかです

  def self.from_omniauth(auth)
    if !where(email: auth.info.email).empty?
      user = where(email: auth.info.email).first
      user.provider = auth.provider # and connect him to facebook here
      user.uid = auth.uid           # and here
      user.save!
      user
    else
      where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
        user.email = auth.info.email
        user.password = Devise.friendly_token[0,20]
        user.first_name = auth.info.name   # assuming the user model has a name
        user.avatar = process_uri(auth.info.image) # assuming the user model has an image
      end
    end
  end

メールでユーザーを探します。ある場合はプロバイダーと uid を追加します。ない場合は、ドキュメントで提案されているように作成します

于 2015-02-15T06:03:58.573 に答える
0

次のようなものにすることができますfrom_omniauth

def self.from_omniauth(auth)
    where(auth.info.slice(:email)).first_or_create do |user|
      user.email = auth.info.email
      user.password = Devise.friendly_token[0,20]
      user.username = auth.info.name
      user.description = auth.extra.raw_info.bio
    end
end

このように、Facebook アカウントと同じメールアドレスを持つ既存のユーザーがいる場合、 はそれfirst_or_createを返し、ユーザーはサインインできます (更新されません)。

于 2014-07-07T10:49:03.123 に答える