questionnaire_engine 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +9 -0
- data/MIT-LICENSE +20 -0
- data/README.md +234 -0
- data/Rakefile +30 -0
- data/app/models/survey/answer.rb +50 -0
- data/app/models/survey/attempt.rb +74 -0
- data/app/models/survey/option.rb +44 -0
- data/app/models/survey/options_type.rb +35 -0
- data/app/models/survey/predefined_value.rb +23 -0
- data/app/models/survey/question.rb +52 -0
- data/app/models/survey/questions_type.rb +27 -0
- data/app/models/survey/section.rb +47 -0
- data/app/models/survey/survey.rb +63 -0
- data/config/locales/en.yml +54 -0
- data/config/locales/pt-PT.yml +48 -0
- data/config/locales/pt.yml +48 -0
- data/lib/generators/survey/install_generator.rb +35 -0
- data/lib/generators/survey/survey_generator.rb +77 -0
- data/lib/generators/templates/active_admin.rb +85 -0
- data/lib/generators/templates/attempts_plain.rb +36 -0
- data/lib/generators/templates/attempts_views/_form.html.erb +61 -0
- data/lib/generators/templates/attempts_views/new.html.erb +10 -0
- data/lib/generators/templates/helper.rb +46 -0
- data/lib/generators/templates/migration.rb +56 -0
- data/lib/generators/templates/migration_add_head_number_to_options_table.rb +6 -0
- data/lib/generators/templates/migration_add_mandatory_to_questions_table.rb +6 -0
- data/lib/generators/templates/migration_add_types_to_questions_and_options.rb +13 -0
- data/lib/generators/templates/migration_create_predefined_values_table.rb +14 -0
- data/lib/generators/templates/migration_section.rb +22 -0
- data/lib/generators/templates/migration_update_survey_tables.rb +22 -0
- data/lib/generators/templates/rails_admin.rb +8 -0
- data/lib/generators/templates/survey_plain.rb +60 -0
- data/lib/generators/templates/survey_views/_form.html.erb +72 -0
- data/lib/generators/templates/survey_views/_option_fields.html.erb +26 -0
- data/lib/generators/templates/survey_views/_question_fields.html.erb +42 -0
- data/lib/generators/templates/survey_views/_section_fields.html.erb +29 -0
- data/lib/generators/templates/survey_views/edit.html.erb +2 -0
- data/lib/generators/templates/survey_views/index.html.erb +14 -0
- data/lib/generators/templates/survey_views/new.html.erb +2 -0
- data/lib/survey.rb +5 -0
- data/lib/survey/active_record.rb +15 -0
- data/lib/survey/engine.rb +6 -0
- data/lib/survey/version.rb +3 -0
- metadata +142 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
class Survey::OptionsType
|
2
|
+
@@options_types = {:multi_choices => 1,
|
3
|
+
:single_choice => 2,
|
4
|
+
:number => 3,
|
5
|
+
:text => 4,
|
6
|
+
:multi_choices_with_text => 5,
|
7
|
+
:single_choice_with_text => 6,
|
8
|
+
:multi_choices_with_number => 7,
|
9
|
+
:single_choice_with_number => 8,
|
10
|
+
:large_text => 9}
|
11
|
+
|
12
|
+
def self.options_types
|
13
|
+
@@options_types
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.options_types_title
|
17
|
+
titled = {}
|
18
|
+
Survey::OptionsType.options_types.each{|k, v| titled[k.to_s.titleize] = v}
|
19
|
+
titled
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.options_type_ids
|
23
|
+
@@options_types.values
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.options_type_keys
|
27
|
+
@@options_types.keys
|
28
|
+
end
|
29
|
+
|
30
|
+
@@options_types.each do |key, val|
|
31
|
+
define_singleton_method "#{key}" do
|
32
|
+
val
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Survey::PredefinedValue < ActiveRecord::Base
|
2
|
+
|
3
|
+
self.table_name = "survey_predefined_values"
|
4
|
+
|
5
|
+
#relations
|
6
|
+
belongs_to :question
|
7
|
+
|
8
|
+
#rails 3 attr_accessible support
|
9
|
+
if Rails::VERSION::MAJOR < 4
|
10
|
+
attr_accessible :head_number, :name, :locale_name, :question_id
|
11
|
+
end
|
12
|
+
|
13
|
+
# validations
|
14
|
+
validates :name, :presence => true
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
self.name
|
18
|
+
end
|
19
|
+
|
20
|
+
def name
|
21
|
+
I18n.locale == I18n.default_locale ? super : locale_name || super
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
class Survey::Question < ActiveRecord::Base
|
2
|
+
|
3
|
+
self.table_name = "survey_questions"
|
4
|
+
# relations
|
5
|
+
has_many :options
|
6
|
+
has_many :predefined_values
|
7
|
+
belongs_to :section
|
8
|
+
|
9
|
+
#rails 3 attr_accessible support
|
10
|
+
if Rails::VERSION::MAJOR < 4
|
11
|
+
attr_accessible :options_attributes, :predefined_values_attributes, :text, :section_id, :head_number, :description, :locale_text, :locale_head_number, :locale_description, :questions_type_id
|
12
|
+
end
|
13
|
+
|
14
|
+
accepts_nested_attributes_for :options,
|
15
|
+
:reject_if => ->(a) { a[:options_type_id].blank? },
|
16
|
+
:allow_destroy => true
|
17
|
+
|
18
|
+
accepts_nested_attributes_for :predefined_values,
|
19
|
+
:reject_if => ->(a) { a[:name].blank? },
|
20
|
+
:allow_destroy => true
|
21
|
+
|
22
|
+
# validations
|
23
|
+
validates :text, :presence => true, :allow_blank => false
|
24
|
+
validates :questions_type_id, :presence => true
|
25
|
+
validates_inclusion_of :questions_type_id, :in => Survey::QuestionsType.questions_type_ids, :unless => Proc.new{|q| q.questions_type_id.blank?}
|
26
|
+
|
27
|
+
scope :mandatory_only, -> { where(:mandatory => true) }
|
28
|
+
|
29
|
+
def correct_options
|
30
|
+
options.correct
|
31
|
+
end
|
32
|
+
|
33
|
+
def incorrect_options
|
34
|
+
options.incorrect
|
35
|
+
end
|
36
|
+
|
37
|
+
def text
|
38
|
+
I18n.locale == I18n.default_locale ? super : locale_text.blank? ? super : locale_text
|
39
|
+
end
|
40
|
+
|
41
|
+
def description
|
42
|
+
I18n.locale == I18n.default_locale ? super : locale_description.blank? ? super : locale_description
|
43
|
+
end
|
44
|
+
|
45
|
+
def head_number
|
46
|
+
I18n.locale == I18n.default_locale ? super : locale_head_number.blank? ? super : locale_head_number
|
47
|
+
end
|
48
|
+
|
49
|
+
def mandatory?
|
50
|
+
self.mandatory == true
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class Survey::QuestionsType
|
2
|
+
@@questions_types = {:general => 1}
|
3
|
+
|
4
|
+
def self.questions_types
|
5
|
+
@@questions_types
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.questions_types_title
|
9
|
+
titled = {}
|
10
|
+
Survey::QuestionsType.questions_types.each{|k, v| titled[k.to_s.titleize] = v}
|
11
|
+
titled
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.questions_type_ids
|
15
|
+
@@questions_types.values
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.questions_type_keys
|
19
|
+
@@questions_types.keys
|
20
|
+
end
|
21
|
+
|
22
|
+
@@questions_types.each do |key, val|
|
23
|
+
define_singleton_method "#{key}" do
|
24
|
+
val
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class Survey::Section < ActiveRecord::Base
|
2
|
+
|
3
|
+
self.table_name = "survey_sections"
|
4
|
+
|
5
|
+
# relations
|
6
|
+
has_many :questions
|
7
|
+
|
8
|
+
#rails 3 attr_accessible support
|
9
|
+
if Rails::VERSION::MAJOR < 4
|
10
|
+
attr_accessible :questions_attributes, :head_number, :name, :description , :survey_id, :locale_head_number, :locale_name, :locale_description
|
11
|
+
end
|
12
|
+
|
13
|
+
accepts_nested_attributes_for :questions,
|
14
|
+
:reject_if => ->(q) { q[:text].blank? }, :allow_destroy => true
|
15
|
+
|
16
|
+
# validations
|
17
|
+
validates :name, :presence => true, :allow_blank => false
|
18
|
+
validate :check_questions_requirements
|
19
|
+
|
20
|
+
def name
|
21
|
+
I18n.locale == I18n.default_locale ? super : locale_name.blank? ? super : locale_name
|
22
|
+
end
|
23
|
+
|
24
|
+
def description
|
25
|
+
I18n.locale == I18n.default_locale ? super : locale_description.blank? ? super : locale_description
|
26
|
+
end
|
27
|
+
|
28
|
+
def head_number
|
29
|
+
I18n.locale == I18n.default_locale ? super : locale_head_number.blank? ? super : locale_head_number
|
30
|
+
end
|
31
|
+
|
32
|
+
def full_name
|
33
|
+
head_name = self.head_number.blank? ? "" : "#{self.head_number}: "
|
34
|
+
"#{head_name}#{self.name}"
|
35
|
+
end
|
36
|
+
|
37
|
+
#######
|
38
|
+
private
|
39
|
+
#######
|
40
|
+
|
41
|
+
# a section only can be saved if has one or more questions and options
|
42
|
+
def check_questions_requirements
|
43
|
+
if self.questions.empty? || self.questions.collect(&:options).empty?
|
44
|
+
errors.add(:base, "Section without questions or options cannot be saved")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
class Survey::Survey < ActiveRecord::Base
|
2
|
+
|
3
|
+
self.table_name = "survey_surveys"
|
4
|
+
|
5
|
+
# relations
|
6
|
+
has_many :attempts
|
7
|
+
has_many :sections
|
8
|
+
|
9
|
+
#rails 3 attr_accessible support
|
10
|
+
if Rails::VERSION::MAJOR < 4
|
11
|
+
attr_accessible :name, :description, :finished, :active, :sections_attributes, :attempts_number, :locale_name, :locale_description
|
12
|
+
end
|
13
|
+
|
14
|
+
accepts_nested_attributes_for :sections,
|
15
|
+
:reject_if => ->(q) { q[:name].blank? }, :allow_destroy => true
|
16
|
+
|
17
|
+
scope :active, -> { where(:active => true) }
|
18
|
+
scope :inactive, -> { where(:active => false) }
|
19
|
+
|
20
|
+
|
21
|
+
validates :attempts_number,
|
22
|
+
:numericality => { :only_integer => true, :greater_than => -1 }
|
23
|
+
|
24
|
+
# validations
|
25
|
+
validates :description, :name, :presence => true, :allow_blank => false
|
26
|
+
validate :check_active_requirements
|
27
|
+
|
28
|
+
# returns all the correct options for current surveys
|
29
|
+
def correct_options
|
30
|
+
Survey::Question.where(:section_id => self.sections.collect(&:id)).map { |question| question.correct_options }.flatten
|
31
|
+
end
|
32
|
+
|
33
|
+
# returns all the incorrect options for current surveys
|
34
|
+
def incorrect_options
|
35
|
+
Survey::Question.where(:section_id => self.sections.collect(&:id)).map { |question| question.incorrect_options }.flatten
|
36
|
+
end
|
37
|
+
|
38
|
+
def avaliable_for_participant?(participant)
|
39
|
+
current_number_of_attempts =
|
40
|
+
self.attempts.for_participant(participant).size
|
41
|
+
upper_bound = self.attempts_number
|
42
|
+
not(current_number_of_attempts >= upper_bound and upper_bound != 0)
|
43
|
+
end
|
44
|
+
|
45
|
+
def name
|
46
|
+
I18n.locale == I18n.default_locale ? super : locale_name.blank? ? super : locale_name
|
47
|
+
end
|
48
|
+
|
49
|
+
def description
|
50
|
+
I18n.locale == I18n.default_locale ? super : locale_description.blank? ? super : locale_description
|
51
|
+
end
|
52
|
+
|
53
|
+
#######
|
54
|
+
private
|
55
|
+
#######
|
56
|
+
|
57
|
+
# a surveys only can be activated if has one or more sections and questions
|
58
|
+
def check_active_requirements
|
59
|
+
if self.sections.empty? || self.sections.collect(&:questions).empty?
|
60
|
+
errors.add(:base, "Survey without sections or questions cannot be saved")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
en:
|
2
|
+
surveys_controller:
|
3
|
+
create: Your Survey has been successfull created
|
4
|
+
update: Your Survey has been successfull updated
|
5
|
+
attempts_controller:
|
6
|
+
create: "Congratulations, you have responded to Survey."
|
7
|
+
surveys: Surveys
|
8
|
+
survey_details: Survey Details
|
9
|
+
questions: Questions
|
10
|
+
sections: Sections
|
11
|
+
predefined_values: Predefined Values
|
12
|
+
activerecord:
|
13
|
+
models:
|
14
|
+
survey:
|
15
|
+
survey: Survey
|
16
|
+
other: Surveys
|
17
|
+
attributes:
|
18
|
+
survey:
|
19
|
+
name: Name
|
20
|
+
locale_name: Localized name
|
21
|
+
finished: Finished
|
22
|
+
description: Short description
|
23
|
+
locale_description: Localized short description
|
24
|
+
active: "Activated?"
|
25
|
+
attempts_number: Number of Maximum Attempts
|
26
|
+
sections_attributes: Sections
|
27
|
+
section:
|
28
|
+
head_number: Head Number
|
29
|
+
name: Name
|
30
|
+
description: Description
|
31
|
+
locale_head_number: Localized head number
|
32
|
+
locale_name: Localized name
|
33
|
+
locale_description: Localized Description
|
34
|
+
question:
|
35
|
+
head_number: Head Number
|
36
|
+
text: Question Text
|
37
|
+
description: Description
|
38
|
+
locale_head_number: Localized head number
|
39
|
+
locale_text: Localized Question Text
|
40
|
+
locale_description: Localized Description
|
41
|
+
options_attributes: Options
|
42
|
+
predefined_values_attributes: Predefined Values
|
43
|
+
options:
|
44
|
+
text: Option Text
|
45
|
+
locale_text: Localized Option Text
|
46
|
+
correct: Correct
|
47
|
+
attempt:
|
48
|
+
answers_attributes: Answers
|
49
|
+
survey: Survey
|
50
|
+
answer:
|
51
|
+
attempt: Attempt
|
52
|
+
question: Question
|
53
|
+
option: Option
|
54
|
+
correct: Answer Correct?
|
@@ -0,0 +1,48 @@
|
|
1
|
+
pt-PT:
|
2
|
+
questions: Perguntas
|
3
|
+
survey_details: Detalhes do Questionário
|
4
|
+
surveys_controller:
|
5
|
+
create: O questionário foi criado com sucesso
|
6
|
+
update: O questionário foi atualizado com sucesso
|
7
|
+
attempts_controller:
|
8
|
+
create: "A sua resposta foi efetuada com sucesso."
|
9
|
+
surveys: Questionários
|
10
|
+
survey_details: Detalhes do Questionário
|
11
|
+
questions: Perguntas
|
12
|
+
activerecord:
|
13
|
+
models:
|
14
|
+
survey:
|
15
|
+
survey: Questionário
|
16
|
+
other: Questionários
|
17
|
+
question:
|
18
|
+
question: Pergunta
|
19
|
+
other: Perguntas
|
20
|
+
option:
|
21
|
+
option: Opção
|
22
|
+
other: Opções
|
23
|
+
attempt:
|
24
|
+
option: Resposta
|
25
|
+
other: Respostas
|
26
|
+
attributes:
|
27
|
+
survey:
|
28
|
+
name: Nome
|
29
|
+
finished: Acabado
|
30
|
+
description: Pequena Descrição
|
31
|
+
active: "Ativo?"
|
32
|
+
attempts_number: Número máximo de tentativas
|
33
|
+
questions_attributes: Perguntas
|
34
|
+
question:
|
35
|
+
text: Corpo da Pergunta
|
36
|
+
options_attributes: Opções
|
37
|
+
options:
|
38
|
+
text: Corpo da Opção
|
39
|
+
correct: Correta
|
40
|
+
attempt:
|
41
|
+
answers_attributes: Respostas
|
42
|
+
survey: Questionário
|
43
|
+
winner: Vencedor
|
44
|
+
answer:
|
45
|
+
attempt: Tentativa
|
46
|
+
question: Pergunta
|
47
|
+
option: Opção
|
48
|
+
correct: Resposta Correta?
|
@@ -0,0 +1,48 @@
|
|
1
|
+
pt:
|
2
|
+
questions: Perguntas
|
3
|
+
survey_details: Detalhes do Questionário
|
4
|
+
surveys_controller:
|
5
|
+
create: O questionário foi criado com sucesso
|
6
|
+
update: O questionário foi atualizado com sucesso
|
7
|
+
attempts_controller:
|
8
|
+
create: "A sua resposta foi efetuada com sucesso."
|
9
|
+
surveys: Questionários
|
10
|
+
survey_details: Detalhes do Questionário
|
11
|
+
questions: Perguntas
|
12
|
+
activerecord:
|
13
|
+
models:
|
14
|
+
survey:
|
15
|
+
survey: Questionário
|
16
|
+
other: Questionários
|
17
|
+
question:
|
18
|
+
question: Pergunta
|
19
|
+
other: Perguntas
|
20
|
+
option:
|
21
|
+
option: Opção
|
22
|
+
other: Opções
|
23
|
+
attempt:
|
24
|
+
option: Resposta
|
25
|
+
other: Respostas
|
26
|
+
attributes:
|
27
|
+
survey:
|
28
|
+
name: Nome
|
29
|
+
finished: Acabado
|
30
|
+
description: Pequena Descrição
|
31
|
+
active: "Ativo?"
|
32
|
+
attempts_number: Número máximo de tentativas
|
33
|
+
questions_attributes: Perguntas
|
34
|
+
question:
|
35
|
+
text: Corpo da Pergunta
|
36
|
+
options_attributes: Opções
|
37
|
+
options:
|
38
|
+
text: Corpo da Opção
|
39
|
+
correct: Correta
|
40
|
+
attempt:
|
41
|
+
answers_attributes: Respostas
|
42
|
+
survey: Questionário
|
43
|
+
winner: Vencedor
|
44
|
+
answer:
|
45
|
+
attempt: Tentativa
|
46
|
+
question: Pergunta
|
47
|
+
option: Opção
|
48
|
+
correct: Resposta Correta?
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Survey
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path("../../templates", __FILE__)
|
5
|
+
|
6
|
+
def copy_migration
|
7
|
+
timestamp_number = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
|
8
|
+
|
9
|
+
migration_files = [{new_file_name: "create_survey", origin_file_name: "migration"},
|
10
|
+
{new_file_name: "create_sections", origin_file_name: "migration_section"},
|
11
|
+
{new_file_name: "update_survey_tables", origin_file_name: "migration_update_survey_tables"},
|
12
|
+
{new_file_name: "add_types_to_questions_and_options", origin_file_name: "migration_add_types_to_questions_and_options"},
|
13
|
+
{new_file_name: "add_head_number_to_options_table", origin_file_name: "migration_add_head_number_to_options_table"},
|
14
|
+
{new_file_name: "create_predefined_values_table", origin_file_name: "migration_create_predefined_values_table"},
|
15
|
+
{new_file_name: "add_mandatory_to_questions_table", origin_file_name: "migration_add_mandatory_to_questions_table"}
|
16
|
+
]
|
17
|
+
|
18
|
+
migration_files.each do |migration_file|
|
19
|
+
unless already_exists?(migration_file[:new_file_name])
|
20
|
+
copy_file "#{migration_file[:origin_file_name]}.rb", "db/migrate/#{timestamp_number}_#{migration_file[:new_file_name]}.rb"
|
21
|
+
timestamp_number += 1
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
#######
|
27
|
+
private
|
28
|
+
#######
|
29
|
+
|
30
|
+
def already_exists?(file_name)
|
31
|
+
Dir.glob("#{File.join(destination_root, File.join("db", "migrate"))}/[0-9]*_*.rb").grep(Regexp.new('\d+_' + file_name + '.rb$')).first
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|