gpt4 book ai didi

ruby - 从外部 gem 扩充模型

转载 作者:数据小太阳 更新时间:2023-10-29 07:03:02 25 4
gpt4 key购买 nike

我正在使用 refinerycms在我们的站点让技术人员较少的更新内容。在 gem 中,它们有一个 Page 类,用于映射站点上的每个顶级页面。我想在此 Page 类上使用 acts_as_taggable gem。现在我可以将 acts_as_taggle 声明直接添加到 page.rb 文件中,但是我必须维护一个单独的 git 存储库来跟踪我的版本和官方版本之间的差异。

基于 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

config/initializers/pants.rb

require 'page_extensions'

Page.send :include, Pants::Extensions::Page

app/views/layouts/application.html.erb

...
Tags: <%= @page.tag_list %>

我第一次从服务器请求页面时,它正确地输出了页面上的所有标签。但是,如果我点击刷新,则会得到一个 NoMethodError 指示 tag_list 未定义。

我是 Rails 的新手,所以也许我的假设是错误的,但我预计对 Page.send 的调用会对 Page 类而不是类的特定实例进行永久更改。那么我如何在每次请求时将 acts_as_taggable 添加到 Page 类?

最佳答案

您需要将 module_eval 代码放入 config.to_prepare do block 中。执行此操作最简单的地方是在 config/application.rb 中或创建一个引擎。代码是相同的,除了它在您每次运行网站时执行,而不仅仅是第一次(这尤其适用于开发模式)和仅在初始化过程(也称为需要文件)之前执行到 config.before_initialize do block 。

config.to_prepare 之所以重要,是因为在开发模式下,代码会在每次请求时重新加载,但初始化程序通常不会。这意味着您正在运行 module_eval 的 Page 只会让 module_eval 运行一次,但会在每次请求时重新加载自身。 config.to_prepare 是一个每次都运行的 Rails Hook ,为这种情况提供了极大的便利。

config/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,那么您可以在 Refinery 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 代码。

希望对你有帮助

关于ruby - 从外部 gem 扩充模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4018701/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com