Class: JSS::AdvancedSearch

Inherits:
APIObject show all
Includes:
Creatable, Criteriable, Updatable
Defined in:
lib/jss.rb,
lib/jss/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].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = {}) ⇒ AdvancedSearch

Returns a new instance of AdvancedSearch.



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/jss/api_object/advanced_search.rb', line 124

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 ||= []
  @result_display_keys = if @search_results.empty?
                           []
                         else
                           @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
end

Instance Attribute Details

#criteriaJSS::Criteriable::Criteria Originally defined in module Criteriable

Returns the criteria for the instance into which we’re mixed.

Returns:

#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



233
234
235
# File 'lib/jss/api_object/advanced_search.rb', line 233

def display_fields
  @display_fields
end

#need_to_updateBoolean (readonly) Originally defined in module Updatable

Returns do we have unsaved changes?.

Returns:

  • (Boolean)

    do we have unsaved changes?

#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:



110
111
112
# File 'lib/jss/api_object/advanced_search.rb', line 110

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



82
83
84
# File 'lib/jss/api_object/advanced_search.rb', line 82

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



113
114
115
# File 'lib/jss/api_object/advanced_search.rb', line 113

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



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

def sql_text
  @sql_text
end

Instance Method Details

#clone(new_name) ⇒ APIObject Originally defined in module Creatable

make a clone of this API object, with a new name. The class must be creatable

Parameters:

  • name (String)

    the name for the new object

Returns:

  • (APIObject)

    An uncreated clone of this APIObject with the given name

Raises:

#countInteger

Returns the number of items found by the search.

Returns:

  • (Integer)

    the number of items found by the search



249
250
251
# File 'lib/jss/api_object/advanced_search.rb', line 249

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:



166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/jss/api_object/advanced_search.rb', line 166

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

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

  @id # remember to return the id
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:



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/jss/api_object/advanced_search.rb', line 268

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.tr(' ', '_')).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

  out
end

#name=(newname) ⇒ void Originally defined in module Updatable

This method returns an undefined value.

Change the name of this item Remember to #update to push changes to the server.

Parameters:

  • newname (String)

    the new name

Raises:

#parse_criteriavoid Originally defined in module Criteriable

This method returns an undefined value.

During initialization, convert the @init_data Hash into a JSS::Criteriable::Criteria instance stored in @criteria

Classes mixing in this module must call this in #initialize

#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:



203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/jss/api_object/advanced_search.rb', line 203

def requery_search_results
  orig_open_timeout = JSS.api_connection.cnx.options[:open_timeout]
  orig_timeout = JSS.api_connection.cnx.options[:timeout]
  JSS.api_connection.timeout = 1800
  JSS.api_connection.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_connection.timeout = orig_timeout
    JSS.api_connection.open_timeout = orig_open_timeout
  end
end

#should_updatevoid Originally defined in module Criteriable

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Allow our Criteria to tell us when there’s been a change that needs to be updated.

#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



187
188
189
190
191
192
193
194
195
# File 'lib/jss/api_object/advanced_search.rb', line 187

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

  @id # remember to return the id
end