If I edit my shema, and run db:migrate the database doesn't changed, but if I clear to version 0, and recall migration it's works, but I lost all database data.
What's wrong?
That's how db:migrate works. It maintains a table in the database called schema_migrations that keeps track of the migration timestamps (i.e. if your file is called 20090807152224_create_widgets.rb, the 20090807152224 part is the timestamp -- and the line that will get added to your schema_migrations table).
You're not supposed to modify the schema.rb file by hand -- that file gets autogenerated as a result of db:migrate.
The thinking in rails is that if you want to make a change to your schema, you're going to generate a new migration with those changes and then run db:migrate (which, as a result, will update the schema.rb file appropriately).
When you say you are updating your schema, does that mean you're updating the db/schema.rb file, or actual migrations?
If you're updating the schema.rb file, you should note that it will have no effect because the file is auto-generated.
See the comment at the top of the file:
# 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.
It sounds like you were changing a migration file.
Don't change migration files. Add new ones. You can have migrations that change say, the type of a column. There are times when changing old migrations may be helpful, but don't do it unless you know the consequences. As others have mentioned, don't change the schema either, but I don't think you were doing that.
Related
I generated a migration, add_content_to_users content:string. I ran db:migrate and in the edit page I added text into this content attribute. I realized I wanted to do something else, so I want to get rid of content. Is db:rollback sufficient, or do I have to also reset and migrate the database again (would rather not) using something like db:migrate:reset?
rake db:rollback undoes the last migration (in most cases) if it added a column, it will drop said column completely from your database table. All data in the column is lost.
If you don't alter or remove that migration file of course, the column will be added again the next time you run rake db:migrate.
One of my migration files is referencing another table/model that will will be created further down the migration sequence.
Postgres doesn't like that:
PG::UndefinedTable: ERROR: relation "users" does not exist
So I wonder if there are any potential problems to manually reorder the migration files (by inventing new timestamps/prefixes)?
The affected tables are already down migrated.
When you run rake db:migrate command it compares schema_migrations table and migration files located in db/migrate folder. All the migrations which were not executed receive MigrationClass#up call then.
So starting from the point when your code is already published and/or migrations are run by other users, changing your migrations timestamps/names may lead to unprocessable migration procedure (as schema_migrations will treat a migration with changed timestamp as new, unprocessed one, and try to process it "again"). Possible workaround for this would be to comment the contents of up method for a while and uncomment it back after migrations are done. For fun you can also manipulate schema_migrations table directly from your db console (adding or removing necessary records). Both of these ways smells like a hack though.
Until then... Everything should work flawlessly.
This is what worked for me for this same situation, even though it's a hack.
Rails runs migrations in order of the timestamp, and Rails tracks which migrations have been run by the timestamp part of the migration file name, but not by the rest of the file name. So if you need to change the order of two migrations because the earlier one references the later one you can simply switch the 14 digit timestamp portion of the filenames by renaming both migration files. If the timestamp is off by even one digit Rails will think it's a new migration so write them down before changing them.
What is happening under the hood when executing this?
rails generate migration create_menu_categories_and_menu_items
Why can't I just create a file in the migrations directory? It seems I have to use the generate command in order for it to actually run, but the only file I see changed is the file created by the above command.
You can, but you need to get the time stamp at the beginning of the file name, so that rails can figure out that it's a "pending migration" and run it. It does this by storing the time stamp (or version in migration parlance) in a special database table (schema_migrations) and anything newer than the last run migration is pending.
Otherwise there's nothing special about the file itself
You dont even have to create a separate migration file. You can just add a column to your table by adding the object to to your current migration class like this:
t.string :name
Then run a rake db:migrate
Hope this helps.
I have a question regarding my migrations in rails.
Normally when i want to add a colum to a model for i dont make extra migrations but instead i perform this steps:
rake db:rollback
next i change the migration file in db/migrations and rerune:
rake db:migrate
The biggest problem is that when i do this i loose my data.
Previous i wrote migrations from the command line with for example
rake g migration Add_Column_House_to_Users house:string
The problem with this approach is that my db/migrations folder afterwards get very large and not very clear! I mean at the end i dont know wich variables the object has! Im not an expert in rails and would like to ask you how to keep the overview over the migrations!Thanks
Just a minor thought - I just use the file db/migrate/schema.rb to determine whats in the database as opposed to tracking through the migrations
You definitely shouldn't use db:rollback with a table with existing data.
I have a few production RonR apps with a ton of data and there are 100+ entries in the migrations table and adding new migrations to tweak tables is the rails way to do things. Not sure what you mean by lucid, but your schema and data model are going to change over time and that is ok and expected.
One tip. The migrations are great, but they are just the beginning, you can include complex logic as needed to fix your existing data (like so)
Changing data in existing table:
def up
add_column :rsvps, :column_name_id, :integer
update_data
end
def update_data
rsvps = Rsvp.where("other_column is not null")
rsvps.each do |rsvp|
invite = Blah.find(rsvp.example_id)
...
rsvp.save
end
end
Another tip: backup your production database often (should do this anyway), but use it to test all of your migrations before deploying. I run scripts like this all the time for local testing:
mysql -u root -ppassword
drop database mydatabase_dev;
create database mydatabase_dev;
use mydatabase_dev;
source /var/www/bak/mydatabase_backup_2013-10-04-16.28.06.sql
exit
rake db:migrate
I am a little confused how migrations affect schema.rb file?
For example if I write a migration to rename a table column and run that migratin and even do a schema:load rake task too, then when I open my schema.rb file should it automatically be changed to have that new column name? or should I manually change it in there too?
Also my create_table*.rb files that create the original tables. They automatically have a t.timestamp field defined in them that creates those two created_at and updated_at fields in the schema, so if I want to remove those is it enough to just alter the create_table*.rb file and take out t.timestamp from them? and run the migration? or again I should manually alter shcema.rb file too?
So if someone can explain a little bit how there work together would be great.
The schema file is automatically altered when you run migrations. You should never have to manually edit it.
See this Rails Guide for moer information.