Docs header transparent bg

如何编写 Bundler 插件

什么是插件?

Bundler 插件是专门的 gem,旨在集成和扩展 Bundler 的功能。本指南将帮助您开始编写自己的 Bundler 插件。

为什么要使用插件?

插件能够集成和扩展 Bundler。
目前,插件可以

  • 向 Bundler 添加命令(例如:bundle my_command
  • 添加一个特殊的处理程序来安装 gem(例如:Mercurial 或 SVN)
  • 向特定挂钩点添加功能
    • 所有可用挂钩、其描述及其块参数的列表可在 plugin/events.rb 文件中找到。
    • 注意:请确保查看您正在使用的 Bundler 版本中的 events.rb 文件。

使用插件

从命令安装插件

插件可以从 RubyGems(默认)或 Git 服务器安装。要使用您机器上的 gem,您可以运行 bundler plugin install gem_name。插件安装后,命令将可用,挂钩将自动注册到 Bundler。

运行 bundler plugin help install 以获取有关从 Git 安装的更多详细信息和说明。

在 Bundler 2.2.0 中,您可以使用 bundler plugin uninstall gem_name 卸载插件。

从 Gemfile 安装插件

您也可以在 Gemfile 中指定插件

plugin 'my_plugin' # Installs from Rubygems
plugin 'my_plugin', path: '/path/to/plugin' # Installs from a path
plugin 'my_plugin', git: 'https://github.com:repo/my_plugin.git' # Installs from Git

开发入门

1. 创建一个 gem

您首先需要创建一个专门的 gem,然后才能创建 Bundler 插件。

使用本指南创建一个 gem。 完成后,返回本指南并继续第二步。

2. 创建一个 plugins.rb 文件

一个 plugins.rb 文件位于 gem 文件夹的顶层,是 Bundler 用于调用插件的入口点。这是一个 Ruby 文件,它定义了您的命令、挂钩和其他代码。通常,您可能只需要 gem 最顶层的 lib 文件。

例如,如果您的 gem 称为“my_plugin”,您可能在 lib/my_plugin.rb 中有一个文件,其中包含 gem 的最高级别命名空间。您的 plugins.rb 文件可能是

require 'my_plugin'

lib/my_plugin.rb 文件将包含其他 require 语句、挂钩和命令,类似于普通的 gem。

3. 创建 Bundler 命令

Bundler 命令允许您使用额外的功能扩展 Bundler 接口。

要添加 Bundler 命令,您需要创建一个将自身(或另一个类)注册为命令的类。例如,要添加对 bundler my_command 命令的支持,您可以创建一个类似于以下的类

class MyCommand < Bundler::Plugin::API
  # Register this class as a handler for the `my_command` command
  command "my_command"

  # The exec method will be called with the `command` and the `args`.
  # This is where you should handle all logic and functionality
  def exec(command, args)
    if args.empty?
      # Using BundlerError in plugins is recommended. See below.
      raise BundlerError, 'My plugin requires arguments'
    end
    puts "You called " + command + " with args: " + args.inspect
  end
end

module MyCommand
  # Register this class as a handler for the `my_command` command
  Bundler::Plugin::API.command('my_command', self)

  # The exec method will be called with the `command_name` and the `args`.
  # This is where you should handle all logic and functionality
  def exec(command_name, args)
    puts "You called " + command_name + " with args: " + args.inspect
  end
end

这两个元素对于命令在 Bundler 中注册至关重要

  1. Bundler::Plugin::API.command(COMMAND_NAME, CLASS)command 'COMMAND_NAME' 将被调用,具体取决于使用的方法(参见上面的示例)
  2. 该类定义了实例方法 exec(command_name, args)

引发错误

如果出现问题,您的插件应该引发 BundlerError。不建议在插件中引发例如 Exception,因为这会导致 Bundler 打印自己的错误报告模板,要求用户向 Bundler 本身报告错误。

要详细了解 bundler 如何处理错误,请查看 bundler/friendly_errors.rb

4. 使用 Bundler 钩子

要与 Bundler 的各个部分交互,您可以使用钩子。钩子允许您通过注册监听特定事件来在特定事件中注入一些功能。要监听事件,您需要为其添加钩子并提供一个代码块。

例如,对于 Bundler::Plugin::Events::GEM_BEFORE_INSTALL_ALL 钩子,您必须提供一个代码块,该代码块有一个用于 Bundler::Dependency 对象数组的参数

Bundler::Plugin.add_hook('before-install-all') do |dependencies|
  # Do something with the dependencies
end

5. 开发源代码插件

源代码插件允许您指定更多可能在 Bundler 中使用的安装源。例如,假设您想从 Amazon S3 安装 gem。这可以通过构建插件来完成。

建议您熟悉 Bundler::Plugin::API::Source 的 API,该 API 可在 rubydoc.info 上源代码中 获得。

源代码插件的基本概述是,您必须子类化 Bundler::Plugin::API::Source 并覆盖许多方法。这些方法在上面链接的文档/源代码中有所说明。

Bundler 使用源代码插件 API 为 RubyGems、Git 和基于路径的 gem 提供接口。这些部分的源代码可能有助于理解 API

6. 在本地运行您的插件

要在本地安装和运行您的插件,您可以运行 bundler plugin install --git '/PATH/TO/GEM' copycat

7. 部署您的插件

将您的插件部署到 RubyGems,以便其他人可以安装它。有关部署到 RubyGems 的说明,请访问 本指南

虽然插件可以从 git 分支安装,但建议直接从 RubyGems 安装插件。

示例插件

以下是一些您可以用作示例和灵感的插件

您还可以查看 Bundler 插件的完整列表