20

PostgreSQL có khái niệm về enumerated types được tích hợp vào cơ sở dữ liệu.Làm thế nào để sử dụng enum trong cơ sở dữ liệu Postgres trong Rails 3?

Làm cách nào bạn triển khai bảng có cột sử dụng loại được liệt kê trong Rails 3? Bạn có cần định nghĩa enum trong PostgreSQL không? Làm thế nào bạn có thể tạo ra một di chuyển DB mà thực hiện điều này?

Làm việc trong Rails 3.07, Ruby 1.92p180, PostgreSQL 8.3.

+0

exac gì tly ngăn cản bạn thêm enum này trong Postgresql thông qua di chuyển, và sau đó sử dụng nó? – plang

Trả lời

13

Đường ray không hỗ trợ ENUM kiểu dữ liệu ra khỏi hộp. Điều này là do không phải tất cả các cơ sở dữ liệu đều hỗ trợ dữ liệu đó. Tôi thấy rằng một cách phổ biến để xử lý các giá trị ENUM là tạo cột enum theo cách thủ công trong cơ sở dữ liệu của bạn (PostgreSQL trong trường hợp của bạn) và xử lý nó dưới dạng cột string trong ứng dụng Rails của bạn. Sau đó, sử dụng trình xác thực validates_inclusion_of để buộc sử dụng các giá trị được phép.

validates_inclusion_of :gender, :in => [ "male", "female" ] 

Và sử dụng SQL bản địa trong việc di chuyển của bạn để thêm các lĩnh vực enum:

class AddEnumType < ActiveRecord::Migration 
    def up 
    execute ".." # your native PostgreSQL queries to add the ENUM field 
    end 
end 

chỉnh sửa (tháng 6 năm 2014)

Rails 4.1 tại supports enums. Các validates_inclusion_of bây giờ có thể được thay đổi để:

enum gender: [ :male, :female ] 

(Tuy nhiên, điều này vẫn không natively hỗ trợ bởi cơ sở dữ liệu cơ bản, do đó di cư SQL mẹ đẻ vẫn cần thiết.)

+3

Điều này có nghĩa là bạn không bao giờ có thể làm một giản đồ: tải mặc dù, vì nó phá vỡ shema.rb. Đối với mysql, có đá quý rubygem-enum_column3. Dunno sẽ khó sửa đổi điều đó như thế nào để làm việc cho bưu chính .. – yxhuvud

+0

Cảm ơn thông tin đó. Tôi hầu như không bao giờ sử dụng 'ENUM' hoặc 'lược đồ: tải';) – rdvdijk

+0

Bạn không có bất kỳ thử nghiệm nào? Lược đồ sử dụng đó: tải. Enums cơ sở dữ liệu thử nghiệm của bạn sẽ kết thúc như là chuỗi thay thế. – yxhuvud

9

Bạn cũng có thể thiết lập giản đồ để sử dụng SQL thô thay vì tệp .rb. Nếu bạn đang tận dụng các tính năng nâng cao hơn của cơ sở dữ liệu (enums, tìm kiếm toàn văn, trình kích hoạt, chức năng, vv) thay vì chỉ đơn giản sử dụng nó như một kho dữ liệu chung, điều này sẽ làm cho cuộc sống của bạn dễ dàng hơn.

Chỉ cần thiết lập dòng này trong cấu hình của bạn/application.rb

# Use SQL for the schema due to many database specific settings 
config.active_record.schema_format = :sql 

Nó sẽ ra một tập tin structure.sql rằng sẽ giải quyết vấn đề đó cho bạn.

3

Ngoài các câu trả lời ở trên, cho Rails 4 (và có thể 3.2), bạn có thể làm điều này để tránh "không hợp lệ OID" cảnh báo loại:

ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID.alias_type 'my_enum_type', 'text' 

Khi truy vấn, bạn cũng sẽ muốn chuyển đổi chuỗi để loại bạn, ví dụ

scope :my_enum_value_is, ->(value){ 
    where('my_enum_value = ?::my_enum_type', value) 
} 

bạn cũng sẽ muốn vá phân tích cú pháp cột:

class ActiveRecord::ConnectionAdapters::Column 
    private 
    def simplified_type_with_my_enum_type(field_type) 
    if field_type == 'my_enum_type' 
     field_type.to_sym 
    else 
     simplified_type_without_my_enum_type(field_type) 
    end 
    end 
    alias_method_chain :simplified_type, :my_enum_type 
end 
+1

Rất thú vị. Hơn nữa, nó sẽ là tuyệt vời để có một cách để ActiveRecord tự động nối thêm ':: my_enum' vào các hằng số cụ thể. – rewritten

+0

@rewritten Có thể có đường ray tự động chuyển đổi nó, xem loại điểm từ https://github.com/rails/rails/pull/7324 để tham khảo. Nếu bạn muốn gửi PR cho đường ray, tôi sẽ rất vui khi được trợ giúp (cũng sẽ cần hỗ trợ schema.rb để biến nó thành chính). – glebm

+0

Tôi nghĩ rằng đó là dành cho các loại cụ thể, bạn có đề xuất có một số mã để quản lý các loại tùy ý do người dùng xác định hoặc chỉ là enums không? Hãy tiếp tục điều này bằng twitter, chỉ cần theo bạn ... – rewritten

Các vấn đề liên quan