ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
ฉันแค่พยายามเข้าถึงไฟล์. rb จากไดเร็กทอรีและบทช่วยสอนกำลังบอกให้ใช้โค้ดนี้ แต่ฉันไม่เห็นว่ามันค้นหาไฟล์ gem ได้อย่างไร
ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
ฉันแค่พยายามเข้าถึงไฟล์. rb จากไดเร็กทอรีและบทช่วยสอนกำลังบอกให้ใช้โค้ดนี้ แต่ฉันไม่เห็นว่ามันค้นหาไฟล์ gem ได้อย่างไร
คำตอบ:
File.expand_path('../../Gemfile', __FILE__)
เป็นสำนวน Ruby ที่ค่อนข้างน่าเกลียดสำหรับการรับเส้นทางสัมบูรณ์ไปยังไฟล์เมื่อคุณทราบเส้นทางที่สัมพันธ์กับไฟล์ปัจจุบัน อีกวิธีหนึ่งในการเขียนคือ:
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__.
ใน Ruby 2.0 มีKernelฟังก์ชันที่เรียก__dir__ว่าใช้งานเป็นFile.dirname(File.realpath(__FILE__)).
File.expand_path('../Gemfile',__dir__)
File.expand_path assumes a directoryแม้ว่า__FILE__จะไม่ใช่ไดเร็กทอรี สำหรับสิ่งที่ควรใช้__dir__ซึ่งจริงๆแล้วคือไดเร็กทอรี
ข้อมูลอ้างอิงสองรายการ:
วันนี้ฉันเจอสิ่งนี้:
หากคุณขึ้นสองไดเร็กทอรีจาก boot.rb ในแผนผังไดเร็กทอรี:
/ railties / lib / ราง / เครื่องกำเนิดไฟฟ้า / ราง / แอป / เทมเพลต
คุณเห็น Gemfile ซึ่งทำให้ฉันเชื่อว่าFile.expand_path("../../Gemfile", __FILE__)การอ้างอิงไฟล์ต่อไปนี้:/path/to/this/file/../../Gemfile