最近刚写完一个 Gem,似乎也没有想象中那么难。之前总觉得写 Gem 难是因为怕麻烦。毕竟写 Gem 意味着要跟原项目抽离,代码调试起来会相当地不便,这篇文章会简单分享一下作者编写 Gem 的经验。原文链接:https://www.lanzhiheng.com/posts/tips-for-write-a-gem
习惯了测试驱动开发之后发现不写测试都不知道该如何写代码了,写 Gem 的时候这个方法特别有帮助。官方 Gem 文档也有推荐我们为 Gem 写测试,一方面是为了保证代码的质量,另一方面也是方便开发工作的进行,降低调试成本。
简单起见可以采用Minitest来写测试用例,并辅以Rake把运行测试的工作封装成一个任务。
# Rakefile
require 'rake/testtask'
Rake::TestTask.new do |t|
t.libs << 'test'
end
desc "Run tests"
task :default => :test
测试代码都会放在test
目录中,具体代码需要自己定制,文档也有相关的参考用例,这里就不贴了。测试任务通过下面的指令便可运行
% rake test
OR
% rake
Rake 会从指定的目录读取测试相关的代码并运行。配合 Github Action,CircleCI 等工具,可以做到每次提交代码,或者提交合并请求之前都自动运行测试,整个过程还是挺舒畅的。
代码即文档,注释即文档
我们可以利用Rdoc来做到这一点,很多时候我们写代码都会顺手给代码加上注释。一般来说这些注释是用来警示后面的维护者“这些代码你可能要注意一下”
def profit_sharing_return_process
## ...
# 不需要重复补款
return if profit_sharing_return.finished?
# ...
end
说白了这种注释是面向源码阅读者的。然而并不是所有的用户都愿意去阅读源代码,因此我们需要另外提供一份针对接口的文档。Gem 的开发者可以在编写代码的时候,顺便针对公共的 API 编写注释,然后通过 Rdoc 的命令即可生成对应的 API 文档。Rdoc 支持的格式很多,笔者这里用的是自己比较熟悉的 Markdown 格式
#
# 余额实时查询
#
# Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_7_1.shtml
#
# Example:
#
# ``` ruby
# WechatPay::Ecommerce.query_realtime_balance(sub_mchid: '1600000')
# ```
def query_realtime_balance(params)
sub_mchid = params.delete(:sub_mchid)
url = "/v3/ecommerce/fund/balance/#{sub_mchid}"
method = 'GET'
make_request(
path: url,
method: method,
extra_headers: {
'Content-Type' => 'application/x-www-form-urlencoded'
}
)
end
上面是我在wechat-pay里封装的,实时查询余额的接口。文档生成好之后会以 HTML 的形式存放在某个目录中,效果如下
最完美的情况就是我们写完 README 以及代码注释之后就什么都不用管了,文档会自动生成在线版本,这种可能性是存在的。RubyDocInfo这个网站就是为此而生,主要借助了Yard这门工具。它能够兼容 Rdoc 的语法,每次我们的 Gem 发布新版本,它都会根据我们的 Gem 版本自动生成对应的文档,如今wechat-pay的最新文档链接在此可以在 Gem 的首页找到对应入口
开发者可以专注于代码跟文档的编写,而不用考虑后面文档的发布过程,还是蛮方便的。
很多人对 Gem 望而却步主要是怕调试麻烦,调试不够方便的话开发的热情就会大减,人之常情。不过如果 Gem 是项目源码的一部分,会不会调试就简单很多了呢?Gem 通过 bundle 载入项目之后,其实它是以文件夹的形式存放于系统的某处,也就是说它其实也是你源码的一部分,只不过存放的路径并不在当前的项目目录中(当然你也可以通过配置让它存放在你的项目目录——记住别提交到仓库就好)。
一般来说我们会在 Gemfile 里面这样去引入 Gem,Ruby 会根据自己的搜索路径加载对应的 Gem
# Gemfile
# ....
gem 'chinese_pinyin'
gem 'wechat-pay', '>= 1.0.1'
而如果你本地正在开发的 Gem 想要利用当前项目的代码进行调试,其实你也可以直接把开发中的 Gem 加载到项目中去,并利用项目已有的逻辑进行调试。
gem 'chinese_pinyin'
# gem 'wechat-pay', '>= 1.0.1'
gem 'wechat-pay', path: '../../OpenSource/wechat-pay'
这样项目就会加载本地开发中的 Gem 了,我们可以直接给 Gem 打断点进行调试。只不过调试完并提交代码的时候记得
如果想要用 Github 上对应 Gem 最新的开发版本可以像这样去做
gem 'wechat-pay', :github => 'lanzhiheng/wechat-pay'
这篇文章不能算是完整的 Gem 开发教程,只是针对自己开发 Gem 的经验进行了总结,简单分享了一些小技巧罢了。