class Twingly::LiveFeed::Parser

Public Instance Methods

parse(document) click to toggle source

Parse an API response body.

@param [String] document containing an API response XML. @raise [Error] which error depends on the API response (see {Error.from_api_response}). @return [Result] containing the result.

# File lib/twingly/livefeed/parser.rb, line 13
def parse(document)
  nokogiri = Nokogiri::XML(document)

  failure = nokogiri.at_xpath('/error')
  handle_failure(failure) if failure

  data_node = nokogiri.at_xpath('/twinglydata')
  handle_non_xml_document(document) unless data_node

  create_result(data_node)
end

Private Instance Methods

create_result(data_node) click to toggle source
# File lib/twingly/livefeed/parser.rb, line 27
def create_result(data_node)
  result = Result.new
  result.ts                  = parse_time(data_node.attribute('ts').value)
  result.from                = parse_time(data_node.attribute('from').value)
  result.number_of_posts     = data_node.attribute('numberOfPosts').value.to_i
  result.max_number_of_posts = data_node.attribute('maxNumberOfPosts').value.to_i
  result.next_timestamp      = parse_time(data_node.attribute('nextTimestamp').value)

  unless result.number_of_posts.zero?
    result.first_post = parse_time(data_node.attribute('firstPost').value)
    result.last_post  = parse_time(data_node.attribute('lastPost').value)
  end

  data_node.xpath('//post').each do |post|
    result.posts << parse_post(post)
  end

  result
end
handle_failure(failure) click to toggle source
# File lib/twingly/livefeed/parser.rb, line 83
def handle_failure(failure)
  code    = failure.attribute('code').value
  message = failure.at_xpath('message').text

  fail Error.from_api_response(code, message)
end
handle_non_xml_document(document) click to toggle source
# File lib/twingly/livefeed/parser.rb, line 90
def handle_non_xml_document(document)
  fail ServerError, "Failed to parse response: \"#{document}\""
end
parse_array(element) click to toggle source
# File lib/twingly/livefeed/parser.rb, line 67
def parse_array(element)
  element.element_children.map do |child|
    child.text
  end
end
parse_coordinates(element) click to toggle source

TODO: Decide if a class or hash should be used…

# File lib/twingly/livefeed/parser.rb, line 74
def parse_coordinates(element)
  return {} if element.children.empty?

  {
    latitude:  element.at_xpath("latitude/text()"),
    longitude: element.at_xpath("longitude/text()"),
  }
end
parse_post(element) click to toggle source
# File lib/twingly/livefeed/parser.rb, line 47
def parse_post(element)
  post_params = {}
  element.element_children.each do |child|
    name = child.name.freeze
    post_params[name] =
      case name
      when "tags", "links", "images"
        parse_array(child)
      when "coordinates"
        parse_coordinates(child)
      else
        child.text
      end
  end

  post = Post.new
  post.set_values(post_params)
  post
end
parse_time(time) click to toggle source
# File lib/twingly/livefeed/parser.rb, line 94
def parse_time(time)
  Time.parse(time)
end