20

PostgreSQL具有內置於數據庫中的enumerated types的概念。如何在Rails 3的Postgres數據庫中使用枚舉?

你將如何實現一個列使用Rails 3中的枚舉類型的列表?你需要以某種方式定義PostgreSQL中的枚舉嗎?你怎麼能創建一個這樣做的數據庫遷移?

在Rails 3.07,Ruby 1.92p180,PostgreSQL 8.3中工作。

+0

什麼EXAC tly可以防止你通過遷移在Postgresql中添加這個枚舉,並在之後使用它? – plang

回答

13

Rails不支持開箱即用的ENUM數據類型。這是因爲不是所有的數據庫都支持它的數據類型。我發現處理ENUM值的常見方法是在數據庫中手動創建枚舉列(PostgreSQL),並在您的Rails應用程序中將其作爲string列處理。然後,使用validates_inclusion_of驗證程序強制使用允許的值。

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

而且使用本地SQL的遷移,添加枚舉領域:

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

編輯(2014年6月)

的Rails 4.1現在supports enums。該validates_inclusion_of現在可以改爲:

enum gender: [ :male, :female ] 

(然而,這仍然不是原生底層的數據庫支持,所以仍需要本地SQL遷移。)

+3

這意味着你永遠無法做一個模式:儘管加載,因爲它打破了shema.rb。對於mysql,有rubygem-enum_column3寶石。不知道修改postgres以及修改它有多困難。 – yxhuvud

+0

感謝您的信息。我很少使用'ENUM'或'schema:load';) – rdvdijk

+0

您沒有任何測試?該使用模式:加載。您的測試數據庫枚舉最終將以字符串結尾。 – yxhuvud

9

您還可以設置使用的模式原始SQL而不是.rb文件。如果您利用數據庫的更多高級功能(枚舉,全文搜索,觸發器,函數等)而不是簡單地將其用作通用數據存儲,這將使您的工作更輕鬆。

在你的config/application.rb中

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

只需設置這條線直接輸出,這將解決這一問題爲你structure.sql文件。

3

除了上述的答案,爲Rails 4(也可能是3.2),你可以這樣做是爲了避免「無效OID」式的警告:

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

查詢時,您還需要將字符串轉換你的類型,例如

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

你還需要修補列解析器:

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

非常有趣。此外,讓ActiveRecord自動將':: my_enum'轉換爲特定常量的方式將會非常棒。 – rewritten

+0

@rewritten有可能讓rails自動轉換它,請參閱https://github.com/rails/rails/pull/7324中的點類型以供參考。如果你想提交一個PR到rails,我很樂意提供幫助(還需要schema.rb支持才能成爲主)。 – glebm

+0

我認爲這是針對特定的類型,你是否建議有一些代碼來管理任意的用戶定義類型或只是枚舉?讓我們繼續通過推特,只是跟着你... – rewritten

相關問題