diff --git a/app/controllers/ingredients_controller.rb b/app/controllers/ingredients_controller.rb index ab5f9dc..abb03e5 100644 --- a/app/controllers/ingredients_controller.rb +++ b/app/controllers/ingredients_controller.rb @@ -49,7 +49,7 @@ class IngredientsController < ApplicationController end def toggle - @ingredient.update(hidden: !@ingredient.hidden) + @ingredient.toggle_hidden! prepare_ingredients end diff --git a/app/controllers/measurements_controller.rb b/app/controllers/measurements_controller.rb index c8914fc..cebd91b 100644 --- a/app/controllers/measurements_controller.rb +++ b/app/controllers/measurements_controller.rb @@ -1,11 +1,68 @@ class MeasurementsController < ApplicationController + before_action :find_project_by_project_id, only: [:index, :create] + before_action :find_measurement, only: [:destroy, :toggle] + before_action :authorize def index + @measurement = @project.measurements.new + @measurement.readouts.new + + prepare_measurements + @measurements << @measurement end def create + @measurement = @project.measurements.new(measurement_params) + if @measurement.save + flash[:notice] = 'Created newmeasurement' + redirect_to :back + else + prepare_measurements + @measurement.readouts.new if @measurement.readouts.empty? + render :index + end end def destroy + # FIXME: don't destroy if there are any readout values + if @measurement.destroy + flash[:notice] = 'Deleted measurement' + end + prepare_measurements + render :toggle + end + + def toggle + @measurement.toggle_hidden! + prepare_measurements + end + + private + + def ingredient_params + params.require(:measurement).permit( + :name, + :source_id, + readouts_attributes: + [ + :id, + :quantity_id, + :unit_id, + :_destroy + ] + ) + end + + # :find_* methods are called before :authorize, + # @project is required for :authorize to succeed + def find_measurement + @measurement = Measurement.find(params[:id]) + @project = @measurement.project + rescue ActiveRecord::RecordNotFound + render_404 + end + + def prepare_measurements + @measurements = @project.measurements.includes(:source) end end diff --git a/app/models/ingredient.rb b/app/models/ingredient.rb index 7124795..70da695 100644 --- a/app/models/ingredient.rb +++ b/app/models/ingredient.rb @@ -37,6 +37,10 @@ class Ingredient < ActiveRecord::Base end end + def toggle_hidden! + self.toggle!(:hidden) + end + def self.filter(project, filters = {}, requested_q = Quantity.none) ingredients = all diff --git a/app/models/measurement.rb b/app/models/measurement.rb index 2c39ebe..8d8d5ac 100644 --- a/app/models/measurement.rb +++ b/app/models/measurement.rb @@ -1,2 +1,29 @@ class Measurement < ActiveRecord::Base + belongs_to :project, required: true + belongs_to :source, required: false + + 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? + } + # Readout (quantity_id, unit_id) pair uniqueness check for nested attributes + validate do + quantities = self.readouts.map { |r| [r.quantity_id, r.unit_id] } + if quantities.length != quantities.uniq.length + errors.add(:readouts, :duplicated_quantity) + end + end + + validates :name, presence: true, uniqueness: {scope: :project_id} + + after_initialize do + if new_record? + self.hidden = false if self.hidden.nil? + end + end + + def toggle_hidden! + self.toggle!(:hidden) + end end diff --git a/app/models/readout.rb b/app/models/readout.rb index 9f93031..b9ae2eb 100644 --- a/app/models/readout.rb +++ b/app/models/readout.rb @@ -1,2 +1,7 @@ class Readout < ActiveRecord::Base + belongs_to :measurement, inverse_of: :readouts, required: true + belongs_to :quantity, required: true + belongs_to :unit, required: true + + validates :quantity, uniqueness: {scope: [:ingredient_id, :unit_id]} end diff --git a/config/routes.rb b/config/routes.rb index d5dba6d..d6e999e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -7,6 +7,7 @@ resources :projects do post 'defaults', on: :collection end resources :measurements, :only => [:index, :create, :destroy] do + post 'toggle', on: :member end resources :ingredients, :only => [:index, :create, :destroy] do get 'nutrients', on: :collection diff --git a/init.rb b/init.rb index a6db291..e849639 100644 --- a/init.rb +++ b/init.rb @@ -24,7 +24,7 @@ Redmine::Plugin.register :body_tracking do }, read: true permission :manage_common, { :body_trackers => [:defaults], - :measurements => [:create, :destroy], + :measurements => [:create, :destroy, :toggle], :ingredients => [:create, :destroy, :toggle, :import, :toggle_nutrient_column], :sources => [:create, :destroy], :quantities => [:create, :destroy, :toggle, :up, :down, :left, :right], diff --git a/lib/body_tracking/project_patch.rb b/lib/body_tracking/project_patch.rb index ef00929..db60fb2 100644 --- a/lib/body_tracking/project_patch.rb +++ b/lib/body_tracking/project_patch.rb @@ -1,6 +1,7 @@ module BodyTracking module ProjectPatch Project.class_eval do + has_many :measurements, -> { order "name" }, dependent: :destroy has_many :ingredients, -> { order "name" }, dependent: :destroy has_many :sources, dependent: :destroy