用代码块收集参数

2016-07-13  本文已影响65人  33d8e4ec2cc9

最近在为看rails源码做一些准备,其中必须要搞懂的东西除了Class,Module,Object,Kernel,eigenclass这类东西之外,还有一个比较重要的就是代码块了,虽然也了解了一些关于代码块的知识,但是对于代码块的运用还是比较少,代码块的基本知识不在本次简书中介绍了,这次先直接介绍我最近用代码块来干了些什么。

对于Sunspot#solr_search这个方法,大家一定很熟悉了,大家可以先回想一下,这个方法要接收什么参数,你想过之后会发现,我们在调用这个方法的时候并没有传什么参数,而是传了一大堆代码过去,恩,相信你已经明白了,对于一个方法,可以将一堆代码传过去作为参数,用{}来包裹他们,或者是从do 到 end, 这段代码会作为一个对象被传进这个方法,这就是代码块最基本的一个应用。下面我会教大家如何实现模仿solr_search的这种参数收集方式,纯自己捣鼓的,有不妥的地方欢迎指点。

首先我们要实现用with,把参数收集起来,就像solr_search那样,里面搜索的参数我们都是用with这个方法来做到的

class Peter
  def my_method
    options = {}
    Kernel.module_eval do
      define_method :with do |k,v|
        options[k] = v 
      end
    end
  yield
  undef :with 
  options
  end
end
peter = Peter.new
peter.my_method do
  with :first_val, 1
  with :second_val, 2
end
#=> {:first_val => 1, :second_val => 2}

是不是还挺酷的?
来看看我做了什么,在我调用这个方法的时候,处在顶级作用域,也就是说当前的class是Object,然后Object这个类include了Kernel这个模块,也就是说在把方法写在Kernel中,任何对象都能调用到,因此我在我的方法里面打开了Kernel这个模块,在里面添加了with这个方法,这样在任何地方调用这个方法并使用with的时候都可以调用到!

接着我们模仿一下,all_of do,在代码块里传代码块,也是可以的!

class Peter
  def my_method
    options = {}
    Kernel.module_eval do
      define_method :all_of do |&block|
        options[:my_block] = block
      end
    end
  yield
  options[:my_block].call('hello')
  end
end
peter = Peter.new
peter.my_method do
  all_of do |i|
    "#{i} world!"
  end
end
#=> 'hello world!'

方法参数不多的话,没有必要写成这样,但是一个方法接收七八个参数,那调用起来也很痛苦,试想一下solr_search这个方法不用代码块收集参数的话,得传多少个参数过去。

上一篇下一篇

猜你喜欢

热点阅读