rubygems.org guides 翻译八(Patterns)

目录

1.命名一致性

2.版本语义化

3.声明依赖

4.加载代码

5.preRelease gem

 

一、命名一致性

There are only two hard things in Computer Science: cache invalidation and naming things. -Phil Karlton

1.文件名

保持lib和bin目录下文件命名的一致性。

hola gem的命名如下:

% tree
.
├── Rakefile
├── bin
│   └── hola
├── hola.gemspec
├── lib
│   ├── hola
│   │   └── translator.rb
│   └── hola.rb
└── test
    └── test_hola.rb

可执行文件和lib下的主文件命令相同。开发者可以轻易的使用require 'hola'来加载。

2.命名你的gem

命名自己的gem非常重要。在你命名你的gem之前,到on RubyGems.org and GitHub 搜索下,看看别人是否已经使用了这个名字。每一个发布的gem都必须使用一个唯一的名字。当你想好自己gem的名字时,请阅读 naming recommendations

 

二、版本语义化

版本控制策略只是一个版本如何被分配的简单规则。它非常简单(例如从1自增),或者非常特别(Knuth’s TeX 项目的 version numbers: 3, 3.1, 3.14, 3.141, 3.1415; each successive version added another digit to PI)

RubyGems团队使用语义化版本号来给gem规定版本。RubyGems并未严格强调命名策略,但是使用不合理的命名策略是在给其他使用你gem的人帮倒忙。

假设你有一个stack的gem,Stack class里面包含push和pop两个方法。如果你使用语义化版本控制,那么你的CHANGELOG需要像这样:

Version 0.0.1: The initial Stack class is released.
Version 0.0.2: Switched to a linked list implementation because it is cooler.
Version 0.1.0: Added a depth method.
Version 1.0.0: Added top and made pop return nil (pop used to return the old top item).
Version 1.1.0: push now returns the value pushed (it used it return nil).
Version 1.1.1: Fixed a bug in the linked list implementation.
Version 1.1.2: Fixed a bug introduced in the last fix.

语义化版本控制归结如下:

PATCH 0.0.x level changes for implementation level detail changes, such as small bug fixes
MINOR 0.x.0 level changes for any backwards compatible API changes, such as new functionality/features
MAJOR x.0.0 level changes for backwards incompatible API changes, such as changes that will break existing users code if they update

 

 

三、声明依赖

gem可以喝其他gem一起协同工作。下面是一些tips以确保他们之前正常工作。

1.运行时 vs 开发

rubygems提供两种类型的依赖:运行时和开发。运行时依赖是你的gem工作时所需要的(例如such as rails needing activesupport

开发时依赖对于别人想修改你的gem时非常有用。当你指定开发时依赖,其他开发者可以使用install --dev your_gem命令,rubygems会同时抓取两种依赖。典型的开发时依赖就是测试框架和构建系统。

在gemspec中设置依赖非常简单。只需要使用add_runtime_dependency and add_development_dependency

Gem::Specification.new do |s|
  s.name = "hola"
  s.version = "2.0.0"
  s.add_runtime_dependency "daemons",
    ["= 1.1.0"]
  s.add_development_dependency "bourne",
    [">= 0"]

2.不要在你得gem中使用gem

你也许有像下面一样的这些代码,确保你指定了gem的版本。

gem "extlib", ">= 1.0.8"
require "extlib"

对于应用来说,这样做有理由说是在consume gems(虽然他们也可能使用其他工具,例如 Bundler).gems本身不会这样做。他们会在gemspec中使用依赖,这样rubygems可以加载它,而不是用户自己去加载。

It’s reasonable for applications that consume gems to use this (though they could also use a tool like Bundler). Gems themselves should not do this. They should instead use dependencies in the gemspec so RubyGems can handle loading the dependency instead of the user.

3.封闭式的版本约束

如果你的gem版本计划遵循语义化版本2.0.0(http://semver.org/lang/zh-CN/),那么其他ruby开发者将会大受裨益,当他们在自己的应用中使用版本约束锁定gem的时候。
看看下面这样的gem版本releases
  • Version 2.1.0 — Baseline
  • Version 2.2.0 — Introduced some new (backward compatible) features.
  • Version 2.2.1 — Removed some bugs
  • Version 2.2.2 — Streamlined your code
  • Version 2.3.0 — More new features (but still backwards compatible).
  • Version 3.0.0 — Reworked the interface. Code written to version 2.x might not work.
某个其他使用你gem的人发现2.2.0在他的应用中工作良好,但是2.1.0不工作。那么他的gem配置,或者Gemfile(使用bundler)配置如下
# gemspec
spec.add_runtime_dependency 'library',
  '>= 2.2.0'

# bundler
gem 'library', '>= 2.2.0'
 
这是一个好的版本约束。他表示所有2.X版本的在我的应用中工作良好,但是3.X的不确定。
The alternative here is to be “pessimistic”. This explicitly(明白地)excludes(排除) the version that might break your code.
# gemspec
spec.add_runtime_dependency 'library',
  ['>= 2.2.0', '< 3.0']

# bundler
gem 'library', '>= 2.2.0', '< 3.0'
 
RubyGems 提供了一种简单的方式,叫做 twiddle-wakka:
# gemspec
spec.add_runtime_dependency 'library',
  '~> 2.2'

# bundler
gem 'library', '~> 2.2'
 
注意:他会抛弃补丁级别的版本号。
这里的~>2.2.0是指在[">=2.2.0", "<2.3.0"]这个区间。
If you want to allow use of newer backwards-compatible(向下兼容) 版本 but need a specific bug fix you can use a compound requirement:
# gemspec
spec.add_runtime_dependency 'library', '~> 2.2', '>= 2.2.1'

# bundler
gem 'library', '~> 2.2', '>= 2.2.1'
 
The important note to take home here is to be aware others will be using your gems, so guard yourself from potential bugs/failures in future releases by using ~> instead of >= if at all possible.
小提示:如果你不得不在你的应用中处理大量的gem依赖,那么我建议你看看bundler和isolate这样的工具,他会帮助你管理复杂的gem依赖问题。
If you want to allow prereleases and regular releases use a compound requirement:
# gemspec
spec.add_runtime_dependency 'library', '>= 2.0.0.a', '< 3'
 
在prerelease版本中使用~>限制你只能使用的prerelease版本。
4.require rubygems

摘要:不要。

这一行。。。。。。

require 'rubygems'

 

没必要出现在你的gem代码中,当一个gem required的时候,RubyGems 已经被加载了。

require 'rubygems'意味着这个gem使用简单,没必要运行RubyGems 客户端。

关于这个主题,如果你想了解更多,请查看 Ryan Tomayko

四、加载代码

从其核心,RubyGems的存在时帮助你管理ruby的$LOAD_PATH,他关系到require语句怎样加载你的代码。有几个方法可以使你确定你正确的加载了代码。

1.respect the global load path

当打包你的gem的时候,你需要特别注意你的lib目录里面是些什么。你安装的每一个gem都会把lib目录添加到你的$LOAD_PATH中去。这意味着lib目录中的顶层文件将会被加载。

例如,我们的foo这个gem有如下的目录结构:

 

.
└── lib
    ├── foo
    │   └── cgi.rb
    ├── erb.rb
    ├── foo.rb
    └── set.rb
 

 

这看上去你把自定义的erb和set文件放在这里是无害的。但这确实是有害的,每一个加载这个gem的用户就不能从ruby的标准库中加载erb和set了。避免这个的最好办法是在lib目录下使用其他目录。通常的做法是把他们放在和你的gem name同名的目录下。例如lib/foo/cgi.rb.

 

2.requiring files relative each other

Gems不应该使用__FILE__来加载其他文件到你的gem中。如下代码出人意料的普遍:

 

require File.join(
          File.dirname(__FILE__),
          "foo", "bar")

# or
require File.expand_path(File.join(
          File.dirname(__FILE__),
          "foo", "bar"))
 

 

The fix is simple,, just require the file relative to the load path:

 

require 'foo/bar'

#or 使用require_relative
require_relative 'foo/bar'
 

 

The make your own gem guide has a great example of this behavior in practice, including a working test suite. The code for that gem is on GitHub as well.

 

3.mangling the load path

gems不应该改变$_LOAD_PATH常量。RubyGems 帮你管理这些。如下代码是必须的:

 

lp = File.expand_path(File.dirname(__FILE__))
unless $LOAD_PATH.include?(lp)
  $LOAD_PATH.unshift(lp)
end

# or
__DIR__ = File.dirname(__FILE__)

$LOAD_PATH.unshift __DIR__ unless
  $LOAD_PATH.include?(__DIR__) ||
  $LOAD_PATH.include?(File.expand_path(__DIR__))
 

 

当RubyGems激活一个gem,退添加lib目录到你的 $LOAD_PATH 以准备好被其他lib或者应用加载。 It is safe to assume you can then require any file in your lib folder.

 

五、preRelease gem

当一个大的gem更新前,许多gem开发者会放出testing或者edge版本。RubyGems 支持prerelease的观点,prerelease可以使betas, alphas或者其他。

他的优点很明显。在你的gem版本中只需要多一个或者几个字母。例如,下面是一个prerelease gemspec的字段:

Gem::Specification.new do |s|
  s.name = "hola"
  s.version = "1.0.0.pre"

 

其他prerelease版本可能包含 2.0.0.rc1, 或者 1.5.0.beta.3. 只需要包含几个字母,你就做大了。这样的gem可以使用--pre,就想这样:

% gem list factory_girl -r --pre

*** REMOTE GEMS ***

factory_girl (2.0.0.beta2, 2.0.0.beta1)
factory_girl_rails (1.1.beta1)

% gem install factory_girl --pre
Successfully installed factory_girl-2.0.0.beta2
1 gem installed

 

六.扩展阅读

Several sources were used for content for this guide:

 

 

你可能感兴趣的:(Pattern)