在循环中设置 Ruby 对象的多个属性



我有一个类,它有很多属性(firstsecondthird等(。 我需要遍历所有"偶数"属性(即secondfourthsixth等(并对这些内容进行一些更正:

report.first = Calculate('1')
report.second = Calculate('2')
report.second *= 0.9 if requireCorrection && report.second > 5
report.third = Calculate('3')
report.fourth = Calculate('4')
report.fourth *= 0.9 if requireCorrection && report.fourth > 5
report.fifth = Calculate('5')
report.sixth = Calculate('6')
report.sixth *= 0.9 if requireCorrection && report.sixth > 5
# etc.

如您所见,除了不同的属性名称外,每个"even"属性都有完全相同的代码。有没有办法避免代码中的这种重复(我总共有大约 50 个属性(?

可以使用Object#sendreport上调用任意方法,方法是将方法名称指定为字符串或符号:

def make_correction(report, which_method)
current_value = report.send(which_method)
current_value *= 0.9 if current_value > 5
report.send "#{which_method}=", current_value
end

方法名称firstsecondthird等不容易实现自动化,但是如果你将方法重命名为item_1item_2等,你可以使用循环来处理所有这些方法:

(1..50).each do |i|
report.send "item_#{i}=", Calculate(i.to_s)
if i.even?
make_correction(report, "item_#{i}") if require_correction
end
end

如果方法名称需要保持不变,您仍然可以像这样简化代码:

attrs = [:first, :second, :third, :fourth, :fifth]
attrs.each_with_index do |attr, ix|
i = ix + 1  # indexes are zero based, we need to adjust them
report.send "#{attr}=", Calculate(i.to_s)
if i.even?
make_correction(report, attr) if require_correction
end
end

最新更新