使用Facebook登录时,设备会抛出ConstraintException错误

时间:2015-07-31 11:48:32

标签: ruby-on-rails facebook devise

我正在使用设备,以便用户可以通过我的应用注册和登录。但我也希望用户通过Facebook登录。

用户现在可以注册并登录,但是当他们通过Facebook登录时我收到错误。

SQLite3::ConstraintException: NOT NULL constraint failed: 
users.email: INSERT INTO "users" 
("provider", "uid", "email", "encrypted_password", "name", "last_sign_in_at", "current_sign_in_at", "last_sign_in_ip", "current_sign_in_ip", "sign_in_count") 
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

User.rb

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable,:omniauthable, :omniauth_providers => [:facebook]

  def self.from_omniauth(auth)
    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.name = auth.info.name   # assuming the user model has a name
    end
  end
end

callbacks_controller.rb

class CallbacksController < Devise::OmniauthCallbacksController
    def facebook
        @user = User.from_omniauth(request.env["omniauth.auth"])
        sign_in_and_redirect @user
    end
end

schema.rb

ActiveRecord::Schema.define(version: 20150731102008) do

  create_table "users", force: :cascade do |t|
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.string   "provider"
    t.string   "uid"
    t.string   "name"
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true
  add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true

end

5 个答案:

答案 0 :(得分:1)

这是在迁移中的男性null: false约束时发生的。

将电子邮件列更改为null:true

create_table "users", force: :cascade do |t|
    t.string   "email",                  default: "", null: true
    t.string   "encrypted_password",     default: "", null: true
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.string   "provider"
    t.string   "uid"
    t.string   "name"
  end

答案 1 :(得分:1)

在使用Facebook进行身份验证时,您始终无法获得电子邮件地址。即使您要求scope=email,用户实际上也可以接受您的应用并拒绝发送电子邮件。

您仍然可以为用户分配username@facebook.com地址。所有Facebook用户都有一个。关键的区别在于您实际上向他们发送了Facebook消息,而不是常规电子邮件。

def self.from_omniauth(auth)
  where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
    user.email = auth.info.email || "#{auth.info.nickname}@facebook.com"
    user.password = Devise.friendly_token[0,20]
    user.name = auth.info.name   # assuming the user model has a name
  end
end

答案 2 :(得分:0)

不确定为什么会有效,但我在这里找到了解决方案https://github.com/plataformatec/devise/issues/588

我更改了我的迁移文件

t.string :email,              null: true, default: ""
t.string :encrypted_password, null: true, default: ""

这些都是假的,我把它们设置为真。

# add_index :users, :email,                unique: true
# add_index :users, :reset_password_token, unique: true
# add_index :users, :confirmation_token,   unique: true
# add_index :users, :unlock_token,         unique: true

我评论了这些。

现在我可以通过Facebook和应用程序本身登录。

答案 3 :(得分:0)

最后,在此处找到解决方案&gt; https://github.com/mkdynamic/omniauth-facebook/issues/61靠近底部。我不得不参与范围并将其包含在我的devise.rb

config.omniauth :facebook, 'id', 'secret',scope: 'public_profile,email', info_fields: 'email,name'

现在我的Facebook电子邮件已保存在数据库中。这不是100%证明的方式,因为一些Facebook用户使用他们的电话号码作为登录。

答案 4 :(得分:0)

问题是您的Facebook帐户没有电子邮件地址。 如果您在Facebook(facebook.com/settings)中添加电子邮件(或其他参数), 它应该工作!