Использование параметра для контроля валидации Rails - PullRequest
2 голосов
/ 21 декабря 2009

У меня есть модель Event с полем finish_time и флажком формы с именем whenever. Когда отмечен whenever, я хочу установить finish_time на nil независимо от его значения в параметрах, когда whenever не проверен, я хочу убедиться, что finish_time является действительной датой, прежде чем сохранить ее в базы данных.


В настоящее время я достигаю этого, используя whenever attr_accessor для события:

params[:event][:finish_time] = nil if whenever = params[:event].delete(:whenever)
@event = Event.new(params[:event])
@event.whenever = whenever

И использование условных проверок для проверки finish_time, если whenever равно false

validates_presence_of :finish_time, :unless => @whenever

Я не доволен дублированием, которое это создает. Единственный способ, которым finish_time может быть nil, - это если whenever равен true, и если вы меняете одно, вам часто приходится менять другое. Если Event обновляется новым finish_time, то whenever также необходимо изменить на false.

В идеале я хотел бы перенести валидацию на мой контроллер. Таким образом, при прямом доступе к модели whenever можно легко указать, установив finish_time в null, но пользователи, публикующие в / events, будут кричать, если они не указали выбор. Однако я не могу найти способ условно добавить или удалить проверки к Event из контроллера или даже если это лучший подход.

Каков наилучший способ удалить это дублирование?

1 Ответ

1 голос
/ 21 декабря 2009

Вместо того, чтобы пытаться решить проблему с помощью проверки, вы можете попытаться решить ее «Рубиновым способом».

В дополнение к валидации вы можете подключиться к мутаторам методов finish_time и whenever.

class Event < ActiveRecord::Base
  # Validate presence
  validates_presence_of :finish_time, :unless => @whenever

  def whenever=(yes)
    write_attribute(:whenever, yes)
    write_attribute(:finish_time, nil) if yes?
  end
  def finish_time=(time)
    write_attribute(:whenever, false)
    write_attribute(:finish_time, time)
  end
end

Тогда вы можете просто попробовать (однако я не уверен, работает ли он):

@event = Event.new(params[:event])

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

И вы также должны понимать, что вы не сможете сделать свой код СУХИМ, если не сделаете свои требования СУХИМЫМИ.

Редактирование # 2: Я думаю, вам следует рассмотреть возможность отказа от finish_time до nil, если whenever установлено в true. Затем вы можете изменить методы доступа так же, как описано выше.

...