-
Notifications
You must be signed in to change notification settings - Fork 118
Expand file tree
/
Copy pathversionable.rb
More file actions
136 lines (120 loc) · 4.16 KB
/
versionable.rb
File metadata and controls
136 lines (120 loc) · 4.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# frozen_string_literal: true
# Helpers that allow us to version Template-Phase-Section-Question
module Versionable
private
# Takes in a Template, phase, Section, Question, or Annotation
# 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
obj = if obj.is_a?(Template)
new_template
else
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
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
# rubocop:disable Metrics/CyclomaticComplexity
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
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
# rubocop:enable Metrics/CyclomaticComplexity
# 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
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
def find_in_space(obj, search_space)
raise ArgumentError, _('The search_space does not respond to each') unless search_space.respond_to?(:each)
if search_space.empty?
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
return search_space.find { |search| search.number == obj.number } if obj.respond_to?(:number)
# object is an instance of Annotation
if 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 = if obj.is_a?(QuestionOption)
:question_options
else
:annotations
end
else
return nil
end
search_space = search_space.find { |search| search.number == number }
return find_in_space(obj, search_space.send(relation)) if search_space.present?
nil
end
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
end