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
Related
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
My app is working fine locally and my push to Heroku was successful. But, when I run heroku run rake db:migrate, I get the following error:
NameError: uninitialized constant AddWeightToExercises
Here is the failed migration:
class AddWeightToExercise < ActiveRecord::Migration
def change
add_column :exercises, :weight, :float
end
end
edit: Thanks for the help everyone. The solution was to pluralize the class name to match the file name. Thanks for the help and quick responses.
Your migration file's name should correspond to AddWeightToExercises. It should be accordingly xxxxxxxx_add_weight_to_exercises, where xxxxxxx corresponds to a particular timestamp.
Your file name uses "exercises" plural, but your class name is AddWeightToExcercise singular. The two need to be consistent for rails to dynamically load the appropriate class.
I wanted to change the name of a table I creted with rake db:migrate from financialss to financials. I created a file in my migrate directory called changeme.rb that looks like this.
class CreateFinancials < ActiveRecord::Migration
def self.up
rename_table :financials, :financialss
end
def self.down
rename_table :financialss, :financials
end
end
I tried to run the following:
rake db:migrate:up changeme.rb
and got the following error:
rake aborted!
Don't know how to build task 'db:migrate:changeme.rb'
All help appreciated
Use the rails generator
rails g migration MigrationName
The rails do not understand when you come out of the convention. So try to use the default generator.
Please see this page, as I have the same problem: DangerousAttributeError in OmniAuth Railscast Tutorial: create is defined by ActiveRecord
However being fairly new to rails, I am not quite sure as to how to remove the fields they speak of from the database. In other-words, there is no step-by-step concise way described anywhere in that post.
The below post is in fact a proper solution, but it is unclear as to what he was referring to when he wrote: "rails g migration remove_silly_authentication_fields_which_should_not_be_there" Not sure what "silly_authentication_fields_which_should_not_be_there" is exactly.
Here is the post I am referring to:
So just to finish the question off you will need to create a migration
using this command:
rails g migration
remove_silly_authentication_fields_which_should_not_be_there
Which looks something like this:
class DropSillyControllerAttributes < ActiveRecord::Migration def
change
remove_column :authentications, :index
remove_column :authentications, :create
remove_column :authentications, :destroy end end
And run it using the usual:
rake db:migration
Or alternatively you should be able to run:
rake db:rollback
To roll back the changes just made to the database and:
rails d scaffold authentication
To remove all the files, then run:
rails g scaffold authentication user_id:integer provider:string
uid:string
And do the other stuff manually
I did exactly the same thing myself by the way.
it's telling you to create a migration to remove the problematic fields and then run the migration
to make it clearer:
run this command:
rails g migration drop_silly_controller_attributes
that command will create a file in /db/migratie/ with the timestamp and that name, something like:
2013121212312312_drop_silly_controller_attributes.rb
open that file and modify it to look like this:
class DropSillyControllerAttributes < ActiveRecord::Migration
def change
remove_column :authentications, :index
remove_column :authentications, :create
remove_column :authentications, :destroy
end
end
then you can run the migration doing:
rake db:migrate
it's confusing because the if you generate the migration with "remove_silly_authentication_fields_which_should_not_be_there" the class should be RemoveSillyAuthenticationFieldsWhichShouldNotBeThere, but then it says "DropSillyControllerAttributes", so you should generate the migration with drop_silly_controller_attributes to make it consistence
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!"