ask 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.markdown +64 -0
- data/Rakefile +39 -0
- data/app/assets/images/add.png +0 -0
- data/app/assets/images/delete.png +0 -0
- data/app/assets/javascripts/ask.js +2 -0
- data/app/assets/javascripts/ask/forms.js +100 -0
- data/app/assets/stylesheets/ask.css +4 -0
- data/app/assets/stylesheets/ask/forms.css.sass +139 -0
- data/app/assets/stylesheets/ask/submissions.css.sass +60 -0
- data/app/helpers/ask_helper.rb +23 -0
- data/app/models/answer.rb +20 -0
- data/app/models/checklist_question.rb +11 -0
- data/app/models/choice.rb +7 -0
- data/app/models/choose_one_question.rb +7 -0
- data/app/models/essay_question.rb +3 -0
- data/app/models/form_section.rb +7 -0
- data/app/models/question.rb +43 -0
- data/app/models/text_question.rb +3 -0
- data/app/views/answerer/_answers.html.haml +9 -0
- data/app/views/answerer/_form.html.haml +39 -0
- data/app/views/asker/_form.html.haml +27 -0
- data/app/views/asker/_form_preview.html.haml +35 -0
- data/db/migrate/20110913214050_create_answers.rb +15 -0
- data/db/migrate/20110913214255_create_choices.rb +11 -0
- data/db/migrate/20110913214410_create_questions.rb +15 -0
- data/lib/ask.rb +6 -0
- data/lib/ask/acts_as_answerer.rb +84 -0
- data/lib/ask/acts_as_asker.rb +8 -0
- data/lib/ask/engine.rb +4 -0
- data/lib/ask/version.rb +3 -0
- data/lib/assets/javascripts/jquery.handle-nesting.js +113 -0
- data/test/ask_test.rb +7 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +9 -0
- data/test/dummy/app/assets/stylesheets/application.css +7 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +45 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +30 -0
- data/test/dummy/config/environments/production.rb +60 -0
- data/test/dummy/config/environments/test.rb +42 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +10 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +58 -0
- data/test/dummy/log/development.log +0 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +26 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/fixtures/answers.yml +13 -0
- data/test/fixtures/choices.yml +9 -0
- data/test/fixtures/questions.yml +17 -0
- data/test/fixtures/submissions.yml +9 -0
- data/test/functional/answers_controller_test.rb +49 -0
- data/test/functional/choices_controller_test.rb +49 -0
- data/test/functional/questions_controller_test.rb +49 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/test_helper.rb +10 -0
- data/test/unit/answer_test.rb +7 -0
- data/test/unit/choice_test.rb +7 -0
- data/test/unit/helpers/answers_helper_test.rb +4 -0
- data/test/unit/helpers/choices_helper_test.rb +4 -0
- data/test/unit/helpers/questions_helper_test.rb +4 -0
- data/test/unit/question_test.rb +7 -0
- metadata +231 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2011 Biola University
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
Ask
|
2
|
+
===
|
3
|
+
Ask is a Rails engine that provides tools to simplify the process of letting your app's users build forms for things like questionnaires or surveys.
|
4
|
+
|
5
|
+
Requirements
|
6
|
+
------------
|
7
|
+
- Rails 3.1 or higher
|
8
|
+
|
9
|
+
Installation
|
10
|
+
------------
|
11
|
+
Add to your Gemfile:
|
12
|
+
|
13
|
+
gem 'ask'
|
14
|
+
|
15
|
+
In your terminal run:
|
16
|
+
|
17
|
+
bundle
|
18
|
+
|
19
|
+
Usage
|
20
|
+
-----
|
21
|
+
Ask needs to be tied to two models in your application: an "asker" and an "answerer". The asker model should be the model that has questions, such as a Survey or Event. The answerer model should be the model that has answers to the questions such as a SurveySubmission or an EventRegistration.
|
22
|
+
|
23
|
+
In your asker model add:
|
24
|
+
|
25
|
+
acts_as_asker
|
26
|
+
|
27
|
+
In your answerer model add:
|
28
|
+
|
29
|
+
acts_as_answerer
|
30
|
+
|
31
|
+
In your asker form views, inside an already defined `form_for` helper add:
|
32
|
+
|
33
|
+
<%= render(:partial => 'asker/form', :locals => { :f => f }) %>
|
34
|
+
|
35
|
+
In your answerer form views, inside an already defined `form_for` helper add:
|
36
|
+
|
37
|
+
<%= render(:partial => 'answerer/form', :locals => { :f => f }) %>
|
38
|
+
|
39
|
+
In your javascript manifest file add:
|
40
|
+
|
41
|
+
//= require ask
|
42
|
+
|
43
|
+
In your stylesheet manifest file add:
|
44
|
+
|
45
|
+
/*
|
46
|
+
*= require ask
|
47
|
+
*/
|
48
|
+
|
49
|
+
In your answerer controller's `new` and `edit` methods you'll want to call `build_or_create_answers` and pass it in the appropriate questions. Such as:
|
50
|
+
|
51
|
+
@event_registration.build_or_create_answers @event_registration.event.questions
|
52
|
+
|
53
|
+
|
54
|
+
Finally you'll need to define an `asker` method on your answerer model, like so:
|
55
|
+
|
56
|
+
class EventRegistration < ActiveRecord::Base
|
57
|
+
def asker
|
58
|
+
return event
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
License
|
63
|
+
-------
|
64
|
+
MIT License
|
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'Ask'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
24
|
+
load 'rails/tasks/engine.rake'
|
25
|
+
|
26
|
+
|
27
|
+
Bundler::GemHelper.install_tasks
|
28
|
+
|
29
|
+
require 'rake/testtask'
|
30
|
+
|
31
|
+
Rake::TestTask.new(:test) do |t|
|
32
|
+
t.libs << 'lib'
|
33
|
+
t.libs << 'test'
|
34
|
+
t.pattern = 'test/**/*_test.rb'
|
35
|
+
t.verbose = false
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
task :default => :test
|
Binary file
|
Binary file
|
@@ -0,0 +1,100 @@
|
|
1
|
+
$(document).ready(function()
|
2
|
+
{
|
3
|
+
var handleChoiceNesting = function(container)
|
4
|
+
{
|
5
|
+
$(container).find('ul.choices').handleNesting({
|
6
|
+
nameMatch: /(.*\[)[0-9]+(\].*)/,
|
7
|
+
nameReplace: '$1{NEW_ID}$2',
|
8
|
+
afterAdd: function(added)
|
9
|
+
{
|
10
|
+
insertDeleteButtons(added.parent(), ".choice");
|
11
|
+
}
|
12
|
+
});
|
13
|
+
}
|
14
|
+
|
15
|
+
var updateChoiceVisibility = function(select)
|
16
|
+
{
|
17
|
+
if (select.val() == "ChooseOneQuestion" || select.val() == "ChecklistQuestion")
|
18
|
+
select.parents("dl").find("dd.choices:hidden").slideDown("fast");
|
19
|
+
else
|
20
|
+
select.parents("dl").find("dd.choices:visible").slideUp("fast");
|
21
|
+
}
|
22
|
+
|
23
|
+
var bindTypeChange = function(select)
|
24
|
+
{
|
25
|
+
select.change(function()
|
26
|
+
{
|
27
|
+
updateChoiceVisibility($(this));
|
28
|
+
});
|
29
|
+
}
|
30
|
+
|
31
|
+
var insertDeleteButtons = function(container, selector)
|
32
|
+
{
|
33
|
+
container.find(selector).each(function()
|
34
|
+
{
|
35
|
+
// Add a delete button if there isn't one already
|
36
|
+
if ($(this).children("button.remove").length == 0)
|
37
|
+
{
|
38
|
+
$("<button type=\"button\" class=\"remove\">Remove</button>").click(function()
|
39
|
+
{
|
40
|
+
$(this).parents(selector).fadeOut("fast", function()
|
41
|
+
{
|
42
|
+
$(this).remove();
|
43
|
+
// If there's only one option left, remove the delete button
|
44
|
+
if (container.find(selector).length == 1)
|
45
|
+
container.find("button.remove:last").remove();
|
46
|
+
});
|
47
|
+
|
48
|
+
return false;
|
49
|
+
}).appendTo($(this));
|
50
|
+
}
|
51
|
+
});
|
52
|
+
}
|
53
|
+
|
54
|
+
var makeSortable = function()
|
55
|
+
{
|
56
|
+
var questions = $("form ul.ask.questions");
|
57
|
+
questions.sortable(
|
58
|
+
{
|
59
|
+
stop: function(event, ui)
|
60
|
+
{
|
61
|
+
var order = 1;
|
62
|
+
questions.find(".position-wrapper").each(function()
|
63
|
+
{
|
64
|
+
$(this).find("input").val(order);
|
65
|
+
order ++;
|
66
|
+
});
|
67
|
+
}
|
68
|
+
});
|
69
|
+
}
|
70
|
+
|
71
|
+
var selects = $("dd.type > select");
|
72
|
+
|
73
|
+
bindTypeChange(selects);
|
74
|
+
|
75
|
+
selects.each(function()
|
76
|
+
{
|
77
|
+
updateChoiceVisibility($(this));
|
78
|
+
});
|
79
|
+
|
80
|
+
makeSortable();
|
81
|
+
|
82
|
+
if(jQuery.fn.handleNesting)
|
83
|
+
{
|
84
|
+
$('form ul.ask.questions').handleNesting({
|
85
|
+
afterAdd: function(added)
|
86
|
+
{
|
87
|
+
handleChoiceNesting(added);
|
88
|
+
insertDeleteButtons(added.parent(), ".question");
|
89
|
+
bindTypeChange(added.find("dd.type > select"));
|
90
|
+
makeSortable();
|
91
|
+
}
|
92
|
+
});
|
93
|
+
}
|
94
|
+
|
95
|
+
$('form ul.ask.questions').children('li').each(function(i,li)
|
96
|
+
{
|
97
|
+
handleChoiceNesting(li);
|
98
|
+
});
|
99
|
+
|
100
|
+
});
|
@@ -0,0 +1,139 @@
|
|
1
|
+
ul.ask.questions
|
2
|
+
margin: 0
|
3
|
+
list-style-type: none
|
4
|
+
|
5
|
+
button.remove:after
|
6
|
+
content: " this question"
|
7
|
+
|
8
|
+
>li
|
9
|
+
position: relative
|
10
|
+
margin: 10px 0
|
11
|
+
padding: 10px 10px 25px 10px
|
12
|
+
border: solid 1px #ccc
|
13
|
+
background-color: #eee
|
14
|
+
cursor: move
|
15
|
+
|
16
|
+
dt
|
17
|
+
display: none
|
18
|
+
|
19
|
+
dd.type select
|
20
|
+
position: absolute
|
21
|
+
top: 10px
|
22
|
+
right: 120px
|
23
|
+
width: 100px
|
24
|
+
|
25
|
+
dd.choices
|
26
|
+
display: none
|
27
|
+
|
28
|
+
a.delete
|
29
|
+
float: none
|
30
|
+
text-indent: 400px
|
31
|
+
width: 16px
|
32
|
+
margin: 0px
|
33
|
+
|
34
|
+
a.delete:after
|
35
|
+
content: ""
|
36
|
+
|
37
|
+
dd.required select
|
38
|
+
position: absolute
|
39
|
+
top: 10px
|
40
|
+
right: 10px
|
41
|
+
width: 100px
|
42
|
+
|
43
|
+
dd.instructions
|
44
|
+
margin-top: 10px
|
45
|
+
|
46
|
+
textarea
|
47
|
+
height: 3em
|
48
|
+
font-family: sans-serif
|
49
|
+
|
50
|
+
input[type=text]
|
51
|
+
width: 300px
|
52
|
+
|
53
|
+
input[type=checkbox]
|
54
|
+
display: none
|
55
|
+
|
56
|
+
button
|
57
|
+
float: right
|
58
|
+
clear: both
|
59
|
+
|
60
|
+
button.remove
|
61
|
+
padding: 0px
|
62
|
+
color: #000
|
63
|
+
font-family: sans-serif
|
64
|
+
font-size: 9pt
|
65
|
+
font-weight: normal
|
66
|
+
text-shadow: none
|
67
|
+
border: none
|
68
|
+
background: image-url("delete.png") no-repeat transparent
|
69
|
+
display: inline-block
|
70
|
+
vertical-align: 1px
|
71
|
+
text-indent: 20px
|
72
|
+
margin: 5px
|
73
|
+
float: right
|
74
|
+
height: 16px
|
75
|
+
text-decoration: none
|
76
|
+
-moz-box-shadow: none
|
77
|
+
-webkit-box-shadow: none
|
78
|
+
box-shadow: none
|
79
|
+
|
80
|
+
button.remove:after
|
81
|
+
content: " Question"
|
82
|
+
|
83
|
+
button.remove:active
|
84
|
+
top: 0px
|
85
|
+
|
86
|
+
button.add
|
87
|
+
float: none
|
88
|
+
height: 16px
|
89
|
+
padding: 0 20px 0 0
|
90
|
+
color: #000
|
91
|
+
font-family: sans-serif
|
92
|
+
font-size: 9pt
|
93
|
+
font-weight: normal
|
94
|
+
text-shadow: none
|
95
|
+
border: none
|
96
|
+
background: image-url("add.png") left center no-repeat transparent
|
97
|
+
-moz-box-shadow: none
|
98
|
+
-webkit-box-shadow: none
|
99
|
+
box-shadow: none
|
100
|
+
text-indent: 20px
|
101
|
+
|
102
|
+
button.add:after
|
103
|
+
content: " Choice"
|
104
|
+
|
105
|
+
ul.choices
|
106
|
+
|
107
|
+
li
|
108
|
+
margin: 10px 0
|
109
|
+
padding: 0
|
110
|
+
border: none
|
111
|
+
background: transparent
|
112
|
+
|
113
|
+
label
|
114
|
+
display: none
|
115
|
+
|
116
|
+
input[type=text]
|
117
|
+
width: 200px
|
118
|
+
|
119
|
+
input[type=checkbox]
|
120
|
+
display: none
|
121
|
+
|
122
|
+
button.remove
|
123
|
+
position: relative
|
124
|
+
float: none
|
125
|
+
margin: 0px
|
126
|
+
right: 0
|
127
|
+
bottom: 0
|
128
|
+
height: 16px
|
129
|
+
width: 16px
|
130
|
+
padding: 0
|
131
|
+
text-indent: -9999px
|
132
|
+
border: none
|
133
|
+
background: image-url("delete.png") no-repeat transparent
|
134
|
+
-moz-box-shadow: none
|
135
|
+
-webkit-box-shadow: none
|
136
|
+
box-shadow: none
|
137
|
+
|
138
|
+
button.remove:after
|
139
|
+
content: ""
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#page
|
2
|
+
|
3
|
+
&.submissions.show
|
4
|
+
dd
|
5
|
+
padding-left: 10px
|
6
|
+
|
7
|
+
&.application_forms, &.reference_forms, &.interview_forms
|
8
|
+
&.show
|
9
|
+
#wrapperContent
|
10
|
+
#content
|
11
|
+
background-image: url(../images/preview.png)
|
12
|
+
background-position: top right
|
13
|
+
background-repeat: no-repeat
|
14
|
+
|
15
|
+
#content
|
16
|
+
|
17
|
+
h3.section
|
18
|
+
margin-top: 40px
|
19
|
+
border-bottom: solid 1px #ccc
|
20
|
+
|
21
|
+
.instructions
|
22
|
+
display: block
|
23
|
+
font-style: italic
|
24
|
+
font-weight: normal
|
25
|
+
|
26
|
+
dt
|
27
|
+
|
28
|
+
.instructions
|
29
|
+
margin: 5px 0
|
30
|
+
color: #333
|
31
|
+
font-size: 10pt
|
32
|
+
|
33
|
+
|
34
|
+
input[type=text], textarea
|
35
|
+
width: 400px
|
36
|
+
|
37
|
+
textarea
|
38
|
+
height: 100px
|
39
|
+
|
40
|
+
h2
|
41
|
+
border-bottom: solid 1px #ccc
|
42
|
+
|
43
|
+
dt, dd
|
44
|
+
font-size: 11pt
|
45
|
+
|
46
|
+
dt
|
47
|
+
padding-top: 10px
|
48
|
+
letter-spacing: -.05em
|
49
|
+
|
50
|
+
#contentAside
|
51
|
+
a
|
52
|
+
&.csv, &.table
|
53
|
+
padding-left: 24px
|
54
|
+
font-size: 10pt
|
55
|
+
font-weight: bold
|
56
|
+
text-decoration: none
|
57
|
+
&.csv
|
58
|
+
background: url(../images/csv.png) 5px center no-repeat
|
59
|
+
&.table
|
60
|
+
background: url(../images/table.png) 5px center no-repeat
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module AskHelper
|
2
|
+
|
3
|
+
def question_label(question, builder=nil)
|
4
|
+
if question.type.to_sym == :ChecklistQuestion
|
5
|
+
h(question.name)
|
6
|
+
else
|
7
|
+
if builder
|
8
|
+
builder.label(:answer, question.name)
|
9
|
+
else
|
10
|
+
label_tag(:answer, question.name)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def question_instructions(question)
|
16
|
+
require 'rails_autolink/helpers'
|
17
|
+
|
18
|
+
unless question.instructions.blank?
|
19
|
+
content_tag(:span, auto_link(simple_format(question.instructions), :all, :target=>'_blank'), :class=>'instructions')
|
20
|
+
end || ''
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|