class Greeve::BaseItem

An abstract class used to map XML responses from the EVE XML API into Ruby objects. This class is designed to be subclassed by classes representing the specific EVE API resources.

Public Class Methods

attribute(name, opts = {}) click to toggle source

A DSL method to map an XML attribute to a Ruby object.

@param name [Symbol] the Ruby name for this attribute

@option opts [Symbol] :xpath the xpath string used to locate the attribute

in the XML element

@option opts [:integer, :numeric, :string] :type method used to coerce the

XML value

@example

attribute :character_id, xpath: "characterID/?[0]", type: :integer
# File lib/greeve/base_item.rb, line 31
def self.attribute(name, opts = {})
  @attributes ||= {}

  add_attribute(name, opts)
  define_attribute_method(:class, name, opts)
end
endpoint(path) click to toggle source

A DSL method to specify the API endpoint.

@param path [String] path of the API endpoint. It shouldn't include the

leading slash `/`, or the extension `.xml.aspx`

@example

endpoint "eve/CharacterInfo"
# File lib/greeve/base_item.rb, line 106
def self.endpoint(path)
  raise ArgumentError, "Endpoint shouldn't start with a slash" \
    if path.start_with?("/")

  @endpoint = path
end
namespace(name, opts = {}, &block) click to toggle source

A DSL method to nest a set of attributes within a namespace.

@param name [Symbol] the Ruby name for this namespace

@option opts [Symbol] :xpath the xpath string used to locate the namespace

in the XML element

@example

namespace :general_settings, xpath: "eveapi/result/generalSettings" do
  attribute :usage_flags, xpath: "usageFlags/?[0]", type: :integer
end
# File lib/greeve/base_item.rb, line 49
def self.namespace(name, opts = {}, &block)
  @attributes ||= {}

  opts[:type] = :namespace

  add_attribute(name, opts)
  define_namespace_method(:class, name, opts, &block)
end
new(opts = {}) click to toggle source

@abstract Subclass and use the DSL methods to map API endpoints to objects

@option opts [String, Fixnum] :key API key @option opts [String] :vcode API vCode @option opts [Hash<String, String>] :query_params a hash of HTTP query

params that specify how a value maps to the API request

@example

super(query_params: {
  "characterID" => character_id,
})
# File lib/greeve/base_item.rb, line 124
def initialize(opts = {})
  raise TypeError, "Cannot instantiate an abstract class" \
    if self.class.superclass != Greeve::BaseItem

  @api_key = opts[:key]
  @api_vcode = opts[:vcode]
  @query_params = opts[:query_params] || {}

  if @api_key && @api_vcode
    @query_params.merge!({
      "keyID" => @api_key,
      "vCode" => @api_vcode,
    })
  end

  refresh
end
rowset(name, opts = {}, &block) click to toggle source

A DSL method to map an XML rowset to a Ruby object.

@param name [Symbol] the Ruby name for this attribute

@option opts [Symbol] :xpath the xpath string used to locate the attribute

in the XML element

@example

rowset :employment_history, xpath: "eveapi/result/rowset[@name='employmentHistory']" do
  attribute :record_id,        xpath: "@recordID",        type: :integer
  attribute :corporation_id,   xpath: "@corporationID",   type: :integer
  attribute :corporation_name, xpath: "@corporationName", type: :string
  attribute :start_date,       xpath: "@startDate",       type: :datetime
end
# File lib/greeve/base_item.rb, line 72
def self.rowset(name, opts = {}, &block)
  @attributes ||= {}

  opts[:type] = :rowset

  add_attribute(name, opts)

  define_method(name) do
    ivar = instance_variable_get(:"@#{name}")
    return ivar unless ivar.nil?

    # Since Ox doesn't support the xpath [@k='v'] syntax, parse it out
    # with a regex (captures :path, :attr, :attr_value).
    attr_regex = %r{\A(?<path>.*?)\[@(?<attr>\w+)=['"](?<attr_value>\w+)['"]\]\z}
    match = opts[:xpath].match(attr_regex)

    rowset_element =
      @xml_element
        .locate(match[:path])
        .find { |e| e.attributes[match[:attr].to_sym] == match[:attr_value] }

    rowset = Rowset.new(name, rowset_element, &block)

    instance_variable_set(:"@#{name}", rowset)
  end
end

Public Instance Methods

cache_expired?() click to toggle source

@return true if the API cache timer has expired and this object can

be refreshed
# File lib/greeve/base_item.rb, line 155
def cache_expired?
  !(cached_until && cached_until > Time.now)
end
cached_until() click to toggle source

@return [Time, nil] time when the cache expires and the resource can be

refreshed (sends an HTTP request)
# File lib/greeve/base_item.rb, line 161
def cached_until
  return unless @xml_element

  _cached_until = @xml_element.locate("eveapi/cachedUntil/?[0]").first
  _cached_until ? Time.parse(_cached_until + " UTC") : nil
end
refresh() click to toggle source

Query the API, refreshing this object's data.

@return true if the endpoint was fetched (HTTP request sent), false if

the cache hasn't expired
# File lib/greeve/base_item.rb, line 146
def refresh
  return false unless cache_expired?

  fetch
  true
end