Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Rails 5: Change Database Columns

DZone's Guide to

Rails 5: Change Database Columns

A web developer describes how to your Ruby on Rails to interact with and manipulate the database that it connected to your team's web application.

· Web Dev Zone ·
Free Resource

Deploy code to production now. Release to users when ready. Learn how to separate code deployment from user-facing feature releases with LaunchDarkly.

While working on a Rails application, we all have had to change the database column in some way. You can change the column name and the column type, as well as changing the column with the type conversion.

Changing the Column Name

Before we can change a column, we have to create it. Let's start with creating a model for profiles.

class CreateProfiles < ActiveRecord::Migration 
  def change 
    create_table :profiles do |t| 
      t.references :user 
      t.string :avatar 
      t.string :name, null: false 
    end 
  end 
end 

Once you run rake db:migrate the profiles data will be migrated to the database. Then we decided to change the column name. How can we do this?

There are 3 different ways to achieve that:

  • Making a new migration.
  • Fixing the existing migration.
  • Making a migration in order to change the table.

Be sure to run rake db:migrate at the end of all the examples, so the changes will be saved in the database.

Making a New Migration to Change the Column Name

First, you need to create a new migration:

rails g migration rename_profile_name_to_full_name 

Then, add a rename_column in the newly generated file, specifying which table and what column you want to change:

class RenameProfileNameToFullName < ActiveRecord::Migration 
  def change 
    rename_column :profiles, :name, :full_name 
  end 
end 

And you are done!

Fixing an Existing Migration

Before we start, you should rollback the migration that you want to fix. Depending on when the migration was made you can do it in the following ways:

  • The last migration: rake db:rollback.
  • Calling the migration version: rake db:migrate:down VERSION=YOUR_MIGRATION_VERSION.

Once the rollback has been completed you are free to edit the model.

class CreateProfiles < ActiveRecord::Migration 
  def change 
    create_table :profiles do |t| 
      t.references :user 
      t.string :avatar 
      t.string :full_name, null: false 
    end 
  end 
end 

Making a New Migration to Change the Table

You should only use this option when adding multiple changes to the table at once.

Start by creating a new migration:

rails g migration change_profiles 

After the file has been created, specifying which column you want to change by adding a rename type on its place:

class ChangeProfiles < ActiveRecord::Migration 
  def change 
    change_table :profiles do |t| 
      t.references :user 
      t.string :avatar 
      t.rename :name, :full_name # t.string -> t.rename 
    end 
  end 
end 

Always run your RSpec tests after each change to the database to make it sure everything is working as intended. Also, please be careful with reserved names in Rails or SQL when renaming a column. Here is a list of reserved words to help you.

Changing the Column Type

This is a common change that every programmer encounters - you start with a model having an attribute of one type and then you realize it needs to be another. At first, you might think that you should store a profile name as a text when it should actually be a string.

Don't worry! You can easily fix this by generating a new migration:

rails g migration change_name_to_be_string_in_profiles 

Now, open up the migration file and edit it in the following way:

class ChangeNameToBeStringInProfiles < ActiveRecord::Migration 
  def change 
    change_column :profiles, :name, :string 
  end 
end 

Note that change_column is an irreversible migration. It will cause an error if you try to rollback. To prevent this, modify the usual change method in the migration to use two separate up and down methods like this:

class ChangeNameToBeStringInProfiles < ActiveRecord::Migration 
  def up 
    change_column :profiles, :name, :string 
  end 

  def down 
    change_column :profiles, :name, :text 
  end 
end 

Test this out! Start by creating a profile factory and change the name type to a string.

Changing the Column Type - Errors

There are times when simply changing the column type will not work. When you try to write a migration that converts a string column to an integer:

change_column :profile, :age, :integer 

Your database will complain and raise an error:

PG::DatatypeMismatch: ERROR: column "age" cannot be cast 
automatically to type integer 
HINT: Specify a USING expression to perform the conversion. 

To solve this, we will follow the hint and specify in our migration how data should be converted. There are two ways to do this:

  • change_column :profile, :age, 'integer USING CAST(age AS integer)'
  • change_column :profile, :age, :integer, using: 'age::integer'

That's it! Hope these steps helped you to change the database columns to your liking.

Deploy code to production now. Release to users when ready. Learn how to separate code deployment from user-facing feature releases with LaunchDarkly.

Topics:
rails ,database migrations ,database management ,ruby on rails ,web dev

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}