0

Good evening everyone! I am stuck with something about a plugin of mine, and I would really appreciate some advice.

The problem

I wrote a simple plugin, that modifies the form for creating a new project by adding new fieldset with some checkboxes. I wrote all of the login in my files in my plugin directory. So far, so good. Everything works fine, except that when it came to sending the files to my colleagues, there was something they didn't like. It appears that they are not too fond of the idea of modifying the core files a bit in order to get things working, because things may go messed up when they update the version of Redmine. I've managed to reduce the code injected in the core files to 3 lines only (3 lines, ikr!!), but that's as far as I could go.

projects_controller.rb

selected_tasks = params[:checkListItems].collect {|id| id.to_i}
call_hook(:add_tasks_after_project_save, { :selected_ids => selected_tasks, :project => @project})

And in project's form /views/projects/_form.html.erb

<%= call_hook(:append_check_list_tasks, { :project => @project }) %>

I wont be surprised if there is a way to remove the code I use in projects_controller.rb and use only the one in my files, but I'm not so sure about the hook I placed inside the form.html.

The question in short

IS there a way to get my plugin working the way it is like now, but without having to modify the core files of Redmine?

Robert
  • 10,403
  • 14
  • 67
  • 117
Artamiel
  • 3,652
  • 2
  • 19
  • 24
  • Where you put your code exactly (in controller, in view)? Provide please exactly line. – gotva Mar 27 '14 at 20:09
  • The first 2 lines I posted are put in my controller as I pointed out. In "create" method. The second paragraph of code is in my view (_form.html.erb) and its being displayed only when a project is created. – Artamiel Mar 27 '14 at 20:15

1 Answers1

1

1 How to patch form.

You can use a hook from the core. Here is hook list

Or if you need to patch a view where no hooks you can use gem deface. Please see this commit

2 How to patch controller. It is a problem, because you can't use before_filter or alias_method_chain in this case - Project is initialized inside method.

I suppose that you would like to do some action after (or before) project is created and you need to know selected_tasks. My idea is to follow standart workflow and pass these values to model through new virtual attr_writer.

What I think you should do:

  • add attr_writer to model project
  • define new safe_attribute smth like this (I think Redmine won't allow assign unsafed attributes, see this)
  • add before_create or after_create callback to process accepted params through attr_writer.

PS of course it is just a plan and I can't check if it works :)

Plan B

There is a new (simpler) idea how to patch. Code for patching can be placed to after_filter where you can check if @project has been created successfully and process selected_tasks.

You can patch core from pluging adding after_filter this way. Do not forget to include your patch to controller see this

gotva
  • 5,919
  • 2
  • 25
  • 35
  • I know its a bit late, I had not much of a free time lately. I came to a conclusion that modifying core template by a plugin it's not such a big deal, and rather possible. But... as for a controller, that's may not be possible, or at least I still haven't found a way. And since, you only tried to help, I'm gonna accept that as a correct answer. – Artamiel Apr 04 '14 at 18:11
  • I think you should not accept answer as correct because it can confuse others in future (for example you can do only +1 as useful but not a solution for you). If you say what exactly you would like to do with `selected_tasks` I can improve my answer with more details and examples – gotva Apr 04 '14 at 18:26
  • I have a separate(new) table with some records, which I display on project form template. When the user adds new project, he can choose zero or more(all) of those records with checkbox(that's what selected_tasks stands for) and then each of the selected records are being added as "Issues" for the newly created project. And in order to create those Issues I need a reference to the @project variable in my plugin controller, but without having to modify core plugin controller. – Artamiel Apr 04 '14 at 20:11
  • I have another simpler idea. Try to add `after_filter :add_selected_issues, :only => [:create]` to `projects_controller`. In the method `add_selected_issues` check if `@project.persisted?` then you can create predefined selected issues in this new project. – gotva Apr 04 '14 at 20:30
  • I already have a working version of this. And yes, your idea sounds good as well, I might modify my own version according to this. But, what you are suggesting requires to modify the Core file of redmine, and that is what I really am trying to escape. I need to find a way to use a reference of the newly create project as variable, by only using the logic in my own plugin. – Artamiel Apr 05 '14 at 05:11
  • I do understand that ALL code must be in plugin :). But if you manage to write code to different method before/after method it means that Ruby allows you to add this code from plugin "on the fly". Please see updated answe with example how to patch controller. – gotva Apr 05 '14 at 06:47