私は数日間掘り下げていましたが、この動作の変化についての適切な説明が見つかりませんでした。Railsアプリケーションを3.2から5.2にアップグレードしている最中です。これは、Rails3アプリの合格テストのコードです。
ps = Project.includes(:rentals).where('rentals.id IN (?)', [1,2,3,4])
これは、大きな古い左結合SQLクエリを吐き出します。
しかし、Rails 5で同じクエリを実行すると、mysqlエラーが発生します
ActiveRecord::StatementInvalid (Mysql2::Error: Unknown column 'rentals.id' in 'where clause': SELECT `projects`.* FROM `projects` WHERE (rentals.id IN (1,2,3,4)) LIMIT 11 /*application:ConHQ*/)
インクルードについての私の理解は、インクルードされたテーブルがwhere句で参照されていない限り、個別のクエリを実行する必要があるということです。参照されている場合は、左結合を実行する必要があります。しかし、それはここでは起こっていないようです。この場合、eager_loadの使用は機能します。
ps = Project.eager_load(:rentals).where('rentals.id IN (?)', [1,2,3,4])
しかし、私はインクルードが同じことをするべきだと思いました。
私も時々含まれていることに気づいたんeager_loadと同じクエリを実行します
@project = Project.find(174)
@project.rentals.eager_load(:equipment_name).where('equipment_names.id IN (?)', [1,2,3,4])
@project.rentals.includes(:equipment_name).where('equipment_names.id IN (?)', [1,2,3,4])
この場合、eager_loadとインクルードの両方が左結合を実行します。これらの状況でインクルードの動作が異なる理由を説明するドキュメントは見つかりませんでした。インクルードは、実行するクエリをどの程度正確に選択しますか?
includes
ActiveRecordにデータを熱心にロードする必要があることを伝えるだけですが、これは好きなように実現できます。クエリで他のモデルを参照する場合はreferences(:rentals)
、も使用する必要があります。
ActiveRecord APIは非常に強力で用途が広いですが、Rubyとそのライブラリでよくあることですが、何かを実現する方法はたくさんあります。この場合、を使用merge
して別の関係にマージすることもできます。
rentals = Rental.where(id: [1,2,3,4])
projects = Project.joins(:rentals).merge(rentals) # you can additionally add includes, too, if you want to access the rentals
これには、Rental
モデルのテーブル名を気にする必要がないという追加の利点があります。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加