रूबी में लोड कैसे अलग होता है?


81

क्या रूबी अनुप्रयोगों के बीच loadऔर requireरूबी में कोई बड़ा अंतर है ? या क्या उन दोनों की कार्यक्षमता समान है?


जवाबों:


98

requireसभी परिभाषित खोज पथों में लाइब्रेरी की खोज करता है और आपके द्वारा दर्ज फ़ाइल नाम के लिए .rb या .so को भी जोड़ता है। यह भी सुनिश्चित करता है कि एक पुस्तकालय केवल एक बार शामिल हो। इसलिए यदि आपके आवेदन में लाइब्रेरी A और B की आवश्यकता है और पुस्तकालय B reqirs Library A भी A को केवल एक बार लोड किया जाएगा।

आपके साथ loadपुस्तकालय का पूरा नाम जोड़ने की आवश्यकता है और यह हर बार आपके द्वारा कॉल किए जाने पर लोड हो जाता है load- भले ही यह पहले से ही स्मृति में हो।


धन्यवाद सर, इसलिए हम कह सकते हैं कि .rb को लोड करने की आवश्यकता नहीं है। और "आवश्यकता" हर समय नहीं बुलाती है, अगर इसकी स्मृति में है?
अर्पित वैष्णव

4
require$LOADED_FEATURES( $") वैश्विक सरणी के माध्यम से जो पहले से लोड किया गया है, उस पर नज़र रखता है , जो loadअनदेखा करता है।
सिरो सेंटिल्ली 郝海东 i iro i 法轮功 '26

39

बीच एक और अंतर Kernel#requireऔर Kernel#loadवह यह है कि Kernel#loadएक वैकल्पिक दूसरा तर्क यह है कि आप एक गुमनाम खाली मॉड्यूल में भरी हुई कोड रैप करने के लिए अनुमति देता है लेता है।

दुर्भाग्य से, यह बहुत उपयोगी नहीं है। सबसे पहले, loadएड कोड के लिए मॉड्यूल से बाहर निकलना आसान है , केवल वैश्विक नेमस्पेस का उपयोग करके, यानी वे अभी भी कुछ पसंद कर सकते हैं class ::String; def foo; end end। और दूसरा, loadमॉड्यूल को वापस नहीं करता है , यह कोड को लपेटता है, इसलिए आपको मूल रूप से इसे ObjectSpace::each_object(Module)हाथ से निकालना होगा ।


जानकर बहुत अच्छा लगा! कोई विचार नहीं Kernel#loadथा एक और तर्क था
जोश बोध

दुर्भाग्य से, यह बहुत उपयोगी नहीं है। सबसे पहले, loadएड कोड के लिए मॉड्यूल से बाहर निकलना आसान है , केवल वैश्विक नेमस्पेस का उपयोग करके, यानी वे अभी भी कुछ पसंद कर सकते हैं class ::String; def foo; end end। और दूसरा, loadमॉड्यूल को वापस नहीं करता है , यह कोड को लपेटता है, इसलिए आपको मूल रूप से इसे ObjectSpace::each_object(Module)हाथ से निकालना होगा ।
Jörg W Mittag

4

मैं एक रेल एप्लिकेशन चला रहा था और जेमफाइल में, मेरे पास एक विशिष्ट कस्टम रत्न था जिसे मैंने "आवश्यकता: गलत" विकल्प के साथ बनाया था। अब जब मैंने रेल सर्वर या रेल कंसोल को लोड किया, तो मुझे इनिशियलाइज़र में रत्न की आवश्यकता थी और रत्न लोड हो गया। हालाँकि, जब मैंने rspec और capybara के साथ एक विशेष फीचर परीक्षण चलाया, तो मुझे एक लोड त्रुटि मिली। और मैं पूरी तरह से हतप्रभ था कि परीक्षण चलाने के दौरान मणि $ LOAD_PATH में क्यों नहीं मिली।

इसलिए मैंने सभी विभिन्न तरीकों की समीक्षा की, जो लोड, आवश्यकता, रूबी और बंडलर इंटरैक्ट करते हैं। और ये मेरे निष्कर्षों का सारांश हैं जिन्होंने मुझे मेरी विशेष समस्या का हल खोजने में मदद की:

भार

1) आप इसे रूबी फ़ाइल के लिए एक निरपेक्ष पथ दे सकते हैं और यह उस फ़ाइल में कोड निष्पादित करेगा।

load('/Users/myuser/foo.rb')

2) आप लोड करने के लिए एक रिश्तेदार पथ पारित कर सकते हैं। यदि आप फ़ाइल के समान निर्देशिका में हैं, तो वह इसे पा लेगा:

> load('./foo.rb')
foo.rb loaded!
=> true

लेकिन यदि आप लोड के साथ अलग निर्देशिका से फ़ाइल लोड करने की कोशिश करते हैं (), तो यह वर्तमान निर्देशिका निर्देशिका (उदाहरण ./) के आधार पर एक सापेक्ष पथ के साथ नहीं मिलेगी।

> load('./foo.rb')
LoadError: cannot load such file -- foo.rb

3) जैसा कि ऊपर दिखाया गया है, लोड हमेशा सही रहता है (यदि फ़ाइल लोड नहीं की जा सकती है तो यह उठता है LoadError)।

4) वैश्विक चर, वर्ग, स्थिरांक और विधियां सभी आयातित हैं, लेकिन स्थानीय चर नहीं।

5) एक ही फाइल पर दो बार लोडिंग कॉल उस फाइल में कोड को दो बार निष्पादित करेगा। यदि निर्दिष्ट फ़ाइल एक स्थिरांक को परिभाषित करती है, तो यह उस स्थिरांक को दो बार परिभाषित करेगी, जो एक चेतावनी पैदा करता है।

6) $ LOAD_PATH निरपेक्ष रास्तों की एक सरणी है। यदि आप केवल एक फ़ाइल नाम लोड करते हैं, तो यह $ LOAD_PATH के माध्यम से लूप करेगा और प्रत्येक निर्देशिका में फ़ाइल की खोज करेगा।

> $LOAD_PATH.push("/Users/myuser")
> load('foo.rb')
foo.rb loaded!
 => true

की आवश्यकता होती है

1) एक ही फाइल पर दो बार कॉलिंग की आवश्यकता होगी, केवल एक बार इसे निष्पादित करेगा। यदि आप एक बार एक रिश्तेदार पथ के साथ एक बार और एक निरपेक्ष पथ के साथ इसे संदर्भित करते हैं तो यह एक ही फ़ाइल को दो बार लोड नहीं करने के लिए पर्याप्त स्मार्ट है।

2) यदि फ़ाइल को निष्पादित नहीं किया गया था तो यह सही है कि रिटर्न की आवश्यकता है।

3) के लिए ट्रैक रखने की आवश्यकता होती है जो फ़ाइलें वैश्विक चर $ LOADED_FEATURES में पहले से लोड की गई हैं।

4) आपको फ़ाइल एक्सटेंशन को शामिल करने की आवश्यकता नहीं है:

require 'foo'

5) foo.rb की आवश्यकता होगी, लेकिन foo.so, foo.o, या foo.dll की तरह गतिशील लाइब्रेरी फ़ाइलें भी। इस तरह आप रूबी से C कोड कॉल कर सकते हैं।

6) आवश्यकता वर्तमान निर्देशिका की जांच नहीं करती है, क्योंकि वर्तमान निर्देशिका डिफ़ॉल्ट रूप से $ LOAD_PATH में नहीं है।

7) requ_relative वर्तमान फ़ाइल के सापेक्ष एक पथ लेता है, प्रक्रिया की कार्यशील निर्देशिका नहीं।

माणिक्य

1) Rubygems एक पैकेज मैनेजर है जिसे आसानी से रूबी लाइब्रेरी की स्थापना के लिए डिज़ाइन किया गया है जिसे रत्न कहा जाता है।

2) यह अपनी सामग्री को एक जिप फाइल के रूप में पैकेज करता है जिसमें रूबी फाइलें और / या डायनामिक लाइब्रेरी फ़ाइलों का एक गुच्छा होता है जिसे कुछ मेटाडेटा के साथ आपके कोड द्वारा आयात किया जा सकता है।

3) रूबीगम्स ने डिफ़ॉल्ट आवश्यकता विधि को अपने स्वयं के संस्करण के साथ बदल दिया। यह संस्करण $ LOAD_PATH में निर्देशिकाओं के अलावा आपके स्थापित रत्नों के माध्यम से दिखेगा। अगर रूबीग्मस आपके रत्नों में फ़ाइल पाता है, तो वह उस रत्न को आपके $ LOAD_PATH में जोड़ देगा।

4) मणि एक मणि की निर्भरता के सभी बाहर आंकड़े स्थापित करता है और उन्हें स्थापित करता है। वास्तव में, यह मणि को स्थापित करने से पहले मणि की निर्भरता के सभी को स्थापित करता है।

बंडलर

1) बुंडलर आपको उन सभी रत्नों को निर्दिष्ट करता है जो आपकी परियोजना की जरूरत है, और वैकल्पिक रूप से उन रत्नों के क्या संस्करण हैं। फिर बंडल कमांड उन सभी रत्नों और उनकी निर्भरता को स्थापित करता है।

2) आप निर्दिष्ट करते हैं कि जेमफाइल नामक फाइल में आपको कौन से रत्न चाहिए।

3) बंडल कमांड भी सूचीबद्ध विशिष्ट संस्करणों में Gemfile.lock में सूचीबद्ध सभी रत्नों को स्थापित करता है।

4) बंडल कमांड को एक कमांड से पहले रखना, जैसे कि बंडल एग्जीक्यूट आरएसपसी, यह सुनिश्चित करता है कि आपके रत्नफ्लॉक में निर्दिष्ट रत्न के संस्करण को लोड करना होगा।

रेल और बुंडलर

1) config / boot.rb में, 'बंडलर / सेटअप' चलाने की आवश्यकता होती है। बुंडलर यह सुनिश्चित करता है कि रूबी रत्न के सभी रत्न (और उनकी सभी निर्भरताएं) पा सकती हैं। आवश्यकता होती है 'बंडलर / सेटअप' अपने आप ही आपके जेमफाइल की खोज कर लेगा, और अपने सभी रत्नों को रूबी के लिए उपलब्ध करा देगा (तकनीकी शब्दों में, यह रत्नों को "लोड पथ पर" डालता है)। आप इसे 'रूबीज' की आवश्यकता के लिए कुछ अतिरिक्त शक्तियों को जोड़ने के रूप में सोच सकते हैं।

ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])

2) अब जब आपका कोड रूबी के लिए उपलब्ध है, तो आपको उन रत्नों की आवश्यकता हो सकती है जिनकी आपको आवश्यकता है। उदाहरण के लिए, आपको 'साइनट्रा' की आवश्यकता हो सकती है। यदि आपके पास बहुत अधिक निर्भरता है, तो आप यह कहना चाह सकते हैं कि "मेरे जेमफाइल में सभी रत्नों की आवश्यकता है"। ऐसा करने के लिए, निम्नलिखित कोड को तुरंत 'बंडलर / सेटअप' की आवश्यकता होती है:

Bundler.require(:default)

3) डिफ़ॉल्ट रूप से, Bundler.require पर कॉल करने पर आपके जेमफाइल में प्रत्येक रत्न की आवश्यकता होगी। अगर Gemfile में लाइन मणि 'फू' कहती है,: = की आवश्यकता होती है, तो झूठी है तो यह सुनिश्चित करेगा कि फू स्थापित है, लेकिन इसे कॉल की आवश्यकता नहीं होगी। यदि आप मणि का उपयोग करना चाहते हैं तो आपको कॉल करना होगा ('फू')।

तो ज्ञान की इस चौड़ाई को देखते हुए, मैं अपने परीक्षण के मुद्दे पर लौट आया और महसूस किया कि मुझे स्पष्ट रूप से rails_helper.rb में मणि की आवश्यकता थी, क्योंकि Bundler.setup ने इसे $ LOAD_PATH में जोड़ा था, लेकिन आवश्यकता थी: इसे स्पष्ट रूप से आवश्यक होने से Bundler.require से हटा दें। । और फिर मसला हल हो गया।

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