class BingAdsApi::ReportUtils

Constants

REPORT_DEFINITION_ORDER

Definition fields have to be in particular order in the XML. Here is its specification.

REQUIRED_FIELDS

Minimal set of required fields for report definition.

Public Class Methods

new(api, version) click to toggle source

Default constructor.

Args:

  • api: BingAdsApi object

  • version: API version to use

# File lib/bing_ads_api/report_utils.rb, line 17
def initialize(api, version)
  @api, @version = api, version
end

Public Instance Methods

download_report(report_definition, cid = nil) click to toggle source

Downloads and returns a report.

Args:

  • report_definition: definition of the report in XML text or hash

  • cid: optional customer ID to run against

Returns:

  • report body

Raises:

# File lib/bing_ads_api/report_utils.rb, line 35
def download_report(report_definition, cid = nil)
  return get_report_response(report_definition, cid).body
end
download_report_as_file(report_definition, path, cid = nil) click to toggle source

Downloads a report and saves it to a file.

Args:

  • report_definition: definition of the report in XML text or hash

  • path: path to save report to

  • cid: optional customer ID to run against

Returns:

  • nil

Raises:

# File lib/bing_ads_api/report_utils.rb, line 54
def download_report_as_file(report_definition, path, cid = nil)
  report_body = download_report(report_definition, cid)
  save_to_file(report_body, path)
  return nil
end

Private Instance Methods

add_report_definition_hash_order(node, name = :root) click to toggle source

Adds fields order hint to generator based on specification.

# File lib/bing_ads_api/report_utils.rb, line 183
def add_report_definition_hash_order(node, name = :root)
  def_order = REPORT_DEFINITION_ORDER[name]
  var_order = def_order.reject { |field| !node.include?(field) }
  node.keys.each do |key|
    if REPORT_DEFINITION_ORDER.include?(key)
      case node[key]
        when Hash
          add_report_definition_hash_order(node[key], key)
        when Array
          node[key].each do |item|
            add_report_definition_hash_order(item, key)
          end
      end
    end
  end
  node[:order!] = var_order
  return nil
end
check_for_errors(response) click to toggle source

Checks downloaded data for error signature. Raises ReportError if it detects an error.

# File lib/bing_ads_api/report_utils.rb, line 126
def check_for_errors(response)
  # Check for error in body.
  report_body = response.body
  if report_body and
      ((RUBY_VERSION < '1.9.1') or report_body.valid_encoding?)
    error_message_regex = '^!!!(-?\d+)\|\|\|(-?\d+)\|\|\|(.*)\?\?\?'
    data = report_body.slice(0, 1024)
    matches = data.match(error_message_regex)
    if matches
      message = (matches[3].nil?) ? data : matches[3]
      raise BingAdsApi::Errors::ReportError.new(response.code,
          'Report download error occured: %s' % message)
    end
  end
  # Check for error code.
  unless response.code == 200
    raise BingAdsApi::Errors::ReportError.new(response.code,
        'Report download error occured, http code: %d, body: %s' %
        [response.code, response.body])
  end
  return nil
end
check_report_definition_hash(report_definition) click to toggle source

Checks if the report definition looks correct.

# File lib/bing_ads_api/report_utils.rb, line 157
def check_report_definition_hash(report_definition)
  # Minimal set of fields required.
  REQUIRED_FIELDS.each do |field|
    unless report_definition.include?(field)
      raise BingAdsApi::Errors::InvalidReportDefinitionError,
          "Required field '%s' is missing in the definition" % field
    end
  end
  # Fields list is also required.
  unless report_definition[:selector].include?(:fields)
    raise BingAdsApi::Errors::InvalidReportDefinitionError,
        'Fields list is required'
  end
  # 'Fields' must be an Array.
  unless report_definition[:selector][:fields].kind_of?(Array)
    raise BingAdsApi::Errors::InvalidReportDefinitionError,
        'Fields list must be an array'
  end
  # We should request at least one field.
  if report_definition[:selector][:fields].empty?
    raise BingAdsApi::Errors::InvalidReportDefinitionError,
        'At least one field needs to be requested'
  end
end
get_report_definition_text(report_definition) click to toggle source

Converts passed object to XML text. Currently support String (no changes) and Hash (renders XML).

# File lib/bing_ads_api/report_utils.rb, line 92
def get_report_definition_text(report_definition)
  return case report_definition
    when String then report_definition
    when Hash then report_definition_to_xml(report_definition)
    else
      raise BingAdsApi::Errors::InvalidReportDefinitionError,
          'Unknown object for report definition: %s' %
          report_definition.class
  end
end
get_report_request_headers(url, cid) click to toggle source

Prepares headers for report request.

# File lib/bing_ads_api/report_utils.rb, line 104
def get_report_request_headers(url, cid)
  @header_handler ||= BingAdsApi::ReportHeaderHandler.new(
      @api.credential_handler, @api.get_auth_handler(), @api.config)
  return @header_handler.headers(url, cid)
end
get_report_response(report_definition, cid) click to toggle source

Send POST request for a report and returns Response object.

# File lib/bing_ads_api/report_utils.rb, line 78
def get_report_response(report_definition, cid)
  definition_text = get_report_definition_text(report_definition)
  data = '__rdxml=%s' % CGI.escape(definition_text)
  url = @api.api_config.adhoc_report_download_url(
      @api.config.read('service.environment'), @version)
  headers = get_report_request_headers(url, cid)
  log_request(url, headers, definition_text)
  response = AdsCommonForBingAds::Http.post_response(url, data, @api.config, headers)
  check_for_errors(response)
  return response
end
log_request(url, headers, body) click to toggle source

Logs the request on debug level.

# File lib/bing_ads_api/report_utils.rb, line 116
def log_request(url, headers, body)
  logger = @api.logger
  logger.debug("Report request to: '%s'" % url)
  logger.debug('HTTP headers: [%s]' %
      (headers.map { |k, v| [k, v].join(': ') }.join(', ')))
  logger.debug(body)
end
report_definition_to_xml(report_definition) click to toggle source

Renders a report definition hash into XML text.

# File lib/bing_ads_api/report_utils.rb, line 150
def report_definition_to_xml(report_definition)
  check_report_definition_hash(report_definition)
  add_report_definition_hash_order(report_definition)
  return Gyoku.xml({:report_definition => report_definition})
end
save_to_file(data, path) click to toggle source

Saves raw data to a file.

# File lib/bing_ads_api/report_utils.rb, line 111
def save_to_file(data, path)
  open(path, 'wb') { |file| file.write(data) } if path
end