คำเตือนที่เลิกใช้งานสำหรับ Rails 4 has_many พร้อมคำสั่งซื้อ


105
class RelatedList < ActiveRecord::Base
  extend Enumerize

  enumerize :list_type, in: %w(groups projects)

  belongs_to :content
  has_many :contents, :order => :position

end

ฉันมีโมเดลนี้ในแอพทางรถไฟซึ่งจะเตือนเมื่อฉันพยายามสร้างเรกคอร์ดในคอนโซล

คำเตือนการเลิกใช้งาน: อ็อพชันต่อไปนี้ใน RelatedList.has_many ของคุณ: การประกาศเนื้อหาไม่ได้รับการสนับสนุน:: order โปรดใช้การบล็อกขอบเขตแทน ตัวอย่างเช่นมีสิ่งต่อไปนี้: has_many: spam_comments, เงื่อนไข: {spam: true}, class_name: 'Comment' ควรเขียนใหม่ดังนี้ has_many: spam_comments, -> {where spam: true}, class_name: 'Comment' (เรียกจากที่ /Users/shivam/Code/auroville/avorg/app/models/related_list.rb:7)

ดูเหมือนว่า Rails 4 จะมีไวยากรณ์คำสั่งใหม่สำหรับใช้ในโมเดล แต่ฉันไม่พบเอกสารประกอบใน Rails Guides

คำตอบ:


250

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

ลองดูสิ:

has_many :contents, -> { order(:position) }

หากต้องการระบุทิศทางการสั่งซื้อเช่นascหรือdescตามที่ @ joshua-coady และ @wsprujit แนะนำให้ใช้:

has_many :contents, -> { order 'position desc' }

หรือใช้รูปแบบแฮช:

has_many :contents, -> { order(position: :desc) }

อ้างอิงเพิ่มเติมเกี่ยวกับขอบเขตการใช้งานบันทึกสำหรับhas_many


3
ใช้งานได้ยอดเยี่ยม! ฉันจะหาข้อมูลดังกล่าวในคู่มือหรือเอกสารได้ที่ไหน หาไม่เจอ ขอบคุณ.
shankardevy


4
ถ้าคุณมีตัวเลือกที่เลิกใช้งานมากกว่าหนึ่งตัวเลือกพูดoderและinclude? สิ่งนี้: แสดง{ order(:position), include(:track) }ข้อผิดพลาดในเครื่องหมายจุลภาค
kakubei

2
สำหรับการสั่ง asc / desc ให้ใช้-> { order(name: :asc) }
wspruijt

1
หากด้วยเหตุผลบางประการคุณเพียงแค่ต้องการให้มีการสั่งซื้อคอลเล็กชันในบางครั้งคุณสามารถทำได้list.contents.order('position desc')ซึ่งจะมีประสิทธิภาพโดยรวมมากกว่าและไม่ใช่เป็นการล่วงล้ำแบบจำลอง (ในคำตอบที่ได้รับการโหวตรายการจะรู้เนื้อหาในส่วนนี้ผู้ควบคุมจะรู้ )
Dirty Henry

35

ฉันใช้เวลาสักพักในการหาวิธีสั่งซื้อและรวมในที่สุดฉันก็พบว่าคุณเชื่อมโยงคำสั่งขอบเขต

has_many :things, -> { includes(:stuff).order("somedate desc") }, class_name: "SomeThing"

2
นี่คือปัญหาของฉัน พยายามหาวิธีจัดลำดับความสัมพันธ์ has_many โดยแอตทริบิวต์หลัก ไม่ทราบว่าคุณสามารถทำเช่นนี้แล้วสั่งซื้อ ขอบคุณ!
timothyashaw

27

แค่คิดว่าฉันจะเพิ่มว่าหากคุณมีอาร์กิวเมนต์แฮชตัวเลือกใด ๆ พวกเขาต้องทำตามแลมด้าดังนี้:

has_many :things, -> { order :stuff }, dependent: :destroy

ใช้เวลาสักครู่ในการคิดออกด้วยตัวเอง - หวังว่าจะช่วยให้คนอื่น ๆ ที่พบคำถามนี้มีปัญหาเดียวกัน


3
นอกจากนี้ยังเป็นความจริงของการเชื่อมโยง "ผ่าน" ที่อาจมีอยู่ในวัตถุ -has_many :items, -> { order 'name' }, through: :suppliers
Major Major


-4

หรือคุณสามารถใส่orderอนุประโยคในโมเดลตัวอย่างเช่น:

has_many :options, order: 'name' # In class Answer

กลายเป็น

has_many :options # In class Answer

default_scope { order 'name' } # In class Option

PS: ผมได้รับเมื่อทำArgumentError: wrong number of arguments (1 for 0)has_many :things, -> {}


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