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 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.1)
100
+ * Ruby (1.8.7 - 1.9.2)
101
101
  * Rails 2.3
102
- * HAML/SASS
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.6
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.id}" : "q_#{q.id}", :class => "q_#{renderer} #{q.css_class(@response_set)}" do
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
@@ -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.to_s
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] }.to_s
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] }.to_s
11
+ len.times.map{|i| RAND_CHARS[rand(RAND_CHARS.size), 1] }.join
12
12
  end
13
13
  end
14
14
 
@@ -48,6 +48,7 @@ module Surveyor
48
48
  end
49
49
  end || responses.first
50
50
  klass = response.answer.response_class
51
+ klass = "answer" if self.as(klass).nil?
51
52
  return case self.operator
52
53
  when "==", "<", ">", "<=", ">="
53
54
  response.as(klass).send(self.operator, self.as(klass))
@@ -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? or hash.any?{|k,v| v.is_a?(Array) ? v.all?{|x| x.to_s.blank?} : v.to_s.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
- require 'fastercsv'
67
- FCSV(result = "") do |csv|
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
- FasterCSV.parse(str, :headers => :first_row, :return_headers => true, :header_converters => :symbol) do |r|
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 FasterCSV::MalformedCSVError
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"}, # existing radio with string value, unchanged
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"}, # existing radio with string value, unchanged
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
@@ -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.6"
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-08}
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: 95
4
+ hash: 93
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 19
9
- - 6
10
- version: 0.19.6
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-08 00:00:00 -05:00
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