Trouble understanding Redmine callbacks
I'm sorry to bother you on such a small issue, since there is already a lot of information available on the subject, but I have some trouble understanding how redmine plugins work. I would like to develop lots of changes in Redmine, but I'd rather not touch the core.
So I'm thinking about developping a plugin, containing new methods in controllers, new items in models, and new views (which apparently can easily override the existing ones).
But I don't get how do I implement those changes since new controllers and models won't override the Redmine ones. I think I have to use Redmine callbacks, but I don't understand how they work (I'm French and I have some trouble with the meaning of the terms "hooks" and "callbacks" in this context).
Basically, how should I do to use new methods, along with the existing ones, without touching the Redmine core (and the same for models) ?
Thanks a lot.
Is there a documented method to add functionnalities to controllers, helpers and models without overriding the original ones? I took a look at some existing plugins as it is said in the plugin_internals documentation, but I don't understand how it works.
Basically, without touching the original files, what do I have to do to :
- add an instance variable in the projects controller for instance?
- add a new method in the projects helper?
- add some features to the projects model?
Some informations can be found on the plugin_internals page as you said.You should make a distinction between the 2 terms you mention :
- callbacks are a Rails concept : it allows you to do things before or after some event occur, such as save. I want to modify something on my object before a Project is saved to the DB, ok, I use
- hooks are a Redmine concept : it litterally means
crochetin French. It allows you to insert code at some specific points of the process. View hooks allow you to add view stuff, while controller or model hook allow you to add code or modify redmine's behavior on the fly
- add an instance variable in the project controller :
in init.rb: require 'my_new_instance_variable' in lib/my_new_instance_variable.rb: require_dependency 'projects_controller' class ProjectsController @blah = "toh" end
- add a new method in the project helper :
in init.rb require 'my_new_method_in_project_helper' in lib/my_new_method_in_project_helper.rb: require_depencendy 'projects_helper' module ProjectsHelper def blahblah "bleh" end end
As I said before, Eric would probably tell me I should do modules and then include them on original classes. But this is ok to me :)
There's just one thing about initialization : what I said might not work correctly if you work in development mode. So instead of :
You should probably wrap your patches into a "to_prepare" block and use "require_dependency" so that Engines reloads it the right way :
config.to_prepare do require_dependency 'blah' end
Hi Jean-Baptiste and thank you for your answer, it helped me quite a lot.
Still, I have a few questions regarding plugins development :
First, how does it work with models? Is it the same as controllers and helpers? Since models are linked to the database structure, I assume there must be some particularities? I had my migrations work fine by using rake db:migrate_plugins, but how do I implement methods and variables to existing models?
Then, it seems that the changes that I've made with my controllers and helpers (well, actually only one of each, since I'm currently trying to understand how it works) work properly when I launch the Webrick (I've made changes on the welcome index page), but if I refresh or navigate through the app and try to reach back the home page, I get error messages, telling me that all of my new instance variables and methods don't actually exist.
Could you help me out?
The same goes for models. You should read articles about common Rails model attributes/methods if you want to understand how it works. Some methods are auto-generated by active record if you have the corresponding column in your database.
About your errors, try to use "require_dependency" instead of "require" and see if it solves your problem. If not, you should post your exact error message here, somebody might be able to help you.