ทำไม Ruby 1.9.2 จึงลบ“.” จาก LOAD_PATH และทางเลือกอื่นคืออะไร


154

เซ็ตการแก้ไขล่าสุดสำหรับ Ruby 1.9.2 จะไม่ทำให้ไดเรกทอรีปัจจุบัน.เป็นส่วนหนึ่งของคุณLOAD_PATHอีกต่อไป ฉันมีจำนวนของ Rakefiles ที่ไม่สำคัญซึ่งถือว่า.เป็นส่วนหนึ่งของLOAD_PATHสิ่งนี้ดังนั้นจึงทำให้พวกเขายากจน (พวกเขารายงานว่า "ไม่มีไฟล์ดังกล่าวที่จะโหลด" สำหรับทุกคำสั่งที่ต้องใช้ตามเส้นทางโครงการ) มีเหตุผลพิเศษสำหรับการทำเช่นนี้หรือไม่?

สำหรับการแก้ไขการเพิ่ม$: << "."ทุกที่ทำงานได้ แต่ดูเหมือนว่าแฮ็คอย่างเหลือเชื่อและฉันไม่ต้องการทำเช่นนั้น วิธีใดที่จะทำให้ Rakefiles 1.9.2+ ของฉันใช้ร่วมกันได้

คำตอบ:


141

ถือว่าเป็นความเสี่ยง "ความปลอดภัย"

คุณสามารถหลีกเลี่ยงได้โดยใช้เส้นทางที่แน่นอน

File.expand_path(__FILE__) et al

หรือทำ

require './filename' (ironically).

หรือโดยการใช้

require_relative 'filename'

หรือเพิ่มไดเรกทอรี "รวม"

ruby -I . ...

หรือเดียวกันโดยใช้ IRB;

$irb -I .

27
require_relativeฉันแผลขึ้นโดยใช้ ขอบคุณ
John Feminella

11
นี่คล้ายกับยูนิกซ์ส่วนใหญ่ที่ไม่รวมไดเรกทอรีปัจจุบันในเส้นทางสำหรับการเรียกใช้โปรแกรมปฏิบัติการหรือไม่?
Andrew Grimm

5
require './filename'ใช้งานได้ก็ต่อเมื่อสคริปต์ของคุณถูกเรียกใช้งานโดยตั้งค่าไดเรกทอรีทำงานเป็นไดเรกทอรีเดียวกันกับที่สคริปต์นั้นตั้งอยู่ นี่ไม่ใช่กรณีในโครงการหลายไดเรกทอรี
mxcl

34

มีสองเหตุผล:

  • ความแข็งแกร่งและ
  • ความปลอดภัย

ทั้งสองเป็นไปตามหลักการพื้นฐานเดียวกัน: โดยทั่วไปแล้วคุณไม่สามารถรู้ได้ว่าไดเรกทอรีปัจจุบันคืออะไรเมื่อรันโค้ดของคุณ ซึ่งหมายความว่าเมื่อคุณต้องการไฟล์และขึ้นอยู่กับว่าอยู่ในไดเรกทอรีปัจจุบันคุณไม่มีทางควบคุมว่าไฟล์นั้นจะอยู่ที่นั่นหรือว่าเป็นไฟล์ที่คุณคาดหวังว่าจะอยู่ที่นั่น


5
ฉันไม่คิดว่าการบังคับให้ไฟล์สองไฟล์อยู่ในตำแหน่งเดียวกันเมื่อเทียบกับไฟล์อื่น ๆ นั้นเป็นข้อกำหนดที่ไม่ดี ถ้านั่นเป็นเรื่องจริงเราจะไม่ใช้ไดเรกทอรี
John Feminella

4
@ John Feminella: สิ่งนี้เกี่ยวข้องกับการวางไฟล์ในเส้นทางที่สัมพันธ์กัน? คำถามคือเกี่ยวกับการวางพวกเขาที่เกี่ยวข้องกับ.เช่นไดเรกทอรีการทำงานปัจจุบัน หากผู้ใช้cds ลงในไดเรกทอรีที่แตกต่างกันจะมีการเปลี่ยนแปลงไดเรกทอรีการทำงานปัจจุบันและตอนนี้คุณrequire สมบูรณ์ไฟล์ที่แตกต่างกันขึ้นอยู่กับสิ่งไดเรกทอรีของผู้ใช้จะเกิดขึ้นในตอนที่เขาเรียกว่าสคริปต์ของคุณ ฉันไม่คิดว่าเป็นความคิดที่ดี
Jörg W Mittag

ดังนั้นเพื่อรักษาอินเทอร์เฟซที่ดีคุณควรทำเช่นนี้? $: << File.dirname(__FILE__)
Joshua Cheek

4
@Joshua Cheek: โดยส่วนตัวแล้วฉันไม่ชอบมัน (แต่โปรดอย่าดูรหัสที่เก่ากว่าของฉันเพราะมันเป็นสิ่งที่เกลื่อนไปด้วย :-)) ผมก็แกล้งทำเป็นว่าlibไดเรกทอรีบน$LOAD_PATHแล้วไฟล์ทั้งหมดเทียบกับrequire libกล่าวอีกนัยหนึ่ง: ฉันปล่อยให้ผู้ดูแลระบบทราบวิธีการตั้งค่า$LOAD_PATHอย่างถูกต้อง ถ้าคุณใช้ RubyGems นั่นเป็นเรื่องเล็กน้อยเพราะ RubyGems ทำเพื่อคุณโดยอัตโนมัติและถ้าคุณใช้แพ็คเกจ Debian นั่นก็เป็นหน้าที่ของผู้ดูแลแพคเกจ สรุปแล้วดูเหมือนว่าจะได้ผลออกมาค่อนข้างดี
Jörg W Mittag

8
@Joshua Cheek: นอกจากนี้ในฐานะที่เป็นเรียงลำดับของการถ่วงดุลเพื่อลบออก.จาก$LOAD_PATHRuby 1.9.2 แนะนำไฟล์require_relativeที่ ... แปลกใจ ... requireไฟล์ที่เกี่ยวข้องกับตำแหน่งของไฟล์ที่กำลังดำเนินการในปัจจุบัน (เช่นที่เกี่ยวข้องกับFile.dirname(__FILE__))
Jörg W Mittag

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'
Tyler Rick

8

ใช้ require_relative 'file_to_require'

โยนสิ่งนี้ในรหัสของคุณเพื่อให้ require_relative ทำงานใน 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

ฉันพบว่านี่เป็นการเปลี่ยนแปลงที่น่าประหลาดใจจนกระทั่งฉันได้ตระหนักถึงบางสิ่ง

คุณสามารถตั้งค่า RUBYLIB ใน. profile (Unix) ของคุณและใช้ชีวิตอย่างที่คุณเคยทำมาก่อน:

export RUBYLIB="."

แต่ดังที่กล่าวไว้ข้างต้นถือว่าไม่ปลอดภัยมานานแล้ว

สำหรับกรณีส่วนใหญ่คุณสามารถหลีกเลี่ยงปัญหาด้วยการเรียกสคริปต์ Ruby ของคุณพร้อมกับการเติมคำว่า '.' เช่น. /scripts/server


3

ดังที่Jörg W Mittag ชี้ให้เห็นฉันคิดว่าสิ่งที่คุณต้องการใช้คือrequire_relativeไฟล์ที่คุณต้องการนั้นสัมพันธ์กับไฟล์ต้นฉบับของการrequireประกาศไม่ใช่ไฟล์ dir ที่ใช้งานในปัจจุบัน

การอ้างอิงของคุณควรสัมพันธ์กับไฟล์สร้างเรคของคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.