Как мне указать и проверить перечисление в рельсах? - PullRequest
26 голосов
/ 16 ноября 2011

В настоящее время у меня есть модель Attend, в которой будет столбец состояния, и в этом столбце состояния будет только несколько значений. STATUS_OPTIONS = {: да,: нет,: возможно}

1) Я не уверен, как я могу проверить это, прежде чем пользователь вставит Attend? В основном enum в Java, но как я могу сделать это в рельсах?

Ответы [ 7 ]

64 голосов
/ 14 октября 2014

Теперь, когда Rails 4.1 включает в себя перечисления, вы можете делать следующее:

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

, который затем предоставляет вам область (например: Attend.yes, Attend.no, Attend.maybe для каждой проверкиметод, чтобы увидеть, установлен ли определенный статус (например: #yes?, #no?, #maybe?), наряду с методами установки атрибутов (например: #yes!, #no!, #maybe!).

Rails Docs на перечислениях

36 голосов
/ 16 ноября 2011

Создайте глобально доступный массив нужных вам опций, затем проверьте значение вашего столбца состояния:

class Attend < ActiveRecord::Base

  STATUS_OPTIONS = %w(yes no maybe)

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

end

Затем вы можете получить доступ к возможным статусам через Attend::STATUS_OPTIONS

11 голосов
/ 10 января 2015

Вот как я реализую свой проект на Rails 4.

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

Attend.sizes дает вам отображение.

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

Подробнее в Rails doc

5 голосов
/ 16 ноября 2011

Вы можете использовать строковый столбец для статуса, а затем параметр :inclusion для validates, чтобы убедиться, что вы получите только то, что ожидаете:

class Attend < ActiveRecord::Base
    validates :size, :inclusion => { :in => %w{yes no maybe} }
    #...
end
3 голосов
/ 25 ноября 2014

То, что мы начали делать, это определение элементов enum в массиве, а затем использование этого массива для указания перечисления, проверок и использования значений в приложении.

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

Таким образом, вы также можете использовать STATUS_OPTIONS позже, например, для создания раскрывающихся списков. Если вы хотите представить свои значения пользователю, вы всегда можете отобразить это так:

STATUS_OPTIONS.map {|s| s.to_s.titleize }
1 голос
/ 26 ноября 2014

Для перечислений в ActiveModels вы можете использовать этот драгоценный камень Перечислять

0 голосов
/ 02 октября 2017

После некоторых поисков я не смог найти однострочник в модели, чтобы это произошло.К настоящему моменту Rails предоставляет Enums, но не исчерпывающий способ проверки недопустимых значений.

Итак, я выбрал составное решение: добавить проверку в контроллере, перед установкой strong_params, а затемпроверка по модели.

Итак, в модели я создам атрибут и пользовательскую проверку:

Particip.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

Кроме того, я проверю параметры на недопустимый ввод и отправлю результат (при необходимости) в модель, поэтому к объекту будет добавлена ​​ошибка, что сделает его недействительным

Participnds_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
...