Một số lỗi thường gặp và cách giải quyết khi sử dụng migration
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 ...
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: trueb. 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 endc. 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: trued. 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: truee. Đá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.