surveyor 1.0.0 → 1.0.1
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.
- 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
|