环境
红宝石 1.9.3p194(2012-04-20 修订版 35410)[x86_64-darwin10.8.0];导轨 3.2.6;OSX 10.6.8;设计(2.0.4);前红地毯(1.0.0)
客观的
我们需要在 Forem 安装 (gem) 中部署额外的订单控制。很可能,我们还想声明更多的模型属性;并且假设我们会这样做:
- 通过将命名范围附加到基础 Forem 模型;
- 或通过覆盖底层模型。
问题
我们会怎么做呢?
环境
红宝石 1.9.3p194(2012-04-20 修订版 35410)[x86_64-darwin10.8.0];导轨 3.2.6;OSX 10.6.8;设计(2.0.4);前红地毯(1.0.0)
客观的
我们需要在 Forem 安装 (gem) 中部署额外的订单控制。很可能,我们还想声明更多的模型属性;并且假设我们会这样做:
问题
我们会怎么做呢?
答案 ― 如何解释装饰器中的异常执行
一位同事将我的请求指向现有的 Forem 文档(Forem:Extended Classes),它可以很好地回答这个问题,但以下非常可能的例外情况除外:
直到现在我还没有做出回应的一个原因是,尝试遵循推荐的模式最初并未成功,因为一些底层代码(少数例外)引用了模型类,而没有将它们作为 Forem 引擎的前缀。因此,起初,这条路线似乎根本行不通;并且,(我仍然不确定所有的后果是什么),因此似乎有必要使用修订后的引用来覆盖底层方法(它没有以“Forem::”开头的引用),形式为“Forem ::ModelName”(与“ModelName”相对)。
正如 Github 上的 Forem 文档页面所示:
“Forem 的所有业务逻辑(模型、控制器、助手等)都可以使用标准 Ruby 习惯用法轻松扩展/覆盖以满足您的确切要求。
在应用程序或扩展中包含此类更改的标准做法是创建目录 app/decorators。将文件放在相关的app/decorators/models或app/decorators/controllers目录中,并将_decorator附加到原始类名。”
换句话说,要在控制器进程中分配更多的接口值,您必须将装饰器添加到相应的目录中,Ruby 将从该目录中找到并覆盖底层进程:
来自原始 Forem 源的控制器位于 /forem/app/ controllers /forem/admin/ groups_controller.rb,因此被 /your_project_name/app/ decorators / controllers /forem/admin/ groups_controller_decorator.rb 覆盖。
在下面的代码片段中(来自这个文件),您会经常调用“index_original”,并将原始索引方法别名为“index_original”:
Forem::Admin::GroupsController.class_eval do
alias_method :index_original, :index unless method_defined?(:index_original)
def index
@h_title_of_page = t('h_title2_forum_admin_groups_index')
@h_description2 = t('h_description2_forums')
index_original
end
然而,这不起作用,因为 Forem 控制器的底层索引方法进行了以下分配:
@groups = Group.all
因此,当您在装饰器中调用 index_original 时,对“Group.all”的调用会引发错误,这显然是因为在没有前缀它属于 Forem 模块的情况下无法识别祖先:
@groups = Forem::Group.all
因此,要在您的装饰器中解决此问题,您必须采用以下方法(# index_original 被注释掉以指示必须替换它的内容):
def index
@h_title_of_page = t('h_title2_forum_admin_groups_index')
@h_description2 = t('h_description2_forums')
# index_original
@groups = Forem::Group.all # @groups = Group.all ERROR
end
注意语句“@groups = Forem::Group.all”是祖先索引方法的唯一语句;因此将固定语句带入您的装饰器就是将整个方法代码带入您自己的装饰器。这修复了异常执行,仅因为对祖先索引方法的完全覆盖本身足以消除对未以 Forem:: 开头的模型的任何进一步调用。如果没有对底层类进行任何进一步的调用,则同样必须将这些方法带入您的装饰器中。
因此,为了解决您自己(依赖)项目中的所有此类潜在异常,您必须从 Github 下载 Forem 源代码,并研究您必须使用别名的底层方法是否引用了他们自己的模型(带/不带前缀)与“前::”:
希望在未来,Ruby 能够识别此类引用,和/或 Forem 作者将在引用其内部的前言(即使代码显然应该在Forem 开发环境中运行良好)。
好吧...我建议1。(诚然,因为我确实对此有答案;-))
把它放到你的 autoload_paths 中:
extend_it.rb
:
require 'active_support/concern'
module ExtendIt
extend ActiveSupport::Concern
included do
scope :extension_scope, where(:name => "Mr. X")
end
module ClassMethods
end
end
在初始化程序中是这样的:
extend_it.rb
:
AnyClass.send :include, ExtendIt
其中当然AnyClass
是您的目标课程之一。更多阅读可以在这里找到:http: //api.rubyonrails.org/classes/ActiveSupport/Concern.html