2011-11-16 14 views
15

obecnie mam model uczęszczać że będzie mieć kolumnę stanu, a kolumna ta pozycja będzie miał tylko kilka wartości dla niego. STATUS_OPTIONS = {Tak, Nie, maybe}Jak określić i zweryfikować enum w szynach?

1) Nie jestem pewien, w jaki sposób mogę potwierdzić to, zanim użytkownik wstawia uczestniczyć? Zasadniczo enum w java, ale jak można zrobić to w szynach?

+0

mu i odpowiedzi Mike'a są dobre - patrz też http://stackoverflow.com/q/265725/887124, co daje trochę inne odpowiedzi na podobne pytanie. –

+0

Tak, faktycznie używam czegoś bardziej podobnego do rozwiązania, które dostarczył Bob: [gist] (https://gist.github.com/1372650) – mnelson

Odpowiedz

26

Tworzenie dostępny globalnie wachlarz opcji, które chcesz, a następnie zatwierdzanie wartość kolumnie stan:

class Attend < ActiveRecord::Base 

    STATUS_OPTIONS = %w(yes no maybe) 

    validates :status, :inclusion => {:in => STATUS_OPTIONS} 

end 

następnie można przejść do możliwych stanów poprzez Attend::STATUS_OPTIONS

+5

Pre Rails 4.1 jest w porządku. W Railsach 4.1+ używaj wbudowanych enum: http://edgeguides.rubyonrails.org/4_1_release_notes.html#active-record-enums – mnelson

+1

Używanie "rodzimych" enums in rails 4.1 ma te same wady, co używanie naprawdę natywnych enums w postgresql. Musisz zająć się prawdziwym porządkiem, nie możesz łatwo modyfikować wyliczenia po utworzeniu itd. Co więcej, z "rodzimymi" wyliczeniami szyn, jest to zepsuta funkcja, ponieważ po jednej stronie piszesz i czytasz je jako żądła, ale na po drugiej stronie trzeba je przesłać jako liczby. Przynajmniej z wyliczeniem postgresql, wszystko z bazy danych będzie widziało łańcuchy. – rewritten

+0

Po ponadgodzinnej próbie uzyskania pracy enum, to rozwiązanie jest o wiele bardziej interesujące i nie ma wad - nie można powiedzieć tego samego dla Enum. –

4

Można użyć kolumny ciąg dla stanu i wtedy :inclusion option for validates, aby upewnić się dostać tylko co czekasz:

class Attend < ActiveRecord::Base 
    validates :size, :inclusion => { :in => %w{yes no maybe} } 
    #... 
end 
45

teraz, że Rails 4.1 zawiera teksty stałe można wykonać następujące czynności:

class Attend < ActiveRecord::Base 
    enum size: [:yes, :no, :maybe] 
    # also can use the %i() syntax for an array of symbols: 
    # %i(yes no maybe) 
    validates :size, inclusion: { in: sizes.keys } 
end 

które następnie udostępnia zakresu (tj: Attend.yes, Attend.no, Attend.maybe dla siebie metodę sprawdzania, aby zobaczyć czy pewne status jest ustawiony (tj: #yes?, #no?, #maybe?), wraz ze sposobami ustawiających atrybutu (tj #yes!, #no!, #maybe!).

Rails Docs on enums

+4

Z tego, co czytam, bieżące implementacje wyliczeń są dla wartości wewnętrznych, a nie dla wystawiania użytkownikom na zadane pytanie (co, jak sądzę, jest wstydem). Otrzymuję to z następującego wątku od 14 lutego. Https://github.com/rails/rails/13011 –

+2

Uwielbiam to. Nowa najlepsza praktyka, imo. –

2

Co zaczęliśmy robić definiuje nasze przedmioty enum w tablicy, a następnie za pomocą tej tablicy do określenia wyliczenia, walidacje, a przy użyciu wartości w aplikacji.

STATUS_OPTIONS = [:yes, :no, :maybe] 
enum status_option: STATUS_OPTIONS 
validates :status_option, inclusion: { in: STATUS_OPTIONS.map {|t| t.to_s } } 

W ten sposób można również użyć STATUS_OPTIONS później, na przykład do tworzenia rozwijanych list. Jeśli chcesz, aby odsłonić swoje wartości dla użytkownika zawsze można map tak:

STATUS_OPTIONS.map {|s| s.to_s.titleize } 
8

ten sposób zaimplementować w moich Rails 4 projektu.

class Attend < ActiveRecord::Base 
    enum size: [:yes, :no, :maybe] 
    validates :size, inclusion: { in: Attend.sizes.keys } 
end 

Attend.sizes daje mapowanie.

Attend.sizes # {"yes" => 0, "no" => 1, "maybe" => 2} 

See more in Rails doc

+6

Zasadniczo ten sam komentarz, co [ten] (http://stackoverflow.com/questions/8146965/how-do-i-specify-and-validate-an-enum-in-rails/8147002#comment42094863_26365696), ale to nie będzie działać, ponieważ atrybuty enum będą wywoływać wyjątek InvalidArgument na niepoprawnych wartościach przed wywołaniem sprawdzania poprawności. Więcej na ten temat tutaj: https://github.com/rails/rails/issues/13971 –

+0

@Koen. ma rację Próbowałem tego rozwiązania i kończyło się na 'ArgumentError' niezależnie. –

0

Po niektóre spojrzenie, nie mogłem znaleźć jedno-liner w modelu, aby pomóc się zdarzyć. Do tej pory, Szyny zapewnia wyliczenia, ale nie sposób kompleksowy do sprawdzania nieprawidłowych wartości.

Tak więc zdecydowałem się na rozwiązanie złożone: Aby dodać sprawdzanie poprawności w kontrolerze, przed ustawieniem strong_params, a następnie poprzez sprawdzenie względem modelu.

Tak, w modelu, to stworzy atrybut i walidacji niestandardowe:

uczestniczyć.rb

enum :status => { your set of values } 
attr_accessor :invalid_status 

validate :valid_status 
#... 
private 
    def valid_status 
     if self.invalid_status == true 
      errors.add(:status, "is not valid") 
     end 
    end 

Również zrobię test przed parametrów nieprawidłowej wejścia i wysłać wynik (jeśli to konieczne) do modelu, więc błąd zostanie dodana do obiektu, dzięki czemu jest nieważny

attends_controller.rb

private 
    def attend_params 
     #modify strong_params to include the additional check 
     if params[:attend][:status].in?(Attend.statuses.keys << nil) # to also allow nil input 
      # Leave this as it was before the check 
      params.require(:attend).permit(....) 
     else 
      params[:attend][:invalid_status] = true 
      # remove the 'status' attribute to avoid the exception and 
      # inject the attribute to the params to force invalid instance 
      params.require(:attend).permit(...., :invalid_status) 
     end 
    end