Rails: dependent =>: destroy VS: dependent =>: delete_all


192

ในคู่มือรางจะมีคำอธิบายเช่นนี้:

วัตถุจะถูกทำลายนอกจากนี้หากพวกเขาเกี่ยวข้อง:dependent => :destroyและถูกลบหากพวกเขาเกี่ยวข้อง:dependent => :delete_all

ถูกต้องเท่ห์ แต่อะไรคือความแตกต่างระหว่างการถูกทำลายและการลบ? ฉันลองทั้งคู่แล้วดูเหมือนจะทำแบบเดียวกัน

คำตอบ:


200

ความแตกต่างอยู่ที่การโทรกลับ

:delete_allทำโดยตรงในใบสมัครของคุณและลบโดย SQL:

DELETE * FROM users where compagny_id = XXXX

ด้วยการ:destroyทำให้ลูกของคุณทุกคนมีความรวดเร็ว ดังนั้นหากคุณไม่สามารถทำลายมันได้หรือหากแต่ละคนมีของตัวเอง:dependentก็สามารถโทรกลับได้


83
การสร้างอินสแตนซ์และการทำลายล้างของวัตถุเด็กแต่ละชิ้นจะช้าถ้าคุณมีลูกจำนวนมาก (และ n ^ 2 หากคุณมีลูกหลานและอื่น ๆ ) delete_all เป็นโซลูชัน "nuke จากวงโคจร" ที่คุณไม่สนใจ / ไม่เคยมีมาก่อน / หลังทำลาย callback บนโมเดล
Ryan Bigg

131

ในการเชื่อมโยงโมเดลของ Rails คุณสามารถระบุ:dependentตัวเลือกซึ่งสามารถใช้หนึ่งในสามรูปแบบต่อไปนี้:

  • :destroy/:destroy_allวัตถุที่เกี่ยวข้องจะถูกทำลายพร้อมกับวัตถุนี้โดยการเรียกdestroyวิธีการของพวกเขา
  • :delete/:delete_allวัตถุที่เกี่ยวข้องทั้งหมดจะถูกทำลายทันทีโดยไม่ต้องเรียก:destroyวิธีการของพวกเขา
  • :nullifyคีย์ต่างประเทศของวัตถุที่เกี่ยวข้องทั้งหมดถูกตั้งค่าเป็นNULLโดยไม่ต้องโทรsaveกลับ

2
ดูapi.rubyonrails.org/classes/ActiveRecord/Associations/… (ค้นหา "nullify") สำหรับ rdocs ที่เชื่อถือได้
mrm

21
ตั้งแต่ Rails 3.0 :restrictก็ยังไปได้ที่จะระบุ หากตั้งค่าเป็น: จำกัด วัตถุนี้จะไม่สามารถลบได้หากมีวัตถุที่เกี่ยวข้อง
RocketR

17
ไม่มี:deleteหรือ:destroy_allตัวเลือกจากรูปลักษณ์ของมัน? ตัวเลือก: ขึ้นอยู่กับคาดว่า: ทำลาย,: delete_all,: ลบล้างหรือ: จำกัด (: ลบ)
Mike Campbell

2
@MikeCampbell :deleteและ:destroy_allไม่มีตัวเลือก อย่างไรก็ตามมีวิธีการเรียนในแบบจำลองที่เรียกdeleteและdestroy_allอาจเป็นเหตุผลของความสับสน
berezovskyi

@MikeCampbell คุณจะหายไปไม่กี่ตัวเลือกเพิ่มเติมโปรดดูที่: ตัวเลือกขึ้นอยู่ต้องเป็นหนึ่งใน [: ทำลาย: delete_all: ลบล้าง: restrict_with_error: restrict_with_exception]
Pravin Mishra

30

ดูทำลายทำลายองค์ประกอบ ที่เกี่ยวข้องที่delete_all สามารถลบข้อมูลจำนวนมากออกจากตารางตัวเองในฐานะDELETE * FROM table where field = 'xyz'

: ขึ้นอยู่กับตัวเลือกที่เป็นไปได้:

ควบคุมสิ่งที่เกิดขึ้นกับวัตถุที่เกี่ยวข้องเมื่อเจ้าของถูกทำลาย โปรดทราบว่าสิ่งเหล่านี้จะถูกนำไปใช้เป็นการเรียกกลับและ Rails จะดำเนินการเรียกกลับตามลำดับ ดังนั้นการเรียกกลับที่คล้ายกันอื่น ๆ อาจส่งผลกระทบต่อ: ลักษณะการทำงานที่ขึ้นอยู่กับและ:dependentลักษณะการทำงานอาจส่งผลต่อการเรียกกลับอื่น ๆ

:destroy ทำให้วัตถุที่เกี่ยวข้องทั้งหมดถูกทำลายเช่นกัน

:delete_all ทำให้วัตถุที่เกี่ยวข้องทั้งหมดถูกลบโดยตรงจากฐานข้อมูล (ดังนั้นการเรียกกลับจะไม่ถูกดำเนินการ)

:nullifyทำให้คีย์ต่างประเทศถูกตั้งค่าเป็น NULL การเรียกกลับจะไม่ดำเนินการ

:restrict_with_exception ทำให้เกิดข้อยกเว้นที่จะเพิ่มขึ้นหากมีระเบียนที่เกี่ยวข้องใด ๆ

:restrict_with_error ทำให้เกิดข้อผิดพลาดที่จะเพิ่มให้กับเจ้าของหากมีวัตถุที่เกี่ยวข้องใด ๆ

หากใช้กับ:throughตัวเลือกการเชื่อมโยงในรูปแบบการรวมจะต้องเป็นของไอเท็มและบันทึกที่ถูกลบคือเรคคอร์ดการเข้าร่วมมากกว่าบันทึกที่เกี่ยวข้อง


3

จริงๆแล้วความแตกต่างที่สำคัญคือการโทรกลับใด ๆ จะไม่ถูกเรียกเมื่อ:delete_allถูกใช้ แต่เมื่อใช้:destroycallbacks stack ( :after_destroy, :after_commit... ) จะถูกไล่ออก

ดังนั้นหากคุณมีtouch:การประกาศไอเอ็นจีในรูปแบบที่ถูกลบไปแล้วมันจะดีกว่าที่จะใช้dependent: :delete_allค่อนข้าง 'พึ่งพา:: ทำลาย'

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.