Một số lỗi thường gặp và cách giải quyết khi sử dụng migration
Bài đăng này đã không được cập nhật trong 7 năm
1. Giới thiệu
Khái niêm "Rails migrations" chắc hẳn không xa lạ gì đối với lập trình viên ruby on rails nói riêng và tất cả lập trình viên của các ngôn ngữ khác nói chung. Việc thao tác với nó là rất phổ biến, và việc gặp lỗi cũng phổ biến không kém. Ở bài viết này, mình sẽ liệt kê ra 1 số lỗi thông dụng và phương pháp giải quyết nó nhé.
2. Các lỗi thường gặp và phương pháp giải quyết
2.1 Rollback
Câu lệnh
rake db:rollback
sử dụng khá phổ biến cho việc revert lại db khi gặp lỗi. Nhưng có một số trường hợp không thể revert lại db nên chúng ta không thể sử dụng câu lệnh này ví dụ như trường hợp này:
class DropUsers < ActiveRecord::Migration
def change
drop_table :users
end
end
Ở trường hợp này, khi ta rake db:migrate và sau đó rake db:rollback thì sẽ gây ra lỗi. vì vậy sử dụng up/down để thay thế cho change, và chỉ định rõ là khi revert sẽ raise ra lỗi fail ActiveRecord::IrreversibleMigration
class DropUsers < ActiveRecord::Migration
def up
drop_table :users
end
def down
fail ActiveRecord::IrreversibleMigration
end
end
Hoặc nếu muốn revert trong trường hợp này, chúng ta phải chỉ định rõ bảng user gồm những gì, và chúng ra drop nó sẽ bao gôm những gì, thì mới có thể revert lại được
class DropUsers < ActiveRecord::Migration
def change
drop_table :users do |t|
t.string :email, null: false
t.timestamps null: false
end
end
end
2.2 add_column
a. Adding a foreign key?
Khi viết mối quan hệ giữa các bảng với nhau cỡ db, cú pháp phổ biến:
add_column :articles, :author_id, :integer
add_index :articles, :author_id
add_foreign_key :articles, :authors
nhưng chúng ta nên sử dụng add_reference (hoặc add_belongs_to) để thay thế cho add_foreign_key
# good
add_reference :articles, :author, index: true, foreign_key: true
# also good
add_belongs_to :articles, :author, index: true, foreign_key: true
b. Thêm ràng buộc not null vào các column
Khi 1 table có 1 column đòi hỏi không được đẻ trống, chúng ta thường không viết nó ở db, mà chỉ validate ở model:
add_column :users, :email, :string
cách viết tốt hơn
add_column :users, :email, :string, null: false
Và tất nhiên, không phải chúng ta chỉ viết null: false cỡ db như này là đã đủ, mà vẫn cần validate đối với model
# GOOD
add_column :users, :email, :string, null: false
# ...
class User < ActiveRecord::Base
validates :email, presence: true
end
c. Thêm ràng buộc uniq
Tương tự như trên, đối với uniq chúng ta cũng cần viết nó ở file migration cách viết không tốt:
add_column :users, :email, :string
cách viết tốt hơn:
add_column :users, :email, :string
add_index :users, :email, unique: true
d. Thêm giá trị default
Khi tạo ra 1 record của 1 bảng nào đó có column đòi hỏi giá trị defautl, thì chúng ta cũng cần phải viết nó trong file migration
add_column :users, :status, :boolean, null: false, default: true
e. Đánh index cho column của bảng giúp tăng tốc độ query
Đều này thì với những table có lượng records lớn chúng ta sẽ thấy rõ sự khác biệt.
# BAD
add_column :users, :email, :string
# Good
add_column :users, :email, :string
add_index :users, :email
2.3 change_column_null
giả sử ta có 1 table user với column favorite_color, lúc đầu tiên ta tạo các record có favorite_color đều là null, và giờ ta muốn add điểu kiện là column này phải not null. Nếu sử dụng
change_column :users, :favorite_color, :string, null: false
Cách viết này có thể gây ra lỗi vì trước đó đã có rất nhiều record có favorite_color là null bởi vậy cách viết đúng phải là
# GOOD - thay đổi tất cả các record có clumn này nil về 'blue' sau đó thì add điều kiện null: false
change_column_null :users, :favorite_color, true, 'blue'
2.4 remove_column
Cách thương dùng
def change
remove_column :posts, :slug
end
Nhưng khi reverts rake db:rollback thì sẽ bị báo lỗi. Cách viết đúng
# GOOD
def change
remove_column :posts, :slug, :string, null: false, default: ''
end
2.5 create_table
Khi tạo bảng cần phải thêm timestamps (created_at, updated_at)
# BAD - no timestamp
create_table :users do |t|
t.string :email, null: false
end
create_table :users do |t|
t.string :email, null: false
t.timestamps null: false
end
3. Kết Luận
Trên đây mình đã trình bày một số lỗi thường gặp khi tạo file migration, và các cú pháp để viết nó một cách tốt nhất. Hi vọng rằng, qua bài viết này, các bạn sẽ không phải những lỗi ở trên nữa, và tạo ra những sản phẩm chất lượng hơn.
4. Tài liệu tham khảo
All rights reserved