We have script/generate migration add_fieldname_to_tablename fieldname:datatype syntax for adding new columns to a model.
On the same line, do we have a script/generate for changing the datatype of a column? Or should I write SQL directly into my vanilla migration?
I want to change a column from datetime to date.
10 Answers
Use #change_column.
change_column(:table_name, :column_name, :date)
# a few more examples:
change_column(:suppliers, :name, :string, limit: 80)
change_column(:accounts, :description, :text)NOTE: the same result can be achieved even outside of db migrations, this might be handy for testing/debugging but this method needs to be used very cautiously:
ActiveRecord::Base.connection.change_column(:table_name, :column_name, :date) 10 You can also use a block if you have multiple columns to change within a table.
Example:
change_table :table_name do |t| t.change :column_name, :column_type, {options}
endSee the API documentation on the Table class for more details.
I'm not aware if you can create a migration from the command line to do all this, but you can create a new migration, then edit the migration to perform this taks.
If tablename is the name of your table, fieldname is the name of your field and you want to change from a datetime to date, you can write a migration to do this.
You can create a new migration with:
rails g migration change_data_type_for_fieldnameThen edit the migration to use change_table:
class ChangeDataTypeForFieldname < ActiveRecord::Migration def self.up change_table :tablename do |t| t.change :fieldname, :date end end def self.down change_table :tablename do |t| t.change :fieldname, :datetime end end
endThen run the migration:
rake db:migrate As I found by the previous answers, three steps are needed to change the type of a column:
Step 1:
Generate a new migration file using this code:
rails g migration sample_name_change_column_typeStep 2:
Go to /db/migrate folder and edit the migration file you made. There are two different solutions.
def change change_column(:table_name, :column_name, :new_type) end
2.
def up change_column :table_name, :column_name, :new_type end def down change_column :table_name, :column_name, :old_type endStep 3:
Don't forget to do this command:
rake db:migrateI have tested this solution for Rails 4 and it works well.
3With Rails 5
From Rails Guides:
If you wish for a migration to do something that Active Record doesn’t know how to reverse, you can use
reversible:
class ChangeTablenameFieldname < ActiveRecord::Migration[5.1] def change reversible do |dir| change_table :tablename do |t| dir.up { t.change :fieldname, :date } dir.down { t.change :fieldname, :datetime } end end end
end Just generate migration:
rails g migration change_column_to_new_from_table_nameUpdate migration like this:
class ClassName < ActiveRecord::Migration change_table :table_name do |table| table.change :column_name, :data_type end
endand finally
rake db:migrate This is all assuming that the datatype of the column has an implicit conversion for any existing data. I've run into several situations where the existing data, let's say a String can be implicitly converted into the new datatype, let's say Date.
In this situation, it's helpful to know you can create migrations with data conversions. Personally, I like putting these in my model file, and then removing them after all database schemas have been migrated and are stable.
/app/models/table.rb ... def string_to_date update(new_date_field: date_field.to_date) end def date_to_string update(old_date_field: date_field.to_s) end ... def up # Add column to store converted data add_column :table_name, :new_date_field, :date # Update the all resources Table.all.each(&:string_to_date) # Remove old column remove_column :table_name, :date_field # Rename new column rename_column :table_name, :new_date_field, :date_field end # Reversed steps does allow for migration rollback def down add_column :table_name, :old_date_field, :string Table.all.each(&:date_to_string) remove_column :table_name, :date_field rename_column :table_name, :old_date_field, :date_field end You can use change_column for this:
def change change_column :table_name, :column_name, :new_data_type
end 1 To complete answers in case of editing default value :
In your rails console :
rails g migration MigrationNameIn the migration :
def change change_column :tables, :field_name, :field_type, default: value endWill look like :
def change change_column :members, :approved, :boolean, default: true end Another way to change data type using migration
step1: You need to remove the faulted data type field name using migration
ex:
rails g migration RemoveFieldNameFromTableName field_name:data_typeHere don't forget to specify data type for your field
Step 2: Now you can add field with correct data type
ex:
rails g migration AddFieldNameToTableName field_name:data_typeThat's it, now your table will added with correct data type field, Happy ruby coding!!
3