surveyor 0.11.0 → 0.12.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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Survey On Rails
1
+ # Surveys On Rails
2
2
 
3
3
  Surveyor is a rails (gem) plugin, that brings surveys to your rails app. Before Rails 2.3, it was implemented as a Rails Engine. Surveys are written in a DSL (Domain Specific Language), with examples available in the "kitchen sink" survey.
4
4
 
@@ -58,15 +58,23 @@ The survey above shows a couple simple question types. The first one is a "pick
58
58
  As a plugin:
59
59
 
60
60
  gem install haml
61
- script/plugin install git://github.com/breakpointer/surveyor.git -r 'tag v0.10.0'
61
+ gem install fastercsv
62
+ script/plugin install git://github.com/breakpointer/surveyor.git -r 'tag v0.12.0'
62
63
 
63
- Or as a gem plugin:
64
+ Or as a gem:
64
65
 
65
66
  # in environment.rb
66
- config.gem "surveyor", :version => '~> 0.10.0', :source => 'http://gemcutter.org'
67
+ config.gem "surveyor", :version => '~> 0.12.0', :source => 'http://gemcutter.org'
67
68
 
68
69
  rake gems:install
69
70
 
71
+ Or as a gem (with bundler):
72
+
73
+ # in environment.rb
74
+ gem "surveyor", '~> 0.12.0'
75
+
76
+ bundle install
77
+
70
78
  Generate assets, run migrations:
71
79
 
72
80
  script/generate surveyor
@@ -111,7 +119,7 @@ The initializer runs once, when the app starts. The block style is used to keep
111
119
  config['default.layout'] = nil # "surveyor_default"
112
120
  config['default.index'] = nil # "/surveys" # or :index_path_method
113
121
  config['default.finish'] = nil # "/surveys" # or :finish_path_method
114
- config['use_restful_authentication'] = false # set to true to use restful authentication
122
+ #config['authentication_method'] = :login_required # set to true to use restful authentication
115
123
  config['extend'] = %w() # %w(survey surveyor_helper surveyor_controller)
116
124
  end
117
125
 
@@ -165,7 +173,7 @@ The <code>surveyor\_includes</code> helper just calls <code>surveyor\_stylsheets
165
173
 
166
174
  # Dependencices
167
175
 
168
- Surveyor depends on Rails 2.3 and the SASS style sheet language, part of HAML (http://haml.hamptoncatlin.com/download). For running the test suite you will need rspec and have the rspec plugin installed in your application.
176
+ Surveyor depends on Ruby (1.8.7 - 1.9.1), Rails 2.3 and the SASS style sheet language, part of HAML (http://haml.hamptoncatlin.com/download). It also depends on fastercsv for csv exports. For running the test suite you will need rspec and have the rspec plugin installed in your application.
169
177
 
170
178
  # Test Suite and Development
171
179
 
@@ -174,6 +182,16 @@ To work on the plugin code (for enhancements, and bug fixes, etc...) fork this g
174
182
 
175
183
  # Changes
176
184
 
185
+ 0.12.0
186
+
187
+ * fix parser error in ruby 1.9, where instance_variables are symbols. closes #61
188
+ * added fastercsv as dependency. closes #59
189
+ * typo fix and test
190
+ * fixed broken spec for survey urls, made pending surveyor_controller specs pass
191
+ * Added explicit dependencycondition and validationcondition to DSL
192
+ * have authentication work with authlogic
193
+ * added "correct_answer" to parser, so you can specify one correct answer per question
194
+
177
195
  0.11.0
178
196
 
179
197
  * basic csv export. closes #21
data/Rakefile CHANGED
@@ -10,6 +10,7 @@ begin
10
10
  gem.homepage = "http://github.com/breakpointer/surveyor"
11
11
  gem.authors = ["Brian Chamberlain", "Mark Yoon"]
12
12
  gem.add_dependency 'haml'
13
+ gem.add_dependency 'fastercsv'
13
14
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
14
15
  end
15
16
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.11.0
1
+ 0.12.1
@@ -11,9 +11,8 @@ class SurveyorController < ApplicationController
11
11
  before_filter :extend_actions
12
12
 
13
13
  # RESTful authentication
14
- if Surveyor::Config['use_restful_authentication']
15
- include AuthenticatedSystem
16
- before_filter :login_required
14
+ if Surveyor::Config['authentication_method']
15
+ before_filter Surveyor::Config['authentication_method']
17
16
  end
18
17
 
19
18
  # Get the response set or current_user
@@ -40,11 +39,16 @@ class SurveyorController < ApplicationController
40
39
 
41
40
  def show
42
41
  @response_set = ResponseSet.find_by_access_code(params[:response_set_code], :include => {:responses => [:question, :answer]})
43
- respond_to do |format|
44
- format.html #{render :action => :show}
45
- format.csv {
46
- send_data(@response_set.to_csv, :type => 'text/csv; charset=utf-8; header=present',:filename => "#{@response_set.updated_at.strftime('%Y-%m-%d')}_#{@response_set.access_code}.csv")
47
- }
42
+ if @response_set
43
+ respond_to do |format|
44
+ format.html #{render :action => :show}
45
+ format.csv {
46
+ send_data(@response_set.to_csv, :type => 'text/csv; charset=utf-8; header=present',:filename => "#{@response_set.updated_at.strftime('%Y-%m-%d')}_#{@response_set.access_code}.csv")
47
+ }
48
+ end
49
+ else
50
+ flash[:notice] = "Unable to find your responses to the survey"
51
+ redirect_to(available_surveys_path)
48
52
  end
49
53
  end
50
54
 
@@ -46,20 +46,27 @@ module SurveyParser
46
46
 
47
47
  # Filter out attributes that shouldn't be in fixtures, including children, parser, placeholders
48
48
  def yml_attrs
49
- instance_variables.sort - self.class.children.map{|model| "@#{model.to_s}"} - %w(@id @parser @dependency @validation @question_reference @answer_reference)
49
+ instance_variables.sort.map(&:to_s) - self.class.children.map{|model| "@#{model.to_s}"} - %w(@id @parser @dependency @validation @question_reference @answer_reference)
50
50
  end
51
+
51
52
  def to_yml
52
53
  out = [ %(#{self.parser.salt}_#{self.class.name.demodulize.underscore}_#{@id}:) ]
53
54
  yml_attrs.each{|a| out << associate_and_format(a)}
54
55
  (out << nil ).join("\r\n")
55
56
  end
57
+
56
58
  def associate_and_format(a)
57
59
  if a =~ /_id$/ # a foreign key, e.g. survey_id
58
- " #{a[1..-4]}: " + (instance_variable_get(a).nil? ? "" : "#{self.parser.salt}_#{a[1..-4]}_#{instance_variable_get(a)}")
60
+ " #{property_name_map(a[1..-4])}: " + (instance_variable_get(a).nil? ? "" : "#{self.parser.salt}_#{a[1..-4]}_#{instance_variable_get(a)}")
59
61
  else # quote strings
60
- " #{a[1..-1]}: #{instance_variable_get(a).is_a?(String) ? "\"#{instance_variable_get(a)}\"" : instance_variable_get(a) }"
62
+ " #{property_name_map(a[1..-1])}: #{instance_variable_get(a).is_a?(String) ? "\"#{instance_variable_get(a)}\"" : instance_variable_get(a) }"
61
63
  end
62
64
  end
65
+
66
+ def property_name_map(property)
67
+ return property
68
+ end
69
+
63
70
  def to_file
64
71
  File.open(self.parser.send("#{self.class.name.demodulize.underscore.pluralize}_yml"), File::CREAT|File::APPEND|File::WRONLY) {|f| f << to_yml}
65
72
  self.class.children.each{|model| self.send(model).compact.map(&:to_file)}
@@ -92,11 +92,35 @@ module SurveyParser
92
92
  raise "Error: No current question" if self.current_question.nil?
93
93
  self.current_answer = Answer.new(self.current_question, args, opts.merge(:display_order => current_question.answers.size + 1))
94
94
  end
95
+
96
+ when "correct"
97
+ drop_the &block
98
+ raise "Error: No current question" if self.current_question.nil?
99
+ self.current_correct_answer = self.current_question.find_current_answers(args)
95
100
 
96
101
  when "validation", "v"
97
102
  drop_the &block
98
103
  self.current_validation = Validation.new(self.current_answer, args, opts)
99
104
 
105
+
106
+ # explicitly define a dependency condition
107
+ # (not really necessary as is default)
108
+ when "dependencycondition", "dcondition", "dc"
109
+ drop_the &block
110
+ raise "Error: No current dependency for this condition" if self.current_dependency.nil?
111
+ self.current_dependency.dependency_conditions << DependencyCondition.new(self.current_dependency, args, opts)
112
+
113
+ # explicitly define a validation condition
114
+ # (is necessary if want dependency AND validation on
115
+ # same question as dependency existance would try to
116
+ # make the condition a dependency condition.)
117
+ when "validationcondition", "vcondition", "vc"
118
+ drop_the &block
119
+ raise "Error: No current validation for this condition" if self.current_validation.nil?
120
+ self.current_validation.validation_conditions << ValidationCondition.new(self.current_validation, args, opts)
121
+
122
+
123
+
100
124
  else
101
125
  raise " ERROR: '#{missing_method}' not valid method"
102
126
 
@@ -135,31 +159,42 @@ module SurveyParser
135
159
  self.surveys << s
136
160
  @current_survey = s
137
161
  end
162
+
138
163
  def current_survey_section=(s)
139
164
  clear_current "survey_section"
140
165
  self.current_survey.survey_sections << s
141
166
  @current_survey_section = s
142
167
  end
168
+
143
169
  def current_question_group=(g)
144
170
  clear_current "question_group"
145
171
  self.current_survey_section.question_groups << g
146
172
  @current_question_group = g
147
- end
173
+ end
174
+
148
175
  def current_question=(q)
149
176
  clear_current "question"
150
177
  self.current_survey_section.questions << q
151
178
  @current_question = q
152
179
  end
180
+
153
181
  def current_dependency=(d)
154
182
  raise "Error: No question or question group" unless (dependent = self.current_question_group || self.current_question)
155
183
  dependent.dependency = d
156
184
  @current_dependency = d
157
185
  end
186
+
158
187
  def current_answer=(a)
159
188
  raise "Error: No current question" if self.current_question.nil?
160
189
  self.current_question.answers << a
161
190
  @current_answer = a
162
- end
191
+ end
192
+
193
+ def current_correct_answer=(a)
194
+ raise "Error: No current question" if self.current_question.nil?
195
+ self.current_question.correct_answer = a
196
+ end
197
+
163
198
  def current_validation=(v)
164
199
  clear_current "validation"
165
200
  self.current_answer.validation = v
@@ -185,4 +220,4 @@ module SurveyParser
185
220
  end
186
221
 
187
222
  end
188
- end
223
+ end
@@ -1,13 +1,15 @@
1
1
  module SurveyParser
2
2
  class Question < SurveyParser::Base
3
+ ANSWER_ID = /\s*\w+_/ unless defined?(ANSWER_ID)
4
+
3
5
  # Context, Content, Reference, Display, Children
4
- attr_accessor :id, :parser, :survey_section_id, :question_group_id
5
- attr_accessor :text, :short_text, :help_text, :pick
6
+ attr_accessor :id, :parser, :survey_section_id, :question_group_id, :correct_answer_id
7
+ attr_accessor :text, :short_text, :help_text, :pick, :answer_id
6
8
  attr_accessor :reference_identifier, :data_export_identifier, :common_namespace, :common_identifier
7
9
  attr_accessor :display_order, :display_type, :is_mandatory, :display_width, :custom_class, :custom_renderer
8
10
  attr_accessor :dependency
9
11
  has_children :answers
10
-
12
+
11
13
  def default_options
12
14
  { :pick => :none,
13
15
  :display_type => :default,
@@ -15,17 +17,38 @@ module SurveyParser
15
17
  :display_order => self.id
16
18
  }
17
19
  end
20
+
18
21
  def parse_opts(opts)
19
22
  (name = opts.delete(:method_name)) =~ /label|image/ ? opts.merge(:display_type => name) : opts
20
23
  end
24
+
21
25
  def parse_args(args)
22
26
  text = args[0] || "Question"
23
27
  {:text => text, :short_text => text, :data_export_identifier => Surveyor.to_normalized_string(text)}.merge(args[1] || {})
24
28
  end
29
+
30
+ def correct_answer=(a)
31
+ self.answer_id = a.id
32
+ end
25
33
 
26
34
  def find_answer_by_reference(ref_id)
27
35
  self.answers.detect{|a| a.reference_identifier == ref_id}
28
36
  end
37
+
38
+ # currently, only one correct answer is allowed
39
+ def find_current_answers(args)
40
+ ref_ids = args[0][:answer]
41
+ ids = ref_ids.to_s.split(ANSWER_ID).compact
42
+ self.answers.select{|a| ids.include?(a.reference_identifier)}.first
43
+ end
44
+
45
+ # so we can build the correct yaml structure
46
+ def property_name_map(property)
47
+ names = {
48
+ "answer" => "correct_answer"
49
+ }
50
+ return names.has_key?(property) ? names[property] : property
51
+ end
29
52
 
30
53
  def to_file
31
54
  super
@@ -26,31 +26,33 @@ describe SurveyorController do
26
26
  response.should be_success
27
27
  response.should render_template('new')
28
28
  end
29
+
29
30
  it "should find all surveys" do
30
31
  Survey.should_receive(:find).with(:all).and_return([@survey])
31
32
  do_get
32
33
  end
34
+
33
35
  it "should assign the found surveys for the view" do
34
36
  do_get
35
37
  assigns[:surveys].should == [@survey]
36
38
  end
37
39
  end
38
40
 
39
- describe "take survey: POST /surveys/XYZ" do
41
+ describe "take survey: POST /surveys/xyz" do
40
42
 
41
43
  before(:each) do
42
- @survey = Factory(:survey, :title => "XYZ", :access_code => "XYZ")
43
- @response_set = Factory(:response_set, :access_code => "PDQ")
44
+ @survey = Factory(:survey, :title => "xyz", :access_code => "xyz")
45
+ @response_set = Factory(:response_set, :access_code => "pdq")
44
46
  ResponseSet.stub!(:create).and_return(@response_set)
45
47
  Survey.stub!(:find_by_access_code).and_return(@survey)
46
48
  end
47
49
 
48
50
  describe "with success" do
49
51
  def do_post
50
- post :create, :survey_code => "XYZ"
52
+ post :create, :survey_code => "xyz"
51
53
  end
52
54
  it "should look for the survey" do
53
- Survey.should_receive(:find_by_access_code).with("XYZ").and_return(@survey)
55
+ Survey.should_receive(:find_by_access_code).with("xyz").and_return(@survey)
54
56
  do_post
55
57
  end
56
58
  it "should create a new response_set" do
@@ -59,7 +61,7 @@ describe SurveyorController do
59
61
  end
60
62
  it "should redirect to the new response_set" do
61
63
  do_post
62
- response.should redirect_to(edit_my_survey_url(:survey_code => "XYZ", :response_set_code => "PDQ"))
64
+ response.should redirect_to(edit_my_survey_url(:survey_code => "xyz", :response_set_code => "pdq"))
63
65
  end
64
66
  end
65
67
 
@@ -77,47 +79,42 @@ describe SurveyorController do
77
79
  end
78
80
  end
79
81
 
80
- describe "view my survey: GET /surveys/XYZ/PDQ" do
82
+ describe "view my survey: GET /surveys/xyz/pdq" do
81
83
 
82
84
  before(:each) do
83
- @survey = Factory(:survey, :title => "XYZ", :access_code => "XYZ", :sections => [Factory(:survey_section)])
84
- @response_set = Factory(:response_set, :access_code => "PDQ", :survey => @survey)
85
+ @survey = Factory(:survey, :title => "xyz", :access_code => "xyz", :sections => [Factory(:survey_section)])
86
+ @response_set = Factory(:response_set, :access_code => "pdq", :survey => @survey)
85
87
  end
86
88
 
87
89
  def do_get
88
- get :show, :survey_code => "XYZ", :response_set_code => "PDQ"
90
+ get :show, :survey_code => "xyz", :response_set_code => "pdq"
89
91
  end
90
92
 
91
93
  it "should be successful" do
92
94
  do_get
93
95
  response.should be_success
94
96
  end
97
+
95
98
  it "should render show template" do
96
99
  do_get
97
100
  response.should render_template('show')
98
101
  end
102
+
99
103
  it "should find the response_set requested" do
100
- pending
101
- ResponseSet.should_receive(:find_by_access_code).with("PDQ").and_return(@response_set)
104
+ ResponseSet.should_receive(:find_by_access_code).with("pdq",{:include=>{:responses=>[:question, :answer]}}).and_return(@response_set)
102
105
  do_get
103
106
  end
107
+
104
108
  it "should assign the found response_set and survey for the view" do
105
- pending
106
109
  do_get
107
- assigns[:response_set].should equal(@response_set)
108
- assigns[:survey].should equal(@survey)
110
+ assigns[:response_set].should == @response_set
109
111
  end
112
+
110
113
  it "should redirect if :response_code not found" do
111
- pending
112
- get :show, :survey_code => "XYZ", :response_set_code => "DIFFERENT"
114
+ get :show, :survey_code => "xyz", :response_set_code => "DIFFERENT"
113
115
  response.should redirect_to(available_surveys_url)
114
116
  end
115
- # I'm not sure this is enterly neccessary since we look up the survey from the response_code in the url -BC
116
- it "should redirect if :survey_code in url doesn't match response_set.survey.access_code" do
117
- pending
118
- get :show, :survey_code => "DIFFERENT", :response_set_code => "PDQ"
119
- response.should redirect_to(available_surveys_url)
120
- end
117
+
121
118
  end
122
119
 
123
120
  describe "edit my survey: GET /surveys/XYZ/PDQ/take" do
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{surveyor}
8
- s.version = "0.11.0"
8
+ s.version = "0.12.1"
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{2010-04-06}
12
+ s.date = %q{2010-08-19}
13
13
  s.email = %q{yoon@northwestern.edu}
14
14
  s.extra_rdoc_files = [
15
15
  "README.md"
@@ -180,7 +180,7 @@ Gem::Specification.new do |s|
180
180
  s.homepage = %q{http://github.com/breakpointer/surveyor}
181
181
  s.rdoc_options = ["--charset=UTF-8"]
182
182
  s.require_paths = ["lib"]
183
- s.rubygems_version = %q{1.3.6}
183
+ s.rubygems_version = %q{1.3.7}
184
184
  s.summary = %q{A rails (gem) plugin to enable surveys in your application}
185
185
  s.test_files = [
186
186
  "spec/controllers/surveyor_controller_spec.rb",
@@ -204,13 +204,16 @@ Gem::Specification.new do |s|
204
204
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
205
205
  s.specification_version = 3
206
206
 
207
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
207
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
208
208
  s.add_runtime_dependency(%q<haml>, [">= 0"])
209
+ s.add_runtime_dependency(%q<fastercsv>, [">= 0"])
209
210
  else
210
211
  s.add_dependency(%q<haml>, [">= 0"])
212
+ s.add_dependency(%q<fastercsv>, [">= 0"])
211
213
  end
212
214
  else
213
215
  s.add_dependency(%q<haml>, [">= 0"])
216
+ s.add_dependency(%q<fastercsv>, [">= 0"])
214
217
  end
215
218
  end
216
219
 
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: surveyor
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 45
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
- - 11
8
- - 0
9
- version: 0.11.0
8
+ - 12
9
+ - 1
10
+ version: 0.12.1
10
11
  platform: ruby
11
12
  authors:
12
13
  - Brian Chamberlain
@@ -15,21 +16,37 @@ autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
18
 
18
- date: 2010-04-06 00:00:00 -05:00
19
+ date: 2010-08-19 00:00:00 -05:00
19
20
  default_executable:
20
21
  dependencies:
21
22
  - !ruby/object:Gem::Dependency
22
23
  name: haml
23
24
  prerelease: false
24
25
  requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
25
27
  requirements:
26
28
  - - ">="
27
29
  - !ruby/object:Gem::Version
30
+ hash: 3
28
31
  segments:
29
32
  - 0
30
33
  version: "0"
31
34
  type: :runtime
32
35
  version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: fastercsv
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ type: :runtime
49
+ version_requirements: *id002
33
50
  description:
34
51
  email: yoon@northwestern.edu
35
52
  executables: []
@@ -210,23 +227,27 @@ rdoc_options:
210
227
  require_paths:
211
228
  - lib
212
229
  required_ruby_version: !ruby/object:Gem::Requirement
230
+ none: false
213
231
  requirements:
214
232
  - - ">="
215
233
  - !ruby/object:Gem::Version
234
+ hash: 3
216
235
  segments:
217
236
  - 0
218
237
  version: "0"
219
238
  required_rubygems_version: !ruby/object:Gem::Requirement
239
+ none: false
220
240
  requirements:
221
241
  - - ">="
222
242
  - !ruby/object:Gem::Version
243
+ hash: 3
223
244
  segments:
224
245
  - 0
225
246
  version: "0"
226
247
  requirements: []
227
248
 
228
249
  rubyforge_project:
229
- rubygems_version: 1.3.6
250
+ rubygems_version: 1.3.7
230
251
  signing_key:
231
252
  specification_version: 3
232
253
  summary: A rails (gem) plugin to enable surveys in your application