最近给公司的 redmine 写了个提高 issue 流程的自动化程度插件。

redmine 官网上的开发者文档并不多,即使看完后,许多时候你也不知道接下来需要怎么做。好在 redmine 是用“约定高于配置”的 Rails 开发的,其命名相对规范。有必要时,可以猜测下对应的接口叫什么名字。实在摸不到门,阅读 redmine 和网上开源出来的 redmine 插件代码也是条路。

为了节省有同样需求的同行的时间,拯救我们日益凋亡的脑细胞,我在这里特意整理了开发过程中摸索出来的一些小技巧。

redmine 插件目录结构

.
├── app
│   ├── controllers
│   ├── models
│   └── views
│       └── settings
├── assets
│   └── javascripts
├── config
│   └── routes.rb
├── init.rb
├── lib
│   └── $plugin

其中 init.rb 是插件的入口。插件的逻辑主要放到 lib/$plugin 里面。其中 $plugin 应该是你的插件的名字。app 目录功能跟 Rails 的同名目录一样。比如你想在 redmine 中引入新的模型,或者加个路由,可以分别到 app/modelsapp/controllers 添加。不过别忘了修改 config/routes.rb 中的规则。要加个邮件模板,也是到 app/views 下加。至于 assets 里的资源文件,会在应用启动时拷贝到 public/plugin_assets/$plugin 路径下。

redmine 主要模型

Rails 数据库表有两种,一种命名是模型名的复数;另一种是 模型A复数_模型B复数,存储两个模型间的关系。

所以当我们列出数据库上的表时,我们便得到一份 redmine 模型清单。

 public | attachments                         | table | redminepublic | auth_sources                        | table | redminepublic | boards                              | table | redminepublic | changes                             | table | redminepublic | changeset_parents                   | table | redminepublic | changesets                          | table | redminepublic | changesets_issues                   | table | redminepublic | comments                            | table | redminepublic | custom_field_enumerations           | table | redminepublic | custom_fields                       | table | redminepublic | custom_fields_projects              | table | redminepublic | custom_fields_roles                 | table | redminepublic | custom_fields_trackers              | table | redminepublic | custom_values                       | table | redminepublic | documents                           | table | redminepublic | email_addresses                     | table | redminepublic | enabled_modules                     | table | redminepublic | enumerations                        | table | redminepublic | groups_users                        | table | redminepublic | import_items                        | table | redminepublic | imports                             | table | redminepublic | issue_categories                    | table | redminepublic | issue_relations                     | table | redminepublic | issue_statuses                      | table | redminepublic | issues                              | table | redminepublic | journal_details                     | table | redminepublic | journals                            | table | redminepublic | member_roles                        | table | redminepublic | members                             | table | redminepublic | messages                            | table | redminepublic | news                                | table | redminepublic | open_id_authentication_associations | table | redminepublic | open_id_authentication_nonces       | table | redminepublic | projects                            | table | redminepublic | projects_trackers                   | table | redminepublic | queries                             | table | redminepublic | queries_roles                       | table | redminepublic | repositories                        | table | redminepublic | roles                               | table | redminepublic | roles_managed_roles                 | table | redminepublic | schema_migrations                   | table | redminepublic | settings                            | table | redminepublic | time_entries                        | table | redminepublic | tokens                              | table | redminepublic | trackers                            | table | redminepublic | user_preferences                    | table | redminepublic | users                               | table | redminepublic | versions                            | table | redminepublic | watchers                            | table | redminepublic | wiki_content_versions               | table | redminepublic | wiki_contents                       | table | redminepublic | wiki_pages                          | table | redminepublic | wiki_redirects                      | table | redminepublic | wikis                               | table | redmine

许多模型名都可以见名知意,比如 issue 对应中文界面上的 问题、tracker 对应中文界面上的 追踪。
不过有些命名和其中文译名差别不小,比如 journal 对应的是问题页面下的 说明、custom_field 对应的是 自定义属性。
这只能多在 rails consolepry 里试试看了。

hooks 和 patch

开发 redmine 插件基本靠两组 API,一个是 hook,另一个是 patch。
前者可以让你在 controller/view 特定的阶段插入自己的逻辑;后者可以覆盖掉原有的逻辑,抑或给 model 特定的阶段插入

对应的官方文档:
hook:http://www.redmine.org/projec...
patch:http://www.redmine.org/projec...

我就补充下文档没有的。

这两者需要在 init.rb 里完成初始化:

...
require '$plugin/hooks' # 引入 `lib/$plugin/hooks.rb`,让 hooks 生效...
Rails.application.config.to_prepare do# 打上 Monkey Patchunless Issue.include?(AutoLicense::IssuePatch)Issue.send(:include, AutoLicense::IssuePatch)end...

patch 主要的应用场景是覆盖掉 model 的 after_save 回调,触发自己的自动化逻辑。

    def self.included(base)base.send(:include, InstanceMethods)base.class_eval doafter_save :after_save_triggerendendmodule InstanceMethodsdef after_save_triggerp self # 这里的 self 是具体的 model 实例

当然覆盖掉其他 Rails callback,比如 xx_create/xx_destroy,也是挺有用的。

hook 主要的应用场景是在 view 或 controller 执行流程中嵌入自己的逻辑。比如在特定 controller action 中加代码:

  class PluginControllerHookListener < Redmine::Hook::Listenerdef controller_issues_new_before_save(context)p context[:request].host_with_port# context 里面可以拿到 controller 上下文相关的变量,例如 :paramsend

还可以在特定的 view 里加代码:

  class PluginViewHookListener < Redmine::Hook::ViewListenerdef view_issues_new_top(context)js = <<-EOFconsole.log('Hello World')EOF"<script type=\"text/javascript\">#{javascript_cdata_section(js)}</script>"

当然如果想自定义前端代码,除了以字符串的形式插入,还可以直接引入整个资源文件。前面说到,

至于 assets 里的资源文件,会在应用启动时拷贝到 public/plugin_assets/$plugin 路径下。

所以把想要引入的资源文件放到 assets 目录下,在插入字符串中以 plugin_assets/$plugin/your_asset_file 路径引用即可。

顺便说一下,redmine 提供了一套 RESTful API:http://www.redmine.org/projec...
注意调用该接口需要提供用户的 API 调用键,细节参见文档。

redmine plugin setting

真正足够复杂的插件都需要一个配置界面 —— John Doe

redmine 给每个插件分配了一个配置页面,在 管理>插件>配置 里面,其对应的路由是 /settings/plugin/$plugin
插件开发者需要提供一个表单,通过这个表单,管理员能够给插件的一些配置项赋值。

这么做仅需两步:
第一步,需要准备一个表单模板,命名为 app/views/settings/_$plugin.html.erb

<table><tbody><tr><td> 配置1 </td><td><input type="text" id="settings_field1"value="<%= settings['field1'] %>"name="settings[field1]" ></td></tr>...

第二步,在插件代码中访问配置值:

settings = Setting.plugin_$plugin
p settings['field1']

当然,如果插件所需的配置项不是简单的 KV 结构,你可以选择自己实现一套独立的配置机制。

通过修改 config/routes.rbapp/controllers 里面的内容,redmine 插件可以添加属于自己的路由:

RedmineApp::Application.routes.draw doget '/xxx', :to => 'plugin#xxx'
end

然后你可以在 app/models 放置自己的 model,用它来存储配置值。这就跟开发独立的 Rails 应用差不多。

redmine 插件开发非官方指南相关推荐

  1. Bitnami Redmine安装配置指南

    Redmine的安装向来是一件麻烦的事情,在工具的介绍中也曾经提出过,随着Remine官方docker镜像的发行使得以前变得无比简单.但是仍然有很多各种情况无法使用docker的场景的存在,bitna ...

  2. Mimikatz 非官方指南和命令参考_Part1

    Her0in · 2016/01/28 10:26 原文地址:adsecurity.org/?page_id=18- 原文作者:Sean Metcalf 译者注: 由于原文中,作者(Sean Metc ...

  3. Easypack之Alpine容器系列:Redmine

    基于ROR开发的项目管理软件Redmine,与功能类似的Trac/Mantis相比也有自己的独特特性,以及和其他版本管理工具以及LDAP等的请打集成功能,是一款深受大家喜爱的开源项目管理软件.Bitn ...

  4. Idea插件开发(二)——插件的创建打包及发布

    Idea插件开发(一)--插件的分类及基础认识 Idea插件开发(二)--插件的创建打包及发布 Idea插件开发(三)--插件JSL的完整开发过程 上一篇简单介绍了插件的基本知识,接下来直接上手开发, ...

  5. redmine mysql 优化_Redmine性能优化方案

    redmine服务器性能问题排查与优化建议: 以下建议的方案是基于redmine运行期的log文件中的render耗时.activerecord耗时,linux系统性能指标采样与 mysql 性能指标 ...

  6. itunes 区域上架情况_在没有额外的膨胀软件的情况下安装iTunes的分步指南

    itunes 区域上架情况 Last week our friend Ed Bott wrote up an excellent article on how to install iTunes 10 ...

  7. Redmine之RestApi集成方式

    Redmine是一个较为强大的开源Ticket管理工具,这篇文章我们将会介绍一下如何使用Curl和Redmine所提供的RestApi来进行集成,将会选取Redmine中的用户进行简单的增删改查的操作 ...

  8. 一系列用于Fuzzing学习的资源汇总

    本文主要是向大家推荐一系列,用于fuzzing和Exploit开发初始阶段学习的资源合集,其中将包括相关的书籍,课程 – 免费或收费的,视频,工具,教程,以及一些供大家练习使用的靶机应用. fuzzi ...

  9. eclipse扩展点_Eclipse扩展点评估变得容易

    eclipse扩展点 编码Eclipse扩展点评估有点冗长,而且很少能自我解释. 当我最近忙于自己忙于这个话题时,我写了一个小助手,目的是减少通用编程步骤的样板代码,同时增加开发指导和可读性. 它原来 ...

最新文章

  1. 数据蒋堂 | 这个产品能支持多大数据量?
  2. 同步两个数据库的结构或者数据
  3. linux开放2280端口,威联通推出适用于NAS/PC的双端口 M.2 2280 PCIe NVMe SSD含双端口2.5GbE扩展卡...
  4. ACM入门之【树状数组】
  5. 数据结构:线性数据结构(2)-队列(栈,队列,deques, 列表)
  6. .NET Core 编写 Azure Function 并连接 GitHub 持续部署
  7. jq获取页面高度_JQ获取窗口文档等等高度总结!
  8. Visual C++ MFC/ATL开发-提高篇
  9. 20171221L09-10老男孩Linux运维实战培训-Nginx服务生产实战应用指南02
  10. linux内存和缓冲区,Linux上怎么清除缓存、缓冲区和交换区空间?
  11. Tkinter注册界面判断用户名是否唯一的合法性验证(Python3.7)
  12. 开发实例系列:一、舒尔特方格小游戏,付源码和APK
  13. 数学模型方法分类总结
  14. 【数据结构】图的基础练习题目,及题解
  15. 计划了近半年的跳槽,最终是面试四家,过3家……
  16. 嵌入式linux加入nes模拟器,成功运行于 ARM 上的 NES模拟器(InfoNES)
  17. Word替换特殊字符
  18. Angular2 模型渲染的一个坑
  19. python画多边形(八边形)
  20. mysql using where_mysql 优化问题 Using where; Using filesort

热门文章

  1. VirtualBox虚拟机开机后台自启动
  2. Linux -- cal/bc/LANGE与帮助文档
  3. RSA解密时javax.crypto.BadPaddingException: Data must start with zero
  4. 前端进阶(第二期)- 作用域闭包笔记
  5. nginx 稳定版 1.16.0 发布,支持动态加载 SSL 证书
  6. go标准库的学习-crypto/sha1
  7. JavaScript中的JS引擎的执行机制
  8. 启动MongoDB shell客户端会什么会一闪而过
  9. 第2章 熟悉Eclipse开发工具---- System.out.println(sum=+(a+b));
  10. IT菜鸟,希望大家赐教