В рельсах, как я могу узнать, что вызвало сбой .save (), кроме ошибок проверки?


91

У меня есть модель ActiveRecord, которая возвращается trueиз valid?(и .errors пуста), но возвращается falseиз save(). Если экземпляр модели действителен, как я могу узнать, что вызывает сбой при сохранении?


7
У меня была эта проблема пару недель назад. В результате некоторого рефакторинга функция before_save все время возвращала false, что приводило к сбою сохранения.
Джефф Пакетт

1
@Jeff - спасибо, оказывается, был метод: before_save, возвращающий false. Как вы узнали? Это была просто проверка кода?
kdt

Это была проверка кода и сравнение с контролем версий.
Джефф Пакетт

Ответы:


49

Проверьте все ваши обратные вызовы.

У меня была такая проблема, когда у меня был метод after_validate, который не работал после того, как я внес кучу изменений в модель. Модель была действительна, но «after_validate» возвращало false, поэтому, если я использовал model.validее, говорило «истина», но затем, если я сохранил, это дало мне ошибки проверки (переданные из обратного вызова after_validate). Это было странно.

Посмотрите на трассировку приложения, и вы сможете увидеть, какая строка кода вызывает исключение.


2
Согласно комментарию Джеффа, проблема оказалась в обратном вызове before_save, возвращающем false.
kdt

3
@kdt - именно в этом и была моя проблема. Я не думал об этом, потому что before_save просто предназначался для установки свойства, но поскольку он устанавливал его на ложное значение, оно неявно возвращалось, и это заставляло сохранение тихо терпеть неудачу. С другой стороны, теперь у меня есть возможность исправить этот код, добавив строку "Hey! That's MY fake leg!" # Believe it or not, this is important. Не то чтобы я так поступил. ;)
Натан Лонг

2
Хороший способ гарантировать истинное возвращаемое значениеtrue.tap { do_something }
Натан Лонг

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


116

Попробуйте использовать версию Bang save!(с восклицательным знаком в конце) и проверьте полученную ошибку.


4
спасти! просто выбрасывает RecordNotSaved (когда я печатаю сообщение об исключении, я просто получаю имя класса исключения). Есть ли где-нибудь, где мне следует поискать более подробную информацию?
kdt

1
Если вы находитесь в режиме разработки Rails, он должен распечатать полное описание ошибки с трассировкой стека. Поищите там подсказки и / или разместите здесь.
Энди Линдеман

1
Я использую консоль, загружаю объект (например, o = Object.find #id), затем выполняю o.save! как говорится в ответе. Он распечатывает, почему не сохраняется.
pduey

1
К вашему сведению, вызов save!может поднять ActiveRecord::RecordInvalid(поскольку он выполняет проверки), или ActiveRecord::RecordNotSavedэто то, что вы хотите спасти.
Деннис

2
+1, потому что это наименее неудовлетворительный ответ на фундаментальный вопрос о том, как диагностировать .saveсбои, не связанные с проверкой. Квалификация «наименее неудовлетворительная» относится к Rails, а не к этому ответу.
Чак Бэтсон

112

Если @user.save(например) возвращается false, просто запустите это, чтобы получить все ошибки:

@user.errors.full_messages

13
Как я уже упоминал в вопросе, .valid? верно - т.е. ошибок проверки нет. Я проверил, что .errors также возвращает пустой список (я обновил вопрос, чтобы указать на это)
kdt

3

Да, я исправил эту проблему, убедившись, что возвращаю true во всех моих обратных вызовах before_ *, после чего он начинает работать :)


-1

Проблема заключалась в том, что я забыл добавить проверку к модели.

class ContactGroup < ActiveRecord::Base
  validates_presence_of :name
end
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.