我想要一个基本的小程序示例,它读入两个插件并注册它们。这两个插件以无冲突的方式以相同的方式挂钩到基本程序中。
我对任何编程语言中的元编程都很陌生,我不知道从哪里开始。
我想要一个基本的小程序示例,它读入两个插件并注册它们。这两个插件以无冲突的方式以相同的方式挂钩到基本程序中。
我对任何编程语言中的元编程都很陌生,我不知道从哪里开始。
我一直在研究这个问题已经有一段时间了。我已经尝试了很多不同的方法来做这件事并向很多人寻求建议。我仍然不确定我拥有的是“正确的方式”,但它运作良好并且很容易做到。
在我的情况下,我特别关注配置并引入配置插件,但即使我的术语特定于配置,原理也是一样的。
在一个非常基本的层面上,我有一个没有任何内容的Configuration类 - 它是空的。我还有一个Configure方法,它返回配置类,并允许您调用它的方法:
# config.rb
class Configuration
end
class MySystem
def self.configure
@config ||= Configuration.new
yield(@config) if block_given?
@config
end
Dir.glob("plugins/**/*.rb").each{|f| require f}
end
MySystem.configure do |config|
config.some_method
config.some_value = "whatever"
config.test = "that thing"
end
puts "some value is: #{MySystem.configure.some_value}"
puts "test #{MySystem.configure.test}"
为了获得配置类上的some_method和some_value,我让插件通过模块扩展配置对象:
# plugins/myconfig.rb
module MyConfiguration
attr_accessor :some_value
def some_method
puts "do stuff, here"
end
end
class Configuration
include MyConfiguration
end
和
# plugins/another.rb
module AnotherConfiguration
attr_accessor :test
end
class Configuration
include AnotherConfiguration
end
要加载插件,您只需要一个代码来查找特定文件夹中的.rb文件并“需要”它们。只要在包含它的文件被加载时它立即运行,这个代码可以存在任何地方...我可能会把它放在MySystem的类定义或类似的东西开始。当有意义时,可能会把它移到其他地方。
Dir.glob("plugins/**/*.rb").each{|f| require f}
运行config.rb,你会得到如下所示的输出:
做点什么,这里 一些价值是:无论如何 测试那件事
有很多选项来实现这个的各个部分,但这应该让你走上正轨。
看起来这个项目可能会有所帮助: https://github.com/eadz/plugman
但是,我没有找到任何可以处理嵌入式(gem)依赖关系的东西。包含Ruby文件很简单,但是一旦你的插件开始需要其他库,那么这个简单的模型就会崩溃(要么所有的deps必须与你的应用程序一起安装,要么你需要一些其他的机制来将插件依赖性gems带入进程)。