jakewendt-surveyor 0.11.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (160) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +285 -0
  3. data/Rakefile +54 -0
  4. data/VERSION +1 -0
  5. data/app/controllers/surveyor_controller.rb +142 -0
  6. data/app/helpers/survey_form_builder.rb +37 -0
  7. data/app/helpers/surveyor_helper.rb +67 -0
  8. data/app/models/answer.rb +23 -0
  9. data/app/models/dependency.rb +50 -0
  10. data/app/models/dependency_condition.rb +47 -0
  11. data/app/models/question.rb +54 -0
  12. data/app/models/question_group.rb +33 -0
  13. data/app/models/response.rb +94 -0
  14. data/app/models/response_set.rb +316 -0
  15. data/app/models/survey.rb +172 -0
  16. data/app/models/survey_section.rb +18 -0
  17. data/app/models/validation.rb +38 -0
  18. data/app/models/validation_condition.rb +47 -0
  19. data/app/views/layouts/surveyor_default.html.erb +13 -0
  20. data/app/views/partials/_answer.html.haml +58 -0
  21. data/app/views/partials/_question.html.haml +80 -0
  22. data/app/views/partials/_question_group.html.haml +39 -0
  23. data/app/views/surveyor/edit.html.haml +38 -0
  24. data/app/views/surveyor/new.html.haml +16 -0
  25. data/app/views/surveyor/show.html.haml +12 -0
  26. data/config/routes.rb +11 -0
  27. data/features/step_definitions/surveyor_steps.rb +7 -0
  28. data/features/step_definitions/web_steps.rb +273 -0
  29. data/features/support/env.rb +57 -0
  30. data/features/support/paths.rb +25 -0
  31. data/features/surveyor.feature +11 -0
  32. data/generators/extend_surveyor/extend_surveyor_generator.rb +22 -0
  33. data/generators/extend_surveyor/templates/EXTENDING_SURVEYOR +17 -0
  34. data/generators/extend_surveyor/templates/extensions/survey_extensions.rb +24 -0
  35. data/generators/extend_surveyor/templates/extensions/surveyor_controller_extensions.rb +28 -0
  36. data/generators/extend_surveyor/templates/extensions/surveyor_custom.html.erb +13 -0
  37. data/generators/extend_surveyor/templates/extensions/surveyor_helper_extensions.rb +17 -0
  38. data/generators/surveyor/surveyor_generator.rb +67 -0
  39. data/generators/surveyor/templates/README +10 -0
  40. data/generators/surveyor/templates/assets/images/222222_11x11_icon_arrows_leftright.gif +0 -0
  41. data/generators/surveyor/templates/assets/images/222222_11x11_icon_arrows_updown.gif +0 -0
  42. data/generators/surveyor/templates/assets/images/222222_11x11_icon_close.gif +0 -0
  43. data/generators/surveyor/templates/assets/images/222222_11x11_icon_doc.gif +0 -0
  44. data/generators/surveyor/templates/assets/images/222222_11x11_icon_folder_closed.gif +0 -0
  45. data/generators/surveyor/templates/assets/images/222222_11x11_icon_folder_open.gif +0 -0
  46. data/generators/surveyor/templates/assets/images/222222_11x11_icon_minus.gif +0 -0
  47. data/generators/surveyor/templates/assets/images/222222_11x11_icon_plus.gif +0 -0
  48. data/generators/surveyor/templates/assets/images/222222_11x11_icon_resize_se.gif +0 -0
  49. data/generators/surveyor/templates/assets/images/222222_35x9_colorpicker_indicator.gif.gif +0 -0
  50. data/generators/surveyor/templates/assets/images/222222_7x7_arrow_down.gif +0 -0
  51. data/generators/surveyor/templates/assets/images/222222_7x7_arrow_left.gif +0 -0
  52. data/generators/surveyor/templates/assets/images/222222_7x7_arrow_right.gif +0 -0
  53. data/generators/surveyor/templates/assets/images/222222_7x7_arrow_up.gif +0 -0
  54. data/generators/surveyor/templates/assets/images/454545_11x11_icon_arrows_leftright.gif +0 -0
  55. data/generators/surveyor/templates/assets/images/454545_11x11_icon_arrows_updown.gif +0 -0
  56. data/generators/surveyor/templates/assets/images/454545_11x11_icon_close.gif +0 -0
  57. data/generators/surveyor/templates/assets/images/454545_11x11_icon_doc.gif +0 -0
  58. data/generators/surveyor/templates/assets/images/454545_11x11_icon_folder_closed.gif +0 -0
  59. data/generators/surveyor/templates/assets/images/454545_11x11_icon_folder_open.gif +0 -0
  60. data/generators/surveyor/templates/assets/images/454545_11x11_icon_minus.gif +0 -0
  61. data/generators/surveyor/templates/assets/images/454545_11x11_icon_plus.gif +0 -0
  62. data/generators/surveyor/templates/assets/images/454545_7x7_arrow_down.gif +0 -0
  63. data/generators/surveyor/templates/assets/images/454545_7x7_arrow_left.gif +0 -0
  64. data/generators/surveyor/templates/assets/images/454545_7x7_arrow_right.gif +0 -0
  65. data/generators/surveyor/templates/assets/images/454545_7x7_arrow_up.gif +0 -0
  66. data/generators/surveyor/templates/assets/images/888888_11x11_icon_arrows_leftright.gif +0 -0
  67. data/generators/surveyor/templates/assets/images/888888_11x11_icon_arrows_updown.gif +0 -0
  68. data/generators/surveyor/templates/assets/images/888888_11x11_icon_close.gif +0 -0
  69. data/generators/surveyor/templates/assets/images/888888_11x11_icon_doc.gif +0 -0
  70. data/generators/surveyor/templates/assets/images/888888_11x11_icon_folder_closed.gif +0 -0
  71. data/generators/surveyor/templates/assets/images/888888_11x11_icon_folder_open.gif +0 -0
  72. data/generators/surveyor/templates/assets/images/888888_11x11_icon_minus.gif +0 -0
  73. data/generators/surveyor/templates/assets/images/888888_11x11_icon_plus.gif +0 -0
  74. data/generators/surveyor/templates/assets/images/888888_7x7_arrow_down.gif +0 -0
  75. data/generators/surveyor/templates/assets/images/888888_7x7_arrow_left.gif +0 -0
  76. data/generators/surveyor/templates/assets/images/888888_7x7_arrow_right.gif +0 -0
  77. data/generators/surveyor/templates/assets/images/888888_7x7_arrow_up.gif +0 -0
  78. data/generators/surveyor/templates/assets/images/dadada_40x100_textures_02_glass_75.png +0 -0
  79. data/generators/surveyor/templates/assets/images/e6e6e6_40x100_textures_02_glass_75.png +0 -0
  80. data/generators/surveyor/templates/assets/images/ffffff_40x100_textures_01_flat_0.png +0 -0
  81. data/generators/surveyor/templates/assets/images/ffffff_40x100_textures_02_glass_65.png +0 -0
  82. data/generators/surveyor/templates/assets/javascripts/accessibleUISlider.jQuery.js +201 -0
  83. data/generators/surveyor/templates/assets/javascripts/jquery-1.2.6.js +3549 -0
  84. data/generators/surveyor/templates/assets/javascripts/jquery-ui-personalized-1.5.3.js +7616 -0
  85. data/generators/surveyor/templates/assets/javascripts/jquery.form.js +637 -0
  86. data/generators/surveyor/templates/assets/javascripts/surveyor.js +47 -0
  87. data/generators/surveyor/templates/assets/stylesheets/jquery-ui-slider-additions.css +71 -0
  88. data/generators/surveyor/templates/assets/stylesheets/reset.css +50 -0
  89. data/generators/surveyor/templates/assets/stylesheets/sass/surveyor.sass +243 -0
  90. data/generators/surveyor/templates/assets/stylesheets/surveyor.css +235 -0
  91. data/generators/surveyor/templates/assets/stylesheets/ui.theme.css +851 -0
  92. data/generators/surveyor/templates/initializers/haml.rb +8 -0
  93. data/generators/surveyor/templates/initializers/surveyor.rb +10 -0
  94. data/generators/surveyor/templates/migrate/add_correct_answer_id_to_questions.rb +9 -0
  95. data/generators/surveyor/templates/migrate/add_display_order_to_surveys.rb +9 -0
  96. data/generators/surveyor/templates/migrate/add_index_to_response_sets.rb +9 -0
  97. data/generators/surveyor/templates/migrate/add_index_to_surveys.rb +9 -0
  98. data/generators/surveyor/templates/migrate/add_manual_numbering.rb +11 -0
  99. data/generators/surveyor/templates/migrate/add_unique_indicies.rb +17 -0
  100. data/generators/surveyor/templates/migrate/create_answers.rb +37 -0
  101. data/generators/surveyor/templates/migrate/create_dependencies.rb +22 -0
  102. data/generators/surveyor/templates/migrate/create_dependency_conditions.rb +29 -0
  103. data/generators/surveyor/templates/migrate/create_question_groups.rb +27 -0
  104. data/generators/surveyor/templates/migrate/create_questions.rb +36 -0
  105. data/generators/surveyor/templates/migrate/create_response_sets.rb +22 -0
  106. data/generators/surveyor/templates/migrate/create_responses.rb +33 -0
  107. data/generators/surveyor/templates/migrate/create_survey_sections.rb +29 -0
  108. data/generators/surveyor/templates/migrate/create_surveys.rb +31 -0
  109. data/generators/surveyor/templates/migrate/create_validation_conditions.rb +32 -0
  110. data/generators/surveyor/templates/migrate/create_validations.rb +20 -0
  111. data/generators/surveyor/templates/surveys/kitchen_sink_survey.rb +218 -0
  112. data/generators/surveyor/templates/tasks/surveyor.rb +4 -0
  113. data/generators/test_surveyor/templates/TESTING_SURVEYOR +0 -0
  114. data/generators/test_surveyor/templates/environments/cucumber.rb +21 -0
  115. data/generators/test_surveyor/test_surveyor_generator.rb +15 -0
  116. data/jakewendt-surveyor.gemspec +212 -0
  117. data/lib/fixtures_extensions.rb +6 -0
  118. data/lib/jakewendt-surveyor.rb +1 -0
  119. data/lib/surveyor.rb +44 -0
  120. data/lib/surveyor/acts_as_response.rb +33 -0
  121. data/lib/surveyor/config.rb +45 -0
  122. data/lib/tasks/surveyor_tasks.rake +33 -0
  123. data/lib/xml_formatter.rb +12 -0
  124. data/rails/init.rb +1 -0
  125. data/script/surveyor/answer.rb +54 -0
  126. data/script/surveyor/base.rb +77 -0
  127. data/script/surveyor/dependency.rb +13 -0
  128. data/script/surveyor/dependency_condition.rb +40 -0
  129. data/script/surveyor/parser.rb +207 -0
  130. data/script/surveyor/question.rb +37 -0
  131. data/script/surveyor/question_group.rb +26 -0
  132. data/script/surveyor/specs/answer_spec.rb +29 -0
  133. data/script/surveyor/specs/question_spec.rb +63 -0
  134. data/script/surveyor/specs/spec_helper.rb +7 -0
  135. data/script/surveyor/specs/survey_section_spec.rb +23 -0
  136. data/script/surveyor/specs/validation_condition_spec.rb +20 -0
  137. data/script/surveyor/specs/validation_spec.rb +20 -0
  138. data/script/surveyor/survey.rb +35 -0
  139. data/script/surveyor/survey_section.rb +21 -0
  140. data/script/surveyor/validation.rb +21 -0
  141. data/script/surveyor/validation_condition.rb +21 -0
  142. data/script/surveyor/whr_dsl.tmproj +244 -0
  143. data/spec/controllers/surveyor_controller_spec.rb +193 -0
  144. data/spec/factories.rb +145 -0
  145. data/spec/lib/surveyor_spec.rb +44 -0
  146. data/spec/models/answer_spec.rb +29 -0
  147. data/spec/models/dependency_condition_spec.rb +321 -0
  148. data/spec/models/dependency_spec.rb +81 -0
  149. data/spec/models/question_group_spec.rb +35 -0
  150. data/spec/models/question_spec.rb +75 -0
  151. data/spec/models/response_set_spec.rb +245 -0
  152. data/spec/models/response_spec.rb +76 -0
  153. data/spec/models/survey_section_spec.rb +32 -0
  154. data/spec/models/survey_spec.rb +71 -0
  155. data/spec/models/validation_condition_spec.rb +105 -0
  156. data/spec/models/validation_spec.rb +59 -0
  157. data/spec/rcov.opts +2 -0
  158. data/spec/spec.opts +4 -0
  159. data/spec/spec_helper.rb +12 -0
  160. metadata +254 -0
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ # Init hook code here
@@ -0,0 +1,54 @@
1
+ module SurveyParser
2
+ class Answer < SurveyParser::Base
3
+ # Context, Content, Reference, Display
4
+ attr_accessor :id, :parser, :question_id
5
+ attr_accessor :text, :short_text, :help_text, :weight, :response_class
6
+ attr_accessor :reference_identifier, :data_export_identifier, :common_namespace, :common_identitier
7
+ attr_accessor :display_order, :is_exclusive, :hide_label, :display_length, :custom_class, :custom_renderer
8
+ attr_accessor :validation
9
+
10
+ def default_options
11
+ { :is_exclusive => false,
12
+ :hide_label => false,
13
+ :response_class => "answer"
14
+ }
15
+ end
16
+
17
+ def parse_args(args)
18
+ case args[0]
19
+ when Hash # Hash
20
+ text_args(args[0][:text]).merge(args[0])
21
+ when String # (String, Hash) or (String, Symbol, Hash)
22
+ text_args(args[0]).merge(hash_from args[1]).merge(args[2] || {})
23
+ when Symbol # (Symbol, Hash) or (Symbol, Symbol, Hash)
24
+ symbol_args(args[0]).merge(hash_from args[1]).merge(args[2] || {})
25
+ else
26
+ text_args(nil)
27
+ end
28
+ end
29
+
30
+ def text_args(text = "Answer")
31
+ {:text => text.to_s, :short_text => text, :data_export_identifier => Surveyor.to_normalized_string(text)}
32
+ end
33
+ def hash_from(arg)
34
+ arg.is_a?(Symbol) ? {:response_class => arg.to_s} : arg.is_a?(Hash) ? arg : {}
35
+ end
36
+ def symbol_args(arg)
37
+ case arg
38
+ when :other
39
+ text_args("Other")
40
+ when :other_and_string
41
+ text_args("Other").merge({:response_class => "string"})
42
+ when :none, :omit # is_exclusive erases and disables other checkboxes and input elements
43
+ text_args(arg.to_s.humanize).merge({:is_exclusive => true})
44
+ when :integer, :date, :time, :datetime, :text, :datetime, :string
45
+ text_args(arg.to_s.humanize).merge({:response_class => arg.to_s, :hide_label => true})
46
+ end
47
+ end
48
+ def to_file
49
+ super
50
+ if self.validation then self.validation.to_file end
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,77 @@
1
+ module SurveyParser
2
+ class Base
3
+
4
+ # Class level instance variable, because class variable are shared with subclasses
5
+ class << self
6
+ attr_accessor :children
7
+ end
8
+
9
+ @children = []
10
+
11
+ # Class methods
12
+ def self.inherited(subclass)
13
+ # set the class level instance variable default on subclasses
14
+ subclass.instance_variable_set(:@children, self.instance_variable_get(:@children))
15
+ end
16
+
17
+ def self.has_children(*args)
18
+ args.each{|model| attr_accessor model}
19
+ self.instance_variable_set(:@children, args)
20
+ end
21
+
22
+ # Instance methods
23
+ def initialize(obj, args, opts)
24
+ # inherit the parser from parent (obj)
25
+ self.parser = (obj.nil? ? nil : obj.class == SurveyParser::Parser ? obj : obj.parser)
26
+ # get a new id from the parser
27
+ self.id = parser.nil? ? nil : parser.send("new_#{self.class.name.demodulize.underscore}_id")
28
+ # set [parent]_id to obj.id, if we have that attribute
29
+ self.send("#{obj.class.name.demodulize.underscore}_id=", obj.nil? ? nil : obj.id) if self.respond_to?("#{obj.class.name.demodulize.underscore}_id=")
30
+ # initialize descendant models
31
+ self.class.children.each{|model| self.send("#{model}=", [])}
32
+ # combine default options, parsed opts, parsed args, and initialize instance variables
33
+ self.default_options.merge(parse_opts(opts)).merge(parse_args(args)).each{|k,v| self.send("#{k.to_s}=", v)}
34
+ # print to the log
35
+ print "#{self.class.name.demodulize.gsub(/[a-z]/, "")[-1,1]}#{self.id} "
36
+ end
37
+ def default_options
38
+ {}
39
+ end
40
+ def parse_opts(opts)
41
+ opts.reject{|k,v| k == :method_name} # toss the method name by default
42
+ end
43
+ def parse_args(args)
44
+ args[0] || {}
45
+ end
46
+
47
+ # Filter out attributes that shouldn't be in fixtures, including children, parser, placeholders
48
+ def yml_attrs
49
+ instance_variables.sort - self.class.children.map{|model| "@#{model.to_s}"} - %w(@id @parser @dependency @validation @question_reference @answer_reference)
50
+ end
51
+ def to_yml
52
+ out = [ %(#{self.parser.salt}_#{self.class.name.demodulize.underscore}_#{@id}:) ]
53
+ yml_attrs.each{|a| out << associate_and_format(a)}
54
+ (out << nil ).join("\r\n")
55
+ end
56
+ def associate_and_format(a)
57
+ if a =~ /_id$/ # a foreign key, e.g. survey_id
58
+ " #{a[1..-4]}: " + (instance_variable_get(a).nil? ? "" : "#{self.parser.salt}_#{a[1..-4]}_#{instance_variable_get(a)}")
59
+ else # quote strings
60
+ #
61
+ # >> Regexp.new( /[0-9a-zA-z\. #]/).to_s
62
+ # => "(?-mix:[0-9a-zA-z\\. #])"
63
+ #
64
+ # The regex in kitchen sink included a space which caused the yml
65
+ # to have a space which got chopped off in the fixture load leaving
66
+ # an open ended regex which ruby did not like at all. Therefore,
67
+ # wrap Regexp in quotes as well?
68
+ #
69
+ " #{a[1..-1]}: #{(instance_variable_get(a).is_a?(String) || instance_variable_get(a).is_a?(Regexp)) ? "\"#{instance_variable_get(a)}\"" : instance_variable_get(a) }"
70
+ end
71
+ end
72
+ def to_file
73
+ File.open(self.parser.send("#{self.class.name.demodulize.underscore.pluralize}_yml"), File::CREAT|File::APPEND|File::WRONLY) {|f| f << to_yml}
74
+ self.class.children.each{|model| self.send(model).compact.map(&:to_file)}
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,13 @@
1
+ module SurveyParser
2
+ class Dependency < SurveyParser::Base
3
+ # Context, Conditional, Children
4
+ attr_accessor :id, :question_id, :question_group_id, :parser
5
+ attr_accessor :rule
6
+ has_children :dependency_conditions
7
+
8
+ def parse_opts(opts)
9
+ {} # toss the method name and reference identifier by default
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,40 @@
1
+ module SurveyParser
2
+ class DependencyCondition < SurveyParser::Base
3
+
4
+ # Context, Conditional, Value
5
+ attr_accessor :id, :dependency_id, :rule_key, :parser
6
+ attr_accessor :question_id, :operator
7
+ attr_accessor :answer_id, :datetime_value, :integer_value, :float_value, :unit, :text_value, :string_value, :response_other
8
+ attr_accessor :question_reference, :answer_reference
9
+
10
+ def default_options
11
+ { :operator => "==" }
12
+ end
13
+ def parse_args(args)
14
+ a0, a1, a2 = args
15
+ {:question_reference => a0.to_s.gsub("q_", ""), :operator => a1}.merge(a2.is_a?(Hash) ? a2 : {:answer_reference => a2.to_s.gsub("a_", "")})
16
+ end
17
+ def parse_opts(opts)
18
+ {:rule_key => opts[:reference_identifier]}
19
+ end
20
+
21
+ def reconcile_dependencies
22
+ # Looking up references to questions and answers for linking the dependency objects
23
+ print "Lookup Q ref #{@question_reference}:"
24
+ if (ref_question = parser.current_survey.find_question_by_reference(@question_reference))
25
+ print " found Q#{ref_question.id} "
26
+ @question_id = ref_question.id
27
+ print "Lookup A ref #{@answer_reference}"
28
+ if (ref_answer = ref_question.find_answer_by_reference(@answer_reference))
29
+ print " found A#{ref_answer.id} "
30
+ @answer_id = ref_answer.id
31
+ else
32
+ raise "Could not find referenced answer #{@answer_reference}"
33
+ end
34
+ else
35
+ raise "Could not find referenced question #{@question_reference}"
36
+ end
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,207 @@
1
+ require 'active_support' # for pluralize, humanize in ActiveSupport::CoreExtensions::String::Inflections
2
+ module SurveyParser
3
+ class Parser
4
+ @@models = %w(survey survey_section question_group question answer dependency dependency_condition validation validation_condition)
5
+
6
+ # Require base and all models
7
+ (%w(base) + @@models).each{|m| require File.dirname(__FILE__) + "/#{m}"}
8
+
9
+ # Attributes
10
+ attr_accessor :salt, :surveys, :grid_answers
11
+ @@models.each{|m| attr_accessor "#{m.pluralize}_yml".to_sym } # for fixtures
12
+ (@@models - %w(dependency_condition validation_condition)).each {|m| attr_accessor "current_#{m}".to_sym} # for current_model caches
13
+
14
+ # Class methods
15
+ def self.parse(file_name)
16
+ self.define_counter_methods(@@models)
17
+ puts "\n--- Parsing '#{file_name}' ---"
18
+ parser = SurveyParser::Parser.new
19
+ parser.instance_eval(File.read(file_name))
20
+ parser.to_files
21
+ puts "--- End of parsing ---\n\n"
22
+ end
23
+
24
+ # new_survey_id, new_survey_section_id, etc.
25
+ def self.define_counter_methods(names)
26
+ names.each do |name|
27
+ define_method("new_#{name}_id") do
28
+ instance_variable_set("@last_#{name}_id", instance_variable_get("@last_#{name}_id") + 1)
29
+ end
30
+ end
31
+ end
32
+
33
+ # Instance methods
34
+ def initialize
35
+ self.salt = Time.now.strftime("%Y%m%d%H%M%S")
36
+ self.surveys = []
37
+ self.grid_answers = []
38
+ initialize_counters(@@models)
39
+ initialize_fixtures(@@models.map(&:pluralize), File.join(RAILS_ROOT, "surveys", "fixtures"))
40
+ end
41
+
42
+ # @last_survey_id, @last_survey_section_id, etc.
43
+ def initialize_counters(names)
44
+ names.each{|name| instance_variable_set("@last_#{name}_id", 0)}
45
+ end
46
+
47
+ # @surveys_yml, @survey_sections_yml, etc.
48
+ def initialize_fixtures(names, path)
49
+ names.each {|name| file = instance_variable_set("@#{name}_yml", "#{path}/#{name}.yml"); File.truncate(file, 0) if File.exist?(file) }
50
+ end
51
+
52
+ # This method_missing does all the heavy lifting for the DSL
53
+ def method_missing(missing_method, *args, &block)
54
+ method_name, reference_identifier = missing_method.to_s.split("_", 2)
55
+ opts = {:method_name => method_name, :reference_identifier => reference_identifier}
56
+ case method_name
57
+ when "survey"
58
+ self.current_survey = Survey.new(self, args, opts)
59
+ evaluate_the "survey", &block
60
+
61
+ when "section"
62
+ self.current_survey_section = SurveySection.new(self.current_survey, args, opts.merge({:display_order => current_survey.survey_sections.size + 1}))
63
+ evaluate_the "survey_section", &block
64
+
65
+ when "group", "g", "grid", "repeater"
66
+ self.current_question_group = QuestionGroup.new(self.current_survey_section, args, opts)
67
+ evaluate_the "question_group", &block
68
+
69
+ when "question", "q", "label", "image"
70
+ drop_the &block
71
+ self.current_question = Question.new(self.current_survey_section, args, opts.merge(:question_group_id => current_question_group ? current_question_group.id : nil))
72
+ add_grid_answers if in_a_grid?
73
+
74
+ when "dependency", "d"
75
+ drop_the &block
76
+ self.current_dependency = Dependency.new(self.current_question_group || current_question, args, opts)
77
+
78
+ when "condition", "c"
79
+ drop_the &block
80
+ raise "Error: No current dependency or validation for this condition" if self.current_dependency.nil? && self.current_validation.nil?
81
+ if self.current_dependency.nil?
82
+ self.current_validation.validation_conditions << ValidationCondition.new(self.current_validation, args, opts)
83
+ else
84
+ self.current_dependency.dependency_conditions << DependencyCondition.new(self.current_dependency, args, opts)
85
+ end
86
+
87
+ when "answer", "a"
88
+ drop_the &block
89
+ if in_a_grid?
90
+ self.grid_answers << Answer.new(nil, args, opts.merge(:display_order => grid_answers.size + 1))
91
+ else
92
+ raise "Error: No current question" if self.current_question.nil?
93
+ self.current_answer = Answer.new(self.current_question, args, opts.merge(:display_order => current_question.answers.size + 1))
94
+ end
95
+
96
+ when "validation", "v"
97
+ drop_the &block
98
+ self.current_validation = Validation.new(self.current_answer, args, opts)
99
+
100
+
101
+ # explicitly define a dependency condition
102
+ # (not really necessary as is default)
103
+ when "dependencycondition", "dcondition", "dc"
104
+ drop_the &block
105
+ raise "Error: No current dependency for this condition" if self.current_dependency.nil?
106
+ self.current_dependency.dependency_conditions << DependencyCondition.new(self.current_dependency, args, opts)
107
+
108
+ # explicitly define a validation condition
109
+ # (is necessary if want dependency AND validation on
110
+ # same question as dependency existance would try to
111
+ # make the condition a dependency condition.)
112
+ when "validationcondition", "vcondition", "vc"
113
+ drop_the &block
114
+ raise "Error: No current validation for this condition" if self.current_validation.nil?
115
+ self.current_validation.validation_conditions << ValidationCondition.new(self.current_validation, args, opts)
116
+
117
+
118
+
119
+ else
120
+ raise " ERROR: '#{missing_method}' not valid method"
121
+
122
+ end
123
+ end
124
+
125
+ def drop_the(&block)
126
+ raise "Error, I'm dropping the block like it's hot" if block_given?
127
+ end
128
+
129
+ def evaluate_the(model, &block)
130
+ raise "Error: A #{model.humanize} cannot be empty" unless block_given?
131
+ self.instance_eval(&block)
132
+ self.send("clear_current", model)
133
+ end
134
+
135
+ def clear_current(model)
136
+ # puts "clear_current #{model}"
137
+ case model
138
+ when "survey"
139
+ self.current_survey.reconcile_dependencies unless current_survey.nil?
140
+ when "question_group"
141
+ self.grid_answers = []
142
+ clear_current("question")
143
+ when "question"
144
+ @current_dependency = nil
145
+ when "answer"
146
+ @current_validation = nil
147
+ end
148
+ instance_variable_set("@current_#{model}", nil)
149
+ "SurveyParser::#{model.classify}".constantize.send(:children).each{|m| clear_current(m.to_s.singularize)}
150
+ end
151
+
152
+ def current_survey=(s)
153
+ clear_current "survey"
154
+ self.surveys << s
155
+ @current_survey = s
156
+ end
157
+ def current_survey_section=(s)
158
+ clear_current "survey_section"
159
+ self.current_survey.survey_sections << s
160
+ @current_survey_section = s
161
+ end
162
+ def current_question_group=(g)
163
+ clear_current "question_group"
164
+ self.current_survey_section.question_groups << g
165
+ @current_question_group = g
166
+ end
167
+ def current_question=(q)
168
+ clear_current "question"
169
+ self.current_survey_section.questions << q
170
+ @current_question = q
171
+ end
172
+ def current_dependency=(d)
173
+ raise "Error: No question or question group" unless (dependent = self.current_question_group || self.current_question)
174
+ dependent.dependency = d
175
+ @current_dependency = d
176
+ end
177
+ def current_answer=(a)
178
+ raise "Error: No current question" if self.current_question.nil?
179
+ self.current_question.answers << a
180
+ @current_answer = a
181
+ end
182
+ def current_validation=(v)
183
+ clear_current "validation"
184
+ self.current_answer.validation = v
185
+ @current_validation = v
186
+ end
187
+
188
+ def in_a_grid?
189
+ self.current_question_group and self.current_question_group.display_type == "grid"
190
+ end
191
+
192
+ def add_grid_answers
193
+ self.grid_answers.each do |grid_answer|
194
+ my_answer = grid_answer.dup
195
+ my_answer.id = new_answer_id
196
+ my_answer.question_id = self.current_question.id
197
+ my_answer.parser = self
198
+ self.current_answer = my_answer
199
+ end
200
+ end
201
+
202
+ def to_files
203
+ self.surveys.compact.map(&:to_file)
204
+ end
205
+
206
+ end
207
+ end
@@ -0,0 +1,37 @@
1
+ module SurveyParser
2
+ class Question < SurveyParser::Base
3
+ # Context, Content, Reference, Display, Children
4
+ attr_accessor :id, :parser, :survey_section_id, :question_group_id
5
+ attr_accessor :text, :short_text, :help_text, :pick
6
+ attr_accessor :reference_identifier, :data_export_identifier, :common_namespace, :common_identifier
7
+ attr_accessor :display_order, :display_type, :is_mandatory, :display_width, :custom_class, :custom_renderer
8
+ attr_accessor :dependency
9
+ attr_accessor :number
10
+ has_children :answers
11
+
12
+ def default_options
13
+ { :pick => :none,
14
+ :display_type => :default,
15
+ :is_mandatory => true,
16
+ :display_order => self.id
17
+ }
18
+ end
19
+ def parse_opts(opts)
20
+ (name = opts.delete(:method_name)) =~ /label|image/ ? opts.merge(:display_type => name) : opts
21
+ end
22
+ def parse_args(args)
23
+ text = args[0] || "Question"
24
+ {:text => text, :short_text => text, :data_export_identifier => Surveyor.to_normalized_string(text)}.merge(args[1] || {})
25
+ end
26
+
27
+ def find_answer_by_reference(ref_id)
28
+ self.answers.detect{|a| a.reference_identifier == ref_id}
29
+ end
30
+
31
+ def to_file
32
+ super
33
+ if self.dependency then self.dependency.to_file end
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,26 @@
1
+ module SurveyParser
2
+ class QuestionGroup < SurveyParser::Base
3
+ # Context, Content, Display, Children
4
+ attr_accessor :id, :parser
5
+ attr_accessor :text, :help_text
6
+ attr_accessor :reference_identifier, :data_export_identifier, :common_namespace, :common_identitier
7
+ attr_accessor :display_type, :custom_class, :custom_renderer
8
+ attr_accessor :dependency
9
+
10
+ def default_options
11
+ {:display_type => "default"}
12
+ end
13
+ def parse_args(args)
14
+ {:text => args[0] || "Question Group"}.merge(args[1] || {})
15
+ end
16
+ def parse_opts(opts)
17
+ (name = opts.delete(:method_name)) =~ /grid|repeater/ ? opts.merge(:display_type => name) : opts
18
+ end
19
+
20
+ def to_file
21
+ super
22
+ if self.dependency then self.dependency.to_file end
23
+ end
24
+
25
+ end
26
+ end