ChiliProject is not maintained anymore. Please be advised that there will be no more updates.

We do not recommend that you setup new ChiliProject instances and we urge all existing users to migrate their data to a maintained system, e.g. Redmine. We will provide a migration script later. In the meantime, you can use the instructions by Christian Daehn.

Using an existing helper from a plugin view

Added by Enrique García Cota at 2011-11-08 06:15 pm

Hi there,

I'm developing a plugin for which I'd like to include a model which acts_as_attachable . I had no trouble getting the model to work. My issue is in the views.

I'd like to use the link_to_attachments helper method in one of my views. But I get this error:

undefined method `link_to_attachments'

My model is called License. The controller is LicensesController. I've included AttachmentsHelper module on it like this:

class LicensesController < ApplicationController
  unloadable

  helper :attachments
  include AttachmentsHelper
  ...
end 

This doesn't throw an immediate error - the server can load and all the other pages work. But when I try to load Licenses#show it cracks.

In case it is useful, my init.rb looks like this:

require 'redmine'
require 'dispatcher'

Dispatcher.to_prepare :chiliproject_licenses do
  ...
  require_dependency 'chiliproject_licenses/patches/projects_controller_patch'
  ...
end

Redmine::Plugin.register :my_plugin do
...
end

Each patch I do has the same structure - this is an example with the ProjectsControllerPatch

require_dependency 'projects_controller'

module MyPlugin
  module Patches
    module ProjectsControllerPatch
      def self.included(base)
        unloadable
        # other stuff. Include classmethods when needed
      end
    end
  end
end

ProjectsController.send :include, MyPlugin::Patches::ProjectsControllerPatch

I've tried patching AttachmentController to mark it as unloadable, but that didn't work either.

Any help will be greatly appreciated.

Regards,

Enrique


Replies (5)

RE: Using an existing helper from a plugin view - Added by Eric Davis at 2011-11-08 08:20 pm

Can you post your view? We include all helpers into ApplicationController so it should be available to you without needing to use the helper in your controller (include is still needed if you are using the helper methods in the controller).

ProjectsController.send :include, MyPlugin::Patches::ProjectsControllerPatch

Move this and your require_dependency inside of your dispatcher block in init.rb. Having it in there will make the dispatcher re-run that code each time it reloads. You'll start seeing some really odd bugs and edge cases (I speak from experience here... hours spent in the debugger figuring out what happened...). Don't think it's causing this specific error though.

Eric Davis

RE: Using an existing helper from a plugin view - Added by Enrique García Cota at 2011-11-09 10:43 am

Hi Eric!

Can you post your view?

Certainly - it's nothing too fancy.

<h2><%= link_to t(:label_license_plural), licenses_path %> &#187; <%= link_to @license.title, @license %></h2>
<h4><%= format_date @license.date %><% if @license.authors.present? %> - <%= @license.authors %><% end %></h4>

<div class="wiki">
  <%= textilizable @license, :text %>
</div>

<%= render :partial => 'attachments' %>

And the attachments partial:

<% if @license.attachments.size > 0 %>
  <hr />
  <h3><%= t :label_attachment_plural %></h3>
  <%= link_to_attachments @license, :author => false %>
<% end %>

We include all helpers into ApplicationController so it should be available to you without needing to use the helper in your controller (include is still needed if you are using the helper methods in the controller).

Hmm. That's a difference, certainly. I see that on the current version the helper isn't included any more on any controller, but on my codebase it is.

That's a 2.x thing, right? Due to plugin dependencies, I'm stuck in 1.5.4 :/ .

Move this and your require_dependency inside of your dispatcher block in init.rb. Having it in there will make the dispatcher re-run that code each time it reloads. You'll start seeing some really odd bugs and edge cases (I speak from experience here... hours spent in the debugger figuring out what happened...). Don't think it's causing this specific error though.

Thanks for pointing this out. I'll make this change ASAP.

RE: Using an existing helper from a plugin view - Added by Enrique García Cota at 2011-11-09 11:33 am

I've not been able to solve this.

As I'm pressed on time, I decided to copy the link_to_attachments function to my LicensesHelper.

Yes, this is as despicable as it sounds. But it works! I see no other options.

If anyone has a better approach, or at least a direction to investigate, I'm all ears.

As a side note, I've moved the patch inclusion code to inside the dispatcher block inside init.rb file, as Eric said - no apparent changes, but if Eric says this can solve future bugs, I trust him.

Thanks a lot.

RE: Using an existing helper from a plugin view - Added by Enrique García Cota at 2011-11-10 10:59 am

Update on this - I have been able to solve it!

It turns out that Eric Davis' advice was the key. I had to move everything inside the dispatcher block.

... and do it also in my other plugins.

Once I moved the require_dependencies, patches, etc. there, the helper functions were available on the controllers!

Let me put the code here in case anyone finds this via google:

 # init.rb
require 'redmine'
require 'dispatcher'

Dispatcher.to_prepare :chiliproject_licenses do

  # repeat this structure for all patches
  require_dependency 'projects_controller'
  require_dependency 'chiliproject_licenses/patches/projects_controller_patch'
  ProjectsController.send :include, MyPlugin::Patches::ProjectsControllerPatch

  ...
end

Redmine::Plugin.register :my_plugin do
...
end
# lib/my_plugin/patches/projects_controller_patch.rb
module MyPlugin
  module Patches
    module ProjectsControllerPatch
      def self.included(base)
        unloadable
        # other stuff. Include classmethods when needed
      end
    end
  end
end

This is a bit of black magic. But I'm happy that I can remove the ugly hack I had before.

Eric, some time ago you asked in your blog about the difficulties one finds when implementing a plugin. The dispatchery stuff is certainly one of the highlights.

Thanks, consider this one closed!

RE: Using an existing helper from a plugin view - Added by Eric Davis at 2011-11-10 06:00 pm

Enrique García Cota wrote:

Update on this - I have been able to solve it!

It turns out that Eric Davis' advice was the key. I had to move everything inside the dispatcher block.

AH, I didn't even think about that. Yea, if another plugin loaded the controller then it might not have gotten your patch.

Eric, some time ago you asked in your blog about the difficulties one finds when implementing a plugin. The dispatchery stuff is certainly one of the highlights.

Yea I wrote a little about it on theadmin.org but it's a deep topic. I've been using this newer pattern on all my recent plugins. Hopefully over time it will become standard as people copy my code for their own plugins (#1 reason I share my unreleased plugins). Guess I should clean up and release my plugin development scripts too, they automate a lot of this.

Happy you found the problem.

Eric Davis

(1-5/5)