Project

General

Profile

Plugin Internals » History » Version 1

Mischa The Evil, 2009-03-30 23:48
Initial version of the page

1 1 Mischa The Evil
h1. Plugin Internals
2
3
{{>toc}}
4
5
This page will be used as a central place to store information about plugin-development in Redmine.
6
7
h2. Overriding the Redmine Core
8
9
You can override views but not controllers or models in Redmine. Here's how Redmine/Rails works if you try to override a controller (or model) and a view for a fictional plugin @MyPlugin@:
10
11
h3. Controllers (or models)
12
13
# Rails bootstraps and loads all it's framework
14
# Rails starts to load code in the plugins
15
# Rails finds @IssueController@ in MyPlugin and see it defines a @show@ action
16
# Rails loads all the other plugins
17
# Rails then loads the application from _../app_
18
# Rails finds @IssueController@ again and see it also defines a @show@ action
19
# Rails (or rather Ruby) overwrites the @show@ action from the plugin with the one from _../app_
20
# Rails finishes loading and serves up requests
21
22
h3. Views
23
24
View loading is very similar but with one small difference (because of Redmine's patch to Engines)
25
26
# Rails bootstraps and loads all it's framework
27
# Rails starts to load code in the plugins
28
# Rails finds a views directory in _../vendor/plugins/my_plugin/app/views_ and *pre-pends* it to the views path
29
# Rails loads all the other plugins
30
# Rails then loads the application from _../app_
31
# Rails finishes loading and serves up requests
32
# Request comes in, and a view needs to be rendered
33
# Rails looks for a matching template and loads the plugin's template since it was *pre-pended* to the views path
34
# Rails renders the plugins'view
35
36
Due to the fact that it is so easy to extend models and controllers the Ruby way (via including modules), Redmine shouldn't (and doesn't) maintain an API for overriding the core's models and/or controllers. Views on the other hand are tricky (because of Rails magic) so an API for overriding them is way more useful (and thus implemented in Redmine).
37
38
To override an existing Redmine Core view just create a view file named exactly after the one in _../app/views/_ and Redmine will use it. For example to override the project index page add a file to _../vendor/plugins/my_plugin/app/views/projects/index.rhtml_.
39
40
h2. Extending the Redmine Core
41
42
As explained above: you rarely want to override a model/controller. Instead you should either:
43
* add new methods to a model/controller or 
44
* wrap an existing method.
45
46
h3. Adding a new method
47
48
A quick example of *adding a new method* can be found on Eric Davis' "Budget plugin":http://github.com/edavis10/redmine-budget-plugin/blob/5076b1c88b57c2068aa92cdf694769dbd22d061a/lib/issue_patch.rb. Here he added a new method to Issue called @deliverable_subject@ and also declared a relationship.
49
50
h3. Wrapping an existing method
51
52
A quick example of *wrapping an existing method* can be found on Eric Davis' "Rate plugin":http://github.com/edavis10/redmine_rate/blob/4666ddb10e1061ca3ef362735d0d264676b99024/lib/rate_users_helper_patch.rb. Here he uses the @alias_method_chain@ to hook into the UsersHelper and wrap the @user_settings_tabs@ method. So when the Redmine Core calls @user_settings_tabs@ the codepath looks like:
53
54
# Redmine Core calls @UsersHelper#user_settings_tabs@ 
55
# @UsersHelper#user_settings_tabs@ runs (which is actually @UsersHelper#user_settings_tabs_with_rate_tab@)
56
# @UsersHelper#user_settings_tabs_with_rate_tab@ calls the original @UsersHelper#user_settings_tabs@ (renamed to @UsersHelper#user_settings_tabs_without_rate_tab@)
57
# The result then has a new Hash added to it
58
# @UsersHelper#user_settings_tabs_with_rate_tab@ returns the combined result to the Redmine core, which is then rendered
59
60
"@alias_method_chain@":http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Module.html#M001188 is a pretty advanced method but it's also really powerful.
61
62
h2. References
63
64
* http://www.redmine.org/boards/3/topics/show/4283
65
* http://www.redmine.org/boards/3/topics/show/4095