Misalkan Anda perlu mendapatkan nama pengguna dari lima posting pertama. Anda segera menulis kueri di bawah ini dan nikmati akhir pekan Anda.
posts = Post.limit(5)
posts.each do |post|
puts post.user.name
end
Bagus. Tapi mari kita lihat kuerinya
Post Load (0.5ms) SELECT `posts`.* FROM `posts` LIMIT 5
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
1 query untuk mengambil semua posts dan 1 query untuk mengambil users untuk setiap posting menghasilkan total 6 queries . Lihat solusi di bawah ini yang melakukan hal yang sama, hanya di 2 queries :
posts = Post.includes(:user).limit(5)
posts.each do |post|
puts post.user.name
end
#####
Post Load (0.3ms) SELECT `posts`.* FROM `posts` LIMIT 5
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IN (1, 2)
Ada satu perbedaan kecil. Tambahkan includes(:posts) untuk permintaan Anda, dan masalah terpecahkan. Cepat, bagus, dan mudah.
Tapi jangan hanya menambahkan includes dalam kueri Anda tanpa memahaminya dengan benar. Menggunakan includes dengan joins dapat mengakibatkan penggabungan silang bergantung pada situasinya, dan Anda tidak memerlukannya dalam banyak kasus.
Jika Anda ingin menambahkan ketentuan ke model yang disertakan, Anda harus merujuknya secara eksplisit . Misalnya:
User.includes(:posts).where('posts.name = ?', 'example')
Akan menimbulkan kesalahan, tetapi ini akan berhasil:
User.includes(:posts).where('posts.name = ?', 'example').references(:posts)
Perhatikan bahwa includes bekerja dengan association names sementara references membutuhkan the actual table name .