Class: ActiveRecordSurvey::Node::Answer
- Inherits:
-
ActiveRecordSurvey::Node
- Object
- ActiveRecord::Base
- ActiveRecordSurvey::Node
- ActiveRecordSurvey::Node::Answer
- Defined in:
- lib/active_record_survey/node/answer.rb
Defined Under Namespace
Classes: Boolean, Rank, Scale, Text
Instance Method Summary collapse
-
#build_link(to_node) ⇒ Object
Build a link from this node to another node Building a link actually needs to throw off a whole new clone of all children nodes.
-
#next_question ⇒ Object
Returns the question that follows this answer.
-
#question ⇒ Object
Returns the question that preceeds this answer.
-
#remove_link ⇒ Object
Removes the link.
-
#validate_node(instance) ⇒ Object
Answer nodes are valid if their questions are valid! Validate this node against an instance.
Methods inherited from ActiveRecordSurvey::Node
#answers, #has_instance_node_for_instance?, #instance_node_for_instance, #instance_node_path_to_root?, #is_answered_for_instance?, #validate_instance_node, #validate_parent_instance_node
Instance Method Details
#build_link(to_node) ⇒ Object
Build a link from this node to another node Building a link actually needs to throw off a whole new clone of all children nodes
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 |
# File 'lib/active_record_survey/node/answer.rb', line 84 def build_link(to_node) # build_link only accepts a to_node that inherits from Question if !to_node.class.ancestors.include?(::ActiveRecordSurvey::Node::Question) raise ArgumentError.new "to_node must inherit from ::ActiveRecordSurvey::Node::Question" end if self.question.nil? raise ArgumentError.new "A question is required before calling #build_link" end if self.survey.nil? raise ArgumentError.new "A survey is required before calling #build_link" end from_node_maps = self.survey.node_maps.select { |i| i.node == self && !i.marked_for_destruction? } # Answer has already got a question - throw error if from_node_maps.select { |i| i.children.length === 0 }.length === 0 raise RuntimeError.new "This answer has already been linked" end # Because we need something to clone - filter this further below to_node_maps = self.survey.node_maps.select { |i| i.node == to_node && !i.marked_for_destruction? } if to_node_maps.first.nil? to_node_maps << self.survey.node_maps.build(:survey => self.survey, :node => to_node) end # Ensure we can through each possible path of getting to this answer to_node_map = to_node_maps.first to_node_map.survey = self.survey # required due to voodoo - we want to use the same survey with the same object_id # We only want node maps that aren't linked somewhere to_node_maps = to_node_maps.select { |i| i.parent.nil? } while to_node_maps.length < from_node_maps.length do to_node_maps.push(to_node_map.recursive_clone) end # Link unused node_maps to the new parents from_node_maps.each_with_index { |from_node_map, index| from_node_map.children << to_node_maps[index] } # Ensure no infinite loops were created from_node_maps.each { |node_map| # There is a path from Q -> A that is a loop if node_map.has_infinite_loop? raise RuntimeError.new "Infinite loop detected" end } end |
#next_question ⇒ Object
Returns the question that follows this answer
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/active_record_survey/node/answer.rb', line 34 def next_question self.survey.node_maps.select { |i| i.node == self && !i.marked_for_destruction? }.each { |answer_node_map| answer_node_map.children.each { |child| if !child.node.nil? && !child.marked_for_destruction? if child.node.class.ancestors.include?(::ActiveRecordSurvey::Node::Question) return child.node elsif child.node.class.ancestors.include?(::ActiveRecordSurvey::Node::Answer) return child.node.next_question end else return nil end } } return nil end |
#question ⇒ Object
Returns the question that preceeds this answer
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/active_record_survey/node/answer.rb', line 15 def question self.survey.node_maps.select { |i| i.node == self }.collect { |node_map| if node_map.parent && node_map.parent.node # Question is not the next parent - recurse! if node_map.parent.node.class.ancestors.include?(::ActiveRecordSurvey::Node::Answer) node_map.parent.node.question else node_map.parent.node end # Root already else nil end }.first end |
#remove_link ⇒ Object
Removes the link
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 |
# File 'lib/active_record_survey/node/answer.rb', line 54 def remove_link # not linked to a question - nothing to remove! return true if (question = self.next_question).nil? count = 0 to_remove = [] self.survey.node_maps.each { |node_map| if node_map.node == question if count > 0 to_remove.concat(node_map.self_and_descendants) else node_map.parent = nil end count = count + 1 end if node_map.node == self node_map.children = [] end } self.survey.node_maps.each { |node_map| if to_remove.include?(node_map) node_map.parent = nil node_map.mark_for_destruction end } end |
#validate_node(instance) ⇒ Object
Answer nodes are valid if their questions are valid! Validate this node against an instance
5 6 7 8 9 10 11 12 |
# File 'lib/active_record_survey/node/answer.rb', line 5 def validate_node(instance) # Ensure each parent node to this node (the goal here is to hit a question node) is valid !self.survey.node_maps.select { |i| i.node == self }.collect { |node_map| node_map.parent.node.validate_node(instance) }.include?(false) end |