Rails 5.2.4 で autosave: true な関連が invalid なときに元レコードの valid? の振る舞いが変わっている件
rack の脆弱性対応があり1、それに対応した Rails を使おうとすると 5.2.4.1
を使う必要がある。のでアプデを試みた。5.2.3
-> 5.2.4.1
マイナーバージョンだし、大丈夫やろw と思いながらとりあえずCIを回してみたところテストが落ちた。はい。
原因を気合で確認したところ、この変更によるものであることがわかった。
この変更自体について説明するとこんな感じ。例えば、既存レコードについて何らかの理由で Foo.find(1).valid?
すると false
を返すようなレコードがあるとする。後からバリデーションが追加されたんでも update 文を手でかいたらぶっ壊れたんでもよいけど、とりあえずそういう invalid なレコードがあるとする2。そのときに、それへの autosave: true
な関連をもつモデルについてバリデーションの結果が不正なレコードがロード済みであるかによって結果が変わるという話。ロード済みならつられて invalid 扱いになるし、未ロードの場合は valid 扱いになる。これが 5.2.3
までの挙動。この incosistency がいやなので、変更がなさそうなときはバリデーションかけるのやめようや、という変更が 5.2.4
に bug fix としてはいった。その結果、ロード済でも変更してないと valid になってしまうように振る舞いが変わっている。
元 issue の再現コードをちょっと手直ししたのをここにおいておく。
https://github.com/rails/rails/pull/36671 · GitHub
たしかに 5.2.3
-> 5.2.4
でテスト結果が変わっていることが確認できる。しかし実は他のバージョンも試すと(ログも上記の gist に含まれている) 5.2.3
だけではなく 5.1.7
, 5.0.7.2
, 4.2.11.1
でも落ちていることがわかる。つまり、かなり長い間そうであった挙動がマイナーバージョン変更時に変わったということになる気がしますね。うーん、ちょっと困った。しかも bug fix 扱いなので CHANGELOG にのってないし。
とりあえずはテストのコード変更で対応予定です。
2019-12-20 14:45 追記 && タイトル変えた
さすがに 4.2
からのコードが動かないのツラいっしょっていう話になったので issue 報告してみました。
これは似てるけどたぶん元PRの後追い fix のほうの条件でひっかかってるやつだと思う。
regression というタグはついたけどコード変更したほうがいいのかなー、と迷い中。
2019-12-20 15:18
36671 番の変更の内容をもうちょい詳しく書いてる。
-
再現コードでは
save!(validate: false)
を使っている。↩