I am new to Ruby on Rails, so I have some confusion about rails migration.
I want to add a field on my user table, according to rails documentation is only possible by using
rails generate migration add_field_name_to_table_name field_name: type
Question
Is it possible to add fields to the existing database table without rails g migration in rails? Thanks...
The bigger question is why you need to do that. I mean to imply that whatever makes you think that you need to do this is wrong (I am pretty confident about it, assuming you are a new rails user). It is like you would leave your plane without a reason for a long-distance flight to travel by foot.
Answer:
You can do that by:
logging in to Postgres manually like rails db
then creating table manually the SQL way
then adding the table manually with correct columns in your schema.rb file
then creating a model manually
You still will have to repeat this every time this project is cloned anywhere else with no window for mistake. With migration, on the other hand, you will just need to do rails db:migrate
Happy Coding.
Sorry that this question is not a proper one on this site, but I really thought that I needed to know how to do that, because in production environment, if I delete all data all the time when I delete a model, this should be a serious problem.
In detail
In case re-making the same named model,I mean after delete a model, then make the same named model.
It should be like
rails destroy model Name
and after that
rails g model Name
And usually errors occur in this case, we can basically fix the errors by using the command rails db:schema:load, but this command destroys whole data of an existing database, but I don't want to lose the data so I wonder if there are any other good ways for this.
Thanks
Normally, this should not affect your production database, since Ruby on Rails knows what migrations have run already and that's why you should use rails db:migrate to update your database.
If your production database has old entries that you want to reuse, you can also change the Active Record Migrations so that the affected table does not get dropped and recreated but altered instead.
I have an existing database in which I am converting a formerly 'NULL' column to one that has a default value (and populating that with said default value). However, that value is an ID of a record I need to create. If I put this record in db/seeds.rb, it won't run because db/seeds.rb runs after migrations -- but the migration needs seed data. If I leave the record creation in the migration, then I don't get the record if I make a fresh database with db:load. Is there a better way other than duplicating this in both db/seeds.rb and the migration?
Thanks!
While I can understand your desire to stay DRY and not have to write this in both the migration and seeds.rb, I think you should write it in both places. Not just to make it work, but to accomplish different requirements related to your problem.
You need to ensure that your migration can execute properly regardless of external processes. That means you should put any code required within that specific migration. This isn't to accomplish anything besides making sure your migration executes properly. Suppose someone else tries to migrate without knowing you put part of the code in seeds.rb, it would be very difficult for them to figure out what's going on.
You can make db:load work properly by including similar code in seeds.rb. However, you should be evaluating the current state of your database in seeds.rb due to the fact that it runs after the migrations. So you can check to see if the column exists, and what the default value is etc. This means that if the migration ran and took care of everything, seeds.rb doesn't repeat work or modify values inappropriately. However, if the migration did not set these variables as expected, it is able to set the values.
I'd recommend looking at it as two separate issues so you can be more confident of each one executing successfully independent of one another. It also creates better maintainability for understanding by yourself or others of what's happening in the future.
In my opinion you should treat this in both db/seeds.rb and the migration.
The migration is used to get an existing database from an older version to another version while seeds.rb and schema.rb are used for a fresh database with the latest version.
Many people talking about db migrations, especially about its rollback possibility.
I doubt, whether it is useful at all, because schema of db and model are tightly connected with application logic (MVC).
Suppose i've done rollback of some migration. And what ? The application will not work, because its logic fully relies on db.
What are the use cases of rollback ability for db migrations ?
Update 1
The main question
Why the rollback is presented as a feature, when i need to change the code ?
I don't create the migrations, like "add_another_field_to_table". Instead, each migration file fully describes each table in DB. When i need to change something in my DB, i just change the migration file, but don't roll it back.
Really, if i rollback the migration, it does't brings me back in time, like a version control does. I have a lot of work, when changes are planned and rollback gives me nothing.
The point of rollback is that you rollback code and DB at the same time. The scenario is you upgrade your code and your DB on your production server, then you find a bug and you really need to go back. So rollback your code and use your down migration to roll back your DB.
What are the point of Up migrations?
You create table structures.
You code round it, it works well.
You put site into production, everyone is happy.
Oh, wait, they want a new feature that involves adding a column to an existing table.
How do you handle this? You have to add a column to your development tables, test code, update live site without forgetting to update live DB at the same time (cos if you do there will be big errors) And also remmember to preserve existing live data. This aspect of DB management can be a real pain without a nice managed solution like rails has.
So ...
Code a one line migration that adds a column
Run migration on dev copy, scehma.rb will update
Code new features, if you need to check DB schema use schema.rb NOT migration files.
Now your ready to release on production ....
Update code on production
Run migrations on production. Rails will automatically work out what needs to be applied and do it for you!
Sure, with you adding one column it's not that confusing to do it yourself.
But what if there were 3 programmers all adding migrations? What if you have many live sites, all at different versions? Is that live site 2 or 17 migrations behind? What do I have to do to get the DB up to the latest code, whilst preserving live data? Can you see how this would very quickly get confusing to deal with?
Rails migrations (and practically every migration system works on the same principles) are designed to make updating DB structures really easy. Well worth using properly.
I've found that rollbacks are only useful if they are done locally, ie while you're working on a new bit of code. Once a migration has been committed into your version control system, if you realise there was a mistake then it doesn't really work to roll back the migration because other developers will have pulled the migration down and run it, so you'd need to tell them to roll back as well - this is too difficult to manage and also makes you look incompetent :)
Better in this situation to just do another migration to fix the problem, then everyone (including your production server) just sticks with the pull & migrate system.
Don't really understand your problem, but i try to explain a bit the rollback.
You do rollback if you want to undo the changes by the respective migration. This means that the database will be modified, and also your schema.rb will be automatically regenerated. When you do this probably you want to remove the referencing code too. For example if you removed a field from the model, probably you don't want to refer to that attribute in your code. If you try to access then will gives you undefined attribute exception. That's it.
Can become a bit cumbersome to rollback for example if you created some model 10 migrations before, and you want to change some fields. It's better to create a new migration and modify there, instead of rolling back to the respective migration.
Update 1
Read your update, and i think yo don't use the main advantage of migrations, the flexibility.
But your solution gives more overview of the database situation. If you like to do that way, I suggest the following steps in order.
Roll back to the respective migration.(rake db:migrate VERSION=XXX, I like better rake db:rollback STEP = 2 for example, rolls back 2 migrations, STEP optional)
Make your changes
Migrate your database to update all the tables, and get to current migration version.(rake db:migrate)
This feature don't affect your models or something, just changes the migration file, regenerates your schema.rb and changes the database structure, nothing else. Can't do code rollback like with version control system, and don't really has sense to do something like that. You have to take care about not using removed fields. Rails has automated mapping between database fields and model attibutes, for example if you have an user_id in your comment table, you can call it as an attribute in your model, comment_instance.user_id.
Consider a scenario where you use capistrano to deploy your site and create timestamped snapshots of each deployment. Using the timestamp on the folder and your migrations, you could identify which versions of the code and schema go hand in hand and perform a rollback.
A git repository would give you similar options.
Of course, the real problem is that once users of a site start adding data, that will potentially get purged too, unless you back it up before a rollback and painstakingly restore it at a later date.
I use migration rollback locally with rake db:migrate:redo while working on migration code and before final commit.
I was told that for some reason, you can't update a database schema when using rails. You can drop a table and then recreate a table with an updated schema, but this won't work if you already have content stored in the table that you want to update.
What do you recommend?
Thanks!
What you were told is incorrect. You can update a DB schema when using Rails.
The way you do it is through "migrations."
A common pattern is to write a set of migrations that build your initial schema. As your app develops, you write other migrations that change the tables and columns to suit the evolving design. If the app is in production, you apply these new migrations to the production schema.
Of course some changes will mess up your existing data, but that has nothing to do with Rails. That would be true regardless of what programming language/framework you're using.
If you have a legacy DB schema and are not using migrations, you can still update your schema by interacting directly with the DB server. Again, what will work and what won't in that situation has nothing to do with Rails. It's totally up to the structure of the schema and the data itself.
If you drop a table in the content in it, the content will be destroyed. You can, however, include content migrations alongside db schema migrations, so it will be migrated back to the table once the schema is updated.