I'm new to Ruby on Rails and I'm following the https://www.railstutorial.org/book/ guide to understand a bit more about it. I'm stuck at 6.3.3, where it tells to create a secure password. The previous migration seemed to have worked (to create a unique index and to create the secure password column). After that when i try to run:
rake test
it says that the test was aborted and that i should run:
rake db:migrate RAILS_ENV=test
but when i do run the command above it returns this:
c:\Sites\sample_app>rake db:migrate RAILS_ENV=test
DL is deprecated, please use Fiddle
== 20141226095217 AddIndexToUsersEmail: migrating =============================
-- add_index(:users, :email, {:unique=>true}) rake aborted! StandardError: An error has occurred, this and all later migrations canceled:
SQLite3::ConstraintException: indexed columns are not unique: CREATE UNIQUE INDEX "index_users_on_email" ON "users" ("email")c:/Si tes/sample_app/db/migrate/20141226095217_add_index_to_users_email.rb:3:in `change' C:in `migrate' Tasks: TOP => db:migrate (See full trace by running task with --trace)
I don't understand why this is happening. My DB is empty.
As requested, the migrations files:
20141226095217_add_index_to_users_email.rb
class AddIndexToUsersEmail < ActiveRecord::Migration
def change
add_index :users, :email, unique: true
end
end
20141226095746_add_password_digest_to_users.rb
class AddPasswordDigestToUsers < ActiveRecord::Migration
def change
add_column :users, :password_digest, :string
end
end
See https://stackoverflow.com/a/14765346/429758 for the exact same issue. As mentioned there, the issue is not with the migration, but with having duplicate values for email field in the users table.
Since this error is happening while running tests, it means the test database has duplicate emails for users.
Rails Tutorial book uses fixtures to setup test data. The test/fixtures/users.yml file used to create the users on test env is shown in Listing 6.29 as follows:
one:
name: MyString
email: MyString
two:
name: MyString
email: MyString
Both of these fixtures having MyString as email is what is causing the migration to fail. Change the values to make sure both have different values.
Example:
one:
name: First User
email: first#example.com
two:
name: Second User
email: second#example.com
EDIT
Looking back at the Rails Tutorial, the next step in Listing 6.30 is to empty the test/fixtures/users.yml file. That is another way to ensure this error does not occur.
Related
I am following Michael Hartl's book and I am getting this error when I run the server:
I am getting ActiveRecord::PendingMigrationError when I run the server, this shows up:
Migrations are pending. To resolve this issue, run: bin/rails db:migrate RAILS_ENV=development
Please I've been stuck in this error for so long.
When I type $ RAILS_ENV=development rake db:migrate I get this error:
== 20161209073230 AddActivationToUsers: migrating =============================
-- add_column(:users, :activation_digest, :string) rake aborted! StandardError: An error has occurred, this and all later migrations
canceled:
SQLite3::SQLException: duplicate column name: activation_digest: ALTER
TABLE "users" ADD "activation_digest" varchar
(required)>' Tasks: TOP => db:migrate (See full trace by running task
with --trace)
test/mailers/previews/user_mailer_preview.rb
UserMailerPreview < ActionMailer::Preview
# Preview this email at
http://localhost:3000/rails/mailers/user_mailer/account_activation
def account_activation
user = User.first
user.activation_token = User.new_token
UserMailer.account_activation(user) end
# Preview this email at
http://localhost:3000/rails/mailers/user_mailer/password_reset def
password_reset
UserMailer.password_reset end
end
Schema.rb:
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20161123005710) do
create_table "users", force: :cascade do |t|
t.string "name"
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "password_digest"
t.string "remember_digest"
t.string "activation_digest"
t.index ["email"], name: "index_users_on_email", unique: true end
end
Latest migration is
db/migrate/[timestamp]_add_activation_to_users.rb:
class AddActivationToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :activation_digest, :string
add_column :users, :activated, :boolean, default: falserao
add_column :users, :activated_at, :datetime
end
end
The correct command to apply unapplied migrations is RAILS_ENV=development rake db:migrate
This just means that you have a migration pending. When you create a new migration
railas g migration MigrationName
it means that it changes something in the database schema or the layout of your database. In order to commit that change, you have to run:
bin/rails db:migrate
This will look into your migration file and apply it to your databse. Once the migration is done, you can run server as usual again.
rails server
If you have more question, I recommend reading the migration documentation that Rails published:
http://guides.rubyonrails.org/active_record_migrations.html
SQLite3::SQLException: duplicate column name: activation_digest:
(The following is the SQL command that actually modifies the db):
ALTER TABLE "users" ADD "activation_digest"
The SQL command reads like plain English. Somehow one of your migrations is doing something a previous migration already did, namely adding the activation_digest column to your users table in the db. If you look in the directory db/migrate/, you will see all your migration files. If you open one of them up, you should sort of be able to tell what it is doing. So look at all your migration files and find the two migrations that both add the activation_digest column. If the two migration files are identical, then you need to delete one--but take the following steps before deleting a migration:
https://www.baserails.com/questions/i-messed-up-while-generating-my-migration-how-can-i-undo-it
Also check out the section Rolling Back in the Rails Guide:
http://edgeguides.rubyonrails.org/active_record_migrations.html#reverting-previous-migrations
If for some reason you don't have two identical migration files that both add the activation_digest column, e.g one of the migration files does something additionally, then you need to figure out what steps in the tutorial that you did wrong, then rollback to the last migration that you know is correct. Finally, follow the steps in the tutorial again for generating the subsequent migrations.
It seems your users table already have a column named activation_digest. Remove the add_column line where the column is added from the migration file and run the migration again.
I think this migration file should work:
class AddActivationToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :activated, :boolean, default: false
add_column :users, :activated_at, :datetime
end
end
Ok the answer is very simple!Just try migrating your DB to version=0 with command: rake db:migrate VERSION=0
and then run rake db:migrate
I'm following along with the rails tutorial. I'm on ch. 6 and I'm getting a strange error with SQLite3 (for the record, I'm using sqlite version 1.3.10 and the tutorial uses 1.3.9)
I don't get an error when I run rake db:migrate, but when I run the migration for the test environment, here's what I get:
$ bundle exec rake test:models
rake aborted!
ActiveRecord::PendingMigrationError:
Migrations are pending. To resolve this issue, run:
bin/rake db:migrate RAILS_ENV=test
sample_app/test/test_helper.rb:3:in `<top (required)>'
sample_app/test/models/user_test.rb:1:in `require'
sample_app/test/models/user_test.rb:1:in `<top (required)>'
Tasks: TOP => test:models
(See full trace by running task with --trace)
$ bundle exec rake db:migrate RAILS_ENV=test
== 20150628011937 AddIndexToUsersEmail: migrating ===========================
==
-- add_index(:users, :email, {:unique=>true})
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
SQLite3::ConstraintException: UNIQUE constraint failed: users.email: CREATE UNIQUE INDEX "index_users_on_email" ON "users" ("email")sample_app/db/migrate/20150628011937_add_index_to_users_email.rb:3:in `change'
C:in `migrate'
ActiveRecord::RecordNotUnique: SQLite3::ConstraintException: UNIQUE constrain
t failed: users.email: CREATE UNIQUE INDEX "index_users_on_email" ON "users"
("email")
sample_app/db/migrate/20150628011937_add_index_to_users_email.rb:3:in `change'
C:in `migrate'
SQLite3::ConstraintException: UNIQUE constraint failed: users.email
sample_app/db/migrate/20150628011937_add_index_to_users_email.rb:3:in `change'
C:in `migrate'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
Here is my user.rb model:
class User < ActiveRecord::Base
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
end
Here is my most recent migration
class AddIndexToUsersEmail < ActiveRecord::Migration
def change
add_index :users, :email, unique: true
end
end
I can post any other files if those are relevant. Thanks in advance for the help!
The problem was that I had users in the database with the same email before the migration.
db:reset solved everything
I experienced it for a bit different reason and here is the solution.
For me the error was
Minitest::UnexpectedError: ActiveRecord::RecordNotUnique: SQLite3::ConstraintException: UNIQUE constraint failed: users.email: INSERT INTO "users" ("created_at", "updated_at", "id") VALUES ('2018-05-09 18:23:59.827561', '2018-05-09 18:23:59.827561', 298486374)
Notice the INTO "users" ("created_at", "updated_at", "id"). It was caused by test/fixtures/users.yml was not filled, so then there was duplicate values in columns which has unique key constraint.
test/fixtures/users.yml:
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
# This model initially had no columns defined. If you add columns to the
# model remove the '{}' from the fixture names and add the columns immediately
# below each fixture, per the syntax in the comments below
#
one: {}
# column: value
#
two: {}
# column: value
if you can't reset:db you should try to delete it by hand go to db folder and delete the "development.sqlite3" and the "test.sqlite3" files
then run
rails db:migrate
and bin/rails db:migrate RAILS_ENV=TEST
worked for me, anyway...
If this happens to you when running tests:
Make sure there are no users fixtures, unless you explicitly define those users with unique attributes.
test/fixtures/users.yml
When you generate a model, for example:
rails g model User
Rails automatically creates that file and it looks like:
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
# This model initially had no columns defined. If you add columns to the
# model remove the '{}' from the fixture names and add the columns immediately
# below each fixture, per the syntax in the comments below
#
one: {}
# column: value
#
two: {}
# column: value
This can mess up your tests.
Just use rake db:test:prepare and it will copy the dev database to test so you don't need to run the migrations.
I had to delete my development.db to resolve the issue.
I've been trying to get the Paperclip gem working. The problem that I was initially running into was that pictures were getting uploaded but not displaying. I then messed around with the database by doing a rake db:rollback to try and fix the error. Now I can't rake db:migrate again because of this error
SQLite3::SQLException: duplicate column name: image_file_name: ALTER TABLE "posts" ADD "image_file_name" varchar
I've personally went into the migration folder and deleted the file to try and generate a migration again. I've been trying to do rails generate paperclip post image and it does create a migration file, but I'm unable to rake db:migrate.
Any suggestions?
Thanks!
Deleting a migration file doesn't really rollback the change it made in your database. Your best bet is to:
Don't delete the migration but comment out the content of the migration class, and run rake db:migrate,
Let's say I have this as my migration file
class AddEmailSentToNeeds < ActiveRecord::Migration
def change
add_column :needs, :email_sent, :boolean ,default: false
end
end
Just comment out the method but leave the class, so it would be:
class AddEmailSentToNeeds < ActiveRecord::Migration
# def change
# add_column :needs, :email_sent, :boolean ,default: false
# end
end
This is just a hacky way to tell rails to skip this migration.
OR
start from the start so go do, rake db:drop, rake db:create, and rake db:migrate
When I run rake db:migrate I get following output:
== 20141219011612 CreatePost: migrating =======================================
-- create_table("posts") rake aborted! StandardError: An error has occurred, this and all later migrations canceled:
== 20141219011612 Postposts: migrating =======================================
-- create_table("posts") rake aborted! StandardError: An error has occurred, this and all later migrations canceled:
PG::DuplicateTable: ERROR: relation "posts" already exists : CREATE
TABLE "posts" ("id" serial primary key, "post" text, "release_date"
timestamp, "created_at" timestamp, "updated_at" timestamp)
/home/admin/.rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/connection_adapters/postgresql/database_statements.rb:128:in
async_exec' /home/admin/.rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/connection_adapters/postgresql/database_statements.rb:128:in block in execute'
/home/admin/.rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/connection_adapters/abstract_adapter.rb:373:in block in log' /home/admin/.rvm/gems/ruby-2.1.5/gems/activesupport-4.1.8/lib/active_support/notifications/instrumenter.rb:20:in instrument'
/home/admin/.rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/connection_adapters/abstract_adapter.rb:367:in log' /home/admin/.rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/connection_adapters/postgresql/database_statements.rb:127:in execute'
/home/admin/.rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/connection_adapters/abstract/schema_statements.rb:205:in
create_table' /home/admin/.rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/migration.rb:649:in block in method_missing'
/home/admin/.rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/migration.rb:621:in
block in say_with_time' /home/admin/.rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/migration.rb:621:in say_with_time'
/home/admin/.rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/migration.rb:641:in
`method_missing'
...
migrate' /home/admin/.rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/railties/databases.rake:34:in block (2 levels) in <top (required)>' Tasks: TOP => db:migrate (See
full trace by running task with --trace)
I don't understund how this is possible, bescause In scheme file I don't have post table.
Somehow, you ended up with a table named 'posts' in your database. Perhaps from a prior migration that you deleted without rolling back? If you don't care about any of your data in the database, you can run
rake db:drop db:create db:migrate
to bring your development database inline with your current migrations.
If you have data in other tables you don't want to lose, open the database console and drop the posts table manually:
$ rails db
# drop table posts;
Then run db:migrate again.
For those who didn't get your answer above
In my case, I had been working on a feature a month ago the field happens to be created at that time. Now when I try to run migration rake db: migrate I see this error. I know and am sure that this is not here due to any mistake.
I also tried to rollback that particular migration
rake db:migrate:down VERSION=20200526083835
but due to some reason, it did nothing, and to move further I had to comment out the up method in that migration file.
# frozen_string_literal: true
class AddColToAccounts < ActiveRecord::Migration
def up
# execute 'commit;'
#
# add_column :accounts, :col, :boolean,
# null: false,
# default: false
end
def down
execute 'commit;'
remove_column :accounts, :col
end
end
And, now I am able to run the migrations.
At last, I undo the commenting thing and I am done.
Thanks
Check your db/schema.rb
You most likely have the same table being created there in addition to a migration in db/migrate/[timestamp]your_migration
You can delete the db/migrate/[timestamp]your_migration if it is a duplicate of the one found in the schema and it should work.
In case this helps anyone else, I realized that I had been using a schema.rb file that was generated while using MySQL. After transitioning to Postgres, I simply forgot I would need to run rake db:migrate before I could use rake db:schema:load
One of the hack I found was to put pry before you are creating the table on the migration file.
require 'pry'
binding.pry
create_table :your_table_name
and drop that table:
drop_table :your_table_name
After that you can remove the drop_table line and it will work fine!
kill the current postgres process:
sudo kill -9 `ps -u postgres -o pid`
start postgres again:
brew services start postgres
drop, create, and migrate table:
rails db:drop db:create db:migrate
This will delete your data, don't do it on production.
First remove the orphan migration ********** NO FILE ********** in case you have any, by executing this db command:
delete from schema_migrations where version='<MIGRATION_ID>';
then
rails db:schema:load
then
rails db:migrate
This worked for me.
I had the same problem, the only thing that worked for me was to delete the table from within the rails console, like so:
ActiveRecord::Migration.drop_table(:products)
I want to remove a migration from my application.
I have a migration file 20141105030942_removedate_fromexpense.rb
the class file for the migrations is
class RemovedateFromexpense < ActiveRecord::Migration
def change
remove_column :expenses, :date, :date
end
end
When I give this command:
rake db:migrate:down VERSION=20141105030942
I get the following error:
== 20141105030942 RemovedateFromexpense: reverting ============================
-- add_column(:expenses, :date, :date)
rake aborted!
StandardError: An error has occurred, this migration was canceled:
SQLite3::SQLException: duplicate column name: date: ALTER TABLE "expenses" ADD "date" date/home/sumyvps/.rvm/gems/ruby-1.9.3-p545#railstutorial_rails_4_0/gems/sqlite3-1.3.8/lib/sqlite3/database.rb:91:in `initialize'
db:migrate:status for migration file is as below
up 20141105030942 Removedate fromexpense
Has anyone an idea why this is happening?
You do not need to specify the column type in your migration file. Just the name of the table and the column is enough to remove the column from the table.
Edit your migration file to:
class RemovedateFromexpense < ActiveRecord::Migration
def change
remove_column :expenses, :date
end
end
And then run:
rake db:migrate
This should do the work.
A common task is to rollback the last migration. For example, if you made a mistake in it and wish to correct it. Rather than tracking down the version number associated with the previous migration you can run:
rake db:rollback
This will rollback the latest migration, either by reverting the change method or by running the down method. If you need to undo several migrations you can provide a STEP parameter:
rake db:rollback STEP=3
will revert the last 3 migrations.
First Run:
rails generate migration RemoveDateFromExpense date:date
then rake db:migrate
Hope this help!