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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +9 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +234 -0
  5. data/Rakefile +30 -0
  6. data/app/models/survey/answer.rb +50 -0
  7. data/app/models/survey/attempt.rb +74 -0
  8. data/app/models/survey/option.rb +44 -0
  9. data/app/models/survey/options_type.rb +35 -0
  10. data/app/models/survey/predefined_value.rb +23 -0
  11. data/app/models/survey/question.rb +52 -0
  12. data/app/models/survey/questions_type.rb +27 -0
  13. data/app/models/survey/section.rb +47 -0
  14. data/app/models/survey/survey.rb +63 -0
  15. data/config/locales/en.yml +54 -0
  16. data/config/locales/pt-PT.yml +48 -0
  17. data/config/locales/pt.yml +48 -0
  18. data/lib/generators/survey/install_generator.rb +35 -0
  19. data/lib/generators/survey/survey_generator.rb +77 -0
  20. data/lib/generators/templates/active_admin.rb +85 -0
  21. data/lib/generators/templates/attempts_plain.rb +36 -0
  22. data/lib/generators/templates/attempts_views/_form.html.erb +61 -0
  23. data/lib/generators/templates/attempts_views/new.html.erb +10 -0
  24. data/lib/generators/templates/helper.rb +46 -0
  25. data/lib/generators/templates/migration.rb +56 -0
  26. data/lib/generators/templates/migration_add_head_number_to_options_table.rb +6 -0
  27. data/lib/generators/templates/migration_add_mandatory_to_questions_table.rb +6 -0
  28. data/lib/generators/templates/migration_add_types_to_questions_and_options.rb +13 -0
  29. data/lib/generators/templates/migration_create_predefined_values_table.rb +14 -0
  30. data/lib/generators/templates/migration_section.rb +22 -0
  31. data/lib/generators/templates/migration_update_survey_tables.rb +22 -0
  32. data/lib/generators/templates/rails_admin.rb +8 -0
  33. data/lib/generators/templates/survey_plain.rb +60 -0
  34. data/lib/generators/templates/survey_views/_form.html.erb +72 -0
  35. data/lib/generators/templates/survey_views/_option_fields.html.erb +26 -0
  36. data/lib/generators/templates/survey_views/_question_fields.html.erb +42 -0
  37. data/lib/generators/templates/survey_views/_section_fields.html.erb +29 -0
  38. data/lib/generators/templates/survey_views/edit.html.erb +2 -0
  39. data/lib/generators/templates/survey_views/index.html.erb +14 -0
  40. data/lib/generators/templates/survey_views/new.html.erb +2 -0
  41. data/lib/survey.rb +5 -0
  42. data/lib/survey/active_record.rb +15 -0
  43. data/lib/survey/engine.rb +6 -0
  44. data/lib/survey/version.rb +3 -0
  45. 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