class Gillbus::Parser

Constants

DATE_FORMAT_CONST
DEFAULT_TIMEZONE
NULL_CONST
TIME_FORMAT_REGEXP
TRUE_CONST
YES_CONST

Attributes

doc[RW]
fields[RW]
instance[RW]
parent[RW]

Public Class Methods

new(instance:, doc:, fields:, parent:, options: {}) click to toggle source
# File lib/gillbus/helpers/parser.rb, line 18
def initialize(instance:, doc:, fields:, parent:, options: {})
  @instance = instance
  @doc = doc
  @fields = fields
  @parent = parent
  @options = options
end

Public Instance Methods

parse() click to toggle source
# File lib/gillbus/helpers/parser.rb, line 26
def parse
  fields.each do |name:, key:, type:, root:|
    value =
      if type == :datetime_combined
        datetime_combined(key)
      else
        raw_value = fetch_value(key: key, root: root)
        make_one_or_many(type, raw_value)
      end
    instance.send "#{name}=", value unless value.nil?
  end
  instance
end

Private Instance Methods

array(arg) click to toggle source

nil => []

> []

{} => [{}]

# File lib/gillbus/helpers/parser.rb, line 99
def array(arg)
  return [arg] if arg.is_a? Hash
  Array(arg)
end
bool(val) click to toggle source
# File lib/gillbus/helpers/parser.rb, line 111
def bool(val)
  val == TRUE_CONST
end
date(val) click to toggle source
# File lib/gillbus/helpers/parser.rb, line 123
def date(val)
  Date.strptime(val, DATE_FORMAT_CONST)
end
datetime(val) click to toggle source
# File lib/gillbus/helpers/parser.rb, line 134
def datetime(val)
  ActiveSupport::TimeZone[default_timezone].parse(val)
end
datetime_combined(key) click to toggle source
# File lib/gillbus/helpers/parser.rb, line 138
def datetime_combined(key)
  date_string = doc["#{key}_DATE"]
  time_string = doc["#{key}_TIME"]
  timezone = doc["#{key}_TIMEZONE"].presence || default_timezone
  ActiveSupport::TimeZone[timezone].parse("#{date_string} #{time_string}")
end
decimal(val) click to toggle source
# File lib/gillbus/helpers/parser.rb, line 149
def decimal(val)
  BigDecimal(val)
end
default_timezone() click to toggle source
# File lib/gillbus/helpers/parser.rb, line 145
def default_timezone
  @options[:timezone] || DEFAULT_TIMEZONE
end
ensure_array(val) click to toggle source

Нужно удостовериться, что элемент завёрнут в массив, чтобы дальше эти массивы сложить в методе fetch_value. Есть нюанс, что при сложении ['Item'] + [{'ID'=>'1'}, 'Subitem'] получается

'Item', {'ID'=>'1'}, 'Subitem'], а нам надо ['Item', [{'ID'=>'1'}, 'Subitem']

Поэтому item_with_id заворачиваем во внешний массив

# File lib/gillbus/helpers/parser.rb, line 60
def ensure_array(val)
  if is_item_with_id?(val)
    [val]
  else
    Array(val)
  end
end
fetch_value(key:, root:) click to toggle source
# File lib/gillbus/helpers/parser.rb, line 42
def fetch_value(key:, root:)
  target_doc = root ? doc[root] : doc
  return unless target_doc

  if key.is_a?(Regexp)
    target_doc.select { |k| k =~ key }
  elsif key.is_a?(Array)
    key.map { |k| ensure_array(target_doc[k]) }.inject(&:+)
  else
    target_doc[key]
  end
end
int(val) click to toggle source
# File lib/gillbus/helpers/parser.rb, line 119
def int(val)
  val.to_i
end
is_item_with_id?(val) click to toggle source

Детектит элементы вида <CRITICAL_INF ID=“1”>Text</CRITICAL_INF>, которые парсятся как [{'ID'=>'1'}, 'Text']

# File lib/gillbus/helpers/parser.rb, line 70
def is_item_with_id?(val)
  val.is_a?(Array) && val.size == 2 && val.first.is_a?(Hash) && val.first.keys == ['ID']
end
make_one(type, val) click to toggle source
# File lib/gillbus/helpers/parser.rb, line 87
def make_one(type, val)
  return if val.nil?
  if type.is_a? Class
    type.parse(val, instance: nil, parent: instance, options: @options)
  else
    send type, val
  end
end
make_one_or_many(type, val) click to toggle source
# File lib/gillbus/helpers/parser.rb, line 74
def make_one_or_many(type, val)
  # [:type]
  if type.is_a? Array
    if val.is_a?(Array) && val[0].is_a?(Hash) && !val[0].has_key?('__content__')
      val = [val] if val[1].is_a?(String) # hack to handle attribute parsing by Ox
    end
    array(val).map { |v| make_one type.first, v }
  # :type
  else
    make_one type, val
  end
end
string(val) click to toggle source
# File lib/gillbus/helpers/parser.rb, line 104
def string(val)
  return if val == NULL_CONST
  # если это тег с атрибутами - возвращаем только содержимое тега
  return val.last if val.is_a?(Array) && val.size == 2
  val
end
time(val) click to toggle source

rubocop:disable Style/GuardClause, Style/IfUnlessModifier

# File lib/gillbus/helpers/parser.rb, line 128
def time(val)
  if val =~ TIME_FORMAT_REGEXP
    $1
  end
end
yesno_bool(val) click to toggle source
# File lib/gillbus/helpers/parser.rb, line 115
def yesno_bool(val)
  val == YES_CONST
end