Class: JSS::AdvancedSearch

Inherits:
APIObject show all
Includes:
Creatable, Criteriable, Updatable
Defined in:
lib/jss-api.rb,
lib/jss-api/api_object/advanced_search.rb

Overview

A Parent class for Advanced Computer, MobileDevice, and User searchs

Subclasses must define:

  • the constant RESULT_CLASS which is the JSS Module class of the item returned by the search, e.g. JSS::Computer

  • the constant RESULT_ID_FIELDS, which is an Array of Symbols that come from the API in the search_results along with the symbolized display fields. E.g. for AdvancedComputerSearches, :id, :name, and :udid are present along with whatever display fields have been defined.

Constant Summary collapse

EXPORT_FORMATS =

Class Constants

[:csv, :tab, :xml]

Constants included from Criteriable

Criteriable::CRITERIABLE

Constants included from Updatable

Updatable::UPDATABLE

Constants included from Creatable

Creatable::CREATABLE

Constants inherited from APIObject

JSS::APIObject::DEFAULT_LOOKUP_KEYS, JSS::APIObject::REQUIRED_DATA_KEYS

Instance Attribute Summary collapse

Attributes included from Criteriable

#criteria

Attributes included from Updatable

#need_to_update

Attributes inherited from APIObject

#id, #in_jss, #name, #rest_rsrc

Instance Method Summary collapse

Methods included from Criteriable

#parse_criteria, #should_update

Methods included from Updatable

#name=

Methods inherited from APIObject

all, all_ids, all_names, #delete, get_name, map_all_ids_to, #save, xml_list

Constructor Details

#initialize(args = {}) ⇒ AdvancedSearch

Returns a new instance of AdvancedSearch.



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/jss-api/api_object/advanced_search.rb', line 131

def initialize(args = {})

  super args

  ### @init_data now has the raw data
  ### so fill in our attributes or set defaults

  @sql_text = @init_data[:sql_text]
  @site = JSS::APIObject.get_name(@init_data[:site])



  @display_fields = @init_data[:display_fields] ? @init_data[:display_fields].map{|f| f[:name]} : []

  @search_results =  @init_data[self.class::RESULT_CLASS::RSRC_LIST_KEY]
  @search_results ||= []
  if @search_results.empty?
    @result_display_keys =[]
  else
    @result_display_keys = @search_results[0].keys - self.class::RESULT_ID_FIELDS
  end

  # make sure each hash of the search results
  # has a key matching a standard key.
  #
  @search_results.each do |hash|
    hash.keys.each do |key|
      std_key = key.to_s.gsub(/ |-/,"_").to_sym
      next if hash[std_key]
      hash[std_key] = hash[key]
    end
  end

  parse_criteria


end

Instance Attribute Details

#result_display_keysArray<Symbol> (readonly)

The search result Hash keys for the #display_fields of the search

The field names in #display_fields are strings matching how the field is labeled in the web UI (including the names of Extension Attributes). They have to be that way when submitting them to the API, and thats mostly what #display_fields and related methods are for.

However, when those names come back as the Hash Keys of the #search_results they (inconsistently) have spaces and/or dashes converted to underscores, and, the JSON module converts the keys to Symbols, so they don’t match the #display_fields.

For example, the display field “Last Check-in” might come back as any of these Symbols:

  • :“Last Check-in”

  • :Last_Check_in

  • :“Last_Check-in”

Also, the data returned in the #search_results contains more keys than just the #display_fields - namely it comes with some standard identifiers for each found item. such as JSS id number and name.

#result_display_keys will hold just the Hash keys corresponding to the #display_fields by taking the keys from the first result Hash, and removing the identifier keys as listed in each subclass’s RESULT_ID_FIELDS constant.

Returns:



116
117
118
# File 'lib/jss-api/api_object/advanced_search.rb', line 116

def result_display_keys
  @result_display_keys
end

#search_resultsArray<Hash> (readonly)

Each Hash is one object that matches the criteria. Within each hash there are variable keys, but always at least the keys defined in each subclasses RESULT_ID_FIELDS

The other keys correspond to the #display_fields defined for this Advanced Search.

Returns:

  • (Array<Hash>)

    the results of the search



88
89
90
# File 'lib/jss-api/api_object/advanced_search.rb', line 88

def search_results
  @search_results
end

#siteString (readonly)

Returns the name of the site for this search.

Returns:

  • (String)

    the name of the site for this search



119
120
121
# File 'lib/jss-api/api_object/advanced_search.rb', line 119

def site
  @site
end

#sql_textString (readonly)

Returns the SQL query generated by the JSS based on the critera.

Returns:

  • (String)

    the SQL query generated by the JSS based on the critera



122
123
124
# File 'lib/jss-api/api_object/advanced_search.rb', line 122

def sql_text
  @sql_text
end

Instance Method Details

#countInteger

Returns the number of items found by the search.

Returns:

  • (Integer)

    the number of items found by the search



276
277
278
# File 'lib/jss-api/api_object/advanced_search.rb', line 276

def count
  @search_results.count
end

#create(get_results = false) ⇒ Integer

Create in the JSS

If get_results is true, they’ll be available in #search_results. This might be slow.

Parameters:

  • get_results (Boolean) (defaults to: false)

    should the results of the search be queried immediately?

Returns:

  • (Integer)

    the id of the newly created search

Raises:



182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/jss-api/api_object/advanced_search.rb', line 182

def create(get_results = false)
  raise JSS::InvalidDataError, "JSS::Criteriable::Criteria instance required" unless @criteria.kind_of? JSS::Criteriable::Criteria
  raise JSS::InvalidDataError, "display_fields must be an Array." unless @display_fields.kind_of? Array

  orig_timeout = JSS::API.cnx.options[:timeout]
  JSS::API.timeout = 1800
  super()
  requery_search_results if get_results
  JSS::API.timeout = orig_timeout

  @id # remember to return the id

end

#display_fieldsArray<String>

The API delivers these as an array of Hashes, where each hash has only one key, :name => the name of the fields/ExtAttrib to display. It should probably not have the underlying Hashes, and just be an array of names. This class converts it to just an Array of field names (Strings) for internal use.

These fields are returned in the @search_results data along with :id, :name, and other unique identifiers for each found item. In that data, their names have spaces and dashes converted to underscores, and they are symbolized.

Returns:

  • (Array<String>)

    the fields to be returned with the search results



254
255
256
# File 'lib/jss-api/api_object/advanced_search.rb', line 254

def display_fields
  @display_fields
end

#display_fields=(new_val) ⇒ Object

Set the list of fields to be retrieved with the search results.

Parameters:

Raises:



264
265
266
267
268
269
# File 'lib/jss-api/api_object/advanced_search.rb', line 264

def display_fields= (new_val)
  raise JSS::InvalidDataError, "display_fields must be an Array." unless new_val.kind_of? Array
  return if new_val.sort == @display_fields.sort
  @display_fields = new_val
  @need_to_update = true
end

#export(output_file, format = :csv, overwrite = false) ⇒ Pathname

Note:

This method only exports the display fields defined in this advanced search for

Export the display fields of the search results to a file.

the search_result members (computers, mobile_devices, or users) It doesn’t currently provide the ability to export subsets of info about those objects, as the Web UI does (e.g. group memberships, applications, receipts, etc)

Parameters:

  • output_file (String, Pathname)

    The file in which to store the exported results

  • format (Symbol) (defaults to: :csv)

    one of :csv, :tab, or :xml, defaults to :csv

  • overwrite (Boolean) (defaults to: false)

    should the output_file be overwrite if it exists? Defaults to false

Returns:

  • (Pathname)

    the path to the output file

Raises:



296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
# File 'lib/jss-api/api_object/advanced_search.rb', line 296

def export(output_file, format = :csv, overwrite = false)

  raise JSS::InvalidDataError, "Export format must be one of: :#{EXPORT_FORMATS.join ', :'}" unless EXPORT_FORMATS.include? format

  out = Pathname.new output_file

  unless overwrite
    raise JSS::AlreadyExistsError, "The output file already exists: #{out}" if out.exist?
  end


  case format
    when :csv
      require 'csv'
      CSV.open(out.to_s, 'wb') do |csv|
        csv << @result_display_keys
        @search_results.each do |row|
          csv << @result_display_keys.map {|key| row[key]}
        end # each do row
      end #CSV.open

    when :tab
      tabbed = @result_display_keys.join("\t") + "\n"
      @search_results.each do |row|
        tabbed << @result_display_keys.map {|key| row[key]}.join("\t") + "\n"
      end # each do row
      out.jss_save tabbed.chomp

    else # :xml
      doc = REXML::Document.new '<?xml version="1.0" encoding="ISO-8859-1"?>'
      members = doc.add_element self.class::RESULT_CLASS::RSRC_LIST_KEY.to_s
      @search_results.each do |row|
        member = members.add_element self.class::RESULT_CLASS::RSRC_OBJECT_KEY.to_s
        @result_display_keys.each do |field|
          member.add_element(field.to_s.gsub(' ',"_")).text = row[field].empty? ? nil : row[field]
        end # ech do field
      end #each do row
      out.jss_save doc.to_s.gsub('><', ">\n<")
  end # case

  return out
end

#requery_search_resultsArray<Hash>

Requery the API for the search results.

This can be very slow, so temporarily reset the API timeout to 30 minutes

Returns:



223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/jss-api/api_object/advanced_search.rb', line 223

def requery_search_results
  orig_open_timeout = JSS::API.cnx.options[:open_timeout]
  orig_timeout = JSS::API.cnx.options[:timeout]
  JSS::API.timeout = 1800
  JSS::API.open_timeout = 1800
  begin
    requery = self.class.new(:id => @id)
    @search_results = requery.search_results
    @result_display_keys = requery.result_display_keys
  ensure
    JSS::API.timeout = orig_timeout
    JSS::API.open_timeout = orig_open_timeout
  end
end

#update(get_results = false) ⇒ Integer

Save any changes

If get_results is true, they’ll be available in #search_results. This might be slow.

Parameters:

  • get_results (Boolean) (defaults to: false)

    should the results of the search be queried immediately?

Returns:

  • (Integer)

    the id of the updated search



205
206
207
208
209
210
211
212
213
# File 'lib/jss-api/api_object/advanced_search.rb', line 205

def update(get_results = false)
  orig_timeout = JSS::API.cnx.options[:timeout]
  JSS::API.timeout = 1800
  super()
  requery_search_results if get_results
  JSS::API.timeout = orig_timeout

  @id  # remember to return the id
end