रूबी 1.9.2 क्यों निकालती है "।" LOAD_PATH से, और विकल्प क्या है?


154

रूबी के लिए नवीनतम परिवर्तन 1.9.2 अब .आपके वर्तमान निर्देशिका को हिस्सा नहीं बनाते हैं LOAD_PATH। मेरे पास Rakefiles की एक गैर-तुच्छ संख्या है जो मानती है कि .इसका एक हिस्सा है LOAD_PATH, इसलिए इसने उन्हें तोड़ दिया (उन्होंने रिपोर्ट की "लोड करने के लिए ऐसी कोई फ़ाइल नहीं है" सभी के लिए उन बयानों की आवश्यकता होती है जो परियोजना पथ पर आधारित हैं)। क्या ऐसा करने का कोई विशेष औचित्य था?

एक फिक्स के लिए, $: << "."हर जगह जोड़ने से काम चलता है, लेकिन अविश्वसनीय रूप से हैकरी लगता है और मैं ऐसा नहीं करना चाहता। मेरे राेकफ़ाइल्स 1.9.2+ को संगत बनाने का पसंदीदा तरीका क्या है?

जवाबों:


141

इसे "सुरक्षा" जोखिम माना गया।

आप निरपेक्ष रास्तों का उपयोग करके इसे प्राप्त कर सकते हैं

File.expand_path(__FILE__) et al

या कर रहे हैं

require './filename' (ironically).

या उपयोग करके

require_relative 'filename'

या "शामिल करें" निर्देशिका को जोड़ना

ruby -I . ...

या उसी, irb का उपयोग कर;

$irb -I .

27
मैं का उपयोग करके घाव require_relative। धन्यवाद।
जॉन फेमिनाला

11
क्या यह सबसे यूनिक्स के लिए है जो मौजूदा निर्देशिकाओं को क्रियान्वित करने के लिए पथ में शामिल नहीं करता है?
एंड्रयू ग्रिम

5
require './filename'केवल तभी काम करता है जब आपकी स्क्रिप्ट को उसी निर्देशिका में सेट की गई कार्यशील निर्देशिका के साथ निष्पादित किया जाता है जो स्क्रिप्ट रहती है। बहु-निर्देशिका परियोजनाओं में अक्सर ऐसा नहीं होता है।
mxcl

34

इसके दो कारण हैं:

  • मजबूती और
  • सुरक्षा

दोनों एक ही अंतर्निहित सिद्धांत पर आधारित हैं: सामान्य तौर पर, आप बस यह नहीं जान सकते कि वर्तमान निर्देशिका क्या है, जब आपका कोड चलाया जाता है। जिसका अर्थ है कि, जब आपको किसी फ़ाइल की आवश्यकता होती है और यह वर्तमान निर्देशिका में होने पर निर्भर करता है, तो आपके पास यह नियंत्रित करने का कोई तरीका नहीं है कि क्या वह फ़ाइल वहां भी होगी, या क्या यह फ़ाइल है जिसे आप वास्तव में होने की उम्मीद करते हैं।


5
मुझे नहीं लगता कि यह लागू करना कि दो फाइलें एक-दूसरे के सापेक्ष एक ही स्थान पर हों, आवश्यक रूप से एक बुरी आवश्यकता है। अगर यह सच होता, तो हमारे पास निर्देशिकाओं का कोई उपयोग नहीं होता।
जॉन फेमिनाला

4
@ जॉन फेमिनाला: एक-दूसरे के सापेक्ष रास्तों में फाइलें डालने से क्या होता है? सवाल उन्हें .वर्तमान कार्यशील निर्देशिका के सापेक्ष रखने का है । यदि उपयोगकर्ता cdएक अलग निर्देशिका में है, तो वर्तमान कार्यशील निर्देशिका बदल जाती है, और अब आप require पूरी तरह से अलग-अलग फ़ाइलों पर निर्भर करते हैं कि उपयोगकर्ता ने आपकी स्क्रिप्ट को कॉल करने के दौरान क्या निर्देशिका की है। मुझे नहीं लगता कि यह एक अच्छा विचार है।
जोर्ग डब्ल्यू मित्तग

तो एक सभ्य इंटरफ़ेस बनाए रखने के लिए, आपको यह करना चाहिए? $: << File.dirname(__FILE__)
जोशुआ गाल

4
@ जोशुआ गाल: व्यक्तिगत रूप से, मुझे यह पसंद नहीं है। (लेकिन कृपया मेरे पुराने कोड को न देखें, क्योंकि यह उस तरह के सामान से भरा है :-))। मैं बस यह दिखावा करता हूं कि libनिर्देशिका $LOAD_PATHऔर फिर requireसभी फाइलों के सापेक्ष है lib। दूसरे शब्दों में: मैं इसे $LOAD_PATHसही तरीके से सेट करने का तरीका जानने के लिए प्रशासक पर छोड़ता हूं । यदि आप RubyGems का उपयोग करते हैं, तो यह तुच्छ है, क्योंकि RubyGems स्वचालित रूप से यह आपके लिए करता है , और यदि आप डेबियन पैकेज का उपयोग करते हैं, तो यह पैकेज अनुरक्षक का काम है। सब सब में, यह काफी अच्छी तरह से बाहर काम करने लगता है।
जोर्ग डब्ल्यू मित्तग

8
@Joshua गाल: इसके अलावा, एक प्रतिभार तरह-के रूप में दूर करने .से $LOAD_PATH, रूबी 1.9.2 द्वारा प्रस्तुत किया require_relativeजो ... आश्चर्य ... requireवर्तमान में क्रियान्वित फ़ाइल के स्थान पर सा फ़ाइल रिश्तेदार (यानी के सापेक्ष File.dirname(__FILE__))।
जोर्ग डब्ल्यू मित्तग

16

जैसा कि अन्य उत्तर देते हैं, यह एक सुरक्षा जोखिम है क्योंकि .आपके लोड पथ में वर्तमान कार्यशील निर्देशिका का उल्लेख है Dir.pwd, वर्तमान फ़ाइल की निर्देशिका लोड होने की नहीं। तो जो कोई भी आपकी स्क्रिप्ट को निष्पादित कर रहा है, वह इसे केवल cdदूसरी निर्देशिका में बदल सकता है । अच्छा नही!

मैं __FILE__एक विकल्प के रूप में निर्मित पूर्ण पथ का उपयोग कर रहा हूं ।

require File.expand_path(File.join(File.dirname(__FILE__), 'filename'))

इसके विपरीत require_relative, यह रूबी 1.8.7 के साथ पिछड़ा हुआ है।


4
वहाँ भी यह भिन्नता है (जो मुझे व्यक्तिगत रूप से अधिक पठनीय लगती है): require Pathname.new(__FILE__).dirname + 'filename'
टायलर रिक

8

उपयोग require_relative 'file_to_require'

1.8.7 में आवश्यक कार्य करने के लिए इसे अपने कोड में फेंक दें:

unless Kernel.respond_to?(:require_relative)
  module Kernel
    def require_relative(path)
      require File.join(File.dirname(caller.first), path.to_str)
    end
  end
end

6

'।' आपके मार्ग में लंबे समय तक यूनिक्स की दुनिया में एक बुरी बात मानी गई है (उदाहरण के लिए, http://www.faqs.org/faqs/unix-faq/faq/part2/section-13.html )। मुझे लगता है कि रूबी लोगों को ऐसा न करने की बुद्धिमत्ता के लिए राजी किया गया है।


3

जब तक मुझे कुछ चीजों का अहसास नहीं हुआ, मुझे यह एक बहुत बड़ा बदलाव लगा।

आप अपने .profile (यूनिक्स) में RUBYLIB सेट कर सकते हैं और जीवन के साथ आगे बढ़ सकते हैं जैसा आपने पहले किया था:

export RUBYLIB="."

लेकिन जैसा कि ऊपर उल्लेख किया गया है, ऐसा करने के लिए लंबे समय तक असुरक्षित माना जाता है।

अधिकांश मामलों में आप अपनी रुबी लिपियों को पहले से बताकर समस्याओं से बच सकते हैं '।' जैसे ./scripts/server।


3

जैसा कि Jörg W Mittag ने बताया, मुझे लगता है कि आप जो उपयोग करना चाहते हैं, वह require_relativeइसलिए है कि आपको जिस फ़ाइल की आवश्यकता है, वह requireघोषणा के स्रोत फ़ाइल के सापेक्ष है और वर्तमान कार्यशील dir की नहीं।

आपकी निर्भरता आपकी रेक बिल्ड फ़ाइल के सापेक्ष होनी चाहिए।

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