surveyor 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +17 -0
- data/app/views/partials/_question.html.haml +19 -18
- data/app/views/partials/_question_group.html.haml +39 -38
- data/features/surveyor.feature +31 -0
- data/features/surveyor_parser.feature +61 -2
- data/lib/surveyor/models/dependency_condition_methods.rb +2 -2
- data/lib/surveyor/parser.rb +57 -15
- data/lib/surveyor/surveyor_admin_controller_methods.rb +55 -0
- data/lib/surveyor/version.rb +1 -1
- data/spec/factories.rb +1 -1
- data/spec/lib/parser_spec.rb +5 -1
- data/spec/models/dependency_condition_spec.rb +32 -3
- metadata +3 -2
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,23 @@
|
|
1
1
|
History for Surveyor
|
2
2
|
====================
|
3
3
|
|
4
|
+
1.0.1
|
5
|
+
------
|
6
|
+
|
7
|
+
### Features
|
8
|
+
|
9
|
+
- Question#display_type == "hidden" and QuestionGroup#display_type == "hidden"
|
10
|
+
now exclude the question or question group from the DOM. These display types are
|
11
|
+
used to inject data (responses) into surveys. Note, custom_class => "hidden" doesn't
|
12
|
+
have any effect until a custom css rule is created by the end user. (#197)
|
13
|
+
- more readable parser and more strict parser method aliases (#278)
|
14
|
+
|
15
|
+
### Fixes
|
16
|
+
|
17
|
+
- Replaced deprecated ActiveRecord::Errors#each_full with ActiveRecord::Errors#full_messages. (#363)
|
18
|
+
- fixing dependency condition evaluation where #Response.*_value is nil. (#297)
|
19
|
+
- fixing grid answers leak, introduced in 5baa7ac3. thanks @jsurrett (#375, #377)
|
20
|
+
|
4
21
|
1.0.0
|
5
22
|
------
|
6
23
|
|
@@ -2,26 +2,27 @@
|
|
2
2
|
- rg ||= nil
|
3
3
|
- renderer = q.renderer(g ||= nil)
|
4
4
|
- disabled = defined?(disableFlag) ? disableFlag : false
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
-
|
11
|
-
- i = response_idx
|
12
|
-
= f.semantic_fields_for i, r do |ff|
|
13
|
-
= ff.input :question_id, :as => :quiet
|
14
|
-
= ff.input :response_group, :as => :quiet, :value => rg if g && g.display_type == "repeater"
|
15
|
-
= ff.input :api_id, :as => :quiet
|
16
|
-
= ff.input :answer_id, :as => :select, :collection => q.answers.map{|a| [a.text, a.id]}, :include_blank => (renderer != :slider), :label => q.text, :input_html => { :disabled => disabled }
|
17
|
-
- else # :default, :inline, :inline_default
|
18
|
-
- if q.pick == "one"
|
5
|
+
- unless q.display_type == "hidden"
|
6
|
+
= f.inputs q_text(q, @render_context), :id => rg ? "q_#{q.id}_#{rg}" : "q_#{q.id}", :class => "q_#{renderer} #{q.css_class(@response_set)}" do
|
7
|
+
%span.help= render_help_text(q, @render_context)
|
8
|
+
- case renderer
|
9
|
+
- when :image, :label
|
10
|
+
- when :dropdown, :inline_dropdown, :default_dropdown, :slider, :repeater_dropdown
|
19
11
|
- r = response_for(@response_set, q, nil, rg)
|
20
|
-
- i = response_idx
|
12
|
+
- i = response_idx
|
21
13
|
= f.semantic_fields_for i, r do |ff|
|
22
14
|
= ff.input :question_id, :as => :quiet
|
23
15
|
= ff.input :response_group, :as => :quiet, :value => rg if g && g.display_type == "repeater"
|
24
16
|
= ff.input :api_id, :as => :quiet
|
25
|
-
|
26
|
-
|
27
|
-
|
17
|
+
= ff.input :answer_id, :as => :select, :collection => q.answers.map{|a| [a.text, a.id]}, :include_blank => (renderer != :slider), :label => q.text, :input_html => { :disabled => disabled }
|
18
|
+
- else # :default, :inline, :inline_default
|
19
|
+
- if q.pick == "one"
|
20
|
+
- r = response_for(@response_set, q, nil, rg)
|
21
|
+
- i = response_idx # increment the response index since the answer partial skips for q.pick == one
|
22
|
+
= f.semantic_fields_for i, r do |ff|
|
23
|
+
= ff.input :question_id, :as => :quiet
|
24
|
+
= ff.input :response_group, :as => :quiet, :value => rg if g && g.display_type == "repeater"
|
25
|
+
= ff.input :api_id, :as => :quiet
|
26
|
+
- q.answers.each do |a|
|
27
|
+
- next if (q.pick == "one" or q.pick == "any") and disabled and @response_set.responses.where( :question_id => q.id, :answer_id => a.id).empty?
|
28
|
+
= render a.custom_renderer || '/partials/answer', :q => q, :a => a, :f => f, :rg => rg, :g => g, :disableFlag => disabled
|
@@ -1,40 +1,41 @@
|
|
1
1
|
- renderer = g.renderer
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
-
|
6
|
-
|
7
|
-
%table
|
8
|
-
%col.pre
|
9
|
-
- qs.first.answers.each do |a|
|
10
|
-
%col{:class => cycle("odd", "even")}
|
11
|
-
%col.post
|
12
|
-
%tbody
|
13
|
-
- qs.each_slice(10) do |ten_questions| # header row every 10
|
14
|
-
%tr
|
15
|
-
%th
|
16
|
-
- ten_questions.first.answers.each do |a|
|
17
|
-
%th= a_text(a)
|
18
|
-
%th
|
19
|
-
- ten_questions.each_with_index do |q, i|
|
20
|
-
%tr{:id => "q_#{q.id}", :class => "q_#{renderer} #{q.css_class(@response_set)}"}
|
21
|
-
%th
|
22
|
-
= q.split_text(:pre)
|
23
|
-
- if q.pick == "one"
|
24
|
-
- r = response_for(@response_set, q, nil, g)
|
25
|
-
- i = response_idx # increment the response index since the answer partial skips for q.pick == one
|
26
|
-
= f.semantic_fields_for i, r do |ff|
|
27
|
-
= ff.input :question_id, :as => :quiet
|
28
|
-
= ff.input :api_id, :as => :quiet
|
29
|
-
- q.answers.each do |a|
|
30
|
-
%td= render a.custom_renderer || '/partials/answer', :g => g, :q => q, :a => a, :f => f
|
31
|
-
%th= q.split_text(:post)
|
32
|
-
- when :repeater
|
33
|
-
- (@response_set.count_group_responses(qs) + 1).times do |rg|
|
2
|
+
- unless g.display_type == "hidden"
|
3
|
+
= f.inputs q_text(g, @render_context), :id => "g_#{g.id}", :class => "g_#{renderer} #{g.css_class(@response_set)}" do
|
4
|
+
%li.help= render_help_text(g, @render_context)
|
5
|
+
- case renderer
|
6
|
+
- when :grid
|
34
7
|
%li
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
8
|
+
%table
|
9
|
+
%col.pre
|
10
|
+
- qs.first.answers.each do |a|
|
11
|
+
%col{:class => cycle("odd", "even")}
|
12
|
+
%col.post
|
13
|
+
%tbody
|
14
|
+
- qs.each_slice(10) do |ten_questions| # header row every 10
|
15
|
+
%tr
|
16
|
+
%th
|
17
|
+
- ten_questions.first.answers.each do |a|
|
18
|
+
%th= a_text(a)
|
19
|
+
%th
|
20
|
+
- ten_questions.each_with_index do |q, i|
|
21
|
+
%tr{:id => "q_#{q.id}", :class => "q_#{renderer} #{q.css_class(@response_set)}"}
|
22
|
+
%th
|
23
|
+
= q.split_text(:pre)
|
24
|
+
- if q.pick == "one"
|
25
|
+
- r = response_for(@response_set, q, nil, g)
|
26
|
+
- i = response_idx # increment the response index since the answer partial skips for q.pick == one
|
27
|
+
= f.semantic_fields_for i, r do |ff|
|
28
|
+
= ff.input :question_id, :as => :quiet
|
29
|
+
= ff.input :api_id, :as => :quiet
|
30
|
+
- q.answers.each do |a|
|
31
|
+
%td= render a.custom_renderer || '/partials/answer', :g => g, :q => q, :a => a, :f => f
|
32
|
+
%th= q.split_text(:post)
|
33
|
+
- when :repeater
|
34
|
+
- (@response_set.count_group_responses(qs) + 1).times do |rg|
|
35
|
+
%li
|
36
|
+
- qs.each do |q|
|
37
|
+
= render q.custom_renderer || "/partials/question", :g => g, :rg => rg, :q => q, :f => f
|
38
|
+
= submit_tag("+ add row", :name => "section[#{@section.id}][g_#{g.id}]", :class => "add_row")
|
39
|
+
- else # :inline
|
40
|
+
- qs.each do |q|
|
41
|
+
= render q.custom_renderer || "/partials/question", :g => g, :q => q, :f => f
|
data/features/surveyor.feature
CHANGED
@@ -660,3 +660,34 @@ Feature: Survey creation
|
|
660
660
|
When I check "Refused"
|
661
661
|
Then the checkbox for "Electric" should be disabled
|
662
662
|
And the checkbox for "Don't know" should be disabled
|
663
|
+
|
664
|
+
# #197 - Add a hidden field type, don't show hidden questions and groups in the DOM
|
665
|
+
# don't use up question numbers on them either. custom class "hidden" doesn't
|
666
|
+
# do anything until you add your own css to hide it
|
667
|
+
Scenario: hidden questions for injecting data
|
668
|
+
Given I parse
|
669
|
+
"""
|
670
|
+
survey "Sesame Street" do
|
671
|
+
section "The Count" do
|
672
|
+
q_name "What is your name?", :display_type => :hidden
|
673
|
+
a :string, :help_text => "(e.g. Count Von Count)"
|
674
|
+
|
675
|
+
group "Friends", :display_type => :hidden do
|
676
|
+
q "Who are your friends?"
|
677
|
+
a :string
|
678
|
+
end
|
679
|
+
|
680
|
+
label "AH AH AH AH AH!"
|
681
|
+
|
682
|
+
q_numbers "What is your favorite number?", :pick => :one, :custom_class => "hidden"
|
683
|
+
a "One"
|
684
|
+
a "Two"
|
685
|
+
a "Three!"
|
686
|
+
end
|
687
|
+
end
|
688
|
+
"""
|
689
|
+
When I start the "Sesame Street" survey
|
690
|
+
Then I should see "AH AH AH AH AH!"
|
691
|
+
And I should see "1) What is your favorite number?"
|
692
|
+
And I should not see "What is your name?"
|
693
|
+
|
@@ -3,7 +3,6 @@ Feature: Survey parser
|
|
3
3
|
I want to write out the survey in the DSL
|
4
4
|
So that I can give it to survey participants
|
5
5
|
|
6
|
-
@focus
|
7
6
|
Scenario: Parsing basic questions
|
8
7
|
Given I parse
|
9
8
|
"""
|
@@ -345,7 +344,7 @@ Feature: Survey parser
|
|
345
344
|
end
|
346
345
|
|
347
346
|
"""
|
348
|
-
Then the parser should fail with "
|
347
|
+
Then the parser should fail with "\"sectionals\" is not a surveyor method."
|
349
348
|
|
350
349
|
Scenario: Parsing bad references
|
351
350
|
Given the survey
|
@@ -390,3 +389,63 @@ Feature: Survey parser
|
|
390
389
|
end
|
391
390
|
"""
|
392
391
|
Then the parser should fail with "Duplicate references: q_watch, a_1; q_watch"
|
392
|
+
|
393
|
+
Scenario: Parsing with Rails validation errors
|
394
|
+
Given the survey
|
395
|
+
"""
|
396
|
+
survey do
|
397
|
+
section "Usage" do
|
398
|
+
q_PLACED_BAG_1 "Is the bag placed?", :pick => :one
|
399
|
+
a_1 "Yes"
|
400
|
+
a_2 "No"
|
401
|
+
a_3 "Refused"
|
402
|
+
end
|
403
|
+
end
|
404
|
+
"""
|
405
|
+
Then the parser should fail with "Survey not saved: Title can't be blank"
|
406
|
+
|
407
|
+
Scenario: Parsing bad shortcuts
|
408
|
+
Given the survey
|
409
|
+
"""
|
410
|
+
survey "shortcuts" do
|
411
|
+
section "Bad" do
|
412
|
+
quack "Do you like ducks?", :pick => :one
|
413
|
+
a_1 "Yes"
|
414
|
+
a_1 "No"
|
415
|
+
end
|
416
|
+
end
|
417
|
+
"""
|
418
|
+
Then the parser should fail with "\"quack\" is not a surveyor method."
|
419
|
+
|
420
|
+
Scenario: Clearing grid answers
|
421
|
+
Given I parse
|
422
|
+
"""
|
423
|
+
survey "Grids" do
|
424
|
+
section "Leaking" do
|
425
|
+
grid "How would you rate the following?" do
|
426
|
+
a "bad"
|
427
|
+
a "neutral"
|
428
|
+
a "good"
|
429
|
+
q "steak" , :pick => :one
|
430
|
+
q "chicken", :pick => :one
|
431
|
+
q "fish", :pick => :one
|
432
|
+
end
|
433
|
+
grid "How do you feel about the following?" do
|
434
|
+
a "sad"
|
435
|
+
a "indifferent"
|
436
|
+
a "happy"
|
437
|
+
q "births" , :pick => :one
|
438
|
+
q "weddings", :pick => :one
|
439
|
+
q "funerals", :pick => :one
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
443
|
+
"""
|
444
|
+
Then there should be 18 answers with:
|
445
|
+
| text | display_order |
|
446
|
+
| bad | 0 |
|
447
|
+
| neutral | 1 |
|
448
|
+
| good | 2 |
|
449
|
+
| sad | 0 |
|
450
|
+
| indifferent | 1 |
|
451
|
+
| happy | 2 |
|
@@ -46,11 +46,11 @@ module Surveyor
|
|
46
46
|
return {rule_key.to_sym => true}
|
47
47
|
elsif response = responses.detect{|r| r.answer.id == self.answer.id}
|
48
48
|
klass = response.answer.response_class
|
49
|
-
klass = "answer" if self.as(klass).nil?
|
49
|
+
klass = "answer" if self.as(klass).nil? # it should compare answer ids when the dependency condition *_value is nil
|
50
50
|
case self.operator
|
51
51
|
when "==", "<", ">", "<=", ">="
|
52
52
|
# logger.warn( {rule_key.to_sym => response.as(klass).send(self.operator, self.as(klass))})
|
53
|
-
return {rule_key.to_sym => response.as(klass).send(self.operator, self.as(klass))}
|
53
|
+
return {rule_key.to_sym => !response.as(klass).nil? && response.as(klass).send(self.operator, self.as(klass))}
|
54
54
|
when "!="
|
55
55
|
# logger.warn( {rule_key.to_sym => !response.as(klass).send("==", self.as(klass))})
|
56
56
|
return {rule_key.to_sym => !response.as(klass).send("==", self.as(klass))}
|
data/lib/surveyor/parser.rb
CHANGED
@@ -2,21 +2,53 @@
|
|
2
2
|
module Surveyor
|
3
3
|
class ParserError < StandardError; end
|
4
4
|
class Parser
|
5
|
-
class << self; attr_accessor :options end
|
5
|
+
class << self; attr_accessor :options, :log end
|
6
6
|
|
7
7
|
# Attributes
|
8
8
|
attr_accessor :context
|
9
9
|
|
10
10
|
# Class methods
|
11
11
|
def self.parse(str, options={})
|
12
|
+
self.ensure_attrs
|
12
13
|
self.options = options
|
14
|
+
self.log[:source] = str
|
13
15
|
Surveyor::Parser.rake_trace "\n"
|
14
16
|
Surveyor::Parser.new.parse(str)
|
15
17
|
Surveyor::Parser.rake_trace "\n"
|
16
18
|
end
|
17
|
-
def self.
|
19
|
+
def self.ensure_attrs
|
18
20
|
self.options ||= {}
|
19
|
-
|
21
|
+
self.log ||= {}
|
22
|
+
self.log[:indent] ||= 0
|
23
|
+
self.log[:source] ||= ""
|
24
|
+
end
|
25
|
+
def self.rake_trace(str, indent_increment=0)
|
26
|
+
self.ensure_attrs
|
27
|
+
unless str.blank?
|
28
|
+
puts "#{' ' * self.log[:indent]}#{str}" if self.options[:trace] == true
|
29
|
+
end
|
30
|
+
self.log[:indent] += indent_increment
|
31
|
+
end
|
32
|
+
# from https://github.com/rails/rails/blob/master/actionpack/lib/action_view/template/error.rb#L81
|
33
|
+
def self.source_extract(line)
|
34
|
+
source_code = self.log[:source].split("\n")
|
35
|
+
radius = 3
|
36
|
+
start_on_line = [ line - radius - 1, 0 ].max
|
37
|
+
end_on_line = [ line + radius - 1, source_code.length].min
|
38
|
+
|
39
|
+
return unless source_code = source_code[start_on_line..end_on_line]
|
40
|
+
line_counter = start_on_line
|
41
|
+
source_code.sum do |line|
|
42
|
+
line_counter += 1
|
43
|
+
"#{line_counter}: #{line}\n"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
def self.raise_error(str, skip_trace = false)
|
47
|
+
self.ensure_attrs
|
48
|
+
line = caller[1].split('/').last.split(':')[1].to_i
|
49
|
+
|
50
|
+
raise Surveyor::ParserError, "#{str}\n" if skip_trace
|
51
|
+
raise Surveyor::ParserError, "#{self.source_extract(line)}\nline \##{line}: #{str}\n"
|
20
52
|
end
|
21
53
|
|
22
54
|
# Instance methods
|
@@ -31,12 +63,14 @@ module Surveyor
|
|
31
63
|
def method_missing(missing_method, *args, &block)
|
32
64
|
method_name, reference_identifier = missing_method.to_s.split("_", 2)
|
33
65
|
type = full(method_name)
|
66
|
+
Surveyor::Parser.raise_error( "\"#{type}\" is not a surveyor method." )if !%w(survey survey_section question_group question dependency dependency_condition answer validation validation_condition).include?(type)
|
34
67
|
|
35
|
-
Surveyor::Parser.rake_trace
|
68
|
+
Surveyor::Parser.rake_trace(reference_identifier.blank? ? "#{type} #{args.map(&:inspect).join ', '}" : "#{type}_#{reference_identifier} #{args.map(&:inspect).join ', '}",
|
69
|
+
block_models.include?(type) ? 2 : 0)
|
36
70
|
|
37
71
|
# check for blocks
|
38
|
-
|
39
|
-
|
72
|
+
Surveyor::Parser.raise_error "A #{type.humanize.downcase} should take a block" if block_models.include?(type) && !block_given?
|
73
|
+
Surveyor::Parser.raise_error "A #{type.humanize.downcase} doesn't take a block" if !block_models.include?(type) && block_given?
|
40
74
|
|
41
75
|
# parse and build
|
42
76
|
type.classify.constantize.new.extend("SurveyorParser#{type.classify}Methods".constantize).parse_and_build(context, args, method_name, reference_identifier)
|
@@ -48,9 +82,14 @@ module Surveyor
|
|
48
82
|
resolve_dependency_condition_references
|
49
83
|
resolve_question_correct_answers
|
50
84
|
report_lost_and_duplicate_references
|
51
|
-
Surveyor::Parser.rake_trace
|
52
|
-
|
85
|
+
Surveyor::Parser.rake_trace("", -2)
|
86
|
+
if context[:survey].save
|
87
|
+
Surveyor::Parser.rake_trace "Survey saved."
|
88
|
+
else
|
89
|
+
Surveyor::Parser.raise_error "Survey not saved: #{context[:survey].errors.full_messages.join(", ")}"
|
90
|
+
end
|
53
91
|
else
|
92
|
+
Surveyor::Parser.rake_trace("", -2)
|
54
93
|
context[type.to_sym].clear(context)
|
55
94
|
end
|
56
95
|
end
|
@@ -62,8 +101,8 @@ module Surveyor
|
|
62
101
|
def full(method_name)
|
63
102
|
case method_name.to_s
|
64
103
|
when /^section$/; "survey_section"
|
65
|
-
when /^g
|
66
|
-
when /^q
|
104
|
+
when /^g$|^grid$|^group$|^repeater$/; "question_group"
|
105
|
+
when /^q$|^label$|^image$/; "question"
|
67
106
|
when /^a$/; "answer"
|
68
107
|
when /^d$/; "dependency"
|
69
108
|
when /^c(ondition)?$/; context[:validation] ? "validation_condition" : "dependency_condition"
|
@@ -77,8 +116,8 @@ module Surveyor
|
|
77
116
|
%w(survey survey_section question_group)
|
78
117
|
end
|
79
118
|
def report_lost_and_duplicate_references
|
80
|
-
|
81
|
-
|
119
|
+
Surveyor::Parser.raise_error("Bad references: #{self.context[:bad_references].join("; ")}", true) unless self.context[:bad_references].empty?
|
120
|
+
Surveyor::Parser.raise_error("Duplicate references: #{self.context[:duplicate_references].join("; ")}", true) unless self.context[:duplicate_references].empty?
|
82
121
|
end
|
83
122
|
def resolve_question_correct_answers
|
84
123
|
self.context[:questions_with_correct_answers].each do |question_reference_idenitifer, correct_answer_reference|
|
@@ -126,7 +165,8 @@ module SurveyorParserSurveyMethods
|
|
126
165
|
:bad_references => [],
|
127
166
|
:duplicate_references => [],
|
128
167
|
:dependency_conditions => [],
|
129
|
-
:questions_with_correct_answers => {}
|
168
|
+
:questions_with_correct_answers => {}
|
169
|
+
})
|
130
170
|
end
|
131
171
|
end
|
132
172
|
|
@@ -146,6 +186,7 @@ module SurveyorParserSurveySectionMethods
|
|
146
186
|
def clear(context)
|
147
187
|
[ :survey_section,
|
148
188
|
:question_group,
|
189
|
+
:grid_answers,
|
149
190
|
:question,
|
150
191
|
:dependency,
|
151
192
|
:dependency_condition,
|
@@ -169,12 +210,14 @@ module SurveyorParserQuestionGroupMethods
|
|
169
210
|
end
|
170
211
|
def clear(context)
|
171
212
|
[ :question_group,
|
213
|
+
:grid_answers,
|
172
214
|
:question,
|
173
215
|
:dependency,
|
174
216
|
:dependency_condition,
|
175
217
|
:answer,
|
176
218
|
:validation,
|
177
219
|
:validation_condition ].each{|k| context.delete k}
|
220
|
+
context[:grid_answers] = []
|
178
221
|
end
|
179
222
|
end
|
180
223
|
|
@@ -271,8 +314,7 @@ module SurveyorParserAnswerMethods
|
|
271
314
|
|
272
315
|
# add answers to grid
|
273
316
|
if context[:question_group] && context[:question_group].display_type == "grid"
|
274
|
-
context[:grid_answers]
|
275
|
-
self.attributes = ({:display_order => [:grid_answers].size}.merge(attrs))
|
317
|
+
self.attributes = ({:display_order => context[:grid_answers].size}.merge(attrs))
|
276
318
|
context[:grid_answers] << context[:answer] = self
|
277
319
|
else
|
278
320
|
self.attributes = ({:display_order => context[:question].answers.size}.merge(attrs))
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Surveyor
|
2
|
+
module SurveyorAdminControllerMethods
|
3
|
+
def self.included(base)
|
4
|
+
# base.send :before_filter, :get_current_user, :only => [:new, :create]
|
5
|
+
# base.send :layout, 'surveyor_default'
|
6
|
+
end
|
7
|
+
|
8
|
+
# Actions
|
9
|
+
def new
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
def create
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def show
|
18
|
+
end
|
19
|
+
|
20
|
+
def edit
|
21
|
+
end
|
22
|
+
|
23
|
+
def update
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# This is a hoock method for surveyor-using applications to override and provide the context object
|
29
|
+
def render_context
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
|
33
|
+
# Filters
|
34
|
+
def get_current_user
|
35
|
+
@current_user = self.respond_to?(:current_user) ? self.current_user : nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_render_context
|
39
|
+
@render_context = render_context
|
40
|
+
end
|
41
|
+
|
42
|
+
def redirect_with_message(path, message_type, message)
|
43
|
+
respond_to do |format|
|
44
|
+
format.html do
|
45
|
+
flash[message_type] = message if !message.blank? and !message_type.blank?
|
46
|
+
redirect_to path
|
47
|
+
end
|
48
|
+
format.js do
|
49
|
+
render :text => message, :status => 403
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
data/lib/surveyor/version.rb
CHANGED
data/spec/factories.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
require 'rubygems'
|
3
3
|
require 'factory_girl'
|
4
4
|
|
5
|
-
Factory.sequence(:unique_survey_access_code){|n| "
|
5
|
+
Factory.sequence(:unique_survey_access_code){|n| "simple survey #{UUIDTools::UUID.random_create.to_s}" }
|
6
6
|
|
7
7
|
Factory.define :survey do |s|
|
8
8
|
s.title {"Simple survey"}
|
data/spec/lib/parser_spec.rb
CHANGED
@@ -22,11 +22,15 @@ describe Surveyor::Parser do
|
|
22
22
|
@parser.send(:full, "condition").should == "dependency_condition"
|
23
23
|
@parser.send(:full, "c").should == "dependency_condition"
|
24
24
|
end
|
25
|
+
it "should not translate bad shortcuts" do
|
26
|
+
@parser.send(:full, "quack").should == "quack"
|
27
|
+
@parser.send(:full, "grizzly").should == "grizzly"
|
28
|
+
end
|
25
29
|
it "should identify models that take blocks" do
|
26
30
|
@parser.send(:block_models).should == %w(survey survey_section question_group)
|
27
31
|
end
|
28
32
|
it "should return a survey object" do
|
29
33
|
Surveyor::Parser.new.parse("survey 'hi' do\n end").is_a?(Survey).should be_true
|
30
34
|
end
|
31
|
-
|
35
|
+
|
32
36
|
end
|
@@ -78,9 +78,37 @@ describe DependencyCondition do
|
|
78
78
|
dependency_condition.to_hash(rs).should == {:C => false}
|
79
79
|
end
|
80
80
|
|
81
|
+
|
82
|
+
it "should not assume that Response#as is not nil" do
|
83
|
+
# q_HEIGHT_FT "Portion of height in whole feet (e.g., 5)",
|
84
|
+
# :pick=>:one
|
85
|
+
# a :integer
|
86
|
+
# a_neg_1 "Refused"
|
87
|
+
# a_neg_2 "Don't know"
|
88
|
+
# label "Provided value is outside of the suggested range (4 to 7 feet). This value is admissible, but you may wish to verify."
|
89
|
+
# dependency :rule=>"A or B"
|
90
|
+
# condition_A :q_HEIGHT_FT, "<", {:integer_value => "4"}
|
91
|
+
# condition_B :q_HEIGHT_FT, ">", {:integer_value => "7"}
|
92
|
+
|
93
|
+
answer = Factory(:answer, :response_class => :integer)
|
94
|
+
@dependency_condition = DependencyCondition.new(
|
95
|
+
:dependency => Factory(:dependency),
|
96
|
+
:question => answer.question,
|
97
|
+
:answer => answer,
|
98
|
+
:operator => ">",
|
99
|
+
:integer_value => 4,
|
100
|
+
:rule_key => "A")
|
101
|
+
|
102
|
+
response = Factory(:response, :answer => answer, :question => answer.question)
|
103
|
+
response_set = response.response_set
|
104
|
+
response.integer_value.should == nil
|
105
|
+
|
106
|
+
@dependency_condition.to_hash(response_set).should == {:A => false}
|
107
|
+
end
|
108
|
+
|
81
109
|
describe "evaluate '==' operator" do
|
82
110
|
before(:each) do
|
83
|
-
@a = Factory(:answer)
|
111
|
+
@a = Factory(:answer, :response_class => "answer")
|
84
112
|
@b = Factory(:answer, :question => @a.question)
|
85
113
|
@r = Factory(:response, :question => @a.question, :answer => @a)
|
86
114
|
@rs = @r.response_set
|
@@ -310,7 +338,7 @@ describe DependencyCondition do
|
|
310
338
|
end
|
311
339
|
|
312
340
|
describe "evaluating with response_class string" do
|
313
|
-
it "should compare answer ids when the string_value is nil" do
|
341
|
+
it "should compare answer ids when the dependency condition string_value is nil" do
|
314
342
|
@a = Factory(:answer, :response_class => "string")
|
315
343
|
@b = Factory(:answer, :question => @a.question)
|
316
344
|
@r = Factory(:response, :question => @a.question, :answer => @a, :string_value => "")
|
@@ -319,7 +347,7 @@ describe DependencyCondition do
|
|
319
347
|
@dc.to_hash(@rs).should == {:J => true}
|
320
348
|
end
|
321
349
|
|
322
|
-
it "should compare strings when the string_value is not nil, even if it is blank" do
|
350
|
+
it "should compare strings when the dependency condition string_value is not nil, even if it is blank" do
|
323
351
|
@a = Factory(:answer, :response_class => "string")
|
324
352
|
@b = Factory(:answer, :question => @a.question)
|
325
353
|
@r = Factory(:response, :question => @a.question, :answer => @a, :string_value => "foo")
|
@@ -389,4 +417,5 @@ describe DependencyCondition do
|
|
389
417
|
@dc.to_hash(@rs).should == {:M => true}
|
390
418
|
end
|
391
419
|
end
|
420
|
+
|
392
421
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: surveyor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-10-
|
13
|
+
date: 2012-10-30 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rails
|
@@ -505,6 +505,7 @@ files:
|
|
505
505
|
- lib/surveyor/parser.rb
|
506
506
|
- lib/surveyor/redcap_parser.rb
|
507
507
|
- lib/surveyor/render_text.rb
|
508
|
+
- lib/surveyor/surveyor_admin_controller_methods.rb
|
508
509
|
- lib/surveyor/surveyor_controller_methods.rb
|
509
510
|
- lib/surveyor/unparser.rb
|
510
511
|
- lib/surveyor/version.rb
|