ฉันเพิ่งอ่านเพิ่มเติมเกี่ยวกับความแตกต่างระหว่าง:joins
และ:includes
ในราง นี่คือคำอธิบายของสิ่งที่ฉันเข้าใจ (พร้อมตัวอย่าง :))
พิจารณาสถานการณ์นี้:
ผู้ใช้มีความคิดเห็นจำนวนมากและความคิดเห็นเป็นของผู้ใช้
โมเดลผู้ใช้มีคุณสมบัติดังต่อไปนี้: ชื่อ (สตริง), อายุ (จำนวนเต็ม) โมเดลความคิดเห็นมีคุณสมบัติดังต่อไปนี้: เนื้อหา, user_id สำหรับความคิดเห็น user_id สามารถเป็นโมฆะ
เข้าร่วม:
: joins ทำการรวมภายในระหว่างสองตาราง ดังนั้น
Comment.joins(:user)
#=> <ActiveRecord::Relation [#<Comment id: 1, content: "Hi I am Aaditi.This is my first comment!", user_id: 1, created_at: "2014-11-12 18:29:24", updated_at: "2014-11-12 18:29:24">,
#<Comment id: 2, content: "Hi I am Ankita.This is my first comment!", user_id: 2, created_at: "2014-11-12 18:29:29", updated_at: "2014-11-12 18:29:29">,
#<Comment id: 3, content: "Hi I am John.This is my first comment!", user_id: 3, created_at: "2014-11-12 18:30:25", updated_at: "2014-11-12 18:30:25">]>
จะดึงข้อมูลระเบียนทั้งหมดที่ user_id (จากตารางความคิดเห็น) เท่ากับ user.id (ตารางผู้ใช้) ดังนั้นถ้าคุณทำ
Comment.joins(:user).where("comments.user_id is null")
#=> <ActiveRecord::Relation []>
คุณจะได้อาร์เรย์ที่ว่างเปล่าดังที่แสดง
ยิ่งกว่านั้นการรวมไม่โหลดตารางการรวมในหน่วยความจำ ดังนั้นถ้าคุณทำ
comment_1 = Comment.joins(:user).first
comment_1.user.age
#=>←[1m←[36mUser Load (0.0ms)←[0m ←[1mSELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1←[0m [["id", 1]]
#=> 24
อย่างที่คุณเห็นcomment_1.user.age
จะเริ่มการสืบค้นฐานข้อมูลอีกครั้งในพื้นหลังเพื่อรับผลลัพธ์
รวม:
: include ทำการรวมภายนอกด้านซ้ายระหว่างสองตาราง ดังนั้น
Comment.includes(:user)
#=><ActiveRecord::Relation [#<Comment id: 1, content: "Hi I am Aaditi.This is my first comment!", user_id: 1, created_at: "2014-11-12 18:29:24", updated_at: "2014-11-12 18:29:24">,
#<Comment id: 2, content: "Hi I am Ankita.This is my first comment!", user_id: 2, created_at: "2014-11-12 18:29:29", updated_at: "2014-11-12 18:29:29">,
#<Comment id: 3, content: "Hi I am John.This is my first comment!", user_id: 3, created_at: "2014-11-12 18:30:25", updated_at: "2014-11-12 18:30:25">,
#<Comment id: 4, content: "Hi This is an anonymous comment!", user_id: nil, created_at: "2014-11-12 18:31:02", updated_at: "2014-11-12 18:31:02">]>
จะส่งผลให้ตารางที่เข้าร่วมพร้อมระเบียนทั้งหมดจากตารางความคิดเห็น ดังนั้นถ้าคุณทำ
Comment.includes(:user).where("comment.user_id is null")
#=> #<ActiveRecord::Relation [#<Comment id: 4, content: "Hi This is an anonymous comment!", user_id: nil, created_at: "2014-11-12 18:31:02", updated_at: "2014-11-12 18:31:02">]>
มันจะดึงข้อมูลระเบียนที่ comments.user_id เป็นศูนย์ดังที่แสดง
นอกจากนี้ยังมีการโหลดทั้งตารางในหน่วยความจำ ดังนั้นถ้าคุณทำ
comment_1 = Comment.includes(:user).first
comment_1.user.age
#=> 24
ในขณะที่คุณสามารถสังเกตเห็น comment_1.user.age เพียงแค่โหลดผลลัพธ์จากหน่วยความจำโดยไม่ต้องค้นหาคิวรีฐานข้อมูลในพื้นหลัง
includes
(สำหรับทุกคนที่อ่านข้อความนี้)