module GreenButtonData::Fetchable::ClassMethods

Public Instance Methods

all(url = nil, options = nil) click to toggle source

Returns all entries

Arguments

  • url (OPTIONAL) - URL to fetch from. If not supplied, it defaults to

    the URLs in configuration.
  • options - Options hash

# File lib/green-button-data/fetchable.rb, line 21
def all(url = nil, options = nil)
  if url.is_a?(Hash)
    # Assume it is an options Hash
    options = url
    url = nil
  end

  url ||= url_path_prefix url_options(options)

  @url = url
  @options = options
  return populate_models(fetch(url, options))
end
feed() click to toggle source
# File lib/green-button-data/fetchable.rb, line 113
def feed
  if !options[:reload] && @feed
    @feed
  else
    @feed = fetch url, options
  end
end
fetch(url = nil, options = nil) click to toggle source
# File lib/green-button-data/fetchable.rb, line 83
def fetch(url = nil, options = nil)
  url or raise ArgumentError.new "url is required to fetch data"

  connection_options = {}

  options ||= {}
  connection_options[:ssl] = options[:ssl] if options[:ssl]

  conn = Faraday.new connection_options do |connection|
    connection.response :logger
    connection.adapter Faraday.default_adapter
  end
  conn.authorization :Bearer, options[:token] if options[:token]

  response = conn.get do |req|
    req.url url
    req.params = build_query_params options
  end

  if response.status == 200
    GreenButtonData::Feed.parse response.body
  elsif response.status == 401
    raise "Unauthorized API call; check authorization token and try again"
  elsif response.status == 500
    raise "500 Server Error:\n#{response.body}"
  else
    raise "Status: #{response.status}"
  end
end
find(id = nil, options = nil) click to toggle source

Finds an entry that matches the {id} in the URL of the form: services.greenbuttondata.org/DataCustodian/espi/1_1/resource/{model_name}/{id}

Arguments

  • id - ID of the entry content. URL matching a single entry content

    can be supplied in place of ID.
  • url (OPTIONAL) - If specified, this URL is used to fetch data in

    place of global configuration.
  • options - Options hash

Examples

The following fetches data identically.

ReadingType.find(1, token: “12345678-1024-2048-abcdef001234”) # use global config ReadingType.find(“services.greenbuttondata.org/DataCustodian/espi/1_1/resource/ReadingType/1”, token: “12345678-1024-2048-abcdef001234”) # override global config and use specific url

# File lib/green-button-data/fetchable.rb, line 66
def find(id = nil, options = nil)
  # If +id+ argument is a URL, set the url
  url = if id =~ /\A#{URI::regexp}\z/
    id
  else
    path_prefix = url_path_prefix url_options(options)

    URI.join(path_prefix, "#{id}/").to_s
  end

  return populate_models(fetch(url, options)).first
end
first(url = nil, options = nil) click to toggle source

Returns the first item in the ModelCollection from all entries returned by the API endpoint

Arguments

  • url (OPTIONAL) - URL to fetch from. If not supplied, it defaults to

    the URLs in configuration.
  • options - Options hash

# File lib/green-button-data/fetchable.rb, line 44
def first(url = nil, options = nil)
  return all(url, options).first
end
last(url = nil, options = nil) click to toggle source
# File lib/green-button-data/fetchable.rb, line 79
def last(url = nil, options = nil)
  return all(url, options).last
end
options() click to toggle source
# File lib/green-button-data/fetchable.rb, line 129
def options
  @options
end
records() click to toggle source
# File lib/green-button-data/fetchable.rb, line 121
def records
  if !options[:reload] && @records
    @records
  else
    @records = populate_models(feed)
  end
end
url() click to toggle source
# File lib/green-button-data/fetchable.rb, line 133
def url
  @url
end

Private Instance Methods

build_query_params(options) click to toggle source
# File lib/green-button-data/fetchable.rb, line 245
def build_query_params(options)
  params = {}

  options.each do |key, value|
    if key == :published_min || key == :published_max
      if value.respond_to? :to_time
        value = value.to_time.to_i
      end
    end

    unless key == :ssl || key == :token || key == :subscription_id
      params[key.to_s.dasherize] = value
    end
  end

  return params
end
class_name() click to toggle source
# File lib/green-button-data/fetchable.rb, line 139
def class_name
  self.name.split('::').last
end
each_entry_content(feed) { |id, entry_content, entry, usage_point_id| ... } click to toggle source
# File lib/green-button-data/fetchable.rb, line 211
def each_entry_content(feed)
  entry_content = nil

  feed.entries.each do |entry|
    match_data = resource_from_url(entry.self)

    unless match_data.nil?
      id = match_data[4] || entry.id
      type = match_data[2] || match_data[3]
      next unless type_match_class?(type)

      entry_content = infer_content_from entry, type
      match_usage_point_id = usage_point_id_from_url(entry.self)
      usage_point_id = match_usage_point_id[2] unless match_usage_point_id.nil?
      yield id, entry_content, entry, usage_point_id
    end
  end
end
infer_content_from(entry, resource) click to toggle source
# File lib/green-button-data/fetchable.rb, line 206
def infer_content_from(entry, resource)
  return nil unless valid_resource? resource
  entry.content.send resource.underscore
end
populate_models(feed) click to toggle source
# File lib/green-button-data/fetchable.rb, line 230
def populate_models(feed)
  models = GreenButtonData::ModelCollection.new

  each_entry_content feed do |id, content, entry, usage_point_id|
    attributes_hash = attributes_to_hash(content)
    attributes_hash[:id] = id
    attributes_hash[:usage_point_id] = usage_point_id
    attributes_hash[:links] = construct_links_hash entry
    attributes_hash[:related_urls] = construct_related_urls entry
    models << self.new(attributes_hash)
  end

  return models
end
resource_from_url(url) click to toggle source
# File lib/green-button-data/fetchable.rb, line 143
def resource_from_url(url)
  # Matches resource name in URL (e.g. ApplicationInformation)
  resource = '([a-zA-Z]+)'

  # Matches Base 64 encoded resource ID used by PG&E for MeterReading
  # resource identifier
  base64_id = '\w+=*'

  # Matches numeric ID with thousands separator in commas used for
  # UsageSummary IDs for PG&E endpoints but also matches traditional
  # digits without comma separator
  num_id = '(\d+,*\d*)+'

  # Matches GUID as the resource ID used mainly by PG&E for
  # ApplicationInformation resource identifier
  guid = '[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}' +
          '-[0-9A-Fa-f]{12}'

  # Identifier can be any of the above patterns
  identifier = "(#{base64_id}|#{num_id}|#{guid})"

  /\/(#{resource}|#{resource}\/#{identifier})\/*\z/.match(url)
end
type_match_class?(type) click to toggle source
# File lib/green-button-data/fetchable.rb, line 194
def type_match_class?(type)
  class_name_mapping = {
    'Customer' => 'RetailCustomer',
    'ServiceLocation' => 'RetailCustomer',
    'CustomerAccount' => 'RetailCustomer',
    'CustomerAgreement' => 'RetailCustomer',
    'Meter' => 'RetailCustomer',
    'ElectricPowerUsageSummary' => 'UsageSummary'
  }
  type == class_name || (class_name_mapping.has_key?(type) && class_name_mapping[type] == class_name)
end
url_options(options) click to toggle source
# File lib/green-button-data/fetchable.rb, line 263
def url_options(options)
  url_options = {}

  options.each do |key, value|
    if /_id$/ =~ key
      url_options[key] = value
    end
  end

  return url_options
end
url_path_prefix(options) click to toggle source
# File lib/green-button-data/fetchable.rb, line 275
def url_path_prefix(options)
  if options.keys.size > 0
    GreenButtonData.configuration.send(
      "#{class_name.underscore}_url", options
    )
  else
    GreenButtonData.configuration.send "#{class_name.underscore}_url"
  end
end
usage_point_id_from_url(url) click to toggle source
# File lib/green-button-data/fetchable.rb, line 167
def usage_point_id_from_url(url)
  usage_point = 'UsagePoint\/(.*?)\/'
  /(#{usage_point})/.match(url)
end
valid_resource?(resource) click to toggle source
# File lib/green-button-data/fetchable.rb, line 190
def valid_resource?(resource)
  resource.downcase =~ /(#{valid_resources.join('|')})/
end
valid_resources() click to toggle source
# File lib/green-button-data/fetchable.rb, line 172
def valid_resources
  [
    'applicationinformation',
    'authorization',
    'customer',
    'customeraccount',
    'customeragreement',
    'electricpowerusagesummary',
    'intervalblock',
    'localtimeparameters',
    'meter',
    'readingtype',
    'servicelocation',
    'usagepoint',
    'usagesummary'
  ]
end