active_record_survey 0.1.28 → 0.1.29

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: 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