From a86c5afae262e3c45b3ccd2cbd8bde1c256f280f Mon Sep 17 00:00:00 2001 From: Dan Elbert Date: Sun, 14 Feb 2016 19:29:34 -0600 Subject: [PATCH] display nutrition data in recipe view --- app/controllers/ingredients_controller.rb | 2 +- app/models/ingredient.rb | 1 + app/models/nutrition_data.rb | 51 ++++++++++++++++++++++ app/models/recipe.rb | 11 +++++ app/models/recipe_ingredient.rb | 15 +++++++ app/views/ingredients/_form.html.erb | 5 +++ app/views/recipes/show.html.erb | 52 +++++++++++++++++++++++ spec/factories/ingredients.rb | 5 +++ spec/models/recipe_ingredient_spec.rb | 42 ++++++++++++++++++ 9 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 app/models/nutrition_data.rb diff --git a/app/controllers/ingredients_controller.rb b/app/controllers/ingredients_controller.rb index 9d4da56..14f2283 100644 --- a/app/controllers/ingredients_controller.rb +++ b/app/controllers/ingredients_controller.rb @@ -118,7 +118,7 @@ class IngredientsController < ApplicationController # Never trust parameters from the scary internet, only allow the white list through. def ingredient_params - params.require(:ingredient).permit(:name, :notes, :ndbn, :density, :water, :protein, :lipids, :kcal, :fiber, :sugar) + params.require(:ingredient).permit(:name, :notes, :ndbn, :density, :water, :protein, :lipids, :carbohydrates, :kcal, :fiber, :sugar) end def conversion_params diff --git a/app/models/ingredient.rb b/app/models/ingredient.rb index c300ee0..3901ee1 100644 --- a/app/models/ingredient.rb +++ b/app/models/ingredient.rb @@ -40,6 +40,7 @@ class Ingredient < ActiveRecord::Base self.water = food.water self.protein = food.protein self.lipids = food.lipid + self.carbohydrates = food.carbohydrates self.ash = food.ash self.kcal = food.kcal self.fiber = food.fiber diff --git a/app/models/nutrition_data.rb b/app/models/nutrition_data.rb new file mode 100644 index 0000000..5017bd8 --- /dev/null +++ b/app/models/nutrition_data.rb @@ -0,0 +1,51 @@ +class NutritionData + + attr_reader :protein, :lipids, :carbohydrates, :kcal, :fiber, :sugar, :errors + + def initialize(recipe_ingredients) + @errors = [] + @protein = 0.0 + @lipids = 0.0 + @kcal = 0.0 + @fiber = 0.0 + @sugar = 0.0 + @carbohydrates = 0.0 + + valid_ingredients = [] + + recipe_ingredients.each do |i| + if i.ingredient_id.nil? + @errors << "#{i.name} has no nutrition data" + elsif !i.can_convert_to_grams? + @errors << "#{i.name} can't be converted to grams" + else + valid_ingredients << i + end + end + + keys = [:protein, :lipids, :kcal, :fiber, :sugar, :carbohydrates] + + valid_ingredients.each do |i| + grams = i.to_grams + + keys.each do |k| + value = i.ingredient.send(k) + if value.present? + value = value.to_f + running_total = self.instance_variable_get("@#{k}".to_sym) + delta = (grams / 100.0) * value + self.instance_variable_set("@#{k}".to_sym, running_total + delta) + else + @errors << "#{i.name} missing #{k} data" + end + end + end + + keys.each do |k| + v = self.instance_variable_get("@#{k}".to_sym) + self.instance_variable_set("@#{k}".to_sym, v.round(2)) + end + + end + +end \ No newline at end of file diff --git a/app/models/recipe.rb b/app/models/recipe.rb index 225005b..168b7f2 100644 --- a/app/models/recipe.rb +++ b/app/models/recipe.rb @@ -30,5 +30,16 @@ class Recipe < ActiveRecord::Base end end + def nutrition_data(recalculate = false) + if recalculate || @nutrition_data.nil? + @nutrition_data = calculate_nutrition_data + end + @nutrition_data + end + private + + def calculate_nutrition_data + NutritionData.new(recipe_ingredients) + end end diff --git a/app/models/recipe_ingredient.rb b/app/models/recipe_ingredient.rb index 35943c1..14b0114 100644 --- a/app/models/recipe_ingredient.rb +++ b/app/models/recipe_ingredient.rb @@ -34,4 +34,19 @@ class RecipeIngredient < ActiveRecord::Base end end + def can_convert_to_grams? + if self.quantity.present? && self.units.present? + value_unit = UnitConversion.parse(self.quantity, self.units) + value_unit.mass? || (value_unit.volume? && self.ingredient && self.ingredient.density.present?) + else + false + end + end + + def to_grams + value_unit = UnitConversion.parse(self.quantity, self.units) + gram_unit = value_unit.convert('g', self.ingredient ? self.ingredient.density : nil) + gram_unit.raw_value + end + end diff --git a/app/views/ingredients/_form.html.erb b/app/views/ingredients/_form.html.erb index 238b5f2..2458bf7 100644 --- a/app/views/ingredients/_form.html.erb +++ b/app/views/ingredients/_form.html.erb @@ -57,6 +57,11 @@ <%= f.text_field :lipids, class: 'form-control' %> +
+ <%= f.label :carbohydrates, "Grams of Fat", class: 'control-label' %> + <%= f.text_field :carbohydrates, class: 'form-control' %> +
+
<%= f.label :kcal, "Calories", class: 'control-label' %> <%= f.text_field :kcal, class: 'form-control' %> diff --git a/app/views/recipes/show.html.erb b/app/views/recipes/show.html.erb index 04e4748..8d861a0 100644 --- a/app/views/recipes/show.html.erb +++ b/app/views/recipes/show.html.erb @@ -91,6 +91,58 @@
+
+
+
+
+

Nutrition Data

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ItemTotal
Calories<%= @recipe.nutrition_data.kcal %>
Grams Protein<%= @recipe.nutrition_data.protein %>
Grams Fat<%= @recipe.nutrition_data.lipids %>
Grams Carbohydrates<%= @recipe.nutrition_data.carbohydrates %>
Grams Sugar<%= @recipe.nutrition_data.sugar %>
Grams Fiber<%= @recipe.nutrition_data.fiber %>
+ +

Nutrition Calculation Warnings

+ +
    + <% @recipe.nutrition_data.errors.each do |err| %> +
  • <%= err %>
  • + <% end %> +
+
+
+
+
+
diff --git a/spec/factories/ingredients.rb b/spec/factories/ingredients.rb index 22b3ba6..74caafd 100644 --- a/spec/factories/ingredients.rb +++ b/spec/factories/ingredients.rb @@ -5,4 +5,9 @@ FactoryGirl.define do notes 'note note note' end + factory :ingredient_with_density, parent: :ingredient do + name 'Butter' + density '8 oz/cup' + end + end diff --git a/spec/models/recipe_ingredient_spec.rb b/spec/models/recipe_ingredient_spec.rb index d653cb7..a0c61cf 100644 --- a/spec/models/recipe_ingredient_spec.rb +++ b/spec/models/recipe_ingredient_spec.rb @@ -2,4 +2,46 @@ require 'rails_helper' RSpec.describe RecipeIngredient, type: :model do + describe '#can_convert_to_grams' do + it 'returns false if no quantity or unit' do + ri = RecipeIngredient.new + expect(ri.can_convert_to_grams?).to be_falsey + end + + it 'returns false if no quantity' do + ri = RecipeIngredient.new(units: 'lbs') + expect(ri.can_convert_to_grams?).to be_falsey + end + + it 'returns false if no units' do + ri = RecipeIngredient.new(quantity: '5 1/2') + expect(ri.can_convert_to_grams?).to be_falsey + end + + it 'returns false if weird units' do + ri = RecipeIngredient.new(quantity: '5 1/2', units: 'dogs') + expect(ri.can_convert_to_grams?).to be_falsey + end + + it 'returns true if unit is mass' do + ri = RecipeIngredient.new(quantity: '5 1/2', units: 'lbs') + expect(ri.can_convert_to_grams?).to be_truthy + end + + it 'returns false if unit is volume and there is no ingredient' do + ri = RecipeIngredient.new(quantity: '5 1/2', units: 'cups') + expect(ri.can_convert_to_grams?).to be_falsey + end + + it 'returns false if unit is volume and ingredient has no density' do + ri = RecipeIngredient.new(quantity: '5 1/2', units: 'cups', ingredient: create(:ingredient)) + expect(ri.can_convert_to_grams?).to be_falsey + end + + it 'returns false if unit is volume and ingredient has density' do + ri = RecipeIngredient.new(quantity: '5 1/2', units: 'cups', ingredient: create(:ingredient_with_density)) + expect(ri.can_convert_to_grams?).to be_truthy + end + end + end