Rails Migrations: Kiểm tra sự tồn tại và tiếp tục?


80

Tôi đã làm điều này trong quá trình di chuyển của mình:

add_column :statuses, :hold_reason, :string rescue puts "column already added"

nhưng nó chỉ ra rằng, trong khi điều này hoạt động cho SQLite, nó không hoạt động cho PostgreSQL . Có vẻ như nếu add_column bị nổ tung, ngay cả khi Exception được bắt, giao dịch đã chết và do đó Migration không thể thực hiện thêm bất kỳ công việc nào.

Có bất kỳ cách cụ thể nào không phải DB để kiểm tra xem một cột hoặc bảng đã tồn tại chưa? Không thành công, có cách nào để khối cứu hộ của tôi thực sự hoạt động không?


Nó cần phải được đề cập, mà dẫn di cư có điều kiện đến các vấn đề với rollback do thực tế rằng ở giai đoạn rollback nó không biết gì điều kiện là trong quá trình chuyển về phía trước
oklas

Chỉ làm một phần không bắt buộc trong rollback
Dan Rosenstark

Câu trả lời:


175

Kể từ Rails 3.0 trở lên, bạn có thể sử dụng column_exists?để kiểm tra sự tồn tại của một cột.

unless column_exists? :statuses, :hold_reason
  add_column :statuses, :hold_reason, :string
end

Ngoài ra còn có một table_exists?chức năng, tương tự như Rails 2.1.


Việc kiểm tra xem một cột / bảng có tồn tại hay không trước khi thêm / tạo nó có được coi là phương pháp hay nhất không? (Tôi biết tất nhiên nó phụ thuộc vào vấn đề trong tay)
Aldo 'xoen' Giambelluca

4
Điều này có hoạt động với quá trình khôi phục không nếu tôi xác định nó trong phương thức thay đổi?
dardub

1
Vâng, khôi phục sẽ là một vấn đề ... chúng tôi không chắc liệu chúng tôi có nên xóa cột hay không .. vì chúng tôi không ghi lại trạng thái trước đó.
songyy vào

8

Hoặc thậm chí ngắn hơn

add_column :statuses, :hold_reason, :string unless column_exists? :statuses, :hold_reason

đây sẽ là một nhận xét về câu trả lời khác, không phải là một câu trả lời. Cảm ơn.
Dan Rosenstark

4

Đối với Rails 2.X , bạn có thể kiểm tra sự tồn tại của các cột bằng cách sau:

columns("[table-name]").index {|col| col.name == "[column-name]"}

Nếu nó trả về nil, không có cột nào như vậy tồn tại. Nếu nó trả về một Fixnum, thì cột đó tồn tại. Đương nhiên, bạn có thể đặt các tham số chọn lọc hơn giữa {...}nếu bạn muốn xác định một cột chứ không chỉ tên của nó, ví dụ:

{ |col| col.name == "foo" and col.sql_type == "tinyint(1)" and col.primary == nil }

(câu trả lời này được đăng lần đầu trên Làm thế nào để viết di chuyển có điều kiện trong đường ray? )


0

add_column :statuses, :hold_reason, :string unless Status.column_names.include?("hold_reason")

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.