रेल में वैकल्पिक वैरिएबल आंशिक टेम्प्लेट: मैं कैसे (परिभाषित? फू) गंदगी से बाहर निकलता हूं?


225

मैं एक बुरा बच्चा रहा हूं और स्थानीय वेरिएबल्स के लिए डिफ़ॉल्ट मान सेट करने के लिए मेरे आंशिक टेम्प्लेट में निम्नलिखित सिंटैक्स का उपयोग किया है, यदि मूल्य को स्पष्ट रूप से परिभाषित नहीं किया गया है: आंशिक रेंडर करते समय स्थानीय हैश

<% foo = default_value unless (defined? foo) %>

यह हाल ही में तब तक ठीक काम करता था, जब (बिना किसी कारण के मैं विचार नहीं कर सकता था) गैर-पारित चर व्यवहार करने लगे जैसे कि उन्हें शून्य (अपरिभाषित के बजाय) परिभाषित किया गया हो।

जैसा कि SO पर विभिन्न सहायक लोगों द्वारा बताया गया है, http://api.rubyonrails.org/classes/ActionView/Base.html का उपयोग नहीं करने के लिए कहते हैं

defined? foo

और उपयोग करने के बजाय

local_assigns.has_key? :foo

मैं अपने तरीके में संशोधन करने की कोशिश कर रहा हूं, लेकिन इसका मतलब है कि बहुत सारे टेम्पलेट बदलना।

क्या मैं आगे शुल्क लगा सकता / सकती हूं और सभी टेम्प्लेट में यह बदलाव कर सकती हूं? क्या मुझे देखने के लिए कोई चालाकी की ज़रूरत है? कितनी मेहनत से मुझे हर एक का परीक्षण करने की आवश्यकता है?

जवाबों:


324

मैं यह करता हूँ:

<% some_local = default_value if local_assigns[:some_local].nil? %>

1
हालांकि मुझे वास्तव में hgimenez के सुझाव (ऊपर) के कॉम्पैक्ट सिंटैक्स पसंद हैं, इस दृष्टिकोण को बहुत स्पष्ट होने का लाभ है: क्या चल रहा है। (अभी भी आप स्थानीय के लिए एक मूल्य के रूप में शून्य पारित नहीं होने का नकारात्मक पक्ष है)
Brahn

1
नील पास करने के लिए आपका उपयोग मामला क्या है?
जौनी

ओह, मेरे पास कोई खास मामला नहीं है। पूर्ण निहितार्थ को समझने की कोशिश कर रहा है। इसने मुझे इस उत्तर को स्वीकार करने के लिए याद दिलाया :-)
Brahn

4
शून्य मुद्दे पर आने के लिए, मैं ओपी के लिंक ( api.rubyonrails.org/classes/ActionView/Base.html ) <% से local_assigns.has_key का कोड कॉपी कर रहा हूं ? : शीर्षक%> शीर्षक: <% = शीर्षक%> <% अंत%> - has_key शून्य / झूठी स्थिति से बचा जाता है, और शायद यहां एक पंक्ति को छोटा किया जा सकता है जैसे कि उत्तर
फिल

5
कृपया पाब्लो के उत्तर की जाँच करें: local_assigns.fetchपूरी तरह से शून्य मान के साथ कुंजियाँ भी संभालता है। यह केवल तभी डिफ़ॉल्ट देता है जब कुंजी बिल्कुल सेट नहीं होती है
quetzalcoatl

158

चूँकि local_assignsएक हैश है, आप वैकल्पिक के साथ भी प्राप्त कर सकते हैं default_value

local_assigns.fetch :foo, default_value

default_valueयदि fooसेट नहीं किया गया था तो यह वापस आ जाएगा ।

चेतावनी:

local_assigns.fetch :foo, default_valueजब default_valueकोई विधि हो, तो सावधान रहें क्योंकि इसके परिणाम को पास करने के लिए इसे वैसे भी कहा जाएगा fetch

यदि आपकी default_valueएक विधि है, तो आप इसे ब्लॉक में लपेट सकते हैं: local_assigns.fetch(:foo) { default_value }इसकी कॉल को रोकने के लिए जब इसकी आवश्यकता न हो।


1
यह स्पष्ट रूप से कहने योग्य है: यहां nilमूल्य संरक्षित हैं। यदि हैश में :fooमैप किया गया है nil, तो fetchयह वापस आ जाएगा nil। यानी कम से कम मेरे v1.9.3 पर। मुझे याद नहीं है कि 1.8 ने कैसा व्यवहार किया था।
quetzalcoatl

यह पूरी तरह से सही है। यह मेरे लिए समस्या को याद करता है local_assigns[:foo] || default_value, जब foo एक मिथ्या मूल्य देता है, तो default_valueइसके बजाय उपयोग किया जाएगा। यह आमतौर पर मेमोइज़ेशन के लिए एक समस्या है @some_value ||= expensive_methodयदि विधि एक मिथ्या मूल्य लौटाती है, तो इसे हमेशा निष्पादित किया जाएगा।
पाब्लो कैंटरो

1
जो कोई यह नहीं समझता कि यह सबसे अच्छा उत्तर क्यों है, ने लंबे समय तक रूबी का उपयोग नहीं किया। ब्रावो पाब्लो!
मस्ताबेला

2
एक अनुकूलन निम्नलिखित है, ताकि आपको केवल चर के प्रत्येक उपयोग पर 'लाने वाले गार्ड' का उपयोग करने के बजाय अपने टेम्पलेट के शीर्ष पर एक बार यह कॉल करना पड़े। foo ||= local_assigns[:foo] = local_assigns.fetch(:foo, default_value)
सेहकल

मैं सोच रहा था कि यह काम क्यों नहीं कर रहा है, मैंने यह मान लिया कि इसने भी वैरिएबल बनाया है, लेकिन हमें अभी भी लौटे मूल्य का उपयोग करना है:foo = local_assigns.fetch :foo, true
वडोरेक्वेस्ट

84

कैसा रहेगा

<% foo ||= default_value %>

यह कहता है "उपयोग fooअगर यह शून्य या सच नहीं है। अन्यथा default_valueफू को असाइन करें"


2
मुझे यकीन नहीं है कि जब तक यह स्थानीय हैश के माध्यम से पारित नहीं होता है तब तक यह परिभाषित नहीं होता है।
जोंणी

1
यह काम करता है, लेकिन अगर आपके पास इस तरह के डिफ़ॉल्ट मान हैं, तो शायद यह एक संकेत है कि आपको एक सहायक का उपयोग करना चाहिए?
Psyho

2
यहां कोई जादू नहीं। : पर विषय और जानकारियां groups.google.com/group/comp.lang.ruby/browse_thread/thread/...
hgmnz

37
मैं वास्तव में इस संस्करण को पसंद करता हूं क्योंकि वाक्य रचना इतनी कॉम्पैक्ट है। मुझे लगता है कि बड़ा नकारात्मक पक्ष यह है कि इसका मतलब है कि आप स्थानीय के लिए मान के रूप में शून्य या गलत पास नहीं कर सकते हैं, हालांकि, क्योंकि यह डिफ़ॉल्ट रूप से अधिलेखित हो जाएगा।
3

16
@ बब्रन, यह एक अच्छी बात है। वास्तव में, इस से बचा जाना चाहिए अगर fooएक बूलियन है। इसका सही मूल्य falseहो सकता है, और default_valueगलती से ओवरराइड हो सकता है ।
hmmnz

10

मुझे लगता है कि इसे यहां दोहराया जाना चाहिए ( http://api.rubyonrails.org/classes/ActionView/Ba.html से ):

यदि आपको यह पता लगाने की जरूरत है कि क्या एक विशेष स्थानीय रेंडर को किसी विशेष रेंडर कॉल में मान दिया गया है, तो आपको निम्नलिखित पैटर्न का उपयोग करने की आवश्यकता है:

<% if local_assigns.has_key? :headline %>
  Headline: <%= headline %>
<% end %>

परिभाषित का उपयोग कर परीक्षण? हेडलाइन नहीं चलेगी। यह एक कार्यान्वयन प्रतिबंध है।


6

मेरे मामले में, मैं उपयोग करता हूं:

<% variable ||= "" %>

मेरे आंशिक में।
मुझे नहीं पता कि अगर यह अच्छा है, लेकिन मेरे लिए ठीक है


यह वास्तव में काफी अच्छा काम करता है। अपरिभाषित के लिए काम करता है और जब nilआंशिक कॉल में भी स्थानीय के रूप में गुजरता है ।
जोशुआ पिंटर

3
आह, नीचे पढ़ रहे हैं, यह विफल हो जाएगा अगर variableएक बूलियन है और आपको इसे सेट करने की आवश्यकता है false। यह मूल्य का उपयोग करने के बजाय डिफ़ॉल्ट मान का उपयोग करेगा false। अपने जोखिम पार इस्तेमाल करें।
जोशुआ पिंटर

5

मैं जानता हूँ कि यह एक पुरानी धागा है, लेकिन यहाँ मेरा छोटा सा योगदान है: मैं का प्रयोग करेंगे local_assigns[:foo].presenceएक में सशर्त आंशिक अंदर। तब मैं fooकेवल जब रेंडर कॉल में जरूरत सेट :

<%= render 'path/to/my_partial', always_present_local_var: "bar", foo: "baz" %>

यहाँ ते आधिकारिक पटरियों गाइड पर एक नज़र है । RoR 3.1.0 से मान्य।


मैं local_assigns[:foo]और के बीच कोई वास्तविक अंतर नहीं देख सकता local_assigns[:foo].presencenilयदि हैश में कुंजी मौजूद नहीं है और मान मौजूद है तो या तो कोई वापस आ जाएगा ।
jamesmarkcook

1

मुझे लगता है कि एक बेहतर विकल्प जो कई डिफ़ॉल्ट चर के लिए अनुमति देता है:

<% options = local_assigns.reverse_merge(:include_css => true, :include_js => true) %>
<%= include_stylesheets :national_header_css if options[:include_css] %>
<%= include_javascripts :national_header_js if options[:include_js] %>

1

यह पाब्लो के उत्तर का व्युत्पन्न है। यह मुझे एक डिफ़ॉल्ट ('पूर्ण') सेट करने की अनुमति देता है, और अंत में, 'मोड' को स्थानीय_साइन और एक वास्तविक स्थानीय चर दोनों में सेट किया जाता है।

haml / स्लिम:

- mode ||= local_assigns[:mode] = local_assigns.fetch(:mode, 'full')

ERB:

<% mode ||= local_assigns[:mode] = local_assigns.fetch(:mode, 'full') %>

0

अधिक सहज और कॉम्पैक्ट:

<% some_local = default_value unless local_assigns[:some_local] %>


3
मुझे लगता है कि यह विफल हो जाएगा यदि आप आंशिक रूप से:locals => {:some_local => false}
Brahn

0

यदि आप इसे करने के लिए हर बार कॉल करने के लिए स्थानीय चर को पास नहीं करना चाहते हैं:

<% local_param = defined?(local_param) ? local_param : nil %>

इस तरह आप undefined variableत्रुटि से बच जाते हैं । यह आपको अपने आंशिक को स्थानीय चर के साथ / बिना कॉल करने की अनुमति देगा।


या स्थानीय_परम = स्थानीय_परम यदि परिभाषित किया गया है? (
स्थानीय_परम

0

रूबी 2.5

ERB

यह संभव है, लेकिन आपको अपने डिफ़ॉल्ट मूल्यों को दायरे में घोषित करना होगा।

VARIABLE बदलने के लिए शब्द।

# index.html.erb
...
<%= render 'some_content', VARIABLE: false %>
...

# _some_content.html.erb
...
<% VARIABLE = true if local_assigns[:VARIABLE].nil? %>
<% if VARIABLE %>
    <h1>Do you see me?</h1>
<% end %>
...

-6

इस तरह दिखने के लिए एक सहायक बनाया जा सकता है:

somearg = opt(:somearg) { :defaultvalue }

जैसे लागू किया गया:

module OptHelper
  def opt(name, &block)
    was_assigned, value = eval(
      "[ local_assigns.has_key?(:#{name}), local_assigns[:#{name}] ]", 
      block.binding)
    if was_assigned
      value
    else
      yield
    end
  end
end

मेरा ब्लॉग देखेंकैसे और क्यों पर विवरण के लिए ।

ध्यान दें कि यह समाधान आपको शून्य या असत्य को पारित करने की अनुमति देता है, क्योंकि यह बिना ओवरराइड किए मूल्य के रूप में गलत है।

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