I'm getting an error when trying to run rake db:migrate:
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column "plus_ids" of relation "comments" does not exist
I guess I did do some funky stuff when trying to remove the attribute plus_ids from my comment model. I'm not sure what is going on.
If I do a rake db:reset and then fetch the live database it all works locally again, but if I try to do a rake db:migrate it throws an error again.
How can I get rid of plus_ids properly so I can migrate?
Edit 1: Here's the migration files when I added (and removed) the attribute:
class RemovePlusIdsFromComments < ActiveRecord::Migration
def change
remove_column :comments, :plus_ids, :integer
end
end
And then
class AddPlusIdsToComments < ActiveRecord::Migration
def change
add_column :comments, :plus_ids, :integer
end
end
They're in the wrong order in the migration list, not sure why.
Edit 2: I think there is something wrong with the Up/Down, if I run rake db:migrate:status I get this:
down 20150305203336 Remove plus ids from comments
down 20150305204404 Add plus ids to comments
Any way around this?
The answer was to run
rake db:migrate:up VERSION=20150305204404
On both live and local, and then
rake db:migrate
On both again. Now the live and local database is in sync again, and migrating the database throws no errors.
Related
I want to remove column and index in activities table. To do so I've got below migration:
class RemoveUnnecessaryJourneyActivitiesRelations < ActiveRecord::Migration[6.0]
def change
remove_index :activities, :cms_journey_id
remove_column :activities, :cms_journey_id, :bigint
end
end
When I run rake db:migrate it removes this column and index as well but when I want to reset my DB by rake db:drop db:create db:migrate db:seed or bin/rails db:setup I'm getting an error:
rake aborted!
ActiveModel::UnknownAttributeError: unknown attribute 'cms_journey_id' for Activity.
How was the attribute added in the first place? If it was via a migration it looks like that file had been deleted.
You have two options - if you want to get the above migration working, you'll need to insert one before it (with an earlier timestamp) that creates the attribute, and then run this migration to remove it.
Of course, the easier option is to just delete the above migration. Because there is no migration that creates the attribute, you can delete the above migration, run rake db:migrate, have a look at your db.schema.rb file, and you'll see no column called cms_journey_id on the activities table.
I'm trying to migrate a change to my Comments table with rails migration. I've already made the migration and everything looks good but when I run rake db:migrate it sends back this error NameError: uninitialized constant Model. I can't see the problem? All the naming look right to me. Here is my migration file let me know if anything looks off or if you need more information. Thank you!
MIGRATION:
class AddColumnToComments < ActiveRecord::Migration
def change
add_column :comments, :fav_drink, :string
add_column :comments, :visit_time, :string
end
end
ERROR:
I assume you've used rails generator to create your migration and this generator has probably create a migration file named: 201606xxxxxxxx_model.rb.
If it's the case, rename you migration file as follow: 201606xxxxxxxx_add_column_to_comments.rb
I tried to create a migration to add roles to my user tables but i accidentally typed AddRolesToUsers instead of AddRoleToUser. So i tried creating a new migration with the correct AddRoleToUsers but when i tried to run rake db:migrate i got an error :
SQLite3::SQLException: duplicate column name: role: ALTER TABLE "users" ADD "role" integer/Users/miguel/.rvm/gems/ruby-2.2.1/gems/sqlite3-1.3.11/lib/sqlite3/database.rb:91:in `initialize'
I tried rake db:migrate:down VERSION= do delete the one I had to type on but i keep getting the same error . PS: i deleted the migration file manually after running rake db:migrate:down VERSION=
rails g migration AddRoleToUsers role:integer
migration file :
class AddRoleToUsers < ActiveRecord::Migration
def change
add_column :users, :role, :integer
end
end
When you ran the first migration, the role column was added to the Users table. The error on the second migration tells you that much.
To clear the migration pending error, you need to comment out the add_column statement in the new migration.
i.e,
class AddRoleToUsers < ActiveRecord::Migration
def change
# add_column :users, :role, :integer
end
end
Then run the migration. This way, the new migration should run successfully.
You can now uncomment it and delete the previous migration, so that when you deploy, only the newer migration is run and the role column is added successfully.
In that case right click and delete both migration files and start again. The error exists because it thinks you want to add two columns both named role to your users table
UPDATE
In that case, if role already exists in your users table, a migration must've been successfully run and there is no need to run another. As long as the role column is there, trying to add another column called role will always give you an error. If you wanted to test that you are still able to add new columns you can always check by creating a test migration AddSomethingToUsers something:string and rake db:migrate to test, then rake db:rollback to undo..but it all seems like it's worked so I probably my wouldn't mess with it too much.
So i made a migration like this
class AddDatetimeAttrToUsers < ActiveRecord::Migration
def change
change_column :users, :oauth_expires_at, :datetime
end
end
on my local environment it works just fine but when i try
heroku run rake db:migrate i get an error
ERROR: column "oauth_expires_at" cannot be cast automatically to type timestamp without time zone
HINT: Specify a USING expression to perform the conversion.
When i searched it, i created a new migration like this as best practice for changing an attribute using change.
class PutDatetimeFieldToUsersExpireAtColumn < ActiveRecord::Migration
def change
remove_column :users, :oauth_expires_at
add_column :users, :oauth_expires_at, :datetime
end
end
so i tried to use rake db:rollback to delete last migration and add this one informing me that the last migration is irreversible.
my question is, is there a way to actually rollback on an irreversible migration or should i just migrate using the new migration above?
In your example, you have the following migration file:
class AddDatetimeAttrToUsers < ActiveRecord::Migration
def change
change_column :users, :oauth_expires_at, :datetime
end
end
You have already run rake db:migrate successfully in your dev environment. You are running sqlite3 locally and PG on heroku, and and as a result, your change_column works locally, but it fails on PG because PG expects a 'using' statement.
The fix this, step 1 is to edit your migration file to add an up and down migration as suggested by Yohann above. Yes, you should do this even though you have already raked this migration.
class AddDatetimeAttrToUsers < ActiveRecord::Migration
def up
change_column :users, :oauth_expires_at, :datetime
end
def down
change_column :users, :oauth_expires_at, :time (or whatever type existed before datetime)
end
end
Now you can run rake db:rollback and avoid the irreversible migration error, but only if you HAVE NOT ADDED ADDITIONAL MIGRATIONS. If you have added additional migrations you will need to specify how far back to go using rake db:down VERSION=2018xxxxxxx or rake db:rollback STEP=X.
Now edit the migration so it plays nice with pg and sqlite3:
class AddDatetimeAttrToUsers < ActiveRecord::Migration
def up
change_column :users, :oauth_expires_at, :datetime, using: 'oauth_expires_at::datetime'
end
def down
change_column :users, :oauth_expires_at, :time
end
Now you should be able to rake db:migrate, push to heroku, and heroku run rake db:migrate and move on.
Finally, you should get pg working locally to match your production environment.
You can define up and down methods instead of change in your migration.
Here is an example:
def up
connection.execute %(create or replace view name_of_the_db_view)
end
def down
connection.execute %(drop view name_of_the_db_view)
end
With it you will be able to migrate and rollback the previously irreversible migration like it was a normal migration.
It seems you need to specify a current type of oauth_expires_at column, because at rollback Rails should know it to create the column. I mean following:
remove_column :users, :oauth_expires_at, :string
if you dare to lose your data on your local database then you can recover from irreversible migration(by losing your database data) by doing these steps:
1- first deleting your database(assuming that you are in the development environment and just ok to delete the database in this environment - your test database will also be gone)
export RAILS_ENV=development
rake db:drop
2- Reloading your schema file:
rake db:schema:load
3- To see your current migration files:
rake db:migrate:status
4- Delete the migration that you want to get rid of:
rake db:migrate:down VERSION=xxxxxx
rails destroy migration migration_name
5- Then you can make db:migrate to migrate your migrations.
rake db:migrate
An old one of my ruby on rails migrations contains both the actual migration but also an action to modify data:
class AddTypeFlagToGroup < ActiveRecord::Migration
def self.up
add_column :groups, :selection_type, :string
Group.reset_column_information
Group.transaction do
Group.all.each do |group|
group.selection_type = group.calculate_selection_type
group.save
end
end
end
def self.down
remove_column :groups, :selection_type
end
end
In this migration there are the usual add_column and remove_column migration statements. But there are also some model specific method calls.
I wrote this a couple of weeks ago. Since then, I have removed my Group model, which gives an error when I do a full migration with :reset.
rake db:migrate:reset
(in /Users/jesper/src/pet_project)
[...]
== AddTypeFlagToGroup: migrating =============================================
-- add_column(:groups, :selection_type, :string)
-> 0.0012s
rake aborted!
An error has occurred, this and all later migrations canceled:
uninitialized constant AddTypeFlagToGroup::Group
The thing is that in the current revision of my code, Group does not exist. How should I handle this "the rails way"??
I am thinking I could modify the migration by commenting out the Group.xxx stuff, but is this a wise way to go?
There is no value in leaving the group stuff in your migration now that it is gone from your project. I'd just edit the migration, drop everything from the db and migrate from scratch. There isn't even a reason to comment it out (you are using version control right?)
Also, I believe the "rails way" with migrations is spelled "Arrrrgh!"