questionable_answers 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +97 -0
- data/Rakefile +35 -0
- data/app/assets/javascripts/questionable/answers.js +2 -0
- data/app/assets/javascripts/questionable/application.js +15 -0
- data/app/assets/stylesheets/answers.css +29 -0
- data/app/assets/stylesheets/questionable.css +13 -0
- data/app/controllers/questionable/answers_controller.rb +62 -0
- data/app/controllers/questionable/application_controller.rb +5 -0
- data/app/helpers/questionable/application_helper.rb +4 -0
- data/app/models/questionable/answer.rb +16 -0
- data/app/models/questionable/assignment.rb +30 -0
- data/app/models/questionable/option.rb +9 -0
- data/app/models/questionable/question.rb +35 -0
- data/app/views/admin/options/_form.html.haml +8 -0
- data/app/views/layouts/questionable/application.html.erb +14 -0
- data/app/views/questionable/assignments/_form.html.haml +58 -0
- data/config/initializers/questionable.rb +3 -0
- data/config/routes.rb +3 -0
- data/db/migrate/20130122192903_create_questionable_questions.rb +12 -0
- data/db/migrate/20130122193559_create_questionable_assignments.rb +14 -0
- data/db/migrate/20130122193820_create_questionable_options.rb +13 -0
- data/db/migrate/20130122194315_create_questionable_answers.rb +16 -0
- data/lib/questionable.rb +6 -0
- data/lib/questionable/admin/answers.rb +19 -0
- data/lib/questionable/admin/assignment.rb +24 -0
- data/lib/questionable/admin/option.rb +20 -0
- data/lib/questionable/admin/question.rb +46 -0
- data/lib/questionable/engine.rb +24 -0
- data/lib/questionable/version.rb +3 -0
- data/lib/questionable_surveys.rb +2 -0
- data/lib/tasks/questionable_tasks.rake +4 -0
- metadata +178 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a8719cf883d31e3a10d08eb4ad619d0a258251a8
|
4
|
+
data.tar.gz: bfbac2001a3f41b68b8a136b18f65c7d7009cf5d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b9e4baba910c246013353e6ba1ea2eede7c6f110385678133e642b5118bb90966441324e08118ce7d396aa691c6f34d0a56d507acf8b79825d3ba60cd71a824b
|
7
|
+
data.tar.gz: 0063e26da0dd51193816c9683cb06a6672065342bde95bcc24b3bade6c2c0eaa37de069e6475ff0897b0d9d68cc5c478ee3a3221800e363d64f9be227b8a6cb6
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2013 Bespoke Post
|
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.rdoc
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
= Questionable
|
2
|
+
|
3
|
+
Questionable is a Rails engine that make it easier to create and answer surveys through a web interface.
|
4
|
+
|
5
|
+
You can create your questions and options through the included
|
6
|
+
{ActiveAdmin}[https://github.com/gregbell/active_admin] interface.
|
7
|
+
If ActiveAdmin is installed in your application, Questionable will automatically add admin pages.
|
8
|
+
|
9
|
+
Then you can use the included partial template and controller for displaying
|
10
|
+
the questions and recording your users' answers.
|
11
|
+
|
12
|
+
== Installation
|
13
|
+
|
14
|
+
Add Questionable to your Gemfile:
|
15
|
+
|
16
|
+
gem 'questionable_surveys'
|
17
|
+
|
18
|
+
or for the latest:
|
19
|
+
|
20
|
+
gem 'questionable_surveys', :git => 'git://github.com/bespokepost/questionable.git'
|
21
|
+
|
22
|
+
Then run:
|
23
|
+
|
24
|
+
bundle install
|
25
|
+
rake questionable:install:migrations
|
26
|
+
rake db:migrate
|
27
|
+
|
28
|
+
Add Questionable to your config/routes.rb:
|
29
|
+
|
30
|
+
mount Questionable::Engine, :at => 'questions'
|
31
|
+
|
32
|
+
Optionally add the following to app/assets/stylesheet/application.css:
|
33
|
+
|
34
|
+
*= require questionable
|
35
|
+
|
36
|
+
== Usage
|
37
|
+
|
38
|
+
=== Create some questions
|
39
|
+
|
40
|
+
Create one or more Questions. Supported input_types include select, multiselect,
|
41
|
+
radio, checkboxes, date, and string.
|
42
|
+
|
43
|
+
# input_type may be select, multiselect, radio, checkboxes, or string.
|
44
|
+
q = Questionable::Question.create(title: 'What is your favorite color?', input_type: 'select', note: 'This is important')
|
45
|
+
|
46
|
+
Add Options, unless input_type is 'string'
|
47
|
+
|
48
|
+
q.options.create(title: 'Red', position: 1)
|
49
|
+
q.options.create(title: 'Green', position: 2)
|
50
|
+
q.options.create(title: 'Blue', position: 3)
|
51
|
+
|
52
|
+
Questions must be assigned a 'subject' before they are used.
|
53
|
+
They subject can be either an object, via a polymorphic association,
|
54
|
+
or something general like "preferences", which we can pass here as a symbol or string.
|
55
|
+
|
56
|
+
e.g.
|
57
|
+
|
58
|
+
@product = Product.find(123)
|
59
|
+
Questionable::Assignment.create(question_id: q.id, subject: @product)
|
60
|
+
|
61
|
+
or
|
62
|
+
|
63
|
+
Questionable::Assignment.create(question_id: q.id, subject_type: 'preferences')
|
64
|
+
|
65
|
+
=== In your controller
|
66
|
+
|
67
|
+
Here's we fetch question-assignments for a particular symbol:
|
68
|
+
|
69
|
+
@assignments = Questionable::Assignment.with_subject(:preferences)
|
70
|
+
|
71
|
+
and here, for a product object:
|
72
|
+
|
73
|
+
@product = Product.find(params[:id])
|
74
|
+
@assignments = Questionable::Assignment.with_subject(@product)
|
75
|
+
|
76
|
+
=== In your view
|
77
|
+
|
78
|
+
With HAML
|
79
|
+
|
80
|
+
= render partial: 'questionable/assignments/form', locals: { assignments: @assignments }
|
81
|
+
|
82
|
+
Or ERB
|
83
|
+
|
84
|
+
<%= render partial: 'questionable/assignments/form', locals: { assignments: @assignments } %>
|
85
|
+
|
86
|
+
=== Running Tests
|
87
|
+
|
88
|
+
rake spec
|
89
|
+
|
90
|
+
== Author
|
91
|
+
|
92
|
+
Written by {Nick Urban}[https://github.com/nickurban/] at {Bespoke Post}[https://www.bespokepost.com/].
|
93
|
+
|
94
|
+
== Licence
|
95
|
+
|
96
|
+
This project uses the MIT-LICENSE.
|
97
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
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 = 'Questionable'
|
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("../spec/dummy/Rakefile", __FILE__)
|
24
|
+
load 'rails/tasks/engine.rake'
|
25
|
+
|
26
|
+
Dir[File.join(File.dirname(__FILE__), 'tasks/**/*.rake')].each {|f| load f }
|
27
|
+
|
28
|
+
Bundler::GemHelper.install_tasks
|
29
|
+
|
30
|
+
require 'rspec/core'
|
31
|
+
require 'rspec/core/rake_task'
|
32
|
+
|
33
|
+
desc "Run all specs in spec directory (excluding plugin specs)"
|
34
|
+
RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
|
35
|
+
task :default => :spec
|
@@ -0,0 +1,15 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// the compiled file.
|
9
|
+
//
|
10
|
+
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
11
|
+
// GO AFTER THE REQUIRES BELOW.
|
12
|
+
//
|
13
|
+
//= require jquery
|
14
|
+
//= require jquery_ujs
|
15
|
+
//= require_tree .
|
@@ -0,0 +1,29 @@
|
|
1
|
+
/*
|
2
|
+
Place all the styles related to the matching controller here.
|
3
|
+
They will automatically be included in application.css.
|
4
|
+
*/
|
5
|
+
|
6
|
+
.questions-form .note { font-size: 0.8em; }
|
7
|
+
.questions-form .question-block { margin-bottom: 20px; }
|
8
|
+
|
9
|
+
.questions-form .select-month { width: 10em; }
|
10
|
+
.questions-form .select-day { width: 4em; }
|
11
|
+
.questions-form .select-year { width: 5em; }
|
12
|
+
|
13
|
+
.questions-form select {
|
14
|
+
width: 10em;
|
15
|
+
}
|
16
|
+
|
17
|
+
.questions-form .compact-input {
|
18
|
+
vertical-align: top;
|
19
|
+
}
|
20
|
+
|
21
|
+
.questions-form .question-and-note {
|
22
|
+
width: 320px;
|
23
|
+
}
|
24
|
+
|
25
|
+
.questions-form .question-and-note,
|
26
|
+
.questions-form .compact-input {
|
27
|
+
display: inline-block;
|
28
|
+
}
|
29
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require_self
|
12
|
+
*= require_tree .
|
13
|
+
*/
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require_dependency "questionable/application_controller"
|
2
|
+
|
3
|
+
module Questionable
|
4
|
+
class AnswersController < ApplicationController
|
5
|
+
def create
|
6
|
+
answers = params[:answers]
|
7
|
+
|
8
|
+
unless current_user and answers.is_a?(Hash)
|
9
|
+
flash[:warn] = 'Something went wrong, please try again'
|
10
|
+
return redirect_to_back
|
11
|
+
end
|
12
|
+
|
13
|
+
# Answers should always be a hash, and the values should be arrays,
|
14
|
+
# even if the question input_type only supports a single answer.
|
15
|
+
|
16
|
+
answers.each do |assignment_id, answers|
|
17
|
+
assignment = Assignment.find(assignment_id)
|
18
|
+
assignment.answers.where(user_id: current_user.id).delete_all
|
19
|
+
|
20
|
+
input_type = assignment.question.input_type
|
21
|
+
|
22
|
+
if input_type == 'string'
|
23
|
+
message = answers.first || ''
|
24
|
+
assignment.answers.create(user_id: current_user.id, message: message[0..255])
|
25
|
+
elsif input_type == 'date'
|
26
|
+
date = answers.first
|
27
|
+
if date[:year].present? or date[:month].present? or date[:day].present?
|
28
|
+
if date[:year].present? and date[:month].present? and date[:day].present?
|
29
|
+
answer = assignment.answers.build(user_id: current_user.id, message: "#{date[:year]}-#{date[:month]}-#{date[:day]}")
|
30
|
+
if answer.date_answer.nil?
|
31
|
+
flash[:warn] = 'Could not save date. Invalid date.'
|
32
|
+
else
|
33
|
+
answer.save
|
34
|
+
end
|
35
|
+
else
|
36
|
+
flash[:warn] = 'Could not save date. You did not select all three fields.'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
else
|
40
|
+
option_ids = answers
|
41
|
+
option_ids.each do |oid|
|
42
|
+
unless oid.blank?
|
43
|
+
assignment.answers.create(user_id: current_user.id, option_id: oid)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
redirect_to_back
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def redirect_to_back
|
55
|
+
if request.env["HTTP_REFERER"].present?
|
56
|
+
redirect_to :back
|
57
|
+
else
|
58
|
+
redirect_to root_url
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Questionable
|
2
|
+
class Answer < ActiveRecord::Base
|
3
|
+
belongs_to :user
|
4
|
+
belongs_to :assignment
|
5
|
+
belongs_to :option
|
6
|
+
has_one :question, through: :assignment
|
7
|
+
|
8
|
+
def date_answer
|
9
|
+
return nil if message.nil?
|
10
|
+
|
11
|
+
self.message.to_date
|
12
|
+
rescue ArgumentError
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Questionable
|
2
|
+
class Assignment < ActiveRecord::Base
|
3
|
+
belongs_to :question
|
4
|
+
belongs_to :subject, polymorphic: true
|
5
|
+
|
6
|
+
has_many :answers
|
7
|
+
has_many :answered_options, through: :answers, source: :option
|
8
|
+
|
9
|
+
def self.with_subject(subject)
|
10
|
+
if subject.kind_of?(Symbol) or subject.kind_of?(String)
|
11
|
+
assignments = Questionable::Assignment.where(subject_type: subject)
|
12
|
+
else
|
13
|
+
assignments = Questionable::Assignment.where(
|
14
|
+
subject_type: subject.class.to_s,
|
15
|
+
subject_id: subject.id)
|
16
|
+
end
|
17
|
+
|
18
|
+
assignments.order(:position)
|
19
|
+
end
|
20
|
+
|
21
|
+
def answers_for_user(user)
|
22
|
+
self.answers.where(user_id: user.id)
|
23
|
+
end
|
24
|
+
|
25
|
+
# for ActiveAdmin
|
26
|
+
def display_name
|
27
|
+
"#{self.subject_type}#{self.subject_id}: #{self.question.title}"
|
28
|
+
end
|
29
|
+
end # End Assignment
|
30
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Questionable
|
2
|
+
class Question < ActiveRecord::Base
|
3
|
+
has_many :options
|
4
|
+
has_many :assignments
|
5
|
+
has_many :subjects, through: :assignments
|
6
|
+
has_many :answers, through: :assignments
|
7
|
+
|
8
|
+
validates_presence_of :title
|
9
|
+
|
10
|
+
def accepts_multiple_answers?
|
11
|
+
['checkboxes', 'multiselect'].include?(self.input_type)
|
12
|
+
end
|
13
|
+
|
14
|
+
def answers_for_user(user)
|
15
|
+
answers = self.answers.where(user_id: user.id)
|
16
|
+
answers.any? ? answers : [self.answers.build(user_id: user.id)]
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.with_subject(subject)
|
20
|
+
if subject.kind_of?(Symbol) or subject.kind_of?(String)
|
21
|
+
assignments = { subject_type: subject }
|
22
|
+
else
|
23
|
+
assignments = { subject_type: subject.class.to_s, subject_id: subject.id }
|
24
|
+
end
|
25
|
+
|
26
|
+
join_query = 'INNER JOIN questionable_assignments '
|
27
|
+
join_query += 'ON questionable_assignments.quest)ion_id = questionable_questions.id'
|
28
|
+
|
29
|
+
query = Questionable::Question.joins(join_query)
|
30
|
+
query = query.where(questionable_assignments: assignements)
|
31
|
+
query = query.order('questionable_assignments.position')
|
32
|
+
query
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Questionable</title>
|
5
|
+
<%= stylesheet_link_tag "questionable/application", :media => "all" %>
|
6
|
+
<%= javascript_include_tag "questionable/application" %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
|
11
|
+
<%= yield %>
|
12
|
+
|
13
|
+
</body>
|
14
|
+
</html>
|
@@ -0,0 +1,58 @@
|
|
1
|
+
|
2
|
+
= form_tag questionable.answers_path, method: :post, class: 'questions-form' do
|
3
|
+
- assignments.each do |a|
|
4
|
+
.question-block{:id => "qa_#{a.id}", class: "question-#{a.question.id}"}
|
5
|
+
- q = a.question
|
6
|
+
|
7
|
+
.question-and-note
|
8
|
+
.question= q.title
|
9
|
+
.note= q.note if q.note
|
10
|
+
|
11
|
+
- selected_answers = a.answers_for_user(current_user)
|
12
|
+
- selected_option_ids = selected_answers.map(&:option_id)
|
13
|
+
- field = "answers[#{a.id}][]"
|
14
|
+
|
15
|
+
- if q.accepts_multiple_answers?
|
16
|
+
/ Some inputs can take multiple answers (namely multiselects and checkboxes)
|
17
|
+
- if q.input_type == 'checkboxes'
|
18
|
+
= hidden_field_tag field
|
19
|
+
- q.options.each do |opt|
|
20
|
+
%label.checkbox
|
21
|
+
= opt.title
|
22
|
+
= check_box_tag field, opt.id, selected_option_ids.include?(opt.id)
|
23
|
+
- elsif q.input_type == 'multiselect'
|
24
|
+
= select_tag field,
|
25
|
+
options_from_collection_for_select(q.options, 'id', 'title', selected_option_ids), multiple: true
|
26
|
+
|
27
|
+
- else
|
28
|
+
/ Most inputs just take a single answer
|
29
|
+
- if q.input_type == 'radio'
|
30
|
+
- q.options.each do |opt|
|
31
|
+
%label.radio
|
32
|
+
= opt.title
|
33
|
+
%input{type: :radio, name: field, value: opt.id, checked: selected_option_ids.first == opt.id}
|
34
|
+
=# radio_button_tag "answers[#{a.id}][]", opt.id, selected_option_ids.first
|
35
|
+
- else
|
36
|
+
.compact-input
|
37
|
+
- if q.input_type == 'select'
|
38
|
+
= select_tag "answers[#{a.id}][]",
|
39
|
+
options_from_collection_for_select(q.options, 'id', 'title', selected_option_ids.first), prompt: 'Choose an option'
|
40
|
+
- elsif q.input_type == 'string'
|
41
|
+
= text_field_tag field, selected_answers.first.try(:message)
|
42
|
+
- elsif q.input_type == 'date'
|
43
|
+
=# select_date nil, field, order: [:month, :day, :year]
|
44
|
+
=# date_select (Date.today - 20.years), field, order: [:month, :day, :year]
|
45
|
+
|
46
|
+
- date = selected_answers.first.try(:date_answer)
|
47
|
+
|
48
|
+
.date-fields
|
49
|
+
= select_month date, {prompt: date.blank?}, name: "#{field}[month]", class: 'select-month'
|
50
|
+
= select_day date, {prompt: date.blank?}, name: "#{field}[day]", class: 'select-day'
|
51
|
+
= select_year date,
|
52
|
+
{prompt: date.blank?, start_year: (Date.today-13.years).year, end_year: (Date.today-70.years).year},
|
53
|
+
name: "#{field}[year]", class: 'select-year'
|
54
|
+
|
55
|
+
.form-actions
|
56
|
+
- label = local_assigns.has_key?(:submit_label) ? submit_label : 'Save'
|
57
|
+
= submit_tag label, class: 'btn'
|
58
|
+
|
data/config/routes.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
class CreateQuestionableQuestions < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :questionable_questions do |t|
|
4
|
+
t.string :category
|
5
|
+
t.string :title
|
6
|
+
t.string :note
|
7
|
+
t.string :input_type # string, select, radio, checkboxes, multiselect, etc. statement (checkbox)
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateQuestionableAssignments < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :questionable_assignments do |t|
|
4
|
+
t.integer :question_id
|
5
|
+
t.integer :subject_id
|
6
|
+
t.string :subject_type
|
7
|
+
t.integer :position
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
|
12
|
+
add_index :questionable_assignments, [:subject_type, :subject_id, :position], :name => 'index_questionable_assignments_on_subject_and_position'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreateQuestionableOptions < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :questionable_options do |t|
|
4
|
+
t.integer :question_id
|
5
|
+
t.string :title
|
6
|
+
t.string :note
|
7
|
+
t.integer :position
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
add_index :questionable_options, [:question_id, :position]
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateQuestionableAnswers < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :questionable_answers do |t|
|
4
|
+
t.integer :user_id
|
5
|
+
t.integer :assignment_id
|
6
|
+
t.integer :option_id # which option was chosen as the answer
|
7
|
+
t.string :message # a freeform message e.g. "Other"
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
|
12
|
+
add_index :questionable_answers, :user_id
|
13
|
+
add_index :questionable_answers, :assignment_id
|
14
|
+
add_index :questionable_answers, :option_id
|
15
|
+
end
|
16
|
+
end
|
data/lib/questionable.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
if defined?(ActiveAdmin)
|
2
|
+
ActiveAdmin.register Questionable::Answer, :as => 'Answers' do
|
3
|
+
menu :label => 'Answers', :parent => 'Questionable'
|
4
|
+
|
5
|
+
filter :user_email, :as => :string
|
6
|
+
filter :assignment_sources
|
7
|
+
filter :created_at
|
8
|
+
filter :updated_at
|
9
|
+
|
10
|
+
index do
|
11
|
+
column(:id) { |a| link_to a.id, admin_answer_path(a) }
|
12
|
+
column(:user)
|
13
|
+
column(:assignment)
|
14
|
+
column(:option)
|
15
|
+
column(:message)
|
16
|
+
default_actions
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
if defined?(ActiveAdmin)
|
2
|
+
ActiveAdmin.register Questionable::Assignment, :as => 'Assignments', :sort_order => 'source_type, source_id, position' do
|
3
|
+
menu :label => 'Assignments', :parent => 'Questionable'
|
4
|
+
|
5
|
+
index do
|
6
|
+
column(:id) { |a| link_to a.id, admin_assignment_path(a.id) }
|
7
|
+
column(:subject) { |a| a.subject_id ? a.subject : a.subject_type }
|
8
|
+
column :position
|
9
|
+
column(:question) { |a| a.question.title }
|
10
|
+
column :created_at
|
11
|
+
column :updated_at
|
12
|
+
end
|
13
|
+
|
14
|
+
form do |f|
|
15
|
+
f.inputs do
|
16
|
+
f.input :question
|
17
|
+
f.input :subject_type
|
18
|
+
f.input :subject_id, :as => :number
|
19
|
+
f.input :position
|
20
|
+
end
|
21
|
+
f.actions
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
if defined?(ActiveAdmin)
|
2
|
+
# NOTE: This ":as" option determines the names of the routes generated
|
3
|
+
ActiveAdmin.register Questionable::Option, :as => 'Options' do
|
4
|
+
menu :label => 'Options', :parent => 'Questionable'
|
5
|
+
|
6
|
+
controller do
|
7
|
+
def create
|
8
|
+
create!(location: request.referrer)
|
9
|
+
end
|
10
|
+
|
11
|
+
def update
|
12
|
+
update!(location: admin_question_path(resource.question))
|
13
|
+
end
|
14
|
+
|
15
|
+
def destroy
|
16
|
+
destroy!(location: admin_question_path(resource.question))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
if defined?(ActiveAdmin)
|
2
|
+
# NOTE: This ":as" option determines the names of the routes generated
|
3
|
+
ActiveAdmin.register Questionable::Question, :as => 'Questions' do
|
4
|
+
menu :label => 'Questions', :parent => 'Questionable'
|
5
|
+
|
6
|
+
form do |f|
|
7
|
+
f.inputs do
|
8
|
+
f.input :title
|
9
|
+
f.input :note
|
10
|
+
f.input :category
|
11
|
+
f.input :input_type, :as => :select,
|
12
|
+
:collection => %w(select radio checkboxes multiselect date string statement), :include_blank => false
|
13
|
+
end
|
14
|
+
f.actions
|
15
|
+
end
|
16
|
+
|
17
|
+
show do |q|
|
18
|
+
attributes_table do
|
19
|
+
row :id
|
20
|
+
row :title
|
21
|
+
row :note
|
22
|
+
row :category
|
23
|
+
row :input_type
|
24
|
+
end
|
25
|
+
|
26
|
+
panel 'Options', class: 'options' do
|
27
|
+
table_for(q.options) do
|
28
|
+
column(:id) { |o| link_to o.id, admin_option_path(o) }
|
29
|
+
column :title
|
30
|
+
column :note
|
31
|
+
column :position
|
32
|
+
column(:actions) do |o|
|
33
|
+
link_to('Edit', edit_admin_option_path(o)) + ' | ' +
|
34
|
+
link_to('Delete', admin_option_path(o), :method => :delete)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
panel 'Add Option', class: 'add-option' do
|
41
|
+
render partial: 'admin/options/form', locals: { question: q }
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'stringex'
|
2
|
+
|
3
|
+
module Questionable
|
4
|
+
class Engine < ::Rails::Engine
|
5
|
+
isolate_namespace Questionable
|
6
|
+
|
7
|
+
initializer :questionable do
|
8
|
+
if defined?(ActiveAdmin)
|
9
|
+
dir = File.dirname(__FILE__) + '/admin'
|
10
|
+
# Prepend the load paths, which should allow this to be overridden by an app.
|
11
|
+
# If we wanted to prevent an override, we could append dir to load_paths instead.
|
12
|
+
ActiveAdmin.application.load_paths.unshift dir
|
13
|
+
#ActiveAdmin.application.load_paths += dir
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
config.generators do |g|
|
18
|
+
g.test_framework :rspec, :view_specs => false, :fixture => false
|
19
|
+
g.fixture_replacement :factory_girl, :dir => "spec/factories"
|
20
|
+
g.assets false
|
21
|
+
g.helper false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: questionable_answers
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nick Urban, Dorian Marié
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.2.11
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.2.11
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: haml
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: formtastic
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: stringex
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sqlite3
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec-rails
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: factory_girl_rails
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: Makes it easy to add and edit forms programatically, specifying select,
|
112
|
+
radio, checkbox, or string input, and recordings users' answers. Questions can be
|
113
|
+
associated with specific objects or with string labels. A form template and controller
|
114
|
+
are including for displaying questions and recording answers, and ActiveAdmin is
|
115
|
+
supported for editing the questions and options on the back-end.
|
116
|
+
email:
|
117
|
+
- nick@nickurban.com, dorian@bespokepost.com
|
118
|
+
executables: []
|
119
|
+
extensions: []
|
120
|
+
extra_rdoc_files: []
|
121
|
+
files:
|
122
|
+
- MIT-LICENSE
|
123
|
+
- README.rdoc
|
124
|
+
- Rakefile
|
125
|
+
- app/assets/javascripts/questionable/answers.js
|
126
|
+
- app/assets/javascripts/questionable/application.js
|
127
|
+
- app/assets/stylesheets/answers.css
|
128
|
+
- app/assets/stylesheets/questionable.css
|
129
|
+
- app/controllers/questionable/answers_controller.rb
|
130
|
+
- app/controllers/questionable/application_controller.rb
|
131
|
+
- app/helpers/questionable/application_helper.rb
|
132
|
+
- app/models/questionable/answer.rb
|
133
|
+
- app/models/questionable/assignment.rb
|
134
|
+
- app/models/questionable/option.rb
|
135
|
+
- app/models/questionable/question.rb
|
136
|
+
- app/views/admin/options/_form.html.haml
|
137
|
+
- app/views/layouts/questionable/application.html.erb
|
138
|
+
- app/views/questionable/assignments/_form.html.haml
|
139
|
+
- config/initializers/questionable.rb
|
140
|
+
- config/routes.rb
|
141
|
+
- db/migrate/20130122192903_create_questionable_questions.rb
|
142
|
+
- db/migrate/20130122193559_create_questionable_assignments.rb
|
143
|
+
- db/migrate/20130122193820_create_questionable_options.rb
|
144
|
+
- db/migrate/20130122194315_create_questionable_answers.rb
|
145
|
+
- lib/questionable.rb
|
146
|
+
- lib/questionable/admin/answers.rb
|
147
|
+
- lib/questionable/admin/assignment.rb
|
148
|
+
- lib/questionable/admin/option.rb
|
149
|
+
- lib/questionable/admin/question.rb
|
150
|
+
- lib/questionable/engine.rb
|
151
|
+
- lib/questionable/version.rb
|
152
|
+
- lib/questionable_surveys.rb
|
153
|
+
- lib/tasks/questionable_tasks.rake
|
154
|
+
homepage: https://github.com/bespokepost/questionable
|
155
|
+
licenses:
|
156
|
+
- MIT
|
157
|
+
metadata: {}
|
158
|
+
post_install_message:
|
159
|
+
rdoc_options: []
|
160
|
+
require_paths:
|
161
|
+
- lib
|
162
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - ">="
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
172
|
+
requirements: []
|
173
|
+
rubyforge_project:
|
174
|
+
rubygems_version: 2.2.2
|
175
|
+
signing_key:
|
176
|
+
specification_version: 4
|
177
|
+
summary: Rails engine that programatically generates surveys.
|
178
|
+
test_files: []
|