Redmine plugin hooks
2014-03-07 11:09
816 查看
Redmine supports the concept of Hooks. It is an API to allow external code to extend the core Redmine functionality in a clean way. Hooks allow the plugin author to register callback functions which
are executed one after another when the Redmine code reaches specific points in the code.
There is a list of valid hooks. But the
best way to find them is to just have a look into the code to find the place you would like to extend and search for a call to a hook nearby.
Additional methods to extend or replace Redmine code are:
Adding new methods
Using rails callbacks
Wrapping an existing method using
As said above, when a hook is called, it executes the previously registered callback functions. These functions must accept exactly one parameter: a hash providing some context. This context
hash will always contain data necessary to do something useful in your callback function. In the case of controller of view hooks (see below), it contains at least the following information:
:controller => a reference to the current controller instance
:project => the current project (if set by the controller),
:request => the current request object with much information about the
current web request
Additionally, the hash will contain some data specific to the respective hook. This data is directly passed in the
Model hooks will not contain the default data as it does not apply here. These hooks will only contain the data passed in the
Basically, there are currently three types of hooks:
View hooks
Controller hooks
Model hooks
While both types use exactly the same API, there is a fundamentally different use-case for these.
View hooks are executed while rendering the HTML code of a view. This allows the plugin author to insert some custom HTML code into some sensible places of the view. The return value of the callback
function transformed to a string and included into the view. A shortcut exists for rendering a single partial. See below for an example.
Controller hooks are fewer in number than the view hooks. Often it is sufficient to use additional
filters or to extend the model classes, as the controller actions should be (and are most of the time) very short and don't do much. There are however, some more lengthy actions which use hooks. To properly use those, one has to understand that the objects
in the context hash are only referenced. Thus, if you change an object in-place, the changes will be available in the actual controller (and later in the view). Consider the following simplified example:
Assume the following function is registered to the
Now consider a controller action with the following code:
As you can see, the hook function can change the
There are very few model hooks in Redmine. Most extensions in model code can be done by adding new methods or encapsulating existing ones by creatively applying the alias_method_chain pattern.
The hooks can be used in the same way as the controller hooks.
The following example is going to hook a function into the hook
In your plugin (assumed to be named
The following class does exactly the same as the above but uses a method instead of the shorter
In your
You can register methods to controller and model hooks the same way as the view hooks. Always remember to require the hook class in your
Some additional real-life examples can be found at
View hooks
http://github.com/edavis10/redmine_contracts/blob/master/lib/redmine_contracts/hooks/view_layouts_base_html_head_hook.rb
http://github.com/edavis10/redmine_contracts/blob/master/lib/redmine_contracts/hooks/view_issues_show_details_bottom_hook.rb
http://github.com/edavis10/redmine_contracts/blob/master/lib/redmine_contracts/hooks/view_issues_form_details_bottom_hook.rb
http://github.com/edavis10/redmine_contracts/blob/master/lib/redmine_contracts/hooks/view_issues_bulk_edit_details_bottom_hook.rb
Helper hooks
http://github.com/edavis10/redmine_contracts/blob/master/lib/redmine_contracts/hooks/helper_issues_show_detail_after_setting_hook.rb
Controller hooks
http://github.com/edavis10/redmine_contracts/blob/master/lib/redmine_contracts/hooks/controller_timelog_available_criterias_hook.rb
http://github.com/edavis10/redmine_contracts/blob/master/lib/redmine_contracts/hooks/controller_issues_edit_before_save_hook.rb
http://github.com/edavis10/redmine_contracts/blob/master/lib/redmine_contracts/hooks/controller_issues_bulk_edit_before_save_hook.rb
HowTo add filters to existing controllers?
HowTo overwrite methods using alias_method_chain
instance methods
class methods
initialize
modules
转自:http://www.redmine.org/projects/redmine/wiki/Hooks
are executed one after another when the Redmine code reaches specific points in the code.
There is a list of valid hooks. But the
best way to find them is to just have a look into the code to find the place you would like to extend and search for a call to a hook nearby.
Additional methods to extend or replace Redmine code are:
Adding new methods
Using rails callbacks
Wrapping an existing method using
alias_method_chain
Fundamentals
As said above, when a hook is called, it executes the previously registered callback functions. These functions must accept exactly one parameter: a hash providing some context. This contexthash will always contain data necessary to do something useful in your callback function. In the case of controller of view hooks (see below), it contains at least the following information:
:controller => a reference to the current controller instance
:project => the current project (if set by the controller),
:request => the current request object with much information about the
current web request
Additionally, the hash will contain some data specific to the respective hook. This data is directly passed in the
call_hookcall you will find in Redmine's code.
Model hooks will not contain the default data as it does not apply here. These hooks will only contain the data passed in the
call_hookcall.
Types of hooks
Basically, there are currently three types of hooks:View hooks
Controller hooks
Model hooks
While both types use exactly the same API, there is a fundamentally different use-case for these.
View hooks
View hooks are executed while rendering the HTML code of a view. This allows the plugin author to insert some custom HTML code into some sensible places of the view. The return value of the callbackfunction transformed to a string and included into the view. A shortcut exists for rendering a single partial. See below for an example.
Controller hooks
Controller hooks are fewer in number than the view hooks. Often it is sufficient to use additionalfilters or to extend the model classes, as the controller actions should be (and are most of the time) very short and don't do much. There are however, some more lengthy actions which use hooks. To properly use those, one has to understand that the objects
in the context hash are only referenced. Thus, if you change an object in-place, the changes will be available in the actual controller (and later in the view). Consider the following simplified example:
Assume the following function is registered to the
do_somethinghook. See below for how to achieve that.
def do_something(context={ }) context[:issue].subject = "Nothing to fix" end
Now consider a controller action with the following code:
issue = Issue.find(1) # issue.subject is "Fix me" call_hook(:do_something, :issue => issue) # issue.subject is now "Nothing to fix"
As you can see, the hook function can change the
issueobject in-place. It is however not possible to completely replace an object as this would break the object references.
Model hooks
There are very few model hooks in Redmine. Most extensions in model code can be done by adding new methods or encapsulating existing ones by creatively applying the alias_method_chain pattern.The hooks can be used in the same way as the controller hooks.
Register functions to hooks
View hooks
The following example is going to hook a function into the hook view_issues_form_details_bottom. This can be used to add some additional fields to the issue edit form.
In your plugin (assumed to be named
my_plugin), create the following class in
lib/my_plugin/hooks.rb. You can register to multiple hooks in the same class.
module MyPlugin class Hooks < Redmine::Hook::ViewListener # This just renders the partial in # app/views/hooks/my_plugin/_view_issues_form_details_bottom.rhtml # The contents of the context hash is made available as local variables to the partial. # # Additional context fields # :issue => the issue this is edited # :f => the form object to create additional fields render_on :view_issues_form_details_bottom, :partial => 'hooks/my_plugin/view_issues_form_details_bottom' end end
The following class does exactly the same as the above but uses a method instead of the shorter
render_onhelper. The name of the method decides which callback it registers itself to.
module MyPlugin class Hooks < Redmine::Hook::ViewListener def view_issues_form_details_bottom(context={ }) # the controller parameter is part of the current params object # This will render the partial into a string and return it. context[:controller].send(:render_to_string, { :partial => "hooks/my_plugin/view_issues_form_details_bottom", :locals => context }) # Instead of the above statement, you could return any string generated # by your code. That string will be included into the view end end end
In your
init.rbmake sure to require the file with the hooks. It should look like this:
require 'redmine' # This is the important line. # It requires the file in lib/my_plugin/hooks.rb require_dependency 'my_plugin/hooks' Redmine::Plugin.register :my_plugin do [...] end
Controller and Model hooks
You can register methods to controller and model hooks the same way as the view hooks. Always remember to require the hook class in your init.rb. See an example below:
module MyPlugin class Hooks < Redmine::Hook::ViewListener def controller_issues_bulk_edit_before_save(context={ }) # set my_attribute on the issue to a default value if not set explictly context[:issue].my_attribute ||= "default" end end end
Additional examples
Some additional real-life examples can be found atView hooks
http://github.com/edavis10/redmine_contracts/blob/master/lib/redmine_contracts/hooks/view_layouts_base_html_head_hook.rb
http://github.com/edavis10/redmine_contracts/blob/master/lib/redmine_contracts/hooks/view_issues_show_details_bottom_hook.rb
http://github.com/edavis10/redmine_contracts/blob/master/lib/redmine_contracts/hooks/view_issues_form_details_bottom_hook.rb
http://github.com/edavis10/redmine_contracts/blob/master/lib/redmine_contracts/hooks/view_issues_bulk_edit_details_bottom_hook.rb
Helper hooks
http://github.com/edavis10/redmine_contracts/blob/master/lib/redmine_contracts/hooks/helper_issues_show_detail_after_setting_hook.rb
Controller hooks
http://github.com/edavis10/redmine_contracts/blob/master/lib/redmine_contracts/hooks/controller_timelog_available_criterias_hook.rb
http://github.com/edavis10/redmine_contracts/blob/master/lib/redmine_contracts/hooks/controller_issues_edit_before_save_hook.rb
http://github.com/edavis10/redmine_contracts/blob/master/lib/redmine_contracts/hooks/controller_issues_bulk_edit_before_save_hook.rb
TODO
HowTo add filters to existing controllers?HowTo overwrite methods using alias_method_chain
instance methods
class methods
initialize
modules
转自:http://www.redmine.org/projects/redmine/wiki/Hooks
相关文章推荐
- redmine 插件推荐系列 - Redmine Checklist plugin
- 安装Redmine DMSF Plugin
- 为Redmine安装敏捷插件(Redmine burndown chart plugin for Agile development)
- Redmine 安装并配置使用Agile plugin插件
- redmine安装redmine-wiki_graphviz_plugin插件
- 在Redmine使用Testlink Link plugin的语法详解
- Redmine 安装 Testlink Link Plugin
- eclipse maven plugin 插件 安装 和 配置
- 【jmeter-maven-plugin】二、高级配置之 -- 选择测试脚本
- Gradle Plugin User Guide 中文版
- Redmine与Gitlab深度集成
- 项目管理系统Redmine(v1.1.2)安装手记
- vue---vue2.x自定义plugin,给vue添加全局方法,原型上增加全局方法
- RedMine Email notifications configure for MS Exchange
- 【转载】解决使用tomcat7-maven-plugin插件时 “Application already exists at path”的问题
- Android.HowToDesignPluginArchitectureInAndroidApp
- [转]maven打包报错:Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.5:test
- Unable to load configuration. - bean - jar:file:/.../struts2-gxp-plugin-2.3.1.jar!/strut-plugin.xml
- Error:(2, 0) Plugin with id 'com.github.dcendents.android-maven' not found.
- Kettle Plugin插件开发指导