简体   繁体   English

Rails:扩展现有代码

[英]Rails: Extending existing code

I'm a PHP developer and have worked extensively with Laravel. 我是一名PHP开发人员,并且与Laravel进行了广泛的合作。 However, I currently need to make small extension to Redmine (a Ruby Issue Tracker Tool) for work. 但是,我目前需要对Redmine(Ruby问题跟踪工具)进行小扩展才能工作。

I'm brand new to Ruby and Rails, so I'm simultaneously trying to get up to speed on the language and the framework. 我是Ruby和Rails的新手,所以我同时尝试加快语言和框架的速度。

In general, I'll need to make some migrations which add a few columns to Redmines existing table. 通常,我需要进行一些迁移,从而向Redmines现有表中添加几列。 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. 然后,当在Redmine中触发各种方法(记录时间条目,删除条目,创建项目等)时,我将需要进行几次API调用,并在所述列中插入/更新返回的数据。

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? 1)因为我要扩展现有的Rails应用程序,所以我应该创建一个插件吗? or a Gem? 还是宝石? It seems Redmine has a 'plugin generator' that provides some boiler plate 看来Redmine有一个“插件生成器”,可以提供一些样板

2) I'll need to hook into existing Save and Update events in Redmine. 2)我需要了解Redmine中现有的Save和Update事件。 From what I understand, you're not meant to override existing Controllers and Models. 据我了解,您并不是要覆盖现有的Controllers和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 我发现这很有帮助: 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 更新时合并问题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 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: 在原始代码(控制器,视图,帮助器,模型)中找到nessecary钩子,它们看起来像这样:

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) 如果找不到合适的钩子,则可以添加自己的钩子(仍然需要修改原始代码)或在Redmine页面中添加问题(将需要等待很长时间)

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 your_plugin/init.rb

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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