Rails 4 SQLite3::SQLException error - ruby-on-rails

I have a devise User model which I want to add a admin boolean field so I ran
rails generate migration add_admin_to_users admin:boolean which created the following migration
class AddAdminToUsers < ActiveRecord::Migration
def change
add_column :users, :admin, :boolean
end
end
However when I run rake db:migrate I keep getting the following error
SQLite3::SQLException: no such table: users: ALTER TABLE "users" ADD "admin" boolean/home/notebook/.rvm/gems/ruby-2.0.0-p353/gems/sqlite3-1.3.8/lib/sqlite3/database.rb:91:in `initialize'
I have tried to rake db:migrate VERSION=0 to rollback to the beginning and redone rake db:migrate again but I keep getting the same error
Here is my user model migration file
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
t.string :email, :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, :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
## 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, :null => false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps
end
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
end
end
My db/schema.rb file is as follows:
ActiveRecord::Schema.define(version: 20140217093954) do
create_table "entities", force: true do |t|
t.string "entity"
t.string "genre"
t.string "url"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "entities", ["entity"], name: "index_entities_on_entity", unique: true
end

It sounds like your development database is not in sync with the schema (or what you think the schema is). Running database migrations is intended for incremental changes and not intended to be be a way to rollback the database and run from the first migration. For this you want to use rake db:reset, which will drop the database and load the schema from db/schema. This post has a good overview of the different database rake commands.

Your database has not users table, you need to create users table first:
rails g migration create_users
And put that migration before the one you are trying to run now, i.e. changing its timestamp.
An easier option is to add in your current file:
class AddAdminToUsers < ActiveRecord::Migration
def change
create_table :users
add_column :users, :admin, :boolean
end
end
Whatever of the solutions you apply, you have a problem with the order of your migrations, search inside migrate folder for a migration that actually creates users table.

Related

Rake db:migrate duplicate with Devise

So i'm having some issues with migrations in rails.. i have 2 migrations one to add the users table and one to add devise to users...
now im getting this error when i try run
rake db:migrate
ActiveRecord::StatementInvalid: SQLite3::SQLException: duplicate column name: email: ALTER TABLE "users" ADD "email" varchar DEFAULT '' NOT NULL
which tells me that both migrations are trying to add the column email to the users table..
USER TABLE CREATE MIGRATION
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.string :email
t.string :password_digest
t.timestamps null: false
end
end
end
DEVISE ADDED TO USERS MIGRATION
class AddDeviseToUsers < ActiveRecord::Migration
def self.up
change_table(:users) do |t|
## Database authenticatable
t.string :email, 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, 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
## 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, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
# Uncomment below if timestamps were not included in your original model.
# t.timestamps null: false
end
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
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.
raise ActiveRecord::IrreversibleMigration
end
end
im assuming its the
add_index :users, :email, unique: true
line in the 2nd migration causing this issue... but im just curious... is that line even relevant to devise? i can't find anything relating to this in the documentation... so if I were to delete those 2 lines would that have any effect on the way Devise runs??
You are trying to create column email twice: in your own migration and in devise. Also, you don't need password_digest column. Second time you got an error because the column already exists.
My advice is to rollback on version before creating users (rake db:rollback VERSION=timestamp_from_migration_filename), remove email and password_digest from your CreateUsers and try again all migrations.
change_column helper is for making multiple alteration on a single table. It always try to add column.
Please check the details on api-dock

Devise - cant add confirmation functionality

I know this question has been asked before but none of the answers helped me.
I have the following situation.
I installed devise (all worked well)
Want to include a confirmation mail, so I do
Included :confirmable in the user model
Uncommented the relevant lines in my migrate file (see my whole file below).
Run rake db:migrate (and restarted server)
When I try to sign up now however, I get ""
undefined local variable or method `confirmed_at' for X....
What am I missing here?
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
# t.string :name
t.string :email, 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, 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
## 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, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps
end
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
end
end
You say, you changed your migration and rerun rake db:migrate.
It's not a good idea to change migrations, that had already been migrated.
Rails does not reconise changes in migrations. So unless you really know, that your last migration is not deployed or checked in yet and all data in your current table can be discarted don't change migrations.
Instead create a new migration that adds the new fields.
If you really know, what you are doing, you can roll back the last (or even a view) migration(s), change it and then run it again:
rake db:rollback STEP=1
# edit your migration
rake db:migrate

How to add to devise model?

I create a user model via command rails generate devise Users.
I want my Users model to stay the same however I want to add more columns but I'm not sure how and I am still a bit confused at the moment. I am pretty new to Ruby on Rails. I am not sure what command I am supposed you run after these changes are made as well. I think it is rake db:migrate in order to update the database.
I want to be able to add
name - string
address - string
username - string ..
According to this example in the documentation,
class AddDetailsToProducts < ActiveRecord::Migration
def change
add_column :products, :part_number, :string
add_column :products, :price, :decimal
end
end
Inside the change method, add columns part_number (string) and price (decimal) to the products table
Would this
file: 20141011161019_devise_create_users.rb
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
t.string :email, 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, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.inet :current_sign_in_ip
t.inet :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, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps
end
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
end
end
First, run rake db:migrate. This will run the migration prepared by devise on your database.
After that, just add more fields to your model, just the same as you would if you'd never installed devise. The first step is to generate a new migration. Run this at the command line:
bin/rails generate migration AddNameAddressUsernameToUsers name:string address:string username:string
This will create a new migration file. You should then run that migration file on your database, with rake db:migrate again. After that, you should be able to refer to those new model fields in your controller and views.
While you could do it all in a single migration, it's generally better to keep your migrations small and discrete. This makes it easier to resolve issues if anything goes wrong.
Don't change the existing migration. You want to create a new migration with the command rails generate migration MigrationName, and then follow the Active Record Migrations Rails Guide, which gives lots of examples on how to add database columns.

rails generate devise User error when migrating

I'm a bit new in Rails world and I try to add a new field in devise schema.
I found this :
rails generate model NAME [field[:type][:index] field[:type]
and tried to apply the command :
rails generate devise User linkedin:string
The process seemed correct :
invoke active_record
create db/migrate/20130902085306_add_devise_to_users.rb
insert app/models/user.rb
route devise_for :users
But when I launch a db:migrate it occures an error :
PG::Error: ERROR: column "email" of relation "users" already exists
What did I do wrong ? why does it say (and is it related) email is wrong while it was ok before ?
Thanks a lot !
Here is the migration file result :
class AddDeviseToUsers < ActiveRecord::Migration
def self.up
change_table(:users) do |t|
## Database authenticatable
t.string :email, :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
t.string :linkedin
# Uncomment below if timestamps were not included in your original model.
# t.timestamps
end
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
# 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.
raise ActiveRecord::IrreversibleMigration
end
end
Does your users table already have email field? It seems there is, you have to remove creating an email field again by removing it from migration and make sure it is not referenced twice in user.rb model
db/migrate/20130902085306_add_devise_to_users.rb
Ok!
I've found what was wrong : I created a new table instead of updating existing one.
So the good task was :
rails g migration add_columnLinkedin_to_users
Then adding in the new created migration file :
change_table :users do |t|
t.string :linkedin
end
And db:migrate was a success !
Thanks for your helps !

Rerunning a Migration - Devise Gem

I am developing a rails app and I added the Devise gem to authenticate users. I am now further along with the development and I want to add some of the modules Devise comes packaged with (specifically Confirmable, Lockable, and Token authenticatable). These modules were in the original migrate file commented out. I was wondering if it is possible to simply uncomment these modules and then run "rake db:migrate". Can you rerun a migration like this, or will it break something?
I would have tested this out, but given the work I have put into development, I do not want to break anything at this point. Here is the migration file as it stands:
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
t.string :email, :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
t.timestamps
end
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
# add_index :users, :authentication_token, :unique => true
end
end
Secondly, if I cannot rerun a migration, I realize that I will have to create new migrations and add the modules to the 'Users' model manually. For example:
rails generate migration AddConfirmationToUsers string:confirmation_token datetime:confirmed_at datetime:confirmation_sent_at string:unconfirmed_email
However, I will need to 'add_index' to this new migration just as with the original migration Devise created. Will I just place the 'add_index' at the bottom of the migration (ie, after the 'add_column' method)? Maybe something like this: ?
class AddConfirmableToUsers < ActiveRecord::Migration
def change
add_column :users, :price, :decimal
add_column :users, :confirmation_token, :string
add_column :users, :confirmed_at, :datetime
add_column :users, :confirmation_sent_at, :datetime
add_column :users, :unconfirmed_email, :string
add_index :users, :confirmation_token, :unique => true
end
end
As a recap:
Can I rerun migrations (edit a previous migration and then run
'rake db:migrate')?
If I cannot rerun migrations, where would I
place the 'add_index' line in the new migration?
You can't just edit the file and run db:migrate. Rails keeps track of which migrations have been run and which have not. Rails thinks that it has already run that migration.
The right thing to do is create a new migration just as you've suggested above.
It sound like you're worried that you're going to trash your database and lose a lot of work. I would suggest that you backup the database before you go forward with this. Database backups and git can help remove a lot of the fear that comes with making changes that you're not sure about.

Resources