├── .gitignore
├── Gemfile
├── MIT-LICENSE
├── README.rdoc
├── Rakefile
├── app
├── assets
│ ├── images
│ │ └── qwester
│ │ │ └── .gitkeep
│ ├── javascripts
│ │ └── qwester
│ │ │ └── application.js
│ └── stylesheets
│ │ └── qwester
│ │ └── application.css
├── controllers
│ └── qwester
│ │ ├── application_controller.rb
│ │ └── questionnaires_controller.rb
├── helpers
│ └── qwester
│ │ ├── application_helper.rb
│ │ └── questionnaires_helper.rb
├── models
│ └── qwester
│ │ ├── answer.rb
│ │ ├── answer_store.rb
│ │ ├── presentation.rb
│ │ ├── presentation_questionnaire.rb
│ │ ├── question.rb
│ │ ├── questionnaire.rb
│ │ ├── questionnaires_question.rb
│ │ └── rule_set.rb
└── views
│ ├── layouts
│ └── qwester
│ │ └── application.html.erb
│ └── qwester
│ └── questionnaires
│ ├── _errors.html.erb
│ ├── index.html.erb
│ └── show.html.erb
├── config
└── routes.rb
├── db
└── migrate
│ ├── 20121008151526_create_questions.rb
│ ├── 20121008152106_create_answers.rb
│ ├── 20121008153758_create_rule_sets.rb
│ ├── 20121009080219_create_questionnaires.rb
│ ├── 20121009095600_create_answer_stores.rb
│ ├── 20121009160807_add_questionnaire_id_to_answers.rb
│ ├── 20121009161206_change_answers_value_to_string.rb
│ ├── 20121019111051_add_button_image_to_questionnaires.rb
│ ├── 20121114084347_create_ckeditor_assets.rb
│ ├── 20121115114408_add_ref_to_questions.rb
│ ├── 20121120092108_add_ids_to_questionnaires_questions.rb
│ ├── 20121122130930_add_position_to_answers.rb
│ ├── 20121122141628_remove_questionnaire_from_answer.rb
│ ├── 20121126152146_add_rule_to_rule_sets.rb
│ ├── 20121203150555_add_multi_answer_to_questions.rb
│ ├── 20121204082213_create_answer_stores_questionnaires.rb
│ ├── 20121204100803_add_link_text_to_rule_sets.rb
│ ├── 20130306114331_add_preserved_to_answer_stores.rb
│ ├── 20130315112847_create_qwester_presentations.rb
│ ├── 20130315113027_create_qwester_presentation_questionnaires.rb
│ ├── 20130318102537_add_presentation_to_rule_sets.rb
│ ├── 20130402074240_add_weighting_to_qwester_answers.rb
│ ├── 20130502082540_add_position_to_qwester_presentation_questionnaires.rb
│ └── 20131119142009_add_must_complete_to_qwester_questionnaires.rb
├── lib
├── active_admin
│ └── admin
│ │ ├── answers.rb
│ │ ├── presentations.rb
│ │ ├── questionnaires.rb
│ │ ├── questions.rb
│ │ └── rule_sets.rb
├── qwester.rb
├── qwester
│ ├── engine.rb
│ └── version.rb
├── rails
│ └── actionpack
│ │ └── lib
│ │ └── action_controller
│ │ └── base.rb
├── random_string.rb
└── tasks
│ └── qwester_tasks.rake
├── qwester.gemspec
├── script
└── rails
└── test
├── dummy
├── README.rdoc
├── Rakefile
├── app
│ ├── admin
│ │ ├── admin_user.rb
│ │ └── dashboard.rb
│ ├── assets
│ │ ├── javascripts
│ │ │ ├── active_admin.js
│ │ │ ├── application.js
│ │ │ └── questionnaires.js
│ │ └── stylesheets
│ │ │ ├── active_admin.css.scss
│ │ │ ├── application.css
│ │ │ └── questionnaires.css.scss
│ ├── controllers
│ │ └── application_controller.rb
│ ├── helpers
│ │ └── application_helper.rb
│ ├── mailers
│ │ └── .gitkeep
│ ├── models
│ │ ├── .gitkeep
│ │ └── admin_user.rb
│ └── views
│ │ └── layouts
│ │ └── application.html.erb
├── config.ru
├── config
│ ├── application.rb
│ ├── boot.rb
│ ├── database.yml
│ ├── environment.rb
│ ├── environments
│ │ ├── development.rb
│ │ ├── production.rb
│ │ └── test.rb
│ ├── initializers
│ │ ├── active_admin.rb
│ │ ├── backtrace_silencers.rb
│ │ ├── devise.rb
│ │ ├── inflections.rb
│ │ ├── mime_types.rb
│ │ ├── qwester.rb
│ │ ├── secret_token.rb
│ │ ├── session_store.rb
│ │ └── wrap_parameters.rb
│ ├── locales
│ │ ├── devise.en.yml
│ │ └── en.yml
│ └── routes.rb
├── db
│ ├── migrate
│ │ ├── 20130110115938_devise_create_admin_users.rb
│ │ ├── 20130110115940_create_admin_comments.rb
│ │ ├── 20130314103645_create_questions.qwester.rb
│ │ ├── 20130314103646_create_answers.qwester.rb
│ │ ├── 20130314103647_create_rule_sets.qwester.rb
│ │ ├── 20130314103648_create_questionnaires.qwester.rb
│ │ ├── 20130314103649_create_answer_stores.qwester.rb
│ │ ├── 20130314103650_add_questionnaire_id_to_answers.qwester.rb
│ │ ├── 20130314103651_change_answers_value_to_string.qwester.rb
│ │ ├── 20130314103652_add_button_image_to_questionnaires.qwester.rb
│ │ ├── 20130314103653_create_ckeditor_assets.qwester.rb
│ │ ├── 20130314103654_add_ref_to_questions.qwester.rb
│ │ ├── 20130314103655_add_ids_to_questionnaires_questions.qwester.rb
│ │ ├── 20130314103656_add_position_to_answers.qwester.rb
│ │ ├── 20130314103657_remove_questionnaire_from_answer.qwester.rb
│ │ ├── 20130314103658_add_rule_to_rule_sets.qwester.rb
│ │ ├── 20130314103659_add_multi_answer_to_questions.qwester.rb
│ │ ├── 20130314103660_create_answer_stores_questionnaires.qwester.rb
│ │ ├── 20130314103661_add_link_text_to_rule_sets.qwester.rb
│ │ ├── 20130314103662_add_preserved_to_answer_stores.qwester.rb
│ │ ├── 20130315113346_create_qwester_presentations.qwester.rb
│ │ ├── 20130315113347_create_qwester_presentation_questionnaires.qwester.rb
│ │ ├── 20130402085423_add_presentation_to_rule_sets.qwester.rb
│ │ ├── 20130402085424_add_weighting_to_qwester_answers.qwester.rb
│ │ ├── 20130502082731_add_position_to_qwester_presentation_questionnaires.qwester.rb
│ │ └── 20131119142050_add_must_complete_to_qwester_questionnaires.qwester.rb
│ ├── schema.rb
│ ├── seeds.rb
│ └── seeds
│ │ └── questions.yml
├── lib
│ └── assets
│ │ └── .gitkeep
├── log
│ └── .gitkeep
├── public
│ ├── 404.html
│ ├── 422.html
│ ├── 500.html
│ └── favicon.ico
├── script
│ └── rails
└── test
│ ├── fixtures
│ ├── admin_users.yml
│ └── qwester
│ │ ├── answer_stores.yml
│ │ ├── answers.yml
│ │ ├── presentation_questionnaires.yml
│ │ ├── presentations.yml
│ │ ├── questionnaires.yml
│ │ ├── questionnaires_questions.yml
│ │ ├── questions.yml
│ │ └── rule_sets.yml
│ ├── functional
│ └── qwester
│ │ └── questionnaires_controller_test.rb
│ ├── test_helper.rb
│ └── unit
│ ├── admin_user_test.rb
│ └── helpers
│ └── questionnaires_helper_test.rb
├── integration
└── navigation_test.rb
├── test_helper.rb
└── unit
├── qwester
├── answer_store_test.rb
├── answer_test.rb
├── presentation_questionnaire_test.rb
├── presentation_test.rb
├── question_test.rb
├── questionnaire_test.rb
├── questionnaires_question_test.rb
└── rule_set_test.rb
└── qwester_test.rb
/.gitignore:
--------------------------------------------------------------------------------
1 | .bundle/
2 | log/*.log
3 | pkg/
4 | test/dummy/db/*.sqlite3
5 | test/dummy/log/*.log
6 | test/dummy/tmp/
7 | test/dummy/.sass-cache
8 | test/dummy/public/system/*
9 | .rvmrc
10 | .ruby-*
11 | *.gem
12 | Gemfile.lock
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "http://rubygems.org"
2 |
3 | # Declare your gem's dependencies in qwester.gemspec.
4 | # Bundler will treat runtime dependencies like base dependencies, and
5 | # development dependencies will be added by default to the :development group.
6 | gemspec
7 |
8 | # jquery-rails is used by the dummy application
9 | #gem "jquery-rails"
10 |
11 | # Declare any dependencies that are still in development here instead of in
12 | # your gemspec. These might include edge Rails or gems from your path or
13 | # Git. Remember to move these dependencies to your gemspec before releasing
14 | # your gem to rubygems.org.
15 |
16 | # To use debugger
17 | # gem 'debugger'
18 |
19 |
20 |
21 | # I can't get activeadmin and jquery (which it needs) to work in
22 | # the test/dummy environment without these gem declarations.
23 |
24 | gem 'activeadmin'
25 | gem 'bourbon'
26 | group :assets do
27 | gem 'coffee-script'
28 | gem 'jquery-rails'
29 | # See https://github.com/sstephenson/execjs#readme for more supported runtimes
30 | gem 'therubyracer', '0.10.2', :platforms => :ruby
31 | end
32 |
33 |
--------------------------------------------------------------------------------
/MIT-LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2013 Rob Nichols
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.
21 |
--------------------------------------------------------------------------------
/README.rdoc:
--------------------------------------------------------------------------------
1 | {
}[https://codeclimate.com/github/reggieb/qwester]
2 | = Qwester
3 |
4 | A rails engine used to add questionnaires to rails applications
5 |
6 | == Installation
7 |
8 | Add this to your Gemfile
9 |
10 | gem 'qwester'
11 |
12 | === Migrations
13 |
14 | Qwester includes a set of migrations to build the database tables to match
15 | qwester's models. To use these migrations within the host application, run
16 | this rake task:
17 |
18 | rake qwester:install:migrations
19 |
20 | This will copy the migrations to the host application's db/migrate folder.
21 | They will then be run next time the db:migrate task is run:
22 |
23 | rake db:migrate
24 |
25 | If you only wish to run the qwester migrations use a scope option:
26 |
27 | rake db:migrate SCOPE=qwester
28 |
29 | === Mounting the engine
30 |
31 | To mount qwester within your rails application, add this to config/routes.rb:
32 |
33 | mount Qwester::Engine => "/questionnaires"
34 |
35 | == Questionnaire
36 |
37 | To create a new questionnaire, first create a set of questions that you
38 | wish to appear within the questionnaire. Then create a questionnaire and
39 | associate the questions with that questionnaire. Questions can be used in
40 | multiple questionnaires, and can be ordered within each questionnaire. That
41 | is, the first question in one questionnaire, can be displayed as the second
42 | question in another questionnaire.
43 |
44 | === Questions and Answers
45 |
46 | Each question has a number of answers associated with it. The default set of
47 | answers is given by:
48 |
49 | Qwester::Answer.standard_values
50 |
51 | However, these can be modified and added to as you require. That is, each
52 | question has a unique set of answers that can be modified as required.
53 |
54 | === Answer selection list helper
55 |
56 | The helper method qwester_answers_selection_list will output a set of form
57 | elements matching the answers for the given question, as an unordered list.
58 | The form elements will be radio buttons unless the question is marked as
59 | 'multi-answer', in which case check boxes will be used.
60 |
61 | <%= qwester_answers_selection_list(question) %>
62 |
63 | The controller method update_qwester_answer_store can be used to manage the
64 | data submitted from these form elements. It will add the answers to the
65 | current answer store.
66 |
67 | === Answer store
68 |
69 | Submitted answers are stored in an AnswerStore object. On creation, each
70 | answer_store is assigned a session_id that can then be used within session,
71 | to identify the current user's answer_store. In this way, questionnaire
72 | submissions can be tracked across multiple submissions.
73 |
74 | By default the current answer_store.session_id is stored in
75 | session[:qwester_answer_store]. If you wish to use a different session key,
76 | set Qwester.session_key in the qwester initializer:
77 |
78 | Qwester.session_key = :your_preferred_key
79 |
80 | === Preservation
81 |
82 | To preserve an answer store, call its preserve method:
83 |
84 | preserved_answer_store = answer_store.preserve
85 |
86 | This will create a copy of the original answer_store. This copy will have its
87 | own unique session_id. This session_id can then be used restore the answer_store
88 | at a later date. The answer_store#preserved field stores the datetime
89 | when it was preserved.
90 |
91 | preserved_answer_store.preserved? == true
92 | preserved_answer_store.preserved --> datetime of preservation
93 |
94 | The answers and questionnaires are copied over to the preserved answers store
95 |
96 | answer_store.questionnaires == preserved_answer_store.questionnaires
97 | answer_store.answers == preserved_answer_store.answers
98 |
99 | Note that it is the answer store copy that is preserved, and not the original
100 |
101 | answer_store.preserved? == false
102 |
103 | A preserved answer store therefore acts as a snap shot of an answer_store.
104 |
105 | === Restoration
106 |
107 | Restoring a preserved answer_store, creates a new copy of the answer store. This
108 | restored copy can then be used without alteration of the preserved snap shot.
109 | The restored copy will also have its own session_id.
110 |
111 | restored_answer_store = preserved_answer_store.restore
112 | restored_answer_store.preserved? == false
113 | restored_answer_store.questionnaires == preserved_answer_store.questionnaires
114 | restored_answer_store.answers == preserved_answer_store.answers
115 |
116 | === Clean up answer stores
117 |
118 | A rake task is available that will remove all the unpreserved answer stores that
119 | are more than a day old.
120 |
121 | rake qwester:destroy_unpreserved_answer_stores RAILS_ENV=production
122 |
123 | === Rule set
124 |
125 | Groups of answers can be matched to rule sets using:
126 |
127 | RuleSet.matching(answers)
128 |
129 | which will return an array of rule sets that match those answers.
130 |
131 | Each rule set has an url associated with it, and this url should lead a user
132 | to a resource either within or outside the app.
133 |
134 | RuleSet uses array_logic[http://github.com/reggieb/array_logic] to manage
135 | the logic used to compare each rule set with the array of answers.
136 |
137 | == Presentation
138 |
139 | Questionnaires can be grouped into Presentations, and these are used to
140 | control which questionnaires are displayed (presented to the user) at
141 | any time.
142 |
143 | All questionnaires are display at the engine root unless:
144 |
145 | * A presentation is set as 'default'
146 |
147 | * An existing presentation's name is added to session[:presentations] (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 |
187 | == Answer weighting
188 |
189 | Answers have a weighting field (float) to give selected answers more weight
190 | when comparing answers. You can also define an alias for this field, to give
191 | it a name that is more appropriate to your application.
192 |
193 | For example, you want to use qwester to create a multiple choice test, and each
194 | answer needs to be assigned a 'score'. First you will need to assign :score as
195 | the weighting alias. In an initializer add this:
196 |
197 | Qwester::Answer.weighting_alias = :score
198 |
199 | This will add a 'score' instance method to Answers, that will return the
200 | weighting for that answer.
201 |
202 | Then apply a score/weighting to each correct answer in the database.
203 |
204 | You can then set up a rule to work with the score method. For example:
205 |
206 | rule_set.rule = 'sum(:score) >= 10'
207 |
208 | See array_logic[http://github.com/reggieb/array_logic] for a list of functions
209 | available.
210 |
211 | The default value of weighting is zero.
212 |
213 | == Dummy
214 |
215 | A test app is present within this engine, and provides an example of how
216 | Qwester can be used within a Rails app. See test/dummy.
217 |
218 | However, look at the notes in Gemfile. You may need to uncomment two gem
219 | declarations in the gemfile, before jquery and active_admin work correctly in
220 | the test/dummy environment.
221 |
222 | == Testing
223 |
224 | Note that the test datebase is not updated when running the root tests.
225 |
226 | To create the test database run the following at test/dummy
227 |
228 | rake db:schema:load RAILS_ENV=test
229 |
230 | To keep the test database in step with new migrations, at test/dummy run
231 |
232 | rake db:migrate RAILS_ENV=test
233 |
234 | To run all the tests, run rake test at the engine root.
235 |
236 | == Integration with ActiveAdmin
237 |
238 | Qwester contains a set of ActiveAdmin register files, that allow Qwester
239 | models to be managed from within the parent app's active_admin space. Of course
240 | ActiveAdmin needs to be installed and working in the parent rails application,
241 | for this to work.
242 |
243 | To use the Qwester ActiveAdmin register files, add this to the active_admin
244 | initializer in your application.
245 |
246 | config.load_paths << Qwester.active_admin_load_path
247 |
248 | See test/dummy/config/initializers/active_admin.rb for an example
249 |
250 | === Local modifications of qwester active admin pages
251 | If you wish to over-ride some of Qwester's active admin registers you will
252 | need to reorder the active_admin load_paths. In this case, use this form of
253 | the load_paths declaration:
254 |
255 | config.load_paths = [Qwester.active_admin_load_path] + config.load_paths
256 |
257 | One side-effect of this that I have been unable to solve, is that if you modify
258 | an over-riding register file while the app is running, the load order is altered
259 | and the qwester register file over-rides the local app's register file until the
260 | app is restarted. Therefore, you have to restart the app before modifications
261 | to over-riding register files take effect. In practice this only affects the
262 | development environment, as in both test and production the app is restarted
263 | after a change.
264 |
265 | === Active admin menus
266 | Links to the admin pages for Qwester models will appear in a 'Qwester' sub-menu.
267 | If you wish to change the name of the menu parent group, add this to an
268 | initializer:
269 |
270 | Qwester.active_admin_menu = 'menu name'
271 |
272 | Alternatively, if you want the Qwester models not to be grouped add this to an
273 | initializer:
274 |
275 | Qwester.active_admin_menu = 'none'
276 |
277 | See test/dummy/config/initializers/qwester.rb for an example
278 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
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 = 'Qwester'
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("../test/dummy/Rakefile", __FILE__)
24 | load 'rails/tasks/engine.rake'
25 |
26 |
27 |
28 | Bundler::GemHelper.install_tasks
29 |
30 | require 'rake/testtask'
31 |
32 | Rake::TestTask.new(:test) do |t|
33 | t.libs << 'lib'
34 | t.libs << 'test'
35 | t.pattern = 'test/**/*_test.rb'
36 | t.verbose = false
37 | end
38 |
39 |
40 | task :default => :test
41 |
--------------------------------------------------------------------------------
/app/assets/images/qwester/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reggieb/qwester/458690e814c83405edb32404eb45b06dc5fc8f59/app/assets/images/qwester/.gitkeep
--------------------------------------------------------------------------------
/app/assets/javascripts/qwester/application.js:
--------------------------------------------------------------------------------
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 .
16 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/qwester/application.css:
--------------------------------------------------------------------------------
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 | */
14 |
--------------------------------------------------------------------------------
/app/controllers/qwester/application_controller.rb:
--------------------------------------------------------------------------------
1 | module Qwester
2 | class ApplicationController < ActionController::Base
3 |
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/app/controllers/qwester/questionnaires_controller.rb:
--------------------------------------------------------------------------------
1 | module Qwester
2 | class QuestionnairesController < ApplicationController
3 |
4 | def index
5 | @questionnaires = current_questionnaires
6 | end
7 |
8 | def show
9 | @questionnaire = Qwester::Questionnaire.find(params[:id])
10 | end
11 |
12 | def update
13 | @questionnaire = Qwester::Questionnaire.find(params[:id])
14 | update_qwester_answer_store
15 | if @questionnaire.errors.empty?
16 | redirect_to questionnaires_path
17 | else
18 | render :show
19 | end
20 | end
21 |
22 | def reset
23 | get_qwester_answer_store
24 | @qwester_answer_store.reset
25 | redirect_to questionnaires_path
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/app/helpers/qwester/application_helper.rb:
--------------------------------------------------------------------------------
1 | module Qwester
2 | module ApplicationHelper
3 |
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/app/helpers/qwester/questionnaires_helper.rb:
--------------------------------------------------------------------------------
1 | module Qwester
2 | module QuestionnairesHelper
3 | def qwester_answers_selection_list(question, list_class = 'qwester_options')
4 | button_name = "question_id[#{question.id}][answer_ids][]"
5 | answers = question.answers
6 | buttons = answers.collect do |answer|
7 | if question.multi_answer?
8 | check_box_id = "question_id[#{question.id}][answer_ids][#{answer.id}]"
9 | button = check_box_tag(
10 | check_box_id,
11 | answer.id,
12 | answer_checked(answer),
13 | name: button_name
14 | )
15 | else
16 | button = radio_button_tag(button_name, answer.id, answer_checked(answer))
17 | end
18 | id = button.match(/id=\"(\w+)\"/)[1]
19 | text = label_tag(id, answer.value)
20 | content_tag('li', "#{button}#{text}".html_safe)
21 | end
22 | content_tag('ul', buttons.join.html_safe, :class => list_class)
23 | end
24 |
25 | def answer_checked(answer)
26 | answer_store_answers.include?(answer) || params_includes_answer(answer)
27 | end
28 |
29 | def answer_store_answers
30 | answer_store = get_qwester_answer_store
31 | answer_store ? answer_store.answers : []
32 | end
33 |
34 | # params should be of form: "question_id"=>{"1"=>{"answer_ids"=>["1"]}}
35 | def params_includes_answer(answer)
36 | question_ids = params[:question_id]
37 | return nil unless question_ids.kind_of? Hash
38 | answers = question_ids[answer.question_id.to_s]
39 | return nil unless answers.kind_of? Hash
40 | answers.values.flatten.include?(answer.id.to_s)
41 | end
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/app/models/qwester/answer.rb:
--------------------------------------------------------------------------------
1 | module Qwester
2 | class Answer < ActiveRecord::Base
3 | if Qwester.rails_three?
4 | attr_accessible :value, :question_id, :position, :weighting
5 | end
6 |
7 |
8 | DEFAULT_VALUE = 'Not applicable'
9 | STANDARD_VALUES = ['Yes', 'No', DEFAULT_VALUE]
10 |
11 | has_and_belongs_to_many(
12 | :rule_sets,
13 | :join_table => :qwester_answers_rule_sets
14 | )
15 |
16 | has_and_belongs_to_many(
17 | :answer_stores,
18 | :join_table => :qwester_answer_stores_answers
19 | )
20 |
21 | belongs_to :question
22 |
23 | acts_as_list :scope => :question
24 |
25 | validates :value, :presence => true
26 |
27 | def self.find_first_or_create(attributes)
28 | where(attributes).first || create(attributes)
29 | end
30 |
31 | def self.standard_values
32 | STANDARD_VALUES
33 | end
34 |
35 | def self.default_value
36 | DEFAULT_VALUE
37 | end
38 |
39 | def self.rule_label_prefix
40 | @rule_label_prefix ||= 'a'
41 | end
42 |
43 | def self.weighting_alias
44 | @weighting_alias
45 | end
46 |
47 | def self.weighting_alias=(name)
48 | if name
49 | @weighting_alias = name
50 | define_method(name.to_sym) {send(:weighting)}
51 | else
52 | remove_weighting_alias
53 | end
54 | end
55 |
56 | def self.weighting_alias_name
57 | name = weighting_alias || :weighting
58 | name.to_s
59 | end
60 |
61 | def self.remove_weighting_alias
62 | if weighting_alias
63 | remove_method weighting_alias.to_sym
64 | @weighting_alias = nil
65 | end
66 | end
67 |
68 | def rule_label
69 | "#{self.class.rule_label_prefix}#{self.id}"
70 | end
71 | end
72 | end
--------------------------------------------------------------------------------
/app/models/qwester/answer_store.rb:
--------------------------------------------------------------------------------
1 | module Qwester
2 | class AnswerStore < ActiveRecord::Base
3 | if Qwester.rails_three?
4 | attr_accessible
5 | end
6 |
7 | has_and_belongs_to_many(
8 | :answers,
9 | :class_name => 'Qwester::Answer',
10 | :join_table => :qwester_answer_stores_answers,
11 | :uniq => true
12 | )
13 | has_and_belongs_to_many(
14 | :questionnaires,
15 | :class_name => 'Qwester::Questionnaire',
16 | :join_table => :qwester_answer_stores_questionnaires,
17 | :uniq => true
18 | )
19 |
20 | before_save :generate_session_id
21 |
22 | def self.destroy_unpreserved
23 | where("updated_at < '#{1.day.ago.to_s(:db)}' AND preserved IS NULL").destroy_all
24 | end
25 |
26 | def reset
27 | answers.clear
28 | questionnaires.clear
29 | end
30 |
31 | def to_param
32 | session_id
33 | end
34 |
35 | def preserve
36 | make_copy({:preserved => Time.now}, :without_protection => true)
37 | end
38 |
39 | def restore
40 | make_copy
41 | end
42 |
43 | def completed_questionnaires
44 | questionnaires.select{|q| (q.questions.collect(&:id) - completed_question_ids).empty?}
45 | end
46 |
47 | private
48 |
49 | def completed_question_ids
50 | answers.collect(&:question_id)
51 | end
52 |
53 | def generate_session_id
54 | if !self.session_id or self.session_id.empty?
55 | self.session_id = session_id_not_in_database
56 | end
57 | end
58 |
59 | def make_copy(*args)
60 | copy = self.class.create(*args)
61 | copy.answers = answers
62 | copy.questionnaires = questionnaires
63 | return copy if copy.save
64 | end
65 |
66 | def session_id_not_in_database
67 | session_ids = get_session_ids
68 | random_string = RandomString.new(15) until random_string and !session_ids.include?(random_string)
69 | return random_string
70 | end
71 |
72 | def get_session_ids
73 | self.class.select(:session_id).collect(&:session_id)
74 | end
75 | end
76 | end
77 |
--------------------------------------------------------------------------------
/app/models/qwester/presentation.rb:
--------------------------------------------------------------------------------
1 | module Qwester
2 | class Presentation < ActiveRecord::Base
3 | if Qwester.rails_three?
4 | attr_accessible :description, :name, :title, :questionnaire_ids, :default
5 | end
6 |
7 | has_many(
8 | :presentation_questionnaires,
9 | :order => 'position'
10 | )
11 |
12 | has_many(
13 | :questionnaires,
14 | :through => :presentation_questionnaires,
15 | :uniq => true,
16 | :order => 'position'
17 | )
18 | accepts_nested_attributes_for :questionnaires
19 |
20 | before_save :before_save_tasks
21 | after_save :after_save_tasks
22 |
23 | validates(
24 | :name,
25 | :format => {
26 | :with => /\A\w+\z/,
27 | :message => "must comprise letters or numbers with underscores separating words"
28 | },
29 | :presence => true,
30 | :uniqueness => true
31 | )
32 |
33 | private
34 | def before_save_tasks
35 | update_title_from_name
36 | end
37 |
38 | def after_save_tasks
39 | undefault_others if self.default?
40 | end
41 |
42 | def undefault_others
43 | current_defaults = self.class.find_all_by_default(true)
44 | current_defaults.each{|p| p.update_attribute(:default, false) unless p == self}
45 | end
46 |
47 | def update_title_from_name
48 | self.title = self.name.humanize unless self.title.present?
49 | end
50 |
51 | def method_missing(symbol, *args, &block)
52 | if symbol.to_sym == :position || acts_as_list_method?(symbol)
53 | pass_acts_as_list_method_to(presentation_questionnaires, symbol, args.first)
54 | else
55 | super
56 | end
57 | end
58 |
59 | # Allows acts_as_list methods to be used within the questionnaire.
60 | #
61 | # Usage:
62 | #
63 | # questionnaire.move_to_top(question)
64 | # questionnaire.last?(question)
65 | #
66 | def pass_acts_as_list_method_to(presentation_questionnaires, symbol, questionnaire)
67 | raise "A Questionnaire is needed to identify the PresentationQuesti" unless questionnaire.kind_of? Questionnaire
68 | presentation_questionnaire = presentation_questionnaires.where(:questionnaire_id => questionnaire.id).first
69 | presentation_questionnaire.send(symbol) if presentation_questionnaire
70 | end
71 |
72 | def acts_as_list_method?(symbol)
73 | methods = ActiveRecord::Acts::List::InstanceMethods.instance_methods + ActiveRecord::Acts::List::InstanceMethods.private_instance_methods
74 | methods.include?(symbol.to_sym)
75 | end
76 |
77 | end
78 | end
79 |
--------------------------------------------------------------------------------
/app/models/qwester/presentation_questionnaire.rb:
--------------------------------------------------------------------------------
1 | module Qwester
2 | class PresentationQuestionnaire < ActiveRecord::Base
3 | if Qwester.rails_three?
4 | attr_accessible :presentation_id, :questionnaire_id
5 | end
6 |
7 | belongs_to :presentation
8 | belongs_to :questionnaire
9 |
10 | acts_as_list :scope => :presentation
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/app/models/qwester/question.rb:
--------------------------------------------------------------------------------
1 | module Qwester
2 | class Question < ActiveRecord::Base
3 | if Qwester.rails_three?
4 | attr_accessible :title, :description, :ref, :answers_attributes, :multi_answer
5 | end
6 |
7 | has_many(
8 | :answers,
9 | :order => 'position',
10 | :dependent => :destroy
11 | )
12 | accepts_nested_attributes_for :answers
13 |
14 | has_many :questionnaires_questions
15 |
16 | has_many(
17 | :questionnaires,
18 | :through => :questionnaires_questions,
19 | :uniq => true
20 | )
21 |
22 | validates :title, :presence => true
23 |
24 | def build_standard_answers
25 | created_answers = Array.new
26 | Answer.standard_values.each_with_index do |value, index|
27 | answer = answers.find_or_initialize_by_value(value)
28 | answer.position = index + 1
29 | created_answers << answer
30 | end
31 | return created_answers
32 | end
33 |
34 | def create_standard_answers
35 | build_standard_answers.each(&:save)
36 | end
37 | end
38 | end
--------------------------------------------------------------------------------
/app/models/qwester/questionnaire.rb:
--------------------------------------------------------------------------------
1 | module Qwester
2 | class Questionnaire < ActiveRecord::Base
3 | if Qwester.rails_three?
4 | attr_accessible :title, :description, :button_image, :question_ids, :must_complete
5 | end
6 |
7 | has_many(
8 | :questionnaires_questions,
9 | :order => 'position'
10 | )
11 |
12 | has_many(
13 | :questions,
14 | :class_name => 'Qwester::Question',
15 | :uniq => true,
16 | :through => :questionnaires_questions,
17 | :order => 'position'
18 | )
19 |
20 | has_many(
21 | :answers,
22 | :class_name => 'Qwester::Answer',
23 | :through => :questions,
24 | :uniq => true
25 | )
26 | accepts_nested_attributes_for :answers
27 |
28 | has_and_belongs_to_many(
29 | :answer_stores,
30 | :join_table => :qwester_answer_stores_questionnaires,
31 | :uniq => true
32 | )
33 |
34 | has_many :presentation_questionnaires
35 |
36 | has_many(
37 | :presentations,
38 | :through => :presentation_questionnaires
39 | )
40 |
41 | validates :title, :presence => true
42 |
43 | private
44 | def method_missing(symbol, *args, &block)
45 | if symbol.to_sym == :position || acts_as_list_method?(symbol)
46 | pass_acts_as_list_method_to_questionnaires_question(symbol, args.first)
47 | else
48 | super
49 | end
50 | end
51 |
52 | # Allows acts_as_list methods to be used within the questionnaire.
53 | #
54 | # Usage:
55 | #
56 | # questionnaire.move_to_top(question)
57 | # questionnaire.last?(question)
58 | #
59 | def pass_acts_as_list_method_to_questionnaires_question(symbol, question)
60 | raise "A Question is needed to identify the QuestionnairesQuestion" unless question.kind_of? Question
61 | questionnaires_question = questionnaires_questions.where(:question_id => question.id).first
62 | questionnaires_question.send(symbol) if questionnaires_question
63 | end
64 |
65 | def acts_as_list_method?(symbol)
66 | ActiveRecord::Acts::List::InstanceMethods.instance_methods.include?(symbol.to_sym)
67 | end
68 |
69 | end
70 | end
71 |
--------------------------------------------------------------------------------
/app/models/qwester/questionnaires_question.rb:
--------------------------------------------------------------------------------
1 | module Qwester
2 | class QuestionnairesQuestion < ActiveRecord::Base
3 | if Qwester.rails_three?
4 | attr_accessible :position
5 | end
6 |
7 | belongs_to :questionnaire
8 | belongs_to :question
9 |
10 | acts_as_list :scope => :questionnaire
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/app/models/qwester/rule_set.rb:
--------------------------------------------------------------------------------
1 | require 'array_logic'
2 | module Qwester
3 | class RuleSet < ActiveRecord::Base
4 | if Qwester.rails_three?
5 | attr_accessible :title, :description, :answers, :url, :rule, :answer_ids, :link_text, :warning_id, :presentation
6 | end
7 |
8 | before_save :keep_answers_in_step_with_rule
9 |
10 | DEFAULT_RULE_JOIN = 'or'
11 | ANSWERS_LIMIT = 10
12 |
13 | has_and_belongs_to_many(
14 | :answers,
15 | :uniq => true,
16 | :join_table => :qwester_answers_rule_sets
17 | )
18 | accepts_nested_attributes_for :answers
19 |
20 | has_many(
21 | :questions,
22 | :through => :answers
23 | )
24 |
25 | validate :check_rule_is_valid
26 | validate :check_answers_exist_with_ids_matching_those_in_rule
27 |
28 | validates :title, :presence => true
29 | validates :url, :presence => {:unless => :presentation?}
30 |
31 |
32 | def self.matching(answers)
33 | all.select{|rule_set| rule_set.match(answers)}
34 | end
35 |
36 | def match(answers_to_check = nil)
37 | return unless answers_to_check and !answers_to_check.empty?
38 | generate_default_rule && save
39 | logic.match(answers_to_check)
40 | end
41 |
42 | def logic
43 | @logic || get_logic
44 | end
45 |
46 | def matching_answer_sets
47 | @matching_answer_sets ||= logic.matching_combinations
48 | end
49 |
50 | def blocking_answer_sets
51 | @blocking_answer_set ||= logic.blocking_combinations
52 | end
53 |
54 | def default_rule
55 | answers.collect(&:rule_label).join(" #{DEFAULT_RULE_JOIN} ")
56 | end
57 |
58 | private
59 | def get_logic
60 | @logic = ArrayLogic::Rule.new rule
61 | end
62 |
63 | def generate_default_rule
64 | if (!self.rule or self.rule.empty?) and answers.length > 0
65 | self.rule = default_rule
66 | end
67 | end
68 |
69 | def keep_answers_in_step_with_rule
70 | generate_default_rule
71 | self.answers = get_logic.object_ids_used.collect{|id| Answer.find(id)} # need to use get_logic rather than caching logic
72 | end
73 |
74 | def check_rule_is_valid
75 | if rule?
76 | begin
77 | logic.send :check_rule
78 | rescue => e
79 | errors.add(:rule, "error: #{e.message}")
80 | end
81 | end
82 | end
83 |
84 | def answer_ids_in_rule
85 | rule? ? logic.object_ids_used : []
86 | end
87 |
88 | def answers_ids_in_database_also_found_in_rule
89 | Qwester::Answer.where(id: answer_ids_in_rule).pluck(:id)
90 | end
91 |
92 | def check_answers_exist_with_ids_matching_those_in_rule
93 | mismatch = answer_ids_in_rule - answers_ids_in_database_also_found_in_rule
94 | return if mismatch.empty?
95 | mismatch_report = mismatch.collect{|a| "a#{a}"}.join(", ")
96 | errors.add(:rule, "Answer labels [#{mismatch_report}] do not have corresponding answers in database")
97 | end
98 | end
99 | end
100 |
--------------------------------------------------------------------------------
/app/views/layouts/qwester/application.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Qwester
5 | <%= stylesheet_link_tag "qwester/application", :media => "all" %>
6 | <%= javascript_include_tag "qwester/application" %>
7 | <%= csrf_meta_tags %>
8 |
9 |
10 |
11 | <%= yield %>
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/views/qwester/questionnaires/_errors.html.erb:
--------------------------------------------------------------------------------
1 | <% if @questionnaire and @questionnaire.errors.present? %>
2 |
3 |
Error detected
4 |
5 | <% @questionnaire.errors.full_messages.each do |message| %>
6 | <%= content_tag('li', message, class: 'error_message') %>
7 | <% end %>
8 |
9 | <% end %>
10 |
--------------------------------------------------------------------------------
/app/views/qwester/questionnaires/index.html.erb:
--------------------------------------------------------------------------------
1 | Questionnaires
2 |
3 | <% @questionnaires.each do |questionnaire| %>
4 |
5 | <%= link_to(
6 | questionnaire.title,
7 | questionnaire_path(questionnaire),
8 | :class => 'text_link'
9 | )
10 | %>
11 |
12 | <% end %>
13 |
14 |
15 | <% if @qwester_rule_sets.present? %>
16 | Matching rule sets
17 |
18 | <% @qwester_rule_sets.each do |rule_set| %>
19 | -
20 | <%= rule_set.title %>:
21 | <%= link_to(rule_set.link_text, rule_set.url) %>
22 |
23 | <% end %>
24 |
25 | <% end %>
26 |
27 | <%=
28 | content_tag(
29 | 'p',
30 | link_to('Clear answers and start again', reset_questionnaires_path)
31 | ) if @qwester_answer_store and @qwester_answer_store.answers.present?
32 | %>
33 |
--------------------------------------------------------------------------------
/app/views/qwester/questionnaires/show.html.erb:
--------------------------------------------------------------------------------
1 | <%= @questionnaire.title %>
2 |
3 | <% if @questionnaire.description.present? %>
4 | <%= content_tag('div', sanitize(@questionnaire.description)) %>
5 | <% else %>
6 | Questions
7 | <% end %>
8 | <%= render 'errors' %>
9 | <%= form_for(@questionnaire, :url => questionnaire_path(@questionnaire)) do |form| %>
10 |
11 |
12 | <% @questionnaire.questions.each do |question| %>
13 | -
14 | <%= content_tag(
15 | 'span', question.title,
16 | :class => "label#{' tooltip' if question.description?}",
17 | :title => question.description
18 | )
19 | %>
20 |
21 | <%= qwester_answers_selection_list(question) %>
22 |
23 |
24 | <% end %>
25 |
26 |
27 |
28 |
29 | <%= form.submit('Submit') %>
30 | <%= link_to('Back to the menu', questionnaires_path) %>
31 |
32 | <% end %>
33 |
--------------------------------------------------------------------------------
/config/routes.rb:
--------------------------------------------------------------------------------
1 | Qwester::Engine.routes.draw do
2 |
3 | root :to => 'questionnaires#index'
4 |
5 | resources :questionnaires, :only => [:index, :show, :update] do
6 | collection do
7 | get :reset
8 | end
9 | end
10 |
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20121008151526_create_questions.rb:
--------------------------------------------------------------------------------
1 | class CreateQuestions < ActiveRecord::Migration
2 | def change
3 | create_table :qwester_questions do |t|
4 | t.string :title
5 | t.text :description
6 | t.integer :parent_id
7 | t.integer :lft
8 | t.integer :rgt
9 | t.integer :depth
10 | t.timestamps
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/db/migrate/20121008152106_create_answers.rb:
--------------------------------------------------------------------------------
1 | class CreateAnswers < ActiveRecord::Migration
2 | def change
3 | create_table :qwester_answers do |t|
4 | t.integer :question_id
5 | t.boolean :value
6 | t.timestamps
7 | end
8 | end
9 | end
--------------------------------------------------------------------------------
/db/migrate/20121008153758_create_rule_sets.rb:
--------------------------------------------------------------------------------
1 | class CreateRuleSets < ActiveRecord::Migration
2 | def change
3 | create_table :qwester_rule_sets do |t|
4 | t.string :title
5 | t.text :description
6 | t.string :url
7 | t.timestamps
8 | end
9 |
10 | create_table :qwester_answers_rule_sets, :id => false do |t|
11 | t.integer :answer_id
12 | t.integer :rule_set_id
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/db/migrate/20121009080219_create_questionnaires.rb:
--------------------------------------------------------------------------------
1 | class CreateQuestionnaires < ActiveRecord::Migration
2 | def change
3 | create_table :qwester_questionnaires do |t|
4 | t.string :title
5 | t.text :description
6 | t.timestamps
7 | end
8 |
9 | create_table :qwester_questionnaires_questions, :id => false do |t|
10 | t.integer :questionnaire_id
11 | t.integer :question_id
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/db/migrate/20121009095600_create_answer_stores.rb:
--------------------------------------------------------------------------------
1 | class CreateAnswerStores < ActiveRecord::Migration
2 | def change
3 | create_table :qwester_answer_stores do |t|
4 | t.string :session_id
5 | t.timestamps
6 | end
7 |
8 | create_table :qwester_answer_stores_answers, :id => false do |t|
9 | t.integer :answer_id
10 | t.integer :answer_store_id
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/db/migrate/20121009160807_add_questionnaire_id_to_answers.rb:
--------------------------------------------------------------------------------
1 | class AddQuestionnaireIdToAnswers < ActiveRecord::Migration
2 | def change
3 | add_column :qwester_answers, :questionnaire_id, :integer
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20121009161206_change_answers_value_to_string.rb:
--------------------------------------------------------------------------------
1 | class ChangeAnswersValueToString < ActiveRecord::Migration
2 | def up
3 | change_column(:qwester_answers, :value, :string)
4 | end
5 |
6 | def down
7 | change_column(:qwester_answers, :value, :boolean)
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20121019111051_add_button_image_to_questionnaires.rb:
--------------------------------------------------------------------------------
1 | require 'paperclip'
2 | ActiveRecord::ConnectionAdapters::AbstractAdapter.send :include, Paperclip::Schema::Statements
3 | class AddButtonImageToQuestionnaires < ActiveRecord::Migration
4 | def change
5 | add_attachment :qwester_questionnaires, :button_image
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/db/migrate/20121114084347_create_ckeditor_assets.rb:
--------------------------------------------------------------------------------
1 | class CreateCkeditorAssets < ActiveRecord::Migration
2 | def self.up
3 | create_table :qwester_ckeditor_assets do |t|
4 | t.string :data_file_name, :null => false
5 | t.string :data_content_type
6 | t.integer :data_file_size
7 |
8 | t.integer :assetable_id
9 | t.string :assetable_type, :limit => 30
10 | t.string :type, :limit => 30
11 |
12 | # Uncomment it to save images dimensions, if your need it
13 | t.integer :width
14 | t.integer :height
15 |
16 | t.timestamps
17 | end
18 |
19 | add_index "qwester_ckeditor_assets", ["assetable_type", "type", "assetable_id"], :name => "qwester_idx_ckeditor_assetable_type"
20 | add_index "qwester_ckeditor_assets", ["assetable_type", "assetable_id"], :name => "qwester_idx_ckeditor_assetable"
21 | end
22 |
23 | def self.down
24 | drop_table :qwester_ckeditor_assets
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/db/migrate/20121115114408_add_ref_to_questions.rb:
--------------------------------------------------------------------------------
1 | class AddRefToQuestions < ActiveRecord::Migration
2 | def change
3 | add_column :qwester_questions, :ref, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20121120092108_add_ids_to_questionnaires_questions.rb:
--------------------------------------------------------------------------------
1 | class AddIdsToQuestionnairesQuestions < ActiveRecord::Migration
2 | def up
3 | add_column qq_table, :id, :primary_key
4 | add_column qq_table, :position, :integer
5 | add_column qq_table, :created_at, :datetime
6 | add_column qq_table, :updated_at, :datetime
7 |
8 | execute "UPDATE #{qq_table} SET created_at = '#{Time.now.to_s(:db)}', updated_at = '#{Time.now.to_s(:db)}';"
9 |
10 | puts "=============================================="
11 | puts "Now run 'rake qwester:reset_positions RAILS_ENV=#{Rails.env}' to set the positions"
12 | puts "=============================================="
13 | end
14 |
15 | def down
16 | remove_column qq_table, :id
17 | remove_column qq_table, :position
18 | remove_column qq_table, :created_at
19 | remove_column qq_table, :updated_at
20 | end
21 |
22 | def qq_table
23 | :qwester_questionnaires_questions
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/db/migrate/20121122130930_add_position_to_answers.rb:
--------------------------------------------------------------------------------
1 | class AddPositionToAnswers < ActiveRecord::Migration
2 | def change
3 | # Adds unless clause, because original version of migration added another field
4 | # and file name was changed when this field was removed. This can cause this
5 | # migration to appear a second time if rake qwester:install:migrations is
6 | # run again in an app created before the change was made.
7 | unless column_exists?(:qwester_answers, :position)
8 | add_column :qwester_answers, :position, :integer
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20121122141628_remove_questionnaire_from_answer.rb:
--------------------------------------------------------------------------------
1 | class RemoveQuestionnaireFromAnswer < ActiveRecord::Migration
2 | def up
3 | remove_column :qwester_answers, :questionnaire_id
4 | end
5 |
6 | def down
7 | add_column :qwester_answers, :questionnaire_id, :integer
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20121126152146_add_rule_to_rule_sets.rb:
--------------------------------------------------------------------------------
1 | class AddRuleToRuleSets < ActiveRecord::Migration
2 | def change
3 | add_column :qwester_rule_sets, :rule, :text
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20121203150555_add_multi_answer_to_questions.rb:
--------------------------------------------------------------------------------
1 | class AddMultiAnswerToQuestions < ActiveRecord::Migration
2 | def change
3 | add_column :qwester_questions, :multi_answer, :boolean
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20121204082213_create_answer_stores_questionnaires.rb:
--------------------------------------------------------------------------------
1 | class CreateAnswerStoresQuestionnaires < ActiveRecord::Migration
2 | def change
3 |
4 | create_table :qwester_answer_stores_questionnaires, :id => false do |t|
5 | t.integer :questionnaire_id
6 | t.integer :answer_store_id
7 | end
8 |
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20121204100803_add_link_text_to_rule_sets.rb:
--------------------------------------------------------------------------------
1 | class AddLinkTextToRuleSets < ActiveRecord::Migration
2 | def change
3 | add_column :qwester_rule_sets, :link_text, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20130306114331_add_preserved_to_answer_stores.rb:
--------------------------------------------------------------------------------
1 | class AddPreservedToAnswerStores < ActiveRecord::Migration
2 | def change
3 | add_column :qwester_answer_stores, :preserved, :datetime
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20130315112847_create_qwester_presentations.rb:
--------------------------------------------------------------------------------
1 | class CreateQwesterPresentations < ActiveRecord::Migration
2 | def change
3 | create_table :qwester_presentations do |t|
4 | t.string :name
5 | t.string :title
6 | t.text :description
7 |
8 | t.timestamps
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20130315113027_create_qwester_presentation_questionnaires.rb:
--------------------------------------------------------------------------------
1 | class CreateQwesterPresentationQuestionnaires < ActiveRecord::Migration
2 | def change
3 | create_table :qwester_presentation_questionnaires do |t|
4 | t.integer :questionnaire_id
5 | t.integer :presentation_id
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20130318102537_add_presentation_to_rule_sets.rb:
--------------------------------------------------------------------------------
1 | class AddPresentationToRuleSets < ActiveRecord::Migration
2 | def change
3 | add_column :qwester_rule_sets, :presentation, :string
4 | add_column :qwester_presentations, :default, :boolean
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20130402074240_add_weighting_to_qwester_answers.rb:
--------------------------------------------------------------------------------
1 | class AddWeightingToQwesterAnswers < ActiveRecord::Migration
2 | def change
3 | add_column :qwester_answers, :weighting, :float, :default => 0
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20130502082540_add_position_to_qwester_presentation_questionnaires.rb:
--------------------------------------------------------------------------------
1 | class AddPositionToQwesterPresentationQuestionnaires < ActiveRecord::Migration
2 | def change
3 | add_column :qwester_presentation_questionnaires, :position, :integer
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20131119142009_add_must_complete_to_qwester_questionnaires.rb:
--------------------------------------------------------------------------------
1 | class AddMustCompleteToQwesterQuestionnaires < ActiveRecord::Migration
2 | def change
3 | add_column :qwester_questionnaires, :must_complete, :boolean
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/lib/active_admin/admin/answers.rb:
--------------------------------------------------------------------------------
1 | module Qwester
2 |
3 | ActiveAdmin.register Answer do
4 |
5 | menu_label = 'Answers'
6 | menu_label = "Qwester #{menu_label}" unless Qwester.active_admin_menu
7 | menu :parent => Qwester.active_admin_menu, :label => menu_label
8 |
9 | actions :all, :except => [:edit, :new]
10 | config.batch_actions = false
11 |
12 | filter :question
13 | filter :value
14 | filter :created_at
15 | filter :updated_at
16 | filter :position
17 | filter :weighting, :label => Answer.weighting_alias_name.humanize
18 |
19 |
20 | index do
21 | column :id
22 | column :value
23 | column 'Question (edit answer via question)', :question do |answer|
24 | link_to(answer.question.title, edit_admin_qwester_question_path(answer.question)) if answer.question
25 | end
26 | column Answer.weighting_alias_name.humanize, :weighting
27 | column :position
28 | default_actions
29 | end
30 |
31 | show do |ad|
32 | attributes_table do
33 | row :question
34 | row :value
35 | row :updated_at
36 | row :position
37 | row Answer.weighting_alias_name.humanize do |answer|
38 | answer.weighting
39 | end
40 | end
41 | active_admin_comments
42 | end
43 |
44 | member_action :move_up do
45 | answer = Answer.find(params[:id])
46 | answer.move_higher
47 | redirect_to admin_qwester_question_path(answer.question)
48 | end
49 |
50 | member_action :move_down do
51 | answer = Answer.find(params[:id])
52 | answer.move_lower
53 | redirect_to admin_qwester_question_path(answer.question)
54 | end
55 |
56 | member_action :remove do
57 | answer = Answer.find(params[:id])
58 | answer.destroy
59 | redirect_to admin_qwester_question_path(answer.question)
60 | end
61 |
62 |
63 | end if defined?(ActiveAdmin)
64 |
65 | end
--------------------------------------------------------------------------------
/lib/active_admin/admin/presentations.rb:
--------------------------------------------------------------------------------
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 | div sanitize(qwester_presentation.description) if qwester_presentation.description.present?
27 | qwester_presentation.questionnaires.each do |questionnaire|
28 | div(:style => 'display:inline-block;margin-right:20px;') do
29 | para image_tag(questionnaire.button_image.url(:thumbnail))
30 | para questionnaire.title
31 | move_up_link = " "
32 | move_down_link = " "
33 | unless qwester_presentation.first?(questionnaire)
34 | move_up_link = link_to('<', move_up_admin_qwester_presentation_path(qwester_presentation, :questionnaire_id => questionnaire.id))
35 | end
36 | unless qwester_presentation.last?(questionnaire)
37 | move_down_link = link_to('>', move_down_admin_qwester_presentation_path(qwester_presentation, :questionnaire_id => questionnaire.id))
38 | end
39 | para [move_up_link, 'move', move_down_link].join(' ').html_safe
40 | end
41 | end
42 | para "Default: Will be inital presentation of quesitonnaires" if qwester_presentation.default?
43 | end
44 |
45 | form do |f|
46 | f.inputs "Details" do
47 | f.input :name
48 | f.input :title, :label => "Title (or create from name)"
49 | f.input :default, :label => 'Set as default (that is, the first presentation displayed to a user). If no default, all questionnaires will be displayed'
50 | if defined?(Ckeditor)
51 | f.input :description, :as => :ckeditor, :input_html => { :height => 100}
52 | else
53 | f.input :description, :input_html => { :rows => 3}
54 | end
55 | f.input :questionnaires, :as => :check_boxes, :collection => Questionnaire.all
56 | end
57 | f.actions
58 | end
59 |
60 | controller do
61 | def permitted_params
62 | params.permit(
63 | qwester_presentation: [
64 | :name, :title, :default, :description,
65 | {questionnaire_ids: []}
66 | ]
67 | )
68 | end
69 | end unless Qwester.rails_three?
70 |
71 | member_action :move_up do
72 | presentation = Presentation.find(params[:id])
73 | questionnaire = Questionnaire.find(params[:questionnaire_id])
74 | presentation.move_higher(questionnaire)
75 | redirect_to admin_qwester_presentation_path(presentation)
76 | end
77 |
78 | member_action :move_down do
79 | presentation = Presentation.find(params[:id])
80 | questionnaire = Questionnaire.find(params[:questionnaire_id])
81 | presentation.move_lower(questionnaire)
82 | redirect_to admin_qwester_presentation_path(presentation)
83 | end
84 |
85 | end
86 | end
87 |
--------------------------------------------------------------------------------
/lib/active_admin/admin/questionnaires.rb:
--------------------------------------------------------------------------------
1 | module Qwester
2 |
3 | ActiveAdmin.register Questionnaire do
4 |
5 | menu_label = 'Questionnaires'
6 | menu_label = "Qwester #{menu_label}" unless Qwester.active_admin_menu
7 | menu :parent => Qwester.active_admin_menu, :label => menu_label
8 |
9 | config.batch_actions = false
10 |
11 | index do
12 | column :title
13 | column :questions do |questionnaire|
14 | questionnaire.questions.count
15 | end
16 | column :must_complete do |questionnaire|
17 | questionnaire.must_complete? ? 'Yes' : 'No'
18 | end
19 | default_actions
20 | end
21 |
22 | form do |f|
23 | f.inputs "Details" do
24 | f.input :title
25 | if defined?(Ckeditor)
26 | f.input :description, :as => :ckeditor, :input_html => { :height => 100 }
27 | else
28 | f.input :description, :input_html => { :rows => 3}
29 | end
30 | f.input :must_complete
31 | f.input :questions, :as => :check_boxes, :collection => Question.all
32 | end
33 | f.actions
34 | end
35 |
36 | controller do
37 | def permitted_params
38 | params.permit(
39 | qwester_questionnaire: [
40 | :title, :description, :button_image, :must_complete,
41 | {question_ids: []}
42 | ]
43 | )
44 | end
45 | end unless Qwester.rails_three?
46 |
47 | show do
48 | div do
49 | sanitize(qwester_questionnaire.description.html_safe ) if qwester_questionnaire.description.present?
50 | end
51 |
52 | div do
53 | h3 'Questions'
54 | para("#{qwester_questionnaire.must_complete? ? 'A' : 'Not a'}ll must be completed")
55 | ul :id => 'question_list'
56 | qwester_questionnaire.questions.each do |question|
57 | li do
58 | text = [question.title]
59 | text << link_to('Up', move_up_admin_qwester_questionnaire_path(qwester_questionnaire, :question_id => question)) unless qwester_questionnaire.first?(question)
60 | text << link_to('Down', move_down_admin_qwester_questionnaire_path(qwester_questionnaire, :question_id => question)) unless qwester_questionnaire.last?(question)
61 | text.join(' ').html_safe
62 | end
63 | end
64 | end
65 | end
66 |
67 | member_action :move_up do
68 | questionnaire = Questionnaire.find(params[:id])
69 | question = Question.find(params[:question_id])
70 | questionnaire.move_higher(question)
71 | redirect_to admin_qwester_questionnaire_path(questionnaire)
72 | end
73 |
74 | member_action :move_down do
75 | questionnaire = Questionnaire.find(params[:id])
76 | question = Question.find(params[:question_id])
77 | questionnaire.move_lower(question)
78 | redirect_to admin_qwester_questionnaire_path(questionnaire)
79 | end
80 |
81 | end if defined?(ActiveAdmin)
82 |
83 | end
84 |
--------------------------------------------------------------------------------
/lib/active_admin/admin/questions.rb:
--------------------------------------------------------------------------------
1 | module Qwester
2 |
3 | ActiveAdmin.register Question do
4 |
5 | menu_label = 'Questions'
6 | menu_label = "Qwester #{menu_label}" unless Qwester.active_admin_menu
7 | menu :parent => Qwester.active_admin_menu, :label => menu_label
8 |
9 | config.batch_actions = false
10 |
11 | index do
12 | column :ref
13 | column :title do |qwester_question|
14 | link_to(qwester_question.title, '#', :title => qwester_question.description, :class => 'no_decoration')
15 | end
16 | column :answers do |qwester_question|
17 | qwester_question.answers.count
18 | end
19 | column :multi_answer do |qwester_question|
20 | qwester_question.multi_answer? ? 'Any' : 'One'
21 | end
22 | default_actions
23 | end
24 |
25 | show do
26 | para("References: #{qwester_question.ref}") if qwester_question.ref.present?
27 | para(qwester_question.description)
28 | h3 "Answers"
29 | para "User can select one#{' or many' if qwester_question.multi_answer?} of:"
30 |
31 | table :class => 'sortable_list' do
32 | tr do
33 | th "Value (#{Answer.weighting_alias_name.humanize})"
34 | end
35 | qwester_question.answers.each do |answer|
36 | tr do
37 | td "#{answer.value} (#{answer.weighting})"
38 | td(answer.first? ? " ".html_safe : link_to('Up', move_up_admin_qwester_answer_path(answer)))
39 | td(answer.last? ? " ".html_safe : link_to('Down', move_down_admin_qwester_answer_path(answer)))
40 | td link_to('Delete', remove_admin_qwester_answer_path(answer), :confirm => "Are you sure you want to delete the answer '#{answer.value}'?")
41 | end
42 | end
43 | end
44 | end
45 |
46 | form do |f|
47 | f.inputs "Details" do
48 | f.input :ref, :label => 'Reference'
49 | f.input :title
50 | f.input :description, :input_html => { :rows => 2}
51 | f.input :multi_answer, :label => 'User may select more than one answer to this question?'
52 | end
53 |
54 | f.inputs do
55 | f.has_many :answers do |answer_form|
56 | answer_form.input :value
57 | answer_form.input :position
58 | answer_form.input :weighting, :label => Answer.weighting_alias_name.humanize
59 | end
60 | end
61 |
62 | f.actions
63 | end
64 |
65 | controller do
66 |
67 | def new
68 | @qwester_question = Question.new
69 | @qwester_question.build_standard_answers
70 | end
71 |
72 | end
73 |
74 | controller do
75 |
76 | def permitted_params
77 | params.permit(
78 | qwester_question: [
79 | :ref, :title, :description, :multi_answer,
80 | {answers_attributes: [:value, :position, :weighting]}
81 | ]
82 | )
83 | end
84 |
85 | end unless Qwester.rails_three?
86 |
87 | end if defined?(ActiveAdmin)
88 |
89 | end
90 |
--------------------------------------------------------------------------------
/lib/active_admin/admin/rule_sets.rb:
--------------------------------------------------------------------------------
1 | module Qwester
2 |
3 | ActiveAdmin.register RuleSet do
4 |
5 | menu_label = 'Rule Sets'
6 | menu_label = "Qwester #{menu_label}" unless Qwester.active_admin_menu
7 | menu :parent => Qwester.active_admin_menu, :label => menu_label
8 |
9 | config.batch_actions = false
10 |
11 | index do
12 | column :title
13 | column :presentation
14 | column :answers do |rule_set|
15 | rule_set.answers.count
16 | end
17 | column :rule
18 | default_actions
19 | end
20 |
21 | sidebar :rule_syntax do
22 | para 'R1 = "(a1 and a2) or (a3 and a4)"'
23 |
24 | para 'R2 = "a1 and not a2"'
25 |
26 | para 'R3 = "sum(:id) == 7"'
27 |
28 | para 'R4 = "(2 in a1 a2 a3) and (average(:id) == 3)"'
29 |
30 | table(:class => 'small') do
31 | tr do
32 | th "Input"
33 | th "R1"
34 | th "R2"
35 | th "R3"
36 | th "R4"
37 | end
38 | tr do
39 | th "[a1, a2]"
40 | th "true"
41 | th "false"
42 | th "false"
43 | th "false"
44 | end
45 | tr do
46 | th "[a3, a4]"
47 | th "true"
48 | th "false"
49 | th "true"
50 | th "false"
51 | end
52 | tr do
53 | th "[a1, a3, a5]"
54 | th "false"
55 | th "true"
56 | th "false"
57 | th "true"
58 | end
59 | end
60 |
61 | para link_to('Rule engine documentation', 'https://github.com/reggieb/array_logic', :target => '_blank')
62 |
63 | end
64 |
65 | sidebar :presentations do
66 | para < :ckeditor, :input_html => { :height => 100 }
89 | else
90 | f.input :description, :input_html => { :rows => 3}
91 | end
92 | end
93 |
94 | f.inputs "Output Link" do
95 | f.input :url
96 | f.input :link_text
97 | end
98 |
99 | f.inputs "Change Presentation of Questionnaires" do
100 | f.input :presentation, :as => :select, :collection => Presentation.all.collect(&:name), :include_blank => 'No effect on presentation'
101 | end
102 |
103 | f.inputs "Logic" do
104 | f.input :rule, :input_html => { :rows => 3}
105 | end
106 |
107 | f.inputs("Questions") do
108 |
109 | if qwester_rule_set.questions.empty?
110 |
111 | f.input(
112 | :answers,
113 | :as => :check_boxes,
114 | :member_label => lambda {|a| "a#{a.id}: #{a.value} to '#{a.question.title}'"},
115 | :input_html => { :size => 20, :multiple => true}
116 | )
117 |
118 | else
119 |
120 | questions = qwester_rule_set.questions | Question.all
121 | questions.collect! do |question|
122 | style = 'border:#CCCCCC 1px solid;'
123 | html = [content_tag('td', question.title, :style => style)]
124 | answers = question.answers.collect do |answer|
125 | answer_style = style
126 | answer_style += 'background-color:#005C1F;color:white;font-weight:bold;' if qwester_rule_set.answers.include?(answer)
127 | content_tag('td', "a#{answer.id} #{answer.value}".html_safe, :style => answer_style).html_safe
128 | end
129 | html << answers.join(" ").html_safe
130 | content_tag('tr', html.join(" ").html_safe)
131 | end
132 | table_class = ["selection"]
133 | table_class << 'associated_questions' if qwester_rule_set.id.present?
134 | content_tag 'li', content_tag('table', questions.join("\n").html_safe, :class => table_class.join(' '))
135 |
136 | end
137 |
138 | end
139 |
140 | f.actions
141 | end
142 |
143 | controller do
144 | def permitted_params
145 | params.permit(
146 | qwester_rule_set: [
147 | :title, :description, :url, :link_text, :presentation, :rule,
148 | {answer_ids: []}
149 | ]
150 | )
151 | end
152 | end unless Qwester.rails_three?
153 |
154 | show do
155 | div do
156 | para sanitize(qwester_rule_set.description)
157 | end if qwester_rule_set.description.present?
158 |
159 | div do
160 | h3 'Target url'
161 | para link_to qwester_rule_set.url
162 | para qwester_rule_set.link_text? ? qwester_rule_set.link_text : 'No link text specified'
163 | end
164 |
165 | div do
166 | h3 'Presentation'
167 | if qwester_rule_set.presentation?
168 | para "The presentations of questionnaires should change to: #{qwester_rule_set.presentation}"
169 | else
170 | para "The presentations of questionnaires should be unaffected by this rule"
171 | end
172 | end
173 |
174 | div do
175 | h3 'The rule'
176 | para qwester_rule_set.rule
177 | end
178 |
179 | begin
180 | if qwester_rule_set.matching_answer_sets.present?
181 | div do
182 | h3 'Sample matching answer sets'
183 | if qwester_rule_set.matching_answer_sets.length
184 | para "There are at least #{qwester_rule_set.matching_answer_sets.length} combinations of answers that would pass this test."
185 | end
186 | para 'The following combinations of answers would pass'
187 | qwester_rule_set.matching_answer_sets.each do |answer_set|
188 | ul :style => 'border:#CCCCCC 1px solid;padding:5px;list-style:none;' do
189 | answer_set.each do |answer_id|
190 | next unless Answer.exists?(answer_id)
191 | answer = Answer.find(answer_id)
192 | question_summary = [answer.value, answer.question.title].join(' : ')
193 | li "(a#{answer_id}) #{question_summary}"
194 | end
195 | end
196 | end
197 | end
198 | else
199 | div do
200 | h3 'Matching answer sets'
201 | para 'Answers will pass unless they contain a blocking answer set'
202 | end
203 | end
204 |
205 | if qwester_rule_set.blocking_answer_sets.present?
206 | div do
207 | h3 'Sample blocking answer sets'
208 | para 'The following combinations of answers would not pass'
209 | qwester_rule_set.blocking_answer_sets.each do |answer_set|
210 | ul :style => 'border:#CCCCCC 1px solid;padding:5px;list-style:none;' do
211 | answer_set.each do |answer_id|
212 | next unless Answer.exists?(answer_id)
213 | answer = Answer.find(answer_id)
214 | question_summary = [answer.value, answer.question.title].join(' : ')
215 | li "(a#{answer_id}) #{question_summary}"
216 | end
217 | end
218 | end
219 | end
220 | else
221 | div do
222 | h3 'Blocking answer sets'
223 | para 'Answers will only pass if they contain a matching answer set'
224 | end
225 | end
226 | rescue ArrayLogic::UnableToDetermineCombinationsError => e
227 | h3 'Sample combinations'
228 | para e.message
229 | end
230 |
231 |
232 | end
233 |
234 | end if defined?(ActiveAdmin)
235 |
236 | end
--------------------------------------------------------------------------------
/lib/qwester.rb:
--------------------------------------------------------------------------------
1 | require "qwester/engine"
2 | require 'acts_as_list'
3 | require 'random_string'
4 | require_relative 'rails/actionpack/lib/action_controller/base'
5 |
6 | module Qwester
7 |
8 | def self.active_admin_load_path
9 | File.expand_path("active_admin/admin", File.dirname(__FILE__))
10 | end
11 |
12 | def self.active_admin_menu
13 | if @active_admin_menu == 'none'
14 | return nil
15 | elsif @active_admin_menu
16 | @active_admin_menu
17 | else
18 | 'Qwester'
19 | end
20 | end
21 |
22 | def self.active_admin_menu=(menu)
23 | @active_admin_menu = menu
24 | end
25 |
26 | def self.session_key
27 | @session_key || :qwester_answer_store
28 | end
29 |
30 | def self.session_key=(key)
31 | @session_key = key
32 | end
33 |
34 | def self.rails_version
35 | @rails_version ||= Rails.version.split('.').first if defined? Rails
36 | end
37 |
38 | def self.rails_three?
39 | rails_version == '3'
40 | end
41 |
42 | end
43 |
--------------------------------------------------------------------------------
/lib/qwester/engine.rb:
--------------------------------------------------------------------------------
1 | module Qwester
2 | class Engine < ::Rails::Engine
3 | isolate_namespace Qwester
4 |
5 | initializer 'qwester.action_controller' do |app|
6 | ActiveSupport.on_load :action_controller do
7 |
8 | helper Qwester::QuestionnairesHelper
9 |
10 | end
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/lib/qwester/version.rb:
--------------------------------------------------------------------------------
1 | module Qwester
2 | VERSION = "0.5.0"
3 | end
4 |
5 | # History
6 | # =======
7 | # 0.5.0 - Removes Paperclip as a dependency of this engine.
8 | # Please note that the ActiveAdmin styling in the test/dummy app no longer loads.
9 | # This shouldn't alter the behaviour of this engine, as ActiveAdmin is given here
10 | # as an example.
11 | #
12 | # 0.4.0 - Updates version of paperclip used to avoid recent vulnerability
13 | #
14 | # 0.3.5 - Fixes typo in README (yes ... the same one!)
15 | #
16 | # 0.3.4 - Fixes typo in test/dummy/config/routes.rb
17 | #
18 | # 0.3.3 - Applies labels to checkbox and radio button texts within standard
19 | # questionnaire forms.
20 | #
21 | # 0.3.2 - Fixes issues where rule_set rule references answers that do not exist.
22 | #
23 | # 0.3.1 - Adds facility to mark as questionnaire as 'must complete'
24 | # When set, all questions must be answered before a questionnaire can be
25 | # successfully submitted.
26 | #
27 | # 0.3.0 - Allows qwester to be hosted in a rails 4 app
28 | #
29 | # 0.2.2 - Removes require statements not needed in production
30 | # Some gems needed to be required to run the dummy app, but these may have
31 | # caused some javascript and/or asset pipeline errors in production apps.
32 | #
33 | # 0.2.1 - Allows questionnaires to be positioned within a presentation
34 | #
35 | # 0.2.0 - Adds weighting to answers
36 | # Weighting can be used to give some answers greater weight in comparisons.
37 | # Weighting can be aliased.
38 | #
39 | # 0.1.4 - Bug fix update
40 | # Rescues exception in admin_rules_sets#show due to rule including a function
41 | #
42 | # 0.1.3 - Update to use version of Array Logic that supports functions.
43 | # Allows RuleSet#rule to be defined using sum, average or count functions
44 | #
45 | # 0.1.2 - Modification to admin pages
46 | # Changes CKeditor to use default style.
47 | #
48 | # 0.1.1 - Makes presentation object available to controller and views
49 | # @presentation used to store current Presentation
50 | #
51 | # 0.1.0 - Add presentations as a way of controlling the display of questionnaires
52 | # Allows admin to define groups of questionnaires as presentation views
53 | # and rule sets that will display a presentation when triggered. In that way
54 | # the list of questionnaires being displayed can change as questionnaires are
55 | # submitted.
56 | #
57 | # 0.0.9 - Maintenance update
58 | # Removes cope_index from migrations.
59 | # Ensures answer_store#session_id is unique
60 | #
61 | # 0.0.8 - Add facility to preserve answer stores
62 | # This allows snaps shots to be taken, and redundant answer stores to be
63 | # removed during routine maintenance.
64 | #
65 | # 0.0.7 - Improves deployment process
66 | # Fixes a bug in one of the migrations and updates the README
67 | #
68 | # 0.0.6 - Bug fix update
69 | # Fixes issue where error raised if user submits a questionnaire without
70 | # selecting and answer.
71 | #
72 | # 0.0.5 - Bug fix update
73 | # Fixes issue where active admin rule set form did not include link text field.
74 | #
75 |
--------------------------------------------------------------------------------
/lib/rails/actionpack/lib/action_controller/base.rb:
--------------------------------------------------------------------------------
1 | module ActionController
2 | class Base < Metal
3 |
4 | protected
5 | def update_qwester_answer_store
6 | if params_includes_answers?
7 | get_qwester_answer_store(true)
8 | ActiveRecord::Base.transaction do
9 | add_answers_to_qwester_answer_store
10 | add_questionnaire_to_qwester_answer_store
11 | ensure_complete_all_questionnaires_completed
12 | end
13 | end
14 | end
15 |
16 | def get_qwester_answer_store(create_new = false)
17 | if session[Qwester.session_key]
18 | current_qwester_answer_store
19 | elsif create_new
20 | new_qwester_answer_store
21 | end
22 | end
23 | helper_method :get_qwester_answer_store
24 |
25 | def current_qwester_answer_store
26 | @qwester_answer_store = Qwester::AnswerStore.find_by_session_id(session[Qwester.session_key])
27 | end
28 |
29 | def new_qwester_answer_store
30 | set_qwester_answer_store Qwester::AnswerStore.create
31 | end
32 |
33 | def set_qwester_answer_store(answer_store)
34 | @qwester_answer_store = answer_store
35 | session[Qwester.session_key] = @qwester_answer_store.session_id
36 | @qwester_answer_store
37 | end
38 |
39 | def match_rule_sets
40 | if get_qwester_answer_store
41 | @qwester_rule_sets = Qwester::RuleSet.matching(@qwester_answer_store.answers)
42 | get_presentation_from_rule_sets
43 | return @qwester_rule_sets
44 | end
45 | end
46 | alias_method :matching_rule_sets, :match_rule_sets
47 |
48 | def current_questionnaires
49 | match_rule_sets
50 | presentation_questionnaires || default_presentation_questionnaires || Qwester::Questionnaire.all
51 | end
52 |
53 | def presentation_questionnaires
54 | @presentation = Qwester::Presentation.find_by_name(session[:presentations].last) if session[:presentations]
55 | @presentation.questionnaires if @presentation
56 | end
57 |
58 | def default_presentation_questionnaires
59 | @presentation = Qwester::Presentation.find_by_default(true)
60 | @presentation.questionnaires if @presentation
61 | end
62 |
63 | def get_presentation_from_rule_sets
64 | @qwester_rule_sets.clone.each do |rule_set|
65 | next unless rule_set.presentation?
66 | add_presentation_to_session rule_set.presentation
67 | @qwester_rule_sets.delete(rule_set)
68 | end
69 | end
70 |
71 | def add_presentation_to_session(presentation)
72 | session_presentations = session[:presentations] || []
73 | unless session_presentations.include? presentation
74 | session_presentations << presentation
75 | session[:presentations] = session_presentations
76 | end
77 | end
78 |
79 | def add_answers_to_qwester_answer_store
80 | answers = params[:question_id].values.collect do |question_values|
81 | question_values[:answer_ids].collect{|id| Qwester::Answer.find(id)}
82 | end
83 | answers.flatten!
84 | remove_answers_to_questions_answered_with(answers) if answers.present?
85 | @qwester_answer_store.answers = (@qwester_answer_store.answers | answers)
86 | end
87 |
88 | def params_includes_answers?
89 | params[:question_id].kind_of?(Hash) and params[:question_id].values.present?
90 | end
91 |
92 | def remove_answers_to_questions_answered_with(answers)
93 | question_ids = answers.collect(&:question_id).uniq
94 | answers_to_delete = @qwester_answer_store.answers.collect {|a| a if question_ids.include? a.question_id.to_i}.compact
95 | @qwester_answer_store.answers.delete(answers_to_delete)
96 | end
97 |
98 | def add_questionnaire_to_qwester_answer_store
99 | @qwester_answer_store.questionnaires << @questionnaire
100 | end
101 |
102 | def ensure_complete_all_questionnaires_completed
103 | if @questionnaire.must_complete? and !@qwester_answer_store.completed_questionnaires.include?(@questionnaire)
104 | @questionnaire.errors.add(:base, "All questions must be answered in this questionnaire")
105 | end
106 | raise ActiveRecord::Rollback unless @questionnaire.errors.empty?
107 | end
108 | end
109 | end
110 |
--------------------------------------------------------------------------------
/lib/random_string.rb:
--------------------------------------------------------------------------------
1 | class RandomString < String
2 | def initialize(length = 40)
3 | super(new_random_string(length))
4 | end
5 |
6 |
7 | private
8 | def new_random_string(length = 40)
9 | string = ""
10 | string += random_string until string.length >= length
11 | return string[0, length]
12 | end
13 |
14 | def random_string
15 | string_pairs = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join ).scan(/.{2}/)
16 | random_strings = string_pairs.collect{|s| s[0,1].crypt(s)}
17 | random_string = random_strings.join
18 | return random_string.gsub(/[^A-Za-z0-9]/, "")
19 | end
20 | end
--------------------------------------------------------------------------------
/lib/tasks/qwester_tasks.rake:
--------------------------------------------------------------------------------
1 | namespace :qwester do
2 |
3 | # Usage: rake data:reset_questionnaire_positions RAILS_ENV=production
4 | desc "Goes through each of the acts_as_list objects and resets the positions based on order they were added to the database"
5 | task :reset_questionnaire_positions => :environment do
6 |
7 | Qwester::Questionnaire.all.each do |questionnaire|
8 | first_id = questionnaire.questionnaires_questions.minimum(:id)
9 | if first_id # nil if questionnaire has no questions
10 | sql = "UPDATE qwester_questionnaires_questions SET position = (1 + id - #{first_id}) WHERE questionnaire_id = #{questionnaire.id};"
11 | ActiveRecord::Base.connection.execute sql
12 | end
13 | end
14 |
15 | puts "Positions reset"
16 | end
17 |
18 | desc "Removes unpreserved answer stores"
19 | task :destroy_unpreserved_answer_stores => :environment do
20 | before = Qwester::AnswerStore.count
21 | Qwester::AnswerStore.destroy_unpreserved
22 | after = Qwester::AnswerStore.count
23 | puts "#{before - after} answer stores removed, with #{after} remaining."
24 | end
25 |
26 | desc "Reset positions of questionnaires within presentations"
27 | task :reset_presentation_questionnaires_positions => :environment do
28 | Qwester::Presentation.all.each do |presentation|
29 | presentation.presentation_questionnaires.each_with_index do |presentation_questionnaire, index|
30 | presentation_questionnaire.update_attribute(:position, index + 1)
31 | end
32 | puts "Presentation '#{presentation.name}' questionnaires postitioned #{presentation.presentation_questionnaires.collect(&:position)}"
33 | end
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/qwester.gemspec:
--------------------------------------------------------------------------------
1 | $:.push File.expand_path("../lib", __FILE__)
2 |
3 | # Maintain your gem's version:
4 | require "qwester/version"
5 |
6 | # Describe your gem and declare its dependencies:
7 | Gem::Specification.new do |s|
8 | s.name = "qwester"
9 | s.version = Qwester::VERSION
10 | s.authors = ["Rob Nichols"]
11 | s.email = ["rob@undervale.co.uk"]
12 | s.homepage = "https://github.com/reggieb/qwester"
13 | s.summary = "Questionnaire engine with configurable questions and answers"
14 | s.description = "Questionnaires have many questions. Questions have many answers. Answers match Rule Sets. Qwester manages these objects and the relationships that join them."
15 | s.license = "MIT-LICENSE"
16 | s.files = Dir["{app,config,db,lib}/**/*"] + ["MIT-LICENSE", "Rakefile", "README.rdoc"]
17 | s.test_files = Dir["test/**/*"]
18 |
19 | s.add_dependency "rails", '~> 3.2'
20 | s.add_dependency "array_logic" # logic engine used in rule sets
21 | s.add_dependency 'acts_as_list'
22 |
23 | s.add_development_dependency "dibber" # Used for seeding in test/dummy
24 | s.add_development_dependency "sqlite3"
25 | s.add_development_dependency 'activeadmin'
26 | s.add_development_dependency 'sass-rails'
27 | s.add_development_dependency 'uglifier'
28 | s.add_development_dependency 'jquery-ui-rails'
29 | s.add_development_dependency 'jquery-rails'
30 | s.add_development_dependency 'inherited_resources'
31 | s.add_development_dependency 'devise'
32 | s.add_development_dependency 'test-unit'
33 | end
34 |
--------------------------------------------------------------------------------
/script/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3 |
4 | ENGINE_ROOT = File.expand_path('../..', __FILE__)
5 | ENGINE_PATH = File.expand_path('../../lib/qwester/engine', __FILE__)
6 |
7 | require 'rails/all'
8 | require 'rails/engine/commands'
9 |
--------------------------------------------------------------------------------
/test/dummy/README.rdoc:
--------------------------------------------------------------------------------
1 | == Welcome to Rails
2 |
3 | Rails is a web-application framework that includes everything needed to create
4 | database-backed web applications according to the Model-View-Control pattern.
5 |
6 | This pattern splits the view (also called the presentation) into "dumb"
7 | templates that are primarily responsible for inserting pre-built data in between
8 | HTML tags. The model contains the "smart" domain objects (such as Account,
9 | Product, Person, Post) that holds all the business logic and knows how to
10 | persist themselves to a database. The controller handles the incoming requests
11 | (such as Save New Account, Update Product, Show Post) by manipulating the model
12 | and directing data to the view.
13 |
14 | In Rails, the model is handled by what's called an object-relational mapping
15 | layer entitled Active Record. This layer allows you to present the data from
16 | database rows as objects and embellish these data objects with business logic
17 | methods. You can read more about Active Record in
18 | link:files/vendor/rails/activerecord/README.html.
19 |
20 | The controller and view are handled by the Action Pack, which handles both
21 | layers by its two parts: Action View and Action Controller. These two layers
22 | are bundled in a single package due to their heavy interdependence. This is
23 | unlike the relationship between the Active Record and Action Pack that is much
24 | more separate. Each of these packages can be used independently outside of
25 | Rails. You can read more about Action Pack in
26 | link:files/vendor/rails/actionpack/README.html.
27 |
28 |
29 | == Getting Started
30 |
31 | 1. At the command prompt, create a new Rails application:
32 | rails new myapp (where myapp is the application name)
33 |
34 | 2. Change directory to myapp and start the web server:
35 | cd myapp; rails server (run with --help for options)
36 |
37 | 3. Go to http://localhost:3000/ and you'll see:
38 | "Welcome aboard: You're riding Ruby on Rails!"
39 |
40 | 4. Follow the guidelines to start developing your application. You can find
41 | the following resources handy:
42 |
43 | * The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html
44 | * Ruby on Rails Tutorial Book: http://www.railstutorial.org/
45 |
46 |
47 | == Debugging Rails
48 |
49 | Sometimes your application goes wrong. Fortunately there are a lot of tools that
50 | will help you debug it and get it back on the rails.
51 |
52 | First area to check is the application log files. Have "tail -f" commands
53 | running on the server.log and development.log. Rails will automatically display
54 | debugging and runtime information to these files. Debugging info will also be
55 | shown in the browser on requests from 127.0.0.1.
56 |
57 | You can also log your own messages directly into the log file from your code
58 | using the Ruby logger class from inside your controllers. Example:
59 |
60 | class WeblogController < ActionController::Base
61 | def destroy
62 | @weblog = Weblog.find(params[:id])
63 | @weblog.destroy
64 | logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
65 | end
66 | end
67 |
68 | The result will be a message in your log file along the lines of:
69 |
70 | Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1!
71 |
72 | More information on how to use the logger is at http://www.ruby-doc.org/core/
73 |
74 | Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are
75 | several books available online as well:
76 |
77 | * Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe)
78 | * Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
79 |
80 | These two books will bring you up to speed on the Ruby language and also on
81 | programming in general.
82 |
83 |
84 | == Debugger
85 |
86 | Debugger support is available through the debugger command when you start your
87 | Mongrel or WEBrick server with --debugger. This means that you can break out of
88 | execution at any point in the code, investigate and change the model, and then,
89 | resume execution! You need to install ruby-debug to run the server in debugging
90 | mode. With gems, use sudo gem install ruby-debug. Example:
91 |
92 | class WeblogController < ActionController::Base
93 | def index
94 | @posts = Post.all
95 | debugger
96 | end
97 | end
98 |
99 | So the controller will accept the action, run the first line, then present you
100 | with a IRB prompt in the server window. Here you can do things like:
101 |
102 | >> @posts.inspect
103 | => "[#nil, "body"=>nil, "id"=>"1"}>,
105 | #"Rails", "body"=>"Only ten..", "id"=>"2"}>]"
107 | >> @posts.first.title = "hello from a debugger"
108 | => "hello from a debugger"
109 |
110 | ...and even better, you can examine how your runtime objects actually work:
111 |
112 | >> f = @posts.first
113 | => #nil, "body"=>nil, "id"=>"1"}>
114 | >> f.
115 | Display all 152 possibilities? (y or n)
116 |
117 | Finally, when you're ready to resume execution, you can enter "cont".
118 |
119 |
120 | == Console
121 |
122 | The console is a Ruby shell, which allows you to interact with your
123 | application's domain model. Here you'll have all parts of the application
124 | configured, just like it is when the application is running. You can inspect
125 | domain models, change values, and save to the database. Starting the script
126 | without arguments will launch it in the development environment.
127 |
128 | To start the console, run rails console from the application
129 | directory.
130 |
131 | Options:
132 |
133 | * Passing the -s, --sandbox argument will rollback any modifications
134 | made to the database.
135 | * Passing an environment name as an argument will load the corresponding
136 | environment. Example: rails console production.
137 |
138 | To reload your controllers and models after launching the console run
139 | reload!
140 |
141 | More information about irb can be found at:
142 | link:http://www.rubycentral.org/pickaxe/irb.html
143 |
144 |
145 | == dbconsole
146 |
147 | You can go to the command line of your database directly through rails
148 | dbconsole. You would be connected to the database with the credentials
149 | defined in database.yml. Starting the script without arguments will connect you
150 | to the development database. Passing an argument will connect you to a different
151 | database, like rails dbconsole production. Currently works for MySQL,
152 | PostgreSQL and SQLite 3.
153 |
154 | == Description of Contents
155 |
156 | The default directory structure of a generated Ruby on Rails application:
157 |
158 | |-- app
159 | | |-- assets
160 | | |-- images
161 | | |-- javascripts
162 | | `-- stylesheets
163 | | |-- controllers
164 | | |-- helpers
165 | | |-- mailers
166 | | |-- models
167 | | `-- views
168 | | `-- layouts
169 | |-- config
170 | | |-- environments
171 | | |-- initializers
172 | | `-- locales
173 | |-- db
174 | |-- doc
175 | |-- lib
176 | | `-- tasks
177 | |-- log
178 | |-- public
179 | |-- script
180 | |-- test
181 | | |-- fixtures
182 | | |-- functional
183 | | |-- integration
184 | | |-- performance
185 | | `-- unit
186 | |-- tmp
187 | | |-- cache
188 | | |-- pids
189 | | |-- sessions
190 | | `-- sockets
191 | `-- vendor
192 | |-- assets
193 | `-- stylesheets
194 | `-- plugins
195 |
196 | app
197 | Holds all the code that's specific to this particular application.
198 |
199 | app/assets
200 | Contains subdirectories for images, stylesheets, and JavaScript files.
201 |
202 | app/controllers
203 | Holds controllers that should be named like weblogs_controller.rb for
204 | automated URL mapping. All controllers should descend from
205 | ApplicationController which itself descends from ActionController::Base.
206 |
207 | app/models
208 | Holds models that should be named like post.rb. Models descend from
209 | ActiveRecord::Base by default.
210 |
211 | app/views
212 | Holds the template files for the view that should be named like
213 | weblogs/index.html.erb for the WeblogsController#index action. All views use
214 | eRuby syntax by default.
215 |
216 | app/views/layouts
217 | Holds the template files for layouts to be used with views. This models the
218 | common header/footer method of wrapping views. In your views, define a layout
219 | using the layout :default and create a file named default.html.erb.
220 | Inside default.html.erb, call <% yield %> to render the view using this
221 | layout.
222 |
223 | app/helpers
224 | Holds view helpers that should be named like weblogs_helper.rb. These are
225 | generated for you automatically when using generators for controllers.
226 | Helpers can be used to wrap functionality for your views into methods.
227 |
228 | config
229 | Configuration files for the Rails environment, the routing map, the database,
230 | and other dependencies.
231 |
232 | db
233 | Contains the database schema in schema.rb. db/migrate contains all the
234 | sequence of Migrations for your schema.
235 |
236 | doc
237 | This directory is where your application documentation will be stored when
238 | generated using rake doc:app
239 |
240 | lib
241 | Application specific libraries. Basically, any kind of custom code that
242 | doesn't belong under controllers, models, or helpers. This directory is in
243 | the load path.
244 |
245 | public
246 | The directory available for the web server. Also contains the dispatchers and the
247 | default HTML files. This should be set as the DOCUMENT_ROOT of your web
248 | server.
249 |
250 | script
251 | Helper scripts for automation and generation.
252 |
253 | test
254 | Unit and functional tests along with fixtures. When using the rails generate
255 | command, template test files will be generated for you and placed in this
256 | directory.
257 |
258 | vendor
259 | External libraries that the application depends on. Also includes the plugins
260 | subdirectory. If the app has frozen rails, those gems also go here, under
261 | vendor/rails/. This directory is in the load path.
262 |
--------------------------------------------------------------------------------
/test/dummy/Rakefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env rake
2 | # Add your own tasks in files placed in lib/tasks ending in .rake,
3 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4 |
5 | require File.expand_path('../config/application', __FILE__)
6 |
7 | Dummy::Application.load_tasks
8 |
--------------------------------------------------------------------------------
/test/dummy/app/admin/admin_user.rb:
--------------------------------------------------------------------------------
1 | require_relative '../models/admin_user'
2 | ActiveAdmin.register AdminUser do
3 | index do
4 | column :email
5 | column :current_sign_in_at
6 | column :last_sign_in_at
7 | column :sign_in_count
8 | default_actions
9 | end
10 |
11 | filter :email
12 |
13 | form do |f|
14 | f.inputs "Admin Details" do
15 | f.input :email
16 | f.input :password
17 | f.input :password_confirmation
18 | end
19 | f.actions
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/test/dummy/app/admin/dashboard.rb:
--------------------------------------------------------------------------------
1 | ActiveAdmin.register_page "Dashboard" do
2 |
3 | menu :priority => 1, :label => proc{ I18n.t("active_admin.dashboard") }
4 |
5 | content :title => proc{ I18n.t("active_admin.dashboard") } do
6 | div :class => "blank_slate_container", :id => "dashboard_default_message" do
7 | span :class => "blank_slate" do
8 | span I18n.t("active_admin.dashboard_welcome.welcome")
9 | small I18n.t("active_admin.dashboard_welcome.call_to_action")
10 | end
11 | end
12 |
13 | # Here is an example of a simple dashboard with columns and panels.
14 | #
15 | # columns do
16 | # column do
17 | # panel "Recent Posts" do
18 | # ul do
19 | # Post.recent(5).map do |post|
20 | # li link_to(post.title, admin_post_path(post))
21 | # end
22 | # end
23 | # end
24 | # end
25 |
26 | # column do
27 | # panel "Info" do
28 | # para "Welcome to ActiveAdmin."
29 | # end
30 | # end
31 | # end
32 | end # content
33 | end if defined?(ActiveAdmin)
34 |
--------------------------------------------------------------------------------
/test/dummy/app/assets/javascripts/active_admin.js:
--------------------------------------------------------------------------------
1 | //= require active_admin/application
2 |
3 | $(function() {
4 | if (!!$.prototype.tooltip) {
5 | $( '#questions' ).tooltip();
6 | }
7 |
8 | $(".associated_questions :checkbox").change(function(event) {
9 |
10 | var action = event.target.checked ? 'add' : 'delete';
11 |
12 | $.ajax({
13 | type: "PUT",
14 | url: 'answers/' + event.target.value + '/' + action,
15 |
16 | success: function () {
17 | //console.log('Successfully retrieved ' + name);
18 | },
19 | error: function () {
20 | //console.log('Error retrieving ' + name);
21 | }
22 | })
23 | });
24 |
25 | });
26 |
--------------------------------------------------------------------------------
/test/dummy/app/assets/javascripts/application.js:
--------------------------------------------------------------------------------
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 .
16 |
--------------------------------------------------------------------------------
/test/dummy/app/assets/javascripts/questionnaires.js:
--------------------------------------------------------------------------------
1 | // Place all the behaviors and hooks related to the matching controller here.
2 | // All this logic will automatically be available in application.js.
3 |
--------------------------------------------------------------------------------
/test/dummy/app/assets/stylesheets/active_admin.css.scss:
--------------------------------------------------------------------------------
1 | // SASS variable overrides must be declared before loading up Active Admin's styles.
2 | //
3 | // To view the variables that Active Admin provides, take a look at
4 | // `app/assets/stylesheets/active_admin/mixins/_variables.css.scss` in the
5 | // Active Admin source.
6 | //
7 | // For example, to change the sidebar width:
8 | // $sidebar-width: 242px;
9 |
10 | // Overriding any non-variable SASS must be done after the fact.
11 | // For example, to change the default status-tag color:
12 | //
13 | // body.active_admin {
14 | // .status_tag { background: #6090DB; }
15 | // }
16 | //
17 | // Notice that Active Admin CSS rules are nested within a
18 | // 'body.active_admin' selector to prevent conflicts with
19 | // other pages in the app. It is best to wrap your changes in a
20 | // namespace so they are properly recognized. You have options
21 | // if you e.g. want different styles for different namespaces:
22 | //
23 | // .active_admin applies to any Active Admin namespace
24 | // .admin_namespace applies to the admin namespace (eg: /admin)
25 | // .other_namespace applies to a custom namespace named other (eg: /other)
26 |
27 | body.active_admin {
28 |
29 | a.no_decoration {
30 | text-decoration: none;
31 | color: #323537;
32 | }
33 |
34 | form {
35 |
36 | table.selection {
37 | width: inherit;
38 | tr:nth-child(odd) {
39 | background-color: #d9e4ec;
40 | }
41 |
42 | .options input {
43 | margin-right: 1em;
44 | }
45 | }
46 | }
47 |
48 | .rule_set h2{
49 | margin-top: 1em;
50 | }
51 |
52 | table.sortable_list {
53 | width: inherit;
54 | margin-left: 20px;
55 | }
56 |
57 | ul.matching_answers {
58 | border: black 1px solid;
59 | padding: 10px;
60 |
61 | li {
62 | list-style: none;
63 | }
64 | }
65 |
66 | .rule_example {
67 | margin: 10px 20px 30px;
68 | }
69 |
70 | div.warn {
71 | border: red solid 2px;
72 | padding: 0;
73 | margin: 10px;
74 |
75 | h3 {
76 | background-color: red;
77 | margin: 0;
78 | padding: 5px 10px;
79 | color: white;
80 | }
81 |
82 | p {
83 | padding: 5px 10px;
84 | font-size: 1.2em;
85 | }
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/test/dummy/app/assets/stylesheets/application.css:
--------------------------------------------------------------------------------
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 | */
14 |
--------------------------------------------------------------------------------
/test/dummy/app/assets/stylesheets/questionnaires.css.scss:
--------------------------------------------------------------------------------
1 | // Place all the styles related to the questionnaires controller here.
2 | // They will automatically be included in application.css.
3 | // You can use Sass (SCSS) here: http://sass-lang.com/
4 |
5 | .questionnaire {
6 | display: inline-block;
7 | }
8 |
--------------------------------------------------------------------------------
/test/dummy/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::Base
2 | protect_from_forgery
3 | end
4 |
--------------------------------------------------------------------------------
/test/dummy/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 | end
3 |
--------------------------------------------------------------------------------
/test/dummy/app/mailers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reggieb/qwester/458690e814c83405edb32404eb45b06dc5fc8f59/test/dummy/app/mailers/.gitkeep
--------------------------------------------------------------------------------
/test/dummy/app/models/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reggieb/qwester/458690e814c83405edb32404eb45b06dc5fc8f59/test/dummy/app/models/.gitkeep
--------------------------------------------------------------------------------
/test/dummy/app/models/admin_user.rb:
--------------------------------------------------------------------------------
1 | #require 'active_admin'
2 | class AdminUser < ActiveRecord::Base
3 | # Include default devise modules. Others available are:
4 | # :token_authenticatable, :confirmable,
5 | # :lockable, :timeoutable and :omniauthable
6 | devise :database_authenticatable,
7 | :recoverable, :rememberable, :trackable, :validatable
8 |
9 | # Setup accessible (or protected) attributes for your model
10 | attr_accessible :email, :password, :password_confirmation, :remember_me
11 | end
12 |
--------------------------------------------------------------------------------
/test/dummy/app/views/layouts/application.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Dummy
5 | <%= stylesheet_link_tag "application", :media => "all" %>
6 | <%= javascript_include_tag "application" %>
7 | <%= csrf_meta_tags %>
8 |
9 |
10 |
11 | <%= yield %>
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/test/dummy/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require ::File.expand_path('../config/environment', __FILE__)
4 | run Dummy::Application
5 |
--------------------------------------------------------------------------------
/test/dummy/config/application.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path('../boot', __FILE__)
2 | require "inherited_resources"
3 | require 'devise'
4 |
5 | require 'rails/all'
6 |
7 | Bundler.require
8 | require "qwester"
9 |
10 | module Dummy
11 | class Application < Rails::Application
12 | # Settings in config/environments/* take precedence over those specified here.
13 | # Application configuration should go into files in config/initializers
14 | # -- all .rb files in that directory are automatically loaded.
15 |
16 | # Custom directories with classes and modules you want to be autoloadable.
17 | # config.autoload_paths += %W(#{config.root}/extras)
18 |
19 | # Only load the plugins named here, in the order given (default is alphabetical).
20 | # :all can be used as a placeholder for all plugins not explicitly named.
21 | # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
22 |
23 | # Activate observers that should always be running.
24 | # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
25 |
26 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
27 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
28 | # config.time_zone = 'Central Time (US & Canada)'
29 |
30 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
31 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
32 | # config.i18n.default_locale = :de
33 |
34 | # Configure the default encoding used in templates for Ruby 1.9.
35 | config.encoding = "utf-8"
36 |
37 | # Configure sensitive parameters which will be filtered from the log file.
38 | config.filter_parameters += [:password]
39 |
40 | # Enable escaping HTML in JSON.
41 | config.active_support.escape_html_entities_in_json = true
42 |
43 | # Use SQL instead of Active Record's schema dumper when creating the database.
44 | # This is necessary if your schema can't be completely dumped by the schema dumper,
45 | # like if you have constraints or database-specific column types
46 | # config.active_record.schema_format = :sql
47 |
48 | # Enforce whitelist mode for mass assignment.
49 | # This will create an empty whitelist of attributes available for mass-assignment for all models
50 | # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
51 | # parameters by using an attr_accessible or attr_protected declaration.
52 | config.active_record.whitelist_attributes = true
53 |
54 | # Enable the asset pipeline
55 | config.assets.enabled = true
56 |
57 | # Version of your assets, change this if you want to expire all your assets
58 | config.assets.version = '1.0'
59 | end
60 | end
61 |
62 |
--------------------------------------------------------------------------------
/test/dummy/config/boot.rb:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 | gemfile = File.expand_path('../../../../Gemfile', __FILE__)
3 |
4 | if File.exist?(gemfile)
5 | ENV['BUNDLE_GEMFILE'] = gemfile
6 | require 'bundler'
7 | Bundler.setup
8 | end
9 |
10 | $:.unshift File.expand_path('../../../../lib', __FILE__)
--------------------------------------------------------------------------------
/test/dummy/config/database.yml:
--------------------------------------------------------------------------------
1 | # SQLite version 3.x
2 | # gem install sqlite3
3 | #
4 | # Ensure the SQLite 3 gem is defined in your Gemfile
5 | # gem 'sqlite3'
6 | development:
7 | adapter: sqlite3
8 | database: db/development.sqlite3
9 | pool: 5
10 | timeout: 5000
11 |
12 | # Warning: The database defined as "test" will be erased and
13 | # re-generated from your development database when you run "rake".
14 | # Do not set this db to the same as development or production.
15 | test:
16 | adapter: sqlite3
17 | database: db/test.sqlite3
18 | pool: 5
19 | timeout: 5000
20 |
21 | production:
22 | adapter: sqlite3
23 | database: db/production.sqlite3
24 | pool: 5
25 | timeout: 5000
26 |
--------------------------------------------------------------------------------
/test/dummy/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the rails application
2 | require File.expand_path('../application', __FILE__)
3 |
4 | # Load elements needed for active admin to work in dummy
5 |
6 | require 'action_controller'
7 | require 'active_support/log_subscriber'
8 | require 'inherited_resources'
9 | require 'devise'
10 |
11 | # Initialize the rails application
12 | Dummy::Application.initialize!
13 |
--------------------------------------------------------------------------------
/test/dummy/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | Dummy::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # In the development environment your application's code is reloaded on
5 | # every request. This slows down response time but is perfect for development
6 | # since you don't have to restart the web server when you make code changes.
7 | config.cache_classes = false
8 |
9 | # Log error messages when you accidentally call methods on nil.
10 | config.whiny_nils = true
11 |
12 | # Show full error reports and disable caching
13 | config.consider_all_requests_local = true
14 | config.action_controller.perform_caching = false
15 |
16 | # Don't care if the mailer can't send
17 | config.action_mailer.raise_delivery_errors = false
18 |
19 | # Print deprecation notices to the Rails logger
20 | config.active_support.deprecation = :log
21 |
22 | # Only use best-standards-support built into browsers
23 | config.action_dispatch.best_standards_support = :builtin
24 |
25 | # Raise exception on mass assignment protection for Active Record models
26 | config.active_record.mass_assignment_sanitizer = :strict
27 |
28 | # Log the query plan for queries taking more than this (works
29 | # with SQLite, MySQL, and PostgreSQL)
30 | config.active_record.auto_explain_threshold_in_seconds = 0.5
31 |
32 | # Do not compress assets
33 | config.assets.compress = false
34 |
35 | # Expands the lines which load the assets
36 | config.assets.debug = true
37 | end
38 |
--------------------------------------------------------------------------------
/test/dummy/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | Dummy::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # Code is not reloaded between requests
5 | config.cache_classes = true
6 |
7 | # Full error reports are disabled and caching is turned on
8 | config.consider_all_requests_local = false
9 | config.action_controller.perform_caching = true
10 |
11 | # Disable Rails's static asset server (Apache or nginx will already do this)
12 | config.serve_static_assets = false
13 |
14 | # Compress JavaScripts and CSS
15 | config.assets.compress = true
16 |
17 | # Don't fallback to assets pipeline if a precompiled asset is missed
18 | config.assets.compile = false
19 |
20 | # Generate digests for assets URLs
21 | config.assets.digest = true
22 |
23 | # Defaults to nil and saved in location specified by config.assets.prefix
24 | # config.assets.manifest = YOUR_PATH
25 |
26 | # Specifies the header that your server uses for sending files
27 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
28 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
29 |
30 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
31 | # config.force_ssl = true
32 |
33 | # See everything in the log (default is :info)
34 | # config.log_level = :debug
35 |
36 | # Prepend all log lines with the following tags
37 | # config.log_tags = [ :subdomain, :uuid ]
38 |
39 | # Use a different logger for distributed setups
40 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
41 |
42 | # Use a different cache store in production
43 | # config.cache_store = :mem_cache_store
44 |
45 | # Enable serving of images, stylesheets, and JavaScripts from an asset server
46 | # config.action_controller.asset_host = "http://assets.example.com"
47 |
48 | # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
49 | # config.assets.precompile += %w( search.js )
50 |
51 | # Disable delivery errors, bad email addresses will be ignored
52 | # config.action_mailer.raise_delivery_errors = false
53 |
54 | # Enable threaded mode
55 | # config.threadsafe!
56 |
57 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
58 | # the I18n.default_locale when a translation can not be found)
59 | config.i18n.fallbacks = true
60 |
61 | # Send deprecation notices to registered listeners
62 | config.active_support.deprecation = :notify
63 |
64 | # Log the query plan for queries taking more than this (works
65 | # with SQLite, MySQL, and PostgreSQL)
66 | # config.active_record.auto_explain_threshold_in_seconds = 0.5
67 | end
68 |
--------------------------------------------------------------------------------
/test/dummy/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | Dummy::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # The test environment is used exclusively to run your application's
5 | # test suite. You never need to work with it otherwise. Remember that
6 | # your test database is "scratch space" for the test suite and is wiped
7 | # and recreated between test runs. Don't rely on the data there!
8 | config.cache_classes = true
9 |
10 | # Configure static asset server for tests with Cache-Control for performance
11 | config.serve_static_assets = true
12 | config.static_cache_control = "public, max-age=3600"
13 |
14 | # Log error messages when you accidentally call methods on nil
15 | config.whiny_nils = true
16 |
17 | # Show full error reports and disable caching
18 | config.consider_all_requests_local = true
19 | config.action_controller.perform_caching = false
20 |
21 | # Raise exceptions instead of rendering exception templates
22 | config.action_dispatch.show_exceptions = false
23 |
24 | # Disable request forgery protection in test environment
25 | config.action_controller.allow_forgery_protection = false
26 |
27 | # Tell Action Mailer not to deliver emails to the real world.
28 | # The :test delivery method accumulates sent emails in the
29 | # ActionMailer::Base.deliveries array.
30 | config.action_mailer.delivery_method = :test
31 |
32 | # Raise exception on mass assignment protection for Active Record models
33 | config.active_record.mass_assignment_sanitizer = :strict
34 |
35 | # Print deprecation notices to the stderr
36 | config.active_support.deprecation = :stderr
37 | end
38 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/active_admin.rb:
--------------------------------------------------------------------------------
1 | require 'active_admin'
2 | ActiveAdmin.setup do |config|
3 |
4 | # == Site Title
5 | #
6 | # Set the title that is displayed on the main layout
7 | # for each of the active admin pages.
8 | #
9 | config.site_title = "Dummy"
10 |
11 | # Set the link url for the title. For example, to take
12 | # users to your main site. Defaults to no link.
13 | #
14 | # config.site_title_link = "/"
15 |
16 | # Set an optional image to be displayed for the header
17 | # instead of a string (overrides :site_title)
18 | #
19 | # Note: Recommended image height is 21px to properly fit in the header
20 | #
21 | # config.site_title_image = "/images/logo.png"
22 |
23 | # == Default Namespace
24 | #
25 | # Set the default namespace each administration resource
26 | # will be added to.
27 | #
28 | # eg:
29 | # config.default_namespace = :hello_world
30 | #
31 | # This will create resources in the HelloWorld module and
32 | # will namespace routes to /hello_world/*
33 | #
34 | # To set no namespace by default, use:
35 | # config.default_namespace = false
36 | #
37 | # Default:
38 | # config.default_namespace = :admin
39 | #
40 | # You can customize the settings for each namespace by using
41 | # a namespace block. For example, to change the site title
42 | # within a namespace:
43 | #
44 | # config.namespace :admin do |admin|
45 | # admin.site_title = "Custom Admin Title"
46 | # end
47 | #
48 | # This will ONLY change the title for the admin section. Other
49 | # namespaces will continue to use the main "site_title" configuration.
50 |
51 | # == User Authentication
52 | #
53 | # Active Admin will automatically call an authentication
54 | # method in a before filter of all controller actions to
55 | # ensure that there is a currently logged in admin user.
56 | #
57 | # This setting changes the method which Active Admin calls
58 | # within the controller.
59 | config.authentication_method = :authenticate_admin_user!
60 |
61 |
62 | # == Current User
63 | #
64 | # Active Admin will associate actions with the current
65 | # user performing them.
66 | #
67 | # This setting changes the method which Active Admin calls
68 | # to return the currently logged in user.
69 | config.current_user_method = :current_admin_user
70 |
71 |
72 | # == Logging Out
73 | #
74 | # Active Admin displays a logout link on each screen. These
75 | # settings configure the location and method used for the link.
76 | #
77 | # This setting changes the path where the link points to. If it's
78 | # a string, the strings is used as the path. If it's a Symbol, we
79 | # will call the method to return the path.
80 | #
81 | # Default:
82 | config.logout_link_path = :destroy_admin_user_session_path
83 |
84 | # This setting changes the http method used when rendering the
85 | # link. For example :get, :delete, :put, etc..
86 | #
87 | # Default:
88 | # config.logout_link_method = :get
89 |
90 | # == Root
91 | #
92 | # Set the action to call for the root path. You can set different
93 | # roots for each namespace.
94 | #
95 | # Default:
96 | # config.root_to = 'dashboard#index'
97 |
98 | # == Admin Comments
99 | #
100 | # Admin comments allow you to add comments to any model for admin use.
101 | # Admin comments are enabled by default.
102 | #
103 | # Default:
104 | # config.allow_comments = true
105 | #
106 | # You can turn them on and off for any given namespace by using a
107 | # namespace config block.
108 | #
109 | # Eg:
110 | # config.namespace :without_comments do |without_comments|
111 | # without_comments.allow_comments = false
112 | # end
113 |
114 |
115 | # == Batch Actions
116 | #
117 | # Enable and disable Batch Actions
118 | #
119 | config.batch_actions = true
120 |
121 |
122 | # == Controller Filters
123 | #
124 | # You can add before, after and around filters to all of your
125 | # Active Admin resources and pages from here.
126 | #
127 | # config.before_filter :do_something_awesome
128 |
129 |
130 | # == Register Stylesheets & Javascripts
131 | #
132 | # We recommend using the built in Active Admin layout and loading
133 | # up your own stylesheets / javascripts to customize the look
134 | # and feel.
135 | #
136 | # To load a stylesheet:
137 | # config.register_stylesheet 'my_stylesheet.css'
138 |
139 | # You can provide an options hash for more control, which is passed along to stylesheet_link_tag():
140 | # config.register_stylesheet 'my_print_stylesheet.css', :media => :print
141 | #
142 | # To load a javascript file:
143 | # config.register_javascript 'my_javascript.js'
144 | # Load application.js to remove jQuery conflicts (so jquery is only loaded in application.js):
145 | current_javascripts = config.javascripts.clone
146 | config.clear_javascripts!
147 | config.register_javascript 'application.js'
148 | current_javascripts.reverse_each{|j| config.register_javascript j}
149 |
150 | # == CSV options
151 | #
152 | # Set the CSV builder separator (default is ",")
153 | # config.csv_column_separator = ','
154 | #
155 | # Set the CSV builder options (default is {})
156 | # config.csv_options = {}
157 |
158 | config.load_paths << Qwester.active_admin_load_path
159 |
160 | end
161 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7 | # Rails.backtrace_cleaner.remove_silencers!
8 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/devise.rb:
--------------------------------------------------------------------------------
1 | # Use this hook to configure devise mailer, warden hooks and so forth.
2 | # Many of these configuration options can be set straight in your model.
3 | Devise.setup do |config|
4 |
5 | config.secret_key = '778bf64a3ff719bae4179047012814a0ab280525f3b37e8bc9aba3b2928b2e110588950a4231070581e2155495a5bff3f252d5ce51a9dbcb25410cb76d356b57'
6 |
7 | # ==> Mailer Configuration
8 | # Configure the e-mail address which will be shown in Devise::Mailer,
9 | # note that it will be overwritten if you use your own mailer class with default "from" parameter.
10 | config.mailer_sender = "please-change-me-at-config-initializers-devise@example.com"
11 |
12 | # Configure the class responsible to send e-mails.
13 | # config.mailer = "Devise::Mailer"
14 |
15 | # ==> ORM configuration
16 | # Load and configure the ORM. Supports :active_record (default) and
17 | # :mongoid (bson_ext recommended) by default. Other ORMs may be
18 | # available as additional gems.
19 | require 'devise/orm/active_record'
20 |
21 | # ==> Configuration for any authentication mechanism
22 | # Configure which keys are used when authenticating a user. The default is
23 | # just :email. You can configure it to use [:username, :subdomain], so for
24 | # authenticating a user, both parameters are required. Remember that those
25 | # parameters are used only when authenticating and not when retrieving from
26 | # session. If you need permissions, you should implement that in a before filter.
27 | # You can also supply a hash where the value is a boolean determining whether
28 | # or not authentication should be aborted when the value is not present.
29 | # config.authentication_keys = [ :email ]
30 |
31 | # Configure parameters from the request object used for authentication. Each entry
32 | # given should be a request method and it will automatically be passed to the
33 | # find_for_authentication method and considered in your model lookup. For instance,
34 | # if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
35 | # The same considerations mentioned for authentication_keys also apply to request_keys.
36 | # config.request_keys = []
37 |
38 | # Configure which authentication keys should be case-insensitive.
39 | # These keys will be downcased upon creating or modifying a user and when used
40 | # to authenticate or find a user. Default is :email.
41 | config.case_insensitive_keys = [ :email ]
42 |
43 | # Configure which authentication keys should have whitespace stripped.
44 | # These keys will have whitespace before and after removed upon creating or
45 | # modifying a user and when used to authenticate or find a user. Default is :email.
46 | config.strip_whitespace_keys = [ :email ]
47 |
48 | # Tell if authentication through request.params is enabled. True by default.
49 | # It can be set to an array that will enable params authentication only for the
50 | # given strategies, for example, `config.params_authenticatable = [:database]` will
51 | # enable it only for database (email + password) authentication.
52 | # config.params_authenticatable = true
53 |
54 | # Tell if authentication through HTTP Basic Auth is enabled. False by default.
55 | # It can be set to an array that will enable http authentication only for the
56 | # given strategies, for example, `config.http_authenticatable = [:token]` will
57 | # enable it only for token authentication.
58 | # config.http_authenticatable = false
59 |
60 | # If http headers should be returned for AJAX requests. True by default.
61 | # config.http_authenticatable_on_xhr = true
62 |
63 | # The realm used in Http Basic Authentication. "Application" by default.
64 | # config.http_authentication_realm = "Application"
65 |
66 | # It will change confirmation, password recovery and other workflows
67 | # to behave the same regardless if the e-mail provided was right or wrong.
68 | # Does not affect registerable.
69 | # config.paranoid = true
70 |
71 | # By default Devise will store the user in session. You can skip storage for
72 | # :http_auth and :token_auth by adding those symbols to the array below.
73 | # Notice that if you are skipping storage for all authentication paths, you
74 | # may want to disable generating routes to Devise's sessions controller by
75 | # passing :skip => :sessions to `devise_for` in your config/routes.rb
76 | config.skip_session_storage = [:http_auth]
77 |
78 | # ==> Configuration for :database_authenticatable
79 | # For bcrypt, this is the cost for hashing the password and defaults to 10. If
80 | # using other encryptors, it sets how many times you want the password re-encrypted.
81 | #
82 | # Limiting the stretches to just one in testing will increase the performance of
83 | # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
84 | # a value less than 10 in other environments.
85 | config.stretches = Rails.env.test? ? 1 : 10
86 |
87 | # Setup a pepper to generate the encrypted password.
88 | # config.pepper = "097e57758dd9c4386f41c5209b8af01637d4d0141e750b616397f7f2a6e966b8b27aab567081c13314369ad78d562fdd783181a7fb2f839b19382dc5833b4235"
89 |
90 | # ==> Configuration for :confirmable
91 | # A period that the user is allowed to access the website even without
92 | # confirming his account. For instance, if set to 2.days, the user will be
93 | # able to access the website for two days without confirming his account,
94 | # access will be blocked just in the third day. Default is 0.days, meaning
95 | # the user cannot access the website without confirming his account.
96 | # config.allow_unconfirmed_access_for = 2.days
97 |
98 | # A period that the user is allowed to confirm their account before their
99 | # token becomes invalid. For example, if set to 3.days, the user can confirm
100 | # their account within 3 days after the mail was sent, but on the fourth day
101 | # their account can't be confirmed with the token any more.
102 | # Default is nil, meaning there is no restriction on how long a user can take
103 | # before confirming their account.
104 | # config.confirm_within = 3.days
105 |
106 | # If true, requires any email changes to be confirmed (exactly the same way as
107 | # initial account confirmation) to be applied. Requires additional unconfirmed_email
108 | # db field (see migrations). Until confirmed new email is stored in
109 | # unconfirmed email column, and copied to email column on successful confirmation.
110 | config.reconfirmable = true
111 |
112 | # Defines which key will be used when confirming an account
113 | # config.confirmation_keys = [ :email ]
114 |
115 | # ==> Configuration for :rememberable
116 | # The time the user will be remembered without asking for credentials again.
117 | # config.remember_for = 2.weeks
118 |
119 | # If true, extends the user's remember period when remembered via cookie.
120 | # config.extend_remember_period = false
121 |
122 | # Options to be passed to the created cookie. For instance, you can set
123 | # :secure => true in order to force SSL only cookies.
124 | # config.rememberable_options = {}
125 |
126 | # ==> Configuration for :validatable
127 | # Range for password length. Default is 8..128.
128 | config.password_length = 8..128
129 |
130 | # Email regex used to validate email formats. It simply asserts that
131 | # an one (and only one) @ exists in the given string. This is mainly
132 | # to give user feedback and not to assert the e-mail validity.
133 | # config.email_regexp = /\A[^@]+@[^@]+\z/
134 |
135 | # ==> Configuration for :timeoutable
136 | # The time you want to timeout the user session without activity. After this
137 | # time the user will be asked for credentials again. Default is 30 minutes.
138 | # config.timeout_in = 30.minutes
139 |
140 | # If true, expires auth token on session timeout.
141 | # config.expire_auth_token_on_timeout = false
142 |
143 | # ==> Configuration for :lockable
144 | # Defines which strategy will be used to lock an account.
145 | # :failed_attempts = Locks an account after a number of failed attempts to sign in.
146 | # :none = No lock strategy. You should handle locking by yourself.
147 | # config.lock_strategy = :failed_attempts
148 |
149 | # Defines which key will be used when locking and unlocking an account
150 | # config.unlock_keys = [ :email ]
151 |
152 | # Defines which strategy will be used to unlock an account.
153 | # :email = Sends an unlock link to the user email
154 | # :time = Re-enables login after a certain amount of time (see :unlock_in below)
155 | # :both = Enables both strategies
156 | # :none = No unlock strategy. You should handle unlocking by yourself.
157 | # config.unlock_strategy = :both
158 |
159 | # Number of authentication tries before locking an account if lock_strategy
160 | # is failed attempts.
161 | # config.maximum_attempts = 20
162 |
163 | # Time interval to unlock the account if :time is enabled as unlock_strategy.
164 | # config.unlock_in = 1.hour
165 |
166 | # ==> Configuration for :recoverable
167 | #
168 | # Defines which key will be used when recovering the password for an account
169 | # config.reset_password_keys = [ :email ]
170 |
171 | # Time interval you can reset your password with a reset password key.
172 | # Don't put a too small interval or your users won't have the time to
173 | # change their passwords.
174 | config.reset_password_within = 6.hours
175 |
176 | # ==> Configuration for :encryptable
177 | # Allow you to use another encryption algorithm besides bcrypt (default). You can use
178 | # :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
179 | # :authlogic_sha512 (then you should set stretches above to 20 for default behavior)
180 | # and :restful_authentication_sha1 (then you should set stretches to 10, and copy
181 | # REST_AUTH_SITE_KEY to pepper)
182 | # config.encryptor = :sha512
183 |
184 | # ==> Configuration for :token_authenticatable
185 | # Defines name of the authentication token params key
186 | # config.token_authentication_key = :auth_token
187 |
188 | # ==> Scopes configuration
189 | # Turn scoped views on. Before rendering "sessions/new", it will first check for
190 | # "users/sessions/new". It's turned off by default because it's slower if you
191 | # are using only default views.
192 | # config.scoped_views = false
193 |
194 | # Configure the default scope given to Warden. By default it's the first
195 | # devise role declared in your routes (usually :user).
196 | # config.default_scope = :user
197 |
198 | # Set this configuration to false if you want /users/sign_out to sign out
199 | # only the current scope. By default, Devise signs out all scopes.
200 | # config.sign_out_all_scopes = true
201 |
202 | # ==> Navigation configuration
203 | # Lists the formats that should be treated as navigational. Formats like
204 | # :html, should redirect to the sign in page when the user does not have
205 | # access, but formats like :xml or :json, should return 401.
206 | #
207 | # If you have any extra navigational formats, like :iphone or :mobile, you
208 | # should add them to the navigational formats lists.
209 | #
210 | # The "*/*" below is required to match Internet Explorer requests.
211 | # config.navigational_formats = ["*/*", :html]
212 |
213 | # The default HTTP method used to sign out a resource. Default is :delete.
214 | config.sign_out_via = :delete
215 |
216 | # ==> OmniAuth
217 | # Add a new OmniAuth provider. Check the wiki for more information on setting
218 | # up on your models and hooks.
219 | # config.omniauth :github, 'APP_ID', 'APP_SECRET', :scope => 'user,public_repo'
220 |
221 | # ==> Warden configuration
222 | # If you want to use other strategies, that are not supported by Devise, or
223 | # change the failure app, you can configure them inside the config.warden block.
224 | #
225 | # config.warden do |manager|
226 | # manager.intercept_401 = false
227 | # manager.default_strategies(:scope => :user).unshift :some_external_strategy
228 | # end
229 |
230 | # ==> Mountable engine configurations
231 | # When using Devise inside an engine, let's call it `MyEngine`, and this engine
232 | # is mountable, there are some extra configurations to be taken into account.
233 | # The following options are available, assuming the engine is mounted as:
234 | #
235 | # mount MyEngine, at: "/my_engine"
236 | #
237 | # The router that invoked `devise_for`, in the example above, would be:
238 | # config.router_name = :my_engine
239 | #
240 | # When using omniauth, Devise cannot automatically set Omniauth path,
241 | # so you need to do it manually. For the users scope, it would be:
242 | # config.omniauth_path_prefix = "/my_engine/users/auth"
243 | end if defined?(Devise)
244 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format
4 | # (all these examples are active by default):
5 | # ActiveSupport::Inflector.inflections do |inflect|
6 | # inflect.plural /^(ox)$/i, '\1en'
7 | # inflect.singular /^(ox)en/i, '\1'
8 | # inflect.irregular 'person', 'people'
9 | # inflect.uncountable %w( fish sheep )
10 | # end
11 | #
12 | # These inflection rules are supported but not enabled by default:
13 | # ActiveSupport::Inflector.inflections do |inflect|
14 | # inflect.acronym 'RESTful'
15 | # end
16 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 | # Mime::Type.register_alias "text/html", :iphone
6 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/qwester.rb:
--------------------------------------------------------------------------------
1 |
2 | Qwester.active_admin_menu = 'Q and A'
3 |
4 | Qwester::Answer.weighting_alias = :score
--------------------------------------------------------------------------------
/test/dummy/config/initializers/secret_token.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Your secret key for verifying the integrity of signed cookies.
4 | # If you change this key, all old signed cookies will become invalid!
5 | # Make sure the secret is at least 30 characters and all random,
6 | # no regular words or you'll be exposed to dictionary attacks.
7 | Dummy::Application.config.secret_token = '589061f57c9df78def70559f67cb5186b8c8831efdca6fcc6bb3ce5382bb201ccf33d41e686f44036893ea13df3f5871251d467bb2f1064e85f1dc9db33d89e7'
8 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/session_store.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | Dummy::Application.config.session_store(:cookie_store, key: '_dummy_session')
4 |
5 | # Use the database for sessions instead of the cookie-based default,
6 | # which shouldn't be used to store highly confidential information
7 | # (create the session table with "rails generate session_migration")
8 | # Dummy::Application.config.session_store :active_record_store
9 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 | #
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters(format: [:json])
9 | end
10 |
11 | # Disable root element in JSON by default.
12 | ActiveSupport.on_load(:active_record) do
13 | self.include_root_in_json = false
14 | end
15 |
--------------------------------------------------------------------------------
/test/dummy/config/locales/devise.en.yml:
--------------------------------------------------------------------------------
1 | # Additional translations at https://github.com/plataformatec/devise/wiki/I18n
2 |
3 | en:
4 | errors:
5 | messages:
6 | expired: "has expired, please request a new one"
7 | not_found: "not found"
8 | already_confirmed: "was already confirmed, please try signing in"
9 | not_locked: "was not locked"
10 | not_saved:
11 | one: "1 error prohibited this %{resource} from being saved:"
12 | other: "%{count} errors prohibited this %{resource} from being saved:"
13 | confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
14 |
15 | devise:
16 | failure:
17 | already_authenticated: 'You are already signed in.'
18 | unauthenticated: 'You need to sign in or sign up before continuing.'
19 | unconfirmed: 'You have to confirm your account before continuing.'
20 | locked: 'Your account is locked.'
21 | not_found_in_database: 'Invalid email or password.'
22 | invalid: 'Invalid email or password.'
23 | invalid_token: 'Invalid authentication token.'
24 | timeout: 'Your session expired, please sign in again to continue.'
25 | inactive: 'Your account was not activated yet.'
26 | sessions:
27 | signed_in: 'Signed in successfully.'
28 | signed_out: 'Signed out successfully.'
29 | passwords:
30 | send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
31 | updated: 'Your password was changed successfully. You are now signed in.'
32 | updated_not_active: 'Your password was changed successfully.'
33 | send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
34 | no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
35 | confirmations:
36 | send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
37 | send_paranoid_instructions: 'If your email address exists in our database, you will receive an email with instructions about how to confirm your account in a few minutes.'
38 | confirmed: 'Your account was successfully confirmed. You are now signed in.'
39 | registrations:
40 | signed_up: 'Welcome! You have signed up successfully.'
41 | signed_up_but_unconfirmed: 'A message with a confirmation link has been sent to your email address. Please open the link to activate your account.'
42 | signed_up_but_inactive: 'You have signed up successfully. However, we could not sign you in because your account is not yet activated.'
43 | signed_up_but_locked: 'You have signed up successfully. However, we could not sign you in because your account is locked.'
44 | updated: 'You updated your account successfully.'
45 | update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and click on the confirm link to finalize confirming your new email address."
46 | destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
47 | unlocks:
48 | send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
49 | unlocked: 'Your account has been unlocked successfully. Please sign in to continue.'
50 | send_paranoid_instructions: 'If your account exists, you will receive an email with instructions about how to unlock it in a few minutes.'
51 | omniauth_callbacks:
52 | success: 'Successfully authenticated from %{kind} account.'
53 | failure: 'Could not authenticate you from %{kind} because "%{reason}".'
54 | mailer:
55 | confirmation_instructions:
56 | subject: 'Confirmation instructions'
57 | reset_password_instructions:
58 | subject: 'Reset password instructions'
59 | unlock_instructions:
60 | subject: 'Unlock Instructions'
61 |
--------------------------------------------------------------------------------
/test/dummy/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Sample localization file for English. Add more files in this directory for other locales.
2 | # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3 |
4 | en:
5 | hello: "Hello world"
6 |
--------------------------------------------------------------------------------
/test/dummy/config/routes.rb:
--------------------------------------------------------------------------------
1 | Rails.application.routes.draw do
2 |
3 | root :to => 'qwester/questionnaires#index'
4 |
5 | require 'inherited_resources'
6 | if defined?(ActiveAdmin)
7 | ActiveAdmin.routes(self)
8 | devise_for :admin_users, ActiveAdmin::Devise.config
9 | end
10 |
11 | mount Qwester::Engine => "/questionnaires"
12 |
13 |
14 | end
15 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130110115938_devise_create_admin_users.rb:
--------------------------------------------------------------------------------
1 | class DeviseCreateAdminUsers < ActiveRecord::Migration
2 |
3 | def change
4 | create_table(:admin_users) do |t|
5 | ## Database authenticatable
6 | t.string :email, :null => false, :default => ""
7 | t.string :encrypted_password, :null => false, :default => ""
8 |
9 | ## Recoverable
10 | t.string :reset_password_token
11 | t.datetime :reset_password_sent_at
12 |
13 | ## Rememberable
14 | t.datetime :remember_created_at
15 |
16 | ## Trackable
17 | t.integer :sign_in_count, :default => 0
18 | t.datetime :current_sign_in_at
19 | t.datetime :last_sign_in_at
20 | t.string :current_sign_in_ip
21 | t.string :last_sign_in_ip
22 |
23 | ## Confirmable
24 | # t.string :confirmation_token
25 | # t.datetime :confirmed_at
26 | # t.datetime :confirmation_sent_at
27 | # t.string :unconfirmed_email # Only if using reconfirmable
28 |
29 | ## Lockable
30 | # t.integer :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
31 | # t.string :unlock_token # Only if unlock strategy is :email or :both
32 | # t.datetime :locked_at
33 |
34 | ## Token authenticatable
35 | # t.string :authentication_token
36 |
37 |
38 | t.timestamps
39 | end
40 |
41 | add_index :admin_users, :email, :unique => true
42 | add_index :admin_users, :reset_password_token, :unique => true
43 | # add_index :admin_users, :confirmation_token, :unique => true
44 | # add_index :admin_users, :unlock_token, :unique => true
45 | # add_index :admin_users, :authentication_token, :unique => true
46 | end
47 | end
48 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130110115940_create_admin_comments.rb:
--------------------------------------------------------------------------------
1 | class CreateAdminComments < ActiveRecord::Migration
2 | def change
3 | create_table :active_admin_comments do |t|
4 | t.string :resource_id, :null => false
5 | t.string :resource_type, :null => false
6 | t.references :author, :polymorphic => true
7 | t.string :namespace
8 |
9 | t.text :body
10 | t.timestamps
11 | end
12 | add_index :active_admin_comments, [:namespace]
13 | add_index :active_admin_comments, [:author_type, :author_id]
14 | end
15 |
16 |
17 | end
18 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103645_create_questions.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20121008151526)
2 | class CreateQuestions < ActiveRecord::Migration
3 | def change
4 | create_table :qwester_questions do |t|
5 | t.string :title
6 | t.text :description
7 | t.integer :parent_id
8 | t.integer :lft
9 | t.integer :rgt
10 | t.integer :depth
11 | t.timestamps
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103646_create_answers.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20121008152106)
2 | class CreateAnswers < ActiveRecord::Migration
3 | def change
4 | create_table :qwester_answers do |t|
5 | t.integer :question_id
6 | t.boolean :value
7 | t.timestamps
8 | end
9 | end
10 | end
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103647_create_rule_sets.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20121008153758)
2 | class CreateRuleSets < ActiveRecord::Migration
3 | def change
4 | create_table :qwester_rule_sets do |t|
5 | t.string :title
6 | t.text :description
7 | t.string :url
8 | t.timestamps
9 | end
10 |
11 | create_table :qwester_answers_rule_sets, :id => false do |t|
12 | t.integer :answer_id
13 | t.integer :rule_set_id
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103648_create_questionnaires.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20121009080219)
2 | class CreateQuestionnaires < ActiveRecord::Migration
3 | def change
4 | create_table :qwester_questionnaires do |t|
5 | t.string :title
6 | t.text :description
7 | t.timestamps
8 | end
9 |
10 | create_table :qwester_questionnaires_questions, :id => false do |t|
11 | t.integer :questionnaire_id
12 | t.integer :question_id
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103649_create_answer_stores.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20121009095600)
2 | class CreateAnswerStores < ActiveRecord::Migration
3 | def change
4 | create_table :qwester_answer_stores do |t|
5 | t.string :session_id
6 | t.timestamps
7 | end
8 |
9 | create_table :qwester_answer_stores_answers, :id => false do |t|
10 | t.integer :answer_id
11 | t.integer :answer_store_id
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103650_add_questionnaire_id_to_answers.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20121009160807)
2 | class AddQuestionnaireIdToAnswers < ActiveRecord::Migration
3 | def change
4 | add_column :qwester_answers, :questionnaire_id, :integer
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103651_change_answers_value_to_string.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20121009161206)
2 | class ChangeAnswersValueToString < ActiveRecord::Migration
3 | def up
4 | change_column(:qwester_answers, :value, :string)
5 | end
6 |
7 | def down
8 | change_column(:qwester_answers, :value, :boolean)
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103652_add_button_image_to_questionnaires.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20121019111051)
2 | require 'paperclip'
3 | ActiveRecord::ConnectionAdapters::AbstractAdapter.send :include, Paperclip::Schema::Statements
4 | class AddButtonImageToQuestionnaires < ActiveRecord::Migration
5 | def change
6 | add_attachment :qwester_questionnaires, :button_image
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103653_create_ckeditor_assets.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20121114084347)
2 | class CreateCkeditorAssets < ActiveRecord::Migration
3 | def self.up
4 | create_table :qwester_ckeditor_assets do |t|
5 | t.string :data_file_name, :null => false
6 | t.string :data_content_type
7 | t.integer :data_file_size
8 |
9 | t.integer :assetable_id
10 | t.string :assetable_type, :limit => 30
11 | t.string :type, :limit => 30
12 |
13 | # Uncomment it to save images dimensions, if your need it
14 | t.integer :width
15 | t.integer :height
16 |
17 | t.timestamps
18 | end
19 |
20 | add_index "qwester_ckeditor_assets", ["assetable_type", "type", "assetable_id"], :name => "qwester_idx_ckeditor_assetable_type"
21 | add_index "qwester_ckeditor_assets", ["assetable_type", "assetable_id"], :name => "qwester_idx_ckeditor_assetable"
22 | end
23 |
24 | def self.down
25 | drop_table :qwester_ckeditor_assets
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103654_add_ref_to_questions.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20121115114408)
2 | class AddRefToQuestions < ActiveRecord::Migration
3 | def change
4 | add_column :qwester_questions, :ref, :string
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103655_add_ids_to_questionnaires_questions.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20121120092108)
2 | class AddIdsToQuestionnairesQuestions < ActiveRecord::Migration
3 | def up
4 | add_column qq_table, :id, :primary_key
5 | add_column qq_table, :position, :integer
6 | add_column qq_table, :created_at, :datetime
7 | add_column qq_table, :updated_at, :datetime
8 |
9 | execute "UPDATE #{qq_table} SET created_at = '#{Time.now.to_s(:db)}', updated_at = '#{Time.now.to_s(:db)}';"
10 |
11 | puts "=============================================="
12 | puts "Now run 'rake qwester:reset_positions RAILS_ENV=#{Rails.env}' to set the positions"
13 | puts "=============================================="
14 | end
15 |
16 | def down
17 | remove_column qq_table, :id
18 | remove_column qq_table, :position
19 | remove_column qq_table, :created_at
20 | remove_column qq_table, :updated_at
21 | end
22 |
23 | def qq_table
24 | :qwester_questionnaires_questions
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103656_add_position_to_answers.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20121122130930)
2 | class AddPositionToAnswers < ActiveRecord::Migration
3 | def change
4 | # Adds unless clause, because original version of migration added another field
5 | # and file name was changed when this field was removed. This can cause this
6 | # migration to appear a second time if rake qwester:install:migrations is
7 | # run again in an app created before the change was made.
8 | unless column_exists?(:qwester_answers, :position)
9 | add_column :qwester_answers, :position, :integer
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103657_remove_questionnaire_from_answer.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20121122141628)
2 | class RemoveQuestionnaireFromAnswer < ActiveRecord::Migration
3 | def up
4 | remove_column :qwester_answers, :questionnaire_id
5 | end
6 |
7 | def down
8 | add_column :qwester_answers, :questionnaire_id, :integer
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103658_add_rule_to_rule_sets.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20121126152146)
2 | class AddRuleToRuleSets < ActiveRecord::Migration
3 | def change
4 | add_column :qwester_rule_sets, :rule, :text
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103659_add_multi_answer_to_questions.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20121203150555)
2 | class AddMultiAnswerToQuestions < ActiveRecord::Migration
3 | def change
4 | add_column :qwester_questions, :multi_answer, :boolean
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103660_create_answer_stores_questionnaires.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20121204082213)
2 | class CreateAnswerStoresQuestionnaires < ActiveRecord::Migration
3 | def change
4 |
5 | create_table :qwester_answer_stores_questionnaires, :id => false do |t|
6 | t.integer :questionnaire_id
7 | t.integer :answer_store_id
8 | end
9 |
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103661_add_link_text_to_rule_sets.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20121204100803)
2 | class AddLinkTextToRuleSets < ActiveRecord::Migration
3 | def change
4 | add_column :qwester_rule_sets, :link_text, :string
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130314103662_add_preserved_to_answer_stores.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20130306114331)
2 | class AddPreservedToAnswerStores < ActiveRecord::Migration
3 | def change
4 | add_column :qwester_answer_stores, :preserved, :datetime
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130315113346_create_qwester_presentations.qwester.rb:
--------------------------------------------------------------------------------
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
13 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130315113347_create_qwester_presentation_questionnaires.qwester.rb:
--------------------------------------------------------------------------------
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
12 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130402085423_add_presentation_to_rule_sets.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20130318102537)
2 | class AddPresentationToRuleSets < ActiveRecord::Migration
3 | def change
4 | add_column :qwester_rule_sets, :presentation, :string
5 | add_column :qwester_presentations, :default, :boolean
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130402085424_add_weighting_to_qwester_answers.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20130402074240)
2 | class AddWeightingToQwesterAnswers < ActiveRecord::Migration
3 | def change
4 | add_column :qwester_answers, :weighting, :float, :default => 0
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20130502082731_add_position_to_qwester_presentation_questionnaires.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20130502082540)
2 | class AddPositionToQwesterPresentationQuestionnaires < ActiveRecord::Migration
3 | def change
4 | add_column :qwester_presentation_questionnaires, :position, :integer
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20131119142050_add_must_complete_to_qwester_questionnaires.qwester.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from qwester (originally 20131119142009)
2 | class AddMustCompleteToQwesterQuestionnaires < ActiveRecord::Migration
3 | def change
4 | add_column :qwester_questionnaires, :must_complete, :boolean
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/test/dummy/db/schema.rb:
--------------------------------------------------------------------------------
1 | # encoding: UTF-8
2 | # This file is auto-generated from the current state of the database. Instead
3 | # of editing this file, please use the migrations feature of Active Record to
4 | # incrementally modify your database, and then regenerate this schema definition.
5 | #
6 | # Note that this schema.rb definition is the authoritative source for your
7 | # database schema. If you need to create the application database on another
8 | # system, you should be using db:schema:load, not running all the migrations
9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10 | # you'll amass, the slower it'll run and the greater likelihood for issues).
11 | #
12 | # It's strongly recommended to check this file into your version control system.
13 |
14 | ActiveRecord::Schema.define(:version => 20131119142050) do
15 |
16 | create_table "active_admin_comments", :force => true do |t|
17 | t.string "resource_id", :null => false
18 | t.string "resource_type", :null => false
19 | t.integer "author_id"
20 | t.string "author_type"
21 | t.string "namespace"
22 | t.text "body"
23 | t.datetime "created_at", :null => false
24 | t.datetime "updated_at", :null => false
25 | end
26 |
27 | add_index "active_admin_comments", ["author_type", "author_id"], :name => "index_active_admin_comments_on_author_type_and_author_id"
28 | add_index "active_admin_comments", ["namespace"], :name => "index_active_admin_comments_on_namespace"
29 |
30 | create_table "admin_users", :force => true do |t|
31 | t.string "email", :default => "", :null => false
32 | t.string "encrypted_password", :default => "", :null => false
33 | t.string "reset_password_token"
34 | t.datetime "reset_password_sent_at"
35 | t.datetime "remember_created_at"
36 | t.integer "sign_in_count", :default => 0
37 | t.datetime "current_sign_in_at"
38 | t.datetime "last_sign_in_at"
39 | t.string "current_sign_in_ip"
40 | t.string "last_sign_in_ip"
41 | t.datetime "created_at", :null => false
42 | t.datetime "updated_at", :null => false
43 | end
44 |
45 | add_index "admin_users", ["email"], :name => "index_admin_users_on_email", :unique => true
46 | add_index "admin_users", ["reset_password_token"], :name => "index_admin_users_on_reset_password_token", :unique => true
47 |
48 | create_table "qwester_answer_stores", :force => true do |t|
49 | t.string "session_id"
50 | t.datetime "created_at", :null => false
51 | t.datetime "updated_at", :null => false
52 | t.datetime "preserved"
53 | end
54 |
55 | create_table "qwester_answer_stores_answers", :id => false, :force => true do |t|
56 | t.integer "answer_id"
57 | t.integer "answer_store_id"
58 | end
59 |
60 | create_table "qwester_answer_stores_questionnaires", :id => false, :force => true do |t|
61 | t.integer "questionnaire_id"
62 | t.integer "answer_store_id"
63 | end
64 |
65 | create_table "qwester_answers", :force => true do |t|
66 | t.integer "question_id"
67 | t.string "value"
68 | t.datetime "created_at", :null => false
69 | t.datetime "updated_at", :null => false
70 | t.integer "position"
71 | t.float "weighting", :default => 0.0
72 | end
73 |
74 | create_table "qwester_answers_rule_sets", :id => false, :force => true do |t|
75 | t.integer "answer_id"
76 | t.integer "rule_set_id"
77 | end
78 |
79 | create_table "qwester_ckeditor_assets", :force => true do |t|
80 | t.string "data_file_name", :null => false
81 | t.string "data_content_type"
82 | t.integer "data_file_size"
83 | t.integer "assetable_id"
84 | t.string "assetable_type", :limit => 30
85 | t.string "type", :limit => 30
86 | t.integer "width"
87 | t.integer "height"
88 | t.datetime "created_at", :null => false
89 | t.datetime "updated_at", :null => false
90 | end
91 |
92 | add_index "qwester_ckeditor_assets", ["assetable_type", "assetable_id"], :name => "qwester_idx_ckeditor_assetable"
93 | add_index "qwester_ckeditor_assets", ["assetable_type", "type", "assetable_id"], :name => "qwester_idx_ckeditor_assetable_type"
94 |
95 | create_table "qwester_presentation_questionnaires", :force => true do |t|
96 | t.integer "questionnaire_id"
97 | t.integer "presentation_id"
98 | t.datetime "created_at", :null => false
99 | t.datetime "updated_at", :null => false
100 | t.integer "position"
101 | end
102 |
103 | create_table "qwester_presentations", :force => true do |t|
104 | t.string "name"
105 | t.string "title"
106 | t.text "description"
107 | t.datetime "created_at", :null => false
108 | t.datetime "updated_at", :null => false
109 | t.boolean "default"
110 | end
111 |
112 | create_table "qwester_questionnaires", :force => true do |t|
113 | t.string "title"
114 | t.text "description"
115 | t.datetime "created_at", :null => false
116 | t.datetime "updated_at", :null => false
117 | t.string "button_image_file_name"
118 | t.string "button_image_content_type"
119 | t.integer "button_image_file_size"
120 | t.datetime "button_image_updated_at"
121 | t.boolean "must_complete"
122 | end
123 |
124 | create_table "qwester_questionnaires_questions", :force => true do |t|
125 | t.integer "questionnaire_id"
126 | t.integer "question_id"
127 | t.integer "position"
128 | t.datetime "created_at"
129 | t.datetime "updated_at"
130 | end
131 |
132 | create_table "qwester_questions", :force => true do |t|
133 | t.string "title"
134 | t.text "description"
135 | t.integer "parent_id"
136 | t.integer "lft"
137 | t.integer "rgt"
138 | t.integer "depth"
139 | t.datetime "created_at", :null => false
140 | t.datetime "updated_at", :null => false
141 | t.string "ref"
142 | t.boolean "multi_answer"
143 | end
144 |
145 | create_table "qwester_rule_sets", :force => true do |t|
146 | t.string "title"
147 | t.text "description"
148 | t.string "url"
149 | t.datetime "created_at", :null => false
150 | t.datetime "updated_at", :null => false
151 | t.text "rule"
152 | t.string "link_text"
153 | t.string "presentation"
154 | end
155 |
156 | end
157 |
--------------------------------------------------------------------------------
/test/dummy/db/seeds.rb:
--------------------------------------------------------------------------------
1 | require 'dibber'
2 | Seeder = Dibber::Seeder
3 |
4 | Seeder.seeds_path = "#{Rails.root}/db/seeds"
5 |
6 | ##############################
7 | Seeder.monitor AdminUser
8 | admin_email = 'admin@warwickshire.gov.uk'
9 | password = 'changeme'
10 | AdminUser.create!(
11 | :email => admin_email,
12 | :password => password,
13 | :password_confirmation => password
14 | ) unless AdminUser.exists?(:email => admin_email)
15 |
16 | ##############################
17 | Seeder.monitor Qwester::Questionnaire
18 | Seeder.monitor Qwester::Question
19 | Seeder.monitor Qwester::Answer
20 | Seeder.monitor Qwester::RuleSet
21 | Seeder.process_log.start('first questionnaire questions', 'Qwester::Questionnaire.count > 0 ? Qwester::Questionnaire.first.questions.length : 0')
22 |
23 | if Qwester::Questionnaire.count > 1
24 | puts "**** Bypassing questionnaire, question, answer and rule set population"
25 | puts "**** as there are already #{Qwester::Questionnaire.count} questionnaires in the system"
26 | else
27 | Seeder.objects_from('questions.yml').each do |holder, data|
28 | questionnaire = Qwester::Questionnaire.find_or_create_by_title(data['title'])
29 |
30 | if data['questions']
31 | data['questions'].values.each do |question_data|
32 | question = Qwester::Question.find_or_create_by_title(question_data['question'])
33 | question.create_standard_answers
34 | answer = question.answers.find_or_create_by_value('Yes')
35 | rule_set = Qwester::RuleSet.find_or_initialize_by_title(question_data['title'])
36 | rule_set.url = question_data['url']
37 | rule_set.answers = [answer]
38 | rule_set.save
39 | questionnaire.questions << question
40 | end
41 | end
42 | end
43 | end
44 |
45 |
46 | ##############################
47 | puts Seeder.report
--------------------------------------------------------------------------------
/test/dummy/db/seeds/questions.yml:
--------------------------------------------------------------------------------
1 | Q1:
2 | title: Blue
3 | questions:
4 | a:
5 | title: Other blue favourites
6 | question: Is blue your favourite colour?
7 | url: https://www.google.co.uk/search?q=favourite+blue
8 |
9 | b:
10 | title:
11 | question: Is the sky blue?
12 | url: https://www.google.co.uk/search?q=sky+blue
13 |
14 |
15 | Q2:
16 | title: Qwester
17 | questions:
18 | a:
19 | title: As you like qwester
20 | question: Do you like qwester?
21 | url: https://github.com/reggieb/qwester
22 |
--------------------------------------------------------------------------------
/test/dummy/lib/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reggieb/qwester/458690e814c83405edb32404eb45b06dc5fc8f59/test/dummy/lib/assets/.gitkeep
--------------------------------------------------------------------------------
/test/dummy/log/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reggieb/qwester/458690e814c83405edb32404eb45b06dc5fc8f59/test/dummy/log/.gitkeep
--------------------------------------------------------------------------------
/test/dummy/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
The page you were looking for doesn't exist.
23 |
You may have mistyped the address or the page may have moved.
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/test/dummy/public/422.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The change you wanted was rejected (422)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
The change you wanted was rejected.
23 |
Maybe you tried to change something you didn't have access to.
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/test/dummy/public/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | We're sorry, but something went wrong (500)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
We're sorry, but something went wrong.
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/test/dummy/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reggieb/qwester/458690e814c83405edb32404eb45b06dc5fc8f59/test/dummy/public/favicon.ico
--------------------------------------------------------------------------------
/test/dummy/script/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3 |
4 | APP_PATH = File.expand_path('../../config/application', __FILE__)
5 | require File.expand_path('../../config/boot', __FILE__)
6 | require 'rails/commands'
7 |
--------------------------------------------------------------------------------
/test/dummy/test/fixtures/admin_users.yml:
--------------------------------------------------------------------------------
1 | one:
2 | id: 1
3 | email: 'admin@user.com'
4 | encrypted_password: <%= AdminUser.new.send(:password_digest, 'password') %>
5 |
6 |
--------------------------------------------------------------------------------
/test/dummy/test/fixtures/qwester/answer_stores.yml:
--------------------------------------------------------------------------------
1 | one:
2 | id: 1
3 | session_id: <%= RandomString.new(15) %>
4 |
5 |
--------------------------------------------------------------------------------
/test/dummy/test/fixtures/qwester/answers.yml:
--------------------------------------------------------------------------------
1 |
2 | one:
3 | id: 1
4 | value: <%= Qwester::Answer.standard_values[0] %>
5 | question_id: 1
6 |
7 | two:
8 | id: 2
9 | value: <%= Qwester::Answer.standard_values[1] %>
10 | question_id: 1
11 |
12 |
--------------------------------------------------------------------------------
/test/dummy/test/fixtures/qwester/presentation_questionnaires.yml:
--------------------------------------------------------------------------------
1 | one:
2 | id: 1
3 | questionnaire_id: 1
4 | presentation_id: 1
5 | position: 1
6 |
--------------------------------------------------------------------------------
/test/dummy/test/fixtures/qwester/presentations.yml:
--------------------------------------------------------------------------------
1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html
2 |
3 | one:
4 | id: 1
5 | name: Start
6 | title: The starting point
7 | description: This is the first set of questionnaires
8 |
9 | two:
10 | id: 2
11 | name: Main
12 | title: Main set of questionnaires
13 | description: This is another set of questionnaires
14 |
--------------------------------------------------------------------------------
/test/dummy/test/fixtures/qwester/questionnaires.yml:
--------------------------------------------------------------------------------
1 | one:
2 | id: 1
3 | title: Questions about stuff
4 |
5 | two:
6 | id: 2
7 | title: More questions
8 |
--------------------------------------------------------------------------------
/test/dummy/test/fixtures/qwester/questionnaires_questions.yml:
--------------------------------------------------------------------------------
1 | one:
2 | id: 1
3 | question_id: 1
4 | questionnaire_id: 1
5 | position: 1
6 |
--------------------------------------------------------------------------------
/test/dummy/test/fixtures/qwester/questions.yml:
--------------------------------------------------------------------------------
1 | one:
2 | id: 1
3 | title: Is this true?
4 |
5 | two:
6 | id: 2
7 | title: Is this a question?
8 |
9 |
--------------------------------------------------------------------------------
/test/dummy/test/fixtures/qwester/rule_sets.yml:
--------------------------------------------------------------------------------
1 |
2 | one:
3 | id: 1
4 | url: http://undervale.co.uk
5 | title: Test Rule Set
6 |
--------------------------------------------------------------------------------
/test/dummy/test/functional/qwester/questionnaires_controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | module Qwester
4 | class QuestionnairesControllerTest < ActionController::TestCase
5 | def setup
6 | @questionnaire = Questionnaire.find(1)
7 | @question = Question.find(1)
8 | @answer = @question.answers.find(1)
9 | @presentation = Presentation.find(1)
10 | end
11 |
12 | def test_setup
13 | assert_equal(2, @question.answers.count)
14 | assert_not_equal(@presentation.questionnaires, Questionnaire.all)
15 | end
16 |
17 | def test_index
18 | get :index, :use_route => :qwester
19 | assert_response :success
20 | assert_equal(Questionnaire.all, assigns('questionnaires'))
21 | end
22 |
23 | def test_presentation_not_assigned_when_not_used
24 | test_index
25 | assert_nil(assigns('presentation'))
26 | end
27 |
28 | def test_index_with_presentation
29 | get :index, {:use_route => :qwester}, :presentations => [@presentation.name]
30 | assert_response :success
31 | assert_equal([@presentation.name], session[:presentations])
32 | assert_equal(@presentation.questionnaires, assigns('questionnaires'))
33 | assert_equal(@presentation, assigns('presentation'))
34 | end
35 |
36 | def test_index_with_presentation_and_history_of_other_presentation
37 | names = [other_presentation.name, @presentation.name]
38 | get :index, {:use_route => :qwester}, :presentations => names
39 | assert_response :success
40 | assert_equal(names, session[:presentations])
41 | assert_equal(@presentation.questionnaires, assigns('questionnaires'))
42 | end
43 |
44 | def test_index_with_other_presentation_and_history_of_presentation
45 | other = other_presentation
46 | names = [@presentation.name, other.name]
47 | get :index, {:use_route => :qwester}, :presentations => names
48 | assert_response :success
49 | assert_equal(names, session[:presentations])
50 | assert_equal(other.questionnaires, assigns('questionnaires'))
51 | end
52 |
53 | def test_index_with_default_presentation
54 | @presentation.update_attribute :default, true
55 | get :index, {:use_route => :qwester}
56 | assert_response :success
57 | assert_equal(@presentation.questionnaires, assigns('questionnaires'))
58 | assert_equal(nil, session[:presentations])
59 | assert_equal(@presentation, assigns('presentation'))
60 | end
61 |
62 | def test_show
63 | get :show, :id => @questionnaire.id, :use_route => :qwester
64 | assert_response :success
65 | assert_equal(@questionnaire, assigns('questionnaire'))
66 | end
67 |
68 |
69 | def test_update
70 | put(
71 | :update,
72 | :id => @questionnaire.id,
73 | :question_id => {
74 | @question.id.to_s => {
75 | :answer_ids => [@answer.id.to_s]
76 | }
77 | },
78 | :use_route => :qwester
79 | )
80 | answer_store = AnswerStore.last
81 | assert_equal(@question, @answer.question)
82 | assert_equal(answer_store.session_id, session[Qwester.session_key])
83 | assert_response :redirect
84 | end
85 |
86 | def test_update_with_no_answers
87 | put(
88 | :update,
89 | :id => @questionnaire.id,
90 | :use_route => :qwester
91 | )
92 | assert_equal(nil, session[Qwester.session_key])
93 | assert_response :redirect
94 | end
95 |
96 | def test_update_with_must_complete_and_all_questions_answered
97 | @questionnaire.update_attribute :must_complete, true
98 | test_update
99 | end
100 |
101 | def test_update_with_must_complete_and_no_questions_answered
102 | @questionnaire.update_attribute :must_complete, true
103 | test_update_with_no_answers
104 | end
105 |
106 | def test_update_with_must_complete_and_some_answers_completed
107 | @questionnaire.update_attribute :must_complete, true
108 | @questionnaire.questions << Question.find(2)
109 | put(
110 | :update,
111 | :id => @questionnaire.id,
112 | :question_id => {
113 | @question.id.to_s => {
114 | :answer_ids => [@answer.id.to_s]
115 | }
116 | },
117 | :use_route => :qwester
118 | )
119 | assert_response :success
120 | assert assigns('questionnaire').errors.present?, "@questionnaire should include errors"
121 | assert !assigns('qwester_answer_store').questionnaires.include?(@questionnaire), "@questionnaire should not be stored"
122 | end
123 |
124 | def test_answer_store_created_when_questionnaire_first_submitted
125 | assert_difference 'AnswerStore.count' do
126 | test_update
127 | end
128 | end
129 |
130 | def test_update_add_multiple_answers
131 | other_question = Question.find(2)
132 | other_question.create_standard_answers
133 | other_answer = other_question.answers.last
134 | assert_difference 'AnswerStore.count' do
135 | put(
136 | :update,
137 | :id => @questionnaire.id,
138 | :question_id => {
139 | @question.id.to_s => {
140 | :answer_ids => [@answer.id.to_s]
141 | },
142 | other_question.id.to_s => {
143 | :answer_ids => [other_answer.id.to_s]
144 | }
145 | },
146 | :use_route => :qwester
147 | )
148 | end
149 | answer_store = AnswerStore.last
150 |
151 | assert_equal([@answer, other_answer], answer_store.answers)
152 | end
153 |
154 | def test_update_add_multiple_answers_for_same_question
155 | answer, other_answer = @question.answers[0..1]
156 | assert_not_equal(answer, other_answer)
157 | assert_difference 'AnswerStore.count', 1 do
158 | put(
159 | :update,
160 | :id => @questionnaire.id,
161 | :question_id => {
162 | @question.id.to_s => {
163 | :answer_ids => [answer.id.to_s, other_answer.id.to_s]
164 | }
165 | },
166 | :use_route => :qwester
167 | )
168 | end
169 | answer_store = AnswerStore.last
170 |
171 | assert_equal([answer, other_answer], answer_store.answers)
172 | end
173 |
174 | def test_rule_set_match_after_update
175 | test_update
176 | rule_set = RuleSet.first
177 | rule_set.answers << AnswerStore.last.answers.first
178 | rule_set.save
179 | get :index, :use_route => :qwester
180 | assert_equal([rule_set], assigns['qwester_rule_sets'])
181 | end
182 |
183 | def test_reset
184 | test_update
185 | assert_no_difference 'Answer.count' do
186 | get :reset, :use_route => :qwester
187 | assert_response :redirect
188 | assert_equal([], AnswerStore.last.answers)
189 | assert_equal([], AnswerStore.last.questionnaires)
190 | end
191 | end
192 |
193 | def test_update_adds_questionnaire_to_answer_store
194 | test_update
195 | assert_equal([@questionnaire], AnswerStore.last.questionnaires)
196 | end
197 |
198 | def test_previous_answers_to_question_removed_on_update
199 | assert_difference 'AnswerStore.count', 1 do
200 | test_update
201 | end
202 | @answer = @question.answers.find(2)
203 | assert_no_difference 'AnswerStore.count' do
204 | test_update
205 | end
206 | end
207 |
208 | def test_transition_from_default_to_final_via_submission_of_questionnaire
209 | @target_presentation = Presentation.find(2)
210 | @target_presentation.questionnaires = [Questionnaire.find(2)]
211 | @target_presentation.save
212 | @rule_set = RuleSet.find(1)
213 | @rule_set.answers = [@answer]
214 | @rule_set.presentation = @target_presentation.name
215 | @rule_set.save
216 | @presentation.update_attribute :default, true
217 | get :index, :use_route => :qwester
218 | assert_equal(@presentation.questionnaires, assigns[:questionnaires])
219 | put(
220 | :update,
221 | :id => @questionnaire.id,
222 | :question_id => {
223 | @question.id.to_s => {
224 | :answer_ids => [@answer.id.to_s]
225 | }
226 | },
227 | :use_route => :qwester
228 | )
229 | assert_response :redirect
230 | get :index, :use_route => :qwester
231 | assert_equal(@target_presentation.questionnaires, assigns[:questionnaires])
232 | end
233 |
234 | private
235 | def other_presentation
236 | presentation = Presentation.find(2)
237 | presentation.questionnaires << Questionnaire.find(2)
238 | return presentation
239 | end
240 | end
241 |
242 | end
243 |
--------------------------------------------------------------------------------
/test/dummy/test/test_helper.rb:
--------------------------------------------------------------------------------
1 | require_relative '../../test_helper'
2 |
3 | puts "!!!! Running tests from /test/dummy only runs the tests in /test/dummy/test, and ignores tests in /test/unit !!!!"
4 | puts "run 'rake test' at the project root to run all tests."
--------------------------------------------------------------------------------
/test/dummy/test/unit/admin_user_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class AdminUserTest < ActiveSupport::TestCase
4 |
5 | def setup
6 | @admin_user = AdminUser.find(1)
7 | end
8 |
9 | end
10 |
--------------------------------------------------------------------------------
/test/dummy/test/unit/helpers/questionnaires_helper_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class QuestionnairesHelperTest < ActionView::TestCase
4 | end
5 |
--------------------------------------------------------------------------------
/test/integration/navigation_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class NavigationTest < ActionDispatch::IntegrationTest
4 | fixtures :all
5 |
6 | # test "the truth" do
7 | # assert true
8 | # end
9 | end
10 |
11 |
--------------------------------------------------------------------------------
/test/test_helper.rb:
--------------------------------------------------------------------------------
1 | # Configure Rails Environment
2 | ENV["RAILS_ENV"] = "test"
3 |
4 | require File.expand_path("../dummy/config/environment.rb", __FILE__)
5 | require "rails/test_help"
6 |
7 | Rails.backtrace_cleaner.remove_silencers!
8 |
9 | puts "fixture path = " + ActiveSupport::TestCase.fixture_path
10 |
11 | class ActiveSupport::TestCase
12 | fixtures :all
13 | end
14 |
--------------------------------------------------------------------------------
/test/unit/qwester/answer_store_test.rb:
--------------------------------------------------------------------------------
1 | require_relative '../../test_helper'
2 | module Qwester
3 |
4 | class AnswerStoreTest < ActiveSupport::TestCase
5 |
6 | def setup
7 | @answer_store = AnswerStore.find(1)
8 | @answer_store.update_attribute(:updated_at, 2.days.ago)
9 | @answer = Answer.find(1)
10 | @other_answer = Answer.find(2)
11 | @questionnaire = Questionnaire.find(1)
12 | end
13 |
14 | def test_answers_empty
15 | assert_equal([], @answer_store.answers)
16 | end
17 |
18 | def test_answer_store_accepts_objects
19 | @answer_store.answers << @answer
20 | @answer_store.questionnaires << @questionnaire
21 | assert_equal([@questionnaire], @answer_store.questionnaires)
22 | assert_equal([@answer], @answer_store.answers)
23 | end
24 |
25 | def test_reset
26 | test_answer_store_accepts_objects
27 | @answer_store.reset
28 | assert_equal([], @answer_store.questionnaires)
29 | assert_equal([], @answer_store.answers)
30 | end
31 |
32 | def test_session_id_generated_on_creation
33 | answer_store = AnswerStore.create
34 | assert_match /^\w*$/, answer_store.session_id
35 | assert_equal 15, answer_store.session_id.length
36 | end
37 |
38 | def test_preserve
39 | assert_difference 'AnswerStore.count', 1 do
40 | @preserved = @answer_store.preserve
41 | end
42 | assert(@preserved.preserved?)
43 | assert(!@answer_store.preserved?)
44 | end
45 |
46 | def test_preserved_is_last_created
47 | test_preserve
48 | assert_equal(AnswerStore.last, @preserved)
49 | end
50 |
51 | def test_preserved_answer_store_has_new_session_id
52 | test_preserve
53 | assert_not_equal(@answer_store.session_id, @preserved.session_id)
54 | end
55 |
56 | def test_preserved_has_same_objects_as_original
57 | test_answer_store_accepts_objects
58 | test_preserve
59 | assert_equal(@answer_store.answers, @preserved.answers)
60 | assert_equal(@answer_store.questionnaires, @preserved.questionnaires)
61 | end
62 |
63 | def test_changes_to_original_do_not_affect_preserved
64 | test_preserve
65 | assert_equal([], @preserved.answers)
66 | assert_equal([], @preserved.questionnaires)
67 | test_answer_store_accepts_objects
68 | @preserved.reload
69 | assert_equal([], @preserved.answers)
70 | assert_equal([], @preserved.questionnaires)
71 | end
72 |
73 | def test_destroy_unpreserved
74 | assert_not_equal(0, AnswerStore.count)
75 | AnswerStore.destroy_unpreserved
76 | assert_equal(0, AnswerStore.count)
77 | end
78 |
79 | def test_destroy_unpreserved_does_not_remove_preserved
80 | count = AnswerStore.count
81 | test_preserve
82 | assert_difference 'AnswerStore.count', - count do
83 | AnswerStore.destroy_unpreserved
84 | end
85 | assert_equal(@preserved, AnswerStore.first)
86 | end
87 |
88 | def test_destroy_unpreserved_does_not_destroy_answers
89 | test_answer_store_accepts_objects
90 | assert_no_difference 'Answer.count' do
91 | AnswerStore.destroy_unpreserved
92 | end
93 | end
94 |
95 | def test_destroy_unpreserved_does_not_destroy_questionnaires
96 | test_answer_store_accepts_objects
97 | assert_no_difference 'Questionnaire.count' do
98 | AnswerStore.destroy_unpreserved
99 | end
100 | end
101 |
102 | def test_destroy_unpreserved_removes_entries_from_answers_join_table
103 | test_answer_store_accepts_objects
104 | assert_on_destroy_unpreserved_join_entries_removed_for 'answers'
105 | end
106 |
107 | def test_destroy_unpreserved_removes_entries_from_questionnaires_join_table
108 | test_answer_store_accepts_objects
109 | assert_on_destroy_unpreserved_join_entries_removed_for 'questionnaires'
110 | end
111 |
112 | def test_destroy_unpreserved_does_not_remove_recent_answer_stores
113 | answer_store = AnswerStore.create
114 | AnswerStore.destroy_unpreserved
115 | assert_equal([answer_store], AnswerStore.all)
116 | end
117 |
118 | def test_restore_preserved
119 | test_preserve
120 | assert_difference 'AnswerStore.count' do
121 | @restored = @preserved.restore
122 | end
123 | assert_equal(false, @restored.preserved?)
124 | assert_not_equal(@preserved.session_id, @restored.session_id)
125 | assert_equal(@preserved.answers, @restored.answers)
126 | assert_equal(@preserved.questionnaires, @restored.questionnaires)
127 | end
128 |
129 | def test_get_session_ids
130 | test_preserve # to populate database with extra answer_stores
131 | assert_equal(AnswerStore.all.collect(&:session_id).sort, @answer_store.send(:get_session_ids).sort)
132 | end
133 |
134 | def test_completed_questionnaires
135 | assert_equal [], @answer_store.completed_questionnaires
136 | @answer_store.answers << @questionnaire.questions.first.answers.first
137 | @answer_store.questionnaires << @questionnaire
138 | assert_equal [@questionnaire], @answer_store.completed_questionnaires
139 | end
140 |
141 | def test_completed_questionnaires_with_second_question
142 | first_question = @questionnaire.questions.first
143 | second_question = Question.find(2)
144 | second_question.build_standard_answers
145 | second_question.save
146 | @questionnaire.questions = [first_question, second_question]
147 | @answer_store.answers << first_question.answers.first
148 | @answer_store.questionnaires << @questionnaire
149 | assert_equal [], @answer_store.completed_questionnaires
150 | @answer_store.answers << second_question.answers.first
151 | assert_equal [@questionnaire], @answer_store.completed_questionnaires
152 | end
153 |
154 | private
155 | def assert_on_destroy_unpreserved_join_entries_removed_for(table)
156 | join_table = @answer_store.association(table).join_table.name
157 | sql = "SELECT count(*) FROM #{join_table}"
158 | original_joins = AnswerStore.connection.select_value(sql)
159 | AnswerStore.destroy_unpreserved
160 | joins = AnswerStore.connection.select_value(sql)
161 | assert_equal(original_joins - 1, joins)
162 | end
163 |
164 | end
165 | end
--------------------------------------------------------------------------------
/test/unit/qwester/answer_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | module Qwester
4 |
5 | class AnswerTest < ActiveSupport::TestCase
6 | def setup
7 | @answer = Answer.find(1)
8 | end
9 |
10 | def test_find_first_or_create
11 | answer = Answer.find_first_or_create(
12 | :value => @answer.value,
13 | :question_id => @answer.question_id
14 | )
15 | assert_equal(@answer, answer)
16 | end
17 |
18 | def test_find_first_or_create_when_answer_does_not_exist
19 | new_value = 'something'
20 | assert_difference 'Answer.count' do
21 | answer = Answer.find_first_or_create(
22 | :value => 'something',
23 | :question_id => Question.first.id
24 | )
25 | end
26 | assert_equal(new_value, Answer.last.value)
27 | end
28 |
29 | def test_destroy
30 | rule_set = RuleSet.first
31 | answer_store = AnswerStore.first
32 | @answer.rule_sets = [rule_set]
33 | @answer.answer_stores = [answer_store]
34 | assert_difference 'Answer.count', -1 do
35 | assert_difference 'rule_set.answers.count', -1 do
36 | assert_difference 'answer_store.answers.count', -1 do
37 | @answer.destroy
38 | end
39 | end
40 | end
41 | end
42 |
43 | def test_rule_label
44 | assert_equal("a#{@answer.id}", @answer.rule_label)
45 | end
46 |
47 | def test_set_weighting_alias
48 | name = :new_alias_method
49 | assert(!Answer.instance_methods.include?(name.to_sym), "Answer methods should not include #{name} at start of test")
50 | Answer.weighting_alias = name
51 | assert_equal(name, Answer.weighting_alias)
52 | assert(Answer.instance_methods.include?(name.to_sym), "Set weighting alias should define instance method #{name} ")
53 | weighting = 4
54 | @answer.weighting = weighting
55 | assert_equal(weighting, @answer.send(name))
56 | remove_weighting_alias
57 | end
58 |
59 | def test_remove_weighting_alias
60 | Answer.weighting_alias = :something
61 | remove_weighting_alias
62 | end
63 |
64 | def test_setting_weighting_alias_to_nil_removes_existing_alias
65 | name = :new_alias_method
66 | Answer.weighting_alias = name
67 | Answer.weighting_alias = nil
68 | assert(!Answer.instance_methods.include?(name), "Answer methods should not include #{name}")
69 | assert_nil(Answer.weighting_alias)
70 | end
71 |
72 | def test_weighting_alias_name
73 | assert_equal('weighting', Answer.weighting_alias_name)
74 | name = 'something_weighty'
75 | Answer.weighting_alias = name
76 | assert_equal(name, Answer.weighting_alias_name)
77 | end
78 |
79 | private
80 | def remove_weighting_alias
81 | name = Answer.weighting_alias.to_sym
82 | Answer.remove_weighting_alias
83 | assert(!Answer.instance_methods.include?(name), "Answer methods should not include #{name}")
84 | Answer.class_eval "@weighting_alias = nil"
85 | assert_nil(Answer.weighting_alias)
86 | end
87 |
88 | end
89 | end
90 |
--------------------------------------------------------------------------------
/test/unit/qwester/presentation_questionnaire_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | module Qwester
4 | class PresentationQuestionnaireTest < ActiveSupport::TestCase
5 |
6 | def setup
7 | @presentation_questionnaire = PresentationQuestionnaire.find(1)
8 | @questionnaire = Questionnaire.find(2)
9 | @presentation = @presentation_questionnaire.presentation
10 | @presentation.questionnaires << @questionnaire
11 | @default_order = [@presentation_questionnaire.questionnaire, @questionnaire]
12 | end
13 |
14 | def test_setup
15 | assert_kind_of(Questionnaire, @presentation_questionnaire.questionnaire)
16 | assert_not_equal(@questionnaire, @presentation_questionnaire.questionnaire)
17 | assert_equal(@default_order, @presentation.questionnaires)
18 | end
19 |
20 | def test_acts_as_list_method_last
21 | assert_equal(true, @presentation.last?(@questionnaire))
22 | assert_equal(false, @presentation.last?(@presentation_questionnaire.questionnaire))
23 | end
24 |
25 | def test_acts_as_list_method_move_to_top
26 | @presentation.move_to_top(@questionnaire)
27 | assert_equal(@default_order.reverse, @presentation.questionnaires)
28 | end
29 |
30 | def test_position
31 | assert_equal(@presentation_questionnaire.position, @presentation.position(@presentation_questionnaire.questionnaire))
32 | end
33 |
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/test/unit/qwester/presentation_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | module Qwester
4 | class PresentationTest < ActiveSupport::TestCase
5 |
6 | def setup
7 | @questionnaire = Questionnaire.find(1)
8 | @presentation = Presentation.find(1)
9 | end
10 |
11 | def test_questionnaires
12 | assert(@presentation.questionnaires.include? @questionnaire)
13 | end
14 |
15 | def test_empty_questionnaires
16 | assert_equal([], empty_presentation.questionnaires)
17 | end
18 |
19 | def test_valid_names
20 | valid = %w{this that foo_bar HeyHo this1 that2 123}
21 | valid.each do |name|
22 | @presentation.name = name
23 | assert(@presentation.save, "#{name} should be a valid presentation name #{@presentation.errors.full_messages}")
24 | end
25 | end
26 |
27 | def test_invalid_names
28 | invalid = ['This and that', 'foo bar', '$this', '@that']
29 | invalid.each do |name|
30 | @presentation.name = name
31 | assert(!@presentation.save, "'#{name}' should be an invalid presentation name")
32 | end
33 | end
34 |
35 | def test_title_created_from_name
36 | @presentation.name = "foo_bar"
37 | @presentation.title = nil
38 | @presentation.save
39 | assert_equal('Foo bar', @presentation.title)
40 | end
41 |
42 | def test_set_as_default
43 | assert !@presentation.default?, "Presentation should not be default at start"
44 | @presentation.update_attribute(:default, true)
45 | assert @presentation.default?, "Presentation should be default"
46 | assert !empty_presentation.reload.default?, "Empty presentation should not be default"
47 | end
48 |
49 | def test_set_as_default_when_other_presentation_default
50 | test_set_as_default
51 | empty_presentation.update_attribute(:default, true)
52 | assert !@presentation.reload.default?, "Presentation should not be default"
53 | assert empty_presentation.default?, "Empty presentation should be default"
54 | end
55 |
56 | # Overriding this method, so want to make sure default behaviour still works
57 | # Tests for methods over-riding this are in other test, e.g. questionnaires_question_test.rb
58 | def test_method_missing
59 | assert_raise NoMethodError do
60 | @questionnaire.no_such_method
61 | end
62 | end
63 |
64 | def empty_presentation
65 | @empty_presentation ||= Presentation.find(2)
66 | end
67 |
68 | end
69 | end
70 |
--------------------------------------------------------------------------------
/test/unit/qwester/question_test.rb:
--------------------------------------------------------------------------------
1 | require_relative '../../test_helper'
2 | module Qwester
3 |
4 | class QuestionTest < ActiveSupport::TestCase
5 |
6 | def setup
7 | @question = Question.find(2)
8 | end
9 |
10 | def test_setup
11 | assert_equal(0, @question.answers.count)
12 | end
13 |
14 | def test_build_standard_answers
15 | assert_no_difference 'Answer.count' do
16 | @question.build_standard_answers
17 | assert_question_has_standard_answers
18 | end
19 | end
20 |
21 | def test_create_standard_answers
22 | assert_difference 'Answer.count', Answer.standard_values.length do
23 | @question.create_standard_answers
24 | assert_question_has_standard_answers
25 | end
26 | end
27 |
28 | def test_destroy
29 | test_create_standard_answers
30 | assert_difference 'Question.count', -1 do
31 | assert_difference 'Answer.count', -(Answer.standard_values.length) do
32 | @question.destroy
33 | end
34 | end
35 | end
36 |
37 | private
38 | def assert_question_has_standard_answers
39 | assert_equal(Answer.standard_values, @question.answers.collect(&:value))
40 | end
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/test/unit/qwester/questionnaire_test.rb:
--------------------------------------------------------------------------------
1 | require_relative '../../test_helper'
2 | module Qwester
3 |
4 | class QuestionnaireTest < ActiveSupport::TestCase
5 | def setup
6 | @questionnaire = Questionnaire.find(1)
7 | end
8 |
9 | # Overriding this method, so want to make sure default behaviour still works
10 | # Tests for methods over-riding this are in other test, e.g. questionnaires_question_test.rb
11 | def test_method_missing
12 | assert_raise NoMethodError do
13 | @questionnaire.no_such_method
14 | end
15 | end
16 |
17 | def test_habtm_joins_to_answer_store
18 | @questionnaire.answer_stores << AnswerStore.first
19 | end
20 |
21 | def test_presentation
22 | assert_equal([Presentation.find(1)], @questionnaire.presentations)
23 | end
24 | end
25 |
26 | end
27 |
--------------------------------------------------------------------------------
/test/unit/qwester/questionnaires_question_test.rb:
--------------------------------------------------------------------------------
1 | require_relative '../../test_helper'
2 | module Qwester
3 |
4 | class QuestionnairesQuestionTest < ActiveSupport::TestCase
5 | def setup
6 | @questionnaires_question = QuestionnairesQuestion.find(1)
7 | @questionnaire = @questionnaires_question.questionnaire
8 | @question = Question.find(2)
9 | end
10 |
11 | def test_setup
12 | assert_not_equal(@questionnaires_question.question, @question)
13 | end
14 |
15 | def test_position
16 | @questionnaire.questions << @question
17 | assert_equal(1, @questionnaires_question.position)
18 | assert_equal(2, QuestionnairesQuestion.last.position)
19 | end
20 |
21 | def test_move_question_up
22 | test_position
23 | @questionnaire.move_higher(@question)
24 | assert_equal(2, @questionnaires_question.reload.position)
25 | assert_equal(1, QuestionnairesQuestion.last.position)
26 | end
27 |
28 | def test_second_questionnaire_not_affected_by_positioning_in_first
29 | questionnaire = Questionnaire.find(2)
30 | question = Question.find(1)
31 | questionnaire.questions << question
32 | questionnaire.questions << @question
33 | assert_not_equal(@questionnaire, questionnaire, "should be working with two questionnaires")
34 | assert_equal([question, @question], questionnaire.questions)
35 | assert_equal([question], @questionnaire.questions)
36 | test_move_question_up
37 | assert_equal([question, @question], questionnaire.reload.questions)
38 | assert_equal([@question, question], @questionnaire.reload.questions)
39 | end
40 |
41 | def test_adding_question_again_does_not_create_duplicates
42 | @questionnaire.questions << @question
43 | assert_no_difference '@questionnaire.questions.count' do
44 | @questionnaire.reload.questions << @question
45 | end
46 | end
47 |
48 | def test_removing_quesition
49 | test_adding_question_again_does_not_create_duplicates
50 | @questionnaire.questions.delete(@question)
51 | assert_equal(1, @questionnaire.questions.count)
52 | end
53 |
54 | def test_removing_question_deletes_questionnaires_question_but_does_not_delete_question
55 | assert_no_difference 'Question.count' do
56 | assert_difference 'QuestionnairesQuestion.count', -1 do
57 | @questionnaire.questions.delete(@questionnaire.questions.first)
58 | end
59 | end
60 | end
61 | end
62 | end
63 |
--------------------------------------------------------------------------------
/test/unit/qwester/rule_set_test.rb:
--------------------------------------------------------------------------------
1 | require_relative '../../test_helper'
2 | module Qwester
3 |
4 | class RuleSetTest < ActiveSupport::TestCase
5 | def setup
6 | @rule_set = RuleSet.find(1)
7 | @answer = Answer.find(1)
8 | @other_answer = Answer.find(2)
9 | @rule_set.answers << @answer
10 | end
11 |
12 | def test_match
13 | assert(@rule_set.match(@rule_set.answers), "should match if rule_set.answers equal answers passed in")
14 | end
15 |
16 | def test_match_when_additional_answers_passed_in
17 | assert(@rule_set.match([@rule_set.answers, @other_answer].flatten), "should match as long as answers passed in include ruleset.answers")
18 | end
19 |
20 | def test_match_failure
21 | assert_no_rule_set_match([@other_answer])
22 | end
23 |
24 | def test_partial_match
25 | @rule_set.answers << @other_answer
26 | assert(@rule_set.match([@other_answer]), "should match as long as answers includes @other_answer")
27 | end
28 |
29 | def test_match_when_no_answers_passed_in
30 | assert_no_rule_set_match([])
31 | end
32 |
33 | def test_match_when_nil_passed_in
34 | assert_no_rule_set_match(nil)
35 | end
36 |
37 | def test_matches
38 | create_more_rule_sets
39 | rule_sets = RuleSet.matching([@answer])
40 | assert_equal(2, rule_sets.length)
41 | assert(rule_sets.include?(@rule_set), "RuleSet @rule_set should be included")
42 | assert(rule_sets.include?(@rule_set_one), "RuleSet one should be included")
43 | assert(!rule_sets.include?(@rule_set_two), "RuleSet two should not be included")
44 | end
45 |
46 | def test_matchs_with_where
47 | create_more_rule_sets
48 | rule_sets = RuleSet.where(:title => @rule_set.title).matching([@answer])
49 | assert_equal([@rule_set], rule_sets)
50 | end
51 |
52 | def test_custom_rule
53 | create_custom_rule_set('a1 and a2')
54 | assert(@rule_set.match([@answer, @other_answer]), "Should match as both answers present")
55 | assert(!@rule_set.match([@answer]), "Should not match as other answer missing")
56 | end
57 |
58 | def test_custom_rule_or
59 | create_custom_rule_set('a1 or a2')
60 | assert(@rule_set.match([@answer, @other_answer]), "Should match as both answers present")
61 | assert(@rule_set.match([@answer]), "Should match as answer present")
62 | end
63 |
64 | def test_custom_rule_in
65 | create_custom_rule_set('2 in a1 a2')
66 | assert(@rule_set.match([@answer, @other_answer]), "Should match as both answers present")
67 | assert(!@rule_set.match([@answer]), "Should not match as only one answer present")
68 | end
69 |
70 | def test_matching_answer_sets
71 | create_custom_rule_set('a1 and a2')
72 | assert_equal([[1, 2]], @rule_set.matching_answer_sets)
73 | end
74 |
75 | def test_blocking_answer_sets
76 | create_custom_rule_set('a1 and a2')
77 | assert_equal([[1], [2]], @rule_set.blocking_answer_sets)
78 | end
79 |
80 | def test_default_rules_created_from_answers_on_create
81 | rule_set = RuleSet.create(:title => 'One', :answers => [@answer], :url => 'http://undervale.co.uk')
82 | assert_equal(rule_set.default_rule, rule_set.rule)
83 | rule_set = RuleSet.create(:title => 'Two', :answers => [@answer, @other_answer], :url => 'http://undervale.co.uk')
84 | assert_equal(rule_set.default_rule, rule_set.rule)
85 | end
86 |
87 | def test_default_rule
88 | assert_equal(@answer.rule_label, @rule_set.default_rule)
89 | @rule_set.answers << @other_answer
90 | expected = "#{@answer.rule_label} #{RuleSet::DEFAULT_RULE_JOIN} #{@other_answer.rule_label}"
91 | assert_equal(expected, @rule_set.default_rule)
92 | end
93 |
94 | def test_answers_populated_by_rules
95 | test_custom_rule
96 | assert_equal([@answer, @other_answer], @rule_set.answers)
97 | end
98 |
99 | def test_answers_shrink_when_answer_removed_from_rule
100 | test_answers_populated_by_rules
101 | @rule_set.reload.rule = 'a1'
102 | @rule_set.save
103 | assert_equal([@answer], @rule_set.answers)
104 | end
105 |
106 | def test_answers_expand_when_answer_added_to_rule
107 | @rule_set.rule = 'a1 and a2'
108 | @rule_set.save
109 | assert_equal([@answer, @other_answer], @rule_set.answers)
110 | end
111 |
112 | def test_rule_validation
113 | @rule_set.rule = 'invalid'
114 | @rule_set.save
115 | assert(@rule_set.errors[:rule].present?, "there should be an error against the rule field")
116 | end
117 |
118 | def test_rule_has_url
119 | @rule_set.url = nil
120 | assert(@rule_set.invalid?, "RuleSet should be invalid if no url")
121 | assert(@rule_set.errors[:url], "Error should be on url field")
122 | end
123 |
124 | def test_rule_valid_without_url_if_presentation_set
125 | @rule_set.presentation = 'something'
126 | @rule_set.url = nil
127 | assert(@rule_set.valid?, "RuleSet should be valid")
128 | end
129 |
130 | def test_rule_set_invalid_if_answer_in_rule_does_not_exist
131 | nonexistent_answer_id = Qwester::Answer.select('id').max.id + 1
132 | @rule_set.rule = "a#{nonexistent_answer_id}"
133 | assert @rule_set.invalid?, "Rules set should be invalid"
134 | assert @rule_set.errors[:rule], 'Error should be on rule'
135 | end
136 |
137 | private
138 | def assert_no_rule_set_match(answers = nil)
139 | assert(!@rule_set.match(answers), "should not return true if no match found")
140 | end
141 |
142 | def create_more_rule_sets
143 | @rule_set_one = RuleSet.create(:title => 'One', :answers => [@answer], :url => 'http://undervale.co.uk')
144 | @rule_set_two = RuleSet.create(:title => 'Two', :answers => [@other_answer], :url => 'http://undervale.com')
145 | end
146 |
147 | def create_custom_rule_set(rule)
148 | @rule_set = RuleSet.create(:title => 'Custom', :rule => rule, :url => 'http://undervale.co.uk')
149 | end
150 |
151 | end
152 |
153 | end
154 |
--------------------------------------------------------------------------------
/test/unit/qwester_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class QwesterTest < ActiveSupport::TestCase
4 |
5 | def setup
6 | Qwester.active_admin_menu = nil
7 | Qwester.session_key = nil
8 | end
9 |
10 | def test_qwester_set_up_as_a_module
11 | assert_kind_of Module, Qwester
12 | end
13 |
14 | def test_active_admin_load_path
15 | expected = "#{Qwester::Engine.root}/lib/active_admin/admin"
16 | assert_equal(expected, Qwester.active_admin_load_path)
17 | end
18 |
19 | def test_active_admin_menu
20 | assert_equal('Qwester', Qwester.active_admin_menu)
21 | end
22 |
23 | def test_setting_active_admin_menu
24 | text = 'Foo'
25 | Qwester.active_admin_menu = text
26 | assert_equal(text, Qwester.active_admin_menu)
27 | end
28 |
29 | def test_active_admin_menu_none
30 | Qwester.active_admin_menu = 'none'
31 | assert_nil(Qwester.active_admin_menu)
32 | end
33 |
34 | def test_session_key
35 | assert_equal(:qwester_answer_store, Qwester.session_key)
36 | end
37 |
38 | def test_setting_session_key
39 | key = :something_else
40 | Qwester.session_key = key
41 | assert_equal(key, Qwester.session_key)
42 | end
43 |
44 | end
45 |
--------------------------------------------------------------------------------