Скажем, у меня есть настраиваемый установщик в модели Activemodel DateRange, который автоматически устанавливает атрибут DateTime при вводе строки. Это похоже на это

  def from=(value)
    @from = value.to_date
  end

Теперь это работает, если вы вводите допустимую строку даты, но если вы вводите недопустимую дату, это останавливает мою заявку. Как я могу отменить назначение, чтобы приложение продолжило работу, а DateRange не прошел проверку позже в моем контроллере?

3
Marco Prins 4 Мар 2014 в 15:52
1
Какая у вас ошибка?
 – 
jordelver
4 Мар 2014 в 15:54
Если я ввожу недопустимую дату, но в правильном формате, например, «13/13/2010», я получаю ArgumentError (недопустимая дата), но если я ввожу вредоносную строку, например, «не дата», я получаю NoMethodError
 – 
Marco Prins
4 Мар 2014 в 16:03

3 ответа

Лучший ответ
def from=(value)
  begin
    @from = value.to_date
  rescue ArgumentError, NoMethodError
    errors.add(:from, "is not a valid date")
  end
end

Возможно, лучший способ сделать это, но это должно сработать

3
j-dexx 4 Мар 2014 в 16:14
1
Проблема в том, что это не препятствует сохранению атрибута (с атрибутом from, как это было раньше). Я обнаружил, что для этого вам нужно инкапсулировать эту логику внутри валидатора: stackoverflow.com/a/9676246/1755300
 – 
unmultimedio
29 Ноя 2016 в 23:50
2
Это решение НЕ является правильным. Вызов valid? полностью проигнорирует добавленную ошибку, и модель может быть создана/обновлена.
 – 
Itay Grudev
31 Май 2017 в 13:32
1
Это не сработает, потому что valid? будет очистить errors перед выполнением фактических обратных вызовов проверки
 – 
Kirill
19 Авг 2020 в 15:57

Обычно вы хотите спасти / решить любую проблему в вашем сеттере.

def from=(value)
  @from = Date.parse(value)
rescue ArgumentError
  nil
end

Затем позвольте вашим обычным проверкам даты обрабатывать значение nil позже.

Я бы не стал добавлять ваши ошибки в сеттер, так как ему не нужно знать о ваших проверках и наоборот.

2
jordelver 4 Мар 2014 в 16:49
Не будет ли это сбивать с толку пользователя, поскольку он скажет, что он не может быть пустым (при условии проверки присутствия), даже если он что-то вводит?
 – 
j-dexx
4 Мар 2014 в 17:20

Как говорит @jordelver, нет смысла добавлять ошибки проверки, кроме как во время проверки. Однако вы можете сохранить ошибку в виртуальном атрибуте и проверить ее во время проверки.

validate :no_bad_dates
attr_accessor :bad_date_error

def from=(value)
  @from = Date.parse(value)
rescue ArgumentError => ex
  self.bad_date_error = ex
end

def no_bad_dates()
  errors.add(:from, bad_date_error.message) if bad_date_error
end
1
Tom Wilson 19 Фев 2018 в 22:28
Обратите внимание, что bad_date_error не обязательно должен быть общедоступным. Реализовано здесь как attr_accessor для упрощения истории.
 – 
Tom Wilson
20 Фев 2018 в 21:45