คำตอบ:
ลองพิจารณาตัวอย่างพื้นฐาน:
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 ให้ดีคือการจัดลำดับชุดผลลัพธ์
ฉันจะอยู่ห่างจากการใช้where
default_scope และสร้างขอบเขตสำหรับสิ่งนั้น
default_scope
จะมีเพียงขอบเขตเดียวorder
ก็ตาม พฤติกรรมunscoped
นี้ค่อนข้างคาดไม่ถึง
สำหรับฉันก็คือไม่ความคิดที่ดีแต่ต้องใช้ด้วยความระมัดระวัง !. มีบางกรณีที่ฉันต้องการซ่อนบางระเบียนเมื่อตั้งค่าเขตข้อมูล
default_scope
จะต้องตรงกับค่าเริ่มต้น DB (เช่น{ where(hidden_id: nil) }
)unscoped
วิธีการที่จะหลีกเลี่ยงไฟล์default_scope
ดังนั้นมันจะขึ้นอยู่กับความต้องการที่แท้จริง
ฉันพบว่าdefault_scope
มีประโยชน์ในการสั่งให้พารามิเตอร์บางตัวอยู่ในasc
หรือdesc
เรียงลำดับในทุกสถานการณ์เท่านั้น มิฉะนั้นฉันจะหลีกเลี่ยงมันเช่นโรคระบาด