【问题标题】:SQLite3::ConstraintException: column email is not uniqueSQLite3::ConstraintException:列电子邮件不是唯一的
【发布时间】:2013-10-22 06:39:40
【问题描述】:

我对 Rails 完全陌生,我几乎不知道自己在做什么。但。问题是:使用 Devise 注册新用户会导致:

SQLite3::ConstraintException: column email is not unique: 
INSERT INTO "users" ("created_at","encrypted_password", "name", "updated_at") 
VALUES (?, ?, ?, ?)

以及请求参数:

 {"utf8"=>"✓",
 "authenticity_token"=>"1bgk4ovS3JitphVkIvcCZi3ex8QsBq4eEf6ZihQLiHg=",
 "user"=>{"name"=>"Someone",
 "email"=>"8@prosto.me",
 "password"=>"[FILTERED]"},
 "commit"=>"Sign up"}

用户模型:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable;
end

数据库迁移:

class DeviseCreateUsers < ActiveRecord::Migration
  def self.up
    change_table(:users) do |t|
      ## Database authenticatable
      t.string :email,              :null => false, :default => ""
      t.string :name,               :null => false, :default => ""
      t.string :encrypted_password, :null => false, :default => ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      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

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at

      ## Token authenticatable
      # t.string :authentication_token


      # Uncomment below if timestamps were not included in your original model.
      # t.timestamps
    end

    add_index :users, :email,                :unique => true
    add_index :users, :name,                 :unique => true
    add_index :users, :reset_password_token, :unique => true
    # add_index :users, :confirmation_token,   :unique => true
    # add_index :users, :unlock_token,         :unique => true
    # add_index :users, :authentication_token, :unique => true
  end

  def self.down
    # By default, we don't want to make any assumption about how to roll back a migration when your
    # model already existed. Please edit below which fields you would like to remove in this migration.
  end
end

如果我需要提供任何其他代码,请告诉我。 并提前感谢您的所有帮助。

更新数据库架构:

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

  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,  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.datetime "created_at"
    t.datetime "updated_at"
    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

Update 2:而且身份验证也有问题。设计告诉任何以前成功注册的用户尝试登录的“无效的电子邮件或密码”。

【问题讨论】:

  • 看起来你也有同样的问题:stackoverflow.com/questions/5769758/…
  • 嗯。尝试drop 用户表。这是您应该做的事情,但它可能对您有所帮助。
  • @Dave Devise 在安装后完美运行。所以我相信情况并非如此。
  • 好的,如果我删除用户表——然后呢?
  • 您是否尝试过使用另一封电子邮件,该电子邮件可能不仅仅是一个数字作为前缀?这可能是一个可能的原因

标签: ruby-on-rails ruby sqlite devise


【解决方案1】:

SQLite 告诉您它正在尝试创建一条新记录,其中一个值将是一封电子邮件,但该电子邮件已经存在一条记录。

读取数据库记录的一种简单方法是在终端窗口中查询数据库:

$ rails console
$ User.all

如果您想查看您的测试数据库,它将与您的固定装置一起加载:

$ rails console -e=test
$ User.all

查找与您尝试创建的电子邮件具有相同电子邮件的记录。

如果这是您第一次使用 Devise,您应该检查一下您的灯具。设计当前默认为两个没有属性的灯具。如果您在测试环境中运行,那么这些固定装置将作为两条记录加载到测试数据库中,其中电子邮件的值为 nil,它们是重复的电子邮件值。像下面这样的装置会让你传递你的错误信息。

file: app/test/fixtures/users.yml

one:
  email: user@example.com
  encrypted_password: password1

two:
  email: user2@example.com
  encrypted_password: password2

【讨论】:

    【解决方案2】:

    您在该数据库中还有其他“电子邮件”列吗?

    也许您已经有一个“用户”表,其中电子邮件列已通过 Devise 复制。如果您能告诉我们您的表格有哪些列,那将会很有帮助:)

    【讨论】:

    • SQLite3::ConstraintException:列电子邮件不是唯一的:插入“用户”(“created_at”,“encrypted_pa​​ssword”,“name”,“updated_at”)值(?,?,?,? ) -> 看起来您没有使用此查询插入电子邮件?会不会是这个问题?
    • 如何检查?顺便说一句,我是一个真正的新手 :-)
    • 您是如何获得您在帖子顶部发布的 SQL 转储的?我的印象是您在测试中通过系统发送数据,但您似乎只是通过设计表单注册了您的应用程序?
    • 嗯,这很令人困惑!你有可以分享的日志吗?您可以通过转到 /log/development.log 来获取它们
    • 好吧,我无法解释。我重新启动了服务器几次(我之前至少做了 5 次)并且注册和登录以某种方式正常工作。我不明白。
    【解决方案3】:

    尝试向您的 User 模型添加唯一性验证:

    validates_uniqueness_of :email, :allow_blank => true
    

    这将重新呈现您的用户创建表单,而不是导致错误。

    【讨论】:

    • 试过了。设计引发“电子邮件已被占用”错误。当然,所提供的电子邮件对于应用程序来说绝对是新的。
    • @VladislavIvanov 我认为您遇到的问题是它确保电子邮件的唯一性,但是如果您希望电子邮件具有空白默认值,则必须使用 :allow_blank =&gt; true 接受空白值.请参阅上面的更新答案,希望对您有用。
    • 感谢您的建议,但现在我收到应用错误 'SQLite3::ConstraintException: column email is not unique: INSERT INTO "users" ("created_at", "encrypted_pa​​ssword", "name" , "updated_at") 值 (?, ?, ?, ?)'
    • @VladislavIvanov 您能否在问题的用户表中发布数据?我认为可能有一些数据会破坏任何新的存档。
    • 太棒了,我该怎么做? :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-09
    • 2012-08-03
    • 2015-03-02
    • 2021-08-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多