Removed ITEM_TYPES in favor of uniformly named scopes/attributes
This commit is contained in:
parent
7584c650da
commit
c402fe8353
@ -16,12 +16,16 @@ class Food < ActiveRecord::Base
|
||||
belongs_to :ref_unit, class_name: 'Unit', required: true
|
||||
belongs_to :source, required: false
|
||||
has_many :ingredients, dependent: :restrict_with_error
|
||||
has_many :nutrients, foreign_key: 'registry_id', inverse_of: :food, dependent: :destroy,
|
||||
validate: true
|
||||
|
||||
DOMAIN = :diet
|
||||
alias_attribute :subitems, :nutrients
|
||||
scope :subitems, -> { includes(nutrients: [:quantity, :unit]) }
|
||||
|
||||
has_many :nutrients, inverse_of: :food, dependent: :destroy, validate: true
|
||||
validates :nutrients, presence: true
|
||||
accepts_nested_attributes_for :nutrients, allow_destroy: true, reject_if: proc { |attrs|
|
||||
attrs['quantity_id'].blank? && attrs['amount'].blank?
|
||||
}
|
||||
accepts_nested_attributes_for :nutrients, allow_destroy: true,
|
||||
reject_if: proc { |attrs| attrs['quantity_id'].blank? && attrs['amount'].blank? }
|
||||
# Nutrient quantity_id uniqueness check for nested attributes
|
||||
validate do
|
||||
quantities = self.nutrients.reject { |n| n.marked_for_destruction? }
|
||||
|
@ -2,6 +2,11 @@ class Ingredient < ActiveRecord::Base
|
||||
belongs_to :composition, inverse_of: :ingredients, polymorphic: true, required: true
|
||||
belongs_to :food, required: true
|
||||
belongs_to :part_of, required: false
|
||||
has_many :nutrients, through: :food, source: :nutrients
|
||||
|
||||
DOMAIN = :diet
|
||||
alias_attribute :subitems, :nutrients
|
||||
scope :subitems, -> { includes(nutrients: [:quantity, :unit]) }
|
||||
|
||||
validates :ready_ratio, numericality: {greater_than_or_equal_to: 0.0}
|
||||
validates :amount, numericality: {greater_than_or_equal_to: 0.0}
|
||||
|
@ -1,19 +1,22 @@
|
||||
class Measurement < ActiveRecord::Base
|
||||
belongs_to :routine, required: true, inverse_of: :measurements,
|
||||
class_name: 'MeasurementRoutine'
|
||||
accepts_nested_attributes_for :routine, allow_destroy: true, reject_if: proc { |attrs|
|
||||
attrs['name'].blank?
|
||||
}
|
||||
after_destroy { self.routine.destroy if self.routine.measurements.empty? }
|
||||
has_one :project, through: :routine
|
||||
|
||||
belongs_to :source, required: false
|
||||
has_one :project, through: :routine
|
||||
has_many :readouts, foreign_key: 'registry_id', inverse_of: :measurement,
|
||||
dependent: :destroy, validate: true
|
||||
|
||||
DOMAIN = :measurement
|
||||
alias_attribute :subitems, :readouts
|
||||
scope :subitems, -> { includes(readouts: [:quantity, :unit]) }
|
||||
|
||||
accepts_nested_attributes_for :routine, allow_destroy: true,
|
||||
reject_if: proc { |attrs| attrs['name'].blank? }
|
||||
after_destroy { self.routine.destroy if self.routine.measurements.empty? }
|
||||
|
||||
has_many :readouts, inverse_of: :measurement, dependent: :destroy, validate: true
|
||||
validates :readouts, presence: true
|
||||
accepts_nested_attributes_for :readouts, allow_destroy: true, reject_if: proc { |attrs|
|
||||
attrs['quantity_id'].blank? && attrs['value'].blank?
|
||||
}
|
||||
accepts_nested_attributes_for :readouts, allow_destroy: true,
|
||||
reject_if: proc { |attrs| attrs['quantity_id'].blank? && attrs['value'].blank? }
|
||||
# Readout quantity_id + unit_id uniqueness validation. Cannot be effectively
|
||||
# checked on Readout model level.
|
||||
validate do
|
||||
|
@ -1,9 +1,10 @@
|
||||
class Nutrient < QuantityValue
|
||||
belongs_to :food, inverse_of: :nutrients, required: true
|
||||
belongs_to :food, foreign_key: 'registry_id', inverse_of: :nutrients, required: true
|
||||
|
||||
validates :value, numericality: {greater_than_or_equal_to: 0.0}
|
||||
# Uniqueness NOT validated here, see Value for explanation
|
||||
#validates :quantity, uniqueness: {scope: :food_id}
|
||||
validates :value, numericality: {greater_than_or_equal_to: 0.0}
|
||||
|
||||
alias_attribute :amount, :value
|
||||
delegate :ref_amount, to: :food
|
||||
end
|
||||
|
@ -1,7 +1,7 @@
|
||||
class Readout < QuantityValue
|
||||
belongs_to :measurement, inverse_of: :readouts, required: true
|
||||
belongs_to :measurement, foreign_key: 'registry_id', inverse_of: :readouts, required: true
|
||||
|
||||
validates :value, numericality: true
|
||||
# Uniqueness NOT validated here, see Value for explanation
|
||||
#validates :quantity, uniqueness: {scope: [:measurement_id, :unit_id]}
|
||||
validates :value, numericality: true
|
||||
end
|
||||
|
@ -1,23 +1,5 @@
|
||||
module BodyTracking
|
||||
module ItemsWithQuantities
|
||||
ITEM_TYPES = {
|
||||
'Ingredient' => {
|
||||
domain: :diet,
|
||||
associations: [:food, :nutrients],
|
||||
value_field: :amount
|
||||
},
|
||||
'Food' => {
|
||||
domain: :diet,
|
||||
associations: [:nutrients],
|
||||
value_field: :amount
|
||||
},
|
||||
'Measurement' => {
|
||||
domain: :measurement,
|
||||
associations: [:readouts],
|
||||
value_field: :value
|
||||
}
|
||||
}
|
||||
|
||||
def filter(filters, requested_q = nil)
|
||||
items = all
|
||||
|
||||
@ -33,11 +15,10 @@ module BodyTracking
|
||||
if filters[:formula][:code].present?
|
||||
owner = proxy_association.owner
|
||||
project = owner.is_a?(Project) ? owner : owner.project
|
||||
domain = ITEM_TYPES[proxy_association.klass.name][:domain]
|
||||
filter_q_attrs = {
|
||||
name: 'Filter formula',
|
||||
formula_attributes: filters[:formula],
|
||||
domain: domain
|
||||
domain: proxy_association.klass::DOMAIN
|
||||
}
|
||||
project.quantities.new(filter_q_attrs)
|
||||
end
|
||||
@ -56,23 +37,10 @@ module BodyTracking
|
||||
def compute_quantities(requested_q, filter_q = nil)
|
||||
items = all
|
||||
|
||||
item_type = ITEM_TYPES[proxy_association.klass.name]
|
||||
subitems = Hash.new { |h,k| h[k] = {} }
|
||||
# Ingredient.includes(food: {nutrients: [:quantity, :unit]}).order('quantities.lft')
|
||||
# Food.includes(nutrients: [:quantity, :unit]).order('quantities.lft')
|
||||
includes = item_type[:associations].reverse
|
||||
.inject([:quantity, :unit]) { |relation, assoc| {assoc => relation} }
|
||||
all.includes(includes).order('quantities.lft').each do |i|
|
||||
item_type[:associations].inject(i) { |o, m| o.send(m) }.each do |s|
|
||||
subitem_value =
|
||||
if i.respond_to?(item_type[:value_field])
|
||||
s_value = s.send(item_type[:value_field])
|
||||
i_value = i.send(item_type[:value_field])
|
||||
# NOTE: for now scaling is designed only for Ingredients
|
||||
s_value * i_value / i.food.ref_amount
|
||||
else
|
||||
s.send(item_type[:value_field])
|
||||
end
|
||||
all.subitems.order('quantities.lft').each do |i|
|
||||
i.subitems.each do |s|
|
||||
subitem_value = i.respond_to?(:amount) ? i.amount*s.amount/s.ref_amount : s.value
|
||||
subitems[s.quantity][i] = [subitem_value, s.unit]
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user