12/08/2018, 15:28

Tổng quan về Active Record Migration(Phần 1)

1. Migrations là gì? Migrations giúp thay đổi/cập nhật cấu trúc database của chúng ta một cách đơn giản. Hãy tưởng tượng rằng, mỗi Migration tạo ra giống như một phiên bản (version) của database vậy. Ban đầu database của chúng ta không có gì. Bằng cách tạo ra các Migration, chúng ta có thể thêm, ...

1. Migrations là gì?

  • Migrations giúp thay đổi/cập nhật cấu trúc database của chúng ta một cách đơn giản. Hãy tưởng tượng rằng, mỗi Migration tạo ra giống như một phiên bản (version) của database vậy. Ban đầu database của chúng ta không có gì. Bằng cách tạo ra các Migration, chúng ta có thể thêm, chỉnh sửa hoặc xóa các bảng, cột cũng như các mục trong database. Active Record cũng sẽ thay đổi schema của chúng ta tương ứng với những cập nhật đó. Những thay đổi sẽ được cập nhật vào file db/schema.rb trong thư mục ứng dụng.

2. Tạo Migration

  • Như đã đề cập ở trên, Migration có thể thêm, xóa hoặc chỉnh sửa bảng, cột. Tuy nhiên ở ví dụ dưới đây, tôi sẽ tạo một bảng để làm ví dụ. Chúng ta sẽ tạo một bảng có tên là User. Bảng này chứa hai trường là name và email, hai trường này đều có kiểu dữ liệu là string. Ta sẽ gõ lệnh sau: rails generate model User name:string email:string. Ta sẽ thấy một file mới được tạo ra trong thư mục db/migrate, file này sẽ có tên dạng YYYYMMDDHHMMSS_create_users.rb. Trong đó, YYYYMMDDHHMMSS sẽ là thời gian của hệ thống khi file này được sinh ra. Đây chính là cách để Rails quản lý các phiên bản của Migration, quyết định các hành động sẽ thực hiện.
  • Trong file này bạn sẽ thấy nội dung như sau:
class CreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email

      t.timestamps
    end
  end
end

Như chúng ta có thể thấy, trường timestamps tự được thêm vào bảng dữ liệu. Nó sẽ tạo ra hai cột created_at và updated_at, chúng sẽ ghi lại thời gian tạo và cập nhật của một bản ghi. Tiếp đến, chúng ta sẽ chạy câu lệnh: rails db:migrate để cập nhật lại database và Active Record cũng sẽ cập nhật nội dung trong file db/schema.rb ứng với các thay đổi vừa thực hiện. File schema.rb bây giờ sẽ trông như thế này:

ActiveRecord::Schema.define(version: 20170622162316) do

  create_table "users", force: :cascade do |t|
    t.string   "name"
    t.string   "email"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

end

Ta có thể dễ dàng nhận ra các thay đổi đã được cập nhật. Và hãy chú ý đến phần version: 20170622162316. Đây chính là phiên bản hiện tại của schema. Tiếp theo chúng ta sẽ thử thay đổi bảng User một chút. Ta sẽ thực hiện bằng cách gõ câu lệnh: rails generate migration AddPasswordToUser. Trong thư mục db/migrate sẽ xuất hiện file dạng như 20170622162449_add_password_to_user.rb. Nội dung sẽ là:

class AddPasswordToUser < ActiveRecord::Migration[5.0]
  def change
  end
end

Chúng ta sẽ thêm cột password cho bảng User bằng cách thêm: add_column :users, :password, :string vào method change. Bây giờ, nội dung file cập nhật sẽ là:

class AddPasswordToUser < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :password, :string
  end
end

Sau đó chạy lệnh rails db:migrate để cập nhật thay đổi cho database cũng như file db/schema.rb. File schema.rb sẽ có nội dung:

ActiveRecord::Schema.define(version: 20170622162449) do

  create_table "users", force: :cascade do |t|
    t.string   "name"
    t.string   "email"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string   "password"
  end

end

Ta có thể thấy rằng nội dung file đã được cập nhật, version hiện tại của schema là 20170622162449. Không chỉ dừng lại ở đó, method change sẽ cung cấp cho chúng ta những phương thức sau để cập nhật cũng như thay đổi database:

add_column
add_foreign_key
add_index
add_reference
add_timestamps
change_column_default (must supply a :from and :to option)
change_column_null
create_join_table
create_table
disable_extension
drop_join_table
drop_table (must supply a block)
enable_extension
remove_column (must supply a type)
remove_foreign_key (must supply a second table)
remove_index
remove_reference
remove_timestamps
rename_column
rename_index
rename_table

3. Một vài khái niệm khác

3.1. Up/down method

Ngoài việc sử dụng method change thì chúng ta có thể sử dụng method up và down. Hiểu nôm na một cách đơn giản, nếu bạn muốn thay đổi schema bằng cách định nghĩa các thay đổi vào method up thì khi bạn muốn hủy bỏ những thay đổi đó, bạn sẽ viết nó vào method down. Ví dụ khi bạn thêm một cột address trong method up thì trong method down bạn sẽ xóa cột đó đi. Hãy mường tượng nó qua đoạn code đơn giản sau:

class AddAddressToUser < ActiveRecord::Migration[5.0]
  def up
    add_column :users, :address, :string
  end

  def down
    remove_column :users, :address, :string
  end
end

3.2. Rolling Back

Trên thực tế, sẽ có lúc bạn thực hiện thay đổi và sau đó nhận ra rằng thay đổi mình vừa làm không tốt cho database của mình. Bạn không biết làm thế nào để hủy bỏ thay đổi đó, chẳng lẽ sẽ phải tạo một migration khác để làm việc đó (ví dụ bạn vừa thêm một cột thì bạn sẽ xóa bỏ cột đó trong migration mới). Nhưng may mắn hơn, Action Record đã cung cấp cho chúng ta một cách đơn giản hơn để giải quyết vấn đề đó. Đó là câu lệnh rollback. Khi bạn chạy câu lệnh rails db:rollback thì nó sẽ quay trở lại version ngay trước của version hiện tại, giúp bạn hủy bỏ các thay đổi vừa làm. Ta sẽ tiếp tục lấy ví dụ trên làm minh họa. Giả sử như ta vừa thêm cột password vào bảng User, bây giờ ta sẽ hủy bỏ thay đổi đó bằng câu lệnh rails db:rollback. Nội dung file schema.rb bây giờ là:

ActiveRecord::Schema.define(version: 20170622162316) do

  create_table "users", force: :cascade do |t|
    t.string   "name"
    t.string   "email"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

end

Chúng ta có thể thấy file schema.rb đã được đưa về version trước đó là: 20170622162316 và cột password đã bị xóa. Thêm nữa, nếu ta muốn quay trở lại các một version nào đó xa hơn chẳng hạn. Hãy sử dụng câu lệnh: rails db:rollback STEP=n trong đó n là số lần muốn rollback. Chẳng hạn db:rollback STEP=2 sẽ tương đương với 2 lần chúng ta chạy câu lệnh rails db:rollback.

Trên đây là một vài chia sẻ ngắn của tôi về Migration trong Active Record. Hy vọng nó sẽ giúp được mọi người hiểu thêm về Migration trong Rails. Rất mong nhận được sự đóng góp của mọi người để tôi có thể hoàn thiện bài viết hơn. Các bạn có thể tham khảo thêm về Migration tại đây

0