Module: Aspera::RestList

Included in:
Api::AoC, Api::Faspex
Defined in:
lib/aspera/rest_list.rb

Overview

List and lookup methods for Rest To be included in classes inheriting Rest that require those methods.

Constant Summary collapse

MAX_ITEMS =

‘max`: special query parameter: max number of items for list command

'max'
MAX_PAGES =

‘pmax`: special query parameter: max number of pages for list command

'pmax'

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.lookup_entity_generic(entity:, value:, field: 'name') { ... } ⇒ Hash

Lookup entity by field and value. Extracts a single result from the list returned by the block.

Parameters:

  • entity (String)

    Type of entity to lookup (path, and by default it is also the field name in result)

  • value (String)

    Value to match against the field.

  • field (String) (defaults to: 'name')

    Field to match in the hashes (defaults to ‘name’).

Yields:

  • A mandatory block that returns an Array of Hashes.

Returns:

  • (Hash)

    The unique matching object.

Raises:



115
116
117
118
119
120
121
122
# File 'lib/aspera/rest_list.rb', line 115

def lookup_entity_generic(entity:, value:, field: 'name')
  Aspera.assert(block_given?)
  found = yield
  Aspera.assert_array_all(found, Hash)
  found = found.select{ |i| i[field].eql?(value)}
  return found.first if found.length.eql?(1)
  raise Cli::BadIdentifier.new(entity, value, field: field, count: found.length)
end

Instance Method Details

#list_entities_limit_offset_total_count(entity:, items_key: nil, query: nil) ⇒ Array<(Array<Hash>, Integer)>

Get a (full or partial) list of all entities of a given type. Using query: ‘offset` + `limit` And response `total_count`

Parameters:

  • entity (String, Symbol)

    API endpoint of entity to list

  • items_key (String) (defaults to: nil)

    Key in the result to get the list of items (Default: same as ‘entity`)

  • query (Hash, nil) (defaults to: nil)

    Additional query parameters

Returns:

  • (Array<(Array<Hash>, Integer)>)

    items, total_count



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/aspera/rest_list.rb', line 51

def list_entities_limit_offset_total_count(
  entity:,
  items_key: nil,
  query: nil
)
  entity = entity.to_s if entity.is_a?(Symbol)
  items_key = entity.split('/').last if items_key.nil?
  query = {} if query.nil?
  Aspera.assert_type(entity, String)
  Aspera.assert_type(items_key, String)
  Aspera.assert_type(query, Hash)
  Log.log.debug{"list_entities t=#{entity} k=#{items_key} q=#{query}"}
  result = []
  offset = 0
  max_items = query.delete(MAX_ITEMS)
  remain_pages = query.delete(MAX_PAGES)
  # Merge default parameters, by default 100 per page
  query = {'limit'=> PER_PAGE_DEFAULT}.merge(query)
  total_count = nil
  loop do
    query['offset'] = offset
    page_result = read(entity, query)
    Aspera.assert_type(page_result[items_key], Array)
    result.concat(page_result[items_key])
    # Reach the limit set by user ?
    if !max_items.nil? && (result.length >= max_items)
      result = result.slice(0, max_items)
      break
    end
    total_count ||= page_result['total_count']
    break if result.length >= total_count
    remain_pages -= 1 unless remain_pages.nil?
    break if remain_pages == 0
    offset += page_result[items_key].length
    RestParameters.instance.spinner_cb.call("#{result.length} / #{total_count || '?'}")
  end
  RestParameters.instance.spinner_cb.call(action: :success)
  return result, total_count
end

#lookup_entity_by_field(entity:, value:, field: 'name', items_key: nil, query: :default) ⇒ Object

Lookup an entity id from its name. Uses query ‘q` if `query` is `:default` and `field` is `name`.

Parameters:

  • entity (String)

    Type of entity to lookup, by default it is the path, and it is also the field name in result

  • value (String)

    Value to lookup

  • field (String) (defaults to: 'name')

    Field to match, by default it is ‘’name’‘

  • items_key (String) (defaults to: nil)

    Key in the result to get the list of items (override entity)

  • query (Hash) (defaults to: :default)

    Additional query parameters (Default: ‘:default`)



98
99
100
101
102
103
104
# File 'lib/aspera/rest_list.rb', line 98

def lookup_entity_by_field(entity:, value:, field: 'name', items_key: nil, query: :default)
  if query.eql?(:default)
    Aspera.assert(field.eql?('name')){'Default query is on name only'}
    query = {'q'=> value}
  end
  lookup_entity_generic(entity: entity, field: field, value: value){list_entities_limit_offset_total_count(entity: entity, items_key: items_key, query: query).first}
end

#lookup_with_q(entity, value:, field: 'name', query: {}) ⇒ Object

Query entity by general search (read with parameter ‘q`)

Parameters:

  • entity (String)

    Path of entity in API

  • value (String)

    Value of field of searched entity

  • field (String) (defaults to: 'name')

    Field of searched entity

  • query (Hash) (defaults to: {})

    Optional additional search query parameters



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/aspera/rest_list.rb', line 19

def lookup_with_q(entity, value:, field: 'name', query: {})
  Aspera.assert_type(query, Hash){'query'}
  Aspera.assert_type(field, String){'field'}
  # returns entities matching the query (it matches against several fields in case insensitive way)
  # We don't do paging, as anyway, we look for only one match
  matching_items = read(entity, query.merge({'q' => value}))
  # API style: {totalcount:, ...} cspell: disable-line: TODO: is that total_count ?
  # @type [Array<Hash{String => String}>]
  matching_items = matching_items[entity] if matching_items.is_a?(Hash)
  Aspera.assert_type(matching_items, Array)
  case matching_items.length
  when 1 then return matching_items.first
  when 0 then raise EntityNotFound, %Q{No such #{entity}: "#{value}"}
  else
    # multiple case insensitive partial matches, try case insensitive full match
    # (anyway AoC does not allow creation of 2 entities with same case insensitive field value)
    value_matches = matching_items.select{ |i| i[field].casecmp?(value)}
    case value_matches.length
    when 1 then return value_matches.first
    when 0 then raise %Q(#{entity}: Multiple case insensitive partial match for: "#{value}" in #{matching_items.map{ |i| i[field]}.join(', ')} but no case insensitive full match. Please be more specific or give exact #{field}.)
    else raise "Two entities cannot have the same case insensitive #{field}: #{value_matches.map{ |i| i[field]}}"
    end
  end
end