Class: Dependency

Inherits:
ActiveRecord::Base
  • Object
show all
Includes:
Surveyor::Models::DependencyMethods
Defined in:
lib/surveyor/parser.rb,
app/models/dependency.rb,
lib/surveyor/unparser.rb,
lib/surveyor/redcap_parser.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Surveyor::Models::DependencyMethods

#conditions_hash, included, #is_met?, #question_group_id=, #question_id=

Class Method Details

.build_and_set(context, r) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/surveyor/redcap_parser.rb', line 100

def self.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)
    context[:dependency] = context[:question].build_dependency(:rule => hash[:rule])
    hash[:components].each do |component|
      context[:dependency].dependency_conditions.build(decompose_component(component).merge(:lookup_reference => context[:lookup], :rule_key => letters.shift))
    end
    print "dependency(#{hash[:rule]}) "
  end
end

.decompose_component(str) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/surveyor/redcap_parser.rb', line 112

def self.decompose_component(str)
   # [initial_52] = "1"
  if match = str.match(/^\[(\w+)\] ?([!=><]+) ?"(\w+)"$/)
    {:question_reference => match[1], :operator => match[2].gsub(/^=$/, "=="), :answer_reference => match[3]}
  # [initial_119(2)] = "1"
  elsif match = str.match(/^\[(\w+)\((\w+)\)\] ?([!=><]+) ?"1"$/)
    {:question_reference => match[1], :operator => match[3].gsub(/^=$/, "=="), :answer_reference => match[2]}
  # [f1_q15] >= 21
  elsif match = str.match(/^\[(\w+)\] ?([!=><]+) ?(\d+)$/)
    {:question_reference => match[1], :operator => match[2].gsub(/^=$/, "=="), :integer_value => match[3]}
  # uhoh
  else
    puts "\n!!! skipping dependency_condition #{str}"
  end
end

.decompose_rule(str) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/surveyor/redcap_parser.rb', line 127

def self.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

.parse_and_build(context, args, original_method, reference_identifier) ⇒ Object

nonblock



166
167
168
169
170
171
172
173
174
175
176
# File 'lib/surveyor/parser.rb', line 166

def self.parse_and_build(context, args, original_method, reference_identifier)
  # clear context
  context.delete_if{|k,v| %w(dependency dependency_condition).map(&:to_sym).include? k}
  
  # build and set context
  if context[:question]
    context[:dependency] = context[:question].build_dependency(args[0] || {})
  elsif context[:question_group]
    context[:dependency] = context[:question_group].build_dependency(args[0] || {})
  end
end

Instance Method Details

#unparse(dsl) ⇒ Object

nonblock



84
85
86
87
88
89
90
# File 'lib/surveyor/unparser.rb', line 84

def unparse(dsl)
  attrs = (self.attributes.diff Dependency.new.attributes).delete_if{|k,v| %w(created_at updated_at id question_id).include?(k) }.symbolize_keys!
  dsl << "  " if question.part_of_group?
  dsl << "    dependency"
  dsl << (attrs.blank? ? "\n" : " #{attrs.inspect.gsub(/\{|\}/, "")}\n")
  dependency_conditions.each{|dependency_condition| dependency_condition.unparse(dsl)}
end