questionnaire_engine 0.1

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