require File.dirname(__FILE__) + '/question_group' require File.dirname(__FILE__) + '/question' require File.dirname(__FILE__) + '/answer' require File.dirname(__FILE__) + '/dependency' require File.dirname(__FILE__) + '/dependency_condition' require File.dirname(__FILE__) + '/columnizer' require 'activesupport' #require 'activesupport/lib/active_support/core_ext/string/inflections' class SurveySection include Columnizer # Context, Content, Display, Reference, Children, Placeholders attr_accessor :id, :survey_id, :parser attr_accessor :title, :description attr_accessor :display_order attr_accessor :reference_identifier, :data_export_identifier attr_accessor :question_groups, :questions, :grid_answers attr_accessor :current_question_group, :current_question, :current_dependency # id, survey, and title required def initialize(id, survey, title, options = {}) self.id = id self.survey_id = survey.id self.parser = survey.parser self.title = title.strip self.questions = [] self.question_groups = [] self.grid_answers = [] self.current_question_group = nil self.current_question = nil self.current_dependency = nil self.default_options(title).merge(options).each{|key,value| self.instance_variable_set("@#{key}", value)} end def default_options(title) { :data_export_identifier => Columnizer.to_normalized_column(title) } end # This method_missing magic does all the heavy lifting for the DSL def method_missing(missing_method, *args, &block) method_name, reference_identifier = missing_method.to_s.split("_") case method_name when "group", "g", "grid", "repeater" puts " Group: #{reference_identifier}" raise "Error: A question group cannot be empty" unless block_given? options = {:reference_identifier => reference_identifier, :display_type => (method_name =~ /grid|repeater/)? method_name : nil } self.question_groups << (self.current_question_group = QuestionGroup.new(self, args, options)) self.instance_eval(&block) clear_current_question_group when "question", "q", "label", "image" puts " Question: #{reference_identifier}" raise "Error: I'm dropping the block like it's hot" if block_given? clear_current_question options = {:reference_identifier => reference_identifier, :question_group_id => (current_question_group ? current_question_group.id : nil)} options.merge!({:display_type => "label"}) if method_name == "label" options.merge!({:display_type => "image"}) if method_name == "image" self.questions << (self.current_question = Question.new(self, args, options)) add_grid_answers if self.current_question_group and self.current_question_group.display_type == "grid" when "dependency", "d" puts " Dependency: #{reference_identifier}" raise "Error: I'm dropping the block like it's hot" if block_given? raise "Error: " unless self.current_question options = {:reference_identifier => reference_identifier} self.current_question.dependency = (self.current_dependency = Dependency.new(current_question, args, options)) when "condition", "c" puts " Condition: #{reference_identifier}" raise "Error, I'm dropping the block like it's hot" if block_given? raise "Error: No current dependency" unless self.current_dependency options = {:reference_identifier => reference_identifier} self.current_dependency.add_dependency_condition DependencyCondition.new(self, args, options) when "answer", "a" puts " Answer: #{reference_identifier}" raise "Error, I'm dropping the block like it's hot" if block_given? if self.current_question_group and self.current_question_group.display_type == "grid" options = {:reference_identifier => reference_identifier, :display_order => self.grid_answers.size + 1} self.grid_answers << Answer.new(nil, args, options) else raise "Error: No current question" unless self.current_question options = {:reference_identifier => reference_identifier, :display_order => self.current_question.answers.size + 1} self.current_question.answers << Answer.new(self.current_question, args, options) end else raise " ERROR: '#{m_name}' not valid method_missing name" end end def clear_current_question_group self.current_question_group = nil self.grid_answers = [] self.current_question = nil end def clear_current_question self.current_question = nil self.current_dependency = nil end def add_grid_answers self.grid_answers.each do |grid_answer| my_answer = grid_answer.dup my_answer.id = self.parser.new_answer_id my_answer.question_id = self.current_question.id my_answer.parser = self.parser self.current_question.answers << my_answer end end # Used to find questions for dependency linking def find_question_by_reference(ref_id) question = nil count = 0 while question.nil? and count < questions.size question = self.questions[count] if self.questions[count].reference_identifier == ref_id count +=1 end question end def to_yml out =[ %(#{@data_export_identifier}_#{@id}:) ] out << %( id: #{@id}) out << %( survey_id: #{@survey_id}) out << %( title: "#{@title}") out << %( description: "#{@description}") out << %( display_order: #{display_order}) out << %( reference_identifier: #{@reference_identifier}) out << %( data_export_identifier: "#{@data_export_identifier}") (out << nil ).join("\r\n") end def to_file File.open(self.parser.survey_sections_yml, File::CREAT|File::APPEND|File::WRONLY) {|f| f << to_yml} self.question_groups.compact.map(&:to_file) self.questions.compact.map(&:to_file) end end