meta_programming中的method_missing

来源:互联网 发布:数据库建模工具哪个好 编辑:程序博客网 时间:2024/06/18 14:21


当你使用ruby的activerecord的时候,你是否会经常遇到以下的程序了


    Post.find_by_title("Awesomeness!")    User.find_by_email("bob@example.com")    User.find_by_email_and_login("bob@example.com", "bob")

那么这些程序是如何实现的呢? 


让我们来看一下源代码吧!


    class ActiveRecord::Base      def method_missing(meth, *args, &block)        if meth.to_s =~ /^find_by_(.+)$/          run_find_by_method($1, *args, &block)        else          super # You *must* call super if you don't handle the                # method, otherwise you'll mess up Ruby's method                # lookup.        end      end      def run_find_by_method(attrs, *args, &block)        # Make an array of attribute names        attrs = attrs.split('_and_')        # #transpose will zip the two arrays together like so:        #   [[:a, :b, :c], [1, 2, 3]].transpose        #   # => [[:a, 1], [:b, 2], [:c, 3]]        attrs_with_args = [attrs, args].transpose        # Hash[] will take the passed associative array and turn it        # into a hash like so:        #   Hash[[[:a, 2], [:b, 4]]] # => { :a => 2, :b => 4 }        conditions = Hash[attrs_with_args]        # #where and #all are new AREL goodness that will find all        # records matching our conditions        where(conditions).all      end    end


当你执行find_by_mail 的时候,你发现class中没有这个函数定义, 这个时候系统就会转向method_missing 函数


进入函数就遇到一个正规表达式, 如果函数名开头是以find_by_开头的, 就当作匹配成功,这个时候就要执行run_find_by_method


而这个函数的参数里面出现了$1, 这个是用来获取  

/^find_by_(.+)$/ 括号里面的参数。
比如find_by_mail $1 = 'mail'
find_by_mail_and_login  $1 = 'mail_and_login'
函数进去之后,就先分割字符串
比如说 ‘mail_and_login’ 分割为 ['mail', 'login']
下一步就是对号入座
[['mail', 'login'], ['bob@163.com', 'bob']]
再将数组变换为hash
{ :mail => 'bob@163.com', :login => 'bob'}
是不是突然有一种ruby很高深的感觉了。。。。。。。。。。。。。。。。。。

原创粉丝点击