questionnaire_engine 0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|