Modify a Specific Migration - ruby-on-rails

I have migration (created way back) that i need to change, it's the below:
20130923000732_create_questions.rb
I need to change
t.string to --> t.text
how can i achieve this ?
I read along that i can create a new migration renaming the column, but i did not quite understand it.

If 20130923000732_create_questions.rb migration is your last migration you can rollback with:
rake db:rollback
Otherwise you can simply down your specific migration with VERSION:
rake db:migrate:down VERSION=20130923000732
After rollback your migration, change your migration file and migrate again.

Your app is in development yet, just open that migration in edtor, change it to text and run all your migrations again.
Or write a migration that will update that field type.
First in you terminal:
rails g migration change_column_type_in_questions
Then in your migration file:
class ChangeColumnTypeInQuestions < ActiveRecord::Migration
def change
change_column :questions, :body, :text
end
end
Migration will look for table questions and will update column body type without loosing data.

Run rails generate migration change_string_to_text_in_questions then a new migration file will be created, with
def change
end
method, now insert, change_column :table_name, :column_name, :type now your migration file should look like this,
def change
change_column :table_name, :column_name,:type
end
After this, Save the Changes and run db:migrate

Related

Create a field in a table using Command Prompt *Ruby on Rails

How do I create a new field in an existing table using the Ruby command prompt?
I created the model (and migrated it) but I forgot to add a field - how would I go about this?
Generate a new migration to add a new column to table.
rails g migration add_column_name_to_table_name column_name:type
This will create a migration class like below:
#config/migration/20150304121554_add_column_name_to_table_name.rb
class AddColumnNameToTableName < ActiveRecord::Migration
def change
add_column :table_name, :column_name, :type
end
end
Here, column_name, table_name and type should be your desired name and type. Than run rake db:migrate command.
There are two ways to make changes in your situation:
Roll back the last migration
Add the new field in a new migration
Undoing the last migration should only be done if you have not yet pushed the migration to a public server. Here's how to do it:
Run rake db:rollback
Add the new field to the same migration file you originally used
Run rake db:migrate
Option 2:
To add the field in a new migration:
rails g migration AddFieldNameToTableName
For example, if your field is name and your table is users, you would run:
rails g migration AddNameToUsers
This will create a new migration file whose name starts with today's date and ends with add_name_to_users.rb. Open the file and add the field using the add_column command, like this:
class AddNameToUsers < ActiveRecord::Migration
def change
add_column :users, :name, :string
end
end
Save the file, then run rake db:migrate.
I encourage you to read the Rails migrations guide to learn more.

Rake db:migrate not ignoring old migrations?

Running through Michael Hartl's well known Rails tutorial, hit this snag.
I have this in a migration file, created by rails generate model etc:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.string :email
t.timestamps
end
end
end
Later, I added this second migration file:
class AddIndexToUsersEmail < ActiveRecord::Migration
def change
add_index :users, :email, unique: true
end
end
To try and update the database to include the new one, I followed the instructions and ran rake db:migrate, but this gives me an error telling me I'm trying to create a table that already exists, which is to say I'm clearly missing something.
Am I...supposed to delete the first migration? That wouldn't make any sense. What to do?
(These are the only files under db/migrate)
if you realy want to see what migrations have been ran into the database, you can inspect your app database, there is a table called schema_migrations, in there you can see the unique id of each migration as a row for example is your migration is called: 20130402190449_add_flagand_table.rb, you should see the number 20130402190449 as a row of that table, hope i gave you some guidance
What you can do is rollback couple of migration and re-run.
You can rollback migration like this
#rake db:rollback STEP=2
and then run
#rake db:migrate
Hope it should work
My issues was my 2nd to last migration ran and it was trying to rerun that migration again after i added a new migration.
I ended up just commenting out the code inside the one it was trying to rerun, and then ran rake db:migrate then uncommented the migration code.
This way the schema does not break and it fixes whatever bug occurred.

Ruby on Rails: adding columns to existing database

I'm getting an error:
SQLite3::SQLException: no such column: ideas.list_id:
SELECT "ideas".* FROM "ideas"
WHERE "ideas"."list_id" = 2
But I added
t.integer :list_id
to my db migration file:
class CreateIdeas < ActiveRecord::Migration
def change
create_table :ideas do |t|
t.string :name
t.text :description
t.string :picture
t.timestamps
end
add_foreign_key :ideas, :lists
end
end
which gave me this:
class CreateIdeas < ActiveRecord::Migration
def change
create_table :ideas do |t|
t.string :name
t.text :description
t.string :picture
t.integer :list_id
t.timestamps
end
add_foreign_key :ideas, :lists
end
end
and then I typed
rake db:migrate
Any idea why I would be getting an error saying there's no column? I'm still new to RoRs. Do I have to add a column some other way?
Thanks
As Speransky suggested, you should never modify old migration files. Rather you should create a new migration that adds the desired column. For instance, in this case you would run the following command in your app to create the new migration:
rails generate migration AddListIdColumnToIdeas list_id:integer
And Rails would generate the migration file automatically and the only thing left to do is run rake db:migrate.
If you insist on modifying the old migration file, you can add the column as you did and run the following:
rake db:drop
rake db:create
rake db:migrate
Which will destroy your current database, create a new one and run all the migrations (which will include your new column).
If you want to add a new column to an exist database, you should use rails generate migration. So you can try rails generate migration add_list_id_to_ideas list_id:integer and then use rake db:migrate to commit this change.
You should not add new rows to old migrations. Migration is a step of building database. And number of last executed migration is stored in schema, and it will not be run or redone if you use will use rake db:migrate. If you run the migration with creating the table before, then you should create new migration where you may use add_column method.
migration file name has the datetime encoded in its name so rails run this migration one and do not run it again unless you do a rollback
and here come the magic of migration to build you db with small steps so no need to update a migration after run rake db:migrate , you should make a new migration to do the change you want to your db schema
and remember to
remove the added line form the old migration file as it might raise errors if you decided to rollback this migration
Rails 4.0 easy way to add single or multiple column
https://gist.github.com/pyk/8569812
You can also do this ..
rails g migration add_column_to_users list_id:string
then rake db:migrate
also add :list_id attribute in your user controller ;
for more detail check out http://guides.rubyonrails.org/active_record_migrations.html
If you already have files in your migrate folder, you could just add column you want there(just type the code), delete development.sqlite or whatever represents your db file, and run rake db:migrate.
It will then create a new sqlite file with new column in table, and you can check it in schema.rb
So, basically, everything you did seems good, except you didn't delete your database file.
Doing this seems the easiest for me, all though you will lose all the files in your database. If you're just testing and developing Rails app, this works.
Can anyone comment if there is something wrong with this approach, besides what i wrote?
Edit: I actually found an answer about that here
Editing Existing Rails Migrations is a good idea?

Renaming original migration file in Rails after doing the rename_table_migration

I happened to create a Query model in Rails and recently found out that this is one of the reserved words now..
I renamed the table using a new migration file and renamed all the files that were created (name of new model - Plot)
Question: is it OK to rename the original migration file (20111228212521_create_queries.rb) to 20111228212521_create_plots.rb)
and everything inside the old file:
class CreateQueries < ActiveRecord::Migration
def change
create_table :queries do |t|
t.string :name
t.text :content
t.timestamps
end
end
end
to
class CreatePlots < ActiveRecord::Migration
def change
create_table :plots do |t|
t.string :name
t.text :content
t.timestamps
end
end
end
??
I just don't want too many migration files and also worried that there may be some errors when I switch to production..
You can change the migration file name, but you have to perform a few steps:
rake db:rollback to the point that queries table is rolled back.
Now change the name of migration file, also the contents.
Change the name of any Model that may use the table.
rake db:migrate
The short answer is to just make another migration file.
Migration files are meant to keep track of each and every change to the database. So, you're encouraged to make small one-off changes in a separate file. I can't speak for your situation, but in my situation, when I make a mistake like this, I simply create a new migration file and don't check the old migration file into source control. This way the errant changes are only on my local db and don't get into prod/dev/staging.
Aside from rolling back, and especially useful for when you need to rename a migration from early on in production you can now in Rails 4 create a new migration to rename it.
$rails generate migration RenamesFooBarr
and then in the method of the new migration add
rename_table :old_migration_name, :new_migration name
like this:
class RenamesFooBar < ActiveRecord::Migration
def change
rename_table :old_foo_bar_name, :new_foo_bar_name
end
end
This will effectively take care of all the indexes as well in the up and down since ActiveRecord recognizes the rename_table
source: http://api.rubyonrails.org/classes/ActiveRecord/Migration.html
Simply, do like this
Rollback the migration for that queries. i.e rake db:rollback
Change migration file, class name and the content of it.
Finally, Migrate the database. i.e rake db:migrate

How to drop columns using Rails migration

What's the syntax for dropping a database table column through a Rails migration?
remove_column :table_name, :column_name
For instance:
remove_column :users, :hobby
would remove the hobby Column from the users table.
For older versions of Rails
ruby script/generate migration RemoveFieldNameFromTableName field_name:datatype
For Rails 3 and up
rails generate migration RemoveFieldNameFromTableName field_name:datatype
Rails 4 has been updated, so the change method can be used in the migration to drop a column and the migration will successfully rollback. Please read the following warning for Rails 3 applications:
Rails 3 Warning
Please note that when you use this command:
rails generate migration RemoveFieldNameFromTableName field_name:datatype
The generated migration will look something like this:
def up
remove_column :table_name, :field_name
end
def down
add_column :table_name, :field_name, :datatype
end
Make sure to not use the change method when removing columns from a database table (example of what you don't want in the migration file in Rails 3 apps):
def change
remove_column :table_name, :field_name
end
The change method in Rails 3 is not smart when it comes to remove_column, so you will not be able to rollback this migration.
In a rails4 app it is possible to use the change method also for removing columns. The third param is the data_type and in the optional forth you can give options. It is a bit hidden in the section 'Available transformations' on the documentation .
class RemoveFieldFromTableName < ActiveRecord::Migration
def change
remove_column :table_name, :field_name, :data_type, {}
end
end
There are two good ways to do this:
remove_column
You can simply use remove_column, like so:
remove_column :users, :first_name
This is fine if you only need to make a single change to your schema.
change_table block
You can also do this using a change_table block, like so:
change_table :users do |t|
t.remove :first_name
end
I prefer this as I find it more legible, and you can make several changes at once.
Here's the full list of supported change_table methods:
http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/change_table
Clear & Simple Instructions for Rails 5 & 6
WARNING: You will lose data.
Warning: the below instructions are for trivial migrations. For complex migrations with e.g. millions of rows, read/write dbs, clusters, this advice is not for you:
1. Create a migration
Run the following command in your terminal:
rails generate migration remove_fieldname_from_tablename fieldname:fieldtype (Table name in plural, as per convention. See the documentation here. )
Example: rails g migration RemoveAcceptedFromQuotes accepted:boolean
2. Check the migration
# db/migrate/20190122035000_remove_accepted_from_quotes.rb
class RemoveAcceptedFromQuotes < ActiveRecord::Migration[5.2]
# with rails 5.2 you don't need to add a separate "up" and "down" method.
def change
remove_column :quotes, :accepted, :boolean
end
end
3. Run the migration
rake db:migrate or rails db:migrate (they're both the same)
....And then you're off to the races!
Generate a migration to remove a column such that if it is migrated (rake db:migrate), it should drop the column. And it should add column back if this migration is rollbacked (rake db:rollback).
The syntax:
remove_column :table_name, :column_name, :type
Removes column, also adds column back if migration is rollbacked.
Example:
remove_column :users, :last_name, :string
Note: If you skip the data_type, the migration will remove the column successfully but if you rollback the migration it will throw an error.
in rails 5 you can use this command in the terminal:
rails generate migration remove_COLUMNNAME_from_TABLENAME COLUMNNAME:DATATYPE
for example to remove the column access_level(string) from table users:
rails generate migration remove_access_level_from_users access_level:string
and then run:
rake db:migrate
Remove Columns For RAILS 5 App
rails g migration Remove<Anything>From<TableName> [columnName:type]
Command above generate a migration file inside db/migrate directory. Snippet blow is one of remove column from table example generated by Rails generator,
class RemoveAgeFromUsers < ActiveRecord::Migration
def up
remove_column :users, :age
end
def down
add_column :users, :age, :integer
end
end
I also made a quick reference guide for Rails which can be found at here.
You can try the following:
remove_column :table_name, :column_name
(Official documentation)
rails g migration RemoveXColumnFromY column_name:data_type
X = column name
Y = table name
EDIT
Changed RemoveXColumnToY to RemoveXColumnFromY as per comments - provides more clarity for what the migration is actually doing.
To remove the column from table you have to run following migration:
rails g migration remove_column_name_from_table_name column_name:data_type
Then run command:
rake db:migrate
remove_column in change method will help you to delete the column from the table.
class RemoveColumn < ActiveRecord::Migration
def change
remove_column :table_name, :column_name, :data_type
end
end
Go on this link for complete reference : http://guides.rubyonrails.org/active_record_migrations.html
For removing column from table in just easy 3 steps as follows:
write this command
rails g migration remove_column_from_table_name
after running this command in terminal one file created by this name and time stamp (remove_column from_table_name).
Then go to this file.
inside file you have to write
remove_column :table_name, :column_name
Finally go to the console and then do
rake db:migrate
Give below command it will add in migration file on its own
rails g migration RemoveColumnFromModel
After running above command you can check migration file remove_column code must be added there on its own
Then migrate the db
rake db:migrate
Heres one more from rails console
ActiveRecord::Migration.remove_column(:table_name, :column_name)
Step 1: Create a migration
rails g migration remove_column_name_from_table
Step 2: Change code in file migration just created
rails version < 3
def change
remove_column :table_name, :column_name, :datatype
end
rails version >= 3
def change
remove_column :table_name, :column_name
end
Step 3: Migrate
rake db:migrate
Simply, You can remove column
remove_column :table_name, :column_name
For Example,
remove_column :posts, :comment
first try to create a migration file running the command:
rails g migration RemoveAgeFromUsers age:string
and then on the root directory of the project run the migration running the command:
rails db:migrate
Through
remove_column :table_name, :column_name
in a migration file
You can remove a column directly in a rails console by typing:
ActiveRecord::Base.remove_column :table_name, :column_name
Do like this;
rails g migration RemoveColumnNameFromTables column_name:type
I.e. rails g migration RemoveTitleFromPosts title:string
Anyway, Would be better to consider about downtime as well since the ActiveRecord caches database columns at runtime so if you drop a column, it might cause exceptions until your app reboots.
Ref: Strong migration
Mark the column as ignored in the model
class MyModel < ApplicationRecord
self.ignored_columns = ["my_field"]
end
Generate a migration
$ bin/rails g migration DropMyFieldFromMyModel
Edit the migration
class DropMyFieldFromMyModel < ActiveRecord::Migration[6.1]
def change
safety_assured { remove_column :my_table, :my_field }
end
end
Run the migration
$ bin/rails db:migrate
you can use rails migration command
rails generate migration RemoveColumnNameFromTableName column_name:column_type
than you can migrate the database:
rails db:migrate
Just run this in the rails console
ActiveRecord::Base.connection.remove_column("table_name", :column_name, :its_data_type)
or
TableName.find_by_sql(“ALTER TABLE table_name DROP column_name”)

Resources