File.expand_path ("../../ Gemfile", __FILE__) यह कैसे काम करता है? फाइल कहां है?


84

ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)

मैं बस कुछ डायरेक्टरी से .rb फाइल को एक्सेस करने की कोशिश कर रहा हूं और एक ट्यूटोरियल मुझे इस कोड का उपयोग करने के लिए कह रहा है, लेकिन मैं यह नहीं देख पा रहा हूं कि यह मणि फाइल कैसे ढूंढ रहा है।


1
इसके अलावा प्रश्न stackoverflow.com/questions/4333286
Theo

जवाबों:


194
File.expand_path('../../Gemfile', __FILE__)

जब आप वर्तमान फ़ाइल के सापेक्ष पथ जानते हैं, तो फ़ाइल के लिए पूर्ण पथ प्राप्त करने के लिए कुछ बदसूरत रूबी मुहावरा है। इसे लिखने का एक और तरीका यह है:

File.expand_path('../Gemfile', File.dirname(__FILE__))

दोनों बदसूरत हैं, लेकिन पहला संस्करण छोटा है। पहला संस्करण, हालांकि, तब तक बहुत गैर-सहज है जब तक आप इसे लटका नहीं लेते। अतिरिक्त क्यों ..? (लेकिन दूसरा संस्करण इस बात का संकेत दे सकता है कि इसकी आवश्यकता क्यों है)।

यह यह है कि यह कैसे काम करता है: File.expand_pathपहले तर्क के निरपेक्ष मार्ग को लौटाता है, दूसरे तर्क के सापेक्ष (जो वर्तमान कार्य निर्देशिका में चूक करता है)। __FILE__फ़ाइल उस कोड का पथ है जो इस स्थिति में है। चूंकि इस मामले में दूसरा तर्क एक फ़ाइल के लिए एक पथ है, और File.expand_pathएक निर्देशिका को मानता है, हमें ..पथ को सही करने के लिए पथ में एक अतिरिक्त छड़ी करना होगा। यह इस तरह काम करता है:

File.expand_pathमूल रूप से इसे इस तरह लागू किया जाता है (निम्नलिखित कोड pathमें इसका मान होगा ../../Gemfileऔर relative_toइसका मूल्य होगा /path/to/file.rb):

def File.expand_path(path, relative_to=Dir.getwd)
  # first the two arguments are concatenated, with the second argument first
  absolute_path = File.join(relative_to, path)
  while absolute_path.include?('..')
    # remove the first occurrence of /<something>/..
    absolute_path = absolute_path.sub(%r{/[^/]+/\.\.}, '')
  end
  absolute_path
end

(इसके लिए थोड़ा और अधिक है, यह ~होम निर्देशिका में फैलता है और इसी तरह - कोड के साथ शायद कुछ अन्य मुद्दे भी हैं)

ऊपर दिए गए कोड के लिए एक कॉल के माध्यम से कदम रखने से absolute_pathपहले मूल्य प्राप्त होगा /path/to/file.rb/../../Gemfile, फिर लूप में प्रत्येक दौर के लिए पहले ..हटा दिया जाएगा, इसके साथ पथ घटक के साथ। पहले /file.rb/..हटा दिया जाता है, फिर अगले दौर /to/..में हटा दिया जाता है, और हम प्राप्त करते हैं /path/Gemfile

एक लंबी कहानी को छोटा File.expand_path('../../Gemfile', __FILE__)करने के लिए, जब आप वर्तमान फ़ाइल के सापेक्ष पथ जानते हैं, तो किसी फ़ाइल का पूर्ण पथ प्राप्त करने की एक चाल है। ..सापेक्ष पथ में अतिरिक्त फ़ाइल के नाम को समाप्त करना है __FILE__

रूबी 2.0 में एक Kernelफ़ंक्शन होता है जिसे कहा जाता __dir__है File.dirname(File.realpath(__FILE__))


2
क्या कोई कारण है कि आपको पूर्व में रूबी 1.9.2 के साथ असंगति के अलावा अन्य 'requ_relative' का उपयोग नहीं करना चाहिए?
डैनी एंड्रयूज

9
रूबी 2.0 के रूप में आप उपयोग कर सकते हैंFile.expand_path('../Gemfile',__dir__)
Phrogz

थियो की इस लाइन को आखिरकार मेरे लिए क्लिक करने के लिए मिल गया File.expand_path assumes a directory, भले ही __FILE__यह एक निर्देशिका नहीं है। चीजों का उपयोग करने के लिए __dir__जो वास्तव में एक निर्देशिका है।
म्बिग्रास

9

दो संदर्भ:

  1. फ़ाइल :: विस्तार_पथ विधि प्रलेखन
  2. __FILE__रूबी में काम कैसे करता है

मैं आज इस पर ठोकर खाई:

रेल Github में boot.rb कमिट करें

यदि आप डायरेक्टरी ट्री में boot.rb से दो डाइरेक्टरी ऊपर जाते हैं:

/ Railties / lib / रेल / जनरेटर / रेल / ऐप्स / टेम्पलेट्स

आप Gemfile देखते हैं, जो मुझे विश्वास दिलाता है कि File.expand_path("../../Gemfile", __FILE__)निम्नलिखित फ़ाइल का संदर्भ:/path/to/this/file/../../Gemfile


पोस्ट के लिए धन्यवाद, लेकिन यह gembundler ट्यूटोरियल से आया था इसलिए मैं इसे समझने की कोशिश कर रहा था कि उनके पास यह कैसे है :)
thenengah
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.