简体   繁体   中英

Rails: Extending existing code

I'm a PHP developer and have worked extensively with Laravel. However, I currently need to make small extension to Redmine (a Ruby Issue Tracker Tool) for work.

I'm brand new to Ruby and Rails, so I'm simultaneously trying to get up to speed on the language and the framework.

In general, I'll need to make some migrations which add a few columns to Redmines existing table. Then when various methods are trigged in Redmine (logging time entries, deleting entries, creating projects, etc), I'll need to make a couple API calls, and insert/update the returned data in said columns.

So not terribly complicated, however I'm wondering a few things as I get off the ground:

1) Because I'm extending an existing Rails app, should I be creating a Plugin? or a Gem? It seems Redmine has a 'plugin generator' that provides some boiler plate

2) I'll need to hook into existing Save and Update events in Redmine. From what I understand, you're not meant to override existing Controllers and Models. In that, what methods are used for implementing additional functionality to an existing application?

I found this helpful piece: http://www.redmine.org/projects/redmine/wiki/Plugin_Internals

However, it mentions:

As explained above: you rarely want to override a model/controller. Instead you should either:

    1) add new methods to a model/controller or
    2) wrap an existing method.

Presumably, you wouldn't be adding methods directly to the original source? I notice he uses Modules to implement this, but unsure of exactly how they work.

Yes, original source modification is not recomended because of:

  • Merge problems when You are updates Redmine
  • Problems with other plugins

For add new or modify existing methods You must create controller, model or helper patch:

require_dependency 'issues_controller'

module IssuesControllerPatch
    def self.included(base) # :nodoc:
    base.send(:include, InstanceMethods)

    base.class_eval do
       unloadable
       alias_method_chain :some_method, :your_action # modify some_method method by adding your_action action
    end

    module InstanceMethods

        # modified some_method
        # You can call original method before or after
        # even in the middle of your actions
        # or not to call to all
        def some_method_with_your_action # modified some_method
          do_something_before # your actions before
          some_method_with_your_action # call original some_method if needed
          do_something_after # your actions after
        end

        # new method
        def your_method
          do_something
        end

    end
end

IssuesController.send :include, IssuesControllerPatch

And add

require 'path/to/your/issues_controller_patch'

to your_plugin/init.rb


Also, if You want call your code in the middle of original code, You must use hooks. Find nessecary hook in original code (controller, view, helper, model), they looks like this:

call_hook(:controller_account_success_authentication_after, {:user => user})

If not found suitable hook, You can add your own (still have modify original code) or add issue at Redmine page (will have to wait a long)

To use hooks, add hook listener like:

class IssuesControllerHookListener < Redmine::Hook::ViewListener

      # use view hook - add path/to/your/view.html.erb redmine issues list
      # position of your additions depends of used hook position
      # view_issues_index_bottom is hook name
      # :partial is parameter, value of that is your view
      render_on :view_issues_index_bottom, :partial => 'path/to/your/view'

      # use controller hook - call your code inside original
      # controller_issues_ready_before_index is hook name, method must be named same
      # context here is parameters come from hook calling method
      # You can use it for your own purposes
      def controller_issues_ready_before_index(context = {})
        if context[:some_context_param] == some_value
           do_something
        end
      end

end

And add

require 'path/to/your/hook'

to your_plugin/init.rb

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM