Rails 3 中一些最大的变化涉及到 Rails 对插件行为的预期。
如果您的插件有依赖关系,请将其打包成 gem,并让用户使用 Gemfile 进行安装。这将确保 Bundler 能够正确计算与其他用户应用程序的依赖关系。
如果您需要覆盖 ActionController、ActiveRecord 或其他 Rails 框架,请先加载它们,然后再覆盖。不要假设 Rails 会在“正确”的时间加载您的 gem 插件,而要假设用户会尽早加载您的插件。
这让您有机会更早地挂入初始化过程,但也意味着您应该明确加载所需的依赖项。
# in your_lib.rb
require "active_record"
require "your_lib/extensions"
ActiveRecord::Base.class_eval { include YourLib::Extensions }
即使您可以预期您的 gem 会很早加载,您仍然可能需要挂入初始化过程的后期。如果需要,请继承自 Rails::Railties。在 Railtie 中,您可以声明一个 Rails 在运行 Rakefile 时应执行的块,指定初始化块,向通知系统添加订阅者,并指定要加载的生成器。
class TestingFu < Rails::Railtie
# This creates a config.my_plugin in the user's Application
railtie_name :testing_fu
rake_task do
load "testing_fu/tasks.rake"
end
# specify the default generators for test frameworks
config.generators.test_framework :testing_fu
# you can also specify :before or :after to ensure that
# your initializer block runs before or after another
# initializer block
initializer :setup_my_plugin do |app|
# in here, I have access to the user's application,
# which gives me access to app.config
end
end
请确保加载您打算扩展的任何 railtie。例如,如果您想在 ActionController 中定义的初始化程序之前运行一个初始化程序,请加载 “action_controller/railtie”
话虽如此,如果您的代码不需要挂入 Rails 生命周期中的任何部分,请不要使用 Railtie。如果可能,只需创建一个标准的 Ruby 库,加载您需要覆盖的 Rails 部分。
插件(vendor/plugins)中的引擎的工作方式与 Rails 2 相同。在 gem 中,您需要提供一个 Rails::Engine 子类
# lib/my_engine.rb
module MyEngine
class Engine < ::Rails::Engine
engine_name :my_engine
end
end
将您的 app 目录放在 lib 目录旁边,Rails 就会找到它。您可以在此处一次性阅读关于 Railte、Engine、Plugin 和 Application 的文档:https://gist.github.com/af7e572c2dc973add221
为了使此过程更容易,Engine Yard 搭建了 railsplugins.org。如果您是插件作者,请将您的插件提交到该网站。您可以告诉用户您的插件是否预期可以在 Rails 3 上运行,用户是否可以在线程安全模式下运行它们,以及它们是否可以在 JRuby 上运行。
一旦您将插件发布到那里,用户就可以表示他们同意您的插件可以运行或不同意,并附带有关出了什么问题的评论。您可以回复任何此类评论,如果用户只是犯了个错误,他可以改变主意。当您提交一个新版本时,该网站会创建一个全新的页面,因此关于旧版本不起作用的评论不会干扰当前版本(如果用户愿意,仍然可以访问旧版本)。
如果我们能做好这一点,Rails 社区将对 Rails 3 上什么有效,什么无效有一个清晰的认识。放手去做吧!