题
我使用 refinerycms 在我们的网站,让更少的技术人员更新内容。宝石里面,他们有每个顶级页面映射网站上的Page类。我想用acts_as_taggable宝石在这个Page类。现在我可以直接添加acts_as_taggle声明的page.rb文件,但后来我不得不保持一个单独的混帐回购协议来跟踪我的版本和正式发布之间的差异。
根据这里SO我一些其它问题,创造了一个初始化和延伸像这样:
LIB / page_extensions.rb:
module Pants
module Extensions
module Page
module ClassMethods
def add_taggable
acts_as_taggable
end
end
def self.included(base)
base.extend(ClassMethods).add_taggable
end
end
end
end
配置/初始化/ pants.rb
require 'page_extensions'
Page.send :include, Pants::Extensions::Page
应用程序/视图/布局/ application.html.erb
...
Tags: <%= @page.tag_list %>
我第一次从服务器请求页面它正确地输出所有的页面上的标签。但是,如果我打刷新我,而不是得到一个NoMethodError
表明tag_list不确定。
我是新来的铁轨所以也许我的假设是错误的,但我预计Page.send该呼叫将使到Page类,而不是类的特定实例的永久性改变。所以,我怎么会得到加Page类对每个请求的acts_as_taggable?
解决方案
您将需要把你的module_eval代码放到一个config.to_prepare do
块。要做到这一点,最简单的地方是在config/application.rb
或创建一个引擎。该代码是相同的,除了它执行每次运行的网站不只是第一次(其特别适用于开发模式)和代码仅初始化过程之前执行(又名需要文件)转换成config.before_initialize do
块时间。
之所以说config.to_prepare
重要的是,因为在开发模式中,代码被重新加载在每次请求但初始化一般不。这意味着Page
,您正在运行一个module_eval,只会有一次module_eval运行,但将自动重新加载每个请求。 config.to_prepare
是运行每一次对这样的情况下,提供了极大的方便一个Rails钩。
配置/ application.rb中接近
class Application < Rails::Application
# ... other stuff ...
config.before_initialize do
require 'page_extensions'
end
config.to_prepare do
Page.send :include, Pants::Extensions::Page
end
end
发动机的方法
如果你不想修改config/application.rb
那么你就可以在炼油厂CMS,创建vendor/engines/add_page_extensions/lib/add_page_extensions.rb
这将是这样的:
require 'refinery'
module Refinery
module AddPageExtensions
class Engine < Rails::Engine
config.before_initialize do
require 'page_extensions'
end
config.to_prepare do
Page.send :include, Pants::Extensions::Page
end
end
end
end
如果您使用的发动机接近你还需要创建vendor/engines/add_page_extensions/add_page_extensions.gemspec
它应该包含一个简单gemspec:
Gem::Specification.new do |s|
s.name = 'add_page_extensions'
s.require_paths = %w(lib)
s.version = 1.0
s.files = Dir["lib/**/*"]
end
然后在你的Gemfile
加入这一行:
gem 'add_page_extensions', :path => 'vendor/engines'
如果你走在引擎的方式,你可能会想要把所有的逻辑引擎的lib
目录包括Pants::Extensions::Page
代码中。
希望这有助于