Class: ComicVine::API

Inherits:
Object
  • Object
show all
Defined in:
lib/comic_vine.rb

Overview

Class-level entry point for all ComicVine API calls.

Resource methods are resolved dynamically against the API's /types/ list: plural resources (characters, volumes, ...) return a CVObjectList, singular resources (character, volume, ...) take an id and return a CVObject.

Constant Summary collapse

API_BASE_URL =
"https://comicvine.gamespot.com/api/"
TYPES_CACHE_TTL =
4 * 60 * 60
RETRYABLE_STATUS_CODES =
[420, 429, 500, 502, 503, 504].freeze
RETRYABLE_EXCEPTIONS =
[
  Net::OpenTimeout, Net::ReadTimeout, Errno::ECONNRESET, Errno::ECONNREFUSED,
  Errno::ETIMEDOUT, SocketError, EOFError, OpenSSL::SSL::SSLError
].freeze

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.keyString?

Returns your ComicVine API key (required).

Returns:

  • (String, nil)

    your ComicVine API key (required)



82
83
84
# File 'lib/comic_vine.rb', line 82

def key
  @key
end

.max_retriesInteger

Returns retries on 420/429/5xx and connection errors (default 3).

Returns:

  • (Integer)

    retries on 420/429/5xx and connection errors (default 3)



94
95
96
# File 'lib/comic_vine.rb', line 94

def max_retries
  @max_retries
end

.open_timeoutNumeric

Returns seconds to wait for the connection to open (default 10).

Returns:

  • (Numeric)

    seconds to wait for the connection to open (default 10)



88
89
90
# File 'lib/comic_vine.rb', line 88

def open_timeout
  @open_timeout
end

.read_timeoutNumeric

Returns seconds to wait for a response (default 30).

Returns:

  • (Numeric)

    seconds to wait for a response (default 30)



88
# File 'lib/comic_vine.rb', line 88

attr_accessor :open_timeout, :read_timeout

.retry_base_delayNumeric

Returns base for exponential backoff, in seconds (default 1.0).

Returns:

  • (Numeric)

    base for exponential backoff, in seconds (default 1.0)



94
# File 'lib/comic_vine.rb', line 94

attr_accessor :max_retries, :retry_base_delay

.user_agentString

The User-Agent header sent with every request.

Returns:

  • (String)

    defaults to comic_vine gem/x.y.z (Ruby/x.y.z)



101
102
103
# File 'lib/comic_vine.rb', line 101

def user_agent
  @user_agent ||= "comic_vine gem/#{ComicVine::VERSION} (Ruby/#{RUBY_VERSION})"
end

Class Method Details

.find_detail(type) ⇒ Hash?

Looks up a singular (detail) resource in the /types/ list.

Parameters:

  • type (String)

    e.g. "character"

Returns:

  • (Hash, nil)


130
131
132
# File 'lib/comic_vine.rb', line 130

def find_detail type
  types.find { |t| t['detail_resource_name'] == type }
end

.find_list(type) ⇒ Hash?

Looks up a plural (list) resource in the /types/ list.

Parameters:

  • type (String)

    e.g. "characters"

Returns:

  • (Hash, nil)


122
123
124
# File 'lib/comic_vine.rb', line 122

def find_list type
  types.find { |t| t['list_resource_name'] == type }
end

.get_details(item_type, id, opts = nil) ⇒ CVObject

Fetches a single resource by id.

Parameters:

  • item_type (String)

    singular resource name (e.g. "volume")

  • id (Integer, String)

    the resource id

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

    query options (:field_list, ...)

Returns:

Raises:

  • (CVError)

    if the type is unknown or the request fails



205
206
207
208
209
210
211
# File 'lib/comic_vine.rb', line 205

def get_details item_type, id, opts = nil
  detail = find_detail(item_type)
  raise CVError, "Unknown ComicVine resource type: #{item_type}" if detail.nil?

  resp = hit_api(build_base_url("#{item_type}/#{detail['id']}-#{id}"), build_query(opts))
  ComicVine::CVObject.new(resp['results'])
end

.get_details_by_url(url) ⇒ CVObject

Fetches a resource from its api_detail_url.

Parameters:

  • url (String)

Returns:

Raises:



218
219
220
221
# File 'lib/comic_vine.rb', line 218

def get_details_by_url url
  resp = hit_api(url)
  ComicVine::CVObject.new(resp['results'])
end

.get_list(list_type, opts = nil) ⇒ CVObjectList

Fetches a list resource.

Parameters:

  • list_type (String)

    plural resource name (e.g. "characters")

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

    query options (:limit, :offset, :filter, :sort, :field_list, ...)

Returns:

Raises:



193
194
195
196
# File 'lib/comic_vine.rb', line 193

def get_list list_type, opts = nil
  resp = hit_api(build_base_url(list_type), build_query(opts))
  ComicVine::CVObjectList.new(resp, list_type, opts || {})
end

.method_missing(method_sym, *arguments) ⇒ Object

Resolves resource methods (ComicVine::API.characters, ComicVine::API.volume 766, ...) against the /types/ list.



136
137
138
139
140
141
142
143
144
# File 'lib/comic_vine.rb', line 136

def method_missing(method_sym, *arguments, &)
  if find_list(method_sym.to_s)
    get_list method_sym.to_s, arguments.first
  elsif find_detail(method_sym.to_s)
    get_details method_sym.to_s, *arguments
  else
    super
  end
end

.reset_types_cache!void

This method returns an undefined value.

Clears the cached /types/ list (mainly useful in tests).



179
180
181
182
183
184
# File 'lib/comic_vine.rb', line 179

def reset_types_cache!
  @types_mutex.synchronize do
    @types = nil
    @last_type_check = nil
  end
end

.respond_to_missing?(method_sym, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


146
147
148
149
150
151
152
153
# File 'lib/comic_vine.rb', line 146

def respond_to_missing?(method_sym, include_private = false)
  name = method_sym.to_s
  return true if find_list(name) || find_detail(name)

  super
rescue CVError
  super
end

.search(res, query, opts = {}) ⇒ CVSearchList

Searches ComicVine.

Parameters:

  • res (String)

    resource type or types, comma-separated (e.g. "volume,issue")

  • query (String)

    the search string

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

    extra query options (:limit, :field_list, ...)

Returns:

Raises:



112
113
114
115
116
# File 'lib/comic_vine.rb', line 112

def search res, query, opts = {}
  query_opts = opts.merge(:resources => res.gsub(" ", ""), :query => query)
  resp = hit_api(build_base_url("search"), build_query(query_opts))
  ComicVine::CVSearchList.new(resp, res, query, opts)
end

.typesArray<Hash>

The cached /types/ list, fetched on first use and refreshed every TYPES_CACHE_TTL seconds.

Returns:

  • (Array<Hash>)

Raises:

  • (CVError)

    if the /types/ list cannot be fetched



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/comic_vine.rb', line 160

def types
  @types_mutex.synchronize do
    if @types.nil? || (@last_type_check + TYPES_CACHE_TTL) < Time.now
      begin
        @types = hit_api(build_base_url('types'))['results']
        @last_type_check = Time.now
      rescue CVHTTPError => e
        raise e.class.new("Could not load the ComicVine /types/ list (needed to resolve API methods): #{e.message}", e.status)
      rescue CVError => e
        raise e.class, "Could not load the ComicVine /types/ list (needed to resolve API methods): #{e.message}"
      end
    end
    @types
  end
end