คำตอบ:
ลองพิจารณาตัวอย่างพื้นฐาน:
class Post < ActiveRecord::Base
default_scope { where(published: true) }
end
แรงจูงใจในการตั้งค่าเริ่มต้นpublished: trueอาจเป็นเพื่อให้แน่ใจว่าคุณจะต้องถูกเปิดเผยเมื่อต้องการแสดงโพสต์ที่ไม่ได้เผยแพร่ (ส่วนตัว) จนถึงตอนนี้ดีมาก
2.1.1 :001 > Post.all
Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."published" = 't'
นี่เป็นสิ่งที่เราคาดหวังมาก ตอนนี้ให้ลอง:
2.1.1 :004 > Post.new
=> #<Post id: nil, title: nil, published: true, created_at: nil, updated_at: nil>
และที่นั่นเรามีปัญหาใหญ่ประการแรกเกี่ยวกับขอบเขตเริ่มต้น:
=> default_scope จะส่งผลต่อการเริ่มต้นโมเดลของคุณ
ในอินสแตนซ์ที่สร้างขึ้นใหม่ของแบบจำลองดังกล่าวdefault_scopeจะมีการแสดงผล ดังนั้นในขณะที่คุณอาจต้องการให้แน่ใจว่าจะไม่แสดงรายการโพสต์ที่ไม่ได้เผยแพร่โดยบังเอิญตอนนี้คุณกำลังสร้างโพสต์ที่เผยแพร่ตามค่าเริ่มต้น
ลองพิจารณาตัวอย่างที่ละเอียดยิ่งขึ้น:
class Post < ActiveRecord::Base
default_scope { where(published: true) }
belongs_to :user
end
class User < ActiveRecord::Base
has_many :posts
end
ให้ผู้ใช้รายแรกโพสต์:
2.1.1 :001 > User.first.posts
Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."published" = 't' AND "posts"."user_id" = ? [["user_id", 1]]
ดูเหมือนว่าคาดไว้ (อย่าลืมเลื่อนไปทางขวาจนสุดเพื่อดูส่วนที่เกี่ยวกับ user_id)
ตอนนี้เราต้องการรับรายการโพสต์ทั้งหมด - รวมที่ไม่ได้เผยแพร่ - พูดสำหรับมุมมองของผู้ใช้ที่ล็อกอิน คุณจะรู้ว่าคุณต้อง 'เขียนทับ' หรือ 'เลิกทำ' ผลของdefault_scope. หลังจากที่ Google unscopedอย่างรวดเร็วคุณมีแนวโน้มที่จะหาข้อมูลเกี่ยวกับ ดูว่าจะเกิดอะไรขึ้นต่อไป:
2.1.1 :002 > User.first.posts.unscoped
Post Load (0.2ms) SELECT "posts".* FROM "posts"
=> Unscoped จะลบขอบเขตทั้งหมดที่โดยปกติอาจใช้กับการเลือกของคุณรวมถึงการเชื่อมโยง (แต่ไม่ จำกัด เพียง)
มีหลายวิธีในการเขียนทับเอฟเฟกต์ต่างๆของไฟล์default_scope. การได้รับสิทธิ์นั้นซับซ้อนอย่างรวดเร็วและฉันจะเถียงว่าไม่ใช้default_scopeตั้งแต่แรกจะเป็นทางเลือกที่ปลอดภัยกว่า
unscopedแทนที่จะเป็นdefault_scopeปัญหา # 2
default_scope default_scope { order(:name) }
อีกเหตุผลหนึ่งที่จะไม่ใช้default_scopeคือเมื่อคุณลบอินสแตนซ์ของโมเดลที่มีความสัมพันธ์default_scopeแบบ1 ต่อหลายกับโมเดล
พิจารณาตัวอย่าง:
class User < ActiveRecord::Base
has_many :posts, dependent: :destroy
end
class Post < ActiveRecord::Base
default_scope { where(published: true) }
belongs_to :user
end
โทรuser.destroyจะลบข้อความทั้งหมดที่มีแต่มันจะโพสต์ไม่ได้ลบที่มีpublished unpublishedดังนั้นฐานข้อมูลจะโยนการละเมิดคีย์ต่างประเทศเนื่องจากมีบันทึกที่อ้างอิงผู้ใช้ที่คุณต้องการลบ
มักจะแนะนำให้ใช้ default_scope เนื่องจากบางครั้งมีการใช้อย่างไม่ถูกต้องเพื่อ จำกัด ชุดผลลัพธ์ การใช้ default_scope ให้ดีคือการจัดลำดับชุดผลลัพธ์
ฉันจะอยู่ห่างจากการใช้wheredefault_scope และสร้างขอบเขตสำหรับสิ่งนั้น
default_scopeจะมีเพียงขอบเขตเดียวorderก็ตาม พฤติกรรมunscopedนี้ค่อนข้างคาดไม่ถึง
สำหรับฉันก็คือไม่ความคิดที่ดีแต่ต้องใช้ด้วยความระมัดระวัง !. มีบางกรณีที่ฉันต้องการซ่อนบางระเบียนเมื่อตั้งค่าเขตข้อมูล
default_scopeจะต้องตรงกับค่าเริ่มต้น DB (เช่น{ where(hidden_id: nil) })unscopedวิธีการที่จะหลีกเลี่ยงไฟล์default_scopeดังนั้นมันจะขึ้นอยู่กับความต้องการที่แท้จริง
ฉันพบว่าdefault_scopeมีประโยชน์ในการสั่งให้พารามิเตอร์บางตัวอยู่ในascหรือdescเรียงลำดับในทุกสถานการณ์เท่านั้น มิฉะนั้นฉันจะหลีกเลี่ยงมันเช่นโรคระบาด