nubic / surveyor Goto Github PK
View Code? Open in Web Editor NEWA Rails gem that lets you code surveys, questionnaires, quizzes, etc... and add them to your app.
Home Page: http://nubic.github.com/surveyor
License: MIT License
A Rails gem that lets you code surveys, questionnaires, quizzes, etc... and add them to your app.
Home Page: http://nubic.github.com/surveyor
License: MIT License
app/views/partials/_question_group.html.haml has logic that causes a repeater question to always be initialized to 3 rows? And to always append 3 rows? Is this configurable via the DSL?
The dependents method of app/controllers/surveying_controller.rb checks to see if a question has met its dependency condition and been answered. This check for the second condition causes a dependent question to disappear after you answer it:
if dep.met?(response_set) and response_set.has_not_answered_question?(dep.question)
I removed the check for the second condition in my application.
the method "mandatory_questions_answered" returns false if a label is included e.g
survey "portal 4 screen" do
section "screen" do
label "Before you take this survey we would like to know some things about you"
question_1 "Are you Ugly?",:pick=>:one
answer "no"
answer "yes"
end
end
welcome page, finishing page
The method of extending a model suggested by running
script/generate extend_surveyor
does not work within a Rails development environment because
config.cache_classes = false
Consequently, the Survey model gets reloaded each time you reference it but the initializer code does not. So methods start disappearing.
Maybe a different way would be to use inheritance instead of method injection. For example:
class ExtendedSurvey < Survey
end
don't re-include in rakefile
allow skipping of migrations
add jquery to uncheck/disable everything else
My html validator is complaining that ...
..... there is no attribute "autocomplete" .
<input autocomplete="off" .....
Checkbox and radio button events do not fire properly in IE. This causes a problem with dependency triggering.
answers aren't displayed in order
namespace surveyor routes
section.with_includes.questions not in order. thanks mike!
Hey. I'm getting this issue using surveyor in development mode with phusion. Can't say I properly understand what's going on but see these two:
http://dev.rubyonrails.org/ticket/6001
http://strd6.com/?p=250
I don't properly understand what the right fix is, but a simple one is to add 'unloadable' to the definition of SurveyorController. Apparently (according to the comments of the second link) that is deprecated, but I can't find any Rails documentation about this.
Line #29 says
if (@Survey = Survey.find_by_access_code(params[:survey_code])) && (@response_set = ResponseSet.create(:survey => @Survey, :user_id => @current_user))
Shouldn't is say:
if (@Survey = Survey.find_by_access_code(params[:survey_code])) && (@response_set = ResponseSet.create(:survey => @Survey, :user => @current_user))
(the results it was creating didn't properly have users attached).
Should surveys have a unique access_code?
As there is no model validation or unique index in the database, there is no guarantee that your survey access_code will be unique. It is just a normalized version of your survey title.
Running ...
rake surveyor FILE=surveys/kitchen_sink_survey.rb APPEND=true rake surveyor FILE=surveys/kitchen_sink_survey.rb APPEND=true script/console Survey.all.collect(&:access_code)
should show this to be true.
This will show both surveys as able to be taken, but will only allow the first one when the attempt is made as the survey is found by
@survey = Survey.find_by_access_code(params[:survey_code])
In addition, adding a unique index to the db and model will make a mess when running
rake surveyor FILE=surveys/kitchen_sink_survey.rb APPEND=true rake surveyor FILE=surveys/kitchen_sink_survey.rb APPEND=true
as the access_code is not unique and the survey fixtures are loaded last, leaving the associations with an invalid survey_id. To avoid this, the survey fixture should probably be attempted first.
Update...
Adding something like ...
def access_code=(value) counter = 2 original_value = value while( ( survey = Survey.find_by_access_code(value) ) && ( self.id != survey.id ) ) value = [original_value,"_",counter].join counter += 1 end super end
... to Survey seems to provide a "fix" for this "problem", although I don't know how kosher it is.
It works in my test environment, but does not actually work in the "rake surveyor" task as the survey is built from a different Survey model completely and then loaded into the database and not created though the application.
My final "fix" was to add
require 'lib/surveyor/survey_extensions'
to my Rakefile and create the file
# > cat lib/surveyor/survey_extensions.rb if surveyor_gem = Gem.searcher.find('surveyor') require surveyor_gem.full_gem_path + '/script/surveyor/parser' require surveyor_gem.full_gem_path + '/script/surveyor/survey' end module SurveyParser module SurveyExtensions def self.included(base) base.class_eval do def initialize_with_unique_access_code(obj, args, opts) initialize_without_unique_access_code(obj, args, opts) counter = 2 ac = self.access_code original_ac = self.access_code while( survey = ::Survey.find_by_access_code(ac) ) ac = [original_ac,"_",counter].join counter += 1 end self.access_code = ac end alias_method_chain :initialize, :unique_access_code end end end end SurveyParser::Survey.send(:include, SurveyParser::SurveyExtensions)
It is not as clean as I would've liked, but works.
Of course, now you have to different surveys that probably have the same name. But at least you can take them both!
Need a way to tell if a section is complete
for now, html, xml and csv seem to be reasonable formats for survey data export
Surveyor sporadically saves duplicate responses. Currently, the gem binds an ajaxSubmit to the change event of the #survey_form. If you have a text box as the last question in a section and enter a response and then click the 'Previous Section', 'Next Section' or 'Finish' buttons, two put requests are submitted to the SurveyorController's update action. One ajax request and one standard HTTP request. These submissions are right next to each other.
Currently the update action deletes and inserts the responses every time.
@response_set.clear_responses saved = @response_set.update_attributes(:response_attributes => (params[:responses] || {}).dup , :response_group_attributes => (params[:response_groups] || {}).dup) #copy (dup) to preserve params because we manipulate params in the response_set methods
But if the the first request has not been committed to the database by the time the second request is processed, then duplicate response occur because the first response set is not deleted.
Forcing a reload in the clear_responses method did not solve the problem:
def clear_responses question_ids = Question.find_all_by_survey_section_id(current_section_id).map(&:id) responses(true).select{|r| question_ids.include? r.question_id}.map(&:destroy) responses.reload end
The workaround that I came up with was to delay the submission of the request submitted by a button with some JavaScript.
var pause = true; $('.next_section input[type=submit], .previous_section input[type=submit]').click(function () { var button = $(this); if ( pause ) { $(this).delay(1000, function () { pause = false; button.click(); }); return false; } else { return true; } });
Simply changing the implementation to "update if exists" will probably not solve the problem because you would still need to check if the response exists. Most likely, some kind of client-side coordination between the submission of ajax and non-ajax requests will be necessary. Nevertheless, updating instead of deleting and inserting would be much better for auditing purposes.
I attached my ResponseSets to a Subject and added
belongs_to :subject, :counter_cache => true
to the base.class_eval section of the ResponseSetExtensions. Now when I add a new response set, the counter cache column in the subject is double incremented. I doubt that this is a Surveyor issue, but I fixed it by wrapping the association in a condition like
unless base.instance_methods.include?('subject')
belongs_to :subject, :counter_cache => true
end
This sounds more like a rails problem, but it shows its head here. Has anyone else seen this?
Hello,
When I try the kitchen sink example, then click "Next section" (bottom of page), I get this:
NoMethodError (undefined method `transation' for ActiveRecord::Base:Class): vendor/plugins/surveyor/app/controllers/surveyor_controller.rb:64:in `update' haml (2.2.20) lib/sass/plugin/rails.rb:20:in `process' /usr/lib/ruby/1.8/webrick/httpserver.rb:104:in `service' /usr/lib/ruby/1.8/webrick/httpserver.rb:65:in `run' /usr/lib/ruby/1.8/webrick/server.rb:173:in `start_thread' /usr/lib/ruby/1.8/webrick/server.rb:162:in `start' /usr/lib/ruby/1.8/webrick/server.rb:162:in `start_thread' /usr/lib/ruby/1.8/webrick/server.rb:95:in `start' /usr/lib/ruby/1.8/webrick/server.rb:92:in `each' /usr/lib/ruby/1.8/webrick/server.rb:92:in `start' /usr/lib/ruby/1.8/webrick/server.rb:23:in `start' /usr/lib/ruby/1.8/webrick/server.rb:82:in `start'
Fixing the typo "transation" to "transaction" on line 64 of app/controllers/surveyor_controller.rb seems to get it working again. Thought you may want to include this fix.
Thanks for the great gem.
As there is no model validation or unique index in the database, there is no guarantee that your response_set access_code will be unique. It is just the output from Surveyor.make_tiny_code which is just 10 randomly selected characters. The character set is upper and lower case letters plus digits, giving a set size of 62. I concede that 62 ^ 10 is a HUGE number, but each time a survey is taken, the possibility of those 10 randomly selected characters already existing goes up.
In the ridiculously unlikely chance that a duplicate access_code is created, when the create action redirects to the edit action, the response set will be the first one and not the one just created.
@response_set = ResponseSet.find_by_access_code(params[:response_set_code])
Update....
Adding ...
def access_code=(value) while ResponseSet.find_by_access_code(value) value = Surveyor.make_tiny_code end super end
... to ResponseSet seems to "fix" this "problem", although I don't know how kosher it is.
if defined current_user, use it, else ignore
authenticated system is not in scope in time
This is more of an FYI for those who may be interested and don't already know. When using foxy fixtures, the id is generated based on the fixture label. As the id is a finite, albeit large, number, it is not guaranteed to be unique. A collision, intended in this case, can be demonstrated by ...
rake surveyor FILE=surveys/kitchen_sink_survey.rb APPEND=true rake surveyor:load_fixtures APPEND=true
and should show something like
Loading ............../surveys/fixtures/answers.yml... Appending, skipping delete... rake aborted! Mysql::Error: Duplicate entry '943057946' for key 'PRIMARY': INSERT INTO `answers` (`question_id`, `is_exclusive`, `created_at`, `updated_at`, `hide_label`, `text`, `response_class`, `id`, `short_text`, `display_order`, `reference_identifier`, `data_export_identifier`) VALUES (304607657, 0, '2010-03-24 23:21:39', '2010-03-24 23:21:39', 0, '2', 'answer', 943057946, '2', 5, NULL, '2')
In the random chance that this collision occurs on 2 labels that are not identical in the middle of a fixture load, you will be left with a mess. The only foreseeable solution would be to regenerate the fixtures and try again.
In order to get the Surveyor plugin/gem and PostgreSql to work with my application I had to modify the following files:
app/views/question_display_types/_repeater_dropdown.html.haml
app/views/question_display_types/_repeater_default.html.haml
The call in both of these files to ResponseSet#response_for model needs to convert the argument for the response_group to a string like so:
response_set.response_for(question.id, a.id, response_group.to_s)
Using the :symbol option for config['default.finish'] is supposed to delegate the generation of the url path upon the finish of a survey to a method in the host application's ApplicationController. This feature is not working. It is always redirecting to /surveys
Currently all previous surveys are deleted when you load new ones.....Ideally, it should just load new surveys
In response_set.rb: lines 57 and 109, in the "response_attributes=" and "response_group_attributes=" functions, updating the responses requires calling delete on all of the Response objects in a particular section, but it would be good to delete only responses that have been cleared by the user of the survey instead of deleting everything - this probably would require the program to know the response values beforehand.
support notions of survey completion and correctness
<li>
<form action="/surveys/home_exposure_survey" method="post"><div style="margin:0;padding:0;display:inline"><input name="authenticity_token" type="hidden" value="0z2orvAjNy5gXt3DzDHQcbwwhiVBO958pfpTcdmkL5o=" /></div>
<input id="current_user_id" name="current_user_id" type="hidden" value="1" />
Home Exposure survey
<input name="commit" type="submit" value="Take it" />
</form>
</li>
</ul>
The id isn't needed so should probably be set to 'nil' in app/views/surveyor/new.html.haml
to avoid this.
= hidden_field_tag("current_user_id", @current_user.nil? ? nil : @current_user.id, :id => nil)
either templates, or a survey helper method
Surveyor's Validation model now determines whether or not an answer is_valid? per the criteria set out by the author of the survey. This functionality is not yet hooked into the views, and needs to be implemented in a style similar to Question and QuestionGroup Dependencies.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.