Module: SurveyorRedcapParserDependencyMethods

Defined in:
lib/surveyor/redcap_parser.rb

Overview

Dependency model

Instance Method Summary collapse

Instance Method Details

#build_and_set(context, r) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/surveyor/redcap_parser.rb', line 135

def build_and_set(context, r)
  unless (bl = r[:branching_logic_show_field_only_if]).blank?
    # TODO: forgot to tie rule key to component, counting on the sequence of components
    letters = ('A'..'Z').to_a
    hash = decompose_rule(bl)
    self.attributes = {:rule => hash[:rule]}
    context[:question].dependency = context[:dependency] = self
    hash[:components].each do |component|
      dc = context[:dependency].dependency_conditions.build(decompose_component(component).merge({ :rule_key => letters.shift } ))
      context[:dependency_conditions] << dc
    end
    Surveyor::RedcapParser.rake_trace "dependency(#{hash[:rule]}) "
  end
end

#decompose_component(str) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/surveyor/redcap_parser.rb', line 149

def decompose_component(str)
  # [initial_52] = "1" or [f1_q15] = '' or [f1_q15] = '-2' or [hi_event1_type] <> ''
  if match = str.match(/^\[(\w+)\] ?([!=><]+) ?['"](-?\w*)['"]$/)
    {:question_reference => match[1], :operator => match[2].gsub(/^=$/, "==").gsub(/^<>$/, "!="), :answer_reference => match[3]}
  # [initial_119(2)] = "1" or [hiprep_heat2(97)] = '1'
  elsif match = str.match(/^\[(\w+)\((\w+)\)\] ?([!=><]+) ?['"]1['"]$/)
    {:question_reference => match[1], :operator => match[3].gsub(/^=$/, "==").gsub(/^<>$/, "!="), :answer_reference => match[2]}
  # [f1_q15] >= 21 or [f1_q15] >= -21
  elsif match = str.match(/^\[(\w+)\] ?([!=><]+) ?(-?\d+)$/)
    {:question_reference => match[1], :operator => match[2].gsub(/^=$/, "==").gsub(/^<>$/, "!="), :integer_value => match[3]}
  else
    Surveyor::RedcapParser.rake_trace "\n!!! skipping dependency_condition #{str}"
  end
end

#decompose_rule(str) ⇒ Object



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/surveyor/redcap_parser.rb', line 163

def decompose_rule(str)
  # see spec/lib/redcap_parser_spec.rb for examples
  letters = ('A'..'Z').to_a
  rule = str
  components = str.split(/\band\b|\bor\b|\((?!\d)|\)(?!\(|\])/).reject(&:blank?).map(&:strip)
  components.each_with_index do |part, i|
    # internal commas on the right side of the operator e.g. '[initial_189] = "1, 2, 3"'
    if match = part.match(/^(\[[^\]]+\][^\"]+)"([0-9 ]+,[0-9 ,]+)"$/)
      nums = match[2].split(",").map(&:strip)
      components[i] = nums.map{|x| "#{match[1]}\"#{x}\""}
      # sub in rule key
      rule = rule.gsub(part, "(#{nums.map{letters.shift}.join(' and ')})")
    # multiple internal parenthesis on the left  e.g. '[initial_119(1)(2)(3)(4)(6)] = "1"'
    elsif match = part.match(/^\[(\w+)(\(\d+\)\([\d\(\)]+)\]([^\"]+"\d+")$/)
      nums = match[2].split(/\(|\)/).reject(&:blank?).map(&:strip)
      components[i] = nums.map{|x| "[#{match[1]}(#{x})]#{match[3]}"}
      # sub in rule key
      rule = rule.gsub(part, "(#{nums.map{letters.shift}.join(' and ')})")
    else
      # 'or' on the right of the operator
      components[i] = components[i-1].gsub(/"(\d+)"/, part) if part.match(/^"(\d+)"$/) && i != 0
      # sub in rule key
      rule = rule.gsub(part){letters.shift}
    end
  end
  {:rule => rule, :components => components.flatten}
end