20

PostgreSQL ma koncepcję enumerated types wbudowaną w bazę danych.Jak używać enum w bazie danych Postgres w Rails 3?

Jak zaimplementować tabelę z kolumną używającą typu wyliczeniowego w Railsach 3? Czy w jakiś sposób musisz zdefiniować wyliczenie w PostgreSQL? Jak można utworzyć migrację DB, która to robi?

Praca w Railsach 3.07, Ruby 1.92p180, PostgreSQL 8.3.

+0

Co EXAC tly uniemożliwia dodanie tego wyliczenia w PostgreSQL po migracji i później? – plang

Odpowiedz

13

Railsy nie obsługują typu danych ENUM po wyjęciu z pudełka. Dzieje się tak, ponieważ nie wszystkie bazy danych obsługują ten typ danych. Zauważyłem, że powszechnym sposobem radzenia sobie z wartościami ENUM jest ręczne utworzenie kolumny enum w bazie danych (PostgreSQL w twoim przypadku) i radzenie sobie z nią jako kolumna string w twojej aplikacji Rails. Następnie użyj walidatora validates_inclusion_of, aby wymusić użycie dozwolonych wartości.

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

I używać ojczystego języka SQL w migracji, aby dodać pola ENUM:

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

zmienił (czerwiec 2014)

Rails 4.1 teraz supports enums. validates_inclusion_of może być teraz zmieniony na:

enum gender: [ :male, :female ] 

(Jest to jednak nadal nie natywnie wspierany przez podstawowej bazy danych, więc rodzimy migracji SQL jest nadal potrzebna.)

+3

Oznacza to, że nigdy nie możesz zrobić schematu: załaduj, ponieważ zepsuje shema.rb. Dla mysql istnieje gem gem rubem-enum_column3. Nie wiem jak trudno byłoby zmodyfikować to do pracy również dla PostgreSQL. – yxhuvud

+0

Dzięki za te informacje. Rzadko używam 'ENUM's lub' schema: load';) – rdvdijk

+0

Nie masz żadnych testów? Ten schemat użycia: ładuj. Wyliczenia bazy danych testowych będą zamiast tego traktowane jako ciągi. – yxhuvud

9

Można również ustawić schemat używać surowy SQL zamiast pliku .rb. Jeśli korzystasz z bardziej zaawansowanych funkcji bazy danych (wyliczenia, wyszukiwanie pełnotekstowe, wyzwalacze, funkcje itp.), A nie po prostu używasz go jako ogólnego magazynu danych, ułatwi to Ci życie.

Wystarczy ustawić tę linię w config/environment.rb

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

wyświetli się structure.sql plik, który rozwiąże ten problem dla ciebie to.

3

Oprócz powyższych odpowiedzi na szynach 4 (i ewentualnie 3.2) można to zrobić, aby uniknąć „Nieprawidłowy OID” ostrzeżenia Typ:

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

Podczas odpytywania, będzie również chcesz przekonwertować ciąg do typu, na przykład

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

będziesz także chcą załatać parser kolumna:

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

Bardzo interesujące. Co więcej, byłoby wspaniale mieć sposób, aby ActiveRecord automatycznie dodawał rzutowanie ':: my_enum' do konkretnych stałych. – rewritten

+0

@rewritten Możliwe jest, aby szyny były konwertowane automatycznie, patrz punkt typ z https://github.com/rails/rails/pull/7324 dla odniesienia. Jeśli chcesz przesłać PR do torów, chętnie pomogę (będzie również potrzebować wsparcia schema.rb, aby uczynić go mistrzem). – glebm

+0

Myślę, że jest to dla konkretnych typów, czy proponujesz jakiś kod do zarządzania dowolnymi typami zdefiniowanymi przez użytkownika lub po prostu wyliczaniem? Kontynuujmy to przez Twittera, po prostu za Tobą ... – rewritten

Powiązane problemy