effective_questions 0.0.2
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +133 -0
- data/Rakefile +18 -0
- data/app/assets/config/effective_questions_manifest.js +1 -0
- data/app/assets/stylesheets/effective_questions.scss +0 -0
- data/app/controllers/admin/questions_controller.rb +13 -0
- data/app/datatables/admin/effective_questionable_results_datatable.rb +44 -0
- data/app/datatables/admin/effective_questions_datatable.rb +45 -0
- data/app/helpers/effective_questions_helper.rb +2 -0
- data/app/models/concerns/acts_as_questionable.rb +30 -0
- data/app/models/concerns/acts_as_responsable.rb +30 -0
- data/app/models/effective/question.rb +124 -0
- data/app/models/effective/question_option.rb +26 -0
- data/app/models/effective/response.rb +87 -0
- data/app/models/effective/response_option.rb +6 -0
- data/app/views/admin/questions/_form.html.haml +133 -0
- data/app/views/effective/questionable/_result.html.haml +2 -0
- data/app/views/effective/questionable/_results.html.haml +31 -0
- data/app/views/effective/questionable/results/_choose_one.html.haml +2 -0
- data/app/views/effective/questionable/results/_date.html.haml +14 -0
- data/app/views/effective/questionable/results/_email.html.haml +14 -0
- data/app/views/effective/questionable/results/_long_answer.html.haml +2 -0
- data/app/views/effective/questionable/results/_number.html.haml +14 -0
- data/app/views/effective/questionable/results/_question_option.html.haml +17 -0
- data/app/views/effective/questionable/results/_select_all_that_apply.html.haml +2 -0
- data/app/views/effective/questionable/results/_select_up_to_1.html.haml +2 -0
- data/app/views/effective/questionable/results/_select_up_to_2.html.haml +2 -0
- data/app/views/effective/questionable/results/_select_up_to_3.html.haml +2 -0
- data/app/views/effective/questionable/results/_select_up_to_4.html.haml +2 -0
- data/app/views/effective/questionable/results/_select_up_to_5.html.haml +2 -0
- data/app/views/effective/questionable/results/_short_answer.html.haml +2 -0
- data/app/views/effective/questionable/results/_upload_file.html.haml +3 -0
- data/app/views/effective/questions/_question.html.haml +6 -0
- data/app/views/effective/responsable/_fields.html.haml +19 -0
- data/app/views/effective/responsable/_results.html.haml +23 -0
- data/app/views/effective/responses/_fields.html.haml +15 -0
- data/app/views/effective/responses/_response.html.haml +2 -0
- data/app/views/effective/responses/fields/_choose_one.html.haml +1 -0
- data/app/views/effective/responses/fields/_date.html.haml +2 -0
- data/app/views/effective/responses/fields/_email.html.haml +2 -0
- data/app/views/effective/responses/fields/_long_answer.html.haml +1 -0
- data/app/views/effective/responses/fields/_number.html.haml +2 -0
- data/app/views/effective/responses/fields/_select_all_that_apply.html.haml +1 -0
- data/app/views/effective/responses/fields/_select_up_to_1.html.haml +1 -0
- data/app/views/effective/responses/fields/_select_up_to_2.html.haml +1 -0
- data/app/views/effective/responses/fields/_select_up_to_3.html.haml +1 -0
- data/app/views/effective/responses/fields/_select_up_to_4.html.haml +1 -0
- data/app/views/effective/responses/fields/_select_up_to_5.html.haml +1 -0
- data/app/views/effective/responses/fields/_short_answer.html.haml +1 -0
- data/app/views/effective/responses/fields/_upload_file.html.haml +2 -0
- data/app/views/effective/responses/responses/_choose_one.html.haml +1 -0
- data/app/views/effective/responses/responses/_date.html.haml +1 -0
- data/app/views/effective/responses/responses/_email.html.haml +1 -0
- data/app/views/effective/responses/responses/_long_answer.html.haml +1 -0
- data/app/views/effective/responses/responses/_number.html.haml +1 -0
- data/app/views/effective/responses/responses/_select_all_that_apply.html.haml +5 -0
- data/app/views/effective/responses/responses/_select_up_to_1.html.haml +1 -0
- data/app/views/effective/responses/responses/_select_up_to_2.html.haml +5 -0
- data/app/views/effective/responses/responses/_select_up_to_3.html.haml +5 -0
- data/app/views/effective/responses/responses/_select_up_to_4.html.haml +5 -0
- data/app/views/effective/responses/responses/_select_up_to_5.html.haml +5 -0
- data/app/views/effective/responses/responses/_short_answer.html.haml +1 -0
- data/app/views/effective/responses/responses/_upload_file.html.haml +4 -0
- data/config/effective_questions.rb +5 -0
- data/config/locales/effective_questions.yml +11 -0
- data/config/routes.rb +13 -0
- data/db/migrate/101_create_effective_questions.rb +60 -0
- data/db/seeds.rb +15 -0
- data/lib/effective_questions/engine.rb +19 -0
- data/lib/effective_questions/version.rb +3 -0
- data/lib/effective_questions.rb +13 -0
- data/lib/generators/effective_questions/install_generator.rb +28 -0
- data/lib/tasks/effective_questions_tasks.rake +8 -0
- metadata +270 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
= effective_form_with(model: [:admin, question], engine: true) do |f|
|
|
2
|
+
- if inline_datatable?
|
|
3
|
+
= f.hidden_field :questionable_type
|
|
4
|
+
= f.hidden_field :questionable_id
|
|
5
|
+
- else
|
|
6
|
+
%P TODO
|
|
7
|
+
|
|
8
|
+
-# Follow up
|
|
9
|
+
- if inline_datatable? && (original = f.object.question).present?
|
|
10
|
+
= f.hidden_field :follow_up, value: true
|
|
11
|
+
= f.hidden_field :question_id
|
|
12
|
+
|
|
13
|
+
.mb-3.card
|
|
14
|
+
.card-body
|
|
15
|
+
%h5 Follow up Question
|
|
16
|
+
%p.text-muted This question will only appear when they answer the above question with the following value:
|
|
17
|
+
|
|
18
|
+
- if original.question_option?
|
|
19
|
+
= f.select :question_option_id, original.question_options, label: 'Answer required to display this question'
|
|
20
|
+
- else
|
|
21
|
+
= f.text_field :follow_up_value, label: 'Answer required to display this question', required: true, hint: 'Enter the exact answer value that should trigger this question to appear'
|
|
22
|
+
|
|
23
|
+
= f.text_field :title, label: 'Question Title'
|
|
24
|
+
|
|
25
|
+
- if defined?(EffectiveArticleEditor)
|
|
26
|
+
= f.article_editor :body, label: 'Body (optional)'
|
|
27
|
+
- else
|
|
28
|
+
= f.rich_text_area :body, label: 'Body (optional)'
|
|
29
|
+
|
|
30
|
+
= f.check_box :required, hint: 'A response to this question will be required'
|
|
31
|
+
= f.select :category, Effective::Question::CATEGORIES
|
|
32
|
+
|
|
33
|
+
= f.show_if :category, 'Choose one' do
|
|
34
|
+
.mt-3.card
|
|
35
|
+
.card-body
|
|
36
|
+
%h5 Choose one
|
|
37
|
+
%p Display radio buttons to select one option
|
|
38
|
+
|
|
39
|
+
= f.show_if :category, 'Select all that apply' do
|
|
40
|
+
.card
|
|
41
|
+
.card-body
|
|
42
|
+
%h5 Select all that apply
|
|
43
|
+
%p Display checkboxes to select all options that apply
|
|
44
|
+
|
|
45
|
+
= f.show_if :category, 'Select up to 1' do
|
|
46
|
+
.card
|
|
47
|
+
.card-body
|
|
48
|
+
%h5 Select up to 1 (one)
|
|
49
|
+
%p Display checkboxes to select up to 1 option
|
|
50
|
+
|
|
51
|
+
= f.show_if :category, 'Select up to 2' do
|
|
52
|
+
.card
|
|
53
|
+
.card-body
|
|
54
|
+
%h5 Select up to 2 (two)
|
|
55
|
+
%p Display checkboxes to select up to 2 options
|
|
56
|
+
|
|
57
|
+
= f.show_if :category, 'Select up to 3' do
|
|
58
|
+
.card
|
|
59
|
+
.card-body
|
|
60
|
+
%h5 Select up to 3 (three)
|
|
61
|
+
%p Display checkboxes to select up to 3 options
|
|
62
|
+
|
|
63
|
+
= f.show_if :category, 'Select up to 4' do
|
|
64
|
+
.card
|
|
65
|
+
.card-body
|
|
66
|
+
%h5 Select up to 4 (four)
|
|
67
|
+
%p Display checkboxes to select up to 4 options
|
|
68
|
+
|
|
69
|
+
= f.show_if :category, 'Select up to 5' do
|
|
70
|
+
.card
|
|
71
|
+
.card-body
|
|
72
|
+
%h5 Select up to 5 (five)
|
|
73
|
+
%p Display checkboxes to select up to 5 options
|
|
74
|
+
|
|
75
|
+
= f.show_if :category, 'Short Answer' do
|
|
76
|
+
.card
|
|
77
|
+
.card-body
|
|
78
|
+
%h5 Short Answer
|
|
79
|
+
%p Display a text field to enter a short text answer
|
|
80
|
+
|
|
81
|
+
= f.show_if :category, 'Long Answer' do
|
|
82
|
+
.card
|
|
83
|
+
.card-body
|
|
84
|
+
%h5 Long Answer
|
|
85
|
+
%p Display a textarea to enter a long text answer
|
|
86
|
+
|
|
87
|
+
= f.show_if :category, 'Date' do
|
|
88
|
+
.card
|
|
89
|
+
.card-body
|
|
90
|
+
%h5 Date
|
|
91
|
+
%p Display a date field to enter a date
|
|
92
|
+
|
|
93
|
+
= f.show_if :category, 'Email' do
|
|
94
|
+
.card
|
|
95
|
+
.card-body
|
|
96
|
+
%h5 Email
|
|
97
|
+
%p Display an email field to enter an email
|
|
98
|
+
|
|
99
|
+
= f.show_if :category, 'Number' do
|
|
100
|
+
.card
|
|
101
|
+
.card-body
|
|
102
|
+
%h5 Number
|
|
103
|
+
%p Display a number field to enter an integer number
|
|
104
|
+
|
|
105
|
+
= f.show_if :category, 'Upload File' do
|
|
106
|
+
.card
|
|
107
|
+
.card-body
|
|
108
|
+
%h5 Upload File
|
|
109
|
+
%p Display a file field to upload a file
|
|
110
|
+
|
|
111
|
+
= f.show_if_any :category, Effective::Question::WITH_OPTIONS_CATEGORIES do
|
|
112
|
+
.mt-3.card
|
|
113
|
+
.card-body
|
|
114
|
+
%h5 Options
|
|
115
|
+
%p Display the following options:
|
|
116
|
+
|
|
117
|
+
= f.has_many :question_options, class: 'tight' do |fa|
|
|
118
|
+
= fa.text_field :title, label: false
|
|
119
|
+
|
|
120
|
+
= effective_submit(f)
|
|
121
|
+
|
|
122
|
+
- unless question.follow_up?
|
|
123
|
+
%h2 Follow up questions
|
|
124
|
+
|
|
125
|
+
- if Effective::Question::UNSUPPORTED_FOLLOW_UP_QUESTION_CATEGORIES.include?(question.category)
|
|
126
|
+
%p.text-muted
|
|
127
|
+
%em Follow up questions are not supported for the #{question.category} question category
|
|
128
|
+
- elsif question.new_record?
|
|
129
|
+
%p.text-muted
|
|
130
|
+
%em Please save this question to add follow up questions
|
|
131
|
+
- else
|
|
132
|
+
%p Display follow up question(s) based on the answer to this question:
|
|
133
|
+
= render_inline_datatable Admin::EffectiveQuestionsDatatable.new(follow_up: true, question: question)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
- # The grouped results for an entire questionable resource
|
|
2
|
+
.questionable-results
|
|
3
|
+
%table.table.table-hover
|
|
4
|
+
%thead
|
|
5
|
+
%tr
|
|
6
|
+
%th Question
|
|
7
|
+
%th Results
|
|
8
|
+
|
|
9
|
+
%tbody
|
|
10
|
+
- questionable.questions.top_level.each_with_index do |question, index|
|
|
11
|
+
- responses = questionable.completed_responses(question: question)
|
|
12
|
+
|
|
13
|
+
%tr
|
|
14
|
+
%td
|
|
15
|
+
#{index + 1}. #{question}
|
|
16
|
+
%br
|
|
17
|
+
%small.text-muted= question.category
|
|
18
|
+
|
|
19
|
+
%td= render('effective/questionable/result', question: question, responses: responses)
|
|
20
|
+
|
|
21
|
+
- question.follow_up_questions.each_with_index do |follow_up_question, index|
|
|
22
|
+
- responses = questionable.completed_responses(question: follow_up_question)
|
|
23
|
+
|
|
24
|
+
%tr
|
|
25
|
+
%td
|
|
26
|
+
.ml-4
|
|
27
|
+
#{('a'.ord + index).chr}. #{follow_up_question}
|
|
28
|
+
%br
|
|
29
|
+
%small.text-muted= follow_up_question.category
|
|
30
|
+
|
|
31
|
+
%td= render('effective/questionable/result', question: follow_up_question, responses: responses)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
- sorted = responses.sort { |a, b| (a.date || Time.zone.now.end_of_year) <=> (b.date || Time.zone.now.end_of_year) }
|
|
2
|
+
|
|
3
|
+
- sorted.group_by { |br| br.response }.each do |response, selected|
|
|
4
|
+
- count = selected.length
|
|
5
|
+
- total = responses.length
|
|
6
|
+
- percent = (total.zero? ? 0 : ((count * 100.0) / total).round)
|
|
7
|
+
|
|
8
|
+
.questionable-result-option
|
|
9
|
+
.d-flex
|
|
10
|
+
.mr-auto= response.blank? ? 'None of the Above' : response.strftime('%F')
|
|
11
|
+
.text-muted #{count} (#{percent}%)
|
|
12
|
+
|
|
13
|
+
.progress.mb-3
|
|
14
|
+
.progress-bar{role: 'progressbar', 'aria-valuenow': count, 'aria-valuemin': 0, 'aria-valuemax': total, style: "width: #{percent}%"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
- sorted = responses.sort { |a, b| (a.email || '') <=> (b.email || '') }
|
|
2
|
+
|
|
3
|
+
- sorted.group_by { |br| br.response }.each do |response, selected|
|
|
4
|
+
- count = selected.length
|
|
5
|
+
- total = responses.length
|
|
6
|
+
- percent = (total.zero? ? 0 : ((count * 100.0) / total).round)
|
|
7
|
+
|
|
8
|
+
.questionable-result-option
|
|
9
|
+
.d-flex
|
|
10
|
+
.mr-auto= response.blank? ? 'None of the Above' : response
|
|
11
|
+
.text-muted #{count} (#{percent}%)
|
|
12
|
+
|
|
13
|
+
.progress.mb-3
|
|
14
|
+
.progress-bar{role: 'progressbar', 'aria-valuenow': count, 'aria-valuemin': 0, 'aria-valuemax': total, style: "width: #{percent}%"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
- sorted = responses.sort { |a, b| (a.number || 999999999) <=> (b.number || 999999999) }
|
|
2
|
+
|
|
3
|
+
- sorted.group_by { |br| br.response }.each do |response, selected|
|
|
4
|
+
- count = selected.length
|
|
5
|
+
- total = responses.length
|
|
6
|
+
- percent = (total.zero? ? 0 : ((count * 100.0) / total).round)
|
|
7
|
+
|
|
8
|
+
.questionable-result-option
|
|
9
|
+
.d-flex
|
|
10
|
+
.mr-auto= response.blank? ? 'None of the Above' : response
|
|
11
|
+
.text-muted #{count} (#{percent}%)
|
|
12
|
+
|
|
13
|
+
.progress.mb-3
|
|
14
|
+
.progress-bar{role: 'progressbar', 'aria-valuenow': count, 'aria-valuemin': 0, 'aria-valuemax': total, style: "width: #{percent}%"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
- (question.question_options + [nil]).each do |question_option|
|
|
2
|
+
- selected = responses.select { |br| br.response.blank? } if question_option.blank?
|
|
3
|
+
- selected ||= responses.select { |br| Array(br.response).include?(question_option) }
|
|
4
|
+
|
|
5
|
+
- count = selected.length
|
|
6
|
+
- total = responses.length
|
|
7
|
+
- percent = (total.zero? ? 0 : ((count * 100.0) / total).round)
|
|
8
|
+
|
|
9
|
+
- next if question_option.blank? && count == 0
|
|
10
|
+
|
|
11
|
+
.questionable-result-option
|
|
12
|
+
.d-flex
|
|
13
|
+
.mr-auto= question_option.blank? ? 'None of the Above' : question_option
|
|
14
|
+
.text-muted #{count} (#{percent}%)
|
|
15
|
+
|
|
16
|
+
.progress.mb-3
|
|
17
|
+
.progress-bar{role: 'progressbar', 'aria-valuenow': count, 'aria-valuemin': 0, 'aria-valuemax': total, style: "width: #{percent}%"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
- raise("expected an acts_as_responsable resource") unless responsable.class.try(:acts_as_responsable?)
|
|
2
|
+
- raise("expected an acts_as_questionable resource") unless questionable.class.try(:acts_as_questionable?)
|
|
3
|
+
|
|
4
|
+
- questionable.questions.top_level.deep.each do |question|
|
|
5
|
+
- response = responsable.response(question: question)
|
|
6
|
+
|
|
7
|
+
= f.fields_for :responses, response do |fbr|
|
|
8
|
+
= render('/effective/responses/fields', f: fbr, question: question)
|
|
9
|
+
|
|
10
|
+
- question.follow_up_questions.each do |follow_up|
|
|
11
|
+
- response = responsable.response(question: follow_up)
|
|
12
|
+
|
|
13
|
+
= fbr.show_if(question.show_if_attribute, follow_up.show_if_value) do
|
|
14
|
+
= f.fields_for :responses, response do |fbr|
|
|
15
|
+
= render('/effective/responses/fields', f: fbr, question: follow_up)
|
|
16
|
+
|
|
17
|
+
= fbr.hide_if(question.show_if_attribute, follow_up.show_if_value) do
|
|
18
|
+
= f.fields_for :responses, response do |fbr|
|
|
19
|
+
= fbr.hidden_field :_destroy, value: true
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
- # The individiaual responses for one resonsable resource
|
|
2
|
+
.responsable-results
|
|
3
|
+
%table.table.table-hover
|
|
4
|
+
%thead
|
|
5
|
+
%tr
|
|
6
|
+
%th Question
|
|
7
|
+
%th Response
|
|
8
|
+
|
|
9
|
+
%tbody
|
|
10
|
+
- questionable.questions.top_level.deep.each do |question|
|
|
11
|
+
- response = responsable.response(question: question)
|
|
12
|
+
|
|
13
|
+
%tr
|
|
14
|
+
%td= question
|
|
15
|
+
%td= render('effective/responses/response', response: response)
|
|
16
|
+
|
|
17
|
+
- question.follow_up_questions.deep.each do |follow_up_question|
|
|
18
|
+
- response = responsable.response(question: follow_up_question)
|
|
19
|
+
|
|
20
|
+
- if response.persisted?
|
|
21
|
+
%tr
|
|
22
|
+
%td= follow_up_question
|
|
23
|
+
%td= render('effective/responses/response', response: response)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
.row
|
|
2
|
+
.col
|
|
3
|
+
%h3= question
|
|
4
|
+
%p.text-muted.mb-2= question.category
|
|
5
|
+
|
|
6
|
+
- if question.body.present?
|
|
7
|
+
.mb-3= question.body
|
|
8
|
+
|
|
9
|
+
= f.hidden_field :questionable_type
|
|
10
|
+
= f.hidden_field :questionable_id
|
|
11
|
+
= f.hidden_field :question_id
|
|
12
|
+
|
|
13
|
+
- response = f.object
|
|
14
|
+
- partial = 'effective/responses/fields/' + question.category_partial
|
|
15
|
+
= render(partial, f: f, response: response, question: question)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= f.radios :question_option_ids, question.question_options, label: false, required: question.required?
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= f.text_area :long_answer, label: false, required: question.required?
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= f.checks :question_option_ids, question.question_options, label: false, required: question.required?
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= f.checks :question_option_ids, question.question_options, label: false, actions: false, required: question.required?
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= f.checks :question_option_ids, question.question_options, label: false, actions: false, required: question.required?
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= f.checks :question_option_ids, question.question_options, label: false, actions: false, required: question.required?
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= f.checks :question_option_ids, question.question_options, label: false, actions: false, required: question.required?
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= f.checks :question_option_ids, question.question_options, label: false, actions: false, required: question.required?
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= f.text_field :short_answer, label: false, required: question.required?
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= response.response.presence || '-'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= response.response&.strftime('%F') || '-'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= response.response.present? ? mail_to(response.response) : '-'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= response.response.presence || '-'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= response.response.presence || '-'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= response.response&.title || '-'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= response.response.presence || '-'
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
en:
|
|
2
|
+
effective_questions:
|
|
3
|
+
name: 'Questions and Responses'
|
|
4
|
+
acronym: 'Questions'
|
|
5
|
+
|
|
6
|
+
activerecord:
|
|
7
|
+
models:
|
|
8
|
+
effective/question: 'Question'
|
|
9
|
+
effective/question_option: 'Question Option'
|
|
10
|
+
effective/response: 'Response'
|
|
11
|
+
effective/response_option: 'Response Option'
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Rails.application.routes.draw do
|
|
2
|
+
mount EffectiveQuestions::Engine => '/', as: 'effective_questions'
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
EffectiveQuestions::Engine.routes.draw do
|
|
6
|
+
scope module: 'effective' do
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
namespace :admin do
|
|
10
|
+
resources :questions, except: [:show]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
class CreateEffectiveQuestions < ActiveRecord::Migration[6.0]
|
|
2
|
+
def change
|
|
3
|
+
create_table :questions do |t|
|
|
4
|
+
t.integer :questionable_id
|
|
5
|
+
t.string :questionable_type
|
|
6
|
+
|
|
7
|
+
t.string :title
|
|
8
|
+
t.string :category
|
|
9
|
+
t.boolean :required, default: true
|
|
10
|
+
|
|
11
|
+
t.integer :position
|
|
12
|
+
|
|
13
|
+
t.boolean :follow_up, default: false
|
|
14
|
+
t.string :follow_up_value
|
|
15
|
+
|
|
16
|
+
t.integer :question_id
|
|
17
|
+
t.integer :question_option_id
|
|
18
|
+
|
|
19
|
+
t.datetime :updated_at
|
|
20
|
+
t.datetime :created_at
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
create_table :question_options do |t|
|
|
24
|
+
t.references :question, polymorphic: false
|
|
25
|
+
|
|
26
|
+
t.string :title
|
|
27
|
+
t.integer :position
|
|
28
|
+
|
|
29
|
+
t.datetime :updated_at
|
|
30
|
+
t.datetime :created_at
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
create_table :responses do |t|
|
|
34
|
+
t.integer :questionable_id
|
|
35
|
+
t.string :questionable_type
|
|
36
|
+
|
|
37
|
+
t.integer :responsable_id
|
|
38
|
+
t.string :responsable_type
|
|
39
|
+
|
|
40
|
+
t.integer :question_id
|
|
41
|
+
|
|
42
|
+
t.date :date
|
|
43
|
+
t.string :email
|
|
44
|
+
t.integer :number
|
|
45
|
+
t.text :long_answer
|
|
46
|
+
t.text :short_answer
|
|
47
|
+
|
|
48
|
+
t.datetime :updated_at
|
|
49
|
+
t.datetime :created_at
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
create_table :response_options do |t|
|
|
53
|
+
t.integer :response_id
|
|
54
|
+
t.integer :question_option_id
|
|
55
|
+
|
|
56
|
+
t.datetime :updated_at
|
|
57
|
+
t.datetime :created_at
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
data/db/seeds.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
puts "Running effective_questions seeds"
|
|
2
|
+
|
|
3
|
+
def build_question(questionable, category)
|
|
4
|
+
questions = Array(category).map.with_index do |category, index|
|
|
5
|
+
question = questionable.questions.build(title: "#{category} Question ##{index+1}", category: category)
|
|
6
|
+
|
|
7
|
+
if question.question_option?
|
|
8
|
+
question.question_options.build(title: 'Option A')
|
|
9
|
+
question.question_options.build(title: 'Option B')
|
|
10
|
+
question.question_options.build(title: 'Option C')
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
questions.length == 1 ? questions.first : questions
|
|
15
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module EffectiveQuestions
|
|
2
|
+
class Engine < ::Rails::Engine
|
|
3
|
+
engine_name 'effective_questions'
|
|
4
|
+
|
|
5
|
+
# Set up our default configuration options.
|
|
6
|
+
initializer 'effective_questions.defaults', before: :load_config_initializers do |app|
|
|
7
|
+
eval File.read("#{config.root}/config/effective_questions.rb")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Include concerns and allow any ActiveRecord object to call it
|
|
11
|
+
initializer 'effective_questions.active_record' do |app|
|
|
12
|
+
app.config.to_prepare do
|
|
13
|
+
ActiveRecord::Base.extend(ActsAsQuestionable::Base)
|
|
14
|
+
ActiveRecord::Base.extend(ActsAsResponsable::Base)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module EffectiveQuestions
|
|
2
|
+
module Generators
|
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
|
4
|
+
include Rails::Generators::Migration
|
|
5
|
+
|
|
6
|
+
desc 'Creates an EffectiveQuestions initializer in your application.'
|
|
7
|
+
|
|
8
|
+
source_root File.expand_path('../../templates', __FILE__)
|
|
9
|
+
|
|
10
|
+
def self.next_migration_number(dirname)
|
|
11
|
+
if not ActiveRecord::Base.timestamped_migrations
|
|
12
|
+
Time.new.utc.strftime("%Y%m%d%H%M%S")
|
|
13
|
+
else
|
|
14
|
+
'%.3d' % (current_migration_number(dirname) + 1)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def copy_initializer
|
|
19
|
+
template ('../' * 3) + 'config/effective_questions.rb', 'config/initializers/effective_questions.rb'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def create_migration_file
|
|
23
|
+
migration_template ('../' * 3) + 'db/migrate/101_create_effective_questions.rb', 'db/migrate/create_effective_questions.rb'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|