2009-04-10 13 views
91

यह वास्तव में एक साधारण सवाल की तरह लगता है लेकिन मैंने इसे कहीं भी उत्तर नहीं देखा है।मैं रेल में स्वचालित रूप से has_many रिश्ते को कैसे क्रमबद्ध करूं?

रेल में आप पूछना चाहते हैं तो: यदि आप इसे एक बहुत का संदर्भ और यहां तक ​​कि करने की जरूरत है

@article.comments(:order=>"created_at DESC") 

नाम गुंजाइश काम करता है:

class Article < ActiveRecord::Base 
    has_many :comments 
end 
class Comments < ActiveRecord::Base 
    belongs_to :article 
end 

क्यों आप कुछ इस तरह के साथ टिप्पणी आदेश नहीं दे सकेंगे लोग इस तरह की चीजें करते हैं:

@article.comments.sort { |x,y| x.created_at <=> y.created_at } 

लेकिन कुछ मुझे बताता है कि यह आसान होना चाहिए। मैं क्या खो रहा हूँ?

+0

सावधान रहें, आप एक अप्रत्याशित विधि का उपयोग कर रहे हैं: @ article.comments (पुनः लोड = false) एक कैश-मिस को मजबूर करने के लिए है (एक पुनः लोड करने के लिए मजबूर करने के लिए आबादी)। यदि आप हैश प्रदान करते हैं, तो यह @ article.comments (true) जैसा ही है। .all (: order => '...') का उपयोग करना न भूलें। मेरे पैर को पहले से ही कुछ बार तोड़ दिया। –

उत्तर

143

आप नंगे संग्रह के लिए सॉर्ट क्रम विकल्प के साथ has_many पर ही निर्दिष्ट कर सकते हैं:,

class Article < ActiveRecord::Base 
    has_many :comments, :order => 'created_at DESC' 
end 
class Comment < ActiveRecord::Base 
    belongs_to :article 
end 

या आप एक सरल, गैर डेटाबेस छँटाई की विधि चाहते हैं , sort_by का उपयोग करें:

article.comments.sort_by &:created_at 

संग्रह

article.comments.find(:all, :order => 'created_at DESC') 
article.comments.all(:order => 'created_at DESC') 

आपका लाभ भिन्न हो सकते हैं: ऊपर दिए गए समाधानों प्रदर्शन विशेषताओं पहली जगह में आप कैसे ला रहे हैं डेटा के आधार पर बेतहाशा बदल जाएगा और जो रूबी आप 'आदेश की ActiveRecord वर्धित तरीकों के साथ इस ing अपने ऐप को चलाने के लिए उपयोग कर रहे हैं।

+0

धन्यवाद, "सब" शायद सबसे सरल है। अच्छी चीज़! रेल 4 में –

+48

, ऑर्डर विकल्प हटा दिया गया है। एक lambda '-> {आदेश (बनाया_at:: desc)} 'का प्रयोग करें। देखें: http://stackoverflow.com/questions/18284606/deprecated-warning-for-rails-4-model-with-order –

+0

यह रेल 4 के साथ बहिष्कृत किया गया था, http://stackoverflow.com/questions/18284606/ देखें बहिष्कृत-चेतावनी-के लिए रेल -4-कई-ऑर्डर-ऑर्डर – bjelli

6

आप अपनी ऑब्जेक्ट्स प्राप्त करने और उन्हें सॉर्ट करने के लिए ActiveRecord की खोज विधि का उपयोग कर सकते हैं।

@article.comments.find(:all, :order => "created_at DESC") 

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

+2

या shorthand विधि @ article.comments.all (: order => 'बनाया_at डीईएससी') – erik

7

यदि आप रेल 2.3 का उपयोग कर रहे हैं और इस ऑब्जेक्ट के सभी संग्रहों के लिए एक ही डिफ़ॉल्ट ऑर्डरिंग का उपयोग करना चाहते हैं तो आप अपने संग्रह को ऑर्डर करने के लिए डिफ़ॉल्ट_स्कोप का उपयोग कर सकते हैं।

class Student < ActiveRecord::Base 
    belongs_to :class 

    default_scope :order => 'name' 

end 

तो अगर आप

@students = @class.students 

फोन वे अपने default_scope के अनुसार आदेश दिया की जाएगी। एक सामान्य सामान्य क्रम में टीबीएच डिफ़ॉल्ट स्कॉप्स का एकमात्र वास्तव में अच्छा उपयोग है।

+0

रेल 4 के रूप में यह अनुपालन नहीं है। सही रेल 4 वाक्यविन्यास के लिए यह समाधान देखें: http://stackoverflow.com/questions/18506038/rails-4-default-scope –

31

रेल 4 के रूप में, आप क्या करना होगा:

class Article < ActiveRecord::Base 
    has_many :comments, -> { order(created_at: :desc) } 
end 
class Comment < ActiveRecord::Base 
    belongs_to :article 
end 

एक has_many :through संबंध तर्क क्रम मामलों (यह दूसरा हो गया है) के लिए:

class Article 
    has_many :comments, -> { order('postables.sort' :desc) }, 
      :through => :postable 
end 

आपको हमेशा पहुंच चाहते हैं तो एक ही क्रम में टिप्पणियां इससे कोई फर्क नहीं पड़ता कि आप default_scope के माध्यम से Comment के माध्यम से ऐसा भी कर सकते हैं:

हालांकि यह reasons discussed in this question के लिए समस्याग्रस्त हो सकता है।

रेल 4 इससे पहले कि आप की तरह के रिश्ते पर एक कुंजी के रूप order निर्दिष्ट कर सकते हैं,:

class Article < ActiveRecord::Base 
    has_many :comments, :order => 'created_at DESC' 
end 

जिम उल्लेख किया है आप भी sort_by उपयोग कर सकते हैं आप प्राप्त किए गए परिणाम के बाद हालांकि आकार के किसी भी परिणाम सेट में इस किया जाएगा SQL/ActiveRecord के माध्यम से अपना ऑर्डर करने से काफी धीमी (और बहुत अधिक मेमोरी का उपयोग करें)।

आप कुछ कर रहे हैं, जहां एक डिफ़ॉल्ट आदेश जोड़ने किसी कारण से बोझिल है या आप कुछ मामलों में अपने डिफ़ॉल्ट ओवरराइड करना चाहते हैं, यह प्राप्त कर रहा है कार्रवाई अपने आप में यह निर्दिष्ट करने के लिए मामूली बात है:

sorted = article.comments.order('created_at').all 
+0

मैं इसे fetching कार्रवाई में कहां निर्दिष्ट कर सकता हूं? क्या मैं मॉडल में एक विधि को ओवरराइड करता हूं? – Wit

+0

@Wit - आप विधि उदाहरण में '.order()' जोड़ सकते हैं, जैसे अंतिम उदाहरण में। क्या आप यही पूछ रहे हैं? –

+0

मुझे खेद है। मुझे याद नहीं है कि मैं क्या हासिल करने की कोशिश कर रहा था। – Wit

0

और यदि आप dependent: :destroy या जो कुछ भी की तरह कुछ अतिरिक्त तर्क पारित करने के लिए की जरूरत है, आप लोगों को एक लैम्ब्डा के बाद, इस तरह संलग्न करना होगा:

class Article < ActiveRecord::Base 
    has_many :comments, -> { order(created_at: :desc) }, dependent: :destroy 
end 
संबंधित मुद्दे