From 3ce5d5c94043207ce8242ebd4068270e04b9c8fa Mon Sep 17 00:00:00 2001 From: cryptogopher Date: Fri, 15 Nov 2019 00:04:34 +0100 Subject: [PATCH] Fix migration of default quantities Allow Quantity formula to be nil but not blank Add computed energy quantity Reverse default quantities deletion order --- app/controllers/quantities_controller.rb | 1 + app/models/quantity.rb | 2 +- db/migrate/002_load_defaults.rb | 252 ++++++++++++----------- lib/body_tracking/formula.rb | 4 +- 4 files changed, 134 insertions(+), 125 deletions(-) diff --git a/app/controllers/quantities_controller.rb b/app/controllers/quantities_controller.rb index cb662be..03db0fb 100644 --- a/app/controllers/quantities_controller.rb +++ b/app/controllers/quantities_controller.rb @@ -59,6 +59,7 @@ class QuantitiesController < ApplicationController private def quantity_params + params[:quantity].delete(:formula) if params[:quantity][:formula].blank? params.require(:quantity).permit( :domain, :parent_id, diff --git a/app/models/quantity.rb b/app/models/quantity.rb index c9881fb..f2322fd 100644 --- a/app/models/quantity.rb +++ b/app/models/quantity.rb @@ -15,7 +15,7 @@ class Quantity < ActiveRecord::Base validate if: -> { parent.present? } do errors.add(:parent, :parent_domain_mismatch) unless domain == parent.domain end - validates :formula, formula: true + validates :formula, formula: {allow_nil: true} after_initialize do if new_record? diff --git a/db/migrate/002_load_defaults.rb b/db/migrate/002_load_defaults.rb index 9d2c10e..1437ed1 100644 --- a/db/migrate/002_load_defaults.rb +++ b/db/migrate/002_load_defaults.rb @@ -1,133 +1,141 @@ class LoadDefaults < ActiveRecord::Migration - reversible do |dir| - dir.up do - Unit.create project: nil, shortname: "g", name: "gram" - Unit.create project: nil, shortname: "mg", name: "milligram" - Unit.create project: nil, shortname: "ug", name: "microgram" - Unit.create project: nil, shortname: "kg", name: "kilogram" - Unit.create project: nil, shortname: "kcal", name: "kilocalorie" - Unit.create project: nil, shortname: "%", name: "percent" + def change + reversible do |dir| + dir.up do + Unit.create project: nil, shortname: "g", name: "gram" + Unit.create project: nil, shortname: "mg", name: "milligram" + Unit.create project: nil, shortname: "ug", name: "microgram" + Unit.create project: nil, shortname: "kg", name: "kilogram" + Unit.create project: nil, shortname: "kcal", name: "kilocalorie" + Unit.create project: nil, shortname: "%", name: "percent" - # https://www.fsai.ie/uploadedFiles/Consol_Reg1169_2011.pdf - # https://www.fsai.ie/legislation/food_legislation/food_information_fic/nutrition_labelling.html - e = Quantity.create project: nil, domain: :diet, parent: nil, name: "Energy", - description: "Total energy", primary: true + # https://www.fsai.ie/uploadedFiles/Consol_Reg1169_2011.pdf + # https://www.fsai.ie/legislation/food_legislation/food_information_fic/nutrition_labelling.html + e = Quantity.create project: nil, domain: :diet, parent: nil, name: "Energy", + description: "Total energy", primary: true - Quantity.create project: nil, domain: :diet, parent: nil, name: "Proteins", - description: "Total amount of proteins", primary: true + p = Quantity.create project: nil, domain: :diet, parent: nil, name: "Proteins", + description: "Total amount of proteins", primary: true - f = Quantity.create project: nil, domain: :diet, parent: nil, name: "Fats", - description: "Total lipids, including phospholipids", primary: true - f1 = Quantity.create project: nil, domain: :diet, parent: f, name: "Fatty acids", - description: "" - f2 = Quantity.create project: nil, domain: :diet, parent: f1, name: "Saturated", - description: "Fatty acids without double bond" - f3 = Quantity.create project: nil, domain: :diet, parent: f1, name: "Unsaturated", - description: "" - f4 = Quantity.create project: nil, domain: :diet, parent: f3, name: "Monounsaturated", - description: "Fatty acids with one cis double bond" - f5 = Quantity.create project: nil, domain: :diet, parent: f3, name: "Polyunsaturated", - description: "Fatty acids with two or more cis, cis-methylene interrupted" \ - " double bonds; PUFA" - f6 = Quantity.create project: nil, domain: :diet, parent: f3, name: "Trans", - description: "Fatty acids with at least one non-conjugated C-C double bond in the" \ - " trans configuration" - f7 = Quantity.create project: nil, domain: :diet, parent: f5, name: "Omega-3 (n-3)", - description: "" - f8 = Quantity.create project: nil, domain: :diet, parent: f5, name: "Omega-6 (n-6)", - description: "" - f9 = Quantity.create project: nil, domain: :diet, parent: f7, name: "ALA 18:3(n-3)", - description: "alpha-Linolenic acid" - f10 = Quantity.create project: nil, domain: :diet, parent: f7, name: "EPA 20:5(n-3)", - description: "Eicosapentaenoic acid; also icosapentaenoic acid" - f11 = Quantity.create project: nil, domain: :diet, parent: f7, name: "DHA 22:6(n-3)", - description: "Docosahexaenoic acid" + f = Quantity.create project: nil, domain: :diet, parent: nil, name: "Fats", + description: "Total lipids, including phospholipids", primary: true + f1 = Quantity.create project: nil, domain: :diet, parent: f, name: "Fatty acids", + description: "" + f2 = Quantity.create project: nil, domain: :diet, parent: f1, name: "Saturated", + description: "Fatty acids without double bond" + f3 = Quantity.create project: nil, domain: :diet, parent: f1, name: "Unsaturated", + description: "" + f4 = Quantity.create project: nil, domain: :diet, parent: f3, name: "Monounsaturated", + description: "Fatty acids with one cis double bond" + f5 = Quantity.create project: nil, domain: :diet, parent: f3, name: "Polyunsaturated", + description: "Fatty acids with two or more cis, cis-methylene interrupted" \ + " double bonds; PUFA" + f6 = Quantity.create project: nil, domain: :diet, parent: f3, name: "Trans", + description: "Fatty acids with at least one non-conjugated C-C double bond in the" \ + " trans configuration" + f7 = Quantity.create project: nil, domain: :diet, parent: f5, name: "Omega-3 (n-3)", + description: "" + f8 = Quantity.create project: nil, domain: :diet, parent: f5, name: "Omega-6 (n-6)", + description: "" + f9 = Quantity.create project: nil, domain: :diet, parent: f7, name: "ALA 18:3(n-3)", + description: "alpha-Linolenic acid" + f10 = Quantity.create project: nil, domain: :diet, parent: f7, name: "EPA 20:5(n-3)", + description: "Eicosapentaenoic acid; also icosapentaenoic acid" + f11 = Quantity.create project: nil, domain: :diet, parent: f7, name: "DHA 22:6(n-3)", + description: "Docosahexaenoic acid" - c1 = Quantity.create project: nil, domain: :diet, parent: nil, name: "Carbohydrates", - description: "Total amount of carbohydrates", primary: true - c2 = Quantity.create project: nil, domain: :diet, parent: c1, name: "Digestible", - description: "" - c3 = Quantity.create project: nil, domain: :diet, parent: c2, name: "Sugars", - description: "Monosaccharides and disaccharides, excluding polyols" - c4 = Quantity.create project: nil, domain: :diet, parent: c3, name: "Monosaccharides", - description: "" - c5 = Quantity.create project: nil, domain: :diet, parent: c4, name: "Glucose", - description: "" - c6 = Quantity.create project: nil, domain: :diet, parent: c4, name: "Fructose", - description: "" - c7 = Quantity.create project: nil, domain: :diet, parent: c3, name: "Disaccharides", - description: "" - c8 = Quantity.create project: nil, domain: :diet, parent: c7, name: "Sucrose", - description: "" - c9 = Quantity.create project: nil, domain: :diet, parent: c7, name: "Lactose", - description: "" - c10 = Quantity.create project: nil, domain: :diet, parent: c2, name: "Polyols", - description: "Alcohols containing more than 2 hydroxyl groups" - c11 = Quantity.create project: nil, domain: :diet, parent: c2, - name: "Polysaccharides", description: "" - c12 = Quantity.create project: nil, domain: :diet, parent: c11, name: "Starch", - description: "" - c13 = Quantity.create project: nil, domain: :diet, parent: c1, name: "Indigestible", - description: "" - c14 = Quantity.create project: nil, domain: :diet, parent: c13, name: "Fibre", - description: "Carbohydrate polymers with 3 or more monomeric units, which are" \ - " neither digested nor absorbed in the human small intestine" + c1 = Quantity.create project: nil, domain: :diet, parent: nil, name: "Carbohydrates", + description: "Total amount of carbohydrates", primary: true + c2 = Quantity.create project: nil, domain: :diet, parent: c1, name: "Digestible", + description: "" + c3 = Quantity.create project: nil, domain: :diet, parent: c2, name: "Sugars", + description: "Monosaccharides and disaccharides, excluding polyols" + c4 = Quantity.create project: nil, domain: :diet, parent: c3, name: "Monosaccharides", + description: "" + c5 = Quantity.create project: nil, domain: :diet, parent: c4, name: "Glucose", + description: "" + c6 = Quantity.create project: nil, domain: :diet, parent: c4, name: "Fructose", + description: "" + c7 = Quantity.create project: nil, domain: :diet, parent: c3, name: "Disaccharides", + description: "" + c8 = Quantity.create project: nil, domain: :diet, parent: c7, name: "Sucrose", + description: "" + c9 = Quantity.create project: nil, domain: :diet, parent: c7, name: "Lactose", + description: "" + c10 = Quantity.create project: nil, domain: :diet, parent: c2, name: "Polyols", + description: "Alcohols containing more than 2 hydroxyl groups" + c11 = Quantity.create project: nil, domain: :diet, parent: c2, + name: "Polysaccharides", description: "" + c12 = Quantity.create project: nil, domain: :diet, parent: c11, name: "Starch", + description: "" + c13 = Quantity.create project: nil, domain: :diet, parent: c1, name: "Indigestible", + description: "" + c14 = Quantity.create project: nil, domain: :diet, parent: c13, name: "Fibre", + description: "Carbohydrate polymers with 3 or more monomeric units, which are" \ + " neither digested nor absorbed in the human small intestine" - m1 = Quantity.create project: nil, domain: :diet, parent: nil, name: "Minerals", - description: "" - m2 = Quantity.create project: nil, domain: :diet, parent: m1, name: "Salt", - description: "Sodium chloride" + m1 = Quantity.create project: nil, domain: :diet, parent: nil, name: "Minerals", + description: "" + m2 = Quantity.create project: nil, domain: :diet, parent: m1, name: "Salt", + description: "Sodium chloride" - v1 = Quantity.create project: nil, domain: :diet, parent: nil, name: "Vitamins", - description: "" - v2 = Quantity.create project: nil, domain: :diet, parent: v1, name: "Vitamin A", - description: "" - v3 = Quantity.create project: nil, domain: :diet, parent: v2, name: "Retinol (A1)", - description: "" - v4 = Quantity.create project: nil, domain: :diet, parent: v1, name: "Provitamin A", - description: "" - v5 = Quantity.create project: nil, domain: :diet, parent: v4, name: "beta-Carotene", - description: "" - v6 = Quantity.create project: nil, domain: :diet, parent: v1, name: "Vitamin B", - description: "" - v7 = Quantity.create project: nil, domain: :diet, parent: v6, name: "Thiamine (B1)", - description: "" - v8 = Quantity.create project: nil, domain: :diet, parent: v6, name: "Riboflavin (B2)", - description: "Vitamin G" - v9 = Quantity.create project: nil, domain: :diet, parent: v6, name: "Vitamin B3", - description: "Vitamin PP" - v10 = Quantity.create project: nil, domain: :diet, parent: v9, name: "Niacin", - description: "Nicotinic acid" - v11 = Quantity.create project: nil, domain: :diet, parent: v6, name: "Vitamin B5", - description: "Pantothenic acid" - v12 = Quantity.create project: nil, domain: :diet, parent: v6, name: "Vitamin B6", - description: "" - v13 = Quantity.create project: nil, domain: :diet, parent: v6, name: "Biotin (B7)", - description: "Vitamin H, also coenzyme R" - v14 = Quantity.create project: nil, domain: :diet, parent: v6, name: "Folate", - description: "Includes: folic acid, folacin and vitamin B9" - v15 = Quantity.create project: nil, domain: :diet, parent: v14, name: "Vitamin B9", - description: "" - v16 = Quantity.create project: nil, domain: :diet, parent: v6, - name: "Cobalamin (B12)", description: "" - v17 = Quantity.create project: nil, domain: :diet, parent: v1, name: "Vitamin C", - description: "" - v18 = Quantity.create project: nil, domain: :diet, parent: v1, name: "Vitamin D", - description: "Calciferol" - v19 = Quantity.create project: nil, domain: :diet, parent: v18, - name: "Cholecalciferol (D3)", description: "" - v20 = Quantity.create project: nil, domain: :diet, parent: v1, name: "Vitamin E", - description: "" - v21 = Quantity.create project: nil, domain: :diet, parent: v1, name: "Vitamin K", - description: "" + v1 = Quantity.create project: nil, domain: :diet, parent: nil, name: "Vitamins", + description: "" + v2 = Quantity.create project: nil, domain: :diet, parent: v1, name: "Vitamin A", + description: "" + v3 = Quantity.create project: nil, domain: :diet, parent: v2, name: "Retinol (A1)", + description: "" + v4 = Quantity.create project: nil, domain: :diet, parent: v1, name: "Provitamin A", + description: "" + v5 = Quantity.create project: nil, domain: :diet, parent: v4, name: "beta-Carotene", + description: "" + v6 = Quantity.create project: nil, domain: :diet, parent: v1, name: "Vitamin B", + description: "" + v7 = Quantity.create project: nil, domain: :diet, parent: v6, name: "Thiamine (B1)", + description: "" + v8 = Quantity.create project: nil, domain: :diet, parent: v6, name: "Riboflavin (B2)", + description: "Vitamin G" + v9 = Quantity.create project: nil, domain: :diet, parent: v6, name: "Vitamin B3", + description: "Vitamin PP" + v10 = Quantity.create project: nil, domain: :diet, parent: v9, name: "Niacin", + description: "Nicotinic acid" + v11 = Quantity.create project: nil, domain: :diet, parent: v6, name: "Vitamin B5", + description: "Pantothenic acid" + v12 = Quantity.create project: nil, domain: :diet, parent: v6, name: "Vitamin B6", + description: "" + v13 = Quantity.create project: nil, domain: :diet, parent: v6, name: "Biotin (B7)", + description: "Vitamin H, also coenzyme R" + v14 = Quantity.create project: nil, domain: :diet, parent: v6, name: "Folate", + description: "Includes: folic acid, folacin and vitamin B9" + v15 = Quantity.create project: nil, domain: :diet, parent: v14, name: "Vitamin B9", + description: "" + v16 = Quantity.create project: nil, domain: :diet, parent: v6, + name: "Cobalamin (B12)", description: "" + v17 = Quantity.create project: nil, domain: :diet, parent: v1, name: "Vitamin C", + description: "" + v18 = Quantity.create project: nil, domain: :diet, parent: v1, name: "Vitamin D", + description: "Calciferol" + v19 = Quantity.create project: nil, domain: :diet, parent: v18, + name: "Cholecalciferol (D3)", description: "" + v20 = Quantity.create project: nil, domain: :diet, parent: v1, name: "Vitamin E", + description: "" + v21 = Quantity.create project: nil, domain: :diet, parent: v1, name: "Vitamin K", + description: "" - Source.create project: nil, name: "nutrition label", - description: "nutrition facts taken from package nutrition label" - end - dir.down do - Unit.where(project: nil).delete_all - Quantity.where(project: nil).delete_all - Source.where(project: nil).delete_all + # Calculated quantities go at the and to make sure dependencies exist + e1 = Quantity.create project: nil, domain: :diet, parent: e, name: "Calculated", + description: "Total energy calculated from macronutrients", primary: true, + formula: "4*Proteins + 9*Fats + 4*Carbohydrates" + + Source.create project: nil, name: "nutrition label", + description: "nutrition facts taken from package nutrition label" + end + + dir.down do + Source.where(project: nil).delete_all + Quantity.where(project: nil).delete_all + Unit.where(project: nil).delete_all + end end end end diff --git a/lib/body_tracking/formula.rb b/lib/body_tracking/formula.rb index 77d38b8..a1c899b 100644 --- a/lib/body_tracking/formula.rb +++ b/lib/body_tracking/formula.rb @@ -7,7 +7,7 @@ module BodyTracking class InvalidFormula < RuntimeError; end class Formula def initialize(project, formula) - @project = project + @project_quantities = Quantity.where(project: project) @formula = formula @paramed_formula = nil @quantities = nil @@ -79,7 +79,7 @@ module BodyTracking # 4th: check if identifiers used in formula correspond to existing quantities identifiers.uniq! - quantities = @project.quantities.where(name: identifiers) + quantities = @project_quantities.where(name: identifiers) quantities_names = quantities.pluck(:name) (identifiers - quantities_names).each do |q| errors << [:unknown_quantity, {quantity: q}]