Module: Surveyor::Models::ResponseSetMethods

Included in:
ResponseSet
Defined in:
lib/surveyor/models/response_set_methods.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/surveyor/models/response_set_methods.rb', line 6

def self.included(base)
  # Associations
  base.send :belongs_to, :survey
  base.send :belongs_to, :user
  base.send :has_many, :responses, :dependent => :destroy
  base.send :accepts_nested_attributes_for, :responses, :allow_destroy => true

  @@validations_already_included ||= nil
  unless @@validations_already_included
    # Validations
    base.send :validates_presence_of, :survey_id
    base.send :validates_associated, :responses
    base.send :validates_uniqueness_of, :access_code

    @@validations_already_included = true
  end

  # Attributes
  base.send :attr_protected, :completed_at

  # Whitelisting attributes
  base.send :attr_accessible, :survey, :responses_attributes, :user_id, :survey_id

  base.send :before_create, :ensure_start_timestamp
  base.send :before_create, :ensure_identifiers

  # Class methods
  base.instance_eval do
    def has_blank_value?(hash)
      return true if hash["answer_id"].blank?
      return false if (q = Question.find_by_id(hash["question_id"])) and q.pick == "one"
      hash.any?{|k,v| v.is_a?(Array) ? v.all?{|x| x.to_s.blank?} : v.to_s.blank?}
    end
  end
end

Instance Method Details

#all_dependencies(question_ids = nil) ⇒ Object



140
141
142
143
144
145
146
# File 'lib/surveyor/models/response_set_methods.rb', line 140

def all_dependencies(question_ids = nil)
  arr = dependencies(question_ids).partition{|d| d.is_met?(self) }
  {
    :show => arr[0].map{|d| d.question_group_id.nil? ? "q_#{d.question_id}" : "g_#{d.question_group_id}"},
    :hide => arr[1].map{|d| d.question_group_id.nil? ? "q_#{d.question_id}" : "g_#{d.question_group_id}"}
  }
end

#as_json(options = nil) ⇒ Object



72
73
74
75
# File 'lib/surveyor/models/response_set_methods.rb', line 72

def as_json(options = nil)
  template_paths = ActionController::Base.view_paths.collect(&:to_path)
  Rabl.render(self, 'surveyor/show.json', :view_path => template_paths, :format => "hash")
end

#complete!Object



77
78
79
# File 'lib/surveyor/models/response_set_methods.rb', line 77

def complete!
  self.completed_at = Time.now
end

#complete?Boolean

Returns:

  • (Boolean)


81
82
83
# File 'lib/surveyor/models/response_set_methods.rb', line 81

def complete?
  !completed_at.nil?
end

#correct?Boolean

Returns:

  • (Boolean)


85
86
87
# File 'lib/surveyor/models/response_set_methods.rb', line 85

def correct?
  responses.all?(&:correct?)
end

#correctness_hashObject



88
89
90
91
92
93
# File 'lib/surveyor/models/response_set_methods.rb', line 88

def correctness_hash
  { :questions => survey.sections_with_questions.map(&:questions).flatten.compact.size,
    :responses => responses.compact.size,
    :correct => responses.find_all(&:correct?).compact.size
  }
end

#count_group_responses(questions) ⇒ Object

Returns the number of response groups (count of group responses enterted) for this question group



118
119
120
121
122
123
124
# File 'lib/surveyor/models/response_set_methods.rb', line 118

def count_group_responses(questions)
  questions.map { |q|
    responses.select { |r|
      (r.question_id.to_i == q.id.to_i) && !r.response_group.nil?
    }.group_by(&:response_group).size
  }.max
end

#ensure_identifiersObject



46
47
48
49
# File 'lib/surveyor/models/response_set_methods.rb', line 46

def ensure_identifiers
  self.access_code ||= Surveyor::Common.make_tiny_code
  self.api_id ||= Surveyor::Common.generate_api_id
end

#ensure_start_timestampObject



42
43
44
# File 'lib/surveyor/models/response_set_methods.rb', line 42

def ensure_start_timestamp
  self.started_at ||= Time.now
end

#is_answered?(question) ⇒ Boolean

Returns:

  • (Boolean)


107
108
109
# File 'lib/surveyor/models/response_set_methods.rb', line 107

def is_answered?(question)
  %w(label image).include?(question.display_type) or !is_unanswered?(question)
end

#is_group_unanswered?(group) ⇒ Boolean

Returns:

  • (Boolean)


113
114
115
# File 'lib/surveyor/models/response_set_methods.rb', line 113

def is_group_unanswered?(group)
  group.questions.any?{|question| is_unanswered?(question)}
end

#is_unanswered?(question) ⇒ Boolean

Returns:

  • (Boolean)


110
111
112
# File 'lib/surveyor/models/response_set_methods.rb', line 110

def is_unanswered?(question)
  self.responses.detect{|r| r.question_id == question.id}.nil?
end

#mandatory_questions_complete?Boolean

Returns:

  • (Boolean)


94
95
96
# File 'lib/surveyor/models/response_set_methods.rb', line 94

def mandatory_questions_complete?
  progress_hash[:triggered_mandatory] == progress_hash[:triggered_mandatory_completed]
end

#no_responses_for_section?(section) ⇒ Boolean

Check existence of responses to questions from a given survey_section

Returns:

  • (Boolean)


149
150
151
# File 'lib/surveyor/models/response_set_methods.rb', line 149

def no_responses_for_section?(section)
  !responses.any?{|r| r.survey_section_id == section.id}
end

#progress_hashObject



97
98
99
100
101
102
103
104
105
106
# File 'lib/surveyor/models/response_set_methods.rb', line 97

def progress_hash
  qs = survey.sections_with_questions.map(&:questions).flatten
  ds = dependencies(qs.map(&:id))
  triggered = qs - ds.select{|d| !d.is_met?(self)}.map(&:question)
  { :questions => qs.compact.size,
    :triggered => triggered.compact.size,
    :triggered_mandatory => triggered.select{|q| q.mandatory?}.compact.size,
    :triggered_mandatory_completed => triggered.select{|q| q.mandatory? and is_answered?(q)}.compact.size
  }
end

#to_csv(access_code = false, print_header = true) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/surveyor/models/response_set_methods.rb', line 51

def to_csv(access_code = false, print_header = true)
  qcols = Question.content_columns.map(&:name) - %w(created_at updated_at)
  acols = Answer.content_columns.map(&:name) - %w(created_at updated_at)
  rcols = Response.content_columns.map(&:name)
  result = Surveyor::Common.csv_impl.generate do |csv|
    if print_header
      csv << (access_code ? ["response set access code"] : []) +
        qcols.map{|qcol| "question.#{qcol}"} +
        acols.map{|acol| "answer.#{acol}"} +
        rcols.map{|rcol| "response.#{rcol}"}
    end
    responses.each do |response|
      csv << (access_code ? [self.access_code] : []) +
        qcols.map{|qcol| response.question.send(qcol)} +
        acols.map{|acol| response.answer.send(acol)} +
        rcols.map{|rcol| response.send(rcol)}
    end
  end
  result
end

#unanswered_dependenciesObject



126
127
128
# File 'lib/surveyor/models/response_set_methods.rb', line 126

def unanswered_dependencies
  unanswered_question_dependencies + unanswered_question_group_dependencies
end

#unanswered_question_dependenciesObject



130
131
132
# File 'lib/surveyor/models/response_set_methods.rb', line 130

def unanswered_question_dependencies
  dependencies.select{ |d| d.question && self.is_unanswered?(d.question) && d.is_met?(self) }.map(&:question)
end

#unanswered_question_group_dependenciesObject



134
135
136
137
138
# File 'lib/surveyor/models/response_set_methods.rb', line 134

def unanswered_question_group_dependencies
  dependencies.
    select{ |d| d.question_group && self.is_group_unanswered?(d.question_group) && d.is_met?(self) }.
    map(&:question_group)
end

#update_from_ui_hash(ui_hash) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/surveyor/models/response_set_methods.rb', line 153

def update_from_ui_hash(ui_hash)
  transaction do
    ui_hash.each do |ord, response_hash|
      api_id = response_hash['api_id']
      fail "api_id missing from response #{ord}" unless api_id

      existing = Response.where(:api_id => api_id).first
      updateable_attributes = response_hash.reject { |k, v| k == 'api_id' }

      if self.class.has_blank_value?(response_hash)
        existing.destroy if existing
      elsif existing
        if existing.question_id.to_s != updateable_attributes['question_id']
          fail "Illegal attempt to change question for response #{api_id}."
        end

        existing.update_attributes(updateable_attributes)
      else
        responses.build(updateable_attributes).tap do |r|
          r.api_id = api_id
          r.save!
        end
      end

    end
  end
end