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.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +133 -0
  4. data/Rakefile +18 -0
  5. data/app/assets/config/effective_questions_manifest.js +1 -0
  6. data/app/assets/stylesheets/effective_questions.scss +0 -0
  7. data/app/controllers/admin/questions_controller.rb +13 -0
  8. data/app/datatables/admin/effective_questionable_results_datatable.rb +44 -0
  9. data/app/datatables/admin/effective_questions_datatable.rb +45 -0
  10. data/app/helpers/effective_questions_helper.rb +2 -0
  11. data/app/models/concerns/acts_as_questionable.rb +30 -0
  12. data/app/models/concerns/acts_as_responsable.rb +30 -0
  13. data/app/models/effective/question.rb +124 -0
  14. data/app/models/effective/question_option.rb +26 -0
  15. data/app/models/effective/response.rb +87 -0
  16. data/app/models/effective/response_option.rb +6 -0
  17. data/app/views/admin/questions/_form.html.haml +133 -0
  18. data/app/views/effective/questionable/_result.html.haml +2 -0
  19. data/app/views/effective/questionable/_results.html.haml +31 -0
  20. data/app/views/effective/questionable/results/_choose_one.html.haml +2 -0
  21. data/app/views/effective/questionable/results/_date.html.haml +14 -0
  22. data/app/views/effective/questionable/results/_email.html.haml +14 -0
  23. data/app/views/effective/questionable/results/_long_answer.html.haml +2 -0
  24. data/app/views/effective/questionable/results/_number.html.haml +14 -0
  25. data/app/views/effective/questionable/results/_question_option.html.haml +17 -0
  26. data/app/views/effective/questionable/results/_select_all_that_apply.html.haml +2 -0
  27. data/app/views/effective/questionable/results/_select_up_to_1.html.haml +2 -0
  28. data/app/views/effective/questionable/results/_select_up_to_2.html.haml +2 -0
  29. data/app/views/effective/questionable/results/_select_up_to_3.html.haml +2 -0
  30. data/app/views/effective/questionable/results/_select_up_to_4.html.haml +2 -0
  31. data/app/views/effective/questionable/results/_select_up_to_5.html.haml +2 -0
  32. data/app/views/effective/questionable/results/_short_answer.html.haml +2 -0
  33. data/app/views/effective/questionable/results/_upload_file.html.haml +3 -0
  34. data/app/views/effective/questions/_question.html.haml +6 -0
  35. data/app/views/effective/responsable/_fields.html.haml +19 -0
  36. data/app/views/effective/responsable/_results.html.haml +23 -0
  37. data/app/views/effective/responses/_fields.html.haml +15 -0
  38. data/app/views/effective/responses/_response.html.haml +2 -0
  39. data/app/views/effective/responses/fields/_choose_one.html.haml +1 -0
  40. data/app/views/effective/responses/fields/_date.html.haml +2 -0
  41. data/app/views/effective/responses/fields/_email.html.haml +2 -0
  42. data/app/views/effective/responses/fields/_long_answer.html.haml +1 -0
  43. data/app/views/effective/responses/fields/_number.html.haml +2 -0
  44. data/app/views/effective/responses/fields/_select_all_that_apply.html.haml +1 -0
  45. data/app/views/effective/responses/fields/_select_up_to_1.html.haml +1 -0
  46. data/app/views/effective/responses/fields/_select_up_to_2.html.haml +1 -0
  47. data/app/views/effective/responses/fields/_select_up_to_3.html.haml +1 -0
  48. data/app/views/effective/responses/fields/_select_up_to_4.html.haml +1 -0
  49. data/app/views/effective/responses/fields/_select_up_to_5.html.haml +1 -0
  50. data/app/views/effective/responses/fields/_short_answer.html.haml +1 -0
  51. data/app/views/effective/responses/fields/_upload_file.html.haml +2 -0
  52. data/app/views/effective/responses/responses/_choose_one.html.haml +1 -0
  53. data/app/views/effective/responses/responses/_date.html.haml +1 -0
  54. data/app/views/effective/responses/responses/_email.html.haml +1 -0
  55. data/app/views/effective/responses/responses/_long_answer.html.haml +1 -0
  56. data/app/views/effective/responses/responses/_number.html.haml +1 -0
  57. data/app/views/effective/responses/responses/_select_all_that_apply.html.haml +5 -0
  58. data/app/views/effective/responses/responses/_select_up_to_1.html.haml +1 -0
  59. data/app/views/effective/responses/responses/_select_up_to_2.html.haml +5 -0
  60. data/app/views/effective/responses/responses/_select_up_to_3.html.haml +5 -0
  61. data/app/views/effective/responses/responses/_select_up_to_4.html.haml +5 -0
  62. data/app/views/effective/responses/responses/_select_up_to_5.html.haml +5 -0
  63. data/app/views/effective/responses/responses/_short_answer.html.haml +1 -0
  64. data/app/views/effective/responses/responses/_upload_file.html.haml +4 -0
  65. data/config/effective_questions.rb +5 -0
  66. data/config/locales/effective_questions.yml +11 -0
  67. data/config/routes.rb +13 -0
  68. data/db/migrate/101_create_effective_questions.rb +60 -0
  69. data/db/seeds.rb +15 -0
  70. data/lib/effective_questions/engine.rb +19 -0
  71. data/lib/effective_questions/version.rb +3 -0
  72. data/lib/effective_questions.rb +13 -0
  73. data/lib/generators/effective_questions/install_generator.rb +28 -0
  74. data/lib/tasks/effective_questions_tasks.rake +8 -0
  75. 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,2 @@
1
+ - partial = 'effective/questionable/results/' + question.category_partial
2
+ = render(partial, question: question, responses: responses)
@@ -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,2 @@
1
+ - partial = 'effective/questionable/results/question_option'
2
+ = render(partial, question: 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,2 @@
1
+ - responses.select { |br| br.long_answer.present? }.each do |response|
2
+ .questionable-result-long-answer= response.response
@@ -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,2 @@
1
+ - partial = 'effective/questionable/results/question_option'
2
+ = render(partial, question: question, responses: responses)
@@ -0,0 +1,2 @@
1
+ - partial = 'effective/questionable/results/question_option'
2
+ = render(partial, question: question, responses: responses)
@@ -0,0 +1,2 @@
1
+ - partial = 'effective/questionable/results/question_option'
2
+ = render(partial, question: question, responses: responses)
@@ -0,0 +1,2 @@
1
+ - partial = 'effective/questionable/results/question_option'
2
+ = render(partial, question: question, responses: responses)
@@ -0,0 +1,2 @@
1
+ - partial = 'effective/questionable/results/question_option'
2
+ = render(partial, question: question, responses: responses)
@@ -0,0 +1,2 @@
1
+ - partial = 'effective/questionable/results/question_option'
2
+ = render(partial, question: question, responses: responses)
@@ -0,0 +1,2 @@
1
+ - responses.select { |br| br.short_answer.present? }.each do |response|
2
+ .questionable-result-short-answer= response.response
@@ -0,0 +1,3 @@
1
+ - responses.select { |br| br.response&.attached? }.each do |response|
2
+ .questionable-result-upload-file
3
+ = link_to(response.response.filename, url_for(response.response), target: '_blank')
@@ -0,0 +1,6 @@
1
+ .effective-question
2
+ Question ##{question.position + 1}:
3
+ = question
4
+
5
+ - if question.body.present?
6
+ .mt-4= question.body.to_s
@@ -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,2 @@
1
+ - partial = 'effective/responses/responses/' + response.category_partial
2
+ = render(partial, response: response)
@@ -0,0 +1 @@
1
+ = f.radios :question_option_ids, question.question_options, label: false, required: question.required?
@@ -0,0 +1,2 @@
1
+ .row
2
+ .col-sm-6= f.date_field :date, label: false, required: question.required?
@@ -0,0 +1,2 @@
1
+ .row
2
+ .col-sm-6= f.email_field :email, label: false, required: question.required?
@@ -0,0 +1 @@
1
+ = f.text_area :long_answer, label: false, required: question.required?
@@ -0,0 +1,2 @@
1
+ .row
2
+ .col-sm-6= f.number_field :number, 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,2 @@
1
+ - # Always required false here because we'll handle the logic in the response model
2
+ = f.file_field :upload_file, label: false, required: false
@@ -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,5 @@
1
+ - response.response.each do |question_option|
2
+ %div= question_option.title
3
+
4
+ - if response.response.blank?
5
+ = '-'
@@ -0,0 +1 @@
1
+ = response.response&.title || '-'
@@ -0,0 +1,5 @@
1
+ - response.response.each do |question_option|
2
+ %div= question_option.title
3
+
4
+ - if response.response.blank?
5
+ = '-'
@@ -0,0 +1,5 @@
1
+ - response.response.each do |question_option|
2
+ %div= question_option.title
3
+
4
+ - if response.response.blank?
5
+ = '-'
@@ -0,0 +1,5 @@
1
+ - response.response.each do |question_option|
2
+ %div= question_option.title
3
+
4
+ - if response.response.blank?
5
+ = '-'
@@ -0,0 +1,5 @@
1
+ - response.response.each do |question_option|
2
+ %div= question_option.title
3
+
4
+ - if response.response.blank?
5
+ = '-'
@@ -0,0 +1 @@
1
+ = response.response.presence || '-'
@@ -0,0 +1,4 @@
1
+ - if response.response&.attached?
2
+ = link_to(response.response.filename, url_for(response.response), target: '_blank')
3
+ - else
4
+ = '-'
@@ -0,0 +1,5 @@
1
+ EffectiveQuestions.setup do |config|
2
+ # Layout Settings
3
+ # Configure the Layout per controller, or all at once
4
+ # config.layout = { application: 'application', admin: 'admin' }
5
+ end
@@ -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,3 @@
1
+ module EffectiveQuestions
2
+ VERSION = '0.0.2'
3
+ end
@@ -0,0 +1,13 @@
1
+ require 'effective_resources'
2
+ require 'effective_datatables'
3
+ require 'effective_questions/engine'
4
+ require 'effective_questions/version'
5
+
6
+ module EffectiveQuestions
7
+
8
+ def self.config_keys
9
+ [ :layout ]
10
+ end
11
+
12
+ include EffectiveGem
13
+ 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