ओवरराइडिंग रेलिंग 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.