display nutrition data in recipe view

This commit is contained in:
Dan Elbert 2016-02-14 19:29:34 -06:00
parent 48d296a7c9
commit a86c5afae2
9 changed files with 183 additions and 1 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -57,6 +57,11 @@
<%= f.text_field :lipids, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :carbohydrates, "Grams of Fat", class: 'control-label' %>
<%= f.text_field :carbohydrates, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :kcal, "Calories", class: 'control-label' %>
<%= f.text_field :kcal, class: 'form-control' %>

View File

@ -91,6 +91,58 @@
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Nutrition Data</h3>
</div>
<div class="panel-body">
<table class="table">
<thread>
<tr>
<th>Item</th>
<th>Total</th>
</tr>
</thread>
<tr>
<td>Calories</td>
<td><%= @recipe.nutrition_data.kcal %></td>
</tr>
<tr>
<td>Grams Protein</td>
<td><%= @recipe.nutrition_data.protein %></td>
</tr>
<tr>
<td>Grams Fat</td>
<td><%= @recipe.nutrition_data.lipids %></td>
</tr>
<tr>
<td>Grams Carbohydrates</td>
<td><%= @recipe.nutrition_data.carbohydrates %></td>
</tr>
<tr>
<td>Grams Sugar</td>
<td><%= @recipe.nutrition_data.sugar %></td>
</tr>
<tr>
<td>Grams Fiber</td>
<td><%= @recipe.nutrition_data.fiber %></td>
</tr>
</table>
<h3>Nutrition Calculation Warnings</h3>
<ul>
<% @recipe.nutrition_data.errors.each do |err| %>
<li><%= err %></li>
<% end %>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="row">

View File

@ -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

View File

@ -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