我正在使用设备,以便用户可以通过我的应用注册和登录。但我也希望用户通过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
答案 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)中添加电子邮件(或其他参数), 它应该工作!