Class: SoftLayer::ObjectFilter

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

Overview

An ObjectFilter is a hash that, when asked to provide an value for an unknown key, will create a sub element at that key that is itself an object filter. So if you start with an empty object filter and ask for object_filter["foo"] then foo will be added to the object and the value of that key will be an Object Filter { "foo" => {} }

This allows you to create object filters by chaining [] calls:

object_filter["foo"]["bar"]["baz"] = 3 yields {"foo" => { "bar" => {"baz" => 3}}}

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Hash

#__sl_object_mask_properties_for_keys, #__valid_root_property_key?, #to_sl_object_mask, #to_sl_object_mask_property

Constructor Details

#initializeObjectFilter

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



122
123
124
125
126
# File 'lib/softlayer/ObjectFilter.rb', line 122

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)


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
168
169
170
171
172
173
174
175
176
177
# File 'lib/softlayer/ObjectFilter.rb', line 131

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 it's 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 tries to simplify creating a correct object filter structure by allowing the caller to provide a string in a simple query language. It then translates that string into an Object Filter operation structure

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')


197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/softlayer/ObjectFilter.rb', line 197

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