Nick Res
Nick Res

Reputation: 2244

DRYing up these helper methods

I've got three methods like this:

def total_fat
  total = 0
  meal_foods = current_user.meal_foods
  meal_foods.each do |food|
    total += food.fat
  end
  return total
end 

One for fat, carbs, and protein.

I'd like to DRY this up.

I've tried this method and it didn't seem to work by passing in the 'macro' as string.

def total_of(macro)
  total = 0
  meal_foods = current_user.meal_foods
  meal_foods.each do |food|
    total += food.macro
  end
  return total 
end  

How could I do this?

Upvotes: 0

Views: 60

Answers (4)

Fon
Fon

Reputation: 91

def total_of(type)
  current_user.meal_foods.map(&:type).sum
end

total_of(:fat)

Upvotes: 1

ian
ian

Reputation: 12251

def total_of(macro)
  current_user.meal_foods.inject(0) do |total,food|
    total + food.send(macro)
  end
end

I'm not certain this will work as you've provided no data to try it with, but have a look at the Enumerable docs to give you some ideas of what can be done. each_with_object is underused and would fit here too.

There's no need for the explicit return. In fact, there's no need to even mention total as it will be the last expression evaluated.

Upvotes: 0

Amit Kumar Gupta
Amit Kumar Gupta

Reputation: 18567

def total_of(marcro)
  current_user.meal_foods.map(&marcro).inject(:+)
end

This takes the Array(-like) collection of meal_foods and maps it to an Array of just the marcro value of the meal_foods, and then injects a "+" between each of the numbers. Make sure to pass the argument as a symbol, e.g. total_of(:fat).

Upvotes: 3

Michael Papile
Michael Papile

Reputation: 6856

You need to use send to invoke methods with variables, and convert macro to a symbol.

so:

  food.send(macro.to_sym)

Upvotes: 0

Related Questions