active_record_survey 0.1.43 → 0.1.44

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5dc949333e22faad454c71dbdc2cd63088cd71cf
4
- data.tar.gz: d341536053150cdfcca45862094780537de92539
3
+ metadata.gz: f946ba156789de15394c69e91b562a102b046b57
4
+ data.tar.gz: f10f2b482a0522dff5028172205e69c56762b072
5
5
  SHA512:
6
- metadata.gz: 6ebc9abf180663238c747ba7173754435148a1b9bf99c996825dd864bed8f25f0cbc96b14ad987ecc65ecf4d382cab28c60a7071056472c13240e8ced7709581
7
- data.tar.gz: 0b85ef3c7fef633bcfc843a3782114fd5dac5884b48993c0a936d35737f4c873e0e989bdd696532653533127574846e49b647ff542d3e73b4ec6bdefe734acb3
6
+ metadata.gz: 043b935b0cb4a714811685febc81d6d67c7bac689dca3916f11749e292da71c7fbe7c946a01710353cf7eeb9dc980d653ef7668755207a26329ec06e3e0528dc
7
+ data.tar.gz: 00d73a743e0874b61d6387f3f1590ba69788161d06068875923e8440bca76342e8e70039a0911f0bdd3801e5fd559768d7c5f021e4ccbe8f267474386fa67df4
@@ -7,6 +7,7 @@ module ActiveRecordSurvey
7
7
  end
8
8
 
9
9
  module InstanceMethods
10
+
10
11
  # Gets index relative to other chained answers
11
12
  def sibling_index
12
13
  if node_map = self.survey.node_maps.select { |i|
@@ -18,6 +19,23 @@ module ActiveRecordSurvey
18
19
  return 0
19
20
  end
20
21
 
22
+ # Chain nodes are different
23
+ # They must also see if this answer linked to subsequent answers, and re-build the link
24
+ def remove_answer(question_node)
25
+ self.survey = question_node.survey
26
+
27
+ # The node from answer from the parent question
28
+ self.survey.node_maps.reverse.select { |i|
29
+ i.node == self && !i.marked_for_destruction?
30
+ }.each { |answer_node_map|
31
+ answer_node_map.children.each { |child|
32
+ answer_node_map.parent.children << child
33
+ }
34
+
35
+ answer_node_map.send((answer_node_map.new_record?)? :destroy : :mark_for_destruction )
36
+ }
37
+ end
38
+
21
39
  # Chain nodes are different - they must find the final answer node added and add to it
22
40
  # They must also see if the final answer node then points somewhere else - and fix the links on that
23
41
  def build_answer(question_node)
@@ -25,6 +43,14 @@ module ActiveRecordSurvey
25
43
 
26
44
  question_node_maps = self.survey.node_maps.select { |i| i.node == question_node && !i.marked_for_destruction? }
27
45
 
46
+ answer_node_maps = self.survey.node_maps.select { |i|
47
+ i.node == self && i.parent.nil?
48
+ }.collect { |i|
49
+ i.survey = self.survey
50
+
51
+ i
52
+ }
53
+
28
54
  # No node_maps exist yet from this question
29
55
  if question_node_maps.length === 0
30
56
  # Build our first node-map
@@ -36,18 +62,23 @@ module ActiveRecordSurvey
36
62
  # Each instance of this question needs the answer hung from it
37
63
  self.survey.node_maps.select { |i|
38
64
  i.node == last_answer_in_chain
39
- }.each { |node_map|
40
- curr_children = self.survey.node_maps.select { |j|
41
- node_map.children.include?(j)
42
- }
65
+ }.each_with_index { |node_map, index|
66
+ if answer_node_maps[index]
67
+ new_node_map = answer_node_maps[index]
68
+ else
69
+ new_node_map = self.survey.node_maps.build(:node => self, :survey => self.survey)
70
+ end
43
71
 
44
- new_node_map = self.survey.node_maps.build(:node => self, :survey => self.survey)
72
+ # Hack - should fix this - why does self.survey.node_maps still think... yea somethigns not referenced right
73
+ #curr_children = self.survey.node_maps.select { |j|
74
+ # node_map.children.include?(j) && j != new_node_map
75
+ #}
45
76
 
46
77
  node_map.children << new_node_map
47
78
 
48
- curr_children.each { |c|
49
- new_node_map.children << c
50
- }
79
+ #curr_children.each { |c|
80
+ # new_node_map.children << c
81
+ #}
51
82
  }
52
83
 
53
84
  true
@@ -140,12 +140,35 @@ module ActiveRecordSurvey
140
140
  end
141
141
 
142
142
  private
143
+ # By default - answers build off the original question node
144
+ #
145
+ # This allows us to easily override the answer removal behaviour for different answer types
146
+ def remove_answer(question_node)
147
+ #self.survey = question_node.survey
148
+
149
+ # The node from answer from the parent question
150
+ self.survey.node_maps.select { |i|
151
+ !i.marked_for_destruction? &&
152
+ i.node == self && i.parent && i.parent.node === question_node
153
+ }.each { |answer_node_map|
154
+ answer_node_map.send((answer_node_map.new_record?)? :destroy : :mark_for_destruction )
155
+ }
156
+ end
157
+
143
158
  # By default - answers build off the original question node
144
159
  #
145
160
  # This allows us to easily override the answer building behaviour for different answer types
146
161
  def build_answer(question_node)
147
162
  self.survey = question_node.survey
148
163
 
164
+ answer_node_maps = self.survey.node_maps.select { |i|
165
+ i.node == self && i.parent.nil?
166
+ }.collect { |i|
167
+ i.survey = self.survey
168
+
169
+ i
170
+ }
171
+
149
172
  question_node_maps = self.survey.node_maps.select { |i| i.node == question_node && !i.marked_for_destruction? }
150
173
 
151
174
  # No node_maps exist yet from this question
@@ -155,8 +178,14 @@ module ActiveRecordSurvey
155
178
  end
156
179
 
157
180
  # Each instance of this question needs the answer hung from it
158
- question_node_maps.each { |question_node_map|
159
- question_node_map.children << self.survey.node_maps.build(:node => self, :survey => self.survey)
181
+ question_node_maps.each_with_index { |question_node_map, index|
182
+ if answer_node_maps[index]
183
+ new_node_map = answer_node_maps[index]
184
+ else
185
+ new_node_map = self.survey.node_maps.build(:node => self, :survey => self.survey)
186
+ end
187
+
188
+ question_node_map.children << new_node_map
160
189
  }
161
190
 
162
191
  true
@@ -7,6 +7,55 @@ module ActiveRecordSurvey
7
7
  }.include?(false)
8
8
  end
9
9
 
10
+ # Updates the answers of this question to a different type
11
+ def update_question_type(klass)
12
+ if self.next_questions.length > 0
13
+ raise RuntimeError.new "No questions can follow when changing the question type"
14
+ end
15
+
16
+ nm = self.survey.node_maps
17
+
18
+ self.answers.collect { |answer|
19
+ nm.select { |i|
20
+ i.node == answer
21
+ }
22
+ }.flatten.uniq.collect { |answer_node_map|
23
+ answer_node_map.move_to_root
24
+ answer_node_map.survey = self.survey
25
+
26
+ answer_node_map
27
+ }.collect { |answer_node_map|
28
+ answer_node_map.node.type = klass.to_s
29
+ answer_node_map.node = answer_node_map.node.becomes(klass)
30
+ answer_node_map.node.survey = self.survey
31
+ answer_node_map.node.save
32
+
33
+ self.build_answer(answer_node_map.node)
34
+
35
+ answer_node_map
36
+ }
37
+ end
38
+
39
+ # Removes an answer
40
+ def remove_answer(answer_node)
41
+ # A survey must either be passed or already present in self.node_maps
42
+ if self.survey.nil?
43
+ raise ArgumentError.new "A survey must be passed if ActiveRecordSurvey::Node::Question is not yet added to a survey"
44
+ end
45
+
46
+ if !answer_node.class.ancestors.include?(::ActiveRecordSurvey::Node::Answer)
47
+ raise ArgumentError.new "::ActiveRecordSurvey::Node::Answer not passed"
48
+ end
49
+
50
+ # Cannot mix answer types
51
+ # Check if not match existing - throw error
52
+ if !self.answers.include?(answer_node)
53
+ raise ArgumentError.new "Answer not linked to question"
54
+ end
55
+
56
+ answer_node.send(:remove_answer, self)
57
+ end
58
+
10
59
  # Build an answer off this node
11
60
  def build_answer(answer_node)
12
61
  # A survey must either be passed or already present in self.node_maps
@@ -34,6 +83,9 @@ module ActiveRecordSurvey
34
83
  # Is a question
35
84
  j.parent == answer_node_map.parent && j.node.class.ancestors.include?(::ActiveRecordSurvey::Node::Question)
36
85
  }.each { |j|
86
+ answer_node_map.survey = self.survey
87
+ j.survey = self.survey
88
+
37
89
  answer_node_map.children << j
38
90
  }
39
91
  }
@@ -10,6 +10,26 @@ module ActiveRecordSurvey
10
10
 
11
11
  # All the answer nodes that follow from this node
12
12
  def answers
13
+ #=begin
14
+ next_answer_nodes = lambda { |node, survey, list|
15
+ survey.node_maps.select { |node_map|
16
+ !node_map.parent.nil? && node_map.parent.node == node && node_map.node.class.ancestors.include?(::ActiveRecordSurvey::Node::Answer) && !node_map.marked_for_destruction?
17
+ }.select { |i|
18
+ !list.include?(i.node)
19
+ }.collect { |i|
20
+ i.survey = self.survey
21
+ i.node.survey = self.survey
22
+
23
+ list << i.node
24
+
25
+ next_answer_nodes.call(i.node, survey, list)
26
+ }.flatten.uniq
27
+
28
+ list
29
+ }
30
+ next_answer_nodes.call(self, self.survey, []).flatten.uniq
31
+ #=end
32
+ =begin
13
33
  self.survey.node_maps.select { |i|
14
34
  i.node == self
15
35
  }.collect { |i|
@@ -25,6 +45,7 @@ module ActiveRecordSurvey
25
45
  i.survey = self.survey # ensure that the survey being referenced by the answers is the original survey - needed for keeping consistent node_maps between build_link and remove_link
26
46
  [i] + i.answers
27
47
  }.flatten.uniq
48
+ =end
28
49
  end
29
50
 
30
51
  # The instance_node recorded for the passed instance for this node
@@ -1,3 +1,3 @@
1
1
  module ActiveRecordSurvey
2
- VERSION = "0.1.43"
2
+ VERSION = "0.1.44"
3
3
  end
@@ -51,6 +51,115 @@ describe ActiveRecordSurvey::Node::Question, :question_spec => true do
51
51
  end
52
52
  end
53
53
 
54
+ describe "#remove_answer" do
55
+ before(:each) do
56
+ @survey = ActiveRecordSurvey::Survey.new()
57
+
58
+ @q1 = ActiveRecordSurvey::Node::Question.new(:text => "Q1", :survey => @survey)
59
+ @q1_a1 = ActiveRecordSurvey::Node::Answer.new(:text => "Q1 A1")
60
+ @q1_a2 = ActiveRecordSurvey::Node::Answer.new(:text => "Q1 A2")
61
+ @q1.build_answer(@q1_a1)
62
+ @q1.build_answer(@q1_a2)
63
+
64
+ @q2 = ActiveRecordSurvey::Node::Question.new(:text => "Q2", :survey => @survey)
65
+ @q2_a1 = ActiveRecordSurvey::Node::Answer.new(:text => "Q2 A1")
66
+ @q2_a2 = ActiveRecordSurvey::Node::Answer.new(:text => "Q2 A2")
67
+ @q2.build_answer(@q2_a1)
68
+ @q2.build_answer(@q2_a2)
69
+
70
+ @q3 = ActiveRecordSurvey::Node::Question.new(:text => "Q3", :survey => @survey)
71
+ @q3_a1 = ActiveRecordSurvey::Node::Answer::Boolean.new(:text => "Q3 A1")
72
+ @q3_a2 = ActiveRecordSurvey::Node::Answer::Boolean.new(:text => "Q3 A1")
73
+ @q3.build_answer(@q3_a1)
74
+ @q3.build_answer(@q3_a2)
75
+
76
+ @survey.save
77
+ end
78
+
79
+ it 'should remove the answer for regular answers' do
80
+ expect(@q1.answers.length).to eq(2)
81
+
82
+ @q1.remove_answer(@q1_a1)
83
+
84
+ expect(@q1.answers.length).to eq(1)
85
+ end
86
+
87
+ it 'should remove the answer for boolean answers' do
88
+ expect(@q3.answers.length).to eq(2)
89
+
90
+ @q3.remove_answer(@q3_a1)
91
+
92
+ @survey.save
93
+ @survey.reload
94
+
95
+ expect(@q3.answers.length).to eq(1)
96
+ end
97
+
98
+ it 'should remove the answer for boolean answers, and keep full question links' do
99
+ @q3_a2.build_link(@q2)
100
+
101
+ @survey.save
102
+ @survey.reload
103
+
104
+ expect(@q3.answers.length).to eq(2)
105
+ expect(@q3.next_questions.length).to eq(1)
106
+
107
+ @q3.remove_answer(@q3_a1)
108
+
109
+ @survey.save
110
+ @survey.reload
111
+
112
+ expect(@q3.answers.length).to eq(1)
113
+ expect(@q3.next_questions.length).to eq(1)
114
+ end
115
+ end
116
+
117
+ describe "#update_question_type" do
118
+ before(:each) do
119
+ @survey = ActiveRecordSurvey::Survey.new()
120
+
121
+ @q1 = ActiveRecordSurvey::Node::Question.new(:text => "Q1", :survey => @survey)
122
+ @q1_a1 = ActiveRecordSurvey::Node::Answer.new(:text => "Q1 A1")
123
+ @q1_a2 = ActiveRecordSurvey::Node::Answer.new(:text => "Q1 A2")
124
+ @q1.build_answer(@q1_a1)
125
+ @q1.build_answer(@q1_a2)
126
+
127
+ @q2 = ActiveRecordSurvey::Node::Question.new(:text => "Q2", :survey => @survey)
128
+ @q2_a1 = ActiveRecordSurvey::Node::Answer.new(:text => "Q2 A1")
129
+ @q2.build_answer(@q2_a1)
130
+
131
+ @q3 = ActiveRecordSurvey::Node::Question.new(:text => "Q3", :survey => @survey)
132
+ @q3_a1 = ActiveRecordSurvey::Node::Answer::Boolean.new(:text => "Q3 A1")
133
+ @q3_a2 = ActiveRecordSurvey::Node::Answer::Boolean.new(:text => "Q3 A2")
134
+ @q3.build_answer(@q3_a1)
135
+ @q3.build_answer(@q3_a2)
136
+
137
+ @survey.save
138
+ end
139
+ it 'should raise exception linked to another question' do
140
+ @q1_a1.build_link(@q2)
141
+ @survey.save
142
+
143
+ expect{@q1.update_question_type(ActiveRecordSurvey::Node::Answer::Boolean)}.to raise_error(RuntimeError)
144
+ end
145
+ it 'should change ActiveRecordSurvey::Node::Answer to ActiveRecordSurvey::Node::Answer::Boolean' do
146
+ @q1.update_question_type(ActiveRecordSurvey::Node::Answer::Boolean)
147
+ expect(@survey.as_map(:no_ids => true)).to eq([{"text"=>"Q1", :type=>"ActiveRecordSurvey::Node::Question", :children=>[{"text"=>"Q1 A1", :type=>"ActiveRecordSurvey::Node::Answer::Boolean", :children=>[{"text"=>"Q1 A2", :type=>"ActiveRecordSurvey::Node::Answer::Boolean", :children=>[]}]}]}, {"text"=>"Q2", :type=>"ActiveRecordSurvey::Node::Question", :children=>[{"text"=>"Q2 A1", :type=>"ActiveRecordSurvey::Node::Answer", :children=>[]}]}, {"text"=>"Q3", :type=>"ActiveRecordSurvey::Node::Question", :children=>[{"text"=>"Q3 A1", :type=>"ActiveRecordSurvey::Node::Answer::Boolean", :children=>[{"text"=>"Q3 A2", :type=>"ActiveRecordSurvey::Node::Answer::Boolean", :children=>[]}]}]}])
148
+ expect(@q1.answers.length).to eq(2)
149
+ @q1.answers.each { |answer|
150
+ expect(answer.class).to eq(ActiveRecordSurvey::Node::Answer::Boolean)
151
+ }
152
+ end
153
+ it 'should change ActiveRecordSurvey::Node::Answer::Boolean to ActiveRecordSurvey::Node::Answer' do
154
+ @q3.update_question_type(ActiveRecordSurvey::Node::Answer)
155
+ expect(@survey.as_map(:no_ids => true)).to eq([{"text"=>"Q1", :type=>"ActiveRecordSurvey::Node::Question", :children=>[{"text"=>"Q1 A1", :type=>"ActiveRecordSurvey::Node::Answer", :children=>[]}, {"text"=>"Q1 A2", :type=>"ActiveRecordSurvey::Node::Answer", :children=>[]}]}, {"text"=>"Q2", :type=>"ActiveRecordSurvey::Node::Question", :children=>[{"text"=>"Q2 A1", :type=>"ActiveRecordSurvey::Node::Answer", :children=>[]}]}, {"text"=>"Q3", :type=>"ActiveRecordSurvey::Node::Question", :children=>[{"text"=>"Q3 A1", :type=>"ActiveRecordSurvey::Node::Answer", :children=>[]}, {"text"=>"Q3 A2", :type=>"ActiveRecordSurvey::Node::Answer", :children=>[]}]}])
156
+ expect(@q3.answers.length).to eq(2)
157
+ @q3.answers.each { |answer|
158
+ expect(answer.class).to eq(ActiveRecordSurvey::Node::Answer)
159
+ }
160
+ end
161
+ end
162
+
54
163
  describe "#remove_link" do
55
164
  it 'should remove the link between the question and child questions or answers child questions' do
56
165
  @survey = ActiveRecordSurvey::Survey.new()
@@ -53,7 +53,7 @@ describe ActiveRecordSurvey::Survey, :survey_spec => true do
53
53
  end
54
54
  end
55
55
 
56
- describe '#nodes', :focus => true do
56
+ describe '#nodes' do
57
57
  it 'should return an array of all the nodes' do
58
58
  expect(@survey.nodes.length).to eq(13)
59
59
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record_survey
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.43
4
+ version: 0.1.44
5
5
  platform: ruby
6
6
  authors:
7
7
  - Butch Marshall
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-21 00:00:00.000000000 Z
11
+ date: 2016-11-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord