Ruby CLI工具未遵循Gemfile配置 如何加载本地/远程Gem依赖
RSpec 运行时默认由 Bundler 接管依赖加载流程,会自动读取项目根目录 Gemfile 的依赖解析规则,包括配置的 path 本地路径映射,因此可以正确加载本地调试版 Gem。
直接执行 ./exe/ 目录下的入口文件时,没有预先初始化 Bundler 环境,Ruby 仅按照默认的 $LOAD_PATH 全局搜索规则加载 Gem,会优先命中系统全局安装的正式版本,不会读取 Gemfile 中配置的本地路径映射。
另外当前 Gemfile 里的本地 Gem 配置被放在 :development, :test 分组下,默认非开发/测试场景不会加载这部分配置,需要在初始化 Bundler 时指定对应分组。
方案1:零代码修改临时调试
执行 CLI 命令时增加 bundle exec 前缀,同时开启本地 Gem 开关的环境变量即可,示例:
KLUE_LOCAL_GEMS=true bundle exec ./exe/k_rails_template
这种方式和 RSpec 运行时的依赖加载逻辑完全一致,Bundler 会自动处理所有路径映射,不需要改动业务代码。
方案2:修改入口文件,直接执行即可适配Gemfile规则
修改 ./exe/k_rails_template 文件,在加载自有业务代码之前加入 Bundler 初始化逻辑,修改后的完整代码如下:
#!/usr/bin/env ruby # frozen_string_literal: true # 初始化Bundler环境,读取Gemfile依赖规则 require 'bundler' # 加载默认分组+开发测试分组,确保本地Gem配置生效 # 生产环境安装时Bundler会自动忽略不存在的本地路径,回退到正式发布版Gem Bundler.setup(:default, :development, :test) lib_path = File.expand_path('../lib', __dir__) $LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path) require 'k_rails_template' Signal.trap('INT') do warn("\n#{caller.join("\n")}: interrupted") exit(1) end begin KRailsTemplate::CLI.start rescue KRailsTemplate::CLI::Error => e puts "ERROR: #{e.message}" exit 1 end
修改完成后,直接执行 KLUE_LOCAL_GEMS=true ./exe/k_rails_template 就会自动加载本地路径的调试版 Gem;不加该环境变量时,会自动加载远程发布的正式版 Gem,不需要额外加 bundle exec 前缀。
如果不希望生产环境运行 CLI 时加载 rspec、rubocop 这类开发测试组的冗余依赖,可以把 Gemfile 里 Klueless 系列自有 Gem 的本地路径配置从 :development, :test 组移出,仅通过 KLUE_LOCAL_GEMS 环境变量控制是否启用本地路径,避免生产环境引入不必要的依赖。
调整后如果出现 Gem 版本冲突,在项目根目录执行 bundle install 刷新 Gemfile.lock 的依赖解析结果即可。
内容的提问来源于stack exchange,提问作者David Cruwys

