class NetSuite::Support::SearchResult

Attributes

current_page[R]
response[RW]
total_pages[R]
total_records[R]

Public Class Methods

new(response, result_class, credentials) click to toggle source

<platformCore:searchResult xmlns:platformCore=“urn:core_2012_1.platform.webservices.netsuite.com”>

<platformCore:status isSuccess="true"/>
<platformCore:totalRecords>2770</platformCore:totalRecords>
<platformCore:pageSize>5</platformCore:pageSize>
<platformCore:totalPages>554</platformCore:totalPages>
<platformCore:pageIndex>1</platformCore:pageIndex>
<platformCore:searchId>WEBSERVICES_738944_SB2_03012013650784545962753432_28d96bd280</platformCore:searchId>
# File lib/netsuite/support/search_result.rb, line 20
def initialize(response, result_class, credentials)
  @result_class = result_class
  @response = response
  @credentials = credentials

  @total_records = response.body[:total_records].to_i
  @total_pages = response.body[:total_pages].to_i
  @current_page = response.body[:page_index].to_i

  if @total_records > 0
    if response.body.has_key?(:record_list)
      # basic search results

      #  `recordList` node can contain several nested `record` nodes, only one node or be empty
      #  so we have to handle all these cases:
      #    * { record_list: nil }
      #    * { record_list: { record: => {...} } }
      #    * { record_list: { record: => [{...}, {...}, ...] } }
      record_list = if response.body[:record_list].nil?
        []
      elsif response.body[:record_list][:record].is_a?(Array)
        response.body[:record_list][:record]
      else
        [response.body[:record_list][:record]]
      end

      record_list.each do |record|
        results << result_class.new(record)
      end
    elsif response.body.has_key? :search_row_list
      # advanced search results
      record_list = response.body[:search_row_list][:search_row]
      record_list = [record_list] unless record_list.is_a?(Array)

      record_list.each do |record|
        record.each_pair do |search_group, search_data|
          # skip all attributes: look for :basic and all :xxx_join
          next if search_group.to_s.start_with?('@')

          record[search_group].each_pair do |k, v|
            # all return values are wrapped in a <SearchValue/>
            # extract the value from <SearchValue/> to make results easier to work with

            if k == :custom_field_list
              # Here's an example of a response

              # <platformCommon:customFieldList>
              #   <platformCore:customField internalId="1756" scriptId="custitem_stringfield" xsi:type="platformCore:SearchColumnStringCustomField">
              #     <platformCore:searchValue>sample string value</platformCore:searchValue>
              #   </platformCore:customField>
              #   <platformCore:customField internalId="1713" scriptId="custitem_apcategoryforsales" xsi:type="platformCore:SearchColumnSelectCustomField">
              #     <platformCore:searchValue internalId="4" typeId="464"/>
              #   </platformCore:customField>
              # </platformCommon:customFieldList>

              custom_field_list = v.fetch(:custom_field)
              custom_field_list = [custom_field_list] unless custom_field_list.is_a?(Array)
              record[search_group][k][:custom_field] = custom_field_list.map do |custom_field|
                custom_field[:value] = custom_field.fetch(:search_value)
                custom_field
              end
            elsif v.is_a?(Hash) && v.has_key?(:search_value)
              # Here's an example of a record ref and string response

              # <platformCommon:entity>
              #   <platformCore:searchValue internalId="446515"/>
              # </platformCommon:entity>
              # <platformCommon:status>
              #   <platformCore:searchValue>open</platformCore:searchValue>
              # </platformCommon:status>

              # in both cases, header-level field's value should be set to the
              # child `searchValue` result: if it's a record ref, the internalId
              # attribute will be transitioned to the parent, and in the case
              # of a string response the parent node's value will be to the string

              record[search_group][k] = v[:search_value]
            else
              # NOTE need to understand this case more, in testing, only the namespace definition hits this condition
            end
          end
        end

        if record[:basic][:internal_id]
          record[:basic][:internal_id] = record[:basic][:internal_id][:@internal_id]
        end

        if record[:basic][:external_id]
          record[:basic][:external_id] = record[:basic][:external_id][:@external_id]
        end

        result_wrapper = result_class.new(record.delete(:basic))
        result_wrapper.search_joins = record
        results << result_wrapper
      end
    else
      raise "uncaught search result"
    end
  end
end

Public Instance Methods

results() click to toggle source
# File lib/netsuite/support/search_result.rb, line 121
def results
  @results ||= []
end
results_in_batches() { |results| ... } click to toggle source
# File lib/netsuite/support/search_result.rb, line 125
def results_in_batches
  return if self.total_records.zero?

  while @response.body[:total_pages] != @response.body[:page_index]
    yield results

    next_search = @result_class.search(
      {
        search_id: @response.body[:search_id],
        page_index: @response.body[:page_index].to_i + 1
      },
      @credentials
    )

    @results = next_search.results
    @response = next_search.response
    @current_page = response.body[:page_index].to_i
  end

  yield results
end