ruby script 在別的資料夾被執行會找不到 gem [LoadError]


#1

嗨大家好!有問題想請教…

最近在用 Ruby 寫 CLI 的工具(myapp/myapp.rb),然後有運用到其它的 Gem ,又因為沒有權限的關係,只好用 bundle install --path vandor/bundle 的方式把 Gem 裝在這支程式自己的資料夾內(myapp/vendor/bundle),按照 Bundler 的說明,程式內先 require 'bundler/setup',再 require 'xxx' 就可以正確載入其它依賴的 Gem,也的確是這樣,不過僅限於在這支程式自己的資料夾內被執行時…。

一旦跳到別的資料夾執行,例如 /etc > ~/Repos/myapp/myapp.rb,就會爆出 LoadError 錯誤,上網查了一下,應該是 Bundler 找不到 myapp/Gemfile 或是 myapp/.bundle/config 所以也無法改寫 $LOAD_PATH 所以就 GG 惹!

請問這樣有解嗎?


#2

這種問題我都會先問你是 rvm 還 rbenv 或原生 ruby & 先參照這篇玩看看

可能單純找不到 gemset 而已


#3

是因為 cwd 不對吧, bundler 預設只會在 cwd 下面找 Gemfile,比較好的方法應該是寫一個 wrapper,先切換到 myapp/ 下再執行 myapp.rb

給你一個參考的 shell script

#!/bin/bash
@cd $(dirname "$0")
ruby myapp.rb -- $@ # or `./myapp.rb $@` if myapp.rb has execute permission

#4

他寫 /etc 所以猜測應該是 cronjob,且猜測是 rvm 才會丟那篇的,且我那篇那樣用 bundler 都正常就是


#5

看起來是 David 大說的那樣,要用另一個 shell script 切換 CWD 再去執行 ruby script,還要另外處理傳 argv 的問題。

所以我現在的理解是,(在不魔改 Bundler code 的情況下) Bundler 就是幫你處理 myapp 內自己的 Gem 依賴,出了 myapp 資料夾它就不管了,想要在任何位置都能跑 myapp,請全域安裝 Gem,不要用 Bundler。

所以 ~/Repos/myapp2 > ~/Repos/myapp1/myapp1.rb,這種例子,Bundler 會帶入 myapp2 的 Gemfile(吧)。


#6

話說…你要不要改用 bindler exec 看看?

http://bundler.io/man/bundle-exec.1.html


#7

它會出現
Could not locate Gemfile or .bundle/ directory

再補充老外的問答:How to tell bundler where the Gemfile is?


#8

bundler 會在載入的時候吃 BUNDLE_GEMFILE 這個環境變數,
你可以在 require 'bundler/setup' 前先設定這個環境變數:

# 將 BUNDLE_GEMFILE 設為與此檔案同目錄的 Gemfile
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('./Gemfile', __dir__)

require 'bundler/setup

# ... 以下為原本的內容

這個技巧其實在 Rails 裡面的 config/boot.rb 裡面有出現XD