Class: Quby::Questionnaires::Entities::Questionnaire

Inherits:
Object
  • Object
show all
Extended by:
ActiveModel::Naming
Includes:
ActiveModel::Validations
Defined in:
lib/quby/questionnaires/entities/questionnaire.rb

Defined Under Namespace

Classes: InputKeyAlreadyDefined, UnknownInputKey, ValidationError

Constant Summary collapse

RESPONDENT_TYPES =
i( profess patient parent second_parent teacher caregiver )

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key, attributes = {}) ⇒ Questionnaire

Returns a new instance of Questionnaire.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 27

def initialize(key, attributes = {})
  @key = key
  @attributes = attributes
  @score_calculations = {}.with_indifferent_access
  @fields = Fields.new(self)
  @extra_css = ""
  @panels = []
  @flags = {}.with_indifferent_access
  @textvars = {}.with_indifferent_access
  @language = :nl
  @respondent_types = []
  @check_key_clashes = true
  @validate_html = true
  @score_schemas = {}.with_indifferent_access
  @check_score_keys_consistency = true
  @lookup_tables = {}
end

Instance Attribute Details

#abortable ⇒ Object

Returns the value of attribute abortable.



49
50
51
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 49

def abortable
  @abortable
end

#allow_hotkeys ⇒ Object



81
82
83
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 81

def allow_hotkeys
  (@allow_hotkeys || :bulk).to_s
end

#attributes ⇒ Object (readonly)

Returns the value of attribute attributes.



45
46
47
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 45

def attributes
  @attributes
end

#check_key_clashes ⇒ Object

whether to check for clashes between question input keys (HTML form keys)



60
61
62
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 60

def check_key_clashes
  @check_key_clashes
end

#check_score_keys_consistency ⇒ Object

whether to check consistency of score subkeys during seed generation



62
63
64
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 62

def check_score_keys_consistency
  @check_score_keys_consistency
end

#default_answer_value ⇒ Object

Returns the value of attribute default_answer_value.



53
54
55
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 53

def default_answer_value
  @default_answer_value
end

#enable_previous_questionnaire_button ⇒ Object

Returns the value of attribute enable_previous_questionnaire_button.



50
51
52
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 50

def enable_previous_questionnaire_button
  @enable_previous_questionnaire_button
end

#extra_css ⇒ Object

Returns the value of attribute extra_css.



56
57
58
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 56

def extra_css
  @extra_css
end

#fields ⇒ Object (readonly)

Returns the value of attribute fields.



55
56
57
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 55

def fields
  @fields
end

#flags ⇒ Object

Returns the value of attribute flags.



68
69
70
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 68

def flags
  @flags
end

#key ⇒ Object

Returns the value of attribute key.



47
48
49
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 47

def key
  @key
end

#language ⇒ Object

Returns the value of attribute language.



57
58
59
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 57

def language
  @language
end

#leave_page_alert ⇒ Object



76
77
78
79
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 76

def leave_page_alert
  return nil unless Settings.enable_leave_page_alert
  @leave_page_alert || "Als u de pagina verlaat worden uw antwoorden niet opgeslagen."
end

#lookup_tables ⇒ Object

Returns the value of attribute lookup_tables.



72
73
74
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 72

def lookup_tables
  @lookup_tables
end

#panels ⇒ Object

Returns the value of attribute panels.



51
52
53
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 51

def panels
  @panels
end

#respondent_types ⇒ Object

Returns the value of attribute respondent_types.



58
59
60
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 58

def respondent_types
  @respondent_types
end

#score_calculations ⇒ Object

Returns the value of attribute score_calculations.



52
53
54
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 52

def score_calculations
  @score_calculations
end

#score_schemas ⇒ Object

Returns the value of attribute score_schemas.



71
72
73
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 71

def score_schemas
  @score_schemas
end

#textvars ⇒ Object

Returns the value of attribute textvars.



69
70
71
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 69

def textvars
  @textvars
end

#title ⇒ Object

Returns the value of attribute title.



48
49
50
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 48

def title
  @title
end

#validate_html ⇒ Object

If false, we don't check html for validity (for mate1 and mate1_pre)



64
65
66
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 64

def validate_html
  @validate_html
end

Instance Method Details

#actions ⇒ Object



153
154
155
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 153

def actions
  score_calculations.values.select(&:action)
end

#add_panel(panel) ⇒ Object



89
90
91
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 89

def add_panel(panel)
  @panels << panel
end

#add_score_calculation(builder) ⇒ Object



133
134
135
136
137
138
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 133

def add_score_calculation(builder)
  if score_calculations.key?(builder.key)
    fail InputKeyAlreadyDefined, "Score key `#{builder.key}` already defined."
  end
  score_calculations[builder.key] = builder
end

#add_score_schema(key, label, subschema_options) ⇒ Object



140
141
142
143
144
145
146
147
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 140

def add_score_schema(key, label, subschema_options)
  schema = Entities::ScoreSchema.new(key: key, label: label, subscore_schemas: subschema_options)
  schema.valid?
  schema.errors.each do |error|
    errors.add("Score schema '#{key}'", "#{error.attribute} #{error.message}")
  end
  score_schemas[key] = schema
end

#answer_dsl_module ⇒ Object

rubocop:disable Metrics/MethodLength



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 183

def answer_dsl_module # rubocop:disable Metrics/MethodLength
  # Have to put this in a local variable so the module definition block can access it
  questions_in_var = questions

  @answer_dsl_cache ||= Module.new do
    questions_in_var.each do |question|
      next if question&.key.blank?
      case question.type
      when :date
        question.components.each do |component|
          # assignment to 'value' hash must be done under string keys
          key = question.send("#{component}_key").to_s
          define_method(key) do
            self.value ||= Hash.new
            self.value[key]
          end

          define_method("#{key}=") do |v|
            self.value ||= Hash.new
            self.value[key] = v&.strip
          end
        end

        define_method(question.key) do
          self.value ||= Hash.new

          components = question.components.sort
          component_values = components.map do |component|
            value_key = question.send("#{component}_key").to_s
            self.value[value_key]
          end
          case components
          when [:day, :month, :year]
            component_values.reverse.take_while { |p| p.present? }.reverse.join('-')
          when [:month, :year]
            component_values.reject(&:blank?).join('-')
          when [:hour, :minute]
            component_values.all?(&:blank?) ? '' : component_values.join(':')
          end
        end

      when :check_box

        define_method(question.key) do
          self.value ||= Hash.new
          self.value[question.key.to_s] ||= Hash.new
        end

        question.options.each do |opt|
          next if opt&.key.blank?
          define_method("#{opt.key}") do
            self.value ||= Hash.new
            self.value[question.key.to_s] ||= Hash.new
            self.value[opt.key.to_s] ||= 0
          end

          define_method("#{opt.key}=") do |v|
            v = v.to_i
            self.value ||= Hash.new
            self.value[question.key.to_s] ||= Hash.new
            self.value[question.key.to_s][opt.key.to_s] = v
            self.value[opt.key.to_s] = v
          end
        end
      else
        # Includes:
        # question.type == :radio
        # question.type == :scale
        # question.type == :select
        # question.type == :string
        # question.type == :textarea
        # question.type == :integer
        # question.type == :float

        define_method(question.key) do
          self.value ||= Hash.new
          self.value[question.key.to_s]
        end

        define_method(question.key.to_s + "=") do |v|
          self.value ||= Hash.new
          self.value[question.key.to_s] = v
        end
      end rescue nil
    end
  end
end

#completion ⇒ Object



157
158
159
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 157

def completion
  score_calculations.values.select(&:completion).first
end

#default_flags ⇒ Object



167
168
169
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 167

def default_flags
  flags.to_h { |key, flag| [key, flag.default] }.reject { |key, value| value.nil? }
end

#default_textvars ⇒ Object



177
178
179
180
181
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 177

def default_textvars
  textvars.select { |key, textvar| textvar.default.present? }
          .map    { |key, textvar| [key, textvar.default] }
          .to_h
end

#filter_flags(given_flags) ⇒ Object



161
162
163
164
165
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 161

def filter_flags(given_flags)
  given_flags.select do |flag_key, _|
    flags.key? flag_key
  end
end

#filter_textvars(given_textvars) ⇒ Object



171
172
173
174
175
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 171

def filter_textvars(given_textvars)
  given_textvars.select do |textvar_key, _|
    textvars.key? textvar_key
  end
end

#key_in_use?(key) ⇒ Boolean

Returns:

  • (Boolean)


129
130
131
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 129

def key_in_use?(key)
  fields.key_in_use?(key) || score_calculations.key?(key)
end

#questions ⇒ Object



121
122
123
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 121

def questions
  question_hash.values
end

#questions_of_type(type) ⇒ Object



125
126
127
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 125

def questions_of_type(type)
  questions.select { |question| question.type == type }
end

#questions_tree ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 109

def questions_tree
  return @questions_tree_cache if @questions_tree_cache

  recurse = lambda do |question|
    [question, question.subquestions.map(&recurse)]
  end

  @questions_tree_cache = (@panels && @panels.map do |panel|
    panel.items.map { |item| recurse.call(item) if item.is_a?(Quby::Questionnaires::Entities::Question) }
  end)
end

#register_question(question) ⇒ Object



93
94
95
96
97
98
99
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 93

def register_question(question)
  fields.add(question)

  if question.sets_textvar && !textvars.key?(question.sets_textvar)
    fail "Undefined textvar: #{question.sets_textvar}"
  end
end

#scores ⇒ Object



149
150
151
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 149

def scores
  score_calculations.values.select(&:score)
end

#to_param ⇒ Object



85
86
87
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 85

def to_param
  key
end

#validate_questions ⇒ Object



101
102
103
104
105
106
107
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 101

def validate_questions
  question_hash.each_value do |q|
    unless q.valid?
      q.errors.each { |attr, err| errors.add(attr, err) }
    end
  end
end

#validations ⇒ Object



271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/quby/questionnaires/entities/questionnaire.rb', line 271

def validations
  @validations ||= fields.question_hash.values.flat_map do |question|
    question.validations.map do |validation|
      case validation[:type]
      when :answer_group_minimum, :answer_group_maximum
        Validation.new(validation.merge(field_keys: questions.select {|q| q.question_group == validation[:group]}.map(&:key)))
      else
        Validation.new(validation.merge(field_key: question.key))
      end
    end
  end.uniq(&:config)
end