Class: JSS::AdvancedSearch

Inherits:
APIObject show all
Includes:
Creatable, Criteriable, Sitable, 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

%i[csv tab xml].freeze
SITE_SUBSET =

Where is site data located in the API JSON?

:top

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = {}) ⇒ AdvancedSearch

Returns a new instance of AdvancedSearch.



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
154
155
156
157
# File 'lib/jss/api_object/advanced_search.rb', line 128

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



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

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:



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

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



86
87
88
# File 'lib/jss/api_object/advanced_search.rb', line 86

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



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

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



120
121
122
# File 'lib/jss/api_object/advanced_search.rb', line 120

def sql_text
  @sql_text
end

Instance Method Details

#clone(new_name, api: nil) ⇒ 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

  • api (JSS::APIConnection) (defaults to: nil)

    the API in which to create the object Defaults to the API used to instantiate this 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



265
266
267
# File 'lib/jss/api_object/advanced_search.rb', line 265

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:



170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/jss/api_object/advanced_search.rb', line 170

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 = @api.cnx.options[:timeout]
  @api.timeout = 1800
  super()
  requery_search_results if get_results
  @api.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:



284
285
286
287
288
289
290
291
292
293
294
295
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
# File 'lib/jss/api_object/advanced_search.rb', line 284

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:



219
220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/jss/api_object/advanced_search.rb', line 219

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

#save(get_results = false) ⇒ Object

Wrapper/alias for both create and update



202
203
204
205
206
207
208
209
210
# File 'lib/jss/api_object/advanced_search.rb', line 202

def save(get_results = false)
  if @in_jss
    raise JSS::UnsupportedError, 'Updating this object in the JSS is currently not supported by ruby-jss' unless updatable?
    update get_results
  else
    raise JSS::UnsupportedError, 'Creating this object in the JSS is currently not supported by ruby-jss' unless creatable?
    create get_results
  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.

#site=(new_site) ⇒ void Originally defined in module Sitable

This method returns an undefined value.

Change the site of this object. Any of the NON_SITES values will unset the site

Parameters:

  • new_site (Integer, String)

    The new site

Raises:

#site_assigned?Boolean Originally defined in module Sitable

Does this object have a site assigned?

Returns:

  • (Boolean)

    Does this object have a site assigned?

#site_idInteger Originally defined in module Sitable

The id of the site for this object.

Returns:

  • (Integer)

    The id of the site for this object.

#site_nameString Also known as: site Originally defined in module Sitable

The name of the site for this object. For backward compatibility, this is aliased to just ‘site’

Returns:

  • (String)

    The name of the site for this object.

#site_objectJSS::Site Originally defined in module Sitable

The JSS::Site instance for this object’s site

Returns:

  • (JSS::Site)

    The JSS::Site instance for this object’s site

#unset_sitevoid Originally defined in module Sitable

This method returns an undefined value.

Set the site to nothing

#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



191
192
193
194
195
196
197
198
199
# File 'lib/jss/api_object/advanced_search.rb', line 191

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

  @id # remember to return the id
end