class TrackerApi::Client

Constants

CONVENIENCE_HEADERS

Header keys that can be passed in options hash to {#get},{#paginate}

USER_AGENT

Attributes

api_version[R]
auto_paginate[R]
connection[R]
last_response[R]
logger[R]
token[R]
url[R]

Public Class Methods

new(options={}, &block) click to toggle source

Create Pivotal Tracker API client.

@param [Hash] options the connection options @option options [String] :token API token to use for requests @option options [String] :url Main HTTP API root @option options [Boolean] :auto_paginate Client should perform pagination automatically. Default true. @option options [String] :api_version The API version URL path @option options [String] :logger Custom logger @option options [String] :adapter Custom http adapter to configure Faraday with @option options [String] :connection_options Connection options to pass to Faraday

@example Creating a Client

Client.new token: 'my-super-special-token'
# File lib/tracker_api/client.rb, line 23
def initialize(options={}, &block)
  url                = options.fetch(:url, 'https://www.pivotaltracker.com')
  @url               = Addressable::URI.parse(url).to_s
  @api_version       = options.fetch(:api_version, '/services/v5')
  @logger            = options.fetch(:logger, ::Logger.new(nil))
  adapter            = options.fetch(:adapter) { defined?(JRUBY_VERSION) ? :net_http : :excon }
  connection_options = options.fetch(:connection_options, { ssl: { verify: true } })
  @auto_paginate     = options.fetch(:auto_paginate, true)
  @token             = options[:token]
  raise 'Missing required options: :token' unless @token

  @faraday_block = block if block_given?

  @connection = Faraday.new({ url: @url }.merge(connection_options)) do |builder|
    # response
    builder.use Faraday::Response::RaiseError
    builder.response :json, content_type: /\bjson/ # e.g., 'application/json; charset=utf-8'

    # request
    builder.request :multipart
    builder.request :json

    builder.use TrackerApi::Logger, @logger
    @faraday_block.call(builder) if @faraday_block
    builder.adapter adapter
  end
end

Public Instance Methods

activity(params={}) click to toggle source

Provides a list of all the activity performed the authenticated person.

@param [Hash] params @return [Array]

# File lib/tracker_api/client.rb, line 177
def activity(params={})
  Endpoints::Activity.new(self).get(params)
end
create_workspace(params) click to toggle source

Create a new workspace.

@param [Hash] params attributes to create the workspace with @return [TrackerApi::Resources::Workspace] newly created Workspace

# File lib/tracker_api/client.rb, line 119
def create_workspace(params)
  Endpoints::Workspace.new(self).create(params)
end
epic(epic_id, params={}) click to toggle source

Get information about an epic without knowing what project the epic belongs to

@param [String] epic_id @param [Hash] params @return [TrackerApi::Resources::Epic]

# File lib/tracker_api/client.rb, line 161
def epic(epic_id, params={})
  Endpoints::Epic.new(self).get_epic(epic_id, params)
end
me() click to toggle source

Get information about the authenticated user

@return [TrackerApi::Resources::Me]

# File lib/tracker_api/client.rb, line 143
def me
  Endpoints::Me.new(self).get
end
notifications(params={}) click to toggle source

Get notifications for the authenticated person

@param [Hash] params @return [Array]

# File lib/tracker_api/client.rb, line 169
def notifications(params={})
  Endpoints::Notifications.new(self).get(params)
end
paginate(path, options = {}) { |data, last_response| ... } click to toggle source

Make one or more HTTP GET requests, optionally fetching the next page of results from information passed back in headers based on value in {#auto_paginate}.

@param path [String] The path, relative to {#api_endpoint} @param options [Hash] Query and header params for request @param block [Block] Block to perform the data concatenation of the

multiple requests. The block is called with two parameters, the first
contains the contents of the requests so far and the second parameter
contains the latest response.

@return [Array]

# File lib/tracker_api/client.rb, line 73
def paginate(path, options = {}, &block)
  opts           = parse_query_and_convenience_headers path, options.dup
  auto_paginate  = opts[:params].delete(:auto_paginate) { |k| @auto_paginate }
  @last_response = request :get, opts
  data           = @last_response.body
  raise TrackerApi::Errors::UnexpectedData, 'Array expected' unless data.is_a? Array

  if auto_paginate
    pager = Pagination.new @last_response.headers

    while pager.more?
      opts[:params].update(pager.next_page_params)

      @last_response = request :get, opts
      pager          = Pagination.new @last_response.headers
      if block_given?
        yield(data, @last_response)
      else
        data.concat(@last_response.body) if @last_response.body.is_a?(Array)
      end
    end
  end

  data
end
project(id, params={}) click to toggle source

Get project

@param [Hash] params @return [TrackerApi::Resources::Project]

# File lib/tracker_api/client.rb, line 111
def project(id, params={})
  Endpoints::Project.new(self).get(id, params)
end
projects(params={}) click to toggle source

Get projects

@param [Hash] params @return [Array]

# File lib/tracker_api/client.rb, line 103
def projects(params={})
  Endpoints::Projects.new(self).get(params)
end
story(story_id, params={}) click to toggle source

Get information about a client story without knowing what project the story belongs to

@param [String] story_id @param [Hash] params @return [TrackerApi::Resources::Story]

# File lib/tracker_api/client.rb, line 152
def story(story_id, params={})
  Endpoints::Story.new(self).get_story(story_id, params)
end
workspace(id, params={}) click to toggle source

Get workspace

@param [Hash] params @return [TrackerApi::Resources::Workspace]

# File lib/tracker_api/client.rb, line 127
def workspace(id, params={})
  Endpoints::Workspace.new(self).get(id, params)
end
workspaces(params={}) click to toggle source

Get workspaces

@param [Hash] params @return [Array]

# File lib/tracker_api/client.rb, line 135
def workspaces(params={})
  Endpoints::Workspaces.new(self).get(params)
end

Private Instance Methods

parse_query_and_convenience_headers(path, options) click to toggle source
# File lib/tracker_api/client.rb, line 183
def parse_query_and_convenience_headers(path, options)
  raise 'Path can not be blank.' if path.to_s.empty?

  opts = { body: options[:body] }

  opts[:url]    = options[:url] || File.join(@url, @api_version, path.to_s)
  opts[:method] = options[:method] || :get
  opts[:params] = options[:params] || {}
  opts[:token]  = options[:token] || @token
  headers       = { 'User-Agent'     => USER_AGENT,
                    'X-TrackerToken' => opts.fetch(:token),
                    'Accept' => 'application/json' }.merge(options.fetch(:headers, {}))

  CONVENIENCE_HEADERS.each do |h|
    if header = options[h]
      headers[h] = header
    end
  end
  opts[:headers] = headers

  opts
end
request(method, options = {}) click to toggle source
# File lib/tracker_api/client.rb, line 206
def request(method, options = {})
  url     = options.fetch(:url)
  params  = options[:params] || {}
  body    = options[:body]
  headers = options[:headers]

  if (method == :post || method == :put) && options[:body].blank?
    body                    = MultiJson.dump(params)
    headers['Content-Type'] = 'application/json'

    params = {}
  end

  @last_response = response = connection.send(method) do |req|
    req.url(url)
    req.headers.merge!(headers)
    req.params.merge!(params)
    req.body = body
  end
  response
rescue Faraday::ClientError, Faraday::ServerError => e
  status_code = e.response[:status]
  case status_code
  when 400..499 then raise TrackerApi::Errors::ClientError.new(e)
  when 500..599 then raise TrackerApi::Errors::ServerError.new(e)
  else raise "Expected 4xx or 5xx HTTP status code; got #{status_code} instead."
  end
end