class ReportElement < ActiveRecord::Base enum type_of: Extends::REPORT_ELEMENT_TYPES # This is only used by certain elements enum sort_order: { asc: 0, desc: 1 } validates :position, presence: true validates :report, presence: true validates :type_of, presence: true validate :has_one_of_referenced_elements belongs_to :report, inverse_of: :report_elements # Hierarchical structure representation has_many :children, -> { order(:position) }, class_name: 'ReportElement', foreign_key: 'parent_id', dependent: :destroy belongs_to :parent, class_name: 'ReportElement' # References to various report entities belongs_to :project, inverse_of: :report_elements belongs_to :experiment, inverse_of: :report_elements belongs_to :my_module, inverse_of: :report_elements belongs_to :step, inverse_of: :report_elements belongs_to :result, inverse_of: :report_elements belongs_to :checklist, inverse_of: :report_elements belongs_to :asset, inverse_of: :report_elements belongs_to :table, inverse_of: :report_elements def has_children? children.length > 0 end def result? result_asset? or result_table? or result_text? end def comments? step_comments? or result_comments? end # Get the referenced element (previously, element's type_of must be set) def element_reference ReportExtends::ELEMENT_REFERENCES.each do |el_ref| return eval(el_ref.element.gsub('_id', '')) if el_ref.check(self) end end # Set the element reference (previously, element's type_of must be set) def set_element_reference(ref_id) ReportExtends::SET_ELEMENT_REFERENCES_LIST.each do |el_ref| check = el_ref.check(self) next unless check public_send("#{el_ref.element}=", ref_id) break end end # removes element that are archived or deleted def clean_removed_or_archived_elements parent_model = '' %w(project experiment my_module step result checklist asset table) .each do |el| parent_model = el if send el end if parent_model == 'experiment' destroy unless send(parent_model).project == report.project elsif parent_model == 'step' destroy unless send(parent_model).completed else destroy unless (send(parent_model).active? rescue send(parent_model)) end end private def has_one_of_referenced_elements num_of_refs = [project, experiment, my_module, step, result, checklist, asset, table].count { |r| r.present? } if num_of_refs != 1 errors.add(:base, 'Report element must have exactly one element reference.') end end end