surveyor 0.19.1 → 0.19.2

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.2
2
+
3
+ * quiz example
4
+ * support correct answers for quizes through dsl. closes #105
5
+ * test dependency issues. closes #73
6
+ * fixing feature, section menu doens't appear until three sections exist
7
+ * fixing default values to only appear when response is blank
8
+ * fixing typo in specs. fixing cucumber on hudson due to residual objects in db from specs
9
+ * tweak to check hudson cucumber issue
10
+ * added dump rake task. thanks bnadav. closes #100
11
+
1
12
  0.19.1
2
13
 
3
14
  * require formtastic. closes #104
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.19.1
1
+ 0.19.2
@@ -14,6 +14,6 @@
14
14
  - when "none"
15
15
  - if %w(date datetime time float integer string text).include? a.response_class
16
16
  = ff.quiet_input :answer_id, :input_html => {:class => a.css_class, :value => a.id}
17
- = ff.input rc_to_attr(a.response_class), :as => rc_to_as(a.response_class), :label => a.split_or_hidden_text(:pre).blank? ? false : a.split_or_hidden_text(:pre), :hint => a.split_or_hidden_text(:post), :input_html => {:value => a.default_value}
17
+ = ff.input rc_to_attr(a.response_class), :as => rc_to_as(a.response_class), :label => a.split_or_hidden_text(:pre).blank? ? false : a.split_or_hidden_text(:pre), :hint => a.split_or_hidden_text(:post), :input_html => (r.as(a.response_class).blank? ? {:value => a.default_value} : {})
18
18
  - else
19
19
  = a.text
@@ -69,3 +69,9 @@ Then /^there should be (\d+) validation_condition(?:s?) with:$/ do |x, table|
69
69
  ValidationCondition.find(:first, :conditions => hash).should_not be_nil
70
70
  end
71
71
  end
72
+
73
+ Then /^question "([^"]*)" should have correct answer "([^"]*)"$/ do |qr, ar|
74
+ (q = Question.find_by_reference_identifier(qr)).should_not be_nil
75
+ q.correct_answer.should == q.answers.find_by_reference_identifier(ar)
76
+ end
77
+
@@ -7,5 +7,28 @@ end
7
7
  Then /^there should be (\d+) response set with (\d+) responses with:$/ do |rs_num, r_num, table|
8
8
  ResponseSet.count.should == rs_num.to_i
9
9
  Response.count.should == r_num.to_i
10
- # table is a Cucumber::Ast::Table
10
+ table.hashes.each do |hash|
11
+ if hash.keys == ["answer"]
12
+ a = Answer.find_by_text(hash["answer"])
13
+ a.should_not be_nil
14
+ Response.first(:conditions => {:answer_id => a.id}).should_not be_nil
15
+ else
16
+ if !(a = hash.delete("answer")).blank? and !(answer = Answer.find_by_text(a)).blank?
17
+ Response.first(:conditions => hash.merge({:answer_id => answer.id})).should_not be_nil
18
+ elsif
19
+ Response.first(:conditions => hash).should_not be_nil
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ Then /^there should be (\d+) dependencies$/ do |x|
26
+ Dependency.count.should == x.to_i
27
+ end
28
+
29
+ Then /^question "([^"]*)" should have a dependency with rule "([^"]*)"$/ do |qr, rule|
30
+ q = Question.find_by_reference_identifier(qr)
31
+ q.should_not be_blank
32
+ q.dependency.should_not be_nil
33
+ q.dependency.rule.should == rule
11
34
  end
@@ -25,13 +25,14 @@ Feature: Survey creation
25
25
  end
26
26
  """
27
27
  When I start the "Favorites" survey
28
+ Then I should see "You with the sad eyes don't be discouraged"
28
29
  And I choose "red"
29
30
  And I choose "blue"
30
31
  And I check "orange"
31
32
  And I check "brown"
32
33
  And I press "Click here to finish"
33
34
  Then there should be 1 response set with 3 responses with:
34
- | to_s |
35
+ | answer |
35
36
  | blue |
36
37
  | orange |
37
38
  | brown |
@@ -42,12 +43,40 @@ Feature: Survey creation
42
43
  survey "Favorites" do
43
44
  section "Foods" do
44
45
  question_1 "What is your favorite food?"
45
- answer :string, :default_value => "beef"
46
+ answer "food", :string, :default_value => "beef"
47
+ end
48
+ section "Section 2" do
49
+ end
50
+ section "Section 3" do
46
51
  end
47
52
  end
48
53
  """
49
54
  When I start the "Favorites" survey
55
+ And I press "Section 3"
50
56
  And I press "Click here to finish"
51
57
  Then there should be 1 response set with 1 responses with:
52
- | to_s |
53
- | clear |
58
+ | string_value |
59
+ | beef |
60
+
61
+ When I start the "Favorites" survey
62
+ And I fill in "food" with "chicken"
63
+ And I press "Foods"
64
+ And I press "Section 3"
65
+ And I press "Click here to finish"
66
+ Then there should be 2 response set with 2 responses with:
67
+ | string_value |
68
+ | chicken |
69
+
70
+ Scenario: Quiz time
71
+ Given the survey
72
+ """
73
+ survey "Favorites" do
74
+ section "Foods" do
75
+ question_1 "What is the best meat?", :pick => :one, :correct => "oink"
76
+ a_oink "bacon"
77
+ a_tweet "chicken"
78
+ a_moo "beef"
79
+ end
80
+ end
81
+ """
82
+ Then question "1" should have correct answer "oink"
@@ -155,3 +155,47 @@ Feature: Survey creation
155
155
  And there should be 2 validation_conditions with:
156
156
  | rule_key | integer_value |
157
157
  | A | 0 |
158
+
159
+ Scenario: Dependencies and validations
160
+ Given I parse
161
+ """
162
+ survey "dependency test" do
163
+ section "section 1" do
164
+
165
+ q_copd_sh_1 "Have you ever smoked cigarettes?",:pick=>:one,:help_text=>"NO means less than 20 packs of cigarettes or 12 oz. of tobacco in a lifetime or less than 1 cigarette a day for 1 year."
166
+ a_1 "Yes"
167
+ a_2 "No"
168
+
169
+ q_copd_sh_1a "How old were you when you first started smoking cigarettes?", :help_text=>"age in years"
170
+ a :integer
171
+ dependency :rule => "A"
172
+ condition_A :q_copd_sh_1, "==", :a_1
173
+
174
+ q_copd_sh_1b "Do you currently smoke cigarettes?",:pick=>:one, :help_text=>"as of 1 month ago"
175
+ a_1 "Yes"
176
+ a_2 "No"
177
+ dependency :rule => "B"
178
+ condition_B :q_copd_sh_1, "==", :a_1
179
+
180
+ q_copd_sh_1c "On the average of the entire time you smoked, how many cigarettes did you smoke per day?"
181
+ a :integer
182
+ dependency :rule => "C"
183
+ condition_C :q_copd_sh_1, "==", :a_1
184
+
185
+ q_copd_sh_1bb "How many cigarettes do you smoke per day now?"
186
+ a_2 "integer"
187
+ dependency :rule => "D"
188
+ condition_D :q_copd_sh_1b, "==", :a_1
189
+
190
+
191
+ q_copd_sh_1ba "How old were you when you stopped?"
192
+ a "Years", :integer
193
+ dependency :rule => "E"
194
+ condition_E :q_copd_sh_1b, "==", :a_2
195
+
196
+ end
197
+ end
198
+ """
199
+ Then there should be 5 dependencies
200
+ And question "copd_sh_1a" should have a dependency with rule "A"
201
+ And question "copd_sh_1ba" should have a dependency with rule "E"
@@ -54,8 +54,8 @@ class SurveyorGenerator < Rails::Generator::Base
54
54
  end
55
55
 
56
56
  # Surveys
57
- m.directory "surveys/fixtures"
58
57
  m.file "surveys/kitchen_sink_survey.rb", "surveys/kitchen_sink_survey.rb"
58
+ m.file "surveys/quiz.rb", "surveys/quiz.rb"
59
59
 
60
60
  m.readme "README"
61
61
 
@@ -0,0 +1,10 @@
1
+ survey "Favorites" do
2
+ section "Foods" do
3
+ # In a quiz, both the questions and the answers need to have reference identifiers
4
+ # Here, the question has reference_identifier: "1", and the answers: "oint", "tweet", and "moo"
5
+ question_1 "What is the best meat?", :pick => :one, :correct => "oink"
6
+ a_oink "bacon"
7
+ a_tweet "chicken"
8
+ a_moo "beef"
9
+ end
10
+ end
@@ -7,6 +7,7 @@ module Surveyor
7
7
  base.send :belongs_to, :question_group, :dependent => :destroy
8
8
  base.send :has_many, :answers, :order => "display_order ASC", :dependent => :destroy # it might not always have answers
9
9
  base.send :has_one, :dependency, :dependent => :destroy
10
+ base.send :has_one, :correct_answer, :class_name => "Answer", :dependent => :destroy
10
11
 
11
12
  # Scopes
12
13
  base.send :default_scope, :order => "display_order ASC"
@@ -58,15 +58,15 @@ module Surveyor
58
58
  super
59
59
  end
60
60
 
61
- def to_csv
61
+ def to_csv(access_code = false, print_header = true)
62
62
  qcols = Question.content_columns.map(&:name) - %w(created_at updated_at)
63
63
  acols = Answer.content_columns.map(&:name) - %w(created_at updated_at)
64
64
  rcols = Response.content_columns.map(&:name)
65
65
  require 'fastercsv'
66
66
  FCSV(result = "") do |csv|
67
- csv << qcols.map{|qcol| "question.#{qcol}"} + acols.map{|acol| "answer.#{acol}"} + rcols.map{|rcol| "response.#{rcol}"}
67
+ 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
68
68
  responses.each do |response|
69
- csv << qcols.map{|qcol| response.question.send(qcol)} + acols.map{|acol| response.answer.send(acol)} + rcols.map{|rcol| response.send(rcol)}
69
+ 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)}
70
70
  end
71
71
  end
72
72
  result
@@ -130,4 +130,4 @@ module Surveyor
130
130
  end
131
131
  end
132
132
  end
133
- end
133
+ end
@@ -73,7 +73,7 @@ class Survey < ActiveRecord::Base
73
73
 
74
74
  def self.parse_and_build(context, args, original_method, reference_identifier)
75
75
  # clear context
76
- context.delete_if{|k,v| true}
76
+ context.delete_if{|k,v| true }
77
77
  context[:question_references] = {}
78
78
  context[:answer_references] = {}
79
79
 
@@ -83,7 +83,7 @@ class Survey < ActiveRecord::Base
83
83
  :reference_identifier => reference_identifier}.merge(args[1] || {}))
84
84
  end
85
85
  def clear(context)
86
- context.delete_if{|k,v| true}
86
+ context.delete_if{|k,v| true }
87
87
  context[:question_references] = {}
88
88
  context[:answer_references] = {}
89
89
  end
@@ -93,14 +93,14 @@ class SurveySection < ActiveRecord::Base
93
93
 
94
94
  def self.parse_and_build(context, args, original_method, reference_identifier)
95
95
  # clear context
96
- context.delete_if{|k,v| k != :survey && k != :question_references && k != :answer_references}
96
+ context.delete_if{|k,v| !%w(survey question_references answer_references).map(&:to_sym).include?(k)}
97
97
 
98
98
  # build and set context
99
99
  title = args[0]
100
100
  context[:survey_section] = context[:survey].sections.build({ :title => title }.merge(args[1] || {}))
101
101
  end
102
102
  def clear(context)
103
- context.delete_if{|k,v| k != :survey && k != :question_references && k != :answer_references}
103
+ context.delete_if{|k,v| !%w(survey question_references answer_references).map(&:to_sym).include?(k)}
104
104
  end
105
105
  end
106
106
  class QuestionGroup < ActiveRecord::Base
@@ -108,7 +108,7 @@ class QuestionGroup < ActiveRecord::Base
108
108
 
109
109
  def self.parse_and_build(context, args, original_method, reference_identifier)
110
110
  # clear context
111
- context.delete_if{|k,v| k != :survey && k != :survey_section && k != :question_references && k != :answer_references}
111
+ context.delete_if{|k,v| !%w(survey survey_section question_references answer_references).map(&:to_sym).include?(k)}
112
112
 
113
113
  # build and set context
114
114
  context[:question_group] = context[:question_group] = new({ :text => args[0] || "Question Group",
@@ -116,12 +116,16 @@ class QuestionGroup < ActiveRecord::Base
116
116
 
117
117
  end
118
118
  def clear(context)
119
- context.delete_if{|k,v| k != :survey && k != :survey_section && k != :question_references && k != :answer_references}
119
+ context.delete_if{|k,v| !%w(survey survey_section question_references answer_references).map(&:to_sym).include?(k)}
120
120
  end
121
121
  end
122
122
  class Question < ActiveRecord::Base
123
123
  # nonblock
124
124
 
125
+ # attributes
126
+ attr_accessor :correct, :context_reference
127
+ before_save :resolve_correct_answers
128
+
125
129
  def self.parse_and_build(context, args, original_method, reference_identifier)
126
130
  # clear context
127
131
  context.delete_if{|k,v| %w(question dependency dependency_condition answer validation validation_condition).map(&:to_sym).include? k}
@@ -129,6 +133,7 @@ class Question < ActiveRecord::Base
129
133
  # build and set context
130
134
  text = args[0] || "Question"
131
135
  context[:question] = context[:survey_section].questions.build({
136
+ :context_reference => context,
132
137
  :question_group => context[:question_group],
133
138
  :reference_identifier => reference_identifier,
134
139
  :text => text,
@@ -146,6 +151,14 @@ class Question < ActiveRecord::Base
146
151
  end
147
152
  end
148
153
  end
154
+
155
+ def resolve_correct_answers
156
+ unless correct.blank? or reference_identifier.blank? or context_reference.blank?
157
+ # Looking up references for quiz answers
158
+ context_reference[:answer_references][reference_identifier] ||= {}
159
+ print (self.correct_answer = context_reference[:answer_references][reference_identifier][correct]) ? "found correct answer:#{correct} " : "lost! correct answer:#{correct} "
160
+ end
161
+ end
149
162
  end
150
163
  class Dependency < ActiveRecord::Base
151
164
  # nonblock
@@ -60,4 +60,17 @@ namespace :surveyor do
60
60
  puts "There are no surveys without response sets"
61
61
  end
62
62
  end
63
- end
63
+ desc "dump all responses to a given survey"
64
+ task :dump => :environment do
65
+ require 'fileutils.rb'
66
+ raise "USAGE: rake surveyor:dump SURVEY_ACCESS_CODE=<access_code> [OUTPUT_DIR=<dir>]" unless ENV["SURVEY_ACCESS_CODE"]
67
+ survey = Survey.find_by_access_code(ENV["SURVEY_ACCESS_CODE"])
68
+ raise "No Survey found with code " + ENV["SURVEY_ACCESS_CODE"] unless survey
69
+ dir = ENV["OUTPUT_DIR"] || Rails.root
70
+ mkpath(dir) # Create all non-existent directories
71
+ full_path = File.join(dir,"#{survey.access_code}_#{Time.now.to_i}.csv")
72
+ File.open(full_path, 'w') do |f|
73
+ survey.response_sets.each_with_index{|r,i| f.write(r.to_csv(true, i == 0)) } # print access code every time, print_header first time
74
+ end
75
+ end
76
+ end
@@ -79,11 +79,13 @@ describe Dependency, "when evaluating dependency conditions of a question in a r
79
79
  end
80
80
  end
81
81
  describe Dependency, "with conditions" do
82
- @dependency = Dependency.new(:rule => "A and B and C", :question_id => 1)
83
- Factory(:dependency_condition, :dependency => @dependency, :rule_key => "A")
84
- Factory(:dependency_condition, :dependency => @dependency, :rule_key => "B")
85
- Factory(:dependency_condition, :dependency => @dependency, :rule_key => "C")
86
- dc_ids = @dependency.dependency_conditions.map(&:id)
87
- @dependency.destroy
88
- dc_ids.each{|id| DependencyCondition.find_by_id(id).should == nil}
82
+ it "should destroy conditions when destroyed" do
83
+ @dependency = Dependency.new(:rule => "A and B and C", :question_id => 1)
84
+ Factory(:dependency_condition, :dependency => @dependency, :rule_key => "A")
85
+ Factory(:dependency_condition, :dependency => @dependency, :rule_key => "B")
86
+ Factory(:dependency_condition, :dependency => @dependency, :rule_key => "C")
87
+ dc_ids = @dependency.dependency_conditions.map(&:id)
88
+ @dependency.destroy
89
+ dc_ids.each{|id| DependencyCondition.find_by_id(id).should == nil}
90
+ end
89
91
  end
@@ -50,20 +50,15 @@ describe Validation, "reporting its status" do
50
50
  it "should validate a response by regexp" do
51
51
  test_var({}, [{:operator => "=~", :regexp => /^[a-z]{1,6}$/}], {:response_class => "string"}, {:string_value => ""}).should be_false
52
52
  end
53
- it "should validate a response by (in)equality" do
54
- # test_var({:operator => "!=", :datetime_value => Date.today + 1}, {:response_class => "date"}, {:datetime_value => Date.today}).should be_true
55
- # test_var({:operator => "==", :answer_id => 2}, {:response_class => "answer"}, {:answer_id => 2}).should be_false
56
- end
57
- it "should validate a response by lookup" do
58
-
59
- end
60
53
  end
61
54
  describe Validation, "with conditions" do
62
- @validation = Factory(:validation)
63
- Factory(:validation_condition, :validation => @validation, :rule_key => "A")
64
- Factory(:validation_condition, :validation => @validation, :rule_key => "B")
65
- Factory(:validation_condition, :validation => @validation, :rule_key => "C")
66
- v_ids = @validation.validation_conditions.map(&:id)
67
- @validation.destroy
68
- v_ids.each{|id| DependencyCondition.find_by_id(id).should == nil}
55
+ it "should destroy conditions when destroyed" do
56
+ @validation = Factory(:validation)
57
+ Factory(:validation_condition, :validation => @validation, :rule_key => "A")
58
+ Factory(:validation_condition, :validation => @validation, :rule_key => "B")
59
+ Factory(:validation_condition, :validation => @validation, :rule_key => "C")
60
+ v_ids = @validation.validation_conditions.map(&:id)
61
+ @validation.destroy
62
+ v_ids.each{|id| DependencyCondition.find_by_id(id).should == nil}
63
+ end
69
64
  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.1"
8
+ s.version = "0.19.2"
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-02-02}
12
+ s.date = %q{2011-02-09}
13
13
  s.email = %q{yoon@northwestern.edu}
14
14
  s.extra_rdoc_files = [
15
15
  "README.md"
@@ -98,6 +98,7 @@ Gem::Specification.new do |s|
98
98
  "generators/surveyor/templates/migrate/create_validation_conditions.rb",
99
99
  "generators/surveyor/templates/migrate/create_validations.rb",
100
100
  "generators/surveyor/templates/surveys/kitchen_sink_survey.rb",
101
+ "generators/surveyor/templates/surveys/quiz.rb",
101
102
  "generators/surveyor/templates/tasks/surveyor.rb",
102
103
  "hudson.rakefile",
103
104
  "init_testbed.rakefile",
@@ -149,7 +150,7 @@ Gem::Specification.new do |s|
149
150
  s.homepage = %q{http://github.com/breakpointer/surveyor}
150
151
  s.rdoc_options = ["--charset=UTF-8"]
151
152
  s.require_paths = ["lib"]
152
- s.rubygems_version = %q{1.4.2}
153
+ s.rubygems_version = %q{1.3.7}
153
154
  s.summary = %q{A rails (gem) plugin to enable surveys in your application}
154
155
  s.test_files = [
155
156
  "spec/controllers/surveyor_controller_spec.rb",
@@ -174,6 +175,7 @@ Gem::Specification.new do |s|
174
175
  ]
175
176
 
176
177
  if s.respond_to? :specification_version then
178
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
177
179
  s.specification_version = 3
178
180
 
179
181
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
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: 81
5
- prerelease:
4
+ hash: 87
5
+ prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 19
9
- - 1
10
- version: 0.19.1
9
+ - 2
10
+ version: 0.19.2
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-02-02 00:00:00 -06:00
19
+ date: 2011-02-09 00:00:00 -06:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -167,6 +167,7 @@ files:
167
167
  - generators/surveyor/templates/migrate/create_validation_conditions.rb
168
168
  - generators/surveyor/templates/migrate/create_validations.rb
169
169
  - generators/surveyor/templates/surveys/kitchen_sink_survey.rb
170
+ - generators/surveyor/templates/surveys/quiz.rb
170
171
  - generators/surveyor/templates/tasks/surveyor.rb
171
172
  - hudson.rakefile
172
173
  - init_testbed.rakefile
@@ -244,7 +245,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
244
245
  requirements: []
245
246
 
246
247
  rubyforge_project:
247
- rubygems_version: 1.4.2
248
+ rubygems_version: 1.3.7
248
249
  signing_key:
249
250
  specification_version: 3
250
251
  summary: A rails (gem) plugin to enable surveys in your application