ホラ👋
このバグを追跡して再現する方法を見つけるのに少し時間がかかりましたが、ついに私はそれを手に入れました! 私は自分の発見をできる限り説明しようと思います。
5.0.0.1から5.0.1に切り替えた後、テストでActiveRecord::StatementInvalid
例外が発生し、 mininum
を実行すると、 ActiveRecord
が期待どおりにクエリを作成していないようです。 –および拡張子ごとにmaximum
、 average
など–計算。 git bisect
を使用するまで、どちらが問題であるかを理解できず、リグレッションを導入したコミットがhttps://github.com/rails/rails/pull/25976であることを検出しました。
次に、問題を再現して修正しようとしましたが、PRを開いて修正するのに時間がかかりましたが、問題がさらに奇妙になるため、なぜActiveRecord::StatementInvalid
が発生するのか説明できません。 http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html 、具体的にPlacing your callbacks after associations is usually a good practice.
を読んだときに、自分の側で問題を修正できました。
私が見つけたものをあなたに話し、専門家にそれを解決させようとします。 最初にテストケースの例を確認してください。https://gist.github.com/yukideluxe/36b4092748310bc8ec020f5e4dad8ea9
has_many
の関連付けの前に指定されている場合、および関連付けられたレコードを自動保存しようとした場合にのみ発生します。after_touch
コールバックを実行するとエラーが発生しますが、 after_create
も実行されている場合に限ります。 after_create
ではSQLクエリはSELECT MIN(`comments`.`id`) FROM `comments` WHERE `comments`.`post_id` IS NULL
ですが、 before_create
については理解できますが、 after_create
にはすでにpost_id
があります😮bound_attributes
のcomments
アソシエーションのActiveRecord::Associations::CollectionProxy
とそのスコープActiveRecord::AssociationRelation
は空ですが、アソシエーションの場合はforeign_key
が必要であることがわかりました。関係のsqlite
を使用しても発生しません!!! すべてのクエリは期待どおりに見えます。これを修正する方法についての私の最初のアイデアは、これを元に戻すことでしたhttps://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations/collection_proxy.rb#L753-L755そもそもその行を紹介するというアイデアでしたが、これがより深刻な問題であるか、まったく問題ではない場合に備えて、あなたも見てください✌️
私の意見では、コールバックが自動保存コールバックの前に実行され、取得した結果が期待どおりでない場合でも、SQLクエリは有効である必要がありますか? どう思いますか?
このテストケースを実行しますhttps://gist.github.com/yukideluxe/36b4092748310bc8ec020f5e4dad8ea9
ruby test_case.rb
例外なし
ARCONN=mysql2 ruby test_case.rb
例外を発生させます
ActiveRecord::StatementInvalid: Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1: SELECT MIN(`comments`.`id`) FROM `comments` WHERE `comments`.`post_id` =
ARCONN=postgresql ruby test_case.rb
例外を発生させます
ActiveRecord::StatementInvalid: PG::ProtocolViolation: ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1
: SELECT MIN("comments"."id") FROM "comments" WHERE "comments"."post_id" = $1
この問題はマスターブランチでも発生しています。https ://github.com/rails/rails/compare/master ... yukideluxe:callbacks-calculation-bugで確認できます。
長い投稿でごめんなさい、私は何も見逃したくありませんでした! 私は自分自身を説明したいと思います。 ご不明な点がございましたら、お気軽にお問い合わせください。 ❤️
#25877で問題が修正されることを確認しました。
素晴らしい@kamipo! コールバックを「推奨」の位置に配置することでこれを回避できるため、急いでいませんが、PRをマージしておくと便利です。 ありがとう!
#25877が統合されてからのクロージング。
最も参考になるコメント
#25877が統合されてからのクロージング。