Reputation: 229
I have a class with bunch of attributes (first
, second
, third
, etc.).
I need to go through all "even" attributes (i.e. second
, fourth
, sixth
, etc.) and make some corrections to just those:
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.
As you can see, I have the exact same code for each "even" attribute, except for the different attribute name. Is there a way to avoid this repetition in the code (I have around 50 attributes in total)?
Upvotes: 1
Views: 418
Reputation: 5977
You can use Object#send
to invoke an arbitrary method on report
by specifying the method name as a string or a symbol:
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
The method names first
, second
, third
, etc. do not easily lend themselves to automatization, but if you renamed the methods to item_1
, item_2
, etc., you could use a loop to process all of them:
(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
If the method names need to stay the same, you can still simplify the code like this:
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
Upvotes: 1