8

假设我有一个名为 foo 的 gem,文件结构如下:

foo.gemspec
test_foo.rb
lib/foo.rb
lib/foo/file1.rb
lib/foo/file2.rb

该文件test_foo.rb包含一些我用来试用我的 gem 的代码。它使用以下行访问 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'

每次我想构建 gem 时,这有点乏味。

所以,我想到了另一种尝试的方法,它是用来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

但这是一个相当缓慢的过程,感觉有点像它打破了 ruby​​ 作为一种语言的意义,在这种语言中,您不必在尝试之前构建代码。

所以,我的问题是,在积极开发 gem 并对其进行测试时,最好的工作流程是什么?

4

3 回答 3

8

require为了使代码在不同的情况下运行(本地测试,“生产”作为 gem 等),必须弄乱源文件中的路径,这很容易出错并且令人困惑。

您可以使用一些技巧来“编写一次,随处运行”(对不起,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​​ 的选项运行 test_foo.rb 以-I在其加载路径中包含 lib/ 目录:

ruby -I lib test_foo.rb

这比直接在代码中添加额外的包含要少得多。

5) Bundler是一种更好的方式来管理您的代码/gem,以便在“现实生活”条件下对其进行测试,特别是如果您同时开发两个或多个相互依赖的 gem。Bundler 为您提供了在本地引用这些 gem 的选项,因此无需正式部署它们即可在开发期间测试它们的功能。要使用 Bundler,您需要将 Gemfile 添加到 gem 代码的根目录中。

6) 最后,为方便起见,将开发过程中的常用步骤集成到 Rakefile 中是有意义的,使用 rake 来驱动流程。

我在自己的项目中经常使用这些技术,这里有一些链接供您参考,并提供一些具体示例:

1)测试文件只包含一个“require 'foo'”

2)使用“主”文件中的“require_relative”来拉入后续部分

3)示例 gemspec,require_path 设置为“lib”

5)示例 Gemfile

6)示例 Rakefile

当然,您不需要使用所有这些技术,使用步骤 1-4 可能会很好,但是随着您的项目变得越来越大,额外的努力肯定会得到回报。

于 2012-06-09T13:40:12.373 回答
2

添加$:.unshift File.expand_path("./lib", __FILE__)你的测试文件然后你可以使用

require 'foo/file1'

更改“./lib”取决于您的文件夹结构

于 2012-06-09T10:03:25.787 回答
1

我知道这已经晚了几年,但由于在学习创建 gem 时,我的搜索结果中经常出现这个问题,所以我想我会添加它。

如果您使用 Bundler gem 生成器 ( bundle gem my_gem_name) 创建您的 gem,它将生成一个 ruby​​ 可执行文件,该可执行文件以您的 gem 加载./bin/console开始,而无需实际安装它。irb

于 2016-07-13T06:52:15.583 回答