$1.to_sym => args[0]
和($1.to_sym,*args,&block)
在以下代码行中做了什么?
class Table
def method_missing(id,*args,&block)
return as($1.to_sym,*args,&block) if id.to_s =~ /^to_(.*)/
return rows_with($1.to_sym => args[0]) if id.to_s =~ /^rows_with_(.*)/
super
end
# ...
end
上下文
Ruport是一个Ruby报告库。您可以使用Ruport :: Data :: Table类创建表格数据并将其转换为不同的格式文本,例如:
require 'ruport'
table = Ruport::Data::Table.new :column_names => ["country" , "wine" ], :data => [["France" , "Bordeaux" ], ["Italy" , "Chianti" ], ["France" , "Chablis" ]]
puts table.to_text
⇒
+--------------------+
| country | wine |
+--------------------+
| France | Bordeaux |
| Italy | Chianti |
| France | Chablis |
+--------------------+
假设您只选择法国葡萄酒并将其转换为以逗号分隔的值:
found = table.rows_with_country("France" )
found.each do |row|
puts row.to_csv
end
⇒
France, Bordeaux
France, Chablis
你刚刚在Ruport :: Data :: Table上调用了一个名为rows_with_country()的方法。但是这个班级的作者怎么会知道你有一个名为country的专栏呢?事实是,作者不知道这一点。如果您查看Ruport内部,您会看到rows_with_country()和to_csv()都是Ghost方法。 Ruport :: Data :: Table类有点如上所定义。
对rows_with_country()的调用将成为对更传统外观的调用 方法,rows_with(:country),它将列名作为参数 - 换货。此外,对to_csv()的调用将成为对(:csv)的调用。如果方法 名称不是以这两个前缀中的任何一个开头,Ruport会退回 到Kernel#method_missing(),它抛出一个NoMethodError。 (那是什么 super关键字适用于。)
答案 0 :(得分:2)
让我们看一下method_missing
:
def method_missing(id,*args,&block)
return as($1.to_sym,*args,&block) if id.to_s =~ /^to_(.*)/
return rows_with($1.to_sym => args[0]) if id.to_s =~ /^rows_with_(.*)/
super
end
必需的背景:在未明确定义请求的方法时,在对象上调用method_missing
。 id
将成为所谓方法的符号; args
将是一个参数数组,block
如果有一个块,则为Proc
,或nil
。
return as($1.to_sym,*args,&block) if id.to_s =~ /^to_(.*)/
执行真的从最后开始,在if
:它检查条件
id.to_s =~ /to_(.*)/
这基本上与被调用方法的字符串上的正则表达式匹配。 x =~ y
返回x
匹配的y
的整数偏移量(如果有的话),否则为零。 e.g:
> "abc" =~ /a/
=> 0
> "abc" =~ /.$/
=> 2
> "abc" =~ /\d/
=> nil
请记住,0
在布尔条件中被视为真值,因此如果被调用函数的名称以if
开头,则to_
将被视为为真。方法名称的其余部分由(.*)
捕获。
现在,我们没有明确保存捕获组,但Ruby从Perl借用,因为第一个捕获组的内容将保存在$1
中,第二个保存在$2
中,等等: / p>
> "abc" =~ /a(.)(.)/
=> 0
> $1
=> "b"
> $2
=> "c"
现在,回到有问题的一行:
return as($1.to_sym,*args,&block) if id.to_s =~ /^to_(.*)/
因此,如果被调用方法的名称是to_XYZ
形式,则它调用as()
方法,第一个参数设置为:XYZ
,其余参数来自调用附加,并通过块(如果有的话)。
继续:
return rows_with($1.to_sym => args[0]) if id.to_s =~ /^rows_with_(.*)/
这基本相同:如果方法名称与rows_with_ABC
类似,则它使用散列rows_with()
调用{:ABC => args[0]}
,其中args[0]
是给定的第一个参数缺少方法调用。