ruby强大的 define_method,有闭包的能力!

闭包的例子一般是在说ruby的块,特片是:访问本地变量和绑定运行上下文(很强大的两点)

 

nums = [10,3,22,34,17]
sum = 0
nums.each{|n| sum += n}
print sum

 

近来看mongoid的代码,发现define_method也能绑定运行上下文!

 

 def getter(name, metadata)
     tap do
       define_method(name) do |*args|
         reload, variable = args.first, "@#{name}"
         options = options(args)
         if instance_variable_defined?(variable) && !reload
           instance_variable_get(variable)
         else
           build(
             name,
             @attributes[metadata.key],
             metadata,
             options.merge(:binding => true, :eager => metadata.embedded?)
           )
         end
       end
     end
   end          

 

定义的getter方法中绑定了当时metadata类实例!这样应用不用再额外做映射表,来维护方法与其它对象的关系,正如有栈系统帮我们存函数出入参数。

 

写了一个简单示意方法:

 

class Metadata
  attr_accessor :relation_name
end

module Accessor           
  def build(name, metadata)
    p name, metadata, metadata.relation_name
  end

  module ClassMethods
    def getter(name, metadata)
      tap do
        define_method(name) do 
          build(
          name,
          metadata
          )
        end
      end
    end
  end        
end   

class Doc
  include Accessor
  extend Accessor::ClassMethods
end

meta = Metadata.new
meta.relation_name = 'embeds_one'

Doc.getter("ss_car", meta)
# p Doc.public_instance_methods
Doc.new.ss_car

meta2 = Metadata.new
meta2.relation_name = 'ref_one'
Doc.getter("ss_bus", meta2)
Doc.new.ss_bus                          

 

输出:

 

"ss_car"
#<Metadata:0x00000100846f38 @relation_name="embeds_one">
"embeds_one"
"ss_bus"
#<Metadata:0x00000100846128 @relation_name="ref_one">
"ref_one"

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值