TL;DR;
In the past (a few years ago now), I have used custom generators within Ruby to change how things are created when say you run rails g model Users
. My question today is whether or not you can change how Rails generates a migration file.
What I am trying to do
Whenever I generate a migration through one of Rails' generation functions, I almost always have to go in and make changes; and usually to the same thing. If not to add in a def up
and def down
for reverting purposes; I almost always need to change the placement of the t.timestamps
. I like to have my timestamps to be at the beginning of a table that way if I ever decide to add additional columns to a table (and let's face it, that always seems to happen as a project grows), the timestamps are not stuck in the middle of the table.
Example
Let's say, for ease of example, that I run rails g scaffold Notes body:text
This generates many files and the following migration document:
class CreateNotes < ActiveRecord::Migration[7.0]
def change
create_table :notes do |t|
t.text :body
t.timestamps
end
end
end
with the following schema after db:migrate
is run:
create_table "notes", force: :cascade do |t|
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Now, if say later on we want to add the ability to have a title to a note. So we run rails g migration AddTitleToNotes title:string
which give us this migration:
class AddTitleToNotes < ActiveRecord::Migration[7.0]
def change
add_column :notes, :title, :string
end
end
And, when db:migrate
is run this time, our schema is updated to look like this:
create_table "notes", force: :cascade do |t|
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "title"
end
Now, this small example may not seem too bad, but when you start off when a table of 7 columns and then add 3 columns later (No reason I came up with those numbers, lol), you get the timestamps at column 9 and 10 (because of the first column of id
is always there) and the new columns at 11-13.
This may just be a "me" problem, but I like to keep my schema's easy to read, and same with the database. So, in this scenario, I would go into the first migration file and change it to:
class CreateNotes < ActiveRecord::Migration[7.0]
def change
create_table :notes do |t|
t.timestamps
t.text :body
end
end
end
That way the resulting schema would look like:
create_table "notes", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "body"
end
and after adding the 'title' later, the schema would look like:
create_table "notes", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "body"
t.string "title"
end
QUESTION
So, my question again is, can I change how Rails creates the migration file to always put t.timestamps
at the beginning of the migration file right after the create_table
clause?
Bonus Question to save my sanity
Can I also change how Rails updates the schema to have it stop adding the "helper" text that is commented out at the top of the schema every time I run a new migration? (Again, may be a me problem, but I like a clean schema, what can I say?)
"Helper" text at the top of the schema.rb file
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# This file is the source Rails uses to define your schema when running `bin/rails
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
# be faster and is potentially less error prone than running all of your
# migrations from scratch. Old migrations may fail to apply correctly if those
# migrations use external dependencies or application code.
#
# It's strongly recommended that you check this file into your version control system.