surveyor 0.19.6 → 0.19.7
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +11 -0
- data/README.md +4 -3
- data/VERSION +1 -1
- data/app/views/partials/_question.html.haml +1 -1
- data/doc/surveyor_models.png +0 -0
- data/doc/surveyor_models2.png +0 -0
- data/lib/surveyor/common.rb +3 -3
- data/lib/surveyor/models/dependency_condition_methods.rb +1 -0
- data/lib/surveyor/models/response_set_methods.rb +7 -3
- data/lib/surveyor/models/survey_methods.rb +3 -2
- data/lib/surveyor/redcap_parser.rb +5 -3
- data/spec/models/dependency_condition_spec.rb +22 -1
- data/spec/models/response_set_spec.rb +11 -2
- data/spec/models/survey_spec.rb +15 -8
- data/surveyor.gemspec +4 -2
- metadata +6 -4
data/CHANGELOG
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
0.19.7
|
2
|
+
|
3
|
+
* fix accidentally allowing through blank pick => any answers
|
4
|
+
* rewrote a test to reflect re-saving a survey via an admin controller
|
5
|
+
* stop survey titles from appending '1' to itself when calling update attributes
|
6
|
+
* fix response saving and dependencies on pick one/many with string. closes #158
|
7
|
+
* changed fastercsv to csv for ruby 1.9. closes #111
|
8
|
+
* changed .to_s to .join for ruby 1.9
|
9
|
+
* Merge pull request #137 from keviniano/master
|
10
|
+
* surveyor models
|
11
|
+
|
1
12
|
0.19.6
|
2
13
|
|
3
14
|
* fix parsing of group questions with dependencies. closes #160
|
data/README.md
CHANGED
@@ -97,11 +97,12 @@ and read surveys/EXTENDING\_SURVEYOR
|
|
97
97
|
|
98
98
|
Surveyor depends on:
|
99
99
|
|
100
|
-
* Ruby (1.8.7 - 1.9.
|
100
|
+
* Ruby (1.8.7 - 1.9.2)
|
101
101
|
* Rails 2.3
|
102
|
-
* HAML
|
102
|
+
* HAML
|
103
|
+
* SASS
|
104
|
+
* fastercsv (or CSV for ruby 1.9) for csv exports
|
103
105
|
* formtastic
|
104
|
-
* fastercsv for csv exports
|
105
106
|
* UUID
|
106
107
|
|
107
108
|
To work on the code fork this github project. Run:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.19.
|
1
|
+
0.19.7
|
@@ -1,7 +1,7 @@
|
|
1
1
|
-# TODO: js for slider
|
2
2
|
- rg ||= nil
|
3
3
|
- renderer = q.renderer(g ||= nil)
|
4
|
-
- f.inputs q_text(q), :id => rg ? "q_#{q.id}_#{rg
|
4
|
+
- f.inputs q_text(q), :id => rg ? "q_#{q.id}_#{rg}" : "q_#{q.id}", :class => "q_#{renderer} #{q.css_class(@response_set)}" do
|
5
5
|
%span.help= q.help_text
|
6
6
|
- case renderer
|
7
7
|
- when :image, :label
|
Binary file
|
Binary file
|
data/lib/surveyor/common.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
module Surveyor
|
2
2
|
class Common
|
3
|
-
RAND_CHARS = [('a'..'z'), ('A'..'Z'), (0..9)].map{|r| r.to_a}.flatten.
|
3
|
+
RAND_CHARS = [('a'..'z'), ('A'..'Z'), (0..9)].map{|r| r.to_a}.flatten.join
|
4
4
|
OPERATORS = %w(== != < > <= >= =~)
|
5
5
|
|
6
6
|
class << self
|
7
7
|
def make_tiny_code(len = 10)
|
8
8
|
if RUBY_VERSION < "1.8.7"
|
9
|
-
(1..len).to_a.map{|i| RAND_CHARS[rand(RAND_CHARS.size), 1] }.
|
9
|
+
(1..len).to_a.map{|i| RAND_CHARS[rand(RAND_CHARS.size), 1] }.join
|
10
10
|
else
|
11
|
-
len.times.map{|i| RAND_CHARS[rand(RAND_CHARS.size), 1] }.
|
11
|
+
len.times.map{|i| RAND_CHARS[rand(RAND_CHARS.size), 1] }.join
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'fastercsv'
|
2
|
+
require 'csv'
|
1
3
|
module Surveyor
|
2
4
|
module Models
|
3
5
|
module ResponseSetMethods
|
@@ -36,7 +38,9 @@ module Surveyor
|
|
36
38
|
result
|
37
39
|
end
|
38
40
|
def has_blank_value?(hash)
|
39
|
-
hash["answer_id"].blank?
|
41
|
+
return true if hash["answer_id"].blank?
|
42
|
+
return false if (q = Question.find_by_id(hash["question_id"])) and q.pick == "one"
|
43
|
+
hash.any?{|k,v| v.is_a?(Array) ? v.all?{|x| x.to_s.blank?} : v.to_s.blank?}
|
40
44
|
end
|
41
45
|
end
|
42
46
|
end
|
@@ -63,8 +67,8 @@ module Surveyor
|
|
63
67
|
qcols = Question.content_columns.map(&:name) - %w(created_at updated_at)
|
64
68
|
acols = Answer.content_columns.map(&:name) - %w(created_at updated_at)
|
65
69
|
rcols = Response.content_columns.map(&:name)
|
66
|
-
|
67
|
-
|
70
|
+
csvlib = CSV.const_defined?(:Reader) ? FasterCSV : CSV
|
71
|
+
result = csvlib.generate do |csv|
|
68
72
|
csv << (access_code ? ["response set access code"] : []) + qcols.map{|qcol| "question.#{qcol}"} + acols.map{|acol| "answer.#{acol}"} + rcols.map{|rcol| "response.#{rcol}"} if print_header
|
69
73
|
responses.each do |response|
|
70
74
|
csv << (access_code ? [self.access_code] : []) + qcols.map{|qcol| response.question.send(qcol)} + acols.map{|acol| response.answer.send(acol)} + rcols.map{|rcol| response.send(rcol)}
|
@@ -42,6 +42,7 @@ module Surveyor
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def title=(value)
|
45
|
+
return if value == self.title
|
45
46
|
adjusted_value = value
|
46
47
|
while Survey.find_by_access_code(Survey.to_normalized_string(adjusted_value))
|
47
48
|
i ||= 0
|
@@ -49,7 +50,7 @@ module Surveyor
|
|
49
50
|
adjusted_value = "#{value} #{i.to_s}"
|
50
51
|
end
|
51
52
|
self.access_code = Survey.to_normalized_string(adjusted_value)
|
52
|
-
super(adjusted_value)
|
53
|
+
super(adjusted_value)
|
53
54
|
# self.access_code = Survey.to_normalized_string(value)
|
54
55
|
# super
|
55
56
|
end
|
@@ -76,4 +77,4 @@ module Surveyor
|
|
76
77
|
end
|
77
78
|
end
|
78
79
|
end
|
79
|
-
end
|
80
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
%w(survey survey_section question_group question dependency dependency_condition answer validation validation_condition).each {|model| require model }
|
2
|
-
require 'fastercsv'
|
3
2
|
require 'active_support' # for humanize
|
3
|
+
require 'fastercsv'
|
4
|
+
require 'csv'
|
4
5
|
module Surveyor
|
5
6
|
class RedcapParser
|
6
7
|
# Attributes
|
@@ -19,8 +20,9 @@ module Surveyor
|
|
19
20
|
self.context = {}
|
20
21
|
end
|
21
22
|
def parse(str, filename)
|
23
|
+
csvlib = CSV.const_defined?(:Reader) ? FasterCSV : CSV
|
22
24
|
begin
|
23
|
-
|
25
|
+
csvlib.parse(str, :headers => :first_row, :return_headers => true, :header_converters => :symbol) do |r|
|
24
26
|
if r.header_row? # header row
|
25
27
|
return puts "Missing headers: #{missing_columns(r).inspect}\n\n" unless missing_columns(r).blank?
|
26
28
|
context[:survey] = Survey.new(:title => filename)
|
@@ -35,7 +37,7 @@ module Surveyor
|
|
35
37
|
end
|
36
38
|
print context[:survey].save ? "saved. " : " not saved! #{context[:survey].errors.each_full{|x| x }.join(", ")} "
|
37
39
|
# print context[:survey].sections.map(&:questions).flatten.map(&:answers).flatten.map{|x| x.errors.each_full{|y| y}.join}.join
|
38
|
-
rescue
|
40
|
+
rescue csvlib::MalformedCSVError
|
39
41
|
puts = "Oops. Not a valid CSV file."
|
40
42
|
# ensure
|
41
43
|
end
|
@@ -339,7 +339,28 @@ describe DependencyCondition do
|
|
339
339
|
@dep_c.is_met?([@response]).should be_true
|
340
340
|
end
|
341
341
|
end
|
342
|
-
|
342
|
+
|
343
|
+
describe "when evaluating a pick one/many with response_class e.g. string" do
|
344
|
+
it "should compare answer ids when the string_value is nil" do
|
345
|
+
a = Factory(:answer, :response_class => "string")
|
346
|
+
dc = Factory(:dependency_condition, :question_id => a.question.id, :answer_id => a.id, :operator => "==")
|
347
|
+
r = Factory(:response, :question_id => a.question.id, :answer_id => a.id, :string_value => "")
|
348
|
+
r.should_receive(:as).with("answer").and_return(a.id)
|
349
|
+
dc.is_met?([r]).should be_true
|
350
|
+
end
|
351
|
+
it "should compare strings when the string_value is not nil, even if it is blank" do
|
352
|
+
a = Factory(:answer, :response_class => "string")
|
353
|
+
dc = Factory(:dependency_condition, :question_id => a.question.id, :answer_id => a.id, :operator => "==", :string_value => "foo")
|
354
|
+
r = Factory(:response, :question_id => a.question.id, :answer_id => a.id, :string_value => "foo")
|
355
|
+
r.should_receive(:as).with("string").and_return("foo")
|
356
|
+
dc.is_met?([r]).should be_true
|
357
|
+
|
358
|
+
dc2 = Factory(:dependency_condition, :question_id => a.question.id, :answer_id => a.id, :operator => "==", :string_value => "")
|
359
|
+
r2 = Factory(:response, :question_id => a.question.id, :answer_id => a.id, :string_value => "")
|
360
|
+
r2.should_receive(:as).with("string").and_return("")
|
361
|
+
dc2.is_met?([r2]).should be_true
|
362
|
+
end
|
363
|
+
end
|
343
364
|
describe "when given responses whether the dependency is satisfied using 'count'" do
|
344
365
|
before(:each) do
|
345
366
|
@dep_c = DependencyCondition.new(:answer_id => nil,
|
@@ -90,7 +90,7 @@ describe ResponseSet do
|
|
90
90
|
"28" => {"question_id" => "16", "answer_id" => "", "string_value" => "foo"}, # new radio with string value, blank
|
91
91
|
"29" => {"question_id" => "17", "answer_id" => "261", "string_value" => "bar"}, # new radio with string value, selected
|
92
92
|
"30" => {"id" => "110", "question_id" => "18", "answer_id" => "271", "string_value" => "moo"}, # existing radio with string value, changed
|
93
|
-
"31" => {"id" => "111", "question_id" => "19", "answer_id" => "281", "string_value" => "mar"}
|
93
|
+
"31" => {"id" => "111", "question_id" => "19", "answer_id" => "281", "string_value" => "mar"} # existing radio with string value, unchanged
|
94
94
|
}
|
95
95
|
ResponseSet.reject_or_destroy_blanks(hash_of_hashes).should == {
|
96
96
|
# "11" => {"question_id" => "1", "answer_id" => [""]}, # new checkbox, blank
|
@@ -113,7 +113,16 @@ describe ResponseSet do
|
|
113
113
|
# "28" => {"question_id" => "16", "answer_id" => "", "string_value" => "foo"}, # new radio with string value, blank
|
114
114
|
"29" => {"question_id" => "17", "answer_id" => "261", "string_value" => "bar"}, # new radio with string value, selected
|
115
115
|
"30" => {"id" => "110", "question_id" => "18", "answer_id" => "271", "string_value" => "moo"}, # existing radio with string value, changed
|
116
|
-
"31" => {"id" => "111", "question_id" => "19", "answer_id" => "281", "string_value" => "mar"}
|
116
|
+
"31" => {"id" => "111", "question_id" => "19", "answer_id" => "281", "string_value" => "mar"} # existing radio with string value, unchanged
|
117
|
+
}
|
118
|
+
end
|
119
|
+
it "should clean up radio and string responses_attributes before passing to nested_attributes" do
|
120
|
+
@qone = Factory(:question, :pick => "one")
|
121
|
+
hash_of_hashes = {
|
122
|
+
"32" => {"question_id" => @qone.id, "answer_id" => "291", "string_value" => ""} # new radio with blank string value, selected
|
123
|
+
}
|
124
|
+
ResponseSet.reject_or_destroy_blanks(hash_of_hashes).should == {
|
125
|
+
"32" => {"question_id" => @qone.id, "answer_id" => "291", "string_value" => ""} # new radio with blank string value, selected
|
117
126
|
}
|
118
127
|
end
|
119
128
|
it "should remove responses" do
|
data/spec/models/survey_spec.rb
CHANGED
@@ -5,12 +5,12 @@ describe Survey, "when saving a new one" do
|
|
5
5
|
before(:each) do
|
6
6
|
@survey = Factory(:survey, :title => "Foo")
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
it "should be invalid without a title" do
|
10
10
|
@survey.title = nil
|
11
11
|
@survey.should have(1).error_on(:title)
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
it "should adjust the title to save unique titles" do
|
15
15
|
original = Survey.new(:title => "Foo")
|
16
16
|
original.save.should be_true
|
@@ -21,7 +21,14 @@ describe Survey, "when saving a new one" do
|
|
21
21
|
bandwagoneer.save.should be_true
|
22
22
|
bandwagoneer.title.should == "Foo 2"
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
|
+
it "should not adjust the title when updating itself" do
|
26
|
+
original = Factory(:survey, :title => "Foo")
|
27
|
+
original.save.should be_true
|
28
|
+
original.update_attributes(:title => "Foo")
|
29
|
+
original.title.should == "Foo"
|
30
|
+
end
|
31
|
+
|
25
32
|
it "should have an api_id" do
|
26
33
|
@survey.api_id.length.should == 36
|
27
34
|
end
|
@@ -44,7 +51,7 @@ describe Survey, "that has sections" do
|
|
44
51
|
@survey.sections.should have(3).sections
|
45
52
|
@survey.sections.should == [@s3, @s1, @s2]
|
46
53
|
end
|
47
|
-
|
54
|
+
|
48
55
|
it "should return survey_sections_with_questions in display order" do
|
49
56
|
@survey.sections_with_questions.map(&:questions).flatten.should have(4).questions
|
50
57
|
@survey.sections_with_questions.map(&:questions).flatten.should == [@q4,@q1,@q3,@q2]
|
@@ -72,19 +79,19 @@ describe Survey do
|
|
72
79
|
@survey.active?.should be_true
|
73
80
|
@survey.inactive_at.should be_nil
|
74
81
|
end
|
75
|
-
|
82
|
+
|
76
83
|
it "should be able to deactivate as of a certain date/time" do
|
77
84
|
@survey.active_at = 2.days.ago
|
78
85
|
@survey.inactive_at = 3.days.ago
|
79
86
|
@survey.active?.should be_false
|
80
87
|
@survey.active_at.should be_nil
|
81
88
|
end
|
82
|
-
|
89
|
+
|
83
90
|
it "should activate and deactivate" do
|
84
91
|
@survey.activate!
|
85
92
|
@survey.active?.should be_true
|
86
93
|
@survey.deactivate!
|
87
94
|
@survey.active?.should be_false
|
88
95
|
end
|
89
|
-
|
90
|
-
end
|
96
|
+
|
97
|
+
end
|
data/surveyor.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{surveyor}
|
8
|
-
s.version = "0.19.
|
8
|
+
s.version = "0.19.7"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Brian Chamberlain", "Mark Yoon"]
|
12
|
-
s.date = %q{2011-06-
|
12
|
+
s.date = %q{2011-06-23}
|
13
13
|
s.email = %q{yoon@northwestern.edu}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"README.md"
|
@@ -52,6 +52,8 @@ Gem::Specification.new do |s|
|
|
52
52
|
"app/views/surveyor/show.html.haml",
|
53
53
|
"ci-env.sh",
|
54
54
|
"config/routes.rb",
|
55
|
+
"doc/surveyor_models.png",
|
56
|
+
"doc/surveyor_models2.png",
|
55
57
|
"features/redcap_parser.feature",
|
56
58
|
"features/step_definitions/parser_steps.rb",
|
57
59
|
"features/step_definitions/surveyor_steps.rb",
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: surveyor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 93
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 19
|
9
|
-
-
|
10
|
-
version: 0.19.
|
9
|
+
- 7
|
10
|
+
version: 0.19.7
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Brian Chamberlain
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-06-
|
19
|
+
date: 2011-06-23 00:00:00 -05:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -149,6 +149,8 @@ files:
|
|
149
149
|
- app/views/surveyor/show.html.haml
|
150
150
|
- ci-env.sh
|
151
151
|
- config/routes.rb
|
152
|
+
- doc/surveyor_models.png
|
153
|
+
- doc/surveyor_models2.png
|
152
154
|
- features/redcap_parser.feature
|
153
155
|
- features/step_definitions/parser_steps.rb
|
154
156
|
- features/step_definitions/surveyor_steps.rb
|