ओवरराइडिंग रेलिंग default_scope


155

अगर मेरे पास एक ActiveRecord :: एक डिफ़ॉल्ट-गुंजाइश के साथ बेस मॉडल:

class Foo < ActiveRecord::Base

  default_scope :conditions => ["bar = ?",bar]

end

क्या शर्तों का उपयोग Foo.find किए बिना ऐसा करने का कोई तरीका है default_scope? दूसरे शब्दों में, क्या आप एक डिफ़ॉल्ट गुंजाइश को ओवरराइड कर सकते हैं?

मैंने सोचा होगा कि नाम में 'डिफ़ॉल्ट' का उपयोग करने से यह पता चलेगा कि यह अति-योग्य था , अन्यथा इसे कुछ global_scopeसही कहा जाएगा ?


जवाबों:


151

संक्षिप्त उत्तर: default_scopeतब तक उपयोग न करें जब तक आपको वास्तव में नहीं करना है। आप शायद नाम वाले स्कोप से बेहतर होंगे। इसके साथ ही कहा गया है, with_exclusive_scopeअगर आपको जरूरत है तो आप डिफॉल्ट स्कोप को ओवरराइड कर सकते हैं ।

अधिक विवरण के लिए इस प्रश्न पर एक नज़र डालें ।


पिछले प्रश्न के लिंक के लिए धन्यवाद
— Gareth

10
जब तक आपको वास्तव में नहीं करना है तब तक default_scope का उपयोग न करें। एक उत्कृष्ट सलाह! धन्यवाद!
— इंस्टॉल करें

2
सच है। उपयोग करना default_scopeएक अच्छा विचार हो सकता है, लेकिन आपके ऐप के जीवनकाल के दौरान कई सिरदर्द होने की संभावना होगी।
— थोमैक्स


1
आप थोड़े से अतिशयोक्ति कर रहे हैं। default_scopeएक उत्कृष्ट उपकरण है और ऐसी स्थितियाँ हैं जहाँ आप एक और तरीका default_scopeअपना सकते हैं, लेकिन इसका सही तरीका है। उदाहरण के लिए, जब आपके पास एक Productमॉडल होता है जिसमें एक inactiveझंडा होता है, तो सेटिंग default_scope { where inactive: false }करना सबसे अच्छा काम होता है, क्योंकि 99% या मामलों में आप एक निष्क्रिय उत्पाद प्रदर्शित नहीं करना चाहेंगे। फिर आप केवल unscopedशेष 1% मामलों पर कॉल करते हैं, जो संभवतः एक व्यवस्थापक पैनल है।
— पडोजरथ

215

रेल में 3:

foos = Foo.unscoped.where(:baz => baz)

58
इसका एक दुष्प्रभाव है, यदि Post has_many टिप्पणी, Post.first.comments.unscoped सभी टिप्पणियाँ देता है।
— एनरिको कारलेसो

3
यह वास्तव में मुझे थोड़ी देर के लिए खराब कर दिया। खासकर यदि आप इसे एक वर्ग विधि में डालते हैं, जैसे: def self.random; unscoped.order('rand()'); endअनकैप्ड इससे पहले सभी एसक्यूएल को हटा देता है, न कि जो कि default_scope के तहत सूचीबद्ध है। जबकि तकनीकी रूप से एक सही उत्तर है, उपयोग करने में सावधानी बरतेंunstopped
— Schneems

7
चेतावनी! Unscoped केवल default_scope को नहीं निकालता है, यह पहले से ही एक अन्य टिप्पणी में कहा गया था, लेकिन यह वास्तव में चीजों के साथ गड़बड़ कर सकता है।
— dsimard

15
अंगूठे का एक अच्छा नियम केवल unscopedतब होता है जब वह सीधे किसी मॉडल का पालन कर सकता है, जैसे Foo.unscoped.blah()कि ठीक है लेकिन कभी नहीं Foo.blah().unscoped।
— ग्रांट बिर्चमियर

stackoverflow.com/questions/1834159/… एनरिको द्वारा उल्लिखित साइड इफेक्ट के आसपास काम करता है
— wbharding

107

यदि आप सभी की जरूरत है कि में परिभाषित आदेश को बदलने के लिए है default_scope, तो आप reorderविधि का उपयोग कर सकते हैं ।

class Foo < ActiveRecord::Base
  default_scope order('created_at desc')
end

Foo.reorder('created_at asc')

निम्न SQL चलाता है:

SELECT * FROM "foos" ORDER BY created_at asc

3
युक्ति: जैसे एक दायरा निर्धारित करें scope :without_default_order, -> { reorder("") }और आप ऐसा कर सकते हैं जैसे Foo.without_default_order.order("created_at ASC")कुछ स्थितियों में यह बेहतर तरीके से पढ़ता है (शायद यह सटीक स्थिति नहीं है, लेकिन मेरे पास एक था)।
— हेनरिक एन

सीमा ने मेरे लिए किया। आपका बहुत बहुत धन्यवाद!
— आंद्रे जिम्पेल

49

चूंकि 4.1आप ActiveRecord::QueryMethods#unscopeडिफ़ॉल्ट दायरे से लड़ने के लिए उपयोग कर सकते हैं :

class User < ActiveRecord::Base
  default_scope { where tester: false }
  scope :testers, -> { unscope(:where).where tester: true }
  scope :with_testers, -> { unscope(:where).where tester: [true, false] }
  # ...
end

यह वर्तमान में unscopeसामान की तरह संभव है :where, :select, :group, :order, :lock, :limit, :offset, :joins, :includes, :from, :readonly, :having:।

लेकिन फिर भी अगर आप कर सकते हैं तो इसके इस्तेमाल से बचेंdefault_scope । यह आपके भले के लिए है।


यह उत्तर अधिक होना चाहिए
— स्टीफन कोर्विन

14

आप with_exclusive_scopeविधि का उपयोग करके एक डिफ़ॉल्ट गुंजाइश को ओवरराइड कर सकते हैं । इसलिए:

foos = Foo.with_exclusive_scope { :conditions => ["baz = ?", baz] }

3
यह सच नहीं है, यह सिर्फ स्थानांतरित किया गया है: apidock.com/rails/ActiveRecord/Scoping/ClassMethods/…
— केविन

5

रेल 3 डिफॉल्ट_कैप ओवरराइड होने के लिए प्रकट नहीं होता है जैसे कि रेल 2 में किया था।

जैसे

class Foo < ActiveRecord::Base
  belongs_to :bar
  default_scope :order=>"created_at desc"
end

class Bar < ActiveRecord::Base
  has_many :foos
end

> Bar.foos
  SELECT * from Foo where bar_id = 2 order by "created_at desc";
> Bar.unscoped.foos
  SELECT * from Foo;  (WRONG!  removes the "has" relationship)
> Bar.foos( :order=>"created_at asc" )  # trying to override ordering
  SELECT * from Foo where bar_id = 2 order by "created_at desc, created_at asc"

मेरे ऐप में, PostgreSQL का उपयोग करते हुए, डिफ़ॉल्ट स्कोप WINS में ऑर्डरिंग। मैं अपने सभी default_scopes हटा रहा हूं और इसे स्पष्ट रूप से हर जगह कोड कर रहा हूं।

ख़तरा रेल 3!


1
आप का उपयोग करने केBar.foos.reorder(:created_at => :asc)
— इवान Stana

5

रेल 3+ के साथ आप अनकैप्ड और मर्ज के संयोजन का उपयोग कर सकते हैं:

# model User has a default scope
query = User.where(email: "foo@example.com")

# get rid of default scope and then merge the conditions
query = query.unscoped.merge(query)

इसने मेरे लिए भी काम किया, जिसे पहले अनकैप्ड (रेल 4.2) कहा जाता था:User.unscoped.where(email: "foo@example.com")
— निक

3

रेल पर 5.1+ (और शायद पहले भी, लेकिन मैंने इसे 5.1 पर काम किया है।) यह एक विशिष्ट कॉलम को अनकैप करने के लिए संभव है, जो default_scopeएक फैशन में एक हटाने के लिए आदर्श समाधान है जो नाम वाले दायरे के अंदर इस्तेमाल किया जा सकता है। ओपी के मामले में default_scope,

Foo.unscope(where: :bar)

या

scope :not_default, -> { unscope(where: :bar) }
Foo.not_default

क्या दोनों में एक sql क्वेरी होगी जो मूल दायरे को लागू नहीं करती है, लेकिन जो भी अन्य स्थितियां हैं, उन्हें विलय में मिला देती हैं।


2

खैर, आप हमेशा पुराने समय का उपयोग find_by_sqlपूरी क्वेरी के साथ कर सकते हैं । उदाहरण के लिए: Model.find_by_sql ("मॉडल से चयन करें जहां आईडी = 123")

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.