How to refactor the following 2 function (4 lines each)


I’m trying to DRY my code and I think It could be done even better. The following 2 functions are “before_save” callbacks that practically do the same thing, but on a different set of attributes.

Since the code is highly similar, I was wondering if someone could help me to refactor the code?

def normalize_budget result = normalize_generic(self.budget) self.budget_min = result[:min] self.budget_max = result[:max] self.budget = result[:display] end

def normalize_size result = normalize_generic(self.size) self.size_min = result[:min] self.size_max = result[:max] self.size = result[:display] end

Kind regards, Axinte

def normalize(property)     result = normalize_generic(self.send(property))     self.send("#{property}_min=", result[:min])     self.send("#{property}_max=", result[:max])     self.send("#{property}=", result[:display])   end

object.normalize(:size) object.normalize(:budget)


try this:

  def normalize     update_result("budget")     update_result("size")   end

  def update_result(field_name)     result = normalize_generic(self.send(field_name))     eval("self.#{field_name}_min = result[:min]")     eval("self.#{field_name}_max = result[:max]")     eval("self.#{field_name} = result[:display]")   end

Thank you both for your feedback. Based on your suggestions, I’ve finally decided to implement it in the following way:

%w[size budget].each do |property| define_method(“normalize_#{property}_range”) do |*args| result = normalize_generic_range(self.send(property)) self.send(“#{property}_min=”, result[:min]) self.send(“#{property}_max=”, result[:max]) self.send(“#{property}=”, result[:display]) end end

this code defines normalize_size_range and normalize_budget_range and updates both sets of attributes accordingly.

kind regards, Axinte

Here's a better solution:

  %w[size budget].each do |property|     class_eval %Q!         def normalize_#{property}_range             result = normalize_generic_range( self.#{property} )             self.#{property}_min = result[:min]             self.#{property}_max = result[:max]             self.#{property} = result[:display]         end     !   end


Thank you again for your help. Is there any difference between your solution and mine?

Kind regards,


Yes, you're defining and method and using send at every call, my solution will generate a method with direct calls instead of sending them.