qwester 0.0.9 → 0.1.0
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.
- data/README.rdoc +51 -0
- data/app/controllers/qwester/application_controller.rb +1 -2
- data/app/controllers/qwester/questionnaires_controller.rb +1 -2
- data/app/models/qwester/presentation.rb +45 -0
- data/app/models/qwester/presentation_questionnaire.rb +8 -0
- data/app/models/qwester/questionnaire.rb +7 -0
- data/app/models/qwester/rule_set.rb +2 -2
- data/app/views/qwester/questionnaires/index.html.erb +3 -3
- data/db/migrate/20130315112847_create_qwester_presentations.rb +11 -0
- data/db/migrate/20130315113027_create_qwester_presentation_questionnaires.rb +10 -0
- data/db/migrate/20130318102537_add_presentation_to_rule_sets.rb +6 -0
- data/lib/active_admin/admin/answers.rb +1 -1
- data/lib/active_admin/admin/presentations.rb +51 -0
- data/lib/active_admin/admin/questionnaires.rb +2 -0
- data/lib/active_admin/admin/questions.rb +2 -0
- data/lib/active_admin/admin/rule_sets.rb +35 -0
- data/lib/qwester/version.rb +7 -1
- data/lib/rails/actionpack/lib/action_controller/base.rb +36 -3
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20130315113346_create_qwester_presentations.qwester.rb +12 -0
- data/test/dummy/db/migrate/20130315113347_create_qwester_presentation_questionnaires.qwester.rb +11 -0
- data/test/dummy/db/migrate/20130318123540_add_presentation_to_rule_sets.qwester.rb +7 -0
- data/test/dummy/db/schema.rb +20 -3
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +9021 -0
- data/test/dummy/log/test.log +146429 -0
- data/test/dummy/public/system/qwester/questionnaires/button_images/000/000/001/link/commend_button.png +0 -0
- data/test/dummy/public/system/qwester/questionnaires/button_images/000/000/001/original/commend_button.png +0 -0
- data/test/dummy/public/system/qwester/questionnaires/button_images/000/000/001/thumbnail/commend_button.png +0 -0
- data/test/dummy/public/system/qwester/questionnaires/button_images/000/000/002/link/commend_button.gif +0 -0
- data/test/dummy/public/system/qwester/questionnaires/button_images/000/000/002/original/commend_button.gif +0 -0
- data/test/dummy/public/system/qwester/questionnaires/button_images/000/000/002/thumbnail/commend_button.gif +0 -0
- data/test/dummy/test/fixtures/qwester/presentation_questionnaires.yml +3 -0
- data/test/dummy/test/fixtures/qwester/presentations.yml +13 -0
- data/test/dummy/test/functional/qwester/questionnaires_controller_test.rb +68 -3
- data/test/unit/qwester/presentation_test.rb +61 -0
- data/test/unit/qwester/questionnaire_test.rb +5 -1
- data/test/unit/qwester/rule_set_test.rb +12 -0
- metadata +32 -2
data/README.rdoc
CHANGED
@@ -133,6 +133,57 @@ to a resource either within or outside the app.
|
|
133
133
|
RuleSet uses array_logic[http://github.com/reggieb/array_logic] to manage
|
134
134
|
the logic used to compare each rule set with the array of answers.
|
135
135
|
|
136
|
+
== Presentation
|
137
|
+
|
138
|
+
Questionnaires can be grouped into Presentations, and these are used to
|
139
|
+
control which questionnaires are displayed (presented to the user) at
|
140
|
+
any time.
|
141
|
+
|
142
|
+
All questionnaires are display at the engine root unless:
|
143
|
+
|
144
|
+
* A presentation is set as 'default'
|
145
|
+
|
146
|
+
* An existing presentation's name is added to session[:presentations]
|
147
|
+
(an array)
|
148
|
+
|
149
|
+
=== Restricting the questionnaires displayed
|
150
|
+
|
151
|
+
If you do not want to display all the available questionnaires, create
|
152
|
+
a presentation, set it as 'default' and add to it the questionnaires you
|
153
|
+
wish to display.
|
154
|
+
|
155
|
+
=== Using a questionnaire to control access to other questionnaires
|
156
|
+
|
157
|
+
Say you have three presentations of questionnaires, and you want to display
|
158
|
+
one initially. Then you want to use the answers submitted from that
|
159
|
+
questionnaire, to control which of the other two sets of questionnaires are
|
160
|
+
displayed next.
|
161
|
+
|
162
|
+
To do this set the initial presentation as default. Then create two rule
|
163
|
+
sets, one for each of the other presentations. Update each rule set to
|
164
|
+
match the answer pattern that should be submitted for the associated
|
165
|
+
pattern to be displayed, and set rule_set#presentation to the name of
|
166
|
+
the presentation you wish displayed when the rule is matched.
|
167
|
+
|
168
|
+
Then when the first set of questionnaires are submitted, the rules will be
|
169
|
+
checked, and if one of the two rules sets matches the submitted answers,
|
170
|
+
the associated presentation's questionnaires will be displayed.
|
171
|
+
|
172
|
+
=== Simple rule matching for presentations
|
173
|
+
|
174
|
+
The rule matching is simple and if two presentation rules match, the system
|
175
|
+
will not try to work out which one it should display. It will just show the
|
176
|
+
last one it finds. So some care is required when setting up presentations
|
177
|
+
with matching rule sets to avoid overlaps and clashes.
|
178
|
+
|
179
|
+
=== Once only match
|
180
|
+
|
181
|
+
Once a presentation has been matched, it cannot be returned to later. That
|
182
|
+
is if there are two presentations: 'one' and 'two', you cannot have a work
|
183
|
+
flow that goes from one to two and then back to one, unless you reset or
|
184
|
+
otherwise manipulate session[:presentations]. Instead you should clone 'one'
|
185
|
+
as a new presentation e.g. 'three', and then go from one to two to three.
|
186
|
+
|
136
187
|
== Dummy
|
137
188
|
|
138
189
|
A test app is present within this engine, and provides an example of how
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Qwester
|
2
|
+
class Presentation < ActiveRecord::Base
|
3
|
+
attr_accessible :description, :name, :title, :questionnaire_ids, :default
|
4
|
+
|
5
|
+
has_many :presentation_questionnaires
|
6
|
+
|
7
|
+
has_many(
|
8
|
+
:questionnaires,
|
9
|
+
:through => :presentation_questionnaires
|
10
|
+
)
|
11
|
+
accepts_nested_attributes_for :questionnaires
|
12
|
+
|
13
|
+
before_save :before_save_tasks
|
14
|
+
after_save :after_save_tasks
|
15
|
+
|
16
|
+
validates(
|
17
|
+
:name,
|
18
|
+
:format => {
|
19
|
+
:with => /^\w+$/,
|
20
|
+
:message => "must comprise letters or numbers with underscores separating words"
|
21
|
+
},
|
22
|
+
:presence => true,
|
23
|
+
:uniqueness => true
|
24
|
+
)
|
25
|
+
|
26
|
+
private
|
27
|
+
def before_save_tasks
|
28
|
+
update_title_from_name
|
29
|
+
end
|
30
|
+
|
31
|
+
def after_save_tasks
|
32
|
+
undefault_others if self.default?
|
33
|
+
end
|
34
|
+
|
35
|
+
def undefault_others
|
36
|
+
current_defaults = self.class.find_all_by_default(true)
|
37
|
+
current_defaults.each{|p| p.update_attribute(:default, false) unless p == self}
|
38
|
+
end
|
39
|
+
|
40
|
+
def update_title_from_name
|
41
|
+
self.title = self.name.humanize unless self.title.present?
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -34,6 +34,13 @@ module Qwester
|
|
34
34
|
:join_table => :qwester_answer_stores_questionnaires,
|
35
35
|
:uniq => true
|
36
36
|
)
|
37
|
+
|
38
|
+
has_many :presentation_questionnaires
|
39
|
+
|
40
|
+
has_many(
|
41
|
+
:presentations,
|
42
|
+
:through => :presentation_questionnaires
|
43
|
+
)
|
37
44
|
|
38
45
|
validates :title, :presence => true
|
39
46
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'array_logic'
|
2
2
|
module Qwester
|
3
3
|
class RuleSet < ActiveRecord::Base
|
4
|
-
attr_accessible :title, :description, :answers, :url, :rule, :answer_ids, :link_text, :warning_id
|
4
|
+
attr_accessible :title, :description, :answers, :url, :rule, :answer_ids, :link_text, :warning_id, :presentation
|
5
5
|
|
6
6
|
before_save :keep_answers_in_step_with_rule
|
7
7
|
|
@@ -23,7 +23,7 @@ module Qwester
|
|
23
23
|
validate :check_rule_is_valid
|
24
24
|
|
25
25
|
validates :title, :presence => true
|
26
|
-
validates :url, :presence =>
|
26
|
+
validates :url, :presence => {:unless => :presentation?}
|
27
27
|
|
28
28
|
|
29
29
|
def self.matching(answers)
|
@@ -19,10 +19,10 @@
|
|
19
19
|
<% end %>
|
20
20
|
</div>
|
21
21
|
|
22
|
-
<% if @
|
22
|
+
<% if @qwester_rule_sets.present? %>
|
23
23
|
<h2>Matching rule sets</h2>
|
24
24
|
<ul>
|
25
|
-
<% @
|
25
|
+
<% @qwester_rule_sets.each do |rule_set| %>
|
26
26
|
<li>
|
27
27
|
<%= rule_set.title %>:
|
28
28
|
<%= link_to(rule_set.link_text, rule_set.url) %>
|
@@ -35,5 +35,5 @@
|
|
35
35
|
content_tag(
|
36
36
|
'p',
|
37
37
|
link_to('Clear answers and start again', reset_questionnaires_path)
|
38
|
-
) if @
|
38
|
+
) if @qwester_rule_sets.present?
|
39
39
|
%>
|
@@ -7,6 +7,7 @@ module Qwester
|
|
7
7
|
menu :parent => Qwester.active_admin_menu, :label => menu_label
|
8
8
|
|
9
9
|
actions :all, :except => [:edit]
|
10
|
+
config.batch_actions = false
|
10
11
|
|
11
12
|
index do
|
12
13
|
column :id
|
@@ -15,7 +16,6 @@ module Qwester
|
|
15
16
|
link_to(answer.question.title, edit_admin_qwester_question_path(answer.question)) if answer.question
|
16
17
|
end
|
17
18
|
column :position
|
18
|
-
column :cope_index
|
19
19
|
default_actions
|
20
20
|
end
|
21
21
|
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Qwester
|
2
|
+
ActiveAdmin.register Presentation do
|
3
|
+
|
4
|
+
menu_label = 'Presentations'
|
5
|
+
menu_label = "Qwester #{menu_label}" unless Qwester.active_admin_menu
|
6
|
+
menu :parent => Qwester.active_admin_menu, :label => menu_label
|
7
|
+
|
8
|
+
config.batch_actions = false
|
9
|
+
|
10
|
+
index do
|
11
|
+
column :name do |presentation|
|
12
|
+
link_to presentation.name, admin_qwester_presentation_path(presentation)
|
13
|
+
end
|
14
|
+
column :title
|
15
|
+
column :default do |presentation|
|
16
|
+
'default' if presentation.default?
|
17
|
+
end
|
18
|
+
column :questionnaires do |presentation|
|
19
|
+
presentation.questionnaires.collect(&:title).join(', ')
|
20
|
+
end
|
21
|
+
default_actions
|
22
|
+
end
|
23
|
+
|
24
|
+
show do
|
25
|
+
h2 qwester_presentation.title
|
26
|
+
qwester_presentation.questionnaires.each do |questionnaire|
|
27
|
+
div(:style => 'display:inline-block;margin-right:20px;') do
|
28
|
+
para image_tag(questionnaire.button_image.url(:thumbnail))
|
29
|
+
para questionnaire.title
|
30
|
+
end
|
31
|
+
end
|
32
|
+
para "Default: Will be inital presentation of quesitonnaires" if qwester_presentation.default?
|
33
|
+
end
|
34
|
+
|
35
|
+
form do |f|
|
36
|
+
f.inputs "Details" do
|
37
|
+
f.input :name
|
38
|
+
f.input :title, :label => "Title (or create from name)"
|
39
|
+
f.input :default, :label => 'Set as default (that is, the first presentation displayed to a user). If no default, all questionnaires will be displayed'
|
40
|
+
if defined?(Ckeditor)
|
41
|
+
f.input :description, :as => :ckeditor, :input_html => { :height => 100, :toolbar => 'Basic' }
|
42
|
+
else
|
43
|
+
f.input :description, :input_html => { :rows => 3}
|
44
|
+
end
|
45
|
+
f.input :questionnaires, :as => :check_boxes, :collection => Questionnaire.all
|
46
|
+
end
|
47
|
+
f.buttons
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -6,6 +6,8 @@ module Qwester
|
|
6
6
|
menu_label = "Qwester #{menu_label}" unless Qwester.active_admin_menu
|
7
7
|
menu :parent => Qwester.active_admin_menu, :label => menu_label
|
8
8
|
|
9
|
+
config.batch_actions = false
|
10
|
+
|
9
11
|
index do
|
10
12
|
column :image do |questionnaire|
|
11
13
|
image_tag(questionnaire.button_image.url(:thumbnail))
|
@@ -6,8 +6,11 @@ module Qwester
|
|
6
6
|
menu_label = "Qwester #{menu_label}" unless Qwester.active_admin_menu
|
7
7
|
menu :parent => Qwester.active_admin_menu, :label => menu_label
|
8
8
|
|
9
|
+
config.batch_actions = false
|
10
|
+
|
9
11
|
index do
|
10
12
|
column :title
|
13
|
+
column :presentation
|
11
14
|
column :answers do |rule_set|
|
12
15
|
rule_set.answers.count
|
13
16
|
end
|
@@ -57,6 +60,25 @@ module Qwester
|
|
57
60
|
|
58
61
|
end
|
59
62
|
|
63
|
+
sidebar :presentations do
|
64
|
+
para <<EOF
|
65
|
+
If a rule is assigned a presentation, that presentation's questionnaires will
|
66
|
+
be displayed when the rule is matched.
|
67
|
+
EOF
|
68
|
+
|
69
|
+
para <<EOF
|
70
|
+
There is no mechanism to handle multiple rules with presentations, being trigged
|
71
|
+
at the same time. The app will just display the questionnaires assigned to the
|
72
|
+
last rule_set.presentation it finds. So some care should be taken to avoid
|
73
|
+
clashes.
|
74
|
+
EOF
|
75
|
+
|
76
|
+
para <<EOF
|
77
|
+
A rule set with a presentation, will change the display. It will not display
|
78
|
+
an output tab, any url associated with the rule will be ignored.
|
79
|
+
EOF
|
80
|
+
end
|
81
|
+
|
60
82
|
form do |f|
|
61
83
|
f.inputs "Details" do
|
62
84
|
f.input :title
|
@@ -72,6 +94,10 @@ module Qwester
|
|
72
94
|
f.input :link_text
|
73
95
|
end
|
74
96
|
|
97
|
+
f.inputs "Change Presentation of Questionnaires" do
|
98
|
+
f.input :presentation, :as => :select, :collection => Presentation.all.collect(&:name), :include_blank => 'No effect on presentation'
|
99
|
+
end
|
100
|
+
|
75
101
|
f.inputs "Logic" do
|
76
102
|
f.input :rule, :input_html => { :rows => 3}
|
77
103
|
end
|
@@ -123,6 +149,15 @@ module Qwester
|
|
123
149
|
para qwester_rule_set.link_text? ? qwester_rule_set.link_text : 'No link text specified'
|
124
150
|
end
|
125
151
|
|
152
|
+
div do
|
153
|
+
h3 'Presentation'
|
154
|
+
if qwester_rule_set.presentation?
|
155
|
+
para "The presentations of questionnaires should change to: #{qwester_rule_set.presentation}"
|
156
|
+
else
|
157
|
+
para "The presentations of questionnaires should be unaffected by this rule"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
126
161
|
div do
|
127
162
|
h3 'The rule'
|
128
163
|
para qwester_rule_set.rule
|
data/lib/qwester/version.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
module Qwester
|
2
|
-
VERSION = "0.0
|
2
|
+
VERSION = "0.1.0"
|
3
3
|
end
|
4
4
|
|
5
5
|
# History
|
6
6
|
# =======
|
7
7
|
#
|
8
|
+
# 0.1.0 - Add presentations as a way of controlling the display of questionnaires
|
9
|
+
# Allows admin to define groups of questionnaires as presentation views
|
10
|
+
# and rule sets that will display a presentation when triggered. In that way
|
11
|
+
# the list of questionnaires being displayed can change as questionnaires are
|
12
|
+
# submitted.
|
13
|
+
#
|
8
14
|
# 0.0.9 - maintenance update
|
9
15
|
# Removes cope_index from migrations.
|
10
16
|
# Ensures answer_store#session_id is unique
|
@@ -33,13 +33,46 @@ module ActionController
|
|
33
33
|
@qwester_answer_store
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
36
|
+
def match_rule_sets
|
37
37
|
if get_qwester_answer_store
|
38
|
-
Qwester::RuleSet.matching(@qwester_answer_store.answers)
|
38
|
+
@qwester_rule_sets = Qwester::RuleSet.matching(@qwester_answer_store.answers)
|
39
|
+
get_presentation_from_rule_sets
|
40
|
+
return @qwester_rule_sets
|
41
|
+
end
|
42
|
+
end
|
43
|
+
alias_method :matching_rule_sets, :match_rule_sets
|
44
|
+
|
45
|
+
def current_questionnaires
|
46
|
+
match_rule_sets
|
47
|
+
presentation_questionnaires || default_presentation_questionnaires || Qwester::Questionnaire.all
|
48
|
+
end
|
49
|
+
|
50
|
+
def presentation_questionnaires
|
51
|
+
presentation = Qwester::Presentation.find_by_name(session[:presentations].last) if session[:presentations]
|
52
|
+
presentation.questionnaires if presentation
|
53
|
+
end
|
54
|
+
|
55
|
+
def default_presentation_questionnaires
|
56
|
+
presentation = Qwester::Presentation.find_by_default(true)
|
57
|
+
presentation.questionnaires if presentation
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_presentation_from_rule_sets
|
61
|
+
@qwester_rule_sets.clone.each do |rule_set|
|
62
|
+
next unless rule_set.presentation?
|
63
|
+
add_presentation_to_session rule_set.presentation
|
64
|
+
@qwester_rule_sets.delete(rule_set)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def add_presentation_to_session(presentation)
|
69
|
+
session_presentations = session[:presentations] || []
|
70
|
+
unless session_presentations.include? presentation
|
71
|
+
session_presentations << presentation
|
72
|
+
session[:presentations] = session_presentations
|
39
73
|
end
|
40
74
|
end
|
41
75
|
|
42
|
-
# private
|
43
76
|
def add_answers_to_qwester_answer_store
|
44
77
|
answers = params[:question_id].values.collect do |question_values|
|
45
78
|
question_values[:answer_ids].collect{|id| Qwester::Answer.find(id)}
|
Binary file
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# This migration comes from qwester (originally 20130315112847)
|
2
|
+
class CreateQwesterPresentations < ActiveRecord::Migration
|
3
|
+
def change
|
4
|
+
create_table :qwester_presentations do |t|
|
5
|
+
t.string :name
|
6
|
+
t.string :title
|
7
|
+
t.text :description
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/test/dummy/db/migrate/20130315113347_create_qwester_presentation_questionnaires.qwester.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# This migration comes from qwester (originally 20130315113027)
|
2
|
+
class CreateQwesterPresentationQuestionnaires < ActiveRecord::Migration
|
3
|
+
def change
|
4
|
+
create_table :qwester_presentation_questionnaires do |t|
|
5
|
+
t.integer :questionnaire_id
|
6
|
+
t.integer :presentation_id
|
7
|
+
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/test/dummy/db/schema.rb
CHANGED
@@ -11,7 +11,7 @@
|
|
11
11
|
#
|
12
12
|
# It's strongly recommended to check this file into your version control system.
|
13
13
|
|
14
|
-
ActiveRecord::Schema.define(:version =>
|
14
|
+
ActiveRecord::Schema.define(:version => 20130318123540) do
|
15
15
|
|
16
16
|
create_table "active_admin_comments", :force => true do |t|
|
17
17
|
t.string "resource_id", :null => false
|
@@ -91,6 +91,22 @@ ActiveRecord::Schema.define(:version => 20130314103662) do
|
|
91
91
|
add_index "qwester_ckeditor_assets", ["assetable_type", "assetable_id"], :name => "qwester_idx_ckeditor_assetable"
|
92
92
|
add_index "qwester_ckeditor_assets", ["assetable_type", "type", "assetable_id"], :name => "qwester_idx_ckeditor_assetable_type"
|
93
93
|
|
94
|
+
create_table "qwester_presentation_questionnaires", :force => true do |t|
|
95
|
+
t.integer "questionnaire_id"
|
96
|
+
t.integer "presentation_id"
|
97
|
+
t.datetime "created_at", :null => false
|
98
|
+
t.datetime "updated_at", :null => false
|
99
|
+
end
|
100
|
+
|
101
|
+
create_table "qwester_presentations", :force => true do |t|
|
102
|
+
t.string "name"
|
103
|
+
t.string "title"
|
104
|
+
t.text "description"
|
105
|
+
t.datetime "created_at", :null => false
|
106
|
+
t.datetime "updated_at", :null => false
|
107
|
+
t.boolean "default"
|
108
|
+
end
|
109
|
+
|
94
110
|
create_table "qwester_questionnaires", :force => true do |t|
|
95
111
|
t.string "title"
|
96
112
|
t.text "description"
|
@@ -127,10 +143,11 @@ ActiveRecord::Schema.define(:version => 20130314103662) do
|
|
127
143
|
t.string "title"
|
128
144
|
t.text "description"
|
129
145
|
t.string "url"
|
130
|
-
t.datetime "created_at",
|
131
|
-
t.datetime "updated_at",
|
146
|
+
t.datetime "created_at", :null => false
|
147
|
+
t.datetime "updated_at", :null => false
|
132
148
|
t.text "rule"
|
133
149
|
t.string "link_text"
|
150
|
+
t.string "presentation"
|
134
151
|
end
|
135
152
|
|
136
153
|
end
|
data/test/dummy/db/test.sqlite3
CHANGED
Binary file
|