lib/ultron/models/entities.rb
module Ultron
class Entities
include Enumerable
def self.method_missing method_name, *args
mname = method_name.to_s
query = nil
path = self.name_for_path
mname.split(/_and_/).each do |part|
case part
when 'get'
true # just so this method actually exists
when 'sample'
true
when 'find'
path = '%s/%s' % [path, args.shift]
when /by_(.*)/
path = self.send(:by_something, $1, args.shift)
when 'with', 'where'
query = self.send(:by_params, args.shift)
when 'vanilla_comics'
query = self.send(:by_params, format: 'comic', formatType: 'comic', noVariants: true)
else
raise NoMethodError
end
end
url = get_url path, query
response = self.response url
set = self.new response['data'], url
return set.sample if mname == 'sample'
mname == 'find' ? set.first : set
end
def self.response url
response = Ultron::Connection.perform url
case response['code'].to_s
when /^4/, /^5/
raise MarvelException.new response
when 'ResourceNotFound'
raise UltronException.new 'Resource does not exist. Check %s' % Config.instance.config.api_docs
when 'RequestThrottled'
raise UltronException.new 'You have exceeded your rate limit. Please try again later'
end
raise UltronException.new 'The search returned no results' unless response['data']['results'].any?
response
end
def self.by_something something, id
[something.pluralize, id, self.name_for_path].join '/'
end
def self.by_params params
params.map { |k, v| '%s=%s&' % [k, v] }.join
end
def self.get_url path, query = nil
Ultron::URL.new path, query
end
def self.name_for_path
self.name.split('::')[-1].downcase
end
# instance methods
attr_reader :metadata, :url
def initialize data, url
@results_set = data['results']
@metadata = OpenStruct.new data
@url = url
end
def [] key
OpenStruct.new @results_set[key]
end
def each
@results_set.each do |item|
yield OpenStruct.new item
end
end
def random_offset
Random.rand @metadata.total
end
def sample
sample_params = 'offset=%d&limit=1&' % random_offset
full_url = self.class.get_url @url.path, '%s%s' % [@url.query, sample_params]
response = Ultron::Connection.perform full_url
self.class.new(response['data'], full_url).first
end
def == other
other.url == @url
end
end
end