当你使用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很高深的感觉了。。。。。。。。。。。。。。。。。。
本文深入探讨了 Ruby 的 ActiveRecord 模型中 find_by 方法的工作原理。通过源代码解析,揭示了该方法如何动态地根据属性查找记录,并将其应用于实际案例。
1153

被折叠的 条评论
为什么被折叠?



