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

91

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

kdt
источник
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, прекратил бы сохранение. Может ли кто-нибудь указать мне на документы по этому поводу? Спасибо за указание на это!
Энди
1
@andy guides.rubyonrails.org/…
Эндрю
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_ *, после чего он начинает работать :)

Pencilcheck
источник
-1

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

class ContactGroup < ActiveRecord::Base
  validates_presence_of :name
end
Ян Воган
источник