环境
ruby 1.9.3p194(2012-04-20修订版35410)[x86_64-darwin10.8.0]; Rails 3.2.6; OSX 10.6.8;设计(2.0.4); forem-redcarpet(1.0.0)
目的
我们需要在Forem安装(gem)中部署额外的订单控制。可能,我们还想要声明更多的模型属性;而且,我们也会这样做:
问题
我们如何做 ?
答案 0 :(得分:1)
答案 - 如何解决装饰品中的异常执行问题
一位同事将我的请求指向现有的Forem文档( Forem: Extending Classes ),会很好地回答这个问题,除了以下内容,非常可能的例外:
我之前没有回应的一个原因是,尝试遵循推荐的模式最初并没有成功,因为一些底层代码(少数例外)引用了模型类而没有预先设置它们属于Forem引擎。因此,起初,似乎这条路线根本不起作用;而且,(我仍然不确定所有后果是什么),因此似乎有必要在表格中覆盖基础方法(不以“Forem ::”为前缀)和修订后的引用,“Forem :: ModelName”(与“ModelName”相对)。
正如Github的Forem文档页面所示:
“所有Forem的业务逻辑(模型,控制器,帮助器等)都可以使用标准的Ruby习语轻松扩展/覆盖,以满足您的确切需求。
在您的应用程序或扩展程序中包含此类更改的标准做法是创建目录应用程序/装饰器。将文件放在相关的 app / decorators / models 或 app / decorators / controllers 目录, _decorator 附加到原始类名。“
换句话说,要在控制器进程中分配更多接口值,您必须将一个装饰器添加到Ruby将找到的相应目录并覆盖基础进程:
来自原始Forem源的控制器驻留为/ forem / app / 控制器 / forem / admin / groups_controller.rb ,因此被/ your_project_name / app /覆盖装饰器 / 控制器 / 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源,并研究你必须使用的基础方法别名参考他们自己的模型,有/没有用“Forem ::”作为前缀:
希望将来,Ruby要么能识别这样的引用,要么/或者Forem作者会在他们的内部开头提到他们的引用(即使代码显然应该运行得很好,否则 in Forem发展环境)。
答案 1 :(得分:0)
嗯......我建议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