surveyor 0.20.0 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. data/.gitignore +26 -0
  2. data/Gemfile +11 -0
  3. data/Gemfile.rails_version +13 -0
  4. data/README.md +40 -22
  5. data/Rakefile +92 -29
  6. data/app/helpers/survey_form_builder.rb +37 -0
  7. data/app/helpers/surveyor_helper.rb +9 -9
  8. data/app/views/partials/_answer.html.haml +1 -1
  9. data/app/views/partials/_question.html.haml +3 -3
  10. data/app/views/partials/_question_group.html.haml +2 -2
  11. data/app/views/partials/_section.html.haml +1 -1
  12. data/app/views/surveyor/edit.html.haml +11 -3
  13. data/app/views/surveyor/new.html.haml +8 -1
  14. data/ci-exec.sh +50 -0
  15. data/config/routes.rb +9 -13
  16. data/cucumber.yml +10 -0
  17. data/doc/question types.png +0 -0
  18. data/features/redcap_parser.feature +1 -1
  19. data/features/step_definitions/common_setps.rb +3 -0
  20. data/features/step_definitions/parser_steps.rb +8 -1
  21. data/features/step_definitions/surveyor_steps.rb +33 -9
  22. data/features/step_definitions/web_steps.rb +85 -165
  23. data/features/support/env.rb +40 -46
  24. data/features/support/paths.rb +4 -4
  25. data/features/support/selectors.rb +39 -0
  26. data/features/surveyor.feature +63 -13
  27. data/features/surveyor_dependencies.feature +289 -0
  28. data/features/surveyor_parser.feature +29 -20
  29. data/lib/formtastic/surveyor_builder.rb +9 -9
  30. data/lib/generators/surveyor/custom_generator.rb +17 -0
  31. data/lib/generators/surveyor/install_generator.rb +50 -0
  32. data/{generators/extend_surveyor/templates/extensions → lib/generators/surveyor/templates/app/controllers}/surveyor_controller.rb +0 -0
  33. data/{generators/extend_surveyor/templates/extensions → lib/generators/surveyor/templates/app/views/layouts}/surveyor_custom.html.erb +0 -0
  34. data/{generators/surveyor/templates → lib/generators/surveyor/templates/config}/locales/surveyor_en.yml +0 -0
  35. data/{generators/surveyor/templates → lib/generators/surveyor/templates/config}/locales/surveyor_es.yml +0 -0
  36. data/{generators/surveyor/templates → lib/generators/surveyor/templates/config}/locales/surveyor_he.yml +0 -0
  37. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/add_api_ids.rb +0 -0
  38. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/add_correct_answer_id_to_questions.rb +0 -0
  39. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/add_default_value_to_answers.rb +0 -0
  40. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/add_display_order_to_surveys.rb +0 -0
  41. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/add_display_type_to_answers.rb +0 -0
  42. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/add_index_to_response_sets.rb +0 -0
  43. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/add_index_to_surveys.rb +0 -0
  44. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/add_section_id_to_responses.rb +0 -0
  45. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/add_unique_indicies.rb +0 -0
  46. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/create_answers.rb +0 -0
  47. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/create_dependencies.rb +0 -0
  48. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/create_dependency_conditions.rb +0 -0
  49. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/create_question_groups.rb +0 -0
  50. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/create_questions.rb +0 -0
  51. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/create_response_sets.rb +0 -0
  52. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/create_responses.rb +0 -0
  53. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/create_survey_sections.rb +0 -0
  54. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/create_surveys.rb +0 -0
  55. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/create_validation_conditions.rb +0 -0
  56. data/{generators/surveyor/templates → lib/generators/surveyor/templates/db}/migrate/create_validations.rb +0 -0
  57. data/{generators/surveyor/templates/assets/images → lib/generators/surveyor/templates/public/images/surveyor}/next.gif +0 -0
  58. data/{generators/surveyor/templates/assets/images → lib/generators/surveyor/templates/public/images/surveyor}/prev.gif +0 -0
  59. data/lib/generators/surveyor/templates/public/javascripts/surveyor/jquery.blockUI.js +499 -0
  60. data/{generators/surveyor/templates/assets/javascripts → lib/generators/surveyor/templates/public/javascripts/surveyor}/jquery.surveyor.js +47 -4
  61. data/{generators/surveyor/templates/assets/javascripts → lib/generators/surveyor/templates/public/javascripts/surveyor}/jquery.tools.min.js +0 -0
  62. data/{generators/surveyor/templates/assets → lib/generators/surveyor/templates/public}/stylesheets/sass/custom.sass +0 -0
  63. data/{generators/surveyor/templates/assets → lib/generators/surveyor/templates/public}/stylesheets/sass/surveyor.sass +2 -2
  64. data/{generators/surveyor/templates/assets/stylesheets → lib/generators/surveyor/templates/public/stylesheets/surveyor}/dateinput.css +0 -0
  65. data/{generators/surveyor/templates/assets/stylesheets → lib/generators/surveyor/templates/public/stylesheets/surveyor}/reset.css +0 -0
  66. data/{generators/surveyor/templates/assets/stylesheets → lib/generators/surveyor/templates/public/stylesheets/surveyor}/results.css +0 -0
  67. data/{generators/extend_surveyor/templates/EXTENDING_SURVEYOR → lib/generators/surveyor/templates/surveys/EXTENDING_SURVEYOR.md} +0 -0
  68. data/{generators → lib/generators}/surveyor/templates/surveys/kitchen_sink_survey.rb +0 -0
  69. data/{generators → lib/generators}/surveyor/templates/surveys/quiz.rb +0 -0
  70. data/lib/surveyor.rb +7 -0
  71. data/lib/surveyor/engine.rb +12 -0
  72. data/lib/surveyor/models/answer_methods.rb +0 -1
  73. data/lib/surveyor/models/dependency_condition_methods.rb +1 -3
  74. data/lib/surveyor/models/question_methods.rb +0 -1
  75. data/lib/surveyor/models/response_methods.rb +2 -2
  76. data/lib/surveyor/models/response_set_methods.rb +30 -14
  77. data/lib/surveyor/models/survey_methods.rb +2 -1
  78. data/lib/surveyor/models/survey_section_methods.rb +1 -2
  79. data/lib/surveyor/parser.rb +9 -7
  80. data/lib/surveyor/redcap_parser.rb +10 -7
  81. data/lib/surveyor/surveyor_controller_methods.rb +45 -11
  82. data/lib/surveyor/version.rb +3 -0
  83. data/lib/tasks/surveyor_tasks.rake +2 -2
  84. data/rails/init.rb +0 -1
  85. data/spec/controllers/surveyor_controller_spec.rb +81 -35
  86. data/spec/helpers/surveyor_helper_spec.rb +7 -1
  87. data/spec/models/dependency_condition_spec.rb +76 -63
  88. data/spec/models/response_set_spec.rb +52 -47
  89. data/spec/models/response_spec.rb +19 -16
  90. data/spec/spec_helper.rb +21 -44
  91. data/surveyor.gemspec +25 -176
  92. metadata +302 -77
  93. data/CHANGELOG +0 -335
  94. data/VERSION +0 -1
  95. data/ci-env.sh +0 -29
  96. data/generators/extend_surveyor/extend_surveyor_generator.rb +0 -21
  97. data/generators/surveyor/surveyor_generator.rb +0 -69
  98. data/generators/surveyor/templates/README +0 -10
  99. data/generators/surveyor/templates/tasks/surveyor.rb +0 -4
  100. data/hudson.rakefile +0 -33
  101. data/init_testbed.rakefile +0 -55
  102. data/testbed/Gemfile +0 -13
@@ -24,23 +24,66 @@ jQuery(document).ready(function(){
24
24
  });
25
25
 
26
26
  jQuery("form#survey_form input, form#survey_form select, form#survey_form textarea").change(function(){
27
+ var elements = [$('[type="submit"]').parent(), $('[name="' + this.name +'"]').closest('li')];
28
+ blockElements(elements);
29
+
27
30
  question_data = $(this).parents('fieldset[id^="q_"],tr[id^="q_"]').find("input, select, textarea").add($("form#survey_form input[name='authenticity_token']")).serialize();
28
31
  // console.log(unescape(question_data));
29
- $.ajax({ type: "PUT", url: $(this).parents('form#survey_form').attr("action"), data: question_data, dataType: 'json', success: successfulSave })
32
+ $.ajax({
33
+ type: "PUT",
34
+ url: $(this).parents('form#survey_form').attr("action"),
35
+ data: question_data, dataType: 'json',
36
+ success: function(response) {
37
+ unblockElements(elements);
38
+ successfulSave(response);
39
+ },
40
+ error: function(xhr, ajaxOptions, thrownError) {
41
+ unblockElements(elements);
42
+ }
43
+ });
30
44
  });
31
- // }
32
45
 
33
46
  // If javascript works, we don't need to show dependents from previous sections at the top of the page.
34
47
  jQuery("#dependents").remove();
35
48
 
36
49
  function successfulSave(responseText){ // for(key in responseText) { console.log("key is "+[key]+", value is "+responseText[key]); }
37
50
  // surveyor_controller returns a json object to show/hide elements and insert/remove ids e.g. {"ids": {"2" => 234}, "remove": {"4" => 21}, "hide":["question_12","question_13"],"show":["question_14"]}
38
- jQuery.each(responseText.show, function(){ jQuery('#' + this).show("fast"); });
39
- jQuery.each(responseText.hide, function(){ jQuery('#' + this).hide("fast"); });
51
+ jQuery.each(responseText.show, function(){ showElement(this) });
52
+ jQuery.each(responseText.hide, function(){ hideElement(this) });
40
53
  jQuery.each(responseText.ids, function(k,v){ jQuery('#r_'+k+'_question_id').after('<input id="r_'+k+'_id" type="hidden" value="'+v+'" name="r['+k+'][id]"/>'); });
41
54
  jQuery.each(responseText.remove, function(k,v){ jQuery('#r_'+k+'_id[value="'+v+'"]').remove(); });
42
55
  return false;
43
56
  }
57
+
58
+ function showElement(id){
59
+ group = id.match('^g_') ? true : false;
60
+ if (group) {
61
+ jQuery('#' + id).removeClass("g_hidden");
62
+ } else {
63
+ jQuery('#' + id).removeClass("q_hidden");
64
+ }
65
+ }
66
+
67
+ function hideElement(id){
68
+ group = id.match('^g_') ? true : false;
69
+ if (group) {
70
+ jQuery('#' + id).addClass("g_hidden");
71
+ } else {
72
+ jQuery('#' + id).addClass("q_hidden");
73
+ }
74
+ }
75
+
76
+ function blockElements(elements) {
77
+ $.blockUI.defaults.overlayCSS.opacity = 0;
78
+ $.blockUI.defaults.message = null;
79
+ $.blockUI.defaults.fadeIn = 0;
80
+ $.blockUI.defaults.fadeOut = 0;
81
+ $.each(elements, function(){ $(this).block()});
82
+ }
83
+
84
+ function unblockElements(elements) {
85
+ $.each(elements, function(){ $(this).unblock()});
86
+ }
44
87
 
45
88
  // is_exclusive checkboxes should disble sibling checkboxes
46
89
  $('input.exclusive:checked').parents('fieldset[id^="q_"]').find(':checkbox').not(".exclusive").attr('checked', false).attr('disabled', true);
@@ -95,7 +95,7 @@ body
95
95
  li.datetime, li.time
96
96
  input, fieldset, fieldset ol li
97
97
  :display inline
98
- &.q_inline ol li
98
+ &.q_inline ol li, &.q_inline_inline ol li
99
99
  :display inline
100
100
  input, textarea, select
101
101
  :margin 0 3px
@@ -103,7 +103,7 @@ body
103
103
  :font-size 0.8em
104
104
 
105
105
  fieldset.q_hidden, fieldset.g_hidden
106
- :display none
106
+ :display none !important
107
107
  fieldset.q_dependent, fieldset.g_dependent
108
108
  :background-color $surveyor_dependent_color
109
109
  legend
data/lib/surveyor.rb CHANGED
@@ -1,6 +1,13 @@
1
+ module Surveyor
2
+ require 'surveyor/engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
3
+
4
+ autoload :VERSION, 'surveyor/version'
5
+ end
1
6
  require 'surveyor/common'
2
7
  require 'surveyor/acts_as_response'
3
8
  require 'formtastic/surveyor_builder'
9
+ # require 'surveyor/surveyor_controller_methods'
10
+ # require 'surveyor/models/survey_methods'
4
11
  Formtastic::SemanticFormHelper.builder = Formtastic::SurveyorBuilder
5
12
  Formtastic::SemanticFormBuilder.default_text_area_height = 5
6
13
  Formtastic::SemanticFormBuilder.default_text_area_width = 50
@@ -0,0 +1,12 @@
1
+ require 'rails'
2
+ require 'surveyor'
3
+ require 'haml' # required for view resolution
4
+
5
+ module Surveyor
6
+ class Engine < Rails::Engine
7
+ config.autoload_paths << File.expand_path("../../", __FILE__)
8
+ # rake_tasks do
9
+ # load "tasks/surveyor_tasks.rake"
10
+ # end
11
+ end
12
+ end
@@ -29,7 +29,6 @@ module Surveyor
29
29
  end
30
30
 
31
31
  def default_args
32
- self.display_order ||= self.question ? self.question.answers.count : 0
33
32
  self.is_exclusive ||= false
34
33
  self.display_type ||= "default"
35
34
  self.response_class ||= "answer"
@@ -33,9 +33,7 @@ module Surveyor
33
33
  # Instance methods
34
34
  def to_hash(response_set)
35
35
  # all responses to associated question
36
- responses = response_set.responses.select do |r|
37
- question && question.answers.include?(r.answer)
38
- end
36
+ responses = question.blank? ? [] : response_set.responses.where("responses.answer_id in (?)", question.answer_ids).all
39
37
  {rule_key.to_sym => (!responses.empty? and self.is_met?(responses))}
40
38
  end
41
39
 
@@ -36,7 +36,6 @@ module Surveyor
36
36
  self.is_mandatory ||= true
37
37
  self.display_type ||= "default"
38
38
  self.pick ||= "none"
39
- self.display_order ||= self.survey_section ? self.survey_section.questions.count : 0
40
39
  self.data_export_identifier ||= Surveyor::Common.normalize(text)
41
40
  self.short_text ||= text
42
41
  self.api_id ||= UUID.generate
@@ -34,7 +34,7 @@ module Surveyor
34
34
  write_attribute :answer_id, (val.is_a?(Array) ? val.detect{|x| !x.to_s.blank?} : val)
35
35
  end
36
36
  def correct?
37
- question.correct_answer_id.nil? or self.answer.response_class != "answer" or (question.correct_answer_id.to_i == answer_id.to_i)
37
+ question.correct_answer.nil? or self.answer.response_class != "answer" or (question.correct_answer.id.to_i == answer.id.to_i)
38
38
  end
39
39
 
40
40
  def to_s # used in dependency_explanation_helper
@@ -46,4 +46,4 @@ module Surveyor
46
46
  end
47
47
  end
48
48
  end
49
- end
49
+ end
@@ -9,39 +9,41 @@ module Surveyor
9
9
  base.send :belongs_to, :user
10
10
  base.send :has_many, :responses, :dependent => :destroy
11
11
  base.send :accepts_nested_attributes_for, :responses, :allow_destroy => true
12
-
12
+
13
13
  @@validations_already_included ||= nil
14
14
  unless @@validations_already_included
15
15
  # Validations
16
16
  base.send :validates_presence_of, :survey_id
17
17
  base.send :validates_associated, :responses
18
18
  base.send :validates_uniqueness_of, :access_code
19
-
19
+
20
20
  @@validations_already_included = true
21
21
  end
22
22
 
23
23
  # Attributes
24
24
  base.send :attr_protected, :completed_at
25
-
25
+
26
26
  # Class methods
27
27
  base.instance_eval do
28
- def reject_or_destroy_blanks(hash_of_hashes)
29
- result = {}
28
+ def to_savable(hash_of_hashes)
29
+ result = []
30
30
  (hash_of_hashes || {}).each_pair do |k, hash|
31
31
  hash = Response.applicable_attributes(hash)
32
32
  if has_blank_value?(hash)
33
- result.merge!({k => hash.merge("_destroy" => "true")}) if hash.has_key?("id")
33
+ result << hash.merge!({:_destroy => '1'}).except('answer_id') if hash.has_key?('id')
34
34
  else
35
- result.merge!({k => hash})
35
+ result << hash
36
36
  end
37
37
  end
38
38
  result
39
39
  end
40
+
40
41
  def has_blank_value?(hash)
41
42
  return true if hash["answer_id"].blank?
42
43
  return false if (q = Question.find_by_id(hash["question_id"])) and q.pick == "one"
43
44
  hash.any?{|k,v| v.is_a?(Array) ? v.all?{|x| x.to_s.blank?} : v.to_s.blank?}
44
45
  end
46
+
45
47
  def trim_for_lookups(hash_of_hashes)
46
48
  result = {}
47
49
  (reject_or_destroy_blanks(hash_of_hashes) || {}).each_pair do |k, hash|
@@ -49,6 +51,20 @@ module Surveyor
49
51
  end
50
52
  result
51
53
  end
54
+
55
+ private
56
+ def reject_or_destroy_blanks(hash_of_hashes)
57
+ result = {}
58
+ (hash_of_hashes || {}).each_pair do |k, hash|
59
+ hash = Response.applicable_attributes(hash)
60
+ if has_blank_value?(hash)
61
+ result.merge!({k => hash.merge("_destroy" => "true")}) if hash.has_key?("id")
62
+ else
63
+ result.merge!({k => hash})
64
+ end
65
+ end
66
+ result
67
+ end
52
68
  end
53
69
  end
54
70
 
@@ -86,7 +102,7 @@ module Surveyor
86
102
  def complete!
87
103
  self.completed_at = Time.now
88
104
  end
89
-
105
+
90
106
  def complete?
91
107
  !completed_at.nil?
92
108
  end
@@ -131,13 +147,13 @@ module Surveyor
131
147
  def unanswered_dependencies
132
148
  unanswered_question_dependencies + unanswered_question_group_dependencies
133
149
  end
134
-
150
+
135
151
  def unanswered_question_dependencies
136
- dependencies.select{|d| d.is_met?(self) and d.question and self.is_unanswered?(d.question)}.map(&:question)
152
+ dependencies.select{ |d| d.question && self.is_unanswered?(d.question) && d.is_met?(self) }.map(&:question)
137
153
  end
138
-
154
+
139
155
  def unanswered_question_group_dependencies
140
- dependencies.select{|d| d.is_met?(self) and d.question_group and self.is_group_unanswered?(d.question_group)}.map(&:question_group)
156
+ dependencies.select{ |d| d.question_group && self.is_group_unanswered?(d.question_group) && d.is_met?(self) }.map(&:question_group)
141
157
  end
142
158
 
143
159
  def all_dependencies(question_ids = nil)
@@ -151,11 +167,11 @@ module Surveyor
151
167
  end
152
168
 
153
169
  protected
154
-
170
+
155
171
  def dependencies(question_ids = nil)
156
172
  deps = Dependency.all(:include => :dependency_conditions, :conditions => {:dependency_conditions => {:question_id => question_ids || responses.map(&:question_id)}})
157
173
  # this is a work around for a bug in active_record in rails 2.3 which incorrectly eager-loads associatins when a condition clause includes an association limiter
158
- deps.each{|d| d.dependency_conditions.reload}
174
+ deps.each{|d| d.dependency_conditions.reload}
159
175
  deps
160
176
  end
161
177
  end
@@ -10,7 +10,7 @@ module Surveyor
10
10
  base.send :has_many, :response_sets
11
11
 
12
12
  # Scopes
13
- base.send :named_scope, :with_sections, {:include => :sections}
13
+ base.send :scope, :with_sections, {:include => :sections}
14
14
 
15
15
  @@validations_already_included ||= nil
16
16
  unless @@validations_already_included
@@ -39,6 +39,7 @@ module Surveyor
39
39
  def default_args
40
40
  self.inactive_at ||= DateTime.now
41
41
  self.api_id ||= UUID.generate
42
+ self.display_order ||= Survey.count
42
43
  end
43
44
 
44
45
  def title=(value)
@@ -8,7 +8,7 @@ module Surveyor
8
8
 
9
9
  # Scopes
10
10
  base.send :default_scope, :order => "display_order ASC"
11
- base.send :named_scope, :with_includes, { :include => {:questions => [:answers, :question_group, {:dependency => :dependency_conditions}]}}
11
+ base.send :scope, :with_includes, { :include => {:questions => [:answers, :question_group, {:dependency => :dependency_conditions}]}}
12
12
 
13
13
  @@validations_already_included ||= nil
14
14
  unless @@validations_already_included
@@ -28,7 +28,6 @@ module Surveyor
28
28
  end
29
29
 
30
30
  def default_args
31
- self.display_order ||= survey ? survey.sections.count : 0
32
31
  self.data_export_identifier ||= Surveyor::Common.normalize(title)
33
32
  end
34
33
 
@@ -80,7 +80,7 @@ class Survey < ActiveRecord::Base
80
80
  # build and set context
81
81
  title = args[0]
82
82
  context[:survey] = new({ :title => title,
83
- :reference_identifier => reference_identifier}.merge(args[1] || {}))
83
+ :reference_identifier => reference_identifier }.merge(args[1] || {}))
84
84
  end
85
85
  def clear(context)
86
86
  context.delete_if{|k,v| true }
@@ -97,7 +97,8 @@ class SurveySection < ActiveRecord::Base
97
97
 
98
98
  # build and set context
99
99
  title = args[0]
100
- context[:survey_section] = context[:survey].sections.build({ :title => title }.merge(args[1] || {}))
100
+ context[:survey_section] = context[:survey].sections.build({ :title => title,
101
+ :display_order => context[:survey].sections.size }.merge(args[1] || {}))
101
102
  end
102
103
  def clear(context)
103
104
  context.delete_if{|k,v| !%w(survey question_references answer_references).map(&:to_sym).include?(k)}
@@ -137,7 +138,8 @@ class Question < ActiveRecord::Base
137
138
  :question_group => context[:question_group],
138
139
  :reference_identifier => reference_identifier,
139
140
  :text => text,
140
- :display_type => (original_method =~ /label|image/ ? original_method : "default")}.merge(args[1] || {}))
141
+ :display_type => (original_method =~ /label|image/ ? original_method : "default"),
142
+ :display_order => context[:survey_section].questions.size }.merge(args[1] || {}))
141
143
 
142
144
  # keep reference for dependencies
143
145
  context[:question_references][reference_identifier] = context[:question] unless reference_identifier.blank?
@@ -218,15 +220,15 @@ class Answer < ActiveRecord::Base
218
220
  # clear context
219
221
  context.delete_if{|k,v| %w(answer validation validation_condition reference_identifier).map(&:to_sym).include? k}
220
222
 
221
- attrs = { :reference_identifier => reference_identifier}.merge(self.parse_args(args))
223
+ attrs = { :reference_identifier => reference_identifier }.merge(self.parse_args(args))
222
224
 
223
225
  # add answers to grid
224
226
  if context[:question_group] && context[:question_group].display_type == "grid"
225
- context[:answer] = new(attrs)
226
- context[:grid_answers] ||= []
227
+ context[:grid_answers] ||= []
228
+ context[:answer] = new({:display_order => [:grid_answers].size}.merge(attrs))
227
229
  context[:grid_answers] << context[:answer]
228
230
  else
229
- context[:answer] = context[:question].answers.build(attrs)
231
+ context[:answer] = context[:question].answers.build({:display_order => context[:question].answers.size}.merge(attrs))
230
232
  context[:answer_references][context[:question].reference_identifier] ||= {} unless context[:question].reference_identifier.blank?
231
233
  context[:answer_references][context[:question].reference_identifier][reference_identifier] = context[:answer] unless reference_identifier.blank? or context[:question].reference_identifier.blank?
232
234
  end
@@ -35,7 +35,7 @@ module Surveyor
35
35
  Dependency.build_and_set(context, r)
36
36
  end
37
37
  end
38
- print context[:survey].save ? "saved. " : " not saved! #{context[:survey].errors.each_full{|x| x }.join(", ")} "
38
+ print context[:survey].save ? "saved. " : " not saved! #{context[:survey].errors.full_messages.join(", ")} "
39
39
  # print context[:survey].sections.map(&:questions).flatten.map(&:answers).flatten.map{|x| x.errors.each_full{|y| y}.join}.join
40
40
  rescue csvlib::MalformedCSVError
41
41
  puts = "Oops. Not a valid CSV file."
@@ -65,7 +65,9 @@ class SurveySection < ActiveRecord::Base
65
65
  if match = context[:survey].sections.detect{|ss| ss.reference_identifier == r[:form_name]}
66
66
  context[:current_survey_section] = match
67
67
  else
68
- context[:survey_section] = context[:survey].sections.build({:title => r[:form_name].to_s.humanize, :reference_identifier => r[:form_name]})
68
+ context[:survey_section] = context[:survey].sections.build({:title => r[:form_name].to_s.humanize,
69
+ :reference_identifier => r[:form_name],
70
+ :display_order => context[:survey].sections.size })
69
71
  print "survey_section_#{context[:survey_section].reference_identifier} "
70
72
  end
71
73
  end
@@ -76,7 +78,7 @@ end
76
78
  class Question < ActiveRecord::Base
77
79
  def self.build_and_set(context, r)
78
80
  if !r[:section_header].blank?
79
- context[:survey_section].questions.build({:display_type => "label", :text => r[:section_header]})
81
+ context[:survey_section].questions.build({:display_type => "label", :text => r[:section_header], :display_order => context[:survey_section].questions.size})
80
82
  print "label_ "
81
83
  end
82
84
  context[:question] = context[:survey_section].questions.build({
@@ -85,7 +87,8 @@ class Question < ActiveRecord::Base
85
87
  :help_text => r[:field_note],
86
88
  :is_mandatory => (/^y/i.match r[:required_field]) ? true : false,
87
89
  :pick => pick_from_field_type(r[:field_type]),
88
- :display_type => display_type_from_field_type(r[:field_type])
90
+ :display_type => display_type_from_field_type(r[:field_type]),
91
+ :display_order => context[:survey_section].questions.size
89
92
  })
90
93
  unless context[:question].reference_identifier.blank?
91
94
  context[:lookup] ||= []
@@ -178,9 +181,9 @@ class Answer < ActiveRecord::Base
178
181
  def self.build_and_set(context, r)
179
182
  case r[:field_type]
180
183
  when "text"
181
- context[:answer] = context[:question].answers.build(:response_class => "string", :text => "Text")
184
+ context[:answer] = context[:question].answers.build(:response_class => "string", :text => "Text", :display_order => context[:question].answers.size)
182
185
  when "notes"
183
- context[:answer] = context[:question].answers.build(:response_class => "text", :text => "Notes")
186
+ context[:answer] = context[:question].answers.build(:response_class => "text", :text => "Notes", :display_order => context[:question].answers.size)
184
187
  when "file"
185
188
  puts "\n!!! skipping answer: file"
186
189
  end
@@ -189,7 +192,7 @@ class Answer < ActiveRecord::Base
189
192
  if aref.blank? or atext.blank? or (aref.to_i.to_s != aref)
190
193
  puts "\n!!! skipping answer #{pair}"
191
194
  else
192
- context[:answer] = context[:question].answers.build(:reference_identifier => aref, :text => atext)
195
+ context[:answer] = context[:question].answers.build(:reference_identifier => aref, :text => atext, :display_order => context[:question].answers.size)
193
196
  unless context[:question].reference_identifier.blank? or aref.blank? or !context[:answer].valid?
194
197
  context[:lookup] ||= []
195
198
  context[:lookup] << [context[:question].reference_identifier, aref, context[:answer]]
@@ -2,6 +2,7 @@ module Surveyor
2
2
  module SurveyorControllerMethods
3
3
  def self.included(base)
4
4
  base.send :before_filter, :get_current_user, :only => [:new, :create]
5
+ base.send :before_filter, :determine_if_javascript_is_enabled, :only => [:create, :update]
5
6
  base.send :layout, 'surveyor_default'
6
7
  end
7
8
 
@@ -45,12 +46,12 @@ module Surveyor
45
46
  if @response_set
46
47
  @survey = Survey.with_sections.find_by_id(@response_set.survey_id)
47
48
  @sections = @survey.sections
48
- if params[:section]
49
- @section = @sections.with_includes.find(section_id_from(params[:section])) || @sections.with_includes.first
49
+ if params[:section]
50
+ @section = @sections.with_includes.find(section_id_from(params[:section])) || @sections.with_includes.first
50
51
  else
51
52
  @section = @sections.with_includes.first
52
53
  end
53
- @dependents = (@response_set.unanswered_dependencies - @section.questions) || []
54
+ set_dependents
54
55
  else
55
56
  flash[:notice] = t('surveyor.unable_to_find_your_responses')
56
57
  redirect_to surveyor_index
@@ -58,20 +59,25 @@ module Surveyor
58
59
  end
59
60
 
60
61
  def update
61
- @response_set = ResponseSet.find_by_access_code(params[:response_set_code], :include => {:responses => :answer}, :lock => true)
62
- return redirect_with_message(available_surveys_path, :notice, t('surveyor.unable_to_find_your_responses')) if @response_set.blank?
63
62
  saved = false
64
63
  ActiveRecord::Base.transaction do
65
- saved = @response_set.update_attributes(:responses_attributes => ResponseSet.reject_or_destroy_blanks(params[:r]))
66
- @response_set.complete! if saved && params[:finish]
67
- saved &= @response_set.save
64
+ @response_set = ResponseSet.find_by_access_code(params[:response_set_code], :include => {:responses => :answer}, :lock => true)
65
+ unless @response_set.blank?
66
+ saved = @response_set.update_attributes(:responses_attributes => ResponseSet.to_savable(params[:r]))
67
+ @response_set.complete! if saved && params[:finish]
68
+ saved &= @response_set.save
69
+ end
68
70
  end
69
71
  return redirect_with_message(surveyor_finish, :notice, t('surveyor.completed_survey')) if saved && params[:finish]
70
72
 
71
73
  respond_to do |format|
72
74
  format.html do
73
- flash[:notice] = t('surveyor.unable_to_update_survey') unless saved
74
- redirect_to :action => "edit", :anchor => anchor_from(params[:section]), :params => {:section => section_id_from(params[:section])}
75
+ if @response_set.blank?
76
+ return redirect_with_message(available_surveys_path, :notice, t('surveyor.unable_to_find_your_responses'))
77
+ else
78
+ flash[:notice] = t('surveyor.unable_to_update_survey') unless saved
79
+ redirect_to edit_my_survey_path(:anchor => anchor_from(params[:section]), :section => section_id_from(params[:section]))
80
+ end
75
81
  end
76
82
  format.js do
77
83
  ids, remove, question_ids = {}, {}, []
@@ -109,7 +115,7 @@ module Surveyor
109
115
  def surveyor_finish
110
116
  available_surveys_path
111
117
  end
112
-
118
+
113
119
  def redirect_with_message(path, message_type, message)
114
120
  respond_to do |format|
115
121
  format.html do
@@ -121,5 +127,33 @@ module Surveyor
121
127
  end
122
128
  end
123
129
  end
130
+
131
+ ##
132
+ # @dependents are necessary in case the client does not have javascript enabled
133
+ # Whether or not javascript is enabled is determined by a hidden field set in the surveyor/edit.html form
134
+ def set_dependents
135
+ if session[:surveyor_javascript] && session[:surveyor_javascript] == "enabled"
136
+ @dependents = []
137
+ else
138
+ @dependents = get_unanswered_dependencies_minus_section_questions
139
+ end
140
+ end
141
+
142
+ def get_unanswered_dependencies_minus_section_questions
143
+ @response_set.unanswered_dependencies - @section.questions || []
144
+ end
145
+
146
+ ##
147
+ # If the hidden field surveyor_javascript_enabled is set to true
148
+ # cf. surveyor/edit.html.haml
149
+ # the set the session variable [:surveyor_javascript] to "enabled"
150
+ def determine_if_javascript_is_enabled
151
+ if params[:surveyor_javascript_enabled] && params[:surveyor_javascript_enabled].to_s == "true"
152
+ session[:surveyor_javascript] = "enabled"
153
+ else
154
+ session[:surveyor_javascript] = "not_enabled"
155
+ end
156
+ end
157
+
124
158
  end
125
159
  end