我正在使用以下代码段来创建一些XML,它的工作原理非常好。
def outputs_xml(dir, t_items, x)
x.murders {
t_items.values.each do |i|
x.murder {
attributes_xml(dir, i, x)
}
end
}
end
生成的XML看起来像这样;
<?xml version="1.0"?>
<outputs>
<murders>
<murder>
<classification>Macabre</classification>
<title>An Old Macabre Murder</title>
<path>C:\an_old_macabre_murder.pdf</path>
</murder>
</murders>
</outputs>
尝试使用define_method
对其进行优化意味着属性未被“翻译”(因为缺少更好的单词)。 XML不再使用类型(例如“谋杀”),而是读取“类型”。
["murders", "mysteries", "thrillers"].each do |type|
define_method("#{type}_xml") do |dir, items, o|
x.type {
items.values.each do |i|
o.type.singularize{
o.classification i[1].to_s
o.titles i[2]
o.path "#{dir}/#{i[3]}.pdf"
}
end
}
end
...
<?xml version="1.0"?>
<outputs>
<type>
<type class="singularize">
<classification>Macabre</classification>
<title>An Old Macabre Murder</title>
<path>C:\an_old_macabre_murder.pdf</path>
</type>
</type>
</outputs>
总结一下:在原始代码中,我能够遍历哈希并使用'x.murder'来生成<murder>...</murder>
但是使用define_method
相同的代码会生成带有属性的<type>
如何使用define_method
?
答案 0 :(得分:2)
您实际上是在致电x.type
和o.type.singularize
而不是致电x.murders
和o.murder
。
由于Nokogiri使用method_missing
工作,我相信您应该使用x.send
代替:
["murders", "mysteries", "thrillers"].each do |type|
define_method("#{type}_xml") do |dir, items, o|
x.send(type) {
items.values.each do |i|
o.send(type.singularize) {
o.classification i[1].to_s
o.titles i[2]
o.path "#{dir}/#{i[3]}.pdf"
}
end
}
end
如果要动态调用方法 ,则不能简单地将变量名称作为方法名称,并希望它将被调用:
a = 'to_i'
'123'.a # <= ERROR - _not_ '123'.to_i
Ruby的send API使您可以通过将方法名称作为参数传递来实现:
调用 symbol 标识的方法,并传递任何参数 指定。如果名称发送冲突,您可以使用
__send__
obj中的现有方法当方法由字符串标识时, string被转换为符号。
a = 'to_i'
'123'.send(a) # => 123