# frozen_string_literal: true
module Versionable
private
# Takes in a Template, phase, Section, Question, or Annotaion
# IF the template is published, generates a new template
# finds the passed object in the new template
#
# obj - Template, Phase, Section, Question, Annotation
#
# Returns ActiveRecord::Base
def get_modifiable(obj)
if obj.respond_to?(:template)
template = obj.template
elsif obj.is_a?(Template)
template = obj
else
raise ArgumentError,
_("obj should be a Template, Phase, Section, Question, or Annotation")
end
# raises RuntimeError if template is not latest
new_template = Template.find_or_generate_version!(template)
if new_template != template
if obj.is_a?(Template)
obj = new_template
else
obj = find_in_space(obj, new_template.phases)
end
end
obj
end
##
# Takes in a phase, Section, Question, or Annotation which is newly
# generated and returns a modifiable version of that object
# NOTE: the obj passed is still not saved however it should belongs to a
# parent already
def get_new(obj)
unless obj.respond_to?(:template)
raise ArgumentError,
_("obj should be a Phase, Section, Question, or Annotation")
end
template = obj.template
# raises RuntimeError if template is not latest
new_template = Template.find_or_generate_version!(template)
if new_template != template # Copied version
case obj
when Phase
belongs = :template
when Section
belongs = :phase
when Question
belongs = :section
when Annotation
belongs = :question
else
raise ArgumentError,
_("obj should be a Phase, Section, Question, or Annotation")
end
if belongs == :template
obj = obj.send(:deep_copy)
obj.template = new_template
else
found = find_in_space(obj.send(belongs), new_template.phases)
obj = obj.send(:deep_copy)
obj.send("#{belongs}=", found)
end
end
obj
end
# Locates an object (e.g. phase, section, question, annotation) in a
# search_space
# (e.g. phases/sections/questions/annotations) by comparing either the number
# method or the org_id and text for annotations
def find_in_space(obj, search_space)
unless search_space.respond_to?(:each)
raise ArgumentError, _("The search_space does not respond to each")
end
unless search_space.length > 0
raise ArgumentError,
_("The search space does not have elements associated")
end
if obj.is_a?(search_space.first.class)
# object is an instance of Phase, Section or Question
if obj.respond_to?(:number)
return search_space.find { |search| search.number == obj.number }
# object is an instance of Annotation
elsif obj.respond_to?(:org_id) && obj.respond_to?(:text)
return search_space.find do |annotation|
annotation.org_id == obj.org_id && annotation.text == obj.text
end
end
return nil
end
case search_space.first
when Phase
number = obj.phase.number
relation = :sections
when Section
number = obj.section.number
relation = :questions
when Question
number = obj.question.number
relation = :annotations
else
return nil
end
search_space = search_space.find { |search| search.number == number }
if search_space.present?
return find_in_space(obj, search_space.send(relation))
end
nil
end
end