How do I solve "index unique_schema_migrations already exists" in Rails? - ruby-on-rails

Running rake db:migrate followed by rake test:units yields the following:
rake test:functionals
(in /projects/my_project)
rake aborted!
SQLite3::SQLException: index unique_schema_migrations already exists: CREATE UNIQUE INDEX "unique_schema_migrations" ON "ts_schema_migrations" ("version")
The relevant part of db/schema.rb is as follows:
create_table "ts_schema_migrations", :id => false, :force => true do |t|
t.string "version", :null => false
end
add_index "ts_schema_migrations", ["version"], :name => "unique_schema_migrations", :unique => true
I'm not manually changing this index anywhere, and I'm using Rails' default SQLite3 adapter with a brand new database. (That is, running rm db/*sqlite3 before rake db:migrate doesn't help.)
Is the test:units task perhaps trying to re-load the schema? If so, why? Shouldn't it recognize the schema is already up to date?

In SQLite, index name uniqueness is enforced at the database level. In MySQL, uniqueness is enforced only at the table level. That's why your migrations work in the latter and not the former: you have two indexes with the same name on different tables.
Rename the index, or find and rename the other unique_schema_migrations index, and your migrations should work.

In your database.yml file are your environments setup up to connect to different databases for Development and Test?
IE:
development:
adapter: sqlite3
database: db/dev.sqlite3
timeout: 5000
test:
adapter: sqlite3
database: db/test.sqlite3
timeout: 5000

Try to search if your schema.rb file does not contain other declarations that create an index with the same name: unique_schema_migrations

Related

Rails migration stopped, even though table does not exist

Rails 6
environment: local development on Mac OS
DB server: MySQL
I deleted all the tables from the DB, and the only tables left in the DB are:
schema_migrations
ar_internal_metadata
I made sure that schema_migrations has no data in it and looked into ar_internal_metadata, and that table has a single row in it, with the following values:
key: environment, value: development
I have several migrations, the most recent one, is devise_create_users.rb.
I am trying to run:
rake db:migrate
But I am getting the error message:
=> rake db:migrate
== 20200317184535 DeviseCreateUsers: migrating ================================
-- create_table(:users)
rake aborted!
StandardError: An error has occurred, all later migrations canceled:
Mysql2::Error: Table 'users' already exists
/Users/dev/rails/myapp/db/migrate/20200317184535_devise_create_users.rb:5:in `change'
Caused by:
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'users' already exists
/Users/dev/rails/myapp/db/migrate/20200317184535_devise_create_users.rb:5:in `change'
Caused by:
Mysql2::Error: Table 'users' already exists
/Users/dev/rails/myapp/db/migrate/20200317184535_devise_create_users.rb:5:in `change'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
Process finished with exit code 1
class DeviseCreateUsers < ActiveRecord::Migration[6.0]
def change
create_table :users do |t|
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
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.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
end
When I check the DB after this, I still don't see a users table, and the schema_migrations table is still empty. In addition, the DeviseCreateUsers migration is the most recent on, so why is it running first.
Any ideas?
Edit:
Based on a comment to the question, I looked at my database.yml file:
default: &default
host: localhost
database: <%= ENV['RAILS_DB_NAME'] %>
username: <%= ENV['RAILS_DB_USER'] %>
password: <%= ENV['RAILS_DB_PWD'] %>
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
socket: /tmp/mysql.sock
development:
<<: *default
I made that change last night, and I forgot that my local ENV settings, were for a different project, so Rails was picking up the settings for that project, and was indeed correct, in that the users table is already there. The fix was for me to create project specific ENV settings, for my local development environment
When things like this happen it is needed to check the database.yml. As in most cases it happens because of some faulty configuration.
Good thing that just mentioning the database.yml in the comment section of the question helped to find the problem.
Using rails console to make sure there is not any users table, try create a new instance of User User.new. If the object was instanciated, your User table is hidden in somewhere. It is not a problem, see all atributtes previously generated and just migrate new ones. I can see in your devise_create_user migration that you can just replace it with something like addColumnstoUser.rb. This will just add the apropriated columns necessary to let Devise runing well.
Choosing this way, inside your migration:
add_column :table_name, :fieldname, :type, in your case, using just one column as an example, it must be:
def change
add_column :users, :reset_password_token, :string
end.
If you are using version controll, such as git, the migration might not know where you can rollback or go ahead. All the migration and rollbacks must stay on the same branch.
For example:
1) Adding a new branch to handle user migration: git checkout -b generate-user-model, generating user model rails generate model User name:string email:string
and running the migration rails db:migrate will create the users table and will update scheema.rb (check scheema file). Adding it to version controll git add . and `git commit -m "Migrating user model"
2) Moving to a new branch git checkout -b comments-controller, generating a new controller rails generate model Comment. And then migrating it rails db:migrate.
This second migration only teachs scheema.rb how to go ahead and how to rollback on this specifc migration. This last git branch doesn't know nothing about how to rollback the User model, unless you merge a branch inside another git merge generate-user-model.
After many migrations has been used, it's usefull keep using migrations to add or delete tables.
Hence, If I had a table called users and I wanted to set it to handle Devise, I just need to generate a new migration with the columns I'd needed.
Use https://sqlitebrowser.org/ to help you cheking your database tables and columns.

Activerecord Migrations multiple postgresql database

I have multiple databases. All the migrations for the main database human_development runs fine. The second database is called animals and the migrations fail.
database.yml:
default: &default
adapter: postgresql
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000
encoding: unicode
user: blah
development:
<<: *default
database: human_development
animals:
<<: *default
database: animals
Migrations that are failing:
class SomeTable < ActiveRecord::Migration[5.2]
def change
ActiveRecord::Base.establish_connection("animals")
create_table :some_table, id: :uuid do |t|
t.string :type
t.timestamps
end
ActiveRecord::Base.establish_connection(Rails.env)
end
end
I have also tried the following, non worked:
def connection
ActiveRecord::Base.establish_connection("animals").connect
#ActiveRecord::Base.establish_connection("animals".to_sym).connect
end
establish connection out side of the change
ActiveRecord::Base.establish_connection("animals").connect
# also tried with to_sym
If I run "rails db:migrate", passing the database name as a string I get the following error:
rake aborted!
ActiveRecord::AdapterNotSpecified: database configuration does not specify adapter
.../db/migrate/2019_some_tables.rb:2:in
and if I run the rails db:migrate with to_sym I get the following error:
-- create_table(:some_table, {:id=>:uuid})
rake aborted!
ActiveRecord::StatementInvalid: PG::ConnectionBad: connection is closed: SELECT pg_advisory_unlock
Caused by:
PG::ConnectionBad: connection is closed
Caused by:
StandardError: An error has occurred, this and all later migrations canceled:
PG::ConnectionBad: connection is closed: ROLLBACK
Caused by:
ActiveRecord::StatementInvalid: PG::ConnectionBad: connection is closed: ROLLBACK
Caused by:
PG::ConnectionBad: connection is closed
The migration file should be the same for all databases
class SomeTable < ActiveRecord::Migration[5.2]
def change
create_table :some_table, id: :uuid do |t|
t.string :type
t.timestamps
end
end
end
then in your console you run
# for the main db
rails db:migrate
# for the animals db
RAILS_ENV=animals rails db:migrate
#Eyeslandic Thank you so much, that helped a lot!
In case anyone else runs into the same problems. Looks like rails 6 is going to have a better solution for this, but meanwhile, here are additional changes I had to make:
database.yml: I wanted to keep the migrations in a separate folder:
├── db
│   ├── migrate
│   ├── schema.rb
│   └── seeds.rb
├── animals_db
│   └── migrate
animals:
<<: *default
database: animals
migrations_paths: animals_db/migrate
Create a new environment: config/environments/animals.rb
Change config/secrets.yml to include new environment
Generate secret: RAILS_ENV=animals rake secret
Save the secret in .env file or export it
Create the database: rails db:create RAILS_ENV=animals
Create the migration in animals_db but here is the catch. I had to include the following in def change
def change
create_table :some_table, id: :uuid do |t|
enable_extension "uuid-ossp"
enable_extension "pgcrypto"
t.string :type
t.timestamps
end
end
Run the migration: rails db:migrate RAILS_ENV=animals
You may need to change config/cable.yml as well to include new environment
Hope this helps. Looking forward to see how rails 6 is going to improve this

Error: Relation does not exist when running Rails in production using postgresql

I'm having a problem with my application on Heroku, and in order to determine whether it is specific to my production environment or specific to Heroku itself I am running my production environment locally on my machine with rails s -e production
When I try to load my posts index, I get the following error:
PG::UndefinedTable: ERROR: relation "posts" does not exist
LINE 1: SELECT "posts".* FROM "posts"
^
: SELECT "posts".* FROM "posts"
PG::UndefinedTable: ERROR: relation "posts" does not exist
LINE 1: SELECT "posts".* FROM "posts"
What's weird is my posts index works fine on Heroku, as well as in development and in test. When I run bundle exec rake db:create:all I get the follow output:
project_development already exists
project_test already exists
project_production already exists
My schema is as follows:
create_table "posts", force: true do |t|
t.string "title"
t.text "body"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "author_id"
t.boolean "published"
end
When I fire up rails db in the command line, I can see the table as expected when I run \dt:
public | posts | table | Thomas
However when I fire it up with ENV=production and run \dt I get the following:
Schema | Name | Type | Owner
--------+-------------------+-------+--------
public | schema_migrations | table | Thomas
I've tried running ENV=production rake db:schema:load and that does not solve the problem.
For reference, here is my database.yaml:
development:
adapter: postgresql
encoding: utf8
database: project_development
pool: 5
username:
password:
test:
adapter: postgresql
encoding: utf8
database: project_test
pool: 5
username:
password:
production:
adapter: postgresql
encoding: utf8
database: project_production
pool: 5
username:
password:
The production database created from the database.yml file with rake db:create:all is created locally on your machine, not on heroku.
Heroku automatically infers the database config for the production environment, and creates it when you run git push heroku master for the first time.
The error message about posts table not existing is because of not running migrations on heroku. Run heroku run rake db:migrate to apply the migrations to the production database on heroku.
Also, you don't need to have the production section of the database.yml on your local environment.
Do refer to https://devcenter.heroku.com/articles/getting-started-with-rails4 while working for the first time with heroku; it is comprehensive and very helpful.
EDIT
The actual problem was to get the local production database to work.
Solution was to apply the migrations correctly with rake db:migrate RAILS_ENV=production

rake db:migrate does nothing

I'm following this tutorial,
and I'm having a problem when running rake db:migrate
In db/migrate I have the create_post.rb file:
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.text :text
t.timestamps
end
end
end
But it does not create the table.
My database.yml file is:
development:
adapter: mysql2
encoding: utf8
database: blog_development
pool: 5
username: root
password:
socket: /tmp/mysql.sock
The output from rake db:migrate seems ok.
I'm using phpMyAdmin to handle the database, which is correctly created manually by me.
What am I doing wrong?
If you are connecting to the right database everything seems fine to me.. I had a similar problem a few weeks ago and the accepted answer of this question fixed my issue.
Here are the steps to run:
rake db:drop:all
rake db:create:all
rake db:migrate
I hope it will fix your problem.
WARNING: this will erase your database.
Could you please tell which OS you got?
Delete the line:
socket: /tmp/mysql.sock
and run:
db:migrate
Give the output of:
db:migrate:status
If this is not working for you, you could also try to add:
host: 127.0.0.1
to your database.yml file
If nothing stated above works please do check your schema.rb for migration contents. If migration contents are already there then just do the below command in production:
rails db:schema:load RAILS_ENV=production.

new to rails, setting up db then running rake db:create/migrate

hi im currently learning rails, and following a tutorial. the instructions were to edit the migration file after i've created the app, then running rake db:migrate, then rake db:create.
i've edited the migration file to this:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :username
t.string :email
t.string :encrypted_password
t.string :salt
t.timestamps
end
end
end
then when i've run 'rake db:migrate' i got an error
Mysql2::Error: Table 'users' already exists: CREATE TABLE `users` ...
after i'm supposed to run 'rake db:create', then im getting this
user_auth_development already exists
user_auth_test already exists
You run rake db:create once and only once, and you run it first. Then you run rake db:migrate every time you add/change a migration. You've either already run this migration, or you are pointing at a database that already exists and already contains a table named users. My guess is that you ran the migration once already, in which case you're probably good to go. If you want to nuke the DB and start over, do rake db:drop db:create db:migrate.
We can simply give, it will do all the rake task which is require for database creation and migration
rake db:setup
For Rails 5 and 6, the command is:
rails setup
This will "create the database, load the schema, and initialize it with the seed data" (docs).
For rails 6 & above, you can give this command to create a database, migrate all the migration files, and seed the data into the database:
rails db:prepare

Resources