20

PostgreSQL ha il concetto di enumerated types integrato nel database.Come utilizzare enum in un database Postgres in Rails 3?

Come implementare una tabella con una colonna che utilizza un tipo enumerato in Rails 3? Hai bisogno di definire l'enum in PostgreSQL in qualche modo? Come si può creare una migrazione DB che faccia questo?

Utilizzo in Rails 3.07, Ruby 1.92p180, PostgreSQL 8.3.

+0

Cosa exac ti impedisce di aggiungere questo enum in Postgresql attraverso una migrazione e di usarlo in seguito? – plang

risposta

13

Rails non supporta il tipo di dati ENUM predefinito. Questo perché non tutti i database supportano tale tipo di dati. Ho scoperto che un modo comune di gestire i valori ENUM consiste nel creare manualmente la colonna enum nel database (PostgreSQL nel tuo caso) e gestirla come una colonna string nell'applicazione Rails. Quindi, utilizzare il validatore validates_inclusion_of per forzare l'utilizzo dei valori consentiti.

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

e utilizzare SQL nativo nella migrazione per aggiungere il campo enum:

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

modifica (giugno 2014)

Rails 4.1 ora supports enums. Il validates_inclusion_of può ora essere modificato a:

enum gender: [ :male, :female ] 

(Tuttavia, questo non è ancora nativamente supportato dal database sottostante, quindi la migrazione SQL nativo è ancora necessaria.)

+3

Ciò significa che non puoi mai fare uno schema: carica però, poiché si rompe shema.rb. Per mysql, ci sono la gemma rubygem-enum_column3. Non so quanto sarebbe difficile modificarlo anche per Postgres .. – yxhuvud

+0

Grazie per queste informazioni. Non uso quasi mai 'ENUM' o' schema: load';) – rdvdijk

+0

Non hai test? Quello usa lo schema: carica. Le enumerazioni del database di test finiranno invece come stringhe. – yxhuvud

9

È anche possibile impostare schema da utilizzare SQL raw invece di un file .rb. Se stai sfruttando le funzionalità più avanzate di un database (enumerazione, ricerca full-text, trigger, funzioni, ecc.) Anziché utilizzarlo semplicemente come un archivio dati generico, ciò ti semplificherà la vita.

appena impostato questa linea nel tuo config/application.rb

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

il risultato sarà un file structure.sql che risolverà il problema per voi.

3

Oltre alle risposte di cui sopra, per Rails 4 (e possibilmente 3.2) si può fare questo per evitare di "non valido OID" tipo avvertimenti:

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

Quando l'esecuzione di query, si vuole anche per convertire la stringa al vostro tipo, ad esempio

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

Si potrà anche patchare il parser colonna:

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

Molto interessante. Inoltre, sarebbe fantastico avere un modo per ActiveRecord di aggiungere automaticamente il cast di ':: my_enum' a costanti specifiche. – rewritten

+0

@rewritten È possibile convertire automaticamente i binari, vedere il tipo di punto da https://github.com/rails/rails/pull/7324 come riferimento. Se desideri inviare un PR alle guide sarò lieto di aiutarti (sarà necessario anche il supporto di schema.rb per renderlo un master). – glebm

+0

Penso che sia per tipi specifici, proponi di avere del codice per gestire tipi arbitrari definiti dall'utente o solo enumerazioni? Continuiamo su Twitter, ti ho appena seguito ... – rewritten

Problemi correlati