class ZendeskAPI::Collection

Represents a collection of resources. Lazily loaded, resources aren’t actually fetched until explicitly needed (e.g. each, {#fetch}).

Constants

SPECIALLY_JOINED_PARAMS

Options passed in that are automatically converted from an array to a comma-separated list.

Attributes

association[R]

@return [ZendeskAPI::Association] The class association

error[R]

@return [ZendeskAPI::ClientError] The last response error

options[R]

@return [Hash] query options

response[R]

@return [Faraday::Response] The last response

Public Class Methods

new(client, resource, options = {}) click to toggle source

Creates a new Collection instance. Does not fetch resources. Additional options are: verb (default: GET), path (default: resource param), page, per_page. @param [Client] client The {Client} to use. @param [String] resource The resource being collected. @param [Hash] options Any additional options to be passed in.

# File lib/zendesk_api/collection.rb, line 30
def initialize(client, resource, options = {})
  @client, @resource_class, @resource = client, resource, resource.resource_name
  @options = SilentMash.new(options)

  set_association_from_options
  join_special_params

  @verb = @options.delete(:verb)
  @includes = Array(@options.delete(:include))

  # Used for Attachments, TicketComment
  if @resource_class.is_a?(Class) && @resource_class.superclass == ZendeskAPI::Data
    @resources = []
    @fetchable = false
  else
    @fetchable = true
  end
end

Public Instance Methods

<<(item) click to toggle source

Adds an item to this collection @option item [ZendeskAPI::Data] the resource to add @raise [ArgumentError] if the resource doesn’t belong in this collection

# File lib/zendesk_api/collection.rb, line 161
def <<(item)
  fetch

  if item.is_a?(Resource)
    if item.is_a?(@resource_class)
      @resources << item
    else
      raise "this collection is for #{@resource_class}"
    end
  else
    @resources << wrap_resource(item, true)
  end
end
all(start_page = @options["page"], &block) click to toggle source

Calls each on every page with the passed in block @param [Block] block Passed to each

# File lib/zendesk_api/collection.rb, line 221
def all(start_page = @options["page"], &block)
  _all(start_page, &block)
end
all!(start_page = @options["page"], &block) click to toggle source

Calls each on every page with the passed in block @param [Block] block Passed to each

# File lib/zendesk_api/collection.rb, line 215
def all!(start_page = @options["page"], &block)
  _all(start_page, :bang, &block)
end
build(opts = {}) click to toggle source

Convenience method to build a new resource and add it to the collection. Fetches the collection as well. @param [Hash] opts Options or attributes to pass

# File lib/zendesk_api/collection.rb, line 86
def build(opts = {})
  wrap_resource(opts, true).tap do |res|
    self << res
  end
end
build!(opts = {}) click to toggle source

Convenience method to build a new resource and add it to the collection. Fetches the collection as well. @param [Hash] opts Options or attributes to pass

# File lib/zendesk_api/collection.rb, line 95
def build!(opts = {})
  wrap_resource(opts, true).tap do |res|
    fetch!

    # << does a fetch too
    self << res
  end
end
clear_cache() click to toggle source

Clears all cached resources and associated values.

# File lib/zendesk_api/collection.rb, line 276
def clear_cache
  @resources = nil
  @count = nil
  @next_page = nil
  @prev_page = nil
  @query = nil
end
count() click to toggle source

@return [Number] The total number of resources server-side (disregarding pagination).

# File lib/zendesk_api/collection.rb, line 105
def count
  fetch
  @count || -1
end
count!() click to toggle source

@return [Number] The total number of resources server-side (disregarding pagination).

# File lib/zendesk_api/collection.rb, line 111
def count!
  fetch!
  @count || -1
end
each_page(*args, &block) click to toggle source
# File lib/zendesk_api/collection.rb, line 230
def each_page(*args, &block)
  warn "ZendeskAPI::Collection#each_page is deprecated, please use ZendeskAPI::Collection#all"
  all(*args, &block)
end
each_page!(*args, &block) click to toggle source
# File lib/zendesk_api/collection.rb, line 225
def each_page!(*args, &block)
  warn "ZendeskAPI::Collection#each_page! is deprecated, please use ZendeskAPI::Collection#all!"
  all!(*args, &block)
end
fetch(*args) click to toggle source
# File lib/zendesk_api/collection.rb, line 195
def fetch(*args)
  fetch!(*args)
rescue Faraday::ClientError => e
  @error = e

  []
end
fetch!(reload = false) click to toggle source

Executes actual GET from API and loads resources into proper class. @param [Boolean] reload Whether to disregard cache

# File lib/zendesk_api/collection.rb, line 182
def fetch!(reload = false)
  if @resources && (!@fetchable || !reload)
    return @resources
  elsif association && association.options.parent && association.options.parent.new_record?
    return (@resources = [])
  end

  @response = get_response(@query || path)
  handle_response(@response.body)

  @resources
end
first_page?() click to toggle source
# File lib/zendesk_api/collection.rb, line 132
def first_page?
  !@prev_page
end
include(*sideloads) click to toggle source

Adds an item (or items) to the list of side-loaded resources to request @option sideloads [Symbol or String] The item(s) to sideload

# File lib/zendesk_api/collection.rb, line 154
def include(*sideloads)
  tap { @includes.concat(sideloads.map(&:to_s)) }
end
last_page?() click to toggle source
# File lib/zendesk_api/collection.rb, line 136
def last_page?
  !@next_page || @next_page == @query
end
method_missing(name, *args, &block) click to toggle source

Sends methods to underlying array of resources.

# File lib/zendesk_api/collection.rb, line 294
def method_missing(name, *args, &block)
  if resource_methods.include?(name)
    collection_method(name, *args, &block)
  elsif [].respond_to?(name, false)
    array_method(name, *args, &block)
  else
    next_collection(name, *args, &block)
  end
end
next() click to toggle source

Find the next page. Does one of three things:

  • If there is already a page number in the options hash, it increases it and invalidates the cache, returning the new page number.

  • If there is a next_page url cached, it executes a fetch on that url and returns the results.

  • Otherwise, returns an empty array.

# File lib/zendesk_api/collection.rb, line 247
def next
  if @options["page"]
    clear_cache
    @options["page"] += 1
  elsif @query = @next_page
    fetch(true)
  else
    clear_cache
    @resources = []
  end
end
page(number) click to toggle source

Changes the page option. Returns self, so it can be chained. No execution. @return [Collection] self

# File lib/zendesk_api/collection.rb, line 126
def page(number)
  clear_cache if number
  @options["page"] = number
  self
end
path() click to toggle source

The API path to this collection

# File lib/zendesk_api/collection.rb, line 176
def path
  @association.generate_path(:with_parent => true)
end
per_page(count) click to toggle source

Changes the per_page option. Returns self, so it can be chained. No execution. @return [Collection] self

# File lib/zendesk_api/collection.rb, line 118
def per_page(count)
  clear_cache if count
  @options["per_page"] = count
  self
end
prev() click to toggle source

Find the previous page. Does one of three things:

  • If there is already a page number in the options hash, it increases it and invalidates the cache, returning the new page number.

  • If there is a prev_page url cached, it executes a fetch on that url and returns the results.

  • Otherwise, returns an empty array.

# File lib/zendesk_api/collection.rb, line 263
def prev
  if @options["page"] && @options["page"] > 1
    clear_cache
    @options["page"] -= 1
  elsif @query = @prev_page
    fetch(true)
  else
    clear_cache
    @resources = []
  end
end
replace(collection) click to toggle source

Replaces the current (loaded or not) resources with the passed in collection @option collection [Array] The collection to replace this one with @raise [ArgumentError] if any resources passed in don’t belong in this collection

# File lib/zendesk_api/collection.rb, line 238
def replace(collection)
  raise "this collection is for #{@resource_class}" if collection.any? { |r| !r.is_a?(@resource_class) }
  @resources = collection
end
respond_to_missing?(name, include_all) click to toggle source
# File lib/zendesk_api/collection.rb, line 289
def respond_to_missing?(name, include_all)
  [].respond_to?(name, include_all)
end
save() click to toggle source

Saves all newly created resources stored in this collection. @return [Collection] self

# File lib/zendesk_api/collection.rb, line 142
def save
  _save
end
save!() click to toggle source

Saves all newly created resources stored in this collection. @return [Collection] self

# File lib/zendesk_api/collection.rb, line 148
def save!
  _save(:save!)
end
to_a() click to toggle source

Alias for fetch(false)

# File lib/zendesk_api/collection.rb, line 204
def to_a
  fetch
end
to_a!() click to toggle source

Alias for fetch!(false)

# File lib/zendesk_api/collection.rb, line 209
def to_a!
  fetch!
end
to_ary() click to toggle source

@private

# File lib/zendesk_api/collection.rb, line 285
def to_ary
  nil
end
to_param() click to toggle source
# File lib/zendesk_api/collection.rb, line 318
def to_param
  map(&:to_param)
end
to_s() click to toggle source

@private

# File lib/zendesk_api/collection.rb, line 305
def to_s
  if @resources
    @resources.inspect
  else
    inspect = []
    inspect << "options=#{@options.inspect}" if @options.any?
    inspect << "path=#{path}"
    "#{Inflection.singular(@resource)} collection [#{inspect.join(',')}]"
  end
end
Also aliased as: to_str
to_str()
Alias for: to_s

Private Instance Methods

_all(start_page = @options["page"], bang = false, &block) click to toggle source
# File lib/zendesk_api/collection.rb, line 335
def _all(start_page = @options["page"], bang = false, &block)
  raise(ArgumentError, "must pass a block") unless block

  page(start_page)
  clear_cache

  while (bang ? fetch! : fetch)
    each do |resource|
      arguments = [resource, @options["page"] || 1]

      if block.arity >= 0
        arguments = arguments.take(block.arity)
      end

      block.call(*arguments)
    end

    last_page? ? break : self.next
  end

  page(nil)
  clear_cache
end
_save(method = :save) click to toggle source
# File lib/zendesk_api/collection.rb, line 359
def _save(method = :save)
  return self unless @resources

  result = true

  @resources.map! do |item|
    if item.respond_to?(method) && !item.destroyed? && item.changed?
      result &&= item.send(method)
    end

    item
  end

  result
end
array_method(name, *args, &block) click to toggle source

Method missing

# File lib/zendesk_api/collection.rb, line 456
def array_method(name, *args, &block)
  to_a.public_send(name, *args, &block)
end
collection_method(name, *args, &block) click to toggle source
# File lib/zendesk_api/collection.rb, line 466
def collection_method(name, *args, &block)
  @resource_class.send(name, @client, *args, &block)
end
get_response(path) click to toggle source

Fetch

# File lib/zendesk_api/collection.rb, line 398
def get_response(path)
  @error = nil
  @response = @client.connection.send(@verb || "get", path) do |req|
    opts = @options.delete_if { |_, v| v.nil? }

    req.params.merge!(:include => @includes.join(",")) if @includes.any?

    if %w{put post}.include?(@verb.to_s)
      req.body = opts
    else
      req.params.merge!(opts)
    end
  end
end
handle_response(response_body) click to toggle source
# File lib/zendesk_api/collection.rb, line 413
def handle_response(response_body)
  unless response_body.is_a?(Hash)
    raise ZendeskAPI::Error::NetworkError, @response.env
  end

  body = response_body.dup
  results = body.delete(@resource_class.model_key) || body.delete("results")

  unless results
    raise ZendeskAPI::Error::ClientError, "Expected #{@resource_class.model_key} or 'results' in response keys: #{body.keys.inspect}"
  end

  @resources = results.map do |res|
    wrap_resource(res)
  end

  set_page_and_count(body)
  set_includes(@resources, @includes, body)
end
join_special_params() click to toggle source

Initialize

# File lib/zendesk_api/collection.rb, line 377
def join_special_params
  # some params use comma-joined strings instead of query-based arrays for multiple values
  @options.each do |k, v|
    if SPECIALLY_JOINED_PARAMS.include?(k.to_sym) && v.is_a?(Array)
      @options[k] = v.join(',')
    end
  end
end
next_collection(name, *args, &block) click to toggle source
# File lib/zendesk_api/collection.rb, line 460
def next_collection(name, *args, &block)
  opts = args.last.is_a?(Hash) ? args.last : {}
  opts.merge!(:collection_path => @collection_path.dup.push(name))
  self.class.new(@client, @resource_class, @options.merge(opts))
end
resource_methods() click to toggle source
# File lib/zendesk_api/collection.rb, line 470
def resource_methods
  @resource_methods ||= @resource_class.singleton_methods(false).map(&:to_sym)
end
set_association_from_options() click to toggle source
# File lib/zendesk_api/collection.rb, line 386
def set_association_from_options
  @collection_path = @options.delete(:collection_path)

  association_options = { :path => @options.delete(:path) }
  association_options[:path] ||= @collection_path.join("/") if @collection_path
  @association = @options.delete(:association) || Association.new(association_options.merge(:class => @resource_class))

  @collection_path ||= [@resource]
end
set_page_and_count(body) click to toggle source
# File lib/zendesk_api/collection.rb, line 324
def set_page_and_count(body)
  @count = (body["count"] || @resources.size).to_i
  @next_page, @prev_page = body["next_page"], body["previous_page"]

  if @next_page =~ /page=(\d+)/
    @options["page"] = $1.to_i - 1
  elsif @prev_page =~ /page=(\d+)/
    @options["page"] = $1.to_i + 1
  end
end
with_association?() click to toggle source

Two special cases, and all namespaced classes

# File lib/zendesk_api/collection.rb, line 449
def with_association?
  [Tag, Setting].include?(@resource_class) ||
    @resource_class.to_s.split("::").size > 2
end
wrap_resource(res, with_association = with_association?) click to toggle source

Simplified Associations#wrap_resource

# File lib/zendesk_api/collection.rb, line 434
def wrap_resource(res, with_association = with_association?)
  case res
  when Array
    wrap_resource(Hash[*res], with_association)
  when Hash
    res = res.merge(:association => @association) if with_association
    @resource_class.new(@client, res)
  else
    res = { :id => res }
    res.merge!(:association => @association) if with_association
    @resource_class.new(@client, res)
  end
end