Rails 5 supports adding comments in migrations

Prajakta Tambe

By Prajakta Tambe

on June 21, 2016

This blog is part of our  Rails 5 series.

Database schemas change rapidly as project progresses. And it can be difficult to track purpose of each table and each column in a large project with multiple team members.

The solution for this problem is to document data models right from Rails migrations.

Solution in Rails 4

You can add comments in Rails 4.x migrations using gems like migration_comments and pg_comment.

Solution in Rails 5

Rails 5 allows to specify comments for tables, column and indexes in migrations.

These comments are stored in database itself.

Currently only MySQL and PostgreSQL supports adding comments.

We can add comments in migration as shown below.

1class CreateProducts < ActiveRecord::Migration[5.0]
2  def change
3    create_table :products, comment: 'Products table' do |t|
4      t.string :name, comment: 'Name of the product'
5      t.string :barcode, comment: 'Barcode of the product'
6      t.string :description, comment: 'Product details'
7      t.float :msrp, comment: 'Maximum Retail Price'
8      t.float :our_price, comment: 'Selling price'
9
10      t.timestamps
11    end
12
13    add_index :products, :name,
14              name: 'index_products_on_name',
15              unique: true,
16              comment: 'Index used to lookup product by name.'
17  end
18end

When we run above migration output will look as shown below.

1➜  rails_5_app rake db:migrate:up VERSION=20160429081156
2== 20160429081156 CreateProducts: migrating ===================================
3-- create_table(:products, {:comment=>"Products table"})
4   -> 0.0119s
5-- add_index(:products, :name, {:name=>"index_products_on_name", :unique=>true, :comment=>"Index used to lookup product by name."})
6   -> 0.0038s
7== 20160429081156 CreateProducts: migrated (0.0159s) ==========================

The comments are also dumped in db/schema.rb file for PostgreSQL and MySQL.

db/schema.rb of application will have following content after running products table migration .

1ActiveRecord::Schema.define(version: 20160429081156) do
2
3  # These are extensions that must be enabled in order to support this database
4  enable_extension "plpgsql"
5
6  create_table "products", force: :cascade, comment: "Products table" do |t|
7      t.string   "name",                     comment: "Name of the product"
8      t.string   "barcode",                  comment: "Barcode of the product"
9      t.string   "description",              comment: "Product details"
10      t.float    "msrp",                     comment: "Maximum Retail Price"
11      t.float    "our_price",                comment: "Selling price"
12      t.datetime "created_at",  null: false
13      t.datetime "updated_at",  null: false
14      t.index ["name"], name: "index_products_on_name", unique: true, using: :btree, comment: "Index used to lookup product by name."
15    end
16end

We can view these comments with Database Administration Tools such as MySQL Workbench or PgAdmin III.

PgAdmin III will show database structure with comments as shown below.

1-- Table: products
2
3-- DROP TABLE products;
4
5CREATE TABLE products
6(
7  id serial NOT NULL,
8  name character varying, -- Name of the product
9  barcode character varying, -- Barcode of the product
10  description character varying, -- Product details with string data type
11  msrp double precision, -- Maximum Retail price
12  our_price double precision, -- Selling price
13  created_at timestamp without time zone NOT NULL,
14  updated_at timestamp without time zone NOT NULL,
15  CONSTRAINT products_pkey PRIMARY KEY (id)
16)
17WITH (
18  OIDS=FALSE
19);
20ALTER TABLE products
21  OWNER TO postgres;
22COMMENT ON TABLE products
23  IS 'Products table';
24COMMENT ON COLUMN products.name IS 'Name of the product';
25COMMENT ON COLUMN products.barcode IS 'Barcode of the product';
26COMMENT ON COLUMN products.description IS 'Product details with string data type';
27COMMENT ON COLUMN products.msrp IS 'Maximum Retail price';
28COMMENT ON COLUMN products.our_price IS 'Selling price';
29
30
31-- Index: index_products_on_name
32
33-- DROP INDEX index_products_on_name;
34
35CREATE UNIQUE INDEX index_products_on_name
36  ON products
37  USING btree
38  (name COLLATE pg_catalog."default");
39COMMENT ON INDEX index_products_on_name
40  IS 'Index used to lookup product by name.';

If we update comments through migrations, corresponding comments will be updated in db/schema.rb file.

Stay up to date with our blogs. Sign up for our newsletter.

We write about Ruby on Rails, ReactJS, React Native, remote work,open source, engineering & design.