假设我有一个名为foo的gem,其文件结构如下:
foo.gemspec
test_foo.rb
lib/foo.rb
lib/foo/file1.rb
lib/foo/file2.rb
文件test_foo.rb
包含一些我用来试用我的宝石的代码。它使用以下行访问gem的代码:
require './lib/foo'
然后,lib/foo.rb
接受gem所需的其他文件,如:
require './lib/foo/file1'
require './lib/foo/file2'
由于test_foo.rb
位于gem目录的根目录中,因此需要lib/foo
中的文件以及根目录中的完整路径。
这一切都很好,并允许我通过更改test_foo.rb
中使用的代码立即玩我的宝石。
但是,如果我想构建gem,那么我必须将我的调用更改为require
,如下所示:
require 'foo/file1'
require 'foo/file2'
而不是
require './lib/foo/file1'
require './lib/foo/file2'
每次我想要制作宝石时都会做一些单调乏味的事情。
所以,我想到了另一种尝试方法,即使用rake
自动构建和安装gem,如下所示:
task :build do
`gem build foo.gemspec`
`gem uninstall foo`
`gem install ./foo-0.0.0.gem`
end
然后当我对代码进行更改并想要尝试时,只需运行rake build
,然后在require 'foo'
中调用test_foo.rb
。
但这是一个相当缓慢的过程,感觉有点像它击败了红宝石作为一种语言,在你尝试之前你不需要构建你的代码。
所以,我的问题是,在积极开发gem并测试它时,最好的工作流程是什么?
答案 0 :(得分:8)
为了使代码在不同情况下运行(本地测试,“生产”作为宝石等),它容易出错并且容易混淆源文件中的require
路径。
你可以使用一些技巧来“编写一次,随处运行”(抱歉Java,偷窃)。这也是您应该瞄准的目标,使用这些标准实践可以让其他人更容易理解您的代码,或者在某些内容无法正常工作时帮助您。
您的代码已经遵循常见的gem目录布局,不需要在那里进行任何更改。但是,作为一般经验法则,您应该使用require
加载“库”和require_relative
(如果您使用Ruby> 1.9)来加载相对于您正在处理的文件的源文件
1)您的文件test_foo.rb应该只包含一行:
require 'foo'
那就是省略require路径中的'./lib'部分。 gem的入口点(“require_path”)通常选择为“lib”。更多内容稍后(3)。
2)接下来,在foo.rb中,使用require_relative
(再次假设Ruby 1.9)来提取相关的源文件:
require_relative 'foo/file1'
require_relative 'foo/file2'
3)要将gem的require_path设置为lib,最好添加gemspec文件。
要测试代码(例如使用test_foo.rb),您有以下几种选择:
4)您可以使用ruby的-I
选项运行test_foo.rb,以在其加载路径中包含lib /目录:
ruby -I lib test_foo.rb
这比直接在代码中添加其他包含更不突兀。
5)Bundler是一种更好的方法来管理您的代码/宝石,以便在“真实”条件下进行测试,特别是如果您一次开发两个或多个相互依赖的宝石。 Bundler为您提供了在本地引用这些gem的选项,因此无需正式部署它们以便在开发期间测试它们的功能。要使用Bundler,您需要将Gemfile添加到gem代码的根目录中。
6)最后,为方便起见,将开发过程中的常用步骤集成到Rakefile中是有意义的,使用rake来驱动进程。
我在自己的项目中使用了这些技术,这里有一些链接供你参考,给你一些具体的例子:
1)Test files just contain a "require 'foo'"
2)Use "require_relative" from your "main" file to pull in subsequent parts
3)Example gemspec with require_path set to "lib"
当然你不需要使用所有这些技术,使用步骤1-4可能会很好,但随着你的项目变得越来越大,额外的努力肯定会得到回报。
答案 1 :(得分:2)
在您的测试文件中添加$:.unshift File.expand_path("./lib", __FILE__)
,然后您可以使用
require 'foo/file1'
更改“./lib”取决于文件夹的结构
答案 2 :(得分:1)
我知道这已经太晚了几年,但是因为在学习创建宝石时我的搜索结果中出现了很多这个问题,我想我会添加它。
如果使用Bundler gem生成器(bundle gem my_gem_name
)创建gem,它将生成一个ruby可执行文件./bin/console
,在加载gem时启动irb
而不实际安装它。