อะไรคือความแตกต่างระหว่าง
@model.destroy
และ @model.delete
ตัวอย่างเช่น:
Model.find_by(col: "foo").destroy_all
//and
Model.find_by(col: "foo").delete_all
มันสำคัญจริงๆถ้าฉันใช้อันใดอันหนึ่ง?
อะไรคือความแตกต่างระหว่าง
@model.destroy
และ @model.delete
ตัวอย่างเช่น:
Model.find_by(col: "foo").destroy_all
//and
Model.find_by(col: "foo").delete_all
มันสำคัญจริงๆถ้าฉันใช้อันใดอันหนึ่ง?
คำตอบ:
โดยทั่วไปdestroy
จะเรียกใช้การเรียกกลับใด ๆ ในรูปแบบในขณะที่delete
ไม่
จากRails API :
ActiveRecord::Persistence.delete
ลบเร็กคอร์ดในฐานข้อมูลและตรึงอินสแตนซ์นี้เพื่อสะท้อนว่าไม่ควรทำการเปลี่ยนแปลง (เนื่องจากไม่สามารถคงอยู่ได้) ส่งคืนอินสแตนซ์แช่แข็ง
แถวนั้นจะถูกลบออกโดยใช้คำสั่ง SQL DELETE บนคีย์หลักของเรกคอร์ดและจะไม่มีการดำเนินการเรียกกลับ
ในการบังคับใช้การเรียกกลับ before_destroy และ after_destroy ของวัตถุหรือตัวเลือกการเชื่อมโยงใด ๆ ที่ขึ้นอยู่กับใช้ #destroy
ActiveRecord::Persistence.destroy
ลบเร็กคอร์ดในฐานข้อมูลและตรึงอินสแตนซ์นี้เพื่อสะท้อนว่าไม่ควรทำการเปลี่ยนแปลง (เนื่องจากไม่สามารถคงอยู่ได้)
มีชุดของการโทรกลับที่เกี่ยวข้องกับการทำลาย ถ้า before_destroy callback return false การกระทำถูกยกเลิกและ destroy ส่งกลับ false ดู ActiveRecord :: การเรียกกลับสำหรับรายละเอียดเพิ่มเติม
model#before_destroy
สามารถใช้เพื่อหยุดการdestroy()
โทรสุดท้ายภายใต้เงื่อนไขบางประการ
delete
จะลบระเบียนวัตถุปัจจุบันออกจากฐานข้อมูลเท่านั้น แต่จะไม่ลบระเบียนลูกที่เกี่ยวข้องออกจากฐานข้อมูล
destroy
จะลบเร็กคอร์ดอ็อบเจ็กต์ปัจจุบันออกจาก db และรวมถึงชายด์เร็กคอร์ดที่เชื่อมโยงจาก db
การใช้งานของพวกเขาสำคัญมาก:
หากวัตถุหลักหลาย ๆ อันของคุณใช้วัตถุลูกร่วมกันการเรียกdestroy
ใช้วัตถุแม่เฉพาะจะลบวัตถุลูกที่ใช้ร่วมกันระหว่างผู้ปกครองหลายคน
destroy
เป็นลูกหลานไม่ใช่เด็ก : ตามเอกสารอธิบายทำลาย "สร้างวัตถุใหม่จากแอตทริบิวต์แล้วเรียกใช้ทำลายมัน" rubydoc.info/docs/rails/4.1.7/ActiveRecord%2FRelation:destroy
เมื่อคุณเรียกใช้destroy
หรือdestroy_all
บนActiveRecord
วัตถุActiveRecord
กระบวนการ 'ทำลาย' ถูกเริ่มต้นมันจะวิเคราะห์คลาสที่คุณกำลังลบมันจะกำหนดสิ่งที่ควรทำสำหรับการอ้างอิงการเรียกใช้ผ่านการตรวจสอบความถูกต้อง ฯลฯ
เมื่อคุณเรียกใช้delete
หรือdelete_all
บนวัตถุActiveRecord
เพียงพยายามเรียกใช้DELETE FROM tablename WHERE conditions
แบบสอบถามกับ db โดยไม่ActiveRecord
ต้องทำงานระดับอื่น
ใช่มีความแตกต่างที่สำคัญระหว่างสองวิธีใช้ delete_all ถ้าคุณต้องการลบระเบียนอย่างรวดเร็วโดยไม่ต้องเรียกแบบจำลองการโทรกลับ
หากคุณสนใจการโทรกลับโมเดลของคุณให้ใช้ destroy_all
จากเอกสารอย่างเป็นทางการ
http://apidock.com/rails/ActiveRecord/Base/destroy_all/class
destroy_all (เงื่อนไข = ไม่มี) สาธารณะ
ทำลายเงื่อนไขการจับคู่ระเบียนโดยสร้างอินสแตนซ์แต่ละระเบียนและเรียกใช้วิธีทำลาย การเรียกกลับของวัตถุแต่ละรายการจะดำเนินการ (รวมถึง: ตัวเลือกการเชื่อมโยงที่ต้องพึ่งพาและวิธีการสังเกตการณ์ before_destroy / after_destroy) ส่งคืนชุดของวัตถุที่ถูกทำลาย แต่ละรายการจะถูกแช่แข็งเพื่อสะท้อนว่าไม่ควรทำการเปลี่ยนแปลง (เนื่องจากไม่สามารถยืนยันได้)
หมายเหตุ: การสร้างอินสแตนซ์การเรียกกลับและการลบแต่ละระเบียนอาจใช้เวลานานเมื่อคุณลบหลาย ๆ ระเบียนในคราวเดียว มันสร้างแบบสอบถาม SQL DELETE อย่างน้อยหนึ่งรายการต่อเร็กคอร์ด (หรืออาจมากกว่านั้นเพื่อบังคับใช้การเรียกกลับของคุณ) หากคุณต้องการลบหลายแถวอย่างรวดเร็วโดยไม่ต้องกังวลกับการเชื่อมโยงหรือการโทรกลับให้ใช้ delete_all แทน
โดยทั่วไป "ลบ" ส่งแบบสอบถามโดยตรงไปยังฐานข้อมูลเพื่อลบบันทึก ในกรณีดังกล่าว Rails ไม่ทราบว่ามีแอตทริบิวต์ใดบ้างในบันทึกการลบหรือหากมีการเรียกกลับ (เช่นbefore_destroy
)
วิธีการ "ทำลาย" ใช้รหัสผ่านดึงรูปแบบจากฐานข้อมูลโดยใช้วิธี "ค้นหา" จากนั้นเรียกใช้ทำลายที่ ซึ่งหมายความว่ามีการเรียกใช้การเรียกกลับ
คุณต้องการใช้ "ลบ" หากคุณไม่ต้องการให้มีการเรียกใช้การเรียกกลับหรือคุณต้องการประสิทธิภาพที่ดีขึ้น มิฉะนั้น (และส่วนใหญ่) คุณจะต้องการใช้ "ทำลาย"
มีคำตอบมากมายอยู่แล้ว ต้องการที่จะเพิ่มขึ้นอีกเล็กน้อย
เอกสาร :
สำหรับ has_many ทำลายและ destroy_all มักจะเรียกวิธีทำลายของบันทึก (s) ที่ถูกลบเพื่อให้เรียกใช้การเรียกกลับ อย่างไรก็ตามการลบและ delete_all จะทำการลบอย่างใดอย่างหนึ่งตามกลยุทธ์ที่ระบุโดยตัวเลือก: dependent หรือหากไม่ได้รับ: ขึ้นอยู่กับตัวเลือกแล้วมันจะเป็นไปตามกลยุทธ์เริ่มต้น กลยุทธ์เริ่มต้นคือการไม่ทำอะไรเลย (ปล่อยปุ่มต่างประเทศไว้กับชุดรหัสผู้ปกครอง) ยกเว้น has_many: ถึงโดยที่กลยุทธ์เริ่มต้นคือ delete_all (ลบระเบียนเข้าร่วมโดยไม่เรียกใช้การเรียกกลับ)
delete
verbage ทำงานแตกต่างกันสำหรับการและActiveRecord::Association.has_many
ActiveRecord::Base
สำหรับหลังการลบจะดำเนินการSQL DELETE
และข้ามการตรวจสอบ / เรียกกลับทั้งหมด อดีตจะถูกดำเนินการตาม:dependent
ตัวเลือกที่ส่งผ่านไปยังสมาคม อย่างไรก็ตามในระหว่างการทดสอบฉันพบผลข้างเคียงต่อไปนี้ที่มีการเรียกกลับมาเฉพาะdelete
และไม่delete_all
dependent: :destroy
ตัวอย่าง:
class Parent < ApplicationRecord
has_many :children,
before_remove: -> (_) { puts "before_remove callback" },
dependent: :destroy
end
class Child < ApplicationRecord
belongs_to :parent
before_destroy -> { puts "before_destroy callback" }
end
> child.delete # Ran without callbacks
Child Destroy (99.6ms) DELETE FROM "children" WHERE "children"."id" = $1 [["id", 21]]
> parent.children.delete(other_child) # Ran with callbacks
before_remove callback
before_destroy callback
Child Destroy (0.4ms) DELETE FROM "children" WHERE "children"."id" = $1 [["id", 22]]
> parent.children.delete_all # Ran without callbacks
Child Destroy (1.0ms) DELETE FROM "children" WHERE "children"."parent_id" = $1 [["parent_id", 1]]