diff --git a/app/controllers/targets_controller.rb b/app/controllers/targets_controller.rb new file mode 100644 index 0000000..0a4077b --- /dev/null +++ b/app/controllers/targets_controller.rb @@ -0,0 +1,24 @@ +class TargetsController < ApplicationController + layout 'body_tracking' + menu_item :body_trackers + helper :body_trackers + + include Concerns::Finders + + before_action :find_project_by_project_id, only: [:index] + + def index + prepare_targets + end + + def new + @target = @project.targets.new + @target.arity.times { @target.thresholds.new } + end + + private + + def prepare_targets + @targets = @project.targets.includes(:item, :thresholds) + end +end diff --git a/app/models/goal.rb b/app/models/goal.rb new file mode 100644 index 0000000..051b921 --- /dev/null +++ b/app/models/goal.rb @@ -0,0 +1,6 @@ +class Goal < ActiveRecord::Base + belongs_to :project, required: true + has_many :targets, inverse_of: :goal, dependent: :destroy + + validates :name, presence: true, uniqueness: {scope: :project_id} +end diff --git a/app/models/ingredient.rb b/app/models/ingredient.rb index 81c78ea..3d48dc0 100644 --- a/app/models/ingredient.rb +++ b/app/models/ingredient.rb @@ -2,7 +2,7 @@ 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 + has_many :nutrients, through: :food DOMAIN = :diet alias_attribute :subitems, :nutrients diff --git a/app/models/nutrient.rb b/app/models/nutrient.rb index 1d75aed..1fdbbba 100644 --- a/app/models/nutrient.rb +++ b/app/models/nutrient.rb @@ -1,6 +1,8 @@ class Nutrient < QuantityValue - belongs_to :food, foreign_key: 'registry_id', foreign_type: 'registry_type', - inverse_of: :nutrients, polymorphic: true, required: true + # Need to specify polymorphic association so :registry_type gets written (see + # QuantityValue for explanation why it's needed) + belongs_to :food, inverse_of: :nutrients, polymorphic: true, required: true, + foreign_key: 'registry_id', foreign_type: 'registry_type' # Uniqueness NOT validated here, see Value for explanation #validates :quantity, uniqueness: {scope: :food_id} diff --git a/app/models/quantity.rb b/app/models/quantity.rb index 74f5118..4d5fb66 100644 --- a/app/models/quantity.rb +++ b/app/models/quantity.rb @@ -9,6 +9,7 @@ class Quantity < ActiveRecord::Base belongs_to :project, inverse_of: :quantities, required: false has_many :nutrients, dependent: :restrict_with_error has_many :readouts, dependent: :restrict_with_error + has_many :thresholds, dependent: :restrict_with_error has_many :values, class_name: 'QuantityValue', dependent: :restrict_with_error has_many :exposures, dependent: :destroy diff --git a/app/models/quantity_value.rb b/app/models/quantity_value.rb index 9dd04b1..ca1c740 100644 --- a/app/models/quantity_value.rb +++ b/app/models/quantity_value.rb @@ -1,5 +1,9 @@ class QuantityValue < ActiveRecord::Base # Requirement validation for :registry left to subclasses + # Polymorphic registry (including :registry_type) is required - despite 1:1 + # mapping between Nutrient:Food, Readout:Measurement, Threshold:Target ... - + # to allow for accessing registry item without knowing QuantityValue (subitem) + # type, e.g. qv.registry.completed_at belongs_to :registry, polymorphic: true belongs_to :quantity, required: true belongs_to :unit, required: true diff --git a/app/models/readout.rb b/app/models/readout.rb index 6c7834a..09789d0 100644 --- a/app/models/readout.rb +++ b/app/models/readout.rb @@ -1,6 +1,8 @@ class Readout < QuantityValue - belongs_to :measurement, foreign_key: 'registry_id', foreign_type: 'registry_type', - inverse_of: :readouts, polymorphic: true, required: true + # Need to specify polymorphic association so :registry_type gets written (see + # QuantityValue for explanation why it's needed) + belongs_to :measurement, inverse_of: :readouts, polymorphic: true, required: true, + foreign_key: 'registry_id', foreign_type: 'registry_type' # Uniqueness NOT validated here, see Value for explanation #validates :quantity, uniqueness: {scope: [:measurement_id, :unit_id]} diff --git a/app/models/target.rb b/app/models/target.rb index 96d273f..402271e 100644 --- a/app/models/target.rb +++ b/app/models/target.rb @@ -10,5 +10,16 @@ class Target < ActiveRecord::Base # TODO: validate thresholds count according to condition type validates :condition, inclusion: {in: [:<, :<=, :>, :>=, :==]} validates :scope, inclusion: {in: [:day], if: -> { thresholds.first.domain == :diet }} - validates :effective_from, presence: {unless: goal?}, absence: {if: goal?} + validates :effective_from, presence: {unless: -> { goal.present? }}, + absence: {if: -> { goal.present? }} + + after_initialize do + if new_record? + self.condition = :< + end + end + + def arity + BigDecimal.method(condition).arity + end end diff --git a/app/models/threshold.rb b/app/models/threshold.rb index 54f6ad1..742da1e 100644 --- a/app/models/threshold.rb +++ b/app/models/threshold.rb @@ -1,6 +1,8 @@ class Threshold < QuantityValue - belongs_to :target, foreign_key: 'registry_id', foreign_type: 'foreign_type', - inverse_of: :thresholds, polymorphic: true, required: true + # Need to specify polymorphic association so :registry_type gets written (see + # QuantityValue for explanation why it's needed) + belongs_to :target, inverse_of: :thresholds, polymorphic: true, required: true, + foreign_key: 'registry_id', foreign_type: 'registry_type' validates :value, numericality: true end diff --git a/app/views/layouts/_sidebar.html.erb b/app/views/layouts/_sidebar.html.erb index 7ea4167..7d083c9 100644 --- a/app/views/layouts/_sidebar.html.erb +++ b/app/views/layouts/_sidebar.html.erb @@ -1,6 +1,12 @@
<%= l(:field_taken_at_date) %> | +<%= l(:field_name) %> | +<%= l(:field_notes) %> | +<%= l(:field_source) %> | +<%= l(:field_action) %> | +
---|---|---|---|---|
<%= format_datetime(m) %> | +
+
+ <%= link_to m.routine.name, readouts_measurement_routine_path(m.routine) %>
+
+
+ <%= " (#{pluralize(m.readouts.size, 'readout')})" %>
+
+ |
+ <%= m.notes %> | +<%= m.source.name if m.source.present? %> | +<%= action_links(m) %> | +
<%= l(:label_no_data) %>
+<% end %> diff --git a/app/views/targets/index.html.erb b/app/views/targets/index.html.erb new file mode 100644 index 0000000..b7ff56f --- /dev/null +++ b/app/views/targets/index.html.erb @@ -0,0 +1,11 @@ +