2012-11-28 35 views
4

假設下列導軌安裝require_relative不起作用:Capistrano的:如預期

  • 的Rails 3.2.9
  • Capistrano的2.13.5
  • 使用多級擴展(即Capistrano的/轉/多級)
  • 定義的生產階段,例如在Rails.root/config/deploy/production.rb

裏面production.rb,你無法使用require_relative,似乎—你最終得到了「不能推斷基本路徑」的錯誤。然而,如果你只是普通的ruby production.rb,require_relative就可以正常工作。

爲什麼會出現這種情況?似乎Capistrano加載/執行代碼的方式使require_relative無法按預期工作。

我懷疑這類似於:Passenger Rack app 'cannot infer basepath',(粗略地說)表明require_relative可能會失敗,這取決於代碼最終加載/運行的方式。

下面給出了分支ruby_1_9_3中require_relative的源代碼,它顯示了require_relative如何依賴於調用堆棧。但是,端到端圖片並不完整— Capistrano如何找到並執行代碼,以及它如何影響調用堆棧。

我不認爲這裏有任何東西是無法解決的,但代替時間來自己挖掘這個問題,任何專家對於發生什麼事情的洞察力都將非常感激,不僅對於具體問題,而且對於洞察Cap和Ruby如何工作。

// load.c 
VALUE 
rb_f_require_relative(VALUE obj, VALUE fname) 
{ 
    VALUE base = rb_current_realfilepath(); 
    if (NIL_P(base)) { 
     rb_raise(rb_eLoadError, "cannot infer basepath"); 
    } 
    base = rb_file_dirname(base); 
    return rb_require_safe(rb_file_absolute_path(fname, base), rb_safe_level()); 
} 

// vm_eval.c 
VALUE 
rb_current_realfilepath(void) 
{ 
    rb_thread_t *th = GET_THREAD(); 
    rb_control_frame_t *cfp = th->cfp; 
    cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)); 
    if (cfp != 0) return cfp->iseq->filepath; 
    return Qnil; 
} 
+0

我(用Ruby 1.9.2測試)無法幫助Rails/Capistrano。在'require_relative'之前,我添加了'p方法(:require_relative).owner'。輸出是內核。你可以檢查它是否require_relative已被重新定義? – BernardK

回答

1

http://pragprog.com/book/ruby3/programming-ruby-1-9說:

要求其路徑是相對於包含 調用文件庫。因此,如果目錄/ usr/local/mylib/bin包含文件 myprog.rb並且該程序包含以下行: require_relative「../lib/mylib」,則Ruby將在 /usr/local中查找mylib/MYLIB/lib中。

如果我有這樣的目錄結構:

a/b/c/d1 
a/b/c/d2 
a/b/c/d2/e/f1 
a/b/c/d2/e/f2 

$ pwd 
a/b/c/d1 
$ ruby -w ../d2/e/f1/test_req_rel 

文件a/b/c/d2/e/f1/test_req_rel.rb包含:

require_relative '../f2/req1' 

所以它會在a/b/c/d2/e/f2搜索,因爲呼叫是在a/b/c/d2/e/f1/test_req_rel.rb'../f2/req1'指回從f1e,然後在f2轉發,其中req1.rb必須存在,否則,你得到錯誤 「沒有這樣的文件來加載 -/A/B/C/C/d/E(LoadError)」

+0

感謝您的回答,但我相當嚴重地修改了這個問題,所以如果您仍然對此感興趣,請查看新版本。 –