effective_questions 0.0.3 → 0.0.4
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 +4 -4
- data/app/controllers/admin/responses_controller.rb +13 -0
- data/app/datatables/admin/effective_questions_datatable.rb +3 -1
- data/app/datatables/admin/effective_responses_datatable.rb +24 -0
- data/app/models/concerns/acts_as_questionable.rb +4 -0
- data/app/models/concerns/acts_as_responsable.rb +14 -0
- data/app/models/effective/question.rb +3 -0
- data/app/models/effective/question_answer.rb +3 -3
- data/app/models/effective/response.rb +69 -5
- data/app/models/effective/response_option.rb +5 -0
- data/app/views/admin/questions/_form.html.haml +3 -0
- data/app/views/effective/questionable/results/_question_option.html.haml +1 -1
- data/app/views/effective/responsable/_results.html.haml +26 -0
- data/app/views/effective/responses/responses/_choose_one.html.haml +1 -1
- data/app/views/effective/responses/responses/_select_all_that_apply.html.haml +2 -2
- data/app/views/effective/responses/responses/_select_up_to_1.html.haml +1 -1
- data/app/views/effective/responses/responses/_select_up_to_2.html.haml +2 -2
- data/app/views/effective/responses/responses/_select_up_to_3.html.haml +2 -2
- data/app/views/effective/responses/responses/_select_up_to_4.html.haml +2 -2
- data/app/views/effective/responses/responses/_select_up_to_5.html.haml +2 -2
- data/config/routes.rb +1 -0
- data/db/migrate/101_create_effective_questions.rb +41 -0
- data/lib/effective_questions/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7b1be795579cdb74c263712b86c74f5b5fe34e2e1d87fbbb57fc8cef6fc07510
|
|
4
|
+
data.tar.gz: 1acfbae757e1852f801024ee6679a9d9c1661cd8fd3f5e4c37d24807dad2b0f4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 16c8a5452a08adf9fe820e809c5a5847a460f01040a3356b1dc8448b50f9e268e3ea4e18a747fa842550898c5856cf44081fe86fb19763dc146af3f65bb76cdb
|
|
7
|
+
data.tar.gz: 7cddf83480381e353009cbbf263c3fc7c9c902e0d9c447c3ef7125d61d1dde8d76cc89a27ddd87ba3204726d4ad1fc43873f4c703bc728bef563d5a4dfe6bd93
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Admin
|
|
2
|
+
class ResponsesController < ApplicationController
|
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
|
4
|
+
before_action { EffectiveResources.authorize!(self, :admin, :effective_questions) }
|
|
5
|
+
|
|
6
|
+
include Effective::CrudController
|
|
7
|
+
|
|
8
|
+
def permitted_params
|
|
9
|
+
params.require(:effective_response).permit!
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -17,7 +17,9 @@ class Admin::EffectiveQuestionsDatatable < Effective::Datatable
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
col :title
|
|
20
|
-
col :
|
|
20
|
+
col :task
|
|
21
|
+
col :points
|
|
22
|
+
col :body, as: :text, visible: false
|
|
21
23
|
col :required
|
|
22
24
|
|
|
23
25
|
col :category, label: 'Type'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class Admin::EffectiveResponsesDatatable < Effective::Datatable
|
|
2
|
+
datatable do
|
|
3
|
+
col :updated_at, visible: false
|
|
4
|
+
col :created_at, visible: false
|
|
5
|
+
col :id, visible: false
|
|
6
|
+
|
|
7
|
+
col :responsable
|
|
8
|
+
col :questionable
|
|
9
|
+
col :question
|
|
10
|
+
|
|
11
|
+
col(:response) do |response|
|
|
12
|
+
render('effective/responses/response', response: response)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
col :correct?, as: :boolean
|
|
16
|
+
|
|
17
|
+
actions_col
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
collection do
|
|
21
|
+
Effective::Response.all.deep
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
@@ -27,4 +27,18 @@ module ActsAsResponsable
|
|
|
27
27
|
response ||= responses.build(questionable: question.questionable, question: question)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
def responsable_completed?
|
|
31
|
+
try(:done?) == true || try(:completed?) == true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def scored_responses
|
|
35
|
+
responses.select { |r| r.question&.scored? }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def responsable_score
|
|
39
|
+
scored = scored_responses()
|
|
40
|
+
return 0 unless scored.present?
|
|
41
|
+
|
|
42
|
+
((scored.count(&:correct?).to_f / scored.length) * 100_000).round
|
|
43
|
+
end
|
|
30
44
|
end
|
|
@@ -147,11 +147,11 @@ module Effective
|
|
|
147
147
|
return short_answer if question.short_answer?
|
|
148
148
|
end
|
|
149
149
|
|
|
150
|
-
raise(
|
|
150
|
+
raise("unknown operation: #{operation}")
|
|
151
151
|
end
|
|
152
152
|
|
|
153
153
|
def equals?
|
|
154
|
-
operation == '
|
|
154
|
+
operation == 'Equal to'
|
|
155
155
|
end
|
|
156
156
|
|
|
157
157
|
def contains?
|
|
@@ -163,7 +163,7 @@ module Effective
|
|
|
163
163
|
end
|
|
164
164
|
|
|
165
165
|
def within_range?
|
|
166
|
-
operation == 'Within
|
|
166
|
+
operation == 'Within range'
|
|
167
167
|
end
|
|
168
168
|
|
|
169
169
|
def lt?
|
|
@@ -59,7 +59,24 @@ module Effective
|
|
|
59
59
|
length: { maximum: 5, message: 'please select 5 options or fewer' }
|
|
60
60
|
|
|
61
61
|
def to_s
|
|
62
|
-
|
|
62
|
+
return '' unless question.present?
|
|
63
|
+
return '' unless response.present?
|
|
64
|
+
|
|
65
|
+
case question.category
|
|
66
|
+
when 'Date'
|
|
67
|
+
response.strftime('%Y-%m-%d')
|
|
68
|
+
when 'Price'
|
|
69
|
+
"$#{'%0.2f' % (response / 100.0)}"
|
|
70
|
+
when 'Percentage'
|
|
71
|
+
precision = (response % 1000).zero? ? 0 : 3
|
|
72
|
+
"#{format("%.#{precision}f", response.to_f / 1000)}%"
|
|
73
|
+
when 'Upload File'
|
|
74
|
+
response.filename.to_s
|
|
75
|
+
when 'Select all that apply', 'Select up to 2', 'Select up to 3', 'Select up to 4', 'Select up to 5'
|
|
76
|
+
Array(response).map(&:to_s).join(', ')
|
|
77
|
+
else
|
|
78
|
+
response.to_s
|
|
79
|
+
end
|
|
63
80
|
end
|
|
64
81
|
|
|
65
82
|
def response
|
|
@@ -75,9 +92,9 @@ module Effective
|
|
|
75
92
|
return short_answer if question.short_answer?
|
|
76
93
|
return upload_file if question.upload_file?
|
|
77
94
|
|
|
78
|
-
return
|
|
79
|
-
return
|
|
80
|
-
return
|
|
95
|
+
return response_options.first if question.choose_one?
|
|
96
|
+
return response_options.first if question.select_up_to_1?
|
|
97
|
+
return response_options if question.question_option?
|
|
81
98
|
|
|
82
99
|
raise('unknown response for unexpected question category')
|
|
83
100
|
end
|
|
@@ -87,7 +104,54 @@ module Effective
|
|
|
87
104
|
end
|
|
88
105
|
|
|
89
106
|
def completed?
|
|
90
|
-
responsable.
|
|
107
|
+
responsable.responsable_completed?
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def correct?
|
|
111
|
+
return unless question.present? && question.scored?
|
|
112
|
+
return false unless response.present?
|
|
113
|
+
|
|
114
|
+
if question.question_option?
|
|
115
|
+
# For option-based questions, check if selected options match answer options
|
|
116
|
+
answers = question.answer.map(&:id)
|
|
117
|
+
selected = Array(response).map(&:question_option_id)
|
|
118
|
+
|
|
119
|
+
if question.select_all_that_apply?
|
|
120
|
+
return selected.sort == answers.sort
|
|
121
|
+
else
|
|
122
|
+
# For choose_one or select_up_to_X, all selected must be correct
|
|
123
|
+
return selected.present? && (selected - answers).blank?
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# For non-option questions, check against question_answer
|
|
128
|
+
answer = question.question_answer
|
|
129
|
+
return false unless answer.present?
|
|
130
|
+
|
|
131
|
+
case answer.operation
|
|
132
|
+
when 'Equal to'
|
|
133
|
+
if response.is_a?(String) && answer.answer.is_a?(String)
|
|
134
|
+
response.downcase.strip == answer.answer.downcase.strip
|
|
135
|
+
else
|
|
136
|
+
response == answer.answer
|
|
137
|
+
end
|
|
138
|
+
when 'Within range'
|
|
139
|
+
answer.answer.cover?(response)
|
|
140
|
+
when 'Less than'
|
|
141
|
+
response < answer.answer
|
|
142
|
+
when 'Less than or equal to'
|
|
143
|
+
response <= answer.answer
|
|
144
|
+
when 'Greater than'
|
|
145
|
+
response > answer.answer
|
|
146
|
+
when 'Greater than or equal to'
|
|
147
|
+
response >= answer.answer
|
|
148
|
+
when 'Contains'
|
|
149
|
+
response.to_s.downcase.include?(answer.answer.to_s.downcase)
|
|
150
|
+
when 'Does not contain'
|
|
151
|
+
!response.to_s.downcase.include?(answer.answer.to_s.downcase)
|
|
152
|
+
else
|
|
153
|
+
false
|
|
154
|
+
end
|
|
91
155
|
end
|
|
92
156
|
|
|
93
157
|
end
|
|
@@ -21,6 +21,9 @@
|
|
|
21
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
22
|
|
|
23
23
|
= f.text_field :title, label: 'Question Title'
|
|
24
|
+
.row
|
|
25
|
+
.col= f.text_field :task, hint: 'An optional task name or number used in exports'
|
|
26
|
+
.col= f.number_field :points, hint: 'An optional number of points awarded for this question'
|
|
24
27
|
|
|
25
28
|
- if defined?(EffectiveArticleEditor)
|
|
26
29
|
= f.article_editor :body, label: 'Body (optional)'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
- (question.question_options + [nil]).each do |question_option|
|
|
2
2
|
- selected = responses.select { |br| br.response.blank? } if question_option.blank?
|
|
3
|
-
- selected ||= responses.select { |br| Array(br.response).
|
|
3
|
+
- selected ||= responses.select { |br| Array(br.response).any? { |ro| ro.question_option == question_option } }
|
|
4
4
|
|
|
5
5
|
- count = selected.length
|
|
6
6
|
- total = responses.length
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
- # The individiaual responses for one responsable resource
|
|
2
|
+
- include_scores = (local_assigns[:include_scores] == true)
|
|
3
|
+
|
|
2
4
|
.responsable-results
|
|
3
5
|
%table.table.table-hover
|
|
4
6
|
%thead
|
|
5
7
|
%tr
|
|
6
8
|
%th Question
|
|
7
9
|
%th Response
|
|
10
|
+
- if include_scores
|
|
11
|
+
%th Scored Result
|
|
8
12
|
|
|
9
13
|
%tbody
|
|
10
14
|
- questionable.questions.top_level.deep.each do |question|
|
|
@@ -14,6 +18,17 @@
|
|
|
14
18
|
%td= question
|
|
15
19
|
%td= render('effective/responses/response', response: response)
|
|
16
20
|
|
|
21
|
+
- if include_scores
|
|
22
|
+
%td
|
|
23
|
+
- if question.scored?
|
|
24
|
+
%span{title: "Correct answer was #{question.answer_to_s}"}
|
|
25
|
+
- if response.correct?
|
|
26
|
+
= badge('Correct', 'badge-success')
|
|
27
|
+
- else
|
|
28
|
+
= badge('Incorrect', 'badge-danger')
|
|
29
|
+
- else
|
|
30
|
+
= '-'
|
|
31
|
+
|
|
17
32
|
- question.follow_up_questions.deep.each do |follow_up_question|
|
|
18
33
|
- response = responsable.response(question: follow_up_question)
|
|
19
34
|
|
|
@@ -21,3 +36,14 @@
|
|
|
21
36
|
%tr
|
|
22
37
|
%td= follow_up_question
|
|
23
38
|
%td= render('effective/responses/response', response: response)
|
|
39
|
+
|
|
40
|
+
- if include_scores
|
|
41
|
+
%td
|
|
42
|
+
- if follow_up_question.scored?
|
|
43
|
+
%span{title: "Correct answer was #{follow_up_question.answer_to_s}"}
|
|
44
|
+
- if response.correct?
|
|
45
|
+
= badge('Correct', 'badge-success')
|
|
46
|
+
- else
|
|
47
|
+
= badge('Incorrect', 'badge-danger')
|
|
48
|
+
- else
|
|
49
|
+
= '-'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
= response.response
|
|
1
|
+
= response.response&.question_option || '-'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
= response.response
|
|
1
|
+
= response.response || '-'
|
data/config/routes.rb
CHANGED
|
@@ -16,6 +16,11 @@ class CreateEffectiveQuestions < ActiveRecord::Migration[6.0]
|
|
|
16
16
|
t.integer :question_id
|
|
17
17
|
t.integer :question_option_id
|
|
18
18
|
|
|
19
|
+
t.boolean :scored, default: false
|
|
20
|
+
|
|
21
|
+
t.string :task
|
|
22
|
+
t.decimal :points
|
|
23
|
+
|
|
19
24
|
t.datetime :updated_at
|
|
20
25
|
t.datetime :created_at
|
|
21
26
|
end
|
|
@@ -26,6 +31,8 @@ class CreateEffectiveQuestions < ActiveRecord::Migration[6.0]
|
|
|
26
31
|
t.string :title
|
|
27
32
|
t.integer :position
|
|
28
33
|
|
|
34
|
+
t.boolean :answer, default: false
|
|
35
|
+
|
|
29
36
|
t.datetime :updated_at
|
|
30
37
|
t.datetime :created_at
|
|
31
38
|
end
|
|
@@ -59,5 +66,39 @@ class CreateEffectiveQuestions < ActiveRecord::Migration[6.0]
|
|
|
59
66
|
t.datetime :updated_at
|
|
60
67
|
t.datetime :created_at
|
|
61
68
|
end
|
|
69
|
+
|
|
70
|
+
create_table :question_answers do |t|
|
|
71
|
+
t.integer :question_id
|
|
72
|
+
|
|
73
|
+
t.string :operation
|
|
74
|
+
|
|
75
|
+
t.date :date
|
|
76
|
+
t.date :date_begin
|
|
77
|
+
t.date :date_end
|
|
78
|
+
|
|
79
|
+
t.decimal :decimal
|
|
80
|
+
t.decimal :decimal_begin
|
|
81
|
+
t.decimal :decimal_end
|
|
82
|
+
|
|
83
|
+
t.string :email
|
|
84
|
+
|
|
85
|
+
t.integer :number
|
|
86
|
+
t.integer :number_begin
|
|
87
|
+
t.integer :number_end
|
|
88
|
+
|
|
89
|
+
t.integer :percentage
|
|
90
|
+
t.integer :percentage_begin
|
|
91
|
+
t.integer :percentage_end
|
|
92
|
+
|
|
93
|
+
t.integer :price
|
|
94
|
+
t.integer :price_begin
|
|
95
|
+
t.integer :price_end
|
|
96
|
+
|
|
97
|
+
t.text :long_answer
|
|
98
|
+
t.text :short_answer
|
|
99
|
+
|
|
100
|
+
t.timestamps
|
|
101
|
+
end
|
|
102
|
+
|
|
62
103
|
end
|
|
63
104
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: effective_questions
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Code and Effect
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-02-
|
|
11
|
+
date: 2026-02-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -177,8 +177,10 @@ files:
|
|
|
177
177
|
- app/assets/config/effective_questions_manifest.js
|
|
178
178
|
- app/assets/stylesheets/effective_questions.scss
|
|
179
179
|
- app/controllers/admin/questions_controller.rb
|
|
180
|
+
- app/controllers/admin/responses_controller.rb
|
|
180
181
|
- app/datatables/admin/effective_questionable_results_datatable.rb
|
|
181
182
|
- app/datatables/admin/effective_questions_datatable.rb
|
|
183
|
+
- app/datatables/admin/effective_responses_datatable.rb
|
|
182
184
|
- app/helpers/effective_questions_helper.rb
|
|
183
185
|
- app/models/concerns/acts_as_questionable.rb
|
|
184
186
|
- app/models/concerns/acts_as_responsable.rb
|