active_record_survey 0.1.28 → 0.1.29

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: 28cbe125545e5fec174484486e07e7ac56088438
4
- data.tar.gz: 39c903c6db06d0f0c8b89a5aa18e766e776167eb
3
+ metadata.gz: d2afb9c3325db53de73001c5d6f59325c1358857
4
+ data.tar.gz: 79c0edcfa55069372786f9aec408e679f4216752
5
5
  SHA512:
6
- metadata.gz: 863edda965f97873d7e7e3e4a0376b31b4df9f4e683f8fec0cc3fadc6a50e3571d421a2b2c5c82054d9bf27ad3545fec044057059244833f93deb93bd3038dd7
7
- data.tar.gz: fdcbe0660f224af0d1b551724afe93e16f2876007f1aa23bb2c8f8295d79c44121127af31e27ee7d17c2de35828209b2d3d6e5e5302ff7ab1ba375a73ecad50b
6
+ metadata.gz: 1b82564a960e98748f511fe5aa26b8b76b1b1a71c6b993f18bdf979631cce2dcf714f008b5da9a1cd7176bb03088bca5ad6c17842df6f494ab225f5f4dea357a
7
+ data.tar.gz: 7ab230a31470113797bd349e784e24a500562ae4cd651e35b4e476f79c39712bcb30ab029cc8b66cfbade0320025593eb4436ef36516c64429ac2fe1180f77be
data/README.md CHANGED
@@ -12,6 +12,10 @@ The goal is to give a simple interface for creating surveys and validating the a
12
12
  Release Notes
13
13
  ============
14
14
 
15
+ **0.1.29**
16
+ - `ActiveRecordSurvey::Node::Answer` now cleans up associated node_maps on destruction
17
+ - extending/including `ActiveRecordSurvey::Answer::Chained` now rebuilds broken links in the parent<->child node_maps if a middle node_map is destroyed
18
+
15
19
  **0.1.26**
16
20
  - Major refactor of answer#build_link and answer#remove_link
17
21
  - `ActiveRecordSurvey::Node` now has a direct reference to its survey. Don't forget to run the install task Update_0_1_26_ActiveRecordSurvey
@@ -1,7 +1,8 @@
1
1
  module ActiveRecordSurvey
2
2
  # Boolean answers can have values 0|1
3
3
  class Node::Answer::Boolean < Node::Answer
4
- include Answer::Chained
4
+ include Answer::Chained::InstanceMethods
5
+ extend Answer::Chained::ClassMethods
5
6
 
6
7
  # Only boolean values
7
8
  def validate_instance_node(instance_node)
@@ -1,28 +1,51 @@
1
1
  module ActiveRecordSurvey
2
2
  class Answer
3
3
  module Chained
4
- # Chain nodes are different - they must find the final answer node added and add to it
5
- def build_answer(question_node)
6
- self.survey = question_node.survey
4
+ module ClassMethods
5
+ def self.extended(base)
6
+ base.before_destroy :before_destroy_rebuild_node_map, prepend: true # prepend is important! otherwise dependent: :destroy on node<->node_map relation is executed first and no records!
7
+ end
8
+ end
7
9
 
8
- question_node_maps = self.survey.node_maps.select { |i| i.node == question_node && !i.marked_for_destruction? }
10
+ module InstanceMethods
11
+ # Chain nodes are different - they must find the final answer node added and add to it
12
+ def build_answer(question_node)
13
+ self.survey = question_node.survey
9
14
 
10
- # No node_maps exist yet from this question
11
- if question_node_maps.length === 0
12
- # Build our first node-map
13
- question_node_maps << self.survey.node_maps.build(:node => question_node, :survey => self.survey)
14
- end
15
+ question_node_maps = self.survey.node_maps.select { |i| i.node == question_node && !i.marked_for_destruction? }
16
+
17
+ # No node_maps exist yet from this question
18
+ if question_node_maps.length === 0
19
+ # Build our first node-map
20
+ question_node_maps << self.survey.node_maps.build(:node => question_node, :survey => self.survey)
21
+ end
15
22
 
16
- last_answer_in_chain = (question_node.answers.last || question_node)
23
+ last_answer_in_chain = (question_node.answers.last || question_node)
24
+
25
+ # Each instance of this question needs the answer hung from it
26
+ self.survey.node_maps.select { |i|
27
+ i.node == last_answer_in_chain
28
+ }.each { |node_map|
29
+ node_map.children << self.survey.node_maps.build(:node => self, :survey => self.survey)
30
+ }
31
+
32
+ true
33
+ end
17
34
 
18
- # Each instance of this question needs the answer hung from it
19
- self.survey.node_maps.select { |i|
20
- i.node == last_answer_in_chain
21
- }.each { |node_map|
22
- node_map.children << self.survey.node_maps.build(:node => self, :survey => self.survey)
23
- }
35
+ private
36
+ # Before a node is destroyed, will re-build the node_map links from parent to child if they exist
37
+ def before_destroy_rebuild_node_map
24
38
 
25
- true
39
+ # All the node_maps from this node
40
+ self.survey.node_maps.select { |i|
41
+ i.node == self
42
+ }.each { |node_map|
43
+ # Remap all of this nodes children to the parent
44
+ node_map.children.each { |child|
45
+ node_map.parent.children << child
46
+ }
47
+ }
48
+ end
26
49
  end
27
50
  end
28
51
  end
@@ -1,7 +1,8 @@
1
1
  module ActiveRecordSurvey
2
2
  # Rank in relation to parent/children of ActiveRecordSurvey::Node::Answer::Rank
3
3
  class Node::Answer::Rank < Node::Answer
4
- include Answer::Chained
4
+ include Answer::Chained::InstanceMethods
5
+ extend Answer::Chained::ClassMethods
5
6
 
6
7
  # Accept integer or empty values
7
8
  # Must be within range of the number of ranking nodes
@@ -1,7 +1,8 @@
1
1
  module ActiveRecordSurvey
2
2
  # Can hold a value on a scale (e.g. from 0-10)
3
3
  class Node::Answer::Scale < Node::Answer
4
- include Answer::Chained
4
+ include Answer::Chained::InstanceMethods
5
+ extend Answer::Chained::ClassMethods
5
6
 
6
7
  # Accept integer, float, or empty values
7
8
  def validate_instance_node(instance_node)
@@ -1,7 +1,8 @@
1
1
  module ActiveRecordSurvey
2
2
  # Text answers are... text answers
3
3
  class Node::Answer::Text < Node::Answer
4
- include Answer::Chained
4
+ include Answer::Chained::InstanceMethods
5
+ extend Answer::Chained::ClassMethods
5
6
 
6
7
  # Text answers are considered answered if they have text entered
7
8
  def is_answered_for_instance?(instance)
@@ -2,8 +2,8 @@ module ActiveRecordSurvey
2
2
  class Node < ::ActiveRecord::Base
3
3
  self.table_name = "active_record_survey_nodes"
4
4
  belongs_to :survey, :class_name => "ActiveRecordSurvey::Survey", :foreign_key => :active_record_survey_id
5
- has_many :node_maps, :class_name => "ActiveRecordSurvey::NodeMap", :foreign_key => :active_record_survey_node_id, autosave: true
6
- has_many :node_validations, :class_name => "ActiveRecordSurvey::NodeValidation", :foreign_key => :active_record_survey_node_id, autosave: true
5
+ has_many :node_maps, :class_name => "ActiveRecordSurvey::NodeMap", :foreign_key => :active_record_survey_node_id, autosave: true, dependent: :destroy
6
+ has_many :node_validations, :class_name => "ActiveRecordSurvey::NodeValidation", :foreign_key => :active_record_survey_node_id, autosave: true, dependent: :destroy
7
7
  has_many :instance_nodes, :class_name => "ActiveRecordSurvey::InstanceNode", :foreign_key => :active_record_survey_node_id
8
8
 
9
9
  # All the answer nodes that follow from this node
@@ -25,9 +25,9 @@ module ActiveRecordSurvey
25
25
  }
26
26
 
27
27
  result = {}
28
- result.merge!({ :id => self.id, :node_id => self.node.id }) if !options[:no_ids]
28
+ result.merge!({ :id => self.id, :node_id => ((self.node.respond_to?(:id))? self.node.id : "") }) if !options[:no_ids] && !self.node.nil?
29
29
  result.merge!({
30
- :type => self.node.class.to_s,
30
+ :type => ((!self.node.nil?)? self.node.class.to_s : ""),
31
31
  :children => c.collect { |i|
32
32
  i.as_map(options)
33
33
  }
@@ -1,3 +1,3 @@
1
1
  module ActiveRecordSurvey
2
- VERSION = "0.1.28"
2
+ VERSION = "0.1.29"
3
3
  end
@@ -1,6 +1,27 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ActiveRecordSurvey::Node::Answer::Boolean, :boolean_spec => true do
4
+ describe '#destroy', :focus => true do
5
+ it 'should re-link broken chains' do
6
+ survey = ActiveRecordSurvey::Survey.new()
7
+ q1 = ActiveRecordSurvey::Node::Question.new(:text => "Question #1", :survey => survey)
8
+ q1_a1 = ActiveRecordSurvey::Node::Answer::Boolean.new(:text => "Q1 Answer #1")
9
+ q1_a2 = ActiveRecordSurvey::Node::Answer::Boolean.new(:text => "Q1 Answer #2")
10
+ q1_a3 = ActiveRecordSurvey::Node::Answer::Boolean.new(:text => "Q1 Answer #3")
11
+ q1.build_answer(q1_a1)
12
+ q1.build_answer(q1_a2)
13
+ q1.build_answer(q1_a3)
14
+ survey.save
15
+
16
+ expect(survey.as_map(no_ids: true)).to eq([{"text"=>"Question #1", :type=>"ActiveRecordSurvey::Node::Question", :children=>[{"text"=>"Q1 Answer #1", :type=>"ActiveRecordSurvey::Node::Answer::Boolean", :children=>[{"text"=>"Q1 Answer #2", :type=>"ActiveRecordSurvey::Node::Answer::Boolean", :children=>[{"text"=>"Q1 Answer #3", :type=>"ActiveRecordSurvey::Node::Answer::Boolean", :children=>[]}]}]}]}])
17
+
18
+ q1_a2.destroy
19
+ survey.reload # reload seems to be necessary
20
+
21
+ expect(survey.as_map(no_ids: true)).to eq([{"text"=>"Question #1", :type=>"ActiveRecordSurvey::Node::Question", :children=>[{"text"=>"Q1 Answer #1", :type=>"ActiveRecordSurvey::Node::Answer::Boolean", :children=>[{"text"=>"Q1 Answer #3", :type=>"ActiveRecordSurvey::Node::Answer::Boolean", :children=>[]}]}]}])
22
+ end
23
+ end
24
+
4
25
  describe 'a boolean survey is' do
5
26
  before(:all) do
6
27
  @survey = ActiveRecordSurvey::Survey.new()
@@ -1,6 +1,30 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ActiveRecordSurvey::Node::Answer, :answer_spec => true do
4
+ # When answer nodes are deleted should:
5
+ # - Clean upp node_maps
6
+ # - If chained, build a chain from parent -> child after removing self
7
+ describe '#destroy' do
8
+ it 'should clean up node maps' do
9
+ survey = ActiveRecordSurvey::Survey.new()
10
+ q1 = ActiveRecordSurvey::Node::Question.new(:text => "Question #1", :survey => survey)
11
+ q1_a1 = ActiveRecordSurvey::Node::Answer.new(:text => "Q1 Answer #1")
12
+ q1_a2 = ActiveRecordSurvey::Node::Answer.new(:text => "Q1 Answer #2")
13
+ q1_a3 = ActiveRecordSurvey::Node::Answer.new(:text => "Q1 Answer #3")
14
+ q1.build_answer(q1_a1)
15
+ q1.build_answer(q1_a2)
16
+ q1.build_answer(q1_a3)
17
+ survey.save
18
+
19
+ expect(survey.as_map(no_ids: true)).to eq([{"text"=>"Question #1", :type=>"ActiveRecordSurvey::Node::Question", :children=>[{"text"=>"Q1 Answer #1", :type=>"ActiveRecordSurvey::Node::Answer", :children=>[]}, {"text"=>"Q1 Answer #2", :type=>"ActiveRecordSurvey::Node::Answer", :children=>[]}, {"text"=>"Q1 Answer #3", :type=>"ActiveRecordSurvey::Node::Answer", :children=>[]}]}])
20
+
21
+ q1_a2.destroy
22
+ survey.reload
23
+
24
+ expect(survey.as_map(no_ids: true)).to eq([{"text"=>"Question #1", :type=>"ActiveRecordSurvey::Node::Question", :children=>[{"text"=>"Q1 Answer #1", :type=>"ActiveRecordSurvey::Node::Answer", :children=>[]}, {"text"=>"Q1 Answer #3", :type=>"ActiveRecordSurvey::Node::Answer", :children=>[]}]}])
25
+ end
26
+ end
27
+
4
28
  describe "#build_link" do
5
29
  it 'should not have to be saved to produce a valid #as_map' do
6
30
  survey = ActiveRecordSurvey::Survey.new()
@@ -83,7 +107,7 @@ describe ActiveRecordSurvey::Node::Answer, :answer_spec => true do
83
107
  expect{q3_a1.build_link(q1)}.to raise_error(RuntimeError) # This should throw exception
84
108
  end
85
109
 
86
- it 'should keep consistent number of nodes after calling #remove_link and #build_link', :focus => true do
110
+ it 'should keep consistent number of nodes after calling #remove_link and #build_link' do
87
111
  survey = FactoryGirl.build(:simple_survey)
88
112
  survey.save
89
113
 
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.28
4
+ version: 0.1.29
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-03-19 00:00:00.000000000 Z
11
+ date: 2016-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -194,7 +194,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
194
194
  version: '0'
195
195
  requirements: []
196
196
  rubyforge_project:
197
- rubygems_version: 2.6.2
197
+ rubygems_version: 2.4.6
198
198
  signing_key:
199
199
  specification_version: 4
200
200
  summary: Surveys using activerecord