【问题标题】:How should I be trying out my gem during development?我应该如何在开发过程中试用我的 gem?
【发布时间】:2012-06-09 09:36:35
【问题描述】:

假设我有一个名为 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。

但是,如果我想构建 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,然后在test_foo.rb 中调用require 'foo'

但这是一个相当缓慢的过程,并且感觉有点违背了 ruby​​ 作为一种语言的意义,在这种语言中,您无需在尝试之前构建代码。

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

【问题讨论】:

    标签: ruby gem rake


    【解决方案1】:

    为了使代码在不同情况下运行(本地测试、“生产”作为 gem 等),必须在源文件中弄乱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 是一种更好的方式来管理您的代码/gem,以便在“现实生活”条件下对其进行测试,特别是如果您同时开发两个或多个相互依赖的 gem。 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"

    5)Example Gemfile

    6)Example Rakefile

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

    【讨论】:

    • 哇 - 很好的答案,谢谢!我尝试使用捆绑器,但由于某种原因,它在运行bundle install 时总是给我一个致命错误。 - 我会告诉你这是如何工作的,干杯。
    • 不客气!我只能建议升级到 Bundler 1.1,它更快 - bundle install 不再是痛苦 ;)
    【解决方案2】:

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

    require 'foo/file1'
    

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

    【讨论】:

    • 感谢您的回答 - 但您能否添加更多细节?抱歉,我对 ruby​​ 很陌生。
    • $: 包含脚本的 ruby​​ 加载路径。 unshift 将您的 lib 文件夹添加到此数组中,因此 ruby​​ 将知道在哪里可以找到您的文件。 Rubygems 在内部做同样的事情然后你已经构建了你的 gem
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2013-09-25
      • 2015-09-25
      • 1970-01-01
      • 2010-09-05
      • 2011-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多