#ruby-on-rails #ruby
Вопрос:
В настоящее время моя модель имеет эти два соответствующих атрибута: first_id
, second_id
Я пытаюсь проверить это при обновлении, если first_id
оно изменилось, затем установите значение second_id
nil
, независимо от того , какое значение second_id
имеет значение.
Поэтому в настоящее время моя реализация в моей модели выглядит примерно так:
validates_presence_of :first_id
before_action :check_if_first_id_changes, only: [:update]
def check_if_first_id_changes
if self.first_id != first_id
# What do I insert here?
end
end
Могу ли я как-нибудь сделать это в модели? Заранее спасибо!
Ответ №1:
before_action
это метод контроллера. Вы, вероятно, захотите использовать before_validation
или before_save
.
Следующее должно соответствовать вашим требованиям:
before_validation :update_second_id_when_first_id_changed, on: [:update]
private
def update_second_id_when_first_id_changed
return unless first_id_changed?
self.second_id = nil
end
Комментарии:
1. Хм, в моем случае пользователь может обновить как first_id, так и second_id, но мне просто нужно убедиться, что если first_id изменится, все, что впоследствии будет сохранено в базе данных-second_id должно быть равно нулю. Почему вы используете self.second_id? Не будет ли он обновляться впоследствии, так как я мог бы обновлять с измененным first_id и ненулевым second_id. Спасибо!
2. Я не уверен, что правильно понял ваш комментарий. Что делает этот код: Если
first_id
он не изменился, то он немедленно возвращается и ничего не делает (см.DirtyAttributes
О том, какfirst_id_changed?
работает метод). Но еслиfirst_id
изменено, тоsecond_id
установлено значениеnil
. Вам нужноself
здесь, потому что в противном случае вы бы просто установилиsecond_id
локальную переменную, но не переменную экземпляра. Все это происходит до проверки и перед сохранением, что означаетsecond_id = nil
, что на следующем шаге оно будет автоматически сохранено в базе данных.3. Я думаю, что у меня было неправильное представление, которое
self.second_id
относится к исходному значению, в то времяsecond_id
как относится к новому значению, до которого оно будет обновлено, поэтому мне было интересно, почему вы сделалиself.second_id = nil
бы, если бы оно просто было обновленоsecond_id
после завершения этогоbefore_validation
метода. Но да, ваше объяснение делает это ясным для меня!
Ответ №2:
Проверка self.first_id != first_id
никогда не сработает, потому что они оба ссылаются на одно и то же значение. Вы можете использовать помощника first_id_changed?
, чтобы проверить, были ли внесены изменения. В ActiveModel::Dirty
документации приведен список всех помощников, касающихся изменений атрибутов экземпляра модели.
Как уже указывалось, before_action
недопустимо в модели. Вы можете проверить доступные обратные вызовы для моделей здесь. Если нет никаких подтверждений second_id
, я бы лично пошел на before_update
это, что устраняет необходимость в установке on: :update
опции.
Лично мне нравится разделять «действие» и «проверку», чтобы вы могли вызывать действие без блокировки проверки. Затем я бы объединил их в определении обратного вызова. Однако это всего лишь личные предпочтения, и вы можете легко перенести проверку в обратный вызов, если это больше соответствует вашим потребностям.
before_update :clear_second_id, if: :first_id_changed?
private
def clear_second_id
self.second_id = nil
end