From dd493a09d515e0b310b43718fb8f7022d9b9a59d Mon Sep 17 00:00:00 2001 From: Dan Elbert Date: Sat, 27 Feb 2016 20:12:41 -0600 Subject: [PATCH] Extra conversion options --- app/controllers/recipes_controller.rb | 27 +++++- app/models/recipe.rb | 24 ++++++ app/models/recipe_ingredient.rb | 46 ++++++++++ app/views/recipes/show.html.erb | 89 +++++++++++++++++--- config/routes.rb | 4 +- lib/unit_conversion/conversions.rb | 60 +++++++++++++ lib/unit_conversion/value_unit.rb | 22 +++++ spec/lib/unit_conversion/conversions_spec.rb | 10 +++ 8 files changed, 266 insertions(+), 16 deletions(-) diff --git a/app/controllers/recipes_controller.rb b/app/controllers/recipes_controller.rb index 0115b94..a7a24e7 100644 --- a/app/controllers/recipes_controller.rb +++ b/app/controllers/recipes_controller.rb @@ -1,6 +1,6 @@ class RecipesController < ApplicationController - before_action :set_recipe, only: [:show, :edit, :update, :destroy, :scale] + before_action :set_recipe, only: [:show, :edit, :update, :destroy] before_filter :ensure_valid_user, except: [:show, :scale, :index] @@ -12,6 +12,31 @@ class RecipesController < ApplicationController # GET /recipes/1 # GET /recipes/1.json def show + if params[:scale].present? + @scale = params[:scale] + @recipe.scale(params[:scale], true) + end + + if params[:system].present? + @system = params[:system] + case @system + when 'metric' + @recipe.convert_to_metric + when 'standard' + @recipe.convert_to_standard + end + end + + if params[:unit].present? + @unit = params[:unit] + case @unit + when 'mass' + @recipe.convert_to_mass + when 'volume' + @recipe.convert_to_volume + end + end + end # GET /recipes/1 diff --git a/app/models/recipe.rb b/app/models/recipe.rb index 168b7f2..143ff4c 100644 --- a/app/models/recipe.rb +++ b/app/models/recipe.rb @@ -30,6 +30,30 @@ class Recipe < ActiveRecord::Base end end + def convert_to_metric + recipe_ingredients.each do |ri| + ri.to_metric + end + end + + def convert_to_standard + recipe_ingredients.each do |ri| + ri.to_standard + end + end + + def convert_to_mass + recipe_ingredients.each do |ri| + ri.to_mass + end + end + + def convert_to_volume + recipe_ingredients.each do |ri| + ri.to_volume + end + end + def nutrition_data(recalculate = false) if recalculate || @nutrition_data.nil? @nutrition_data = calculate_nutrition_data diff --git a/app/models/recipe_ingredient.rb b/app/models/recipe_ingredient.rb index 14b0114..2c9b7dc 100644 --- a/app/models/recipe_ingredient.rb +++ b/app/models/recipe_ingredient.rb @@ -34,6 +34,52 @@ class RecipeIngredient < ActiveRecord::Base end end + def to_metric + return unless self.quantity.present? + value_unit = UnitConversion.parse(self.quantity, self.units) + value_unit = value_unit.to_metric + + self.quantity = value_unit.pretty_value + self.units = value_unit.unit.to_s + end + + def to_standard + return unless self.quantity.present? + value_unit = UnitConversion.parse(self.quantity, self.units) + value_unit = value_unit.to_standard + + self.quantity = value_unit.pretty_value + self.units = value_unit.unit.to_s + end + + def to_volume + return unless self.quantity.present? + if ingredient && ingredient.density + density = UnitConversion.parse(ingredient.density) + if density.density? + value_unit = UnitConversion.parse(self.quantity, self.units) + value_unit = value_unit.to_volume(density) + + self.quantity = value_unit.pretty_value + self.units = value_unit.unit.to_s + end + end + end + + def to_mass + return unless self.quantity.present? + if ingredient && ingredient.density + density = UnitConversion.parse(ingredient.density) + if density.density? + value_unit = UnitConversion.parse(self.quantity, self.units) + value_unit = value_unit.to_mass(density) + + self.quantity = value_unit.pretty_value + self.units = value_unit.unit.to_s + end + end + end + def can_convert_to_grams? if self.quantity.present? && self.units.present? value_unit = UnitConversion.parse(self.quantity, self.units) diff --git a/app/views/recipes/show.html.erb b/app/views/recipes/show.html.erb index 8d861a0..a8e6fc7 100644 --- a/app/views/recipes/show.html.erb +++ b/app/views/recipes/show.html.erb @@ -46,19 +46,9 @@

Ingredients

@@ -152,4 +142,79 @@ <%= link_to 'Back', recipes_path, class: 'btn btn-default' %> + + + \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 8fae2c8..c8d9c29 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,9 +1,7 @@ Rails.application.routes.draw do resources :recipes do - member do - get 'scale/:factor', action: :scale, as: :scale - end + end resources :ingredients, except: [:show] do diff --git a/lib/unit_conversion/conversions.rb b/lib/unit_conversion/conversions.rb index 03ba517..f5cccb2 100644 --- a/lib/unit_conversion/conversions.rb +++ b/lib/unit_conversion/conversions.rb @@ -80,4 +80,64 @@ module UnitConversion end end + class MetricUnitConversion < Conversion + def convert(value_unit) + if value_unit.unit && !value_unit.unit.metric? + if value_unit.mass? + value_unit = value_unit.convert('g').auto_unit + elsif value_unit.volume? + value_unit = value_unit.convert('ml').auto_unit + end + end + + value_unit + end + end + + class StandardUnitConversion < Conversion + def convert(value_unit) + if value_unit.unit && value_unit.unit.metric? + if value_unit.mass? + value_unit = value_unit.convert('oz').auto_unit + elsif value_unit.volume? + value_unit = value_unit.convert('cup').auto_unit + end + end + + value_unit + end + end + + class VolumeUnitConversion < Conversion + def initialize(density_unit_value) + raise UnknownUnitError, "#{density_unit_value} is not a density" if !density_unit_value.density? + @density = density_unit_value + end + + def convert(value_unit) + if value_unit.mass? + unit = value_unit.unit.metric? ? 'ml' : 'cup' + value_unit.convert(unit, @density).auto_unit + else + value_unit + end + end + end + + class MassUnitConversion < Conversion + def initialize(density_unit_value) + raise UnknownUnitError, "#{density_unit_value} is not a density" if !density_unit_value.density? + @density = density_unit_value + end + + def convert(value_unit) + if value_unit.volume? + unit = value_unit.unit.metric? ? 'g' : 'oz' + value_unit.convert(unit, @density).auto_unit + else + value_unit + end + end + end + end diff --git a/lib/unit_conversion/value_unit.rb b/lib/unit_conversion/value_unit.rb index 3521309..4623ca0 100644 --- a/lib/unit_conversion/value_unit.rb +++ b/lib/unit_conversion/value_unit.rb @@ -4,6 +4,10 @@ module UnitConversion def self.for(value_string, unit_string = nil, formatter = nil) raise UnparseableUnitError, "value is empty" if value_string.blank? + if ValueUnit === value_string + return value_string + end + if String === value_string && unit_string.nil? value_string, unit_string = parse_single_string(value_string) end @@ -97,6 +101,24 @@ module UnitConversion AutoUnitConversion.new.convert(self) end + def to_metric + MetricUnitConversion.new.convert(self) + end + + def to_standard + StandardUnitConversion.new.convert(self) + end + + def to_mass(density) + parsed_density = ValueUnit.for(density) + MassUnitConversion.new(parsed_density).convert(self) + end + + def to_volume(density) + parsed_density = ValueUnit.for(density) + VolumeUnitConversion.new(parsed_density).convert(self) + end + def density? unit.density? end diff --git a/spec/lib/unit_conversion/conversions_spec.rb b/spec/lib/unit_conversion/conversions_spec.rb index c9e15ae..9420b15 100644 --- a/spec/lib/unit_conversion/conversions_spec.rb +++ b/spec/lib/unit_conversion/conversions_spec.rb @@ -26,6 +26,16 @@ RSpec.describe UnitConversion::Conversion do end end + describe UnitConversion::MetricUnitConversion do + it 'converts standard units' do + expect(UnitConversion::MetricUnitConversion.new.convert(get_value_unit(1, 'cup')).unit.to_s).to eq 'milliliter' + expect(UnitConversion::MetricUnitConversion.new.convert(get_value_unit(1, 'cup')).pretty_value).to eq '236.588' + + expect(UnitConversion::MetricUnitConversion.new.convert(get_value_unit(1, 'gallon')).unit.to_s).to eq 'liter' + expect(UnitConversion::MetricUnitConversion.new.convert(get_value_unit(1, 'gallon')).pretty_value).to eq '3.785' + end + end + describe UnitConversion::ConvertConversion do it 'converts standard units' do expect(UnitConversion::ConvertConversion.new(get_unit('tbsp')).convert(get_value_unit(1, 'cups')).raw_value).to eq 16