Class: SoftLayer::ObjectFilter

Inherits:
Hash
  • Object
show all
Defined in:
lib/softlayer/ObjectFilter.rb

Overview

An ObjectFilter is a tool that, when passed to the SoftLayer API allows the API server to filter, or limit the result set for a call.

Constructing ObjectFilters is an art that is currently somewhat arcane. This class tries to simplify filtering for the fundamental cases, while still allowing for more complex ObjectFilters to be created.

The ObjectFilter class is implemented as a hash that, when asked to provide an value for an unknown key, will create a sub element at that key which is, itself, an object filter. This allows you to build up object filters by chaining [] dereference operations.

Starting empty object filter when you ask for object_filter either the value at that hash location will be returned, or a new foo key will be added to the object. The value of that key will be an ObjectFilter and that ObjectFilter will be returned.

By way of an example of chaining together [] calls:

object_filter["foo"]["bar"]["baz"] = 3

yields an object filter like this:

{"foo" => { "bar" => {"baz" => 3}}}

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Hash

#_to_sl_object_mask_property, #to_sl_object_mask

Constructor Details

#initializeObjectFilter

The default initialize for a hash is overridden so that object filters create sub-filters when asked for missing keys.



160
161
162
163
164
# File 'lib/softlayer/ObjectFilter.rb', line 160

def initialize
  super do |hash, key|
    hash[key] = ObjectFilter.new
  end
end

Class Method Details

.build(key_path, query = nil, &block) ⇒ Object

Builds an object filter with the given key path, a dot separated list of property keys. The filter itself can be provided as a query string (in the query parameter) or by providing a block that calls routines in the ObjectFilterBlockHandler class.

Raises:

  • (ArgumentError)


169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/softlayer/ObjectFilter.rb', line 169

def self.build(key_path, query = nil, &block)
  raise ArgumentError, "The key path to build cannot be empty" if !key_path

  # Split the keypath into its constituent parts and notify the user
  # if there are no parts
  keys = key_path.split('.')
  raise ArgumentError, "The key path to build cannot be empty" if keys.empty?

  # This will be the result of the build
  result = ObjectFilter.new

  # chase down the key path to the last-but-one key
  current_level = result
  while keys.count > 1
    current_level = current_level[keys.shift]
  end

  # if there is a block, then the query will come from
  # calling the block. We warn in debug mode if you override a
  # query that was passed directly with the value from a block.
  if block
    $stderr.puts "The query from the block passed to ObjectFilter:build will override the query passed as a parameter" if $DEBUG && query
    block_handler = ObjectFilterBlockHandler.new
    query = block_handler.instance_eval(&block)
  end

  # If we have a query, we assign its value to the last key
  # otherwise, we build an emtpy filter at the bottom
  if query
    case
    when query.kind_of?(Numeric)
      current_level[keys.shift] = { 'operation' => query }
    when query.kind_of?(SoftLayer::ObjectFilterOperation)
      current_level[keys.shift] = query.to_h
    when query.kind_of?(String)
      current_level[keys.shift] = query_to_filter_operation(query)
    when query.kind_of?(Hash)
      current_level[keys.shift] = query
    else
      current_level[keys.shift]
    end
  else
    current_level[keys.shift]
  end

  result
end

.query_to_filter_operation(query) ⇒ Object

This method simplifies creating correct object filter structures by defining a simple query language. It translates strings in that language into an Object Filter operations

Object Filter comparisons are done using operators. Some operators make case sensitive comparisons and some do not. The general form of an Object Filter operation is an operator follwed by the value used in the comparison. e.g.

"*= smaug"

The query language also accepts some aliases using asterisks in a regular-expression-like way. Those aliases look like:

'value'   Exact value match (translates to '_= value')
'value*'  Begins with value (translates to '^= value')
'*value'  Ends with value (translates to '$= value')
'*value*' Contains value (translates to '*= value')

This method corresponds to the query_filter method in the SoftLayer-Python API.



237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/softlayer/ObjectFilter.rb', line 237

def self.query_to_filter_operation(query)
  if query.kind_of? String then
    query.strip!

    begin
      return { 'operation' => Integer(query) }
    rescue
    end

    operator = OBJECT_FILTER_OPERATORS.find do | operator_string |
      query[0 ... operator_string.length] == operator_string
    end

    if operator then
      operation = "#{operator} #{query[operator.length..-1].strip}"
    else
      case query
      when /\A\*(.*)\*\Z/
        operation = "*= #{$1}"
      when /\A\*(.*)/
        operation = "$= #{$1}"
      when /\A(.*)\*\Z/
        operation = "^= #{$1}"
      else
        operation = "_= #{query}"
      end #case
    end #if
  else
    operation = query.to_i
  end # query is string

  { 'operation' => operation }
end