RuntimeError в CallbacksController # facebook после успешной аутентификации с помощью Devise / Omniauth Rails

Я настраиваю devise с помощью omniauth facebook gem для создания системы регистрации. Пользователи могут зарегистрироваться по электронной почте или подключиться к своей учетной записи facebook. Если зарегистрированный пользователь электронной почты входит в систему с учетной записью facebook, я проверяю, зарегистрирован ли уже адрес электронной почты, и подключаю эти две учетные записи, а затем вхожу в систему.

Весь этот сценарий уже работает. Запись пользователя обновляется новыми данными omniauth facebook. Я получаю эту ошибку, когда facebooks отправляет обратный вызов (данные из facebook успешно сохраняются в db):

RuntimeError в CallbacksController # facebook

Не удалось найти действительное сопоставление для истины

Извлеченный источник (около строки №5):

class CallbacksController < Devise::OmniauthCallbacksController
  # Define each provider for omniauth here (def twitter...)
  def facebook
    @user = User.from_omniauth(request.env["omniauth.auth"])
    sign_in_and_redirect @user
  end
end

Модель user.rb выглядит так:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :omniauthable, :omniauth_providers => [:facebook]

  def self.from_omniauth(auth)
    user = where(provider: auth.provider, uid: auth.uid).first
    unless user
      user = where(email: auth.info.email).first_or_initialize
      user.provider = auth.provider
      user.uid = auth.uid
      user.email = auth.info.email
      user.name = auth.info.name
      user.nickname = auth.info.nickname
      user.first_name = auth.info.first_name
      user.last_name = auth.info.last_name
      user.location = auth.info.location
      user.description = auth.info.description
      user.image = auth.info.image
      user.phone = auth.info.phone
      user.urls = auth.info.urls
      user.password = Devise.friendly_token[0,20]
      user.save!
    end
  end
end

routes.rb

Rails.application.routes.draw do
  devise_for :users, :controllers => { :omniauth_callbacks => "callbacks" }
  resources :auctions do
    resources :comments
  end

  root 'welcome#index'
  get '/', :to => 'welcome#index'
end

person Alessandro Santamaria    schedule 10.09.2015    source источник


Ответы (1)


Ваш self.from_omniauth метод в вашем User классе возвращает true вместо User модели. Это потому, что возвращаемое значение метода в Ruby является результатом последней вычисленной строки, и в этом случае user.save! - это последняя строка, которая выполняется. Ошибка «Не удалось найти действительное сопоставление для истины» является результатом передачи true в sign_in_and_redirect; вы можете видеть в исходном коде Devise , что первый аргумент передается в Devise::Mapping.find_scope! .

Решение простое - убедитесь, что вы возвращаете свою user модель в from_omniauth:

def self.from_omniauth(auth)
    user = where(provider: auth.provider, uid: auth.uid).first
    unless user
      user = where(email: auth.info.email).first_or_initialize
      user.provider = auth.provider
      user.uid = auth.uid
      user.email = auth.info.email
      user.name = auth.info.name
      user.nickname = auth.info.nickname
      user.first_name = auth.info.first_name
      user.last_name = auth.info.last_name
      user.location = auth.info.location
      user.description = auth.info.description
      user.image = auth.info.image
      user.phone = auth.info.phone
      user.urls = auth.info.urls
      user.password = Devise.friendly_token[0,20]
      user.save!
    end
    user # Make sure we return the user we constructed.
  end
person Alex P    schedule 11.09.2015