更新:我已根据此答案添加了一篇博文,但更详细:http://thoughtsincomputation.com/posts/coding-an-acts_as-gem-for-rails-3
--
我不知道还有其他教程来源,但这里有一些一般提示。
Rails 3 使用了一个非常有用的功能,称为 Railtie - 请参阅 http://api.rubyonrails.org/classes/Rails/Railtie.html。
所以,如果我要实现acts_as_* gem,我会从那里开始。我的 Railtie 可能看起来像:
# lib/acts_as_awesome/railtie.rb
require 'rails'
require 'acts_as_awesome'
module ActsAsAwesome
class Railtie < Rails::Railtie
config.to_prepare do
ApplicationController.send(:extend, ActsAsAwesome::Hook)
end
end
end
以及 ActsAsAwesome::Hook 代码:
# lib/acts_as_awesome/hook.rb
module ActsAsAwesome::Hook
def acts_as_awesome(*args)
options = args.extract_options!
# do the things that make the controller awesome.
include ActsAsAwesome::InstanceMethods
before_filter :an_awesome_filter
end
end
我觉得这里的概念是合理的,并且以前使用过类似的过程。基本上,它会告诉 Rails 在生产期间和开发中的每个请求之前执行一次 to_prepare 块(我们希望这样做,因为 ApplicationController 将在这些时候重新加载,可能会清除我们的钩子方法);钩子就是这样:它为所有控制器(或者更确切地说,所有扩展 ApplicationController 的控制器)添加了一个钩子,以允许用户将真正的“真棒”代码引入他们的控制器,而不会影响不需要它的控制器。
#acts_as_awesome 钩子本身并不传达 Awesome 功能。这是因为并非所有控制器都可能需要此功能。相反,该方法负责通过 ActsAsAwesome::InstanceMethods 模块引入 real 很棒的东西。这样,用户只有在显式调用acts_as_awesome 方法时才能获得Awesome 功能。它还向控制器添加了一个前置过滤器,以证明此方法中的代码将被评估与目标控制器类本身中的代码完全相同。
如果你的目标是模型而不是控制器,这种技术应该同样有效:只需将你的钩子注入 ActiveRecord::Base。由于 AR:B 仅在 Rails 启动时加载,您应该可以将其放入初始化程序(请参阅 Railtie 文档),但我保留在此犯错的权利。
关于 railtie 的一个陷阱:文档读起来好像它应该被自动检测到,但我经常遇到这个问题。要绕过它,只需从 gem 的主源文件中获取 railtie(在上面的示例中,这将是 lib/acts_as_awesome.rb)。
您可以在我的 github 帐户中看到完整的 ActsAsAwesome 源代码:
http://github.com/sinisterchipmunk/acts_as_awesome
我希望这会有所帮助。你的问题有点高级,所以我能做的最好的回答是高级别的。
-科林·麦肯齐四世
http://thoughtsincomputation.com
@sinisterchipmnk