Как указать и проверить перечисление в рельсах?
В настоящее время у меня есть модель Attend, которая будет иметь столбец статуса, и этот столбец статуса будет иметь только несколько значений. STATUS_OPTIONS = {: yes,: no,: возможно}
1) Я не уверен, как я могу проверить это до того, как пользователь вставляет Attend? В основном перечисление в java, но как я могу это сделать в рельсах?
Ответы
Ответ 1
Создайте глобально доступный массив параметров, которые вы хотите, затем подтвердите значение столбца состояния:
class Attend < ActiveRecord::Base
STATUS_OPTIONS = %w(yes no maybe)
validates :status, :inclusion => {:in => STATUS_OPTIONS}
end
Затем вы можете получить доступ к возможным статусам с помощью Attend::STATUS_OPTIONS
Ответ 2
Теперь, когда 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 для перечислений
Ответ 3
Вот как я реализую в своем проекте 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
Ответ 4
Вы можете использовать строковый столбец для статуса, а затем :inclusion
для validates
, чтобы убедиться, что вы получаете только то, что вы "ожидаем:
class Attend < ActiveRecord::Base
validates :size, :inclusion => { :in => %w{yes no maybe} }
#...
end
Ответ 5
То, что мы начали делать, - это определение наших элементов перечисления в массиве, а затем использование этого массива для указания перечисления, проверки и использования значений в приложении.
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 }
Ответ 6
Для перечислений в ActiveModels вы можете использовать этот драгоценный камень Enumerize
Ответ 7
После некоторого поиска я не смог найти модель с одним слоем, чтобы помочь ей. К настоящему времени Rails предоставляет Enums, но не является исчерпывающим способом проверки недопустимых значений.
Итак, я выбрал составное решение. Чтобы добавить проверку в контроллер, перед установкой strong_params
, а затем, проверив модель.
Итак, в модели я создам атрибут и пользовательскую проверку:
attend.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
Кроме того, я проведу проверку параметров для недопустимого ввода и отправлю результат (если необходимо) в модель, поэтому к объекту будет добавлена ошибка, что делает его недействительным
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
Ответ 8
Для определения динамического поведения вы можете использовать обозначение in: :method_name
:
class Attend < ActiveRecord::Base
enum status: [:yes, :no, :maybe]
validates :status, inclusion: {in: :allowed_statuses}
private
# restricts status to be changed from :no to :yes
def allowed_statuses
min_status = Attend.statuses[status_was]
Attend.statuses.select { |_, v| v >= min_status }.keys
end
end