我怎么能用方法
动态正则表达式解析@product.price = line.gsub(/,/, '').scan(/\d{3,9}/).first
@product.model = line.rm_dirty.split(":").last.strip
@product.location = line.split(":").last.strip
然而,我总是得到NoMethodError: undefined method `gsub(/,/, '')'
def fetch_by_keyword_and_regex(regex_str)
@line.send(regex_str)
end
fetch_by_keyword_and_regex("gsub(/,/, '').scan(/\d{3,9}/).first")
答案 0 :(得分:1)
如果你想让这个更加动态,你可以发送一个块:
line_sub = lambda { |line|
line.gsub(/,/, '').scan(/\d{3,9}/).first
}
然后你可以在任何事情上使用它:
line_sub.call(@line)
这很像JavaScript声明var line_sub = function(line) { ... }
。
send
方法只允许按名称进行特定的方法调用:
@ line.send(:sub,/,/,'')。send(:scan,/ \ d {3,9} /)。send(:first)
这是你可以在数组中表达的东西,例如:
line_process = [
[ :sub, /,/, '' ],
[ :scan, /\d{3,9}/ ],
[ :first ]
]
然后使用它:
line_process.inject(@line) do |obj, args|
obj.send(*args)
end
这太乱了,所以我尽可能避免它。 Ruby的块传递语义对于元编程来说更加清晰。
答案 1 :(得分:0)
您必须使用Ruby的一个评估函数,即eval
,instance_eval
或instance_exec
,但不建议这样做。
我会yield
该对象:(假设您的实际实现/用例更复杂)
def fetch(regex_str)
yield @line
end
fetch { |l| l.gsub(/,/, '').scan(/\d{3,9}/).first }
答案 2 :(得分:0)
如果我理解正确,我会完全质疑这种方法。原因:
1)当不那么钝的方法无法满足需要时,元编程应该作为最后的手段,
2)所讨论的变量东西是代码/功能,并且应该这样表达 - 将其表示为字符串然后评估它等等,是多余的,过于复杂,并且
3)这种方法在某种程度上会隐藏于人类读者,并且肯定会隐藏在代码编辑器,分析工具等中,真正发生的事情。一种替代方法是哈希,其键是属性名称,值是应用于值的代码,实质上是属性处理功能的查找表,例如
ATTRIBUTE_PROCESSORS = {
price: ->(line) { line.gsub(/,/, '').scan(/\d{3,9}/).first },
model: ->(line) { line.rm_dirty.split(":").last.strip },
location: ->(line) { line.split(":").last.strip }
}
......并且这样称呼它:
ATTRIBUTE_PROCESSORS[:price].(line)
这样做的另一个好处是所有属性处理都是共处的,因此您可以轻松地发现重复,并在适当的时候进行重构。