之前你可能读到Ruby元编程,也许你的一些项目中使用它,但一些最流行的开源项目是如何利用这个特性?
答案在这篇文章中!
Rails示例
Rails大量使用元编程,这是一个开始的好地方。
例如,当您想要检查当前环境,在你的Rails应用程序,你做些什么:
Rails.env.production?
但什么是 env并且这是如何工作的呢?答案是 StringInquirer类,String这个类的一个子类。这个类使用 method_missing,让你可以调用 env.production?而不是 env == production.
代码是这样的:
def method_missing(method_name, *arguments)
if method_name[-1] == '?'
self == method_name[0..-2]
else
super
end
end
这就是说:“如果是以问号结尾的方法名称就做比较,否则继续祖先链”。
原始代码可在这里找到.
Sinatra委托
如果您以前使用过Sinatra你可能知道有两种方法来定义你的路由:通过使用 get / post这种独立于任何类以外的直接方法,或通过定义一个类继承自 Sinatra::Application.
Sinatra的DSL(领域特定语言)方法定义在 Sinatra::Application内,所以你如何在这个类以外使用呢?
嗯,这里有两个事情:元编程和模块的扩展。
Sinatra定义了一个 Sinatra::Delegator模块,在base.rb,用于将方法调用委托给一个 target。默认情况下目标设置为 Sinatra::Application。
这是一个简化版的定义于Sinatra::Delegator的delegate类方法:
def self.delegate(*methods)
methods.each do |method_name|
define_method(method_name) do |*args, &block|
Delegator.target.send(method_name, *args, &block)
end
end
end
delegate :get, :patch, :put, :post, :delete
这段代码创建了一组方法( define_method),将传递方法调用到 Sinatra::Application(Delegator.target的默认值).
然后 main对象被扩展,使用 Sinatra::Delegator定义的方法,这使得Sinatra的DSL可用 Sinatra::Application类。
值得注意的是,Ruby有两个用于方法委托的内置类,如果你需要他们:Delegator & Forwardable.
Paperclip Gem
Paperclip是gem,帮助您的应用程序来处理文件上传。文件加在ActiveRecord模型。has_attached_file方法定义附加文件。
例如:
class User
has_attached_file :avatar, :styles => { :normal => "100x100#" }
end
该方法定义在paperclip.rb,它使用元编程在模型定义方法。该方法可用于访问文件附件(Paperclip::Attachment类的一个实例)。例如,如果附加文件 :avatar, Paperclip将定义一个 avatar方法在模型上。
这是 define_instance_getter方法负责:
# @name => The name of the attachment
# @klass => The ActiveRecord model where this method is being defined
def define_instance_getter
name = @name
options = @options
@klass.send :define_method, @name do |*args|
ivar = "@attachment_#{name}"
attachment = instance_variable_get(ivar)
if attachment.nil?
attachment = Attachment.new(name, self, options)
instance_variable_set(ivar, attachment)
end
end
end
从这段代码中我们可以看到,对象存储在附件 @attachment_#{name}实例变量。在我们的例子中 @attachment_avatar.
然后检查这个附件已经存在,如果它不存在,它创建一个新的 Attachment对象和设置实例变量。
这是原始源代码.
结论
如您所见,元编程是一个非常强大和灵活的技术,但当你想要使用的时候请记得这句话:“强大意味着更大的责任”。
如果你喜欢这篇文章,不要忘了订阅我的时事通讯:)
广告时间:
Ruby是知识海洋的贝壳,一起来捡吧。
高性价比培训:
一个月短期培训,自由学习无压力
Rails网站开发入门,费用499
Ruby和Rails课程,可以为进入编程领域做准备
欢迎了解和交流
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。