所以,我帮助一位朋友将Omniauth添加到他的应用程序中,出于某种原因,omniauth仅在第一次使用。
但现在,它正在回归:
PG::Error: ERROR: duplicate key value violates
unique constraint "index_users_on_email"
DETAIL: Key (email)=() already exists. : INSERT INTO "users"
("created_at", "provider", "uid", "updated_at", "username")
VALUES ($1, $2, $3, $4, $5) RETURNING "id"
它只是接受一个,然后说“已经存在”。我们怎样才能得到这个工作?
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :omniauthable,
:recoverable, :rememberable, :trackable, :validatable
has_many :songs
has_many :comments
acts_as_voter
def self.from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_create do |user|
user.provider = auth.provider
user.uid = auth.uid
user.username = auth.info.nickname
end
end
def self.new_with_session(params, session)
if session["devise.user_attributes"]
new session["devise.user_attributes"] do |user|
user.attributes = params
user.valid?
end
else
super
end
end
def password_required?
super && provider.blank?
end
def update_with_password(params, *options)
if encrypted_password.blank?
update_attributes(params, *options)
else
super
end
end
def email_required?
super && provider.blank?
end
end
架构snippit
create_table "users", force: true 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
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.datetime "created_at"
t.datetime "updated_at"
t.boolean "admin"
t.string "provider"
t.string "uid"
t.string "username"
end
omni controller
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
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 :twitter, :all
end
所有访问密钥都是在railscasts最新的ep之后正确设置的。
答案 0 :(得分:2)
您对电子邮件字段有唯一约束。因为此字段被定义为不可为空并且具有默认值“”(空字符串)。这意味着如果您未指定电子邮件,则DBMS会将此字段设置为“”。当然,因为它有一个独特的约束,你只能添加两个没有电子邮件的用户,因为只有一个用户可以拥有空字符串电子邮件。
如果你没有手动创建约束,那么我假设rails已经为你创建了它(因为电子邮件字段上的索引太明显了)假设第一个字段是表主键,因为你没有指定任何。这使它在它上创建索引和唯一约束。
答案 1 :(得分:2)
更简单的解释可能是,这是由于您的测试数据是在没有唯一电子邮件的情况下生成的。尝试查看/test/fixtures/users.yml,如果您看到类似的内容:
one: {
}
two: {
}
然后将其更改为
one: {
email: tester1@stack.com
}
one: {
email: tester2@stack.com
}
或者您可以删除文件的内容。
答案 2 :(得分:1)
您可以从电子邮件中删除索引,因为设计将其设置为唯一。根据设计默认设置的方式,您不能拥有重复的空白电子邮件地址。这是一个迁移示例。
class ChangeEmail < ActiveRecord::Migration
def change
remove_index :users, :email
end
end