I do registration with devise

Added username field for User. For authorization I use email + pwd.

class ApplicationController < ActionController::Base protect_from_forgery with: :exception before_action :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys:[:username]) end end class User < ApplicationRecord validates :username, presence: true devise :database_authenticatable, :registerable, :rememberable, :trackable, :validatable end ActiveRecord::Schema.define(version: 20170228132910) do create_table "users", force: :cascade do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false t.string "username", default: "", null: false 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", null: false t.datetime "updated_at", null: false t.index ["email"], name: "index_users_on_email", unique: true t.index [nil], name: "index_users_on_reset_password_token", unique: true end end 

The first user registered normally, on the second I get an error

ActiveRecord :: RecordNotUnique in #Devise :: RegistrationsController # create SQLite3 :: ConstraintException: UNIQUE constraint failed: index ) VALUES (?,?,?,?,?)

What's wrong with index_users_on_reset_password_token?

Added migration

 class DeviseCreateUsers < ActiveRecord::Migration[5.0] def change create_table :users do |t| ## Database authenticatable t.string :email, null: false, default: "" t.string :encrypted_password, null: false, default: "" # Registrable t.string :username, null: false, default: "" ## Rememberable t.datetime :remember_created_at ## Trackable 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.timestamps null: false end add_index :users, :email, unique: true add_index :users, :reset_password_token, unique: true end end 
  • t.index [nil] - what? How did this come about? Show the migration that issued it. - D-side
  • And who is your primary key here? - vp_arth
  • one
    @vp_arth is an implicit, surrogate integer id with auto increment. Rails uses this by default. - D-side
  • Added migration - Sergei R
  • Where is the field? reset_password_token - vp_arth

1 answer 1

This was reported to the Rails bug tracker ( # 27782 ) and this is a problem in SQLite:

SQLite has a (mis-) feature that can be treated as strings. It’s a very early concept. . I regret that choice now, but I can't undo it without breaking backwards compatibility.

- D. Richard Hipp, creator of SQLite

In Russian:

SQLite has (uporoya) feature: identifiers in double quotes, which could not be resolved in the name of a table or column, are perceived as strings. It was a deliberate choice made long before SQLite “shot” and ended up in a wide variety of devices around the world, and it was made to ensure better compatibility with MySQL, the most popular DBMS in the world at that time. Now I regret this choice, but I can’t get rid of it without breaking backward compatibility.

In Rails, it seems, they are determined to fix this on their side , but if they succeed, the question is open. You can't just take and remove quotes from the columns in the definition of the index. This will fix this particular bug, but will add restrictions on what the names of the columns can be, or even just add new bugs.


You added a unique index in the migration to a column that does not exist, reset_password_token . Because of the "feature" above, the result is a functional (calculated) index on a constant string ( "reset_password_token" ). As a result, you cannot have more than one line in the table under this index, because inserting another one will require adding a value to the unique index that is already there. Beauty!

The solution now is to make a new migration, in which to erase this index :

 remove_index :users, name: :index_users_on_reset_password_token 
  • An interesting translation of mis- ... - αλεχολυτ