Class: ActiveRecordSurvey::Node::Question
- Inherits:
-
ActiveRecordSurvey::Node
- Object
- ActiveRecord::Base
- ActiveRecordSurvey::Node
- ActiveRecordSurvey::Node::Question
- Defined in:
- lib/active_record_survey/node/question.rb
Instance Method Summary collapse
-
#build_answer(answer_node) ⇒ Object
Build an answer off this node.
-
#next_questions ⇒ Object
Returns the questions that follows this question (either directly or via its answers).
-
#remove_answer(answer_node) ⇒ Object
Removes an answer.
-
#remove_link ⇒ Object
Removes the node_map link from this question all of its next questions.
-
#update_question_type(klass) ⇒ Object
Updates the answers of this question to a different type.
-
#validate_parent_instance_node(instance_node, child_node) ⇒ Object
Stop validating at the Question node.
Methods inherited from ActiveRecordSurvey::Node
#answers, #build_link, #has_instance_node_for_instance?, #instance_node_for_instance, #instance_node_path_to_root?, #is_answered_for_instance?, #validate_instance_node
Instance Method Details
#build_answer(answer_node) ⇒ Object
Build an answer off this node
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 |
# File 'lib/active_record_survey/node/question.rb', line 66 def build_answer(answer_node) # A survey must either be passed or already present in self.node_maps if self.survey.nil? raise ArgumentError.new "A survey must be passed if ActiveRecordSurvey::Node::Question is not yet added to a survey" end # Cannot mix answer types # Check if not match existing - throw error if !self.answers.select { |answer| answer.class != answer_node.class }.empty? raise ArgumentError.new "Cannot mix answer types on question" end # Answers actually define how they're built off the parent node if answer_node.send(:build_answer, self) # If any questions existed directly following this question, insert after this answer self.survey.node_maps.select { |i| i.node == answer_node && !i.marked_for_destruction? }.each { |answer_node_map| self.survey.node_maps.select { |j| # Same parent # Is a question !j.marked_for_destruction? && j.parent == answer_node_map.parent && j.node.class.ancestors.include?(::ActiveRecordSurvey::Node::Question) }.each { |j| answer_node_map.survey = self.survey j.survey = self.survey answer_node_map.children << j } } true end end |
#next_questions ⇒ Object
Returns the questions that follows this question (either directly or via its answers)
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/active_record_survey/node/question.rb', line 129 def next_questions list = [] if question_node_map = self.survey.node_maps.select { |i| i.node == self && !i.marked_for_destruction? }.first question_node_map.children.each { |child| if !child.node.nil? && !child.marked_for_destruction? if child.node.class.ancestors.include?(::ActiveRecordSurvey::Node::Question) list << child.node elsif child.node.class.ancestors.include?(::ActiveRecordSurvey::Node::Answer) list << child.node.next_question end end } end list.compact.uniq end |
#remove_answer(answer_node) ⇒ Object
Removes an answer
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/active_record_survey/node/question.rb', line 46 def remove_answer(answer_node) # A survey must either be passed or already present in self.node_maps if self.survey.nil? raise ArgumentError.new "A survey must be passed if ActiveRecordSurvey::Node::Question is not yet added to a survey" end if !answer_node.class.ancestors.include?(::ActiveRecordSurvey::Node::Answer) raise ArgumentError.new "::ActiveRecordSurvey::Node::Answer not passed" end # Cannot mix answer types # Check if not match existing - throw error if !self.answers.include?(answer_node) raise ArgumentError.new "Answer not linked to question" end answer_node.send(:remove_answer, self) end |
#remove_link ⇒ Object
Removes the node_map link from this question all of its next questions
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/active_record_survey/node/question.rb', line 105 def remove_link return true if (questions = self.next_questions).length === 0 # Remove the link to any direct questions self.survey.node_maps.select { |i| i.node == self }.each { |node_map| self.survey.node_maps.select { |j| node_map.children.include?(j) }.each { |child| if child.node.class.ancestors.include?(::ActiveRecordSurvey::Node::Question) child.parent = nil child.send((child.new_record?)? :destroy : :mark_for_destruction ) end } } # remove link any answeres that have questions self.answers.collect { |i| i.remove_link } end |
#update_question_type(klass) ⇒ Object
Updates the answers of this question to a different type
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 |
# File 'lib/active_record_survey/node/question.rb', line 11 def update_question_type(klass) if self.next_questions.length > 0 raise RuntimeError.new "No questions can follow when changing the question type" end nm = self.survey.node_maps answers = self.answers.collect { |answer| nm.select { |i| i.node == answer } }.flatten.uniq.collect { |answer_node_map| answer_node_map.move_to_root answer_node_map.survey = self.survey answer_node_map }.collect { |answer_node_map| answer_node_map.node.type = klass.to_s answer_node_map.node = answer_node_map.node.becomes(klass) answer_node_map.node.survey = self.survey answer_node_map.node.save answer_node_map.send((answer_node_map.new_record?)? :destroy : :mark_for_destruction) answer_node_map.node }.uniq answers.each { |answer| answer.survey = self.survey self.build_answer(answer) } end |
#validate_parent_instance_node(instance_node, child_node) ⇒ Object
Stop validating at the Question node
4 5 6 7 8 |
# File 'lib/active_record_survey/node/question.rb', line 4 def validate_parent_instance_node(instance_node, child_node) !self.node_validations.collect { |node_validation| node_validation.validate_instance_node(instance_node, self) }.include?(false) end |