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 return 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 return 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 return nil end end