ฉันพยายามทำความเข้าใจว่าอะไรhas_many :through
คืออะไรและจะใช้เมื่อใด (และอย่างไร) อย่างไรก็ตามฉันไม่เข้าใจ ฉันกำลังอ่าน Beginning Rails 3 และพยายามใช้ Googling แต่ฉันไม่เข้าใจ
ฉันพยายามทำความเข้าใจว่าอะไรhas_many :through
คืออะไรและจะใช้เมื่อใด (และอย่างไร) อย่างไรก็ตามฉันไม่เข้าใจ ฉันกำลังอ่าน Beginning Rails 3 และพยายามใช้ Googling แต่ฉันไม่เข้าใจ
คำตอบ:
สมมติว่าคุณมีสองรุ่น: User
และGroup
.
หากคุณต้องการให้ผู้ใช้อยู่ในกลุ่มคุณสามารถดำเนินการดังนี้:
class Group < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
belongs_to :group
end
จะเป็นอย่างไรหากคุณต้องการติดตามข้อมูลเมตาเพิ่มเติมเกี่ยวกับการเชื่อมโยง ตัวอย่างเช่นเมื่อผู้ใช้เข้าร่วมกลุ่มหรือบางทีบทบาทของผู้ใช้ในกลุ่มคืออะไร
นี่คือที่ที่คุณสร้างการเชื่อมโยงเป็นวัตถุชั้นหนึ่ง:
class GroupMembership < ActiveRecord::Base
belongs_to :user
belongs_to :group
# has attributes for date_joined and role
end
ซึ่งจะแนะนำตารางใหม่และลบgroup_id
คอลัมน์ออกจากตารางของผู้ใช้
ปัญหาเกี่ยวกับรหัสนี้คือคุณต้องอัปเดตทุกที่ที่คุณใช้คลาสผู้ใช้และเปลี่ยน:
user.groups.first.name
# becomes
user.group_memberships.first.group.name
รหัสประเภทนี้แย่มากและทำให้เกิดการเปลี่ยนแปลงเช่นนี้อย่างเจ็บปวด
has_many :through
ให้สิ่งที่ดีที่สุดแก่คุณทั้งสองโลก:
class User < ActiveRecord::Base
has_many :groups, :through => :group_memberships # Edit :needs to be plural same as the has_many relationship
has_many :group_memberships
end
ตอนนี้คุณสามารถปฏิบัติได้เหมือนปกติhas_many
แต่ได้รับประโยชน์จากรูปแบบการเชื่อมโยงเมื่อคุณต้องการ
โปรดทราบว่าคุณสามารถทำได้ด้วยhas_one
ไฟล์.
แก้ไข: ทำให้ง่ายต่อการเพิ่มผู้ใช้ในกลุ่ม
def add_group(group, role = "member")
self.group_associations.build(:group => group, :role => role)
end
user.groups << group
หรือไม่? หรือทุกอย่างจัดการโดยสมาคมนี้?
สมมติว่าคุณมีโมเดลเหล่านี้:
Car
Engine
Piston
รถhas_one :engine
เครื่องยนต์belongs_to :car
เครื่องยนต์has_many :pistons
ลูกสูบbelongs_to :engine
has_many :pistons, through: :engine
ลูกสูบรถยนต์has_one :car, through: :engine
โดยพื้นฐานแล้วคุณกำลังมอบหมายความสัมพันธ์ของโมเดลให้กับโมเดลอื่นดังนั้นแทนที่จะต้องโทรcar.engine.pistons
คุณก็ทำได้car.pistons
has_many :through
และ has_and_belongs_to_many
ฟังก์ชันความสัมพันธ์ผ่านตารางเข้าร่วมซึ่งเป็นตารางกลางที่แสดงถึงความสัมพันธ์ระหว่างตารางอื่น ๆ ซึ่งแตกต่างจากแบบสอบถาม JOIN ข้อมูลจะถูกเก็บไว้ในตาราง
กับ has_and_belongs_to_many
คุณไม่จำเป็นต้องมีคีย์หลักและคุณเข้าถึงเรกคอร์ดผ่านความสัมพันธ์ของ ActiveRecord แทนที่จะใช้แบบจำลอง ActiveRecord โดยปกติคุณจะใช้ HABTM เมื่อคุณต้องการเชื่อมโยงสองโมเดลด้วยความสัมพันธ์แบบกลุ่มต่อกลุ่ม
คุณใช้ไฟล์ has_many :through
ความสัมพันธ์เมื่อคุณต้องการโต้ตอบกับตารางการเข้าร่วมเป็นโมเดล Rails พร้อมด้วยคีย์หลักและความสามารถในการเพิ่มคอลัมน์ที่กำหนดเองลงในข้อมูลที่รวมเข้าด้วยกัน ข้อมูลหลังนี้มีความสำคัญอย่างยิ่งสำหรับข้อมูลที่เกี่ยวข้องกับแถวที่รวมเข้าด้วยกัน แต่ไม่ได้เป็นของโมเดลที่เกี่ยวข้องจริงๆตัวอย่างเช่นการจัดเก็บค่าที่คำนวณได้จากฟิลด์ในแถวที่รวม
ในคู่มือการเชื่อมโยง Active Recordคำแนะนำจะอ่าน:
หลักการง่ายๆที่สุดคือคุณควรตั้งค่า has_many: ผ่านความสัมพันธ์หากคุณต้องการทำงานกับรูปแบบความสัมพันธ์เป็นเอนทิตีอิสระ หากคุณไม่จำเป็นต้องทำอะไรกับรูปแบบความสัมพันธ์การตั้งค่าความสัมพันธ์ has_and_belongs_to_many อาจจะง่ายกว่า (แม้ว่าคุณจะต้องจำไว้ว่าต้องสร้างตารางการเข้าร่วมในฐานข้อมูล)
คุณควรใช้ has_many: ถึงแม้ว่าคุณต้องการการตรวจสอบความถูกต้องการเรียกกลับหรือแอตทริบิวต์เพิ่มเติมในโมเดลการเข้าร่วม
user
โมเดลเพื่อเพิ่มกลุ่ม บางอย่างเช่นการแก้ไขที่ฉันเพิ่งทำ หวังว่านี่จะช่วยได้