Rails: 扩展现有代码
Rails: Extending existing code
我是一名 PHP 开发人员并且与 Laravel 有过广泛的合作。但是,我目前需要对 Redmine(一个 Ruby 问题跟踪器工具)进行小的扩展。
我是 Ruby 和 Rails 的新手,所以我同时也在尝试加快语言和框架的速度。
一般来说,我需要进行一些迁移,将一些列添加到现有的 Redmines table。然后,当在 Redmine 中触发各种方法(记录时间条目、删除条目、创建项目等)时,我需要进行几次 API 调用,并 insert/update 在所述列中返回数据。
不是很复杂,但是我在开始的时候想知道一些事情:
1) 因为我正在扩展现有的 Rails 应用程序,所以我应该创建一个插件吗?还是 Gem?似乎 Redmine 有一个 'plugin generator' 提供了一些样板
2) 我需要连接到 Redmine 中现有的保存和更新事件。据我了解,您并不是要覆盖现有的控制器和模型。其中,哪些方法用于为现有应用程序实现附加功能?
我找到了这篇有用的文章:http://www.redmine.org/projects/redmine/wiki/Plugin_Internals
但是,它提到:
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.
据推测,您不会直接向原始来源添加方法?我注意到他使用模块来实现这一点,但不确定它们究竟是如何工作的。
是的,不推荐原始源修改,因为:
- 更新Redmine时合并问题
- 其他插件的问题
要添加新方法或修改现有方法,您必须创建控制器、模型或助手补丁:
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
并添加
require 'path/to/your/issues_controller_patch'
到your_plugin/init.rb
此外,如果你想在原始代码中间调用你的代码,你必须使用钩子。在原始代码(controller、view、helper、model)中找到必要的钩子,它们看起来是这样的:
call_hook(:controller_account_success_authentication_after, {:user => user})
如果没有找到合适的hook,可以自己添加(还是要修改原代码)或者在Redmine页面添加issue(要等很久)
要使用钩子,请添加钩子侦听器,例如:
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
并添加
require 'path/to/your/hook'
到your_plugin/init.rb
我是一名 PHP 开发人员并且与 Laravel 有过广泛的合作。但是,我目前需要对 Redmine(一个 Ruby 问题跟踪器工具)进行小的扩展。
我是 Ruby 和 Rails 的新手,所以我同时也在尝试加快语言和框架的速度。
一般来说,我需要进行一些迁移,将一些列添加到现有的 Redmines table。然后,当在 Redmine 中触发各种方法(记录时间条目、删除条目、创建项目等)时,我需要进行几次 API 调用,并 insert/update 在所述列中返回数据。
不是很复杂,但是我在开始的时候想知道一些事情:
1) 因为我正在扩展现有的 Rails 应用程序,所以我应该创建一个插件吗?还是 Gem?似乎 Redmine 有一个 'plugin generator' 提供了一些样板
2) 我需要连接到 Redmine 中现有的保存和更新事件。据我了解,您并不是要覆盖现有的控制器和模型。其中,哪些方法用于为现有应用程序实现附加功能?
我找到了这篇有用的文章:http://www.redmine.org/projects/redmine/wiki/Plugin_Internals
但是,它提到:
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.
据推测,您不会直接向原始来源添加方法?我注意到他使用模块来实现这一点,但不确定它们究竟是如何工作的。
是的,不推荐原始源修改,因为:
- 更新Redmine时合并问题
- 其他插件的问题
要添加新方法或修改现有方法,您必须创建控制器、模型或助手补丁:
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
并添加
require 'path/to/your/issues_controller_patch'
到your_plugin/init.rb
此外,如果你想在原始代码中间调用你的代码,你必须使用钩子。在原始代码(controller、view、helper、model)中找到必要的钩子,它们看起来是这样的:
call_hook(:controller_account_success_authentication_after, {:user => user})
如果没有找到合适的hook,可以自己添加(还是要修改原代码)或者在Redmine页面添加issue(要等很久)
要使用钩子,请添加钩子侦听器,例如:
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
并添加
require 'path/to/your/hook'
到your_plugin/init.rb