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
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 |
# File 'lib/active_record_survey/node/question.rb', line 62 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)
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/active_record_survey/node/question.rb', line 125 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
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/active_record_survey/node/question.rb', line 42 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
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/active_record_survey/node/question.rb', line 101 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 |
# 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| node = answer_node_map.node answer_node_map.send((answer_node_map.new_record?)? :destroy : :mark_for_destruction) node }.collect { |answer| answer.type = klass.to_s answer = answer.becomes(klass) answer.save if !answer.new_record? answer }.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 |