active_record_survey 0.1.43 → 0.1.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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