美文网首页
用代码块收集参数

用代码块收集参数

作者: 33d8e4ec2cc9 | 来源:发表于2016-07-13 23:11 被阅读65次

    最近在为看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这个方法不用代码块收集参数的话,得传多少个参数过去。

    相关文章

      网友评论

          本文标题:用代码块收集参数

          本文链接:https://www.haomeiwen.com/subject/vlhejttx.html