रूबी में क्या भेजता है ()?


95

क्या कोई मुझे बता सकता है कि क्या

send("#{Model.find...}")

है और करता है


2
क्या यह कोड की पूरी लाइन है? मेरा मतलब है, 'भेजने' से पहले कुछ नहीं है?
जिराफ

जवाबों:


107

send कक्षा पदानुक्रम में एक वस्तु उदाहरण और उसके पूर्वजों को एक संदेश भेजता है जब तक कि कोई विधि प्रतिक्रिया नहीं करती (क्योंकि इसका नाम पहले तर्क से मेल खाता है)।

व्यावहारिक रूप से, वे पंक्तियाँ समतुल्य हैं:

1.send '+', 2
1.+(2)
1 + 2

ध्यान दें कि sendदृश्यता की जाँच बाईपास करती है, ताकि आप निजी तरीकों को भी कॉल कर सकें, (यूनिट परीक्षण के लिए उपयोगी)।


अगर भेजने से पहले वास्तव में कोई चर नहीं है, तो इसका मतलब है कि वैश्विक ऑब्जेक्ट का उपयोग किया जाता है:

send :to_s    # "main"
send :class   # Object

1
ओह, मैं देख रहा हूं, इसलिए यदि कोई व्यक्ति डेटाबेस को 1.month की तरह संग्रहीत करना चाहता था, तो वह सेंड का उपयोग कर सकता था, बजाय इसके कि आप दिनों की संख्या को कहे।
क्रिश्चियन बैंकेटर

3
सच है, आप इसका उपयोग कॉल विधि के नाम से कर सकते हैं, जो स्थिर हैं, स्थिर नहीं हैं। (आप चाहें तो अप्रतिबंधित उपयोगकर्ता इनपुट, हालांकि, निजी तरीकों बुला से बचने के लिए अनुमति चाहिए नहीं ... आप कर सकते थे, हालांकि, उनमें एक अनूठा उपसर्ग दे: भेजने 'user_method _' + methodName, * args)
giraff

2
अच्छा उपयोग मामला हो सकता है कि आप एक संरक्षित वर्ग विधि का परीक्षण करना चाहते हैं, आप इसे एक वर्ग के बाहर-परीक्षण फ़ाइल में कह सकते हैं ..
GN।

107

भेजना एक रूबी (रेल के बिना) विधि है जो नाम से दूसरी विधि लागू करने की अनुमति देती है।

प्रलेखन से

   class Klass
     def hello(*args)
       "Hello " + args.join(' ')
     end
   end
   k = Klass.new
   k.send :hello, "gentle", "readers"   #=> "Hello gentle readers"

http://corelib.rubyonrails.org/classes/Object.html#M001077


5
महान उत्तर, क्रिया स्वीकार किए गए उत्तर की तुलना में अधिक स्पष्ट।
अरोन-कोडिंग

63

एक सबसे उपयोगी विशेषता जो मुझे लगता है कि .send विधि के साथ है, यह है कि यह गतिशील रूप से विधि को कॉल कर सकता है। यह आपको बहुत टाइपिंग से बचा सकता है। .Send विधि का सबसे लोकप्रिय उपयोग में से एक विशेषता गतिशील रूप से असाइन करना है। उदाहरण के लिए:

class Car
  attr_accessor :make, :model, :year
end  

नियमित रूप से विशेषताओं को असाइन करने के लिए एक की आवश्यकता होगी

c = Car.new
c.make="Honda"
c.model="CRV"
c.year="2014"

या .send विधि का उपयोग कर:

c.send("make=", "Honda")
c.send("model=", "CRV")
c.send("year=","2014")

लेकिन यह सब निम्नलिखित के साथ बदला जा सकता है:

अपने Rails ऐप को उपयोगकर्ता इनपुट से आपकी कार वर्ग को विशेषताएँ निर्दिष्ट करने की आवश्यकता है, आप कर सकते हैं

c = Car.new()
params.each do |key, value|
  c.send("#{key}=", value)
end

महान लिंक के लिए धन्यवाद
sid_09

7
इस तरह से .send का उपयोग अनावश्यक जटिलता जोड़ता है और यह अनजाने में कोड में एक बग को लागू करना आसान बनाता है। उदाहरण के लिए, ऊपर दिए गए कोड में, यदि आप अपने पैरामीटर हैश (जैसे 'सिलेंडर') में एक नई प्रविष्टि जोड़ते हैं, तो कोड एक अपरिभाषित विधि त्रुटि के साथ विफल हो जाएगा।
केविन श्वर्टफिगर 12

1
का जवाब? यदि वांछित हो तो ऐसी त्रुटियों को रोकने के लिए इस्तेमाल किया जा सकता है।
रिचर्ड_जी

1
यह बहुत अच्छी व्याख्या थी! धन्यवाद झा!
शरथ

1
@ केविन आप सही हैं, लेकिन कभी-कभी यह आवश्यक हो सकता है। अधिक लचीलापन अधिक जोखिम से संबंधित है, जिसे कम किया जा सकता है।
विल शेपर्ड

12

एंटोनियो झा के https://stackoverflow.com/a/26193804/1897857 के समान एक और उदाहरण

यदि आपको किसी ऑब्जेक्ट पर विशेषताएँ पढ़ने की आवश्यकता है।

उदाहरण के लिए, यदि आपके पास स्ट्रिंग्स की एक सरणी है, यदि आप उनके माध्यम से पुनरावृति करने की कोशिश करते हैं और उन्हें अपनी वस्तु पर कॉल करते हैं, तो यह काम नहीं करेगा।

atts = ['name', 'description']
@project = Project.first
atts.each do |a|
  puts @project.a
end
# => NoMethodError: undefined method `a'

हालाँकि, आप sendऑब्जेक्ट के लिए तार कर सकते हैं :

atts = ['name', 'description']
@project = Project.first
atts.each do |a|
  puts @project.send(a)
end
# => Vandalay Project
# => A very important project

सरल और आसान स्पष्टीकरण के लिए धन्यवाद!
जुबान चकमा

धन्यवाद! ठीक यही उत्तर मैं बाद में हूं। आश्चर्य है कि यह आमतौर पर इस्तेमाल किया जाता है? मैं विरासत कोड में कुछ इसी तरह से आया था, मुझे यकीन नहीं था कि मुझे इसके साथ रहना चाहिए। @ माइक वालानो
बी लियू

1
@ b-liu मैंने इसे नए कोड में अनुभवी डेवलपर्स द्वारा उपयोग किया है। उपयोग करते समय यह भी सहायक हो सकता है define_method: apidock.com/ruby/Module/define_method
बजे माइक वालानो

बहुत बढ़िया! बहुत बहुत धन्यवाद! @ मायकेवेलानो
बी लियू

4

क्या भेजता है?

send एक विधि को कॉल करने का एक और तरीका है।

यह सबसे अच्छा उदाहरण द्वारा चित्रित किया गया है:

o = Object.new
o.send(:to_s) # => "#<Object:0x00005614d7a24fa3>"
# is equivalent to:
o.to_s # => "#<Object:0x00005614d7a24fa3>"

ऑब्जेक्ट क्लास में जीवन भेजें

Ths का क्या लाभ है?

इस दृष्टिकोण का लाभ यह है कि आप उस विधि से गुजर सकते हैं जिसे आप पैरामीटर के रूप में कॉल करना चाहते हैं। ये रहा एक सरल उदाहरण:

def dynamically_call_a_method(name)
    o = Object.new
    o.send name 
end
dynamically_call_a_method(:to_s) # => "#<Object:0x00005614d7a24fa3>"

आप उस विधि में पास हो सकते हैं जिसे आप बुलाया जाना चाहते हैं। इस मामले में हम पास हुए :to_s। रूबी मेटाप्रोग्रामिंग करते समय यह बहुत आसान हो सकता है, क्योंकि इससे हम अपनी विभिन्न आवश्यकताओं के अनुसार अलग-अलग तरीकों से कॉल कर सकते हैं।


0

विचारों के लिए एक और उपयोग मामला:

    <%= link_to 
    send("first_part_of_path_#{some_dynamic_parameters}_end_path", 
    attr1, attr2), ....
    %>

अनुमति । आप स्केलेबल दृश्य लिखने के लिए जो सभी प्रकार की वस्तुओं के साथ काम करते हैं:

    render 'your_view_path', object: "my_object"

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