2014-09-30 3 views
2

Я хочу попытаться получить дату из params в формат даты, и если она не сможет, тогда я бы хотел присвоить ей дату с года сегодня.Ruby string date to_date с try дает недопустимую дату

Это то, что я пробовал.

valid_until = params[:valid_until].try(:to_date) || Date.today.next_year 

Метод try это круто, потому что если :valid_until дата равна нулю она просто возвращает ноль. Тем не менее, я обнаружил, что если у кого-то неверная дата, например «4790224374», она вернет ArgumentError как недопустимую дату. дата :valid_until будет по-прежнему работать против to_date.

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

EDIT:

Вы можете прочитать о Try here.

Вы можете прочитать о to_date here

+0

Вы можете поставить 'rescue' вместо' || 'и, возможно, сбросить' try'? Это было бы довольно аккуратно, но я думаю, что недостатком является то, что все исключения будут пойманы. –

+0

Да, о чем я думал. его немного сложного. это может стать беспорядочным очень быстро, я потратил последнее мало времени, глядя на несколько идей, но все, кажется, добавляют несколько строк. – TheLegend

+1

, когда вы не используете рубиновый ядро, не могли бы вы включить библиотеки, которые вы используете, чтобы помочь тем, кто хотел бы помочь :) –

ответ

2

вы злоупотребляете Object.try. Этот метод предназначен для отказа, если метод не существует на объекте. В этом случае метод существует (поэтому он называется), и этот метод терпит неудачу.

Это не предназначено для замены блока try/rescue. Возможная реализация приведена ниже.

def expiration_date(a_string) 
    Date.parse(a_string) 
rescue 
    Date.today.next_year 
end 

valid_until = expiration_date(params[:valid_until]) 
1

Если это не какой-то код игры в гольф, я бы не попробовать выжать много логики в один лайнер, как это возможно. Кроме того, вы, вероятно, хотите, чтобы ваши контроллеры опирались, насколько это возможно. Почему бы не использовать здравый смысл OO, который говорит вам: «Если я не могу понять логику здесь, возможно, я должен извлечь ее для разделения метода или класса»? F.I.

# app/services/expirer.rb 
class AccountExpirer 
    def self.expiration_date(user_input) 
    return Date.today.next_year unless user_input.present? 
    begin 
     Date.parse(user_input) 
    rescue ArgumentError 
     Date.today.next_year 
    end 
    end 
end 

# some controller 
valid_until = AccountExpirer.expiration_date(params[:valid_until]) 

Но если вам нужно сообщить пользователю, что он ввел неверные данные, я бы не остановился здесь. Вы можете расширить свой класс с помощью ActiveModel::Model (http://api.rubyonrails.org/classes/ActiveModel/Model.html), что позволит вам написать правильную проверку и использовать ее в своих формах (как и в модели AR).

+0

Эрнест, мне любопытно, как вы и мой метод. Есть ли какая-то причина, по которой вы решили поймать ArgumentErrors в вашем спасении и установить ворота против нуля (что создаст TypeError) вместо того, чтобы просто спасти все? –

+0

@JeffPrice Я не стал бы вообще начинать/спасать, если честно. Но вы не указали никакой информации, о том, как вы применяете формат даты или какие-либо другие ожидания, поэтому моя первая мысль заключалась в том, чтобы использовать Date.parse и поймать исключение, которое он выбрасывает (Date.parse на «недействительной» дате будет бросать ArgumenError , а не, fi Дата: InvalidDateError - это потому, что этот метод не является атрибутом avalidator). Моя точка зрения была иной, т. Е. Такая логика не должна оставаться в контроллере. – Ernest

+0

Этот контроллер передает заказы и не имеет модели для выполнения любых проверок на нем. Но вы абсолютно правы. это плохая практика, чтобы захватить данные, проверенные на уровне контроллера, извлечение этого поведения в службу также является хорошей идеей. Спасибо! – TheLegend

Смежные вопросы